From 6a07ff1ec068c6255d45644eb182dea5c0027286 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 7 Dec 2006 14:14:35 +0000 Subject: * Change the ownership of store paths to the Nix account before deleting them using the setuid helper. --- src/libstore/build.cc | 60 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 4 deletions(-) (limited to 'src/libstore/build.cc') diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 2b2b54cd1f30..2b6e1be14550 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -458,7 +458,7 @@ static bool amPrivileged() } -void killUserWrapped(uid_t uid) +static void killUserWrapped(uid_t uid) { if (amPrivileged()) killUser(uid); @@ -468,6 +468,58 @@ void killUserWrapped(uid_t uid) } +static void getOwnership(const Path & path) +{ + string program = nixLibexecDir + "/nix-setuid-helper"; + + /* Fork. */ + Pid pid; + pid = fork(); + switch (pid) { + + case -1: + throw SysError("unable to fork"); + + case 0: /* child */ + try { + std::vector args; /* careful with c_str()! + */ + args.push_back(program.c_str()); + args.push_back("get-ownership"); + args.push_back(path.c_str()); + args.push_back(0); + + execve(program.c_str(), (char * *) &args[0], 0); + throw SysError(format("executing `%1%'") % program); + } + catch (std::exception & e) { + std::cerr << "error: " << e.what() << std::endl; + } + quickExit(1); + } + + /* Parent. */ + + /* Wait for the child to finish. */ + int status = pid.wait(true); + if (!statusOk(status)) + throw Error(format("program `%1%' %2%") + % program % statusToString(status)); +} + + +static void deletePathWrapped(const Path & path) +{ + /* When using build users and we're not root, we may not have + sufficient permission to delete the path. So use the setuid + helper to change ownership to us. */ + if (querySetting("build-users-group", "") != "" + || !amPrivileged()) + getOwnership(path); + deletePath(path); +} + + ////////////////////////////////////////////////////////////////////// @@ -1170,7 +1222,7 @@ void DerivationGoal::startBuilder() throw Error(format("obstructed build: path `%1%' exists") % path); if (pathExists(path)) { debug(format("removing unregistered path `%1%'") % path); - deletePath(path); + deletePathWrapped(path); } } @@ -1619,7 +1671,7 @@ void DerivationGoal::deleteTmpDir(bool force) format("builder for `%1%' failed; keeping build directory `%2%'") % drvPath % tmpDir); else - deletePath(tmpDir); + deletePathWrapped(tmpDir); tmpDir = ""; } } @@ -1833,7 +1885,7 @@ void SubstitutionGoal::tryToRun() /* Remove the (stale) output path if it exists. */ if (pathExists(storePath)) - deletePath(storePath); + deletePathWrapped(storePath); /* Fork the substitute program. */ pid = fork(); -- cgit 1.4.1