83 lines
2.9 KiB
Diff
83 lines
2.9 KiB
Diff
From e936861263d9bafdfbe395c12526f2dc48ac17d7 Mon Sep 17 00:00:00 2001
|
|
Message-ID: <e936861263d9bafdfbe395c12526f2dc48ac17d7.1729457080.git.reepca@russelstein.xyz>
|
|
From: Reepca Russelstein <reepca@russelstein.xyz>
|
|
Date: Sun, 20 Oct 2024 15:36:06 -0500
|
|
Subject: [PATCH 1/2] nix: build: 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
|
|
---
|
|
nix/libstore/build.cc | 36 +++++++++++++++++++++++++++++++++++-
|
|
1 file changed, 35 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc
|
|
index d23c0944a4..67ebfe2f14 100644
|
|
--- a/nix/libstore/build.cc
|
|
+++ b/nix/libstore/build.cc
|
|
@@ -1301,6 +1301,34 @@ void replaceValidPath(const Path & storePath, const Path tmpPath)
|
|
MakeError(NotDeterministic, BuildError)
|
|
|
|
|
|
+/* Recursively make the file permissions of a path safe for exposure to
|
|
+ arbitrary users, but without canonicalising its permissions, timestamp, and
|
|
+ user. Throw an exception if a file type that isn't explicitly known to be
|
|
+ safe is found. */
|
|
+static void secureFilePerms(Path path)
|
|
+{
|
|
+ struct stat st;
|
|
+ if (lstat(path.c_str(), &st)) return;
|
|
+
|
|
+ switch(st.st_mode & S_IFMT) {
|
|
+ case S_IFLNK:
|
|
+ return;
|
|
+
|
|
+ case S_IFDIR:
|
|
+ for (auto & i : readDirectory(path)) {
|
|
+ secureFilePerms(path + "/" + i.name);
|
|
+ }
|
|
+ /* FALLTHROUGH */
|
|
+
|
|
+ case S_IFREG:
|
|
+ chmod(path.c_str(), (st.st_mode & ~S_IFMT) & ~(S_ISUID | S_ISGID | S_IWOTH));
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ throw Error(format("file `%1%' has an unsupported type") % path);
|
|
+ }
|
|
+}
|
|
+
|
|
void DerivationGoal::buildDone()
|
|
{
|
|
trace("build done");
|
|
@@ -1372,9 +1400,15 @@ void DerivationGoal::buildDone()
|
|
build failures. */
|
|
if (useChroot && buildMode == bmNormal)
|
|
foreach (PathSet::iterator, i, missingPaths)
|
|
- if (pathExists(chrootRootDir + *i))
|
|
+ if (pathExists(chrootRootDir + *i)) {
|
|
+ try {
|
|
+ secureFilePerms(chrootRootDir + *i);
|
|
rename((chrootRootDir + *i).c_str(), i->c_str());
|
|
+ } catch(Error & e) {
|
|
+ printMsg(lvlError, e.msg());
|
|
+ }
|
|
+ }
|
|
|
|
if (diskFull)
|
|
printMsg(lvlError, "note: build failure may have been caused by lack of free disk space");
|
|
|
|
--
|
|
2.45.2
|
|
|