Skip to content

DerivationBuilder: Preserve death signal across setuid,setgid#15193

Merged
xokdvium merged 1 commit intomasterfrom
restore-death-signal
Feb 11, 2026
Merged

DerivationBuilder: Preserve death signal across setuid,setgid#15193
xokdvium merged 1 commit intomasterfrom
restore-death-signal

Conversation

@xokdvium
Copy link
Contributor

It's apparently a common footgun in Linux that the death signal isn't preserved across calls to setuid/setgid. If nix-build gets SIGKILL-ed while a build is running that would lead to a runaway build process that would get reparented to init/systemd.

This is pretty easy to reproduce with the following derivation:

derivation {
  name = "pdeathsig-repro";
  system = builtins.currentSystem;
  builder = "/bin/sh";
  args = [
    "-c"
    ''
      while :; do :; done
    ''
  ];
}

And the reproduction script:

sudo nix-build repro.nix &
sleep 3
BUILDER=$(pgrep -u nixbld1)
sudo kill -9 $(pgrep -f 'nix-build.*repro')
sleep 1
ps -p $BUILDER -o pid,ppid,user,comm

To address this we have to restore the death signal after all the calls to setuid/setgid. This is done in a helper function preserveDeathSignal that takes a callback to avoid code duplication.

See: golang/go#9686

Motivation

Context


Add 👍 to pull requests you find important.

The Nix maintainer team uses a GitHub project board to schedule and track reviews.

It's apparently a common footgun in Linux that the death signal isn't
preserved across calls to setuid/setgid. If nix-build gets SIGKILL-ed
while a build is running that would lead to a runaway build process that
would get reparented to init/systemd.

This is pretty easy to reproduce with the following derivation:

derivation {
  name = "pdeathsig-repro";
  system = builtins.currentSystem;
  builder = "/bin/sh";
  args = [
    "-c"
    ''
      while :; do :; done
    ''
  ];
}

And the reproduction script:

sudo nix-build repro.nix &
sleep 3
BUILDER=$(pgrep -u nixbld1)
sudo kill -9 $(pgrep -f 'nix-build.*repro')
sleep 1
ps -p $BUILDER -o pid,ppid,user,comm

To address this we have to restore the death signal after all the calls
to setuid/setgid. This is done in a helper function preserveDeathSignal
that takes a callback to avoid code duplication.

See: golang/go#9686
@xokdvium
Copy link
Contributor Author

@edolstra, could you review this one, since you are the most familiar with the sandboxing setup?

@xokdvium
Copy link
Contributor Author

xokdvium commented Feb 10, 2026

I'm pretty sure that I saw this happen in a real-world scenario with some build system.

@arromanoff
Copy link

This real-world scenario happened to me and I confirm that I can no longer reproduce it with this patch. Thanks!

@xokdvium xokdvium added this pull request to the merge queue Feb 11, 2026
Merged via the queue into master with commit d9651b1 Feb 11, 2026
18 checks passed
@xokdvium xokdvium deleted the restore-death-signal branch February 11, 2026 22:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants