aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2022-12-23 16:28:26 +0100
committerEelco Dolstra <edolstra@gmail.com>2022-12-23 16:33:55 +0100
commitc164d304f3cd6c5e536e33435084c030f018c2ab (patch)
treef748d194dff9eb2c82e4fdb512729bc2c203587d
parentc9eee5a84d91e974b09623e01d12586e7026f1ce (diff)
nix develop: Set personality
This makes 'nix develop' set the Linux personality in the same way that the actual build does, allowing a command like 'nix develop nix#devShells.i686-linux.default' on x86_64-linux to work correctly.
-rw-r--r--doc/manual/src/release-notes/rl-next.md6
-rw-r--r--src/libstore/build/derivation-goal.cc1
-rw-r--r--src/libstore/build/local-derivation-goal.cc31
-rw-r--r--src/libstore/build/personality.cc44
-rw-r--r--src/libstore/build/personality.hh11
-rw-r--r--src/nix/develop.cc10
-rw-r--r--src/nix/run.cc13
-rw-r--r--src/nix/run.hh3
8 files changed, 85 insertions, 34 deletions
diff --git a/doc/manual/src/release-notes/rl-next.md b/doc/manual/src/release-notes/rl-next.md
index 6c169bd09..906b048f1 100644
--- a/doc/manual/src/release-notes/rl-next.md
+++ b/doc/manual/src/release-notes/rl-next.md
@@ -25,3 +25,9 @@
$ nix-build glibc^dev`
```
does already.
+
+* On Linux, `nix develop` now sets the
+ [*personality*](https://man7.org/linux/man-pages/man2/personality.2.html)
+ for the development shell in the same way as the actual build of the
+ derivation. This makes shells for `i686-linux` derivations work
+ correctly on `x86_64-linux`.
diff --git a/src/libstore/build/derivation-goal.cc b/src/libstore/build/derivation-goal.cc
index d3b995a4f..173058d1b 100644
--- a/src/libstore/build/derivation-goal.cc
+++ b/src/libstore/build/derivation-goal.cc
@@ -39,7 +39,6 @@
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/ip.h>
-#include <sys/personality.h>
#include <sys/mman.h>
#include <sched.h>
#include <sys/param.h>
diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc
index dccd096ec..9d869d513 100644
--- a/src/libstore/build/local-derivation-goal.cc
+++ b/src/libstore/build/local-derivation-goal.cc
@@ -15,6 +15,7 @@
#include "callback.hh"
#include "json-utils.hh"
#include "cgroup.hh"
+#include "personality.hh"
#include <regex>
#include <queue>
@@ -24,7 +25,6 @@
#include <termios.h>
#include <unistd.h>
#include <sys/mman.h>
-#include <sys/utsname.h>
#include <sys/resource.h>
#include <sys/socket.h>
@@ -37,7 +37,6 @@
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/ip.h>
-#include <sys/personality.h>
#include <sys/mman.h>
#include <sched.h>
#include <sys/param.h>
@@ -1964,33 +1963,7 @@ void LocalDerivationGoal::runChild()
/* Close all other file descriptors. */
closeMostFDs({STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO});
-#if __linux__
- /* Change the personality to 32-bit if we're doing an
- i686-linux build on an x86_64-linux machine. */
- struct utsname utsbuf;
- uname(&utsbuf);
- if ((drv->platform == "i686-linux"
- && (settings.thisSystem == "x86_64-linux"
- || (!strcmp(utsbuf.sysname, "Linux") && !strcmp(utsbuf.machine, "x86_64"))))
- || drv->platform == "armv7l-linux"
- || drv->platform == "armv6l-linux")
- {
- if (personality(PER_LINUX32) == -1)
- throw SysError("cannot set 32-bit personality");
- }
-
- /* Impersonate a Linux 2.6 machine to get some determinism in
- builds that depend on the kernel version. */
- if ((drv->platform == "i686-linux" || drv->platform == "x86_64-linux") && settings.impersonateLinux26) {
- int cur = personality(0xffffffff);
- if (cur != -1) personality(cur | 0x0020000 /* == UNAME26 */);
- }
-
- /* Disable address space randomization for improved
- determinism. */
- int cur = personality(0xffffffff);
- if (cur != -1) personality(cur | ADDR_NO_RANDOMIZE);
-#endif
+ setPersonality(drv->platform);
/* Disable core dumps by default. */
struct rlimit limit = { 0, RLIM_INFINITY };
diff --git a/src/libstore/build/personality.cc b/src/libstore/build/personality.cc
new file mode 100644
index 000000000..4ad477869
--- /dev/null
+++ b/src/libstore/build/personality.cc
@@ -0,0 +1,44 @@
+#include "personality.hh"
+#include "globals.hh"
+
+#if __linux__
+#include <sys/utsname.h>
+#include <sys/personality.h>
+#endif
+
+#include <cstring>
+
+namespace nix {
+
+void setPersonality(std::string_view system)
+{
+#if __linux__
+ /* Change the personality to 32-bit if we're doing an
+ i686-linux build on an x86_64-linux machine. */
+ struct utsname utsbuf;
+ uname(&utsbuf);
+ if ((system == "i686-linux"
+ && (std::string_view(SYSTEM) == "x86_64-linux"
+ || (!strcmp(utsbuf.sysname, "Linux") && !strcmp(utsbuf.machine, "x86_64"))))
+ || system == "armv7l-linux"
+ || system == "armv6l-linux")
+ {
+ if (personality(PER_LINUX32) == -1)
+ throw SysError("cannot set 32-bit personality");
+ }
+
+ /* Impersonate a Linux 2.6 machine to get some determinism in
+ builds that depend on the kernel version. */
+ if ((system == "i686-linux" || system == "x86_64-linux") && settings.impersonateLinux26) {
+ int cur = personality(0xffffffff);
+ if (cur != -1) personality(cur | 0x0020000 /* == UNAME26 */);
+ }
+
+ /* Disable address space randomization for improved
+ determinism. */
+ int cur = personality(0xffffffff);
+ if (cur != -1) personality(cur | ADDR_NO_RANDOMIZE);
+#endif
+}
+
+}
diff --git a/src/libstore/build/personality.hh b/src/libstore/build/personality.hh
new file mode 100644
index 000000000..30e4f4062
--- /dev/null
+++ b/src/libstore/build/personality.hh
@@ -0,0 +1,11 @@
+#pragma once
+
+#include <string>
+
+namespace nix {
+
+void setPersonality(std::string_view system);
+
+}
+
+
diff --git a/src/nix/develop.cc b/src/nix/develop.cc
index 6c3a9c6c6..1d90d1dac 100644
--- a/src/nix/develop.cc
+++ b/src/nix/develop.cc
@@ -164,6 +164,14 @@ struct BuildEnvironment
{
return vars == other.vars && bashFunctions == other.bashFunctions;
}
+
+ std::string getSystem() const
+ {
+ if (auto v = get(vars, "system"))
+ return getString(*v);
+ else
+ return settings.thisSystem;
+ }
};
const static std::string getEnvSh =
@@ -570,7 +578,7 @@ struct CmdDevelop : Common, MixEnvironment
}
}
- runProgramInStore(store, shell, args);
+ runProgramInStore(store, shell, args, buildEnvironment.getSystem());
}
};
diff --git a/src/nix/run.cc b/src/nix/run.cc
index 45d2dfd0d..6fca68047 100644
--- a/src/nix/run.cc
+++ b/src/nix/run.cc
@@ -9,6 +9,7 @@
#include "fs-accessor.hh"
#include "progress-bar.hh"
#include "eval.hh"
+#include "build/personality.hh"
#if __linux__
#include <sys/mount.h>
@@ -24,7 +25,8 @@ namespace nix {
void runProgramInStore(ref<Store> store,
const std::string & program,
- const Strings & args)
+ const Strings & args,
+ std::optional<std::string_view> system)
{
stopProgressBar();
@@ -44,7 +46,7 @@ void runProgramInStore(ref<Store> store,
throw Error("store '%s' is not a local store so it does not support command execution", store->getUri());
if (store->storeDir != store2->getRealStoreDir()) {
- Strings helperArgs = { chrootHelperName, store->storeDir, store2->getRealStoreDir(), program };
+ Strings helperArgs = { chrootHelperName, store->storeDir, store2->getRealStoreDir(), std::string(system.value_or("")), program };
for (auto & arg : args) helperArgs.push_back(arg);
execv(getSelfExe().value_or("nix").c_str(), stringsToCharPtrs(helperArgs).data());
@@ -52,6 +54,9 @@ void runProgramInStore(ref<Store> store,
throw SysError("could not execute chroot helper");
}
+ if (system)
+ setPersonality(*system);
+
execvp(program.c_str(), stringsToCharPtrs(args).data());
throw SysError("unable to execute '%s'", program);
@@ -199,6 +204,7 @@ void chrootHelper(int argc, char * * argv)
int p = 1;
std::string storeDir = argv[p++];
std::string realStoreDir = argv[p++];
+ std::string system = argv[p++];
std::string cmd = argv[p++];
Strings args;
while (p < argc)
@@ -262,6 +268,9 @@ void chrootHelper(int argc, char * * argv)
writeFile("/proc/self/uid_map", fmt("%d %d %d", uid, uid, 1));
writeFile("/proc/self/gid_map", fmt("%d %d %d", gid, gid, 1));
+ if (system != "")
+ setPersonality(system);
+
execvp(cmd.c_str(), stringsToCharPtrs(args).data());
throw SysError("unable to exec '%s'", cmd);
diff --git a/src/nix/run.hh b/src/nix/run.hh
index 6180a87dd..fed360158 100644
--- a/src/nix/run.hh
+++ b/src/nix/run.hh
@@ -6,6 +6,7 @@ namespace nix {
void runProgramInStore(ref<Store> store,
const std::string & program,
- const Strings & args);
+ const Strings & args,
+ std::optional<std::string_view> system = std::nullopt);
}