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.
This commit is contained in:
parent
c9eee5a84d
commit
c164d304f3
|
@ -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`.
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 };
|
||||
|
|
44
src/libstore/build/personality.cc
Normal file
44
src/libstore/build/personality.cc
Normal file
|
@ -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
|
||||
}
|
||||
|
||||
}
|
11
src/libstore/build/personality.hh
Normal file
11
src/libstore/build/personality.hh
Normal file
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace nix {
|
||||
|
||||
void setPersonality(std::string_view system);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -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());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue