aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/namespaces.cc
diff options
context:
space:
mode:
authorTom Hubrecht <github@mail.hubrecht.ovh>2024-05-28 16:01:11 +0200
committerTom Hubrecht <github@mail.hubrecht.ovh>2024-05-29 11:41:16 +0200
commit8b6d2d39155e88250c576571a1251769b926ee83 (patch)
tree3b9c895f87c63b879be7086cdde2773a9fe28470 /src/libutil/namespaces.cc
parentf79ee66646f66e5117583bcf9a579b7f538ca8bb (diff)
util.{hh,cc}: Split out namespaces.{hh,cc}
Change-Id: I8fd3f3b50c15ede29d489066b4e8d99c2c4636a6
Diffstat (limited to 'src/libutil/namespaces.cc')
-rw-r--r--src/libutil/namespaces.cc66
1 files changed, 62 insertions, 4 deletions
diff --git a/src/libutil/namespaces.cc b/src/libutil/namespaces.cc
index d092e6fcc..98d3cd306 100644
--- a/src/libutil/namespaces.cc
+++ b/src/libutil/namespaces.cc
@@ -1,5 +1,4 @@
-#if __linux__
-
+#include "file-descriptor.hh"
#include "file-system.hh"
#include "logging.hh"
#include "namespaces.hh"
@@ -8,8 +7,67 @@
#include <sys/mount.h>
+#if __linux__
+# include <mutex>
+# include <sys/resource.h>
+#endif
+
namespace nix {
+#if __linux__
+static AutoCloseFD fdSavedMountNamespace;
+static AutoCloseFD fdSavedRoot;
+#endif
+
+void saveMountNamespace()
+{
+#if __linux__
+ static std::once_flag done;
+ std::call_once(done, []() {
+ fdSavedMountNamespace = AutoCloseFD{open("/proc/self/ns/mnt", O_RDONLY)};
+ if (!fdSavedMountNamespace)
+ throw SysError("saving parent mount namespace");
+
+ fdSavedRoot = AutoCloseFD{open("/proc/self/root", O_RDONLY)};
+ });
+#endif
+}
+
+void restoreMountNamespace()
+{
+#if __linux__
+ try {
+ auto savedCwd = absPath(".");
+
+ if (fdSavedMountNamespace && setns(fdSavedMountNamespace.get(), CLONE_NEWNS) == -1)
+ throw SysError("restoring parent mount namespace");
+
+ if (fdSavedRoot) {
+ if (fchdir(fdSavedRoot.get()))
+ throw SysError("chdir into saved root");
+ if (chroot("."))
+ throw SysError("chroot into saved root");
+ }
+
+ if (chdir(savedCwd.c_str()) == -1)
+ throw SysError("restoring cwd");
+ } catch (Error & e) {
+ debug(e.msg());
+ }
+#endif
+}
+
+void unshareFilesystem()
+{
+#ifdef __linux__
+ if (unshare(CLONE_FS) != 0 && errno != EPERM)
+ throw SysError("unsharing filesystem state in download thread");
+#endif
+}
+
+
+#if __linux__
+
static void diagnoseUserNamespaces()
{
if (!pathExists("/proc/self/ns/user")) {
@@ -95,6 +153,6 @@ bool mountAndPidNamespacesSupported()
return res;
}
-}
-
#endif
+
+}