daemon: Set ownership of kept build directories to the calling user.
Fixes <http://bugs.gnu.org/15890>. * nix/libstore/globals.hh (Settings) Add clientUid and clientGid. * nix/nix-daemon/nix-daemon.cc (daemonLoop] Store UID and GID of the caller in settings. * nix/libstore/build.cc (_chown): New function. (DerivationGoal::deleteTmpDir): Use it, change ownership of build directory if it is kept and the new owner is not root.
This commit is contained in:
parent
43e8824d3c
commit
2608e40988
|
@ -2631,6 +2631,21 @@ void DerivationGoal::closeLogFile()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void _chown(const Path & path, uid_t uid, gid_t gid)
|
||||||
|
{
|
||||||
|
checkInterrupt();
|
||||||
|
|
||||||
|
if (lchown(path.c_str(), uid, gid) == -1) {
|
||||||
|
throw SysError(format("change owner and group of `%1%'") % path);
|
||||||
|
}
|
||||||
|
struct stat st = lstat(path);
|
||||||
|
if (S_ISDIR(st.st_mode)) {
|
||||||
|
for (auto & i : readDirectory(path))
|
||||||
|
_chown(path + "/" + i.name, uid, gid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DerivationGoal::deleteTmpDir(bool force)
|
void DerivationGoal::deleteTmpDir(bool force)
|
||||||
{
|
{
|
||||||
if (tmpDir != "") {
|
if (tmpDir != "") {
|
||||||
|
@ -2639,6 +2654,12 @@ void DerivationGoal::deleteTmpDir(bool force)
|
||||||
format("note: keeping build directory `%2%'")
|
format("note: keeping build directory `%2%'")
|
||||||
% drvPath % tmpDir);
|
% drvPath % tmpDir);
|
||||||
chmod(tmpDir.c_str(), 0755);
|
chmod(tmpDir.c_str(), 0755);
|
||||||
|
// Change the ownership if clientUid is set. Never change the
|
||||||
|
// ownership or the group to "root" for security reasons.
|
||||||
|
if (settings.clientUid != (uid_t) -1 && settings.clientUid != 0) {
|
||||||
|
_chown(tmpDir, settings.clientUid,
|
||||||
|
settings.clientGid != 0 ? settings.clientGid : -1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
deletePath(tmpDir);
|
deletePath(tmpDir);
|
||||||
|
|
|
@ -70,6 +70,12 @@ struct Settings {
|
||||||
subgoal of the same goal) fails. */
|
subgoal of the same goal) fails. */
|
||||||
bool keepGoing;
|
bool keepGoing;
|
||||||
|
|
||||||
|
/* User and groud id of the client issuing the build request. Used to set
|
||||||
|
the owner and group of the kept temporary directories of failed
|
||||||
|
builds. */
|
||||||
|
uid_t clientUid;
|
||||||
|
gid_t clientGid;
|
||||||
|
|
||||||
/* Whether, if we cannot realise the known closure corresponding
|
/* Whether, if we cannot realise the known closure corresponding
|
||||||
to a derivation, we should try to normalise the derivation
|
to a derivation, we should try to normalise the derivation
|
||||||
instead. */
|
instead. */
|
||||||
|
|
|
@ -960,6 +960,18 @@ static void daemonLoop()
|
||||||
strncpy(argvSaved[1], processName.c_str(), strlen(argvSaved[1]));
|
strncpy(argvSaved[1], processName.c_str(), strlen(argvSaved[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(SO_PEERCRED)
|
||||||
|
/* Store the client's user and group for this connection. This
|
||||||
|
has to be done in the forked process since it is per
|
||||||
|
connection. */
|
||||||
|
settings.clientUid = cred.uid;
|
||||||
|
settings.clientGid = cred.gid;
|
||||||
|
#else
|
||||||
|
/* Setting these to -1 means: do not change */
|
||||||
|
settings.clientUid = (uid_t) -1;
|
||||||
|
settings.clientGid = (gid_t) -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Handle the connection. */
|
/* Handle the connection. */
|
||||||
from.fd = remote;
|
from.fd = remote;
|
||||||
to.fd = remote;
|
to.fd = remote;
|
||||||
|
|
Loading…
Reference in New Issue