diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 85a818b..4644810 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -447,6 +447,7 @@ private: string user; uid_t uid; gid_t gid; + std::vector supplementaryGIDs; public: UserLock(); @@ -460,6 +461,7 @@ public: string getUser() { return user; } uid_t getUID() { return uid; } uid_t getGID() { return gid; } + std::vector getSupplementaryGIDs() { return supplementaryGIDs; } bool enabled() { return uid != 0; } @@ -539,6 +541,18 @@ void UserLock::acquire() throw Error(format("the Nix user should not be a member of `%1%'") % settings.buildUsersGroup); + /* Get the list of supplementary groups of this build user. This + is usually either empty or contains a group such as "kvm". */ + supplementaryGIDs.resize(10); + int ngroups = supplementaryGIDs.size(); + int err = getgrouplist(pw->pw_name, pw->pw_gid, + &supplementaryGIDs.at(0), &ngroups); + if (err == -1) + throw Error(format("failed to get list of supplementary groups for `%1'") + % pw->pw_name); + + supplementaryGIDs.resize(ngroups); + return; } } @@ -2179,8 +2193,11 @@ void DerivationGoal::runChild() if (buildUser.enabled()) { printMsg(lvlChatty, format("switching to user `%1%'") % buildUser.getUser()); - if (setgroups(0, 0) == -1) - throw SysError("cannot clear the set of supplementary groups"); + /* Preserve supplementary groups of the build user, to allow + admins to specify groups such as "kvm". */ + if (setgroups(buildUser.getSupplementaryGIDs().size(), + &buildUser.getSupplementaryGIDs().at(0)) == -1) + throw SysError("cannot set supplementary groups of build user"); if (setgid(buildUser.getGID()) == -1 || getgid() != buildUser.getGID() ||