aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJade Lovelace <lix@jade.fyi>2024-05-04 00:55:15 -0700
committerjade <lix@jade.fyi>2024-05-05 00:37:24 +0000
commite3b702fa2211c05ead6f030e63fc869c1b69413e (patch)
tree6b6cc5c8f8a0cbb9ab0c554c32aab5276d9de025
parent9909a175bf1602e7bb4ebfc1c9befeaa56da1fb4 (diff)
Actually try making a userns before assuming they don't work
If unprivileged userns are *believed* to be disabled (such as with "kernel.unprivileged_userns_clone = 0"), Lix would previously *give up* on trying to use a user namespace before actually trying it, even if, in cases such as unprivileged_userns_clone, it would actually be allowed since Nix has CAP_SYS_ADMIN when running as daemon. (see, e.g. https://github.com/archlinux/linux/commit/25d4709a4fc0e4f3b432c24b60dd508fb84f0cb2) We changed it to actually try it first, and then diagnose possible causes, and also to be more loud about the whole thing, using warnings instead of debugs. These warnings will only print on the first build run by the daemon, which is, tbh, eh, shrug. This is what led to us realizing that no-userns was a poorly exercised condition. Change-Id: I8e4f21afc89c574020dc7e89a560cc740ce6573a
-rw-r--r--src/libutil/namespaces.cc45
1 files changed, 23 insertions, 22 deletions
diff --git a/src/libutil/namespaces.cc b/src/libutil/namespaces.cc
index f66accb10..dec3a7189 100644
--- a/src/libutil/namespaces.cc
+++ b/src/libutil/namespaces.cc
@@ -8,31 +8,31 @@
namespace nix {
-bool userNamespacesSupported()
+static void diagnoseUserNamespaces()
{
- static auto res = [&]() -> bool
- {
- if (!pathExists("/proc/self/ns/user")) {
- debug("'/proc/self/ns/user' does not exist; your kernel was likely built without CONFIG_USER_NS=y");
- return false;
- }
+ if (!pathExists("/proc/self/ns/user")) {
+ warn("'/proc/self/ns/user' does not exist; your kernel was likely built without CONFIG_USER_NS=y");
+ }
- Path maxUserNamespaces = "/proc/sys/user/max_user_namespaces";
- if (!pathExists(maxUserNamespaces) ||
- trim(readFile(maxUserNamespaces)) == "0")
- {
- debug("user namespaces appear to be disabled; check '/proc/sys/user/max_user_namespaces'");
- return false;
- }
+ Path maxUserNamespaces = "/proc/sys/user/max_user_namespaces";
+ if (!pathExists(maxUserNamespaces) ||
+ trim(readFile(maxUserNamespaces)) == "0")
+ {
+ warn("user namespaces appear to be disabled; check '/proc/sys/user/max_user_namespaces'");
+ }
- Path procSysKernelUnprivilegedUsernsClone = "/proc/sys/kernel/unprivileged_userns_clone";
- if (pathExists(procSysKernelUnprivilegedUsernsClone)
- && trim(readFile(procSysKernelUnprivilegedUsernsClone)) == "0")
- {
- debug("user namespaces appear to be disabled; check '/proc/sys/kernel/unprivileged_userns_clone'");
- return false;
- }
+ Path procSysKernelUnprivilegedUsernsClone = "/proc/sys/kernel/unprivileged_userns_clone";
+ if (pathExists(procSysKernelUnprivilegedUsernsClone)
+ && trim(readFile(procSysKernelUnprivilegedUsernsClone)) == "0")
+ {
+ warn("user namespaces appear to be disabled for unprivileged users; check '/proc/sys/kernel/unprivileged_userns_clone'");
+ }
+}
+bool userNamespacesSupported()
+{
+ static auto res = [&]() -> bool
+ {
try {
Pid pid = startProcess([&]()
{
@@ -44,7 +44,8 @@ bool userNamespacesSupported()
auto r = pid.wait();
assert(!r);
} catch (SysError & e) {
- debug("user namespaces do not work on this system: %s", e.msg());
+ warn("user namespaces do not work on this system: %s", e.msg());
+ diagnoseUserNamespaces();
return false;
}