From 8b6d2d39155e88250c576571a1251769b926ee83 Mon Sep 17 00:00:00 2001 From: Tom Hubrecht Date: Tue, 28 May 2024 16:01:11 +0200 Subject: [PATCH] util.{hh,cc}: Split out namespaces.{hh,cc} Change-Id: I8fd3f3b50c15ede29d489066b4e8d99c2c4636a6 --- src/libstore/filetransfer.cc | 2 +- src/libutil/current-process.cc | 1 + src/libutil/namespaces.cc | 66 +++++++++++++++++++++++++++++++--- src/libutil/namespaces.hh | 20 +++++++++++ src/libutil/util.cc | 52 --------------------------- src/libutil/util.hh | 20 ----------- src/nix/main.cc | 1 + 7 files changed, 85 insertions(+), 77 deletions(-) diff --git a/src/libstore/filetransfer.cc b/src/libstore/filetransfer.cc index 492463a61..dc656f444 100644 --- a/src/libstore/filetransfer.cc +++ b/src/libstore/filetransfer.cc @@ -1,5 +1,5 @@ #include "filetransfer.hh" -#include "util.hh" +#include "namespaces.hh" #include "globals.hh" #include "store-api.hh" #include "s3.hh" diff --git a/src/libutil/current-process.cc b/src/libutil/current-process.cc index 41f591b0c..f9a08685f 100644 --- a/src/libutil/current-process.cc +++ b/src/libutil/current-process.cc @@ -1,6 +1,7 @@ #include "current-process.hh" #include "file-system.hh" #include "logging.hh" +#include "namespaces.hh" #include "signals.hh" #include "util.hh" #include "strings.hh" 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 +#if __linux__ +# include +# include +#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 + +} diff --git a/src/libutil/namespaces.hh b/src/libutil/namespaces.hh index 0b7eeb66c..3a920e665 100644 --- a/src/libutil/namespaces.hh +++ b/src/libutil/namespaces.hh @@ -3,6 +3,26 @@ namespace nix { +/** + * 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(); + +/** + * Cause this thread to not share any FS attributes with the main + * thread, because this causes setns() in restoreMountNamespace() to + * fail. + */ +void unshareFilesystem(); + + #if __linux__ bool userNamespacesSupported(); diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 8e813abc2..6d6e55ad1 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -88,56 +88,4 @@ void ignoreException(Verbosity lvl) -#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 -} - - } diff --git a/src/libutil/util.hh b/src/libutil/util.hh index e408821b9..867f0a80d 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -39,26 +39,6 @@ struct Source; extern const std::string nativeSystem; -/** - * 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(); - -/** - * Cause this thread to not share any FS attributes with the main - * thread, because this causes setns() in restoreMountNamespace() to - * fail. - */ -void unshareFilesystem(); - - /** * Exception handling in destructors: print an error message, then * ignore the exception. diff --git a/src/nix/main.cc b/src/nix/main.cc index 0f98861d5..5d92cfd76 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -8,6 +8,7 @@ #include "eval-settings.hh" #include "globals.hh" #include "legacy.hh" +#include "namespaces.hh" #include "shared.hh" #include "store-api.hh" #include "filetransfer.hh"