From 3065960f2ad9cc64737c07892eaded1215a23646 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 9 Jun 2023 16:09:29 +0200 Subject: [PATCH] restoreMountNamespace(): Restore the original root directory This is necessary when we're in a chroot environment, where the process root is not the same as the root of the mount namespace (e.g. in nixos-enter). Fixes #7602. (cherry picked from commit e54538c461e993827d9fbe3b8883d3887f184798) (cherry picked from commit 92e198f1db0807b173c4db8ed030a079dec2d8c3) (cherry picked from commit 9783bbad5484b3975b58a54ca1371b161966bb5d) --- src/libutil/util.cc | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 885bae69c9b..3ae14f991c2 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -1782,6 +1782,7 @@ void setStackSize(size_t stackSize) #if __linux__ static AutoCloseFD fdSavedMountNamespace; +static AutoCloseFD fdSavedRoot; #endif void saveMountNamespace() @@ -1789,10 +1790,11 @@ void saveMountNamespace() #if __linux__ static std::once_flag done; std::call_once(done, []() { - AutoCloseFD fd = open("/proc/self/ns/mnt", O_RDONLY); - if (!fd) + fdSavedMountNamespace = open("/proc/self/ns/mnt", O_RDONLY); + if (!fdSavedMountNamespace) throw SysError("saving parent mount namespace"); - fdSavedMountNamespace = std::move(fd); + + fdSavedRoot = open("/proc/self/root", O_RDONLY); }); #endif } @@ -1805,9 +1807,16 @@ void restoreMountNamespace() if (fdSavedMountNamespace && setns(fdSavedMountNamespace.get(), CLONE_NEWNS) == -1) throw SysError("restoring parent mount namespace"); - if (chdir(savedCwd.c_str()) == -1) { - throw SysError("restoring cwd"); + + 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()); }