forked from lix-project/lix
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`
|
$ nix-build glibc^dev`
|
||||||
```
|
```
|
||||||
does already.
|
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 <sys/ioctl.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <netinet/ip.h>
|
#include <netinet/ip.h>
|
||||||
#include <sys/personality.h>
|
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "callback.hh"
|
#include "callback.hh"
|
||||||
#include "json-utils.hh"
|
#include "json-utils.hh"
|
||||||
#include "cgroup.hh"
|
#include "cgroup.hh"
|
||||||
|
#include "personality.hh"
|
||||||
|
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
@ -24,7 +25,6 @@
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/utsname.h>
|
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
@ -37,7 +37,6 @@
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <netinet/ip.h>
|
#include <netinet/ip.h>
|
||||||
#include <sys/personality.h>
|
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
@ -1964,33 +1963,7 @@ void LocalDerivationGoal::runChild()
|
||||||
/* Close all other file descriptors. */
|
/* Close all other file descriptors. */
|
||||||
closeMostFDs({STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO});
|
closeMostFDs({STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO});
|
||||||
|
|
||||||
#if __linux__
|
setPersonality(drv->platform);
|
||||||
/* 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
|
|
||||||
|
|
||||||
/* Disable core dumps by default. */
|
/* Disable core dumps by default. */
|
||||||
struct rlimit limit = { 0, RLIM_INFINITY };
|
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;
|
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 =
|
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 "fs-accessor.hh"
|
||||||
#include "progress-bar.hh"
|
#include "progress-bar.hh"
|
||||||
#include "eval.hh"
|
#include "eval.hh"
|
||||||
|
#include "build/personality.hh"
|
||||||
|
|
||||||
#if __linux__
|
#if __linux__
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
|
@ -24,7 +25,8 @@ namespace nix {
|
||||||
|
|
||||||
void runProgramInStore(ref<Store> store,
|
void runProgramInStore(ref<Store> store,
|
||||||
const std::string & program,
|
const std::string & program,
|
||||||
const Strings & args)
|
const Strings & args,
|
||||||
|
std::optional<std::string_view> system)
|
||||||
{
|
{
|
||||||
stopProgressBar();
|
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());
|
throw Error("store '%s' is not a local store so it does not support command execution", store->getUri());
|
||||||
|
|
||||||
if (store->storeDir != store2->getRealStoreDir()) {
|
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);
|
for (auto & arg : args) helperArgs.push_back(arg);
|
||||||
|
|
||||||
execv(getSelfExe().value_or("nix").c_str(), stringsToCharPtrs(helperArgs).data());
|
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");
|
throw SysError("could not execute chroot helper");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (system)
|
||||||
|
setPersonality(*system);
|
||||||
|
|
||||||
execvp(program.c_str(), stringsToCharPtrs(args).data());
|
execvp(program.c_str(), stringsToCharPtrs(args).data());
|
||||||
|
|
||||||
throw SysError("unable to execute '%s'", program);
|
throw SysError("unable to execute '%s'", program);
|
||||||
|
@ -199,6 +204,7 @@ void chrootHelper(int argc, char * * argv)
|
||||||
int p = 1;
|
int p = 1;
|
||||||
std::string storeDir = argv[p++];
|
std::string storeDir = argv[p++];
|
||||||
std::string realStoreDir = argv[p++];
|
std::string realStoreDir = argv[p++];
|
||||||
|
std::string system = argv[p++];
|
||||||
std::string cmd = argv[p++];
|
std::string cmd = argv[p++];
|
||||||
Strings args;
|
Strings args;
|
||||||
while (p < argc)
|
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/uid_map", fmt("%d %d %d", uid, uid, 1));
|
||||||
writeFile("/proc/self/gid_map", fmt("%d %d %d", gid, gid, 1));
|
writeFile("/proc/self/gid_map", fmt("%d %d %d", gid, gid, 1));
|
||||||
|
|
||||||
|
if (system != "")
|
||||||
|
setPersonality(system);
|
||||||
|
|
||||||
execvp(cmd.c_str(), stringsToCharPtrs(args).data());
|
execvp(cmd.c_str(), stringsToCharPtrs(args).data());
|
||||||
|
|
||||||
throw SysError("unable to exec '%s'", cmd);
|
throw SysError("unable to exec '%s'", cmd);
|
||||||
|
|
|
@ -6,6 +6,7 @@ namespace nix {
|
||||||
|
|
||||||
void runProgramInStore(ref<Store> store,
|
void runProgramInStore(ref<Store> store,
|
||||||
const std::string & program,
|
const std::string & program,
|
||||||
const Strings & args);
|
const Strings & args,
|
||||||
|
std::optional<std::string_view> system = std::nullopt);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue