libstore: set up linux sandbox /etc earlier
permissions and ownership will be the same since the sandbox process will not have changed uid/gid or umask by the time it gets around to writing these files. all of these files contain some information the host must provide, be it contents or configuration info of some kind Change-Id: I0b57cb0699fd29e798ccf330dff99f571f3c0692
This commit is contained in:
@@ -831,6 +831,83 @@ void LinuxLocalDerivationGoal::prepareSandbox()
|
||||
chownToBuilder(chrootRootDir + "/etc");
|
||||
}
|
||||
|
||||
writeFile(
|
||||
chrootRootDir + "/etc/passwd",
|
||||
fmt("root:x:0:0:Nix build user:%3%:/noshell\n"
|
||||
"nixbld:x:%1%:%2%:Nix build user:%3%:/noshell\n"
|
||||
"nobody:x:65534:65534:Nobody:/:/noshell\n",
|
||||
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())
|
||||
);
|
||||
|
||||
/* Fixed-output derivations typically need to access the
|
||||
network, so give them access to /etc/resolv.conf and so
|
||||
on. */
|
||||
if (!derivationType->isSandboxed()) {
|
||||
// Only use nss functions to resolve hosts and
|
||||
// services. Don’t use it for anything else that may
|
||||
// be configured for this system. This limits the
|
||||
// potential impurities introduced in fixed-outputs.
|
||||
writeFile(chrootRootDir + "/etc/nsswitch.conf", "hosts: files dns\nservices: files\n");
|
||||
|
||||
/* N.B. it is realistic that these paths might not exist. It
|
||||
happens when testing Nix building fixed-output derivations
|
||||
within a pure derivation. */
|
||||
for (auto & path : {"/etc/services", "/etc/hosts"}) {
|
||||
if (pathAccessible(path, true)) {
|
||||
// Copy the actual file, not the symlink, because we don't know where
|
||||
// the symlink is pointing, and we don't want to chase down the entire
|
||||
// chain.
|
||||
//
|
||||
// This means if your network config changes during a FOD build,
|
||||
// the DNS in the sandbox will be wrong. However, this is pretty unlikely
|
||||
// to actually be a problem, because FODs are generally pretty fast,
|
||||
// and machines with often-changing network configurations probably
|
||||
// want to run resolved or some other local resolver anyway.
|
||||
//
|
||||
// There's also just no simple way to do this correctly, you have to manually
|
||||
// inotify watch the files for changes on the outside and update the sandbox
|
||||
// while the build is running (or at least that's what Flatpak does).
|
||||
//
|
||||
// I also just generally feel icky about modifying sandbox state under a build,
|
||||
// even though it really shouldn't be a big deal. -K900
|
||||
copyFile(path, chrootRootDir + path, {.followSymlinks = true});
|
||||
} else if (pathExists(path)) {
|
||||
// The path exist but we were not able to access it. This is not a fatal
|
||||
// error, warn about this so the user can remediate.
|
||||
printTaggedWarning(
|
||||
"'%1%' exists but is inaccessible, it will not be copied in the "
|
||||
"sandbox",
|
||||
path
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (pathAccessible("/etc/resolv.conf", true)) {
|
||||
const auto resolvConf = rewriteResolvConf(readFile("/etc/resolv.conf"));
|
||||
writeFile(chrootRootDir + "/etc/resolv.conf", resolvConf);
|
||||
} else if (pathExists("/etc/resolv.conf")) {
|
||||
// The path exist but we were not able to access it. This is not a fatal error,
|
||||
// warn about this so the user can remediate.
|
||||
printTaggedWarning(
|
||||
"'/etc/resolv.conf' exists but is inaccessible, it will not be rewritten "
|
||||
"inside the sandbox; DNS operations inside the sandbox may be "
|
||||
"non-functional."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/* Create /etc/hosts with localhost entry. */
|
||||
if (derivationType->isSandboxed())
|
||||
writeFile(chrootRootDir + "/etc/hosts", "127.0.0.1 localhost\n::1 localhost\n");
|
||||
@@ -1015,63 +1092,6 @@ bool LinuxLocalDerivationGoal::prepareChildSetup()
|
||||
createSymlink("/proc/self/fd/2", chrootRootDir + "/dev/stderr");
|
||||
}
|
||||
|
||||
/* Fixed-output derivations typically need to access the
|
||||
network, so give them access to /etc/resolv.conf and so
|
||||
on. */
|
||||
if (!derivationType->isSandboxed()) {
|
||||
// Only use nss functions to resolve hosts and
|
||||
// services. Don’t use it for anything else that may
|
||||
// be configured for this system. This limits the
|
||||
// potential impurities introduced in fixed-outputs.
|
||||
writeFile(chrootRootDir + "/etc/nsswitch.conf", "hosts: files dns\nservices: files\n");
|
||||
|
||||
/* N.B. it is realistic that these paths might not exist. It
|
||||
happens when testing Nix building fixed-output derivations
|
||||
within a pure derivation. */
|
||||
for (auto & path : {"/etc/services", "/etc/hosts"}) {
|
||||
if (pathAccessible(path, true)) {
|
||||
// Copy the actual file, not the symlink, because we don't know where
|
||||
// the symlink is pointing, and we don't want to chase down the entire
|
||||
// chain.
|
||||
//
|
||||
// This means if your network config changes during a FOD build,
|
||||
// the DNS in the sandbox will be wrong. However, this is pretty unlikely
|
||||
// to actually be a problem, because FODs are generally pretty fast,
|
||||
// and machines with often-changing network configurations probably
|
||||
// want to run resolved or some other local resolver anyway.
|
||||
//
|
||||
// There's also just no simple way to do this correctly, you have to manually
|
||||
// inotify watch the files for changes on the outside and update the sandbox
|
||||
// while the build is running (or at least that's what Flatpak does).
|
||||
//
|
||||
// I also just generally feel icky about modifying sandbox state under a build,
|
||||
// even though it really shouldn't be a big deal. -K900
|
||||
copyFile(path, chrootRootDir + path, {.followSymlinks = true});
|
||||
} else if (pathExists(path)) {
|
||||
// The path exist but we were not able to access it. This is not a fatal
|
||||
// error, warn about this so the user can remediate.
|
||||
printTaggedWarning(
|
||||
"'%1%' exists but is inaccessible, it will not be copied in the "
|
||||
"sandbox",
|
||||
path
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (pathAccessible("/etc/resolv.conf", true)) {
|
||||
const auto resolvConf = rewriteResolvConf(readFile("/etc/resolv.conf"));
|
||||
writeFile(chrootRootDir + "/etc/resolv.conf", resolvConf);
|
||||
} else if (pathExists("/etc/resolv.conf")) {
|
||||
// The path exist but we were not able to access it. This is not a fatal error,
|
||||
// warn about this so the user can remediate.
|
||||
printTaggedWarning(
|
||||
"'/etc/resolv.conf' exists but is inaccessible, it will not be rewritten "
|
||||
"inside the sandbox; DNS operations inside the sandbox may be "
|
||||
"non-functional."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto & i : ss) {
|
||||
pathsInChroot.emplace(i, i);
|
||||
}
|
||||
@@ -1381,21 +1401,6 @@ Pid LinuxLocalDerivationGoal::startChild(
|
||||
debug("note: not using a user namespace");
|
||||
}
|
||||
|
||||
/* Now that we now the sandbox uid, we can write
|
||||
/etc/passwd. */
|
||||
writeFile(chrootRootDir + "/etc/passwd", fmt(
|
||||
"root:x:0:0:Nix build user:%3%:/noshell\n"
|
||||
"nixbld:x:%1%:%2%:Nix build user:%3%:/noshell\n"
|
||||
"nobody:x:65534:65534:Nobody:/:/noshell\n",
|
||||
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()));
|
||||
|
||||
/* Migrate the child inside the available control group. */
|
||||
if (context.cgroup) {
|
||||
context.cgroup->adoptProcess(pid.get());
|
||||
|
||||
Reference in New Issue
Block a user