bug-guix
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#43668: Daemon tries to build GNU/Hurd derivations on GNU/Linux


From: Ludovic Courtès
Subject: bug#43668: Daemon tries to build GNU/Hurd derivations on GNU/Linux
Date: Mon, 28 Sep 2020 12:31:22 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/27.1 (gnu/linux)

Ludovic Courtès <ludo@gnu.org> skribis:

> It’s no wonder that the GNU/Hurd executable fails to run on GNU/Linux.
> The reason the daemon tries to run it anyway is because of the hack
> introduced in 7bf2a70a4ffd976d50638d3b9f2ec409763157df, in support of
> transparent emulation via binfmt_misc.

The thing is that x86 GNU/Hurd and GNU/Linux ELF binaries are
indistinguishable AFAICS since they both use ELFOSABI_NONE:

--8<---------------cut here---------------start------------->8---
scheme@(guile-user)> ,use(guix elf)
scheme@(guile-user)> ,use(rnrs io ports)
scheme@(guile-user)> (define e (parse-elf (call-with-input-file 
"/gnu/store/vq7zyb4hmlrafflmrcjbqccxp4dsx0s3-bash" get-bytevector-all)))
scheme@(guile-user)> (elf-abi e)
$6 = 0
scheme@(guile-user)> ELFOSABI_GNU
$7 = 3
scheme@(guile-user)> (define e2 (parse-elf (call-with-input-file "/bin/sh" 
get-bytevector-all)))
scheme@(guile-user)> (elf-abi e2)
$8 = 0
--8<---------------cut here---------------end--------------->8---

(The ‘file’ command does manage to recognize GNU/Hurd binaries, but I
don’t know how it does it.)

So I think we can’t count on an ‘execve’ error and thus have to treat
this case (same architecture but different OS kernel) specially, as
shown below.

Thoughts?

Ludo’.

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

reply via email to

[Prev in Thread] Current Thread [Next in Thread]