diff options
author | Jade Lovelace <lix@jade.fyi> | 2024-05-04 00:55:15 -0700 |
---|---|---|
committer | jade <lix@jade.fyi> | 2024-05-05 00:37:24 +0000 |
commit | e3b702fa2211c05ead6f030e63fc869c1b69413e (patch) | |
tree | 6b6cc5c8f8a0cbb9ab0c554c32aab5276d9de025 /src/libutil | |
parent | 9909a175bf1602e7bb4ebfc1c9befeaa56da1fb4 (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
Diffstat (limited to 'src/libutil')
-rw-r--r-- | src/libutil/namespaces.cc | 45 |
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; } |