From dd54f45bc7e54c7784fcbfe343f6f553103efeca Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Mon, 2 Feb 2026 14:43:35 +0100 Subject: [PATCH] libstore: fix linux sandbox parent death signal handling setting the signal is not enough, we must also check that the process we expect to be parent to actually *is* our parent, not another process (eg init if the daemon exited). we also have to set the death signal *after* all set[ug]id calls, otherwise it will be cleared again by such changes. Change-Id: I4e8c9102ea407576ed85b3203c8bb9bfb56762de --- lix/libstore/platform/linux.cc | 24 +++++++++++------------- lix/libstore/platform/linux.hh | 9 +++++++++ 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/lix/libstore/platform/linux.cc b/lix/libstore/platform/linux.cc index 4c3b66435..6bcfd9e0f 100644 --- a/lix/libstore/platform/linux.cc +++ b/lix/libstore/platform/linux.cc @@ -1518,6 +1518,16 @@ bool LinuxLocalDerivationGoal::prepareChildSetup() return false; } +void LinuxLocalDerivationGoal::finishChildSetup() +{ + if (prctl(PR_SET_PDEATHSIG, SIGKILL) == -1) { + throw SysError("setting death signal"); + } + if (getppid() != parentPid) { + raise(SIGKILL); + } +} + Pid LinuxLocalDerivationGoal::startChild( const Path & builder, const Strings & envStrs, const Strings & args, AutoCloseFD logPTY ) @@ -1660,10 +1670,6 @@ Pid LinuxLocalDerivationGoal::startChild( } return inVFork(/* flags*/ 0, [&]() { - if (prctl(PR_SET_PDEATHSIG, SIGKILL) == -1) { - throw SysError("setting death signal"); - } - if (dup2(logPTY.get(), STDERR_FILENO) == -1) { throw SysError("failed to redirect build output to log file"); } @@ -1698,15 +1704,7 @@ Pid LinuxLocalDerivationGoal::startChild( options.cloneFlags = CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWIPC | CLONE_NEWUTS | CLONE_PARENT | SIGCHLD; - return startProcess( - [&]() { - if (prctl(PR_SET_PDEATHSIG, SIGKILL) == -1) { - throw SysError("setting death signal"); - } - runChild(builder, envStrs, args); - }, - options - ); + return startProcess([&]() { runChild(builder, envStrs, args); }, options); }); } diff --git a/lix/libstore/platform/linux.hh b/lix/libstore/platform/linux.hh index 0011d9f18..576e76768 100644 --- a/lix/libstore/platform/linux.hh +++ b/lix/libstore/platform/linux.hh @@ -5,6 +5,7 @@ #include "lix/libstore/gc-store.hh" #include "lix/libstore/local-store.hh" #include "lix/libutil/processes.hh" +#include namespace nix { @@ -58,6 +59,12 @@ private: Pid pastaPid; + /** + * used to initialize the parent death signal of children without racing + * with the parent dying before we got around to setting a death signal. + */ + pid_t parentPid = getpid(); + /** * Create a special accessor that can access paths that were built within the sandbox's * chroot. @@ -89,6 +96,8 @@ private: bool prepareChildSetup() override; + void finishChildSetup() override; + std::string rewriteResolvConf(std::string fromHost); /**