Merge "Fix /etc/group having desynced IDs from the actual UID in the sandbox" into main
This commit is contained in:
commit
fb5d6f325b
|
@ -215,17 +215,6 @@ void LocalDerivationGoal::tryLocalBuild()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if __linux__
|
|
||||||
if (useChroot) {
|
|
||||||
if (!mountAndPidNamespacesSupported()) {
|
|
||||||
if (!settings.sandboxFallback)
|
|
||||||
throw Error("this system does not support the kernel namespaces that are required for sandboxing; use '--no-sandbox' to disable sandboxing");
|
|
||||||
debug("auto-disabling sandboxing because the prerequisite namespaces are not available");
|
|
||||||
useChroot = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (useBuildUsers()) {
|
if (useBuildUsers()) {
|
||||||
if (!buildUser)
|
if (!buildUser)
|
||||||
buildUser = acquireUserLock(parsedDrv->useUidRange() ? 65536 : 1, useChroot);
|
buildUser = acquireUserLock(parsedDrv->useUidRange() ? 65536 : 1, useChroot);
|
||||||
|
@ -239,6 +228,26 @@ void LocalDerivationGoal::tryLocalBuild()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if __linux__
|
||||||
|
// FIXME: should user namespaces being unsupported also require
|
||||||
|
// sandbox-fallback to be allowed? I don't think so, since they aren't a
|
||||||
|
// huge security win to have enabled.
|
||||||
|
usingUserNamespace = userNamespacesSupported();
|
||||||
|
|
||||||
|
if (useChroot) {
|
||||||
|
if (!mountAndPidNamespacesSupported()) {
|
||||||
|
if (!settings.sandboxFallback)
|
||||||
|
throw Error("this system does not support the kernel namespaces that are required for sandboxing; use '--no-sandbox' to disable sandboxing. Pass --debug for diagnostics on what is broken.");
|
||||||
|
debug("auto-disabling sandboxing because the prerequisite namespaces are not available");
|
||||||
|
useChroot = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!usingUserNamespace && !buildUser) {
|
||||||
|
throw Error("cannot perform a sandboxed build because user namespaces are not available.\nIn this Lix's configuration, user namespaces are required due to either being non-root, or build-users-group being disabled without also enabling auto-allocate-uids");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
actLock.reset();
|
actLock.reset();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -697,13 +706,6 @@ void LocalDerivationGoal::startBuilder()
|
||||||
if (parsedDrv->useUidRange() && (!buildUser || buildUser->getUIDCount() < 65536))
|
if (parsedDrv->useUidRange() && (!buildUser || buildUser->getUIDCount() < 65536))
|
||||||
throw Error("feature 'uid-range' requires the setting '%s' to be enabled", settings.autoAllocateUids.name);
|
throw Error("feature 'uid-range' requires the setting '%s' to be enabled", settings.autoAllocateUids.name);
|
||||||
|
|
||||||
/* Declare the build user's group so that programs get a consistent
|
|
||||||
view of the system (e.g., "id -gn"). */
|
|
||||||
writeFile(chrootRootDir + "/etc/group",
|
|
||||||
fmt("root:x:0:\n"
|
|
||||||
"nixbld:!:%1%:\n"
|
|
||||||
"nogroup:x:65534:\n", sandboxGid()));
|
|
||||||
|
|
||||||
/* Create /etc/hosts with localhost entry. */
|
/* Create /etc/hosts with localhost entry. */
|
||||||
if (derivationType->isSandboxed())
|
if (derivationType->isSandboxed())
|
||||||
writeFile(chrootRootDir + "/etc/hosts", "127.0.0.1 localhost\n::1 localhost\n");
|
writeFile(chrootRootDir + "/etc/hosts", "127.0.0.1 localhost\n::1 localhost\n");
|
||||||
|
@ -911,8 +913,6 @@ void LocalDerivationGoal::startBuilder()
|
||||||
|
|
||||||
userNamespaceSync.create();
|
userNamespaceSync.create();
|
||||||
|
|
||||||
usingUserNamespace = userNamespacesSupported();
|
|
||||||
|
|
||||||
Pipe sendPid;
|
Pipe sendPid;
|
||||||
sendPid.create();
|
sendPid.create();
|
||||||
|
|
||||||
|
@ -981,8 +981,6 @@ void LocalDerivationGoal::startBuilder()
|
||||||
fmt("%d %d %d", sandboxGid(), hostGid, nrIds));
|
fmt("%d %d %d", sandboxGid(), hostGid, nrIds));
|
||||||
} else {
|
} else {
|
||||||
debug("note: not using a user namespace");
|
debug("note: not using a user namespace");
|
||||||
if (!buildUser)
|
|
||||||
throw Error("cannot perform a sandboxed build because user namespaces are not enabled; check /proc/sys/user/max_user_namespaces");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now that we now the sandbox uid, we can write
|
/* Now that we now the sandbox uid, we can write
|
||||||
|
@ -993,6 +991,13 @@ void LocalDerivationGoal::startBuilder()
|
||||||
"nobody:x:65534:65534:Nobody:/:/noshell\n",
|
"nobody:x:65534:65534:Nobody:/:/noshell\n",
|
||||||
sandboxUid(), sandboxGid(), settings.sandboxBuildDir));
|
sandboxUid(), sandboxGid(), settings.sandboxBuildDir));
|
||||||
|
|
||||||
|
/* Declare the build user's group so that programs get a consistent
|
||||||
|
view of the system (e.g., "id -gn"). */
|
||||||
|
writeFile(chrootRootDir + "/etc/group",
|
||||||
|
fmt("root:x:0:\n"
|
||||||
|
"nixbld:!:%1%:\n"
|
||||||
|
"nogroup:x:65534:\n", sandboxGid()));
|
||||||
|
|
||||||
/* Save the mount- and user namespace of the child. We have to do this
|
/* Save the mount- and user namespace of the child. We have to do this
|
||||||
*before* the child does a chroot. */
|
*before* the child does a chroot. */
|
||||||
sandboxMountNamespace = AutoCloseFD{open(fmt("/proc/%d/ns/mnt", (pid_t) pid).c_str(), O_RDONLY)};
|
sandboxMountNamespace = AutoCloseFD{open(fmt("/proc/%d/ns/mnt", (pid_t) pid).c_str(), O_RDONLY)};
|
||||||
|
|
66
tests/nixos/broken-userns.nix
Normal file
66
tests/nixos/broken-userns.nix
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
# Lix should be able to build derivations that want working NSS, even with
|
||||||
|
# broken user namespaces support
|
||||||
|
{ ... }:
|
||||||
|
let
|
||||||
|
testDerivation = builtins.toFile "test.nix" ''
|
||||||
|
{ cacheBreak }:
|
||||||
|
let pkgs = import <nixpkgs> { };
|
||||||
|
in
|
||||||
|
pkgs.runCommand "test" { } '''
|
||||||
|
# ''${cacheBreak}
|
||||||
|
id -g
|
||||||
|
id -u
|
||||||
|
echo "GROUP"
|
||||||
|
cat /etc/group
|
||||||
|
echo "PASSWD"
|
||||||
|
cat /etc/passwd
|
||||||
|
|
||||||
|
username=$(id -un)
|
||||||
|
groupname=$(id -gn)
|
||||||
|
[[ "$username" =~ nixbld* ]]
|
||||||
|
[[ "$groupname" =~ nixbld* ]]
|
||||||
|
touch $out
|
||||||
|
'''
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
{
|
||||||
|
name = "broken-userns";
|
||||||
|
|
||||||
|
nodes.machine =
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
virtualisation.writableStore = true;
|
||||||
|
nix.settings.substituters = lib.mkForce [ ];
|
||||||
|
nix.nixPath = [ "nixpkgs=${lib.cleanSource pkgs.path}" ];
|
||||||
|
virtualisation.additionalPaths = [
|
||||||
|
pkgs.stdenvNoCC
|
||||||
|
testDerivation
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
testScript =
|
||||||
|
{ nodes }:
|
||||||
|
''
|
||||||
|
start_all()
|
||||||
|
|
||||||
|
# Building it normally should work
|
||||||
|
machine.succeed(r"""
|
||||||
|
nix-build --argstr cacheBreak 1 --store daemon ${testDerivation}
|
||||||
|
""")
|
||||||
|
|
||||||
|
# Building it with broken userns should also work
|
||||||
|
machine.succeed(r"""
|
||||||
|
# break user ns
|
||||||
|
sysctl -w user.max_user_namespaces=0
|
||||||
|
""")
|
||||||
|
machine.systemctl("restart nix-daemon")
|
||||||
|
machine.succeed(r"""
|
||||||
|
nix-build --argstr cacheBreak 2 --store daemon ${testDerivation}
|
||||||
|
""")
|
||||||
|
'';
|
||||||
|
}
|
|
@ -164,4 +164,6 @@ in
|
||||||
symlinkResolvconf = runNixOSTestFor "x86_64-linux" ./symlink-resolvconf.nix;
|
symlinkResolvconf = runNixOSTestFor "x86_64-linux" ./symlink-resolvconf.nix;
|
||||||
|
|
||||||
rootInSandbox = runNixOSTestFor "x86_64-linux" ./root-in-sandbox;
|
rootInSandbox = runNixOSTestFor "x86_64-linux" ./root-in-sandbox;
|
||||||
|
|
||||||
|
broken-userns = runNixOSTestFor "x86_64-linux" ./broken-userns.nix;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue