aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/util.cc
diff options
context:
space:
mode:
authorYorick van Pelt <yorick@yorickvanpelt.nl>2021-10-15 16:25:49 +0200
committerYorick van Pelt <yorick@yorickvanpelt.nl>2021-10-15 16:25:49 +0200
commitfcb8af550f5fca37458da0d9042a2b59523eb304 (patch)
tree050bde8ad2b73808860e9c94043a4532fae66bd2 /src/libutil/util.cc
parent130284b8508dad3c70e8160b15f3d62042fc730a (diff)
Restore parent mount namespace in restoreProcessContext
This ensures any started processes can't write to /nix/store (except during builds). This partially reverts 01d07b1e, which happened because of #2646. The problem was only happening after nix downloads anything, causing me to suspect the download thread. The problem turns out to be: "A process can't join a new mount namespace if it is sharing filesystem-related attributes with another process", in this case this process is the curl thread. Ideally, we might kill it before spawning the shell process, but it's inside a static variable in the getFileTransfer() function. So instead, stop it from sharing FS state using unshare(). A strategy such as the one from #5057 (single-threaded chroot helper binary) is also very much on the table. Fixes #4337.
Diffstat (limited to 'src/libutil/util.cc')
-rw-r--r--src/libutil/util.cc28
1 files changed, 26 insertions, 2 deletions
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 563a72c12..a5e961c1e 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -1629,10 +1629,34 @@ void setStackSize(size_t stackSize)
}
#endif
}
+static AutoCloseFD fdSavedMountNamespace;
-void restoreProcessContext()
+void saveMountNamespace()
+{
+#if __linux__
+ static 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
+}
+
+void restoreProcessContext(bool restoreMounts)
{
restoreSignals();
+ if (restoreMounts) {
+ restoreMountNamespace();
+ }
restoreAffinity();
@@ -1766,7 +1790,7 @@ void commonChildInit(Pipe & logPipe)
logger = makeSimpleLogger();
const static string pathNullDevice = "/dev/null";
- restoreProcessContext();
+ restoreProcessContext(false);
/* Put the child in a separate session (and thus a separate
process group) so that it has no controlling terminal (meaning