about summary refs log tree commit diff
path: root/src/libutil
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2018-11-13T15·15+0100
committerEelco Dolstra <edolstra@gmail.com>2018-11-13T15·15+0100
commita0ef21262f4d5652bfb65cfacaec01d89c475a93 (patch)
tree6fd2c483dde9bb6f56ff989b6724d2a49679d74a /src/libutil
parent56f6e382be03b587c1f7260e16fce6622329d1a4 (diff)
Restore parent mount namespace before executing a child process
This ensures that they can't write to /nix/store. Fixes #2535.
Diffstat (limited to 'src/libutil')
-rw-r--r--src/libutil/util.cc23
-rw-r--r--src/libutil/util.hh9
2 files changed, 32 insertions, 0 deletions
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 259eaf0a0dd3..6e4536e6e4ea 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -936,6 +936,7 @@ pid_t startProcess(std::function<void()> fun, const ProcessOptions & options)
                 throw SysError("setting death signal");
 #endif
             restoreAffinity();
+            restoreMountNamespace();
             fun();
         } catch (std::exception & e) {
             try {
@@ -1504,4 +1505,26 @@ std::unique_ptr<InterruptCallback> createInterruptCallback(std::function<void()>
     return std::unique_ptr<InterruptCallback>(res.release());
 }
 
+static AutoCloseFD fdSavedMountNamespace;
+
+void saveMountNamespace()
+{
+#if __linux__
+    std::once_flag done;
+    std::call_once(done, []() {
+        fdSavedMountNamespace = open("/proc/self/ns/mnt", O_RDONLY);
+        if (!fdSavedMountNamespace)
+            throw SysError("saving parent mount namespace");
+    });
+#endif
+}
+
+void restoreMountNamespace()
+{
+#if __linux__
+    if (fdSavedMountNamespace && setns(fdSavedMountNamespace.get(), CLONE_NEWNS) == -1)
+        throw SysError("restoring parent mount namespace");
+#endif
+}
+
 }
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index bda87bee433e..2689cbd8b412 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -514,4 +514,13 @@ typedef std::function<bool(const Path & path)> PathFilter;
 extern PathFilter defaultPathFilter;
 
 
+/* Save the current mount namespace. Ignored if called more than
+   once. */
+void saveMountNamespace();
+
+/* Restore the mount namespace saved by saveMountNamespace(). Ignored
+   if saveMountNamespace() was never called. */
+void restoreMountNamespace();
+
+
 }