aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/namespaces.cc
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2023-02-10 14:38:14 +0100
committerEelco Dolstra <edolstra@gmail.com>2023-02-10 14:38:14 +0100
commitf094ba7386fc5fbb3df5fd84008ca07d2289ff26 (patch)
treef4796141204130e6f157487b312d9d8ace8551e2 /src/libutil/namespaces.cc
parent5597d68e2d73a3b89ff36fcfeac82d7fe7d4f384 (diff)
Simplify the PID namespace check: just try to mount /proc
Fixes #7783.
Diffstat (limited to 'src/libutil/namespaces.cc')
-rw-r--r--src/libutil/namespaces.cc91
1 files changed, 44 insertions, 47 deletions
diff --git a/src/libutil/namespaces.cc b/src/libutil/namespaces.cc
index fdd52d92b..f66accb10 100644
--- a/src/libutil/namespaces.cc
+++ b/src/libutil/namespaces.cc
@@ -4,7 +4,7 @@
#include "util.hh"
#include "finally.hh"
-#include <mntent.h>
+#include <sys/mount.h>
namespace nix {
@@ -33,63 +33,60 @@ bool userNamespacesSupported()
return false;
}
- Pid pid = startProcess([&]()
- {
- auto res = unshare(CLONE_NEWUSER);
- _exit(res ? 1 : 0);
- });
-
- bool supported = pid.wait() == 0;
-
- if (!supported)
- debug("user namespaces do not work on this system");
-
- return supported;
- }();
- return res;
-}
-
-bool mountNamespacesSupported()
-{
- static auto res = [&]() -> bool
- {
- bool useUserNamespace = userNamespacesSupported();
-
- Pid pid = startProcess([&]()
- {
- auto res = unshare(CLONE_NEWNS | (useUserNamespace ? CLONE_NEWUSER : 0));
- _exit(res ? 1 : 0);
- });
-
- bool supported = pid.wait() == 0;
-
- if (!supported)
- debug("mount namespaces do not work on this system");
+ try {
+ Pid pid = startProcess([&]()
+ {
+ _exit(0);
+ }, {
+ .cloneFlags = CLONE_NEWUSER
+ });
+
+ auto r = pid.wait();
+ assert(!r);
+ } catch (SysError & e) {
+ debug("user namespaces do not work on this system: %s", e.msg());
+ return false;
+ }
- return supported;
+ return true;
}();
return res;
}
-bool pidNamespacesSupported()
+bool mountAndPidNamespacesSupported()
{
static auto res = [&]() -> bool
{
- /* Check whether /proc is fully visible, i.e. there are no
- filesystems mounted on top of files inside /proc. If this
- is not the case, then we cannot mount a new /proc inside
- the sandbox that matches the sandbox's PID namespace.
- See https://lore.kernel.org/lkml/87tvsrjai0.fsf@xmission.com/T/. */
- auto fp = fopen("/proc/mounts", "r");
- if (!fp) return false;
- Finally delFP = [&]() { fclose(fp); };
-
- while (auto ent = getmntent(fp))
- if (hasPrefix(std::string_view(ent->mnt_dir), "/proc/")) {
- debug("PID namespaces do not work because /proc is not fully visible; disabling sandboxing");
+ try {
+
+ Pid pid = startProcess([&]()
+ {
+ /* Make sure we don't remount the parent's /proc. */
+ if (mount(0, "/", 0, MS_PRIVATE | MS_REC, 0) == -1)
+ _exit(1);
+
+ /* Test whether we can remount /proc. The kernel disallows
+ this if /proc is not fully visible, i.e. if there are
+ filesystems mounted on top of files inside /proc. See
+ https://lore.kernel.org/lkml/87tvsrjai0.fsf@xmission.com/T/. */
+ if (mount("none", "/proc", "proc", 0, 0) == -1)
+ _exit(2);
+
+ _exit(0);
+ }, {
+ .cloneFlags = CLONE_NEWNS | CLONE_NEWPID | (userNamespacesSupported() ? CLONE_NEWUSER : 0)
+ });
+
+ if (pid.wait()) {
+ debug("PID namespaces do not work on this system: cannot remount /proc");
return false;
}
+ } catch (SysError & e) {
+ debug("mount namespaces do not work on this system: %s", e.msg());
+ return false;
+ }
+
return true;
}();
return res;