diff options
author | Ludovic Courtès <ludo@gnu.org> | 2020-10-01 11:17:12 +0200 |
---|---|---|
committer | Ludovic Courtès <ludo@gnu.org> | 2020-10-01 12:45:38 +0200 |
commit | 9556ac498fd648147ad7d3b52ec86202d0a8e171 (patch) | |
tree | 74b2029ab01c4bf58506817964cb39f6d48fc845 | |
parent | 905a2ff0c59d7d3701fc4c78190d4484ae833ff3 (diff) | |
download | guix-9556ac498fd648147ad7d3b52ec86202d0a8e171.tar guix-9556ac498fd648147ad7d3b52ec86202d0a8e171.tar.gz |
daemon: Try to execute derivation builders only for matching OS kernels.
Fixes <https://bugs.gnu.org/43668>.
Previously, guix-daemon would try to run GNU/Hurd executables on
GNU/Linux. execve(2) would succeed, but the executable would
immediately crash.
This change prevents it from attempting to execute "i586-gnu" code on
"*-linux", while preserving the binfmt_misc-friendly behavior
implemented in commit 7bf2a70a4ffd976d50638d3b9f2ec409763157df.
* nix/libstore/build.cc (sameOperatingSystemKernel): New function.
(DerivationGoal::runChild): Call 'execve' only when
'sameOperatingSystemKernel' returns true.
-rw-r--r-- | nix/libstore/build.cc | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 88f8d11103..ccec513d8d 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -1946,6 +1946,15 @@ void DerivationGoal::startBuilder() } +/* Return true if the operating system kernel part of SYSTEM1 and SYSTEM2 (the + bit that comes after the hyphen in system types such as "i686-linux") is + the same. */ +static bool sameOperatingSystemKernel(const std::string& system1, const std::string& system2) +{ + auto os1 = system1.substr(system1.find("-")); + auto os2 = system2.substr(system2.find("-")); + return os1 == os2; +} void DerivationGoal::runChild() { @@ -2208,9 +2217,20 @@ void DerivationGoal::runChild() foreach (Strings::iterator, i, drv.args) args.push_back(rewriteHashes(*i, rewritesToTmp)); - execve(drv.builder.c_str(), stringsToCharPtrs(args).data(), stringsToCharPtrs(envStrs).data()); - - int error = errno; + /* If DRV targets the same operating system kernel, try to execute it: + there might be binfmt_misc set up for user-land emulation of other + architectures. However, if it targets a different operating + system--e.g., "i586-gnu" vs. "x86_64-linux"--do not try executing + it: the ELF file for that OS is likely indistinguishable from a + native ELF binary and it would just crash at run time. */ + int error; + if (sameOperatingSystemKernel(drv.platform, settings.thisSystem)) { + execve(drv.builder.c_str(), stringsToCharPtrs(args).data(), + stringsToCharPtrs(envStrs).data()); + error = errno; + } else { + error = ENOEXEC; + } /* Right platform? Check this after we've tried 'execve' to allow for transparent emulation of different platforms with binfmt_misc |