* If not running as root, let the setuid helper kill the build user's
processes before and after the build.
This commit is contained in:
parent
ec23ecc64d
commit
f76fdb6d42
2 changed files with 69 additions and 31 deletions
|
@ -351,6 +351,8 @@ public:
|
||||||
void acquire();
|
void acquire();
|
||||||
void release();
|
void release();
|
||||||
|
|
||||||
|
void kill();
|
||||||
|
|
||||||
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; }
|
||||||
|
@ -452,29 +454,8 @@ void UserLock::release()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool amPrivileged()
|
static void runSetuidHelper(const string & command,
|
||||||
{
|
const string & arg)
|
||||||
return geteuid() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool haveBuildUsers()
|
|
||||||
{
|
|
||||||
return querySetting("build-users-group", "") != "";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void killUserWrapped(uid_t uid)
|
|
||||||
{
|
|
||||||
if (amPrivileged())
|
|
||||||
killUser(uid);
|
|
||||||
else
|
|
||||||
/* !!! TODO */
|
|
||||||
printMsg(lvlError, "must kill");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void getOwnership(const Path & path)
|
|
||||||
{
|
{
|
||||||
string program = nixLibexecDir + "/nix-setuid-helper";
|
string program = nixLibexecDir + "/nix-setuid-helper";
|
||||||
|
|
||||||
|
@ -491,8 +472,8 @@ void getOwnership(const Path & path)
|
||||||
std::vector<const char *> args; /* careful with c_str()!
|
std::vector<const char *> args; /* careful with c_str()!
|
||||||
*/
|
*/
|
||||||
args.push_back(program.c_str());
|
args.push_back(program.c_str());
|
||||||
args.push_back("get-ownership");
|
args.push_back(command.c_str());
|
||||||
args.push_back(path.c_str());
|
args.push_back(arg.c_str());
|
||||||
args.push_back(0);
|
args.push_back(0);
|
||||||
|
|
||||||
execve(program.c_str(), (char * *) &args[0], 0);
|
execve(program.c_str(), (char * *) &args[0], 0);
|
||||||
|
@ -514,6 +495,34 @@ void getOwnership(const Path & path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void UserLock::kill()
|
||||||
|
{
|
||||||
|
assert(enabled());
|
||||||
|
if (amPrivileged())
|
||||||
|
killUser(uid);
|
||||||
|
else
|
||||||
|
runSetuidHelper("kill", user);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool amPrivileged()
|
||||||
|
{
|
||||||
|
return geteuid() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool haveBuildUsers()
|
||||||
|
{
|
||||||
|
return querySetting("build-users-group", "") != "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void getOwnership(const Path & path)
|
||||||
|
{
|
||||||
|
runSetuidHelper("get-ownership", path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void deletePathWrapped(const Path & path)
|
static void deletePathWrapped(const Path & path)
|
||||||
{
|
{
|
||||||
/* When using build users and we're not root, we may not have
|
/* When using build users and we're not root, we may not have
|
||||||
|
@ -850,7 +859,7 @@ void DerivationGoal::buildDone()
|
||||||
open and modifies them after they have been chown'ed to
|
open and modifies them after they have been chown'ed to
|
||||||
root. */
|
root. */
|
||||||
if (buildUser.enabled())
|
if (buildUser.enabled())
|
||||||
killUserWrapped(buildUser.getUID());
|
buildUser.kill();
|
||||||
|
|
||||||
/* Close the read side of the logger pipe. */
|
/* Close the read side of the logger pipe. */
|
||||||
logPipe.readSide.close();
|
logPipe.readSide.close();
|
||||||
|
@ -1332,7 +1341,7 @@ void DerivationGoal::startBuilder()
|
||||||
|
|
||||||
/* Make sure that no other processes are executing under this
|
/* Make sure that no other processes are executing under this
|
||||||
uid. */
|
uid. */
|
||||||
killUserWrapped(buildUser.getUID());
|
buildUser.kill();
|
||||||
|
|
||||||
/* Change ownership of the temporary build directory, if we're
|
/* Change ownership of the temporary build directory, if we're
|
||||||
root. If we're not root, then the setuid helper will do it
|
root. If we're not root, then the setuid helper will do it
|
||||||
|
|
|
@ -66,6 +66,15 @@ static uid_t nameToUid(const string & userName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void checkIfBuildUser(const StringSet & buildUsers,
|
||||||
|
const string & userName)
|
||||||
|
{
|
||||||
|
if (buildUsers.find(userName) == buildUsers.end())
|
||||||
|
throw Error(format("user `%1%' is not a member of the build users group")
|
||||||
|
% userName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Run `program' under user account `targetUser'. `targetUser' should
|
/* Run `program' under user account `targetUser'. `targetUser' should
|
||||||
be a member of `buildUsersGroup'. The ownership of the current
|
be a member of `buildUsersGroup'. The ownership of the current
|
||||||
directory is changed from the Nix user (uidNix) to the target
|
directory is changed from the Nix user (uidNix) to the target
|
||||||
|
@ -80,10 +89,9 @@ static void runBuilder(uid_t uidNix, gid_t gidBuildUsers,
|
||||||
if (uidTargetUser == 0)
|
if (uidTargetUser == 0)
|
||||||
throw Error("won't setuid to root");
|
throw Error("won't setuid to root");
|
||||||
|
|
||||||
/* Verify that the target user is a member of that group. */
|
/* Verify that the target user is a member of the build users
|
||||||
if (buildUsers.find(targetUser) == buildUsers.end())
|
group. */
|
||||||
throw Error(format("user `%1%' is not a member of the build users group")
|
checkIfBuildUser(buildUsers, targetUser);
|
||||||
% targetUser);
|
|
||||||
|
|
||||||
/* Chown the current directory, *if* it is owned by the Nix
|
/* Chown the current directory, *if* it is owned by the Nix
|
||||||
account. The idea is that the current directory is the
|
account. The idea is that the current directory is the
|
||||||
|
@ -118,6 +126,21 @@ static void runBuilder(uid_t uidNix, gid_t gidBuildUsers,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void killBuildUser(gid_t gidBuildUsers,
|
||||||
|
const StringSet & buildUsers, const string & userName)
|
||||||
|
{
|
||||||
|
uid_t uid = nameToUid(userName);
|
||||||
|
|
||||||
|
/* Verify that the user whose processes we are to kill is a member
|
||||||
|
of the build users group. */
|
||||||
|
checkIfBuildUser(buildUsers, userName);
|
||||||
|
|
||||||
|
assert(uid != 0);
|
||||||
|
|
||||||
|
killUser(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef NIX_SETUID_CONFIG_FILE
|
#ifndef NIX_SETUID_CONFIG_FILE
|
||||||
#define NIX_SETUID_CONFIG_FILE "/etc/nix-setuid.conf"
|
#define NIX_SETUID_CONFIG_FILE "/etc/nix-setuid.conf"
|
||||||
#endif
|
#endif
|
||||||
|
@ -204,6 +227,12 @@ static void run(int argc, char * * argv)
|
||||||
secureChown(-1, gidBuildUsers, uidNix, gidBuildUsers, argv[2]);
|
secureChown(-1, gidBuildUsers, uidNix, gidBuildUsers, argv[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (command == "kill") {
|
||||||
|
/* Syntax: nix-setuid-helper kill <username> */
|
||||||
|
if (argc != 3) throw Error("missing user name");
|
||||||
|
killBuildUser(gidBuildUsers, buildUsers, argv[2]);
|
||||||
|
}
|
||||||
|
|
||||||
else throw Error ("invalid command");
|
else throw Error ("invalid command");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue