[bug#75810,v5,05/14] daemon: Remount root directory as read-only.

Message ID e9761dd9d4842617fa5d7f1996e354b0c7a877af.1741973869.git.ludo@gnu.org
State New
Headers
Series Rootless guix-daemon |

Commit Message

Ludovic Courtès March 14, 2025, 5:48 p.m. UTC
  * nix/libstore/build.cc (DerivationGoal::runChild): Bind-mount the store
and /tmp under ‘chrootRootDir’ to themselves as read-write.
Remount / as read-only.

Change-Id: I79565094c8ec8448401897c720aad75304fd1948
---
 nix/libstore/build.cc | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
  

Patch

diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc
index 3861a1ffd9..c8b778362a 100644
--- a/nix/libstore/build.cc
+++ b/nix/libstore/build.cc
@@ -2091,6 +2091,18 @@  void DerivationGoal::runChild()
 
             for (auto & i : ss) dirsInChroot[i] = i;
 
+	    /* Make new mounts for the store and for /tmp.  That way, when
+	       'chrootRootDir' is made read-only below, these two mounts will
+	       remain writable (the store needs to be writable so derivation
+	       outputs can be written to it, and /tmp is writable by
+	       convention).  */
+	    auto chrootStoreDir = chrootRootDir + settings.nixStore;
+	    if (mount(chrootStoreDir.c_str(), chrootStoreDir.c_str(), 0, MS_BIND, 0) == -1)
+                throw SysError(format("read-write mount of store '%1%' failed") % chrootStoreDir);
+	    auto chrootTmpDir = chrootRootDir + "/tmp";
+	    if (mount(chrootTmpDir.c_str(), chrootTmpDir.c_str(), 0, MS_BIND, 0) == -1)
+                throw SysError(format("read-write mount of temporary directory '%1%' failed") % chrootTmpDir);
+
             /* Bind-mount all the directories from the "host"
                filesystem that we want in the chroot
                environment. */
@@ -2164,6 +2176,10 @@  void DerivationGoal::runChild()
 
             if (rmdir("real-root") == -1)
                 throw SysError("cannot remove real-root directory");
+
+	    /* Remount root as read-only.  */
+            if (mount("/", "/", 0, MS_BIND | MS_REMOUNT | MS_RDONLY, 0) == -1)
+                throw SysError(format("read-only remount of build root '%1%' failed") % chrootRootDir);
         }
 #endif