mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-27 00:06:16 +02:00
* If Nix is not running as root, call the setuid helper to start the
builder under the desired build user.
This commit is contained in:
parent
813a7c65c9
commit
a45c498e4e
2 changed files with 41 additions and 26 deletions
|
@ -1342,11 +1342,6 @@ void DerivationGoal::startBuilder()
|
||||||
|
|
||||||
initChild();
|
initChild();
|
||||||
|
|
||||||
/* Fill in the arguments. */
|
|
||||||
Strings args(drv.args);
|
|
||||||
args.push_front(baseNameOf(drv.builder));
|
|
||||||
const char * * argArr = strings2CharPtrs(args);
|
|
||||||
|
|
||||||
/* Fill in the environment. */
|
/* Fill in the environment. */
|
||||||
Strings envStrs;
|
Strings envStrs;
|
||||||
for (Environment::const_iterator i = env.begin();
|
for (Environment::const_iterator i = env.begin();
|
||||||
|
@ -1354,32 +1349,53 @@ void DerivationGoal::startBuilder()
|
||||||
envStrs.push_back(i->first + "=" + i->second);
|
envStrs.push_back(i->first + "=" + i->second);
|
||||||
const char * * envArr = strings2CharPtrs(envStrs);
|
const char * * envArr = strings2CharPtrs(envStrs);
|
||||||
|
|
||||||
|
Path program = drv.builder.c_str();
|
||||||
|
std::vector<const char *> args; /* careful with c_str()! */
|
||||||
|
|
||||||
/* If we are running in `build-users' mode, then switch to
|
/* If we are running in `build-users' mode, then switch to
|
||||||
the user we allocated above. Make sure that we drop
|
the user we allocated above. Make sure that we drop
|
||||||
all root privileges. Note that initChild() above has
|
all root privileges. Note that initChild() above has
|
||||||
closed all file descriptors except std*, so that's
|
closed all file descriptors except std*, so that's
|
||||||
safe. Also note that setuid() when run as root sets
|
safe. Also note that setuid() when run as root sets
|
||||||
the real, effective and saved UIDs. */
|
the real, effective and saved UIDs. */
|
||||||
if (buildUser.getUID() != 0) {
|
if (buildUser.enabled()) {
|
||||||
printMsg(lvlInfo, format("switching to uid `%1%'") % buildUser.getUID());
|
printMsg(lvlInfo, format("switching to uid `%1%'") % buildUser.getUID());
|
||||||
|
|
||||||
if (setgroups(0, 0) == -1)
|
if (amPrivileged()) {
|
||||||
throw SysError("cannot clear the set of supplementary groups");
|
|
||||||
|
|
||||||
if (setgid(buildUser.getGID()) == -1 ||
|
if (setgroups(0, 0) == -1)
|
||||||
getgid() != buildUser.getGID() ||
|
throw SysError("cannot clear the set of supplementary groups");
|
||||||
getegid() != buildUser.getGID())
|
|
||||||
throw SysError("setgid failed");
|
|
||||||
|
|
||||||
if (setuid(buildUser.getUID()) == -1 ||
|
if (setgid(buildUser.getGID()) == -1 ||
|
||||||
getuid() != buildUser.getUID() ||
|
getgid() != buildUser.getGID() ||
|
||||||
geteuid() != buildUser.getUID())
|
getegid() != buildUser.getGID())
|
||||||
throw SysError("setuid failed");
|
throw SysError("setgid failed");
|
||||||
|
|
||||||
|
if (setuid(buildUser.getUID()) == -1 ||
|
||||||
|
getuid() != buildUser.getUID() ||
|
||||||
|
geteuid() != buildUser.getUID())
|
||||||
|
throw SysError("setuid failed");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* Let the setuid helper take care of it. */
|
||||||
|
program = nixLibexecDir + "/nix-setuid-helper";
|
||||||
|
args.push_back(program.c_str());
|
||||||
|
args.push_back("run-builder");
|
||||||
|
args.push_back("nix-builder-1"); /* !!! TODO */
|
||||||
|
args.push_back(drv.builder.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fill in the arguments. */
|
||||||
|
string builderBasename = baseNameOf(drv.builder);
|
||||||
|
args.push_back(builderBasename.c_str());
|
||||||
|
for (Strings::iterator i = drv.args.begin();
|
||||||
|
i != drv.args.end(); ++i)
|
||||||
|
args.push_back(i->c_str());
|
||||||
|
args.push_back(0);
|
||||||
|
|
||||||
/* Execute the program. This should not return. */
|
/* Execute the program. This should not return. */
|
||||||
execve(drv.builder.c_str(),
|
execve(program.c_str(), (char * *) &args[0], (char * *) envArr);
|
||||||
(char * *) argArr, (char * *) envArr);
|
|
||||||
|
|
||||||
throw SysError(format("executing `%1%'")
|
throw SysError(format("executing `%1%'")
|
||||||
% drv.builder);
|
% drv.builder);
|
||||||
|
@ -1484,7 +1500,7 @@ void DerivationGoal::computeClosure()
|
||||||
build. Also, the output should be owned by the build
|
build. Also, the output should be owned by the build
|
||||||
user. */
|
user. */
|
||||||
if ((st.st_mode & (S_IWGRP | S_IWOTH)) ||
|
if ((st.st_mode & (S_IWGRP | S_IWOTH)) ||
|
||||||
(buildUser.getUID() != 0 && st.st_uid != buildUser.getUID()))
|
(buildUser.enabled() && st.st_uid != buildUser.getUID()))
|
||||||
throw Error(format("suspicious ownership or permission on `%1%'; rejecting this build output") % path);
|
throw Error(format("suspicious ownership or permission on `%1%'; rejecting this build output") % path);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ static uid_t nameToUid(const string & userName)
|
||||||
user. */
|
user. */
|
||||||
static void runBuilder(uid_t uidNix,
|
static void runBuilder(uid_t uidNix,
|
||||||
const string & buildUsersGroup, const string & targetUser,
|
const string & buildUsersGroup, const string & targetUser,
|
||||||
string program, int argc, char * * argv)
|
string program, int argc, char * * argv, char * * env)
|
||||||
{
|
{
|
||||||
uid_t uidTargetUser = nameToUid(targetUser);
|
uid_t uidTargetUser = nameToUid(targetUser);
|
||||||
|
|
||||||
|
@ -107,12 +107,11 @@ static void runBuilder(uid_t uidNix,
|
||||||
|
|
||||||
/* Execute the program. */
|
/* Execute the program. */
|
||||||
std::vector<const char *> args;
|
std::vector<const char *> args;
|
||||||
args.push_back(program.c_str());
|
|
||||||
for (int i = 0; i < argc; ++i)
|
for (int i = 0; i < argc; ++i)
|
||||||
args.push_back(argv[i]);
|
args.push_back(argv[i]);
|
||||||
args.push_back(0);
|
args.push_back(0);
|
||||||
|
|
||||||
if (execve(program.c_str(), (char * *) &args[0], 0) == -1)
|
if (execve(program.c_str(), (char * *) &args[0], env) == -1)
|
||||||
throw SysError(format("cannot execute `%1%'") % program);
|
throw SysError(format("cannot execute `%1%'") % program);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,10 +179,10 @@ static void run(int argc, char * * argv)
|
||||||
|
|
||||||
if (command == "run-builder") {
|
if (command == "run-builder") {
|
||||||
/* Syntax: nix-setuid-helper run-builder <username> <program>
|
/* Syntax: nix-setuid-helper run-builder <username> <program>
|
||||||
<args...> */
|
<arg0 arg1...> */
|
||||||
if (argc < 4) throw Error("missing user name / program name");
|
if (argc < 4) throw Error("missing user name / program name");
|
||||||
runBuilder(uidNix, buildUsersGroup,
|
runBuilder(uidNix, buildUsersGroup,
|
||||||
argv[2], argv[3], argc - 4, argv + 4);
|
argv[2], argv[3], argc - 4, argv + 4, oldEnviron);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (command == "fix-ownership") {
|
else if (command == "fix-ownership") {
|
||||||
|
|
Loading…
Reference in a new issue