Preserve supplementary groups of build users

The following patch is an attempt to address this bug (see
<http://bugs.gnu.org/18994>) by preserving the supplementary groups of
build users in the build environment.

In practice, I would expect that supplementary groups would contain only
one or two groups: the build users group, and possibly the “kvm” group.

[Changed &at(0) to data() and removed tabs - Eelco]
This commit is contained in:
Ludovic Courtès 2015-07-01 14:56:34 +02:00 committed by Eelco Dolstra
parent e012c126db
commit 9aed117395

View file

@ -446,6 +446,7 @@ private:
string user; string user;
uid_t uid; uid_t uid;
gid_t gid; gid_t gid;
std::vector<gid_t> supplementaryGIDs;
public: public:
UserLock(); UserLock();
@ -459,6 +460,7 @@ public:
string getUser() { return user; } string getUser() { return user; }
uid_t getUID() { return uid; } uid_t getUID() { return uid; }
uid_t getGID() { return gid; } uid_t getGID() { return gid; }
std::vector<gid_t> getSupplementaryGIDs() { return supplementaryGIDs; }
bool enabled() { return uid != 0; } bool enabled() { return uid != 0; }
@ -538,6 +540,17 @@ void UserLock::acquire()
throw Error(format("the Nix user should not be a member of %1%") throw Error(format("the Nix user should not be a member of %1%")
% settings.buildUsersGroup); % 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.data(), &ngroups);
if (err == -1)
throw Error(format("failed to get list of supplementary groups for %1") % pw->pw_name);
supplementaryGIDs.resize(ngroups);
return; return;
} }
} }
@ -2304,8 +2317,11 @@ void DerivationGoal::runChild()
setuid() when run as root sets the real, effective and setuid() when run as root sets the real, effective and
saved UIDs. */ saved UIDs. */
if (buildUser.enabled()) { if (buildUser.enabled()) {
if (setgroups(0, 0) == -1) /* Preserve supplementary groups of the build user, to allow
throw SysError("cannot clear the set of supplementary groups"); admins to specify groups such as "kvm". */
if (setgroups(buildUser.getSupplementaryGIDs().size(),
buildUser.getSupplementaryGIDs().data()) == -1)
throw SysError("cannot set supplementary groups of build user");
if (setgid(buildUser.getGID()) == -1 || if (setgid(buildUser.getGID()) == -1 ||
getgid() != buildUser.getGID() || getgid() != buildUser.getGID() ||