Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move settings from Settings to LocalStoreConfig #7740

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 31 additions & 23 deletions src/libstore/build/local-derivation-goal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,11 @@ namespace nix {
void handleDiffHook(
uid_t uid, uid_t gid,
const Path & tryA, const Path & tryB,
const Path & drvPath, const Path & tmpDir)
const Path & drvPath, const Path & tmpDir,
const LocalStore & store)
{
auto diffHook = settings.diffHook;
if (diffHook != "" && settings.runDiffHook) {
auto diffHook = store.diffHook;
if (diffHook != "" && store.runDiffHook) {
try {
auto diffRes = runProgram(RunOptions {
.program = diffHook,
Expand Down Expand Up @@ -176,10 +177,12 @@ void LocalDerivationGoal::tryLocalBuild() {
return;
}

auto & localStore = getLocalStore();

/* Are we doing a chroot build? */
{
auto noChroot = parsedDrv->getBoolAttr("__noChroot");
if (settings.sandboxMode == smEnabled) {
if (localStore.sandboxMode == smEnabled) {
if (noChroot)
throw Error("derivation '%s' has '__noChroot' set, "
"but that's not allowed when 'sandbox' is 'true'", worker.store.printStorePath(drvPath));
Expand All @@ -190,13 +193,12 @@ void LocalDerivationGoal::tryLocalBuild() {
#endif
useChroot = true;
}
else if (settings.sandboxMode == smDisabled)
else if (localStore.sandboxMode == smDisabled)
useChroot = false;
else if (settings.sandboxMode == smRelaxed)
else if (localStore.sandboxMode == smRelaxed)
useChroot = derivationType.isSandboxed() && !noChroot;
}

auto & localStore = getLocalStore();
if (localStore.storeDir != localStore.realStoreDir.get()) {
#if __linux__
useChroot = true;
Expand Down Expand Up @@ -399,6 +401,8 @@ static void linkOrCopy(const Path & from, const Path & to)

void LocalDerivationGoal::startBuilder()
{
auto & localStore = getLocalStore();

if ((buildUser && buildUser->getUIDCount() != 1)
#if __linux__
|| settings.useCgroups
Expand Down Expand Up @@ -573,7 +577,7 @@ void LocalDerivationGoal::startBuilder()
host file system. */
dirsInChroot.clear();

for (auto i : settings.sandboxPaths.get()) {
for (auto i : localStore.sandboxPaths.get()) {
if (i.empty()) continue;
bool optional = false;
if (i[i.size() - 1] == '?') {
Expand Down Expand Up @@ -604,7 +608,7 @@ void LocalDerivationGoal::startBuilder()
dirsInChroot.insert_or_assign(p, p);
}

PathSet allowedPaths = settings.allowedImpureHostPrefixes;
PathSet allowedPaths = localStore.allowedImpureHostPrefixes;

/* This works like the above, except on a per-derivation level */
auto impurePaths = parsedDrv->getStringsAttr("__impureHostDeps").value_or(Strings());
Expand Down Expand Up @@ -744,17 +748,17 @@ void LocalDerivationGoal::startBuilder()
if (needsHashRewrite() && pathExists(homeDir))
throw Error("home directory '%1%' exists; please remove it to assure purity of builds without sandboxing", homeDir);

if (useChroot && settings.preBuildHook != "" && dynamic_cast<Derivation *>(drv.get())) {
if (useChroot && localStore.preBuildHook != "" && dynamic_cast<Derivation *>(drv.get())) {
printMsg(lvlChatty, format("executing pre-build hook '%1%'")
% settings.preBuildHook);
% localStore.preBuildHook);
auto args = useChroot ? Strings({worker.store.printStorePath(drvPath), chrootRootDir}) :
Strings({ worker.store.printStorePath(drvPath) });
enum BuildHookState {
stBegin,
stExtraChrootDirs
};
auto state = stBegin;
auto lines = runProgram(settings.preBuildHook, false, args);
auto lines = runProgram(localStore.preBuildHook, false, args);
auto lastPos = std::string::size_type{0};
for (auto nlPos = lines.find('\n'); nlPos != std::string::npos;
nlPos = lines.find('\n', lastPos))
Expand Down Expand Up @@ -956,7 +960,7 @@ void LocalDerivationGoal::startBuilder()
/* Otherwise exit with EPERM so we can handle this in the
parent. This is only done when sandbox-fallback is set
to true (the default). */
if (settings.sandboxFallback)
if (localStore.sandboxFallback)
_exit(1);
/* Mention sandbox-fallback in the error message so the user
knows that having it disabled contributed to the
Expand All @@ -973,7 +977,7 @@ void LocalDerivationGoal::startBuilder()
});

int res = helper.wait();
if (res != 0 && settings.sandboxFallback) {
if (res != 0 && localStore.sandboxFallback) {
useChroot = false;
initTmpDir();
goto fallback;
Expand Down Expand Up @@ -1021,7 +1025,7 @@ void LocalDerivationGoal::startBuilder()
"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));
sandboxUid(), sandboxGid(), localStore.sandboxBuildDir));

/* Save the mount- and user namespace of the child. We have to do this
*before* the child does a chroot. */
Expand Down Expand Up @@ -1090,7 +1094,8 @@ void LocalDerivationGoal::initTmpDir() {
/* In a sandbox, for determinism, always use the same temporary
directory. */
#if __linux__
tmpDirInSandbox = useChroot ? settings.sandboxBuildDir : tmpDir;
const auto & localStore = getLocalStore();
tmpDirInSandbox = useChroot ? localStore.sandboxBuildDir : tmpDir;
#else
tmpDirInSandbox = tmpDir;
#endif
Expand Down Expand Up @@ -1617,10 +1622,10 @@ void LocalDerivationGoal::chownToBuilder(const Path & path)
}


void setupSeccomp()
void setupSeccomp(const LocalStoreConfig & localStore)
{
#if __linux__
if (!settings.filterSyscalls) return;
if (!localStore.filterSyscalls) return;
#if HAVE_SECCOMP
scmp_filter_ctx ctx;

Expand Down Expand Up @@ -1682,7 +1687,7 @@ void setupSeccomp()
seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOTSUP), SCMP_SYS(fsetxattr), 0) != 0)
throw SysError("unable to add seccomp rule");

if (seccomp_attr_set(ctx, SCMP_FLTATR_CTL_NNP, settings.allowNewPrivileges ? 0 : 1) != 0)
if (seccomp_attr_set(ctx, SCMP_FLTATR_CTL_NNP, localStore.allowNewPrivileges ? 0 : 1) != 0)
throw SysError("unable to set 'no new privileges' seccomp attribute");

if (seccomp_load(ctx) != 0)
Expand All @@ -1708,7 +1713,7 @@ void LocalDerivationGoal::runChild()
commonChildInit(builderOut);

try {
setupSeccomp();
setupSeccomp(getLocalStore());
} catch (...) {
if (buildUser) throw;
}
Expand All @@ -1726,6 +1731,8 @@ void LocalDerivationGoal::runChild()
#if __linux__
if (useChroot) {

auto & localStore = getLocalStore();

userNamespaceSync.writeSide = -1;

if (drainFD(userNamespaceSync.readSide.get()) != "1")
Expand Down Expand Up @@ -1880,7 +1887,7 @@ void LocalDerivationGoal::runChild()
/* Mount a new tmpfs on /dev/shm to ensure that whatever
the builder puts in /dev/shm is cleaned up automatically. */
if (pathExists("/dev/shm") && mount("none", (chrootRootDir + "/dev/shm").c_str(), "tmpfs", 0,
fmt("size=%s", settings.sandboxShmSize).c_str()) == -1)
fmt("size=%s", localStore.sandboxShmSize).c_str()) == -1)
throw SysError("mounting /dev/shm");

/* Mount a new devpts on /dev/pts. Note that this
Expand Down Expand Up @@ -2645,15 +2652,16 @@ DrvOutputs LocalDerivationGoal::registerOutputs()
ValidPathInfo oldInfo(*worker.store.queryPathInfo(newInfo.path));
if (newInfo.narHash != oldInfo.narHash) {
worker.checkMismatch = true;
if (settings.runDiffHook || settings.keepFailed) {
if (localStore.runDiffHook || settings.keepFailed) {
auto dst = worker.store.toRealPath(finalDestPath + checkSuffix);
deletePath(dst);
movePath(actualPath, dst);

handleDiffHook(
buildUser ? buildUser->getUID() : getuid(),
buildUser ? buildUser->getGID() : getgid(),
finalDestPath, dst, worker.store.printStorePath(drvPath), tmpDir);
finalDestPath, dst, worker.store.printStorePath(drvPath), tmpDir,
localStore);

throw NotDeterministic("derivation '%s' may not be deterministic: output '%s' differs from '%s'",
worker.store.printStorePath(drvPath), worker.store.toRealPath(finalDestPath), dst);
Expand Down
10 changes: 6 additions & 4 deletions src/libstore/build/worker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ void Worker::run(const Goals & _topGoals)
checkInterrupt();

// TODO GC interface?
if (auto localStore = dynamic_cast<LocalStore *>(&store))
if (auto * localStore = dynamic_cast<LocalStore *>(&store))
localStore->autoGC(false);

/* Call every wake goal (in the ordering established by
Expand Down Expand Up @@ -318,9 +318,11 @@ void Worker::waitForInput()
is a build timeout, then wait for input until the first
deadline for any child. */
auto nearest = steady_time_point::max(); // nearest deadline
if (settings.minFree.get() != 0)
// Periodicallty wake up to see if we need to run the garbage collector.
nearest = before + std::chrono::seconds(10);
// TODO GC interface?
if (auto * localStore = dynamic_cast<const LocalStore *>(&store))
if (localStore->minFree.get() != 0)
// Periodicallty wake up to see if we need to run the garbage collector.
nearest = before + std::chrono::seconds(10);
for (auto & i : children) {
if (!i.respectTimeouts) continue;
if (0 != settings.maxSilentTime)
Expand Down
6 changes: 3 additions & 3 deletions src/libstore/gc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -914,13 +914,13 @@ void LocalStore::autoGC(bool sync)

auto now = std::chrono::steady_clock::now();

if (now < state->lastGCCheck + std::chrono::seconds(settings.minFreeCheckInterval)) return;
if (now < state->lastGCCheck + std::chrono::seconds(minFreeCheckInterval)) return;

auto avail = getAvail();

state->lastGCCheck = now;

if (avail >= settings.minFree || avail >= settings.maxFree) return;
if (avail >= minFree || avail >= maxFree) return;

if (avail > state->availAfterGC * 0.97) return;

Expand All @@ -942,7 +942,7 @@ void LocalStore::autoGC(bool sync)
});

GCOptions options;
options.maxFreed = settings.maxFree - avail;
options.maxFreed = this->maxFree - avail;

printInfo("running auto-GC to free %d bytes", options.maxFreed);

Expand Down
54 changes: 0 additions & 54 deletions src/libstore/globals.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ Settings::Settings()
{
buildUsersGroup = getuid() == 0 ? "nixbld" : "";
lockCPU = getEnv("NIX_AFFINITY_HACK") == "1";
allowSymlinkedStore = getEnv("NIX_IGNORE_SYMLINK_STORE") == "1";

caFile = getEnv("NIX_SSL_CERT_FILE").value_or(getEnv("SSL_CERT_FILE").value_or(""));
if (caFile == "") {
Expand All @@ -62,10 +61,6 @@ Settings::Settings()
builders = concatStringsSep(" ", ss);
}

#if defined(__linux__) && defined(SANDBOX_SHELL)
sandboxPaths = tokenizeString<StringSet>("/bin/sh=" SANDBOX_SHELL);
#endif

/* chroot-like behavior from Apple's sandbox */
#if __APPLE__
sandboxPaths = tokenizeString<StringSet>("/System/Library/Frameworks /System/Library/PrivateFrameworks /bin/sh /bin/bash /private/tmp /private/var/tmp /usr/lib");
Expand Down Expand Up @@ -189,55 +184,6 @@ bool Settings::isWSL1()

const std::string nixVersion = PACKAGE_VERSION;

NLOHMANN_JSON_SERIALIZE_ENUM(SandboxMode, {
{SandboxMode::smEnabled, true},
{SandboxMode::smRelaxed, "relaxed"},
{SandboxMode::smDisabled, false},
});

template<> void BaseSetting<SandboxMode>::set(const std::string & str, bool append)
{
if (str == "true") value = smEnabled;
else if (str == "relaxed") value = smRelaxed;
else if (str == "false") value = smDisabled;
else throw UsageError("option '%s' has invalid value '%s'", name, str);
}

template<> bool BaseSetting<SandboxMode>::isAppendable()
{
return false;
}

template<> std::string BaseSetting<SandboxMode>::to_string() const
{
if (value == smEnabled) return "true";
else if (value == smRelaxed) return "relaxed";
else if (value == smDisabled) return "false";
else abort();
}

template<> void BaseSetting<SandboxMode>::convertToArg(Args & args, const std::string & category)
{
args.addFlag({
.longName = name,
.description = "Enable sandboxing.",
.category = category,
.handler = {[this]() { override(smEnabled); }}
});
args.addFlag({
.longName = "no-" + name,
.description = "Disable sandboxing.",
.category = category,
.handler = {[this]() { override(smDisabled); }}
});
args.addFlag({
.longName = "relaxed-" + name,
.description = "Enable sandboxing, but allow builds to disable it.",
.category = category,
.handler = {[this]() { override(smRelaxed); }}
});
}

void MaxBuildJobsSetting::set(const std::string & str, bool append)
{
if (str == "auto") value = std::max(1U, std::thread::hardware_concurrency());
Expand Down
Loading