summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReepca Russelstein <reepca@russelstein.xyz>2024-10-20 15:36:06 -0500
committerLudovic Courtès <ludo@gnu.org>2024-10-21 00:09:10 +0200
commit558224140dab669cabdaebabff18504a066c48d4 (patch)
treee5bae2ebffdbbc33695f09917b13f6aebc1cdbe4
parent92910f5413fd9112c0502138eed5fff758c5de65 (diff)
daemon: Sanitize failed build outputs prior to exposing them.
The only thing keeping a rogue builder and a local user from collaborating to usurp control over the builder's user during the build is the fact that whatever files the builder may produce are not accessible to any other users yet. If we're going to make them accessible, we should probably do some sanity checking to ensure that sort of collaborating can't happen. Currently this isn't happening when failed build outputs are moved from the chroot as an aid to debugging. * nix/libstore/build.cc (secureFilePerms): new function. (DerivationGoal::buildDone): use it. Change-Id: I9dce1e3d8813b31cabd87a0e3219bf9830d8be96 Signed-off-by: Ludovic Courtès <ludo@gnu.org>
-rw-r--r--nix/libstore/build.cc36
1 files changed, 35 insertions, 1 deletions
diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc
index d23c0944a48..67ebfe2f146 100644
--- a/nix/libstore/build.cc
+++ b/nix/libstore/build.cc
@@ -1301,6 +1301,34 @@ void replaceValidPath(const Path & storePath, const Path tmpPath)
1301MakeError(NotDeterministic, BuildError) 1301MakeError(NotDeterministic, BuildError)
1302 1302
1303 1303
1304/* Recursively make the file permissions of a path safe for exposure to
1305 arbitrary users, but without canonicalising its permissions, timestamp, and
1306 user. Throw an exception if a file type that isn't explicitly known to be
1307 safe is found. */
1308static void secureFilePerms(Path path)
1309{
1310 struct stat st;
1311 if (lstat(path.c_str(), &st)) return;
1312
1313 switch(st.st_mode & S_IFMT) {
1314 case S_IFLNK:
1315 return;
1316
1317 case S_IFDIR:
1318 for (auto & i : readDirectory(path)) {
1319 secureFilePerms(path + "/" + i.name);
1320 }
1321 /* FALLTHROUGH */
1322
1323 case S_IFREG:
1324 chmod(path.c_str(), (st.st_mode & ~S_IFMT) & ~(S_ISUID | S_ISGID | S_IWOTH));
1325 break;
1326
1327 default:
1328 throw Error(format("file `%1%' has an unsupported type") % path);
1329 }
1330}
1331
1304void DerivationGoal::buildDone() 1332void DerivationGoal::buildDone()
1305{ 1333{
1306 trace("build done"); 1334 trace("build done");
@@ -1372,8 +1400,14 @@ void DerivationGoal::buildDone()
1372 build failures. */ 1400 build failures. */
1373 if (useChroot && buildMode == bmNormal) 1401 if (useChroot && buildMode == bmNormal)
1374 foreach (PathSet::iterator, i, missingPaths) 1402 foreach (PathSet::iterator, i, missingPaths)
1375 if (pathExists(chrootRootDir + *i)) 1403 if (pathExists(chrootRootDir + *i)) {
1404 try {
1405 secureFilePerms(chrootRootDir + *i);
1376 rename((chrootRootDir + *i).c_str(), i->c_str()); 1406 rename((chrootRootDir + *i).c_str(), i->c_str());
1407 } catch(Error & e) {
1408 printMsg(lvlError, e.msg());
1409 }
1410 }
1377 1411
1378 if (diskFull) 1412 if (diskFull)
1379 printMsg(lvlError, "note: build failure may have been caused by lack of free disk space"); 1413 printMsg(lvlError, "note: build failure may have been caused by lack of free disk space");