From 9d17ce07e872e88057480744414e0d1ef4fd5fa8 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 21 Nov 2022 12:55:49 +0100 Subject: [PATCH] AutoUserLock: If sandboxing is disabled, use the build users group We have to use a gid that has write access to the Nix store. --- src/libstore/build/local-derivation-goal.cc | 60 ++++++++++----------- src/libstore/lock.cc | 22 ++++---- src/libstore/lock.hh | 2 +- 3 files changed, 44 insertions(+), 40 deletions(-) diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc index 34f8ab5f1..b7084384a 100644 --- a/src/libstore/build/local-derivation-goal.cc +++ b/src/libstore/build/local-derivation-goal.cc @@ -177,9 +177,38 @@ void LocalDerivationGoal::tryLocalBuild() { return; } + /* Are we doing a chroot build? */ + { + auto noChroot = parsedDrv->getBoolAttr("__noChroot"); + if (settings.sandboxMode == smEnabled) { + if (noChroot) + throw Error("derivation '%s' has '__noChroot' set, " + "but that's not allowed when 'sandbox' is 'true'", worker.store.printStorePath(drvPath)); +#if __APPLE__ + if (additionalSandboxProfile != "") + throw Error("derivation '%s' specifies a sandbox profile, " + "but this is only allowed when 'sandbox' is 'relaxed'", worker.store.printStorePath(drvPath)); +#endif + useChroot = true; + } + else if (settings.sandboxMode == smDisabled) + useChroot = false; + else if (settings.sandboxMode == smRelaxed) + useChroot = derivationType.isSandboxed() && !noChroot; + } + + auto & localStore = getLocalStore(); + if (localStore.storeDir != localStore.realStoreDir.get()) { + #if __linux__ + useChroot = true; + #else + throw Error("building using a diverted store is not supported on this platform"); + #endif + } + if (useBuildUsers()) { if (!buildUser) - buildUser = acquireUserLock(parsedDrv->useUidRange() ? 65536 : 1); + buildUser = acquireUserLock(parsedDrv->useUidRange() ? 65536 : 1, useChroot); if (!buildUser) { if (!actLock) @@ -433,35 +462,6 @@ void LocalDerivationGoal::startBuilder() additionalSandboxProfile = parsedDrv->getStringAttr("__sandboxProfile").value_or(""); #endif - /* Are we doing a chroot build? */ - { - auto noChroot = parsedDrv->getBoolAttr("__noChroot"); - if (settings.sandboxMode == smEnabled) { - if (noChroot) - throw Error("derivation '%s' has '__noChroot' set, " - "but that's not allowed when 'sandbox' is 'true'", worker.store.printStorePath(drvPath)); -#if __APPLE__ - if (additionalSandboxProfile != "") - throw Error("derivation '%s' specifies a sandbox profile, " - "but this is only allowed when 'sandbox' is 'relaxed'", worker.store.printStorePath(drvPath)); -#endif - useChroot = true; - } - else if (settings.sandboxMode == smDisabled) - useChroot = false; - else if (settings.sandboxMode == smRelaxed) - useChroot = derivationType.isSandboxed() && !noChroot; - } - - auto & localStore = getLocalStore(); - if (localStore.storeDir != localStore.realStoreDir.get()) { - #if __linux__ - useChroot = true; - #else - throw Error("building using a diverted store is not supported on this platform"); - #endif - } - /* Create a temporary directory where the build will take place. */ tmpDir = createTempDir("", "nix-build-" + std::string(drvPath.name()), false, false, 0700); diff --git a/src/libstore/lock.cc b/src/libstore/lock.cc index 4fad3bfd2..3b93979a8 100644 --- a/src/libstore/lock.cc +++ b/src/libstore/lock.cc @@ -109,22 +109,18 @@ struct AutoUserLock : UserLock { AutoCloseFD fdUserLock; uid_t firstUid = 0; + gid_t firstGid = 0; uid_t nrIds = 1; uid_t getUID() override { assert(firstUid); return firstUid; } gid_t getUIDCount() override { return nrIds; } - gid_t getGID() override - { - // We use the same GID ranges as for the UIDs. - assert(firstUid); - return firstUid; - } + gid_t getGID() override { assert(firstGid); return firstGid; } std::vector getSupplementaryGIDs() override { return {}; } - static std::unique_ptr acquire(uid_t nrIds) + static std::unique_ptr acquire(uid_t nrIds, bool useChroot) { settings.requireExperimentalFeature(Xp::AutoAllocateUids); assert(settings.startId > 0); @@ -154,6 +150,14 @@ struct AutoUserLock : UserLock auto lock = std::make_unique(); lock->fdUserLock = std::move(fd); lock->firstUid = settings.startId + i * maxIdsPerBuild; + if (useChroot) + lock->firstGid = lock->firstUid; + else { + struct group * gr = getgrnam(settings.buildUsersGroup.get().c_str()); + if (!gr) + throw Error("the group '%s' specified in 'build-users-group' does not exist", settings.buildUsersGroup); + lock->firstGid = gr->gr_gid; + } lock->nrIds = nrIds; return lock; } @@ -163,10 +167,10 @@ struct AutoUserLock : UserLock } }; -std::unique_ptr acquireUserLock(uid_t nrIds) +std::unique_ptr acquireUserLock(uid_t nrIds, bool useChroot) { if (settings.autoAllocateUids) - return AutoUserLock::acquire(nrIds); + return AutoUserLock::acquire(nrIds, useChroot); else return SimpleUserLock::acquire(); } diff --git a/src/libstore/lock.hh b/src/libstore/lock.hh index e7ceefab8..49ad86de7 100644 --- a/src/libstore/lock.hh +++ b/src/libstore/lock.hh @@ -31,7 +31,7 @@ struct UserLock /* Acquire a user lock for a UID range of size `nrIds`. Note that this may return nullptr if no user is available. */ -std::unique_ptr acquireUserLock(uid_t nrIds); +std::unique_ptr acquireUserLock(uid_t nrIds, bool useChroot); bool useBuildUsers();