aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/namespaces.cc
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2023-01-27 15:25:56 +0100
committerEelco Dolstra <edolstra@gmail.com>2023-02-07 22:51:53 +0100
commitbc1d9fd8b5a14334af1d0455e6b4d595cae959d5 (patch)
tree0d2c294a900597ee2ae9b09e39d9f8cd98077343 /src/libutil/namespaces.cc
parentfb2f7f5dcc6b37a4f39f59d9f477d3fa57d79095 (diff)
Check whether we can use PID namespaces
In unprivileged podman containers, /proc is not fully visible (there are other filesystems mounted on subdirectories of /proc). Therefore we can't mount a new /proc in the sandbox that matches the PID namespace of the sandbox. So this commit automatically disables sandboxing if /proc is not fully visible.
Diffstat (limited to 'src/libutil/namespaces.cc')
-rw-r--r--src/libutil/namespaces.cc37
1 files changed, 32 insertions, 5 deletions
diff --git a/src/libutil/namespaces.cc b/src/libutil/namespaces.cc
index 0c3c3cbdd..222f0d11b 100644
--- a/src/libutil/namespaces.cc
+++ b/src/libutil/namespaces.cc
@@ -1,5 +1,8 @@
#include "namespaces.hh"
#include "util.hh"
+#include "finally.hh"
+
+#include <mntent.h>
#if __linux__
@@ -7,10 +10,10 @@ namespace nix {
bool userNamespacesSupported()
{
- static bool res = [&]() -> bool
+ static auto res = [&]() -> bool
{
if (!pathExists("/proc/self/ns/user")) {
- notice("'/proc/self/ns/user' does not exist; your kernel was likely built without CONFIG_USER_NS=y, which is required for sandboxing");
+ debug("'/proc/self/ns/user' does not exist; your kernel was likely built without CONFIG_USER_NS=y");
return false;
}
@@ -18,7 +21,7 @@ bool userNamespacesSupported()
if (!pathExists(maxUserNamespaces) ||
trim(readFile(maxUserNamespaces)) == "0")
{
- notice("user namespaces appear to be disabled; they are required for sandboxing; check '/proc/sys/user/max_user_namespaces'");
+ debug("user namespaces appear to be disabled; check '/proc/sys/user/max_user_namespaces'");
return false;
}
@@ -26,7 +29,7 @@ bool userNamespacesSupported()
if (pathExists(procSysKernelUnprivilegedUsernsClone)
&& trim(readFile(procSysKernelUnprivilegedUsernsClone)) == "0")
{
- notice("user namespaces appear to be disabled; they are required for sandboxing; check '/proc/sys/kernel/unprivileged_userns_clone'");
+ debug("user namespaces appear to be disabled; check '/proc/sys/kernel/unprivileged_userns_clone'");
return false;
}
@@ -43,7 +46,7 @@ bool userNamespacesSupported()
bool mountNamespacesSupported()
{
- static bool res = [&]() -> bool
+ static auto res = [&]() -> bool
{
bool useUserNamespace = userNamespacesSupported();
@@ -58,6 +61,30 @@ bool mountNamespacesSupported()
return res;
}
+bool pidNamespacesSupported()
+{
+ 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");
+ return false;
+ }
+
+ return true;
+ }();
+ return res;
+}
+
}
#endif