aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/namespaces.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libutil/namespaces.cc')
-rw-r--r--src/libutil/namespaces.cc72
1 files changed, 66 insertions, 6 deletions
diff --git a/src/libutil/namespaces.cc b/src/libutil/namespaces.cc
index dec3a7189..98d3cd306 100644
--- a/src/libutil/namespaces.cc
+++ b/src/libutil/namespaces.cc
@@ -1,13 +1,73 @@
-#if __linux__
-
+#include "file-descriptor.hh"
+#include "file-system.hh"
+#include "logging.hh"
#include "namespaces.hh"
-#include "util.hh"
-#include "finally.hh"
+#include "processes.hh"
+#include "strings.hh"
#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")) {
@@ -93,6 +153,6 @@ bool mountAndPidNamespacesSupported()
return res;
}
-}
-
#endif
+
+}