diff options
author | Tom Hubrecht <github@mail.hubrecht.ovh> | 2024-05-28 16:01:11 +0200 |
---|---|---|
committer | Tom Hubrecht <github@mail.hubrecht.ovh> | 2024-05-29 11:41:16 +0200 |
commit | 8b6d2d39155e88250c576571a1251769b926ee83 (patch) | |
tree | 3b9c895f87c63b879be7086cdde2773a9fe28470 /src/libutil/namespaces.cc | |
parent | f79ee66646f66e5117583bcf9a579b7f538ca8bb (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.cc | 66 |
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 + +} |