From 5bebecc427e11d078eb8e8c44d1e665ef33a8cb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zolt=C3=A1n=20Papp?= Date: Mon, 1 Jun 2026 20:06:44 +0200 Subject: [PATCH] ui: disable WebKit sandbox when unprivileged userns are blocked WebKitGTK crashes at startup when its bubblewrap sandbox can't create an unprivileged user namespace (bwrap: setting up uid map: Permission denied -> Failed to fully launch dbus-proxy -> panic in webkit_web_view_load_uri). This happens in containers/VMs and on Ubuntu 24.04+ where AppArmor restricts unprivileged user namespaces. Detect that the kernel blocks userns via procfs and set WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS so the UI stays usable; honor an explicit user override either way. --- client/ui/tray_linux.go | 52 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/client/ui/tray_linux.go b/client/ui/tray_linux.go index a213ce2f9..f732cbc9c 100644 --- a/client/ui/tray_linux.go +++ b/client/ui/tray_linux.go @@ -2,10 +2,18 @@ package main -import "os" +import ( + "os" + "strings" +) -// init runs before Wails' own init(), so the env var is set in time. +// init runs before Wails' own init(), so the env vars are set in time. func init() { + disableDMABUFRenderer() + disableWebKitSandboxIfNeeded() +} + +func disableDMABUFRenderer() { if os.Getenv("WEBKIT_DISABLE_DMABUF_RENDERER") != "" { return } @@ -18,6 +26,46 @@ func init() { _ = os.Setenv("WEBKIT_DISABLE_DMABUF_RENDERER", "1") } +// disableWebKitSandboxIfNeeded works around WebKitGTK crashing at startup when +// its bubblewrap (bwrap) sandbox can't create an unprivileged user namespace — +// "bwrap: setting up uid map: Permission denied" followed by "Failed to fully +// launch dbus-proxy" and a panic in webkit_web_view_load_uri. This happens in +// containers/VMs and on Ubuntu 24.04+ where AppArmor restricts unprivileged +// user namespaces (kernel.apparmor_restrict_unprivileged_userns=1). Software +// can't grant the namespace from here, so when we detect that userns are +// blocked we disable the WebKit sandbox to keep the UI usable. The user can +// override either way by setting WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS. +func disableWebKitSandboxIfNeeded() { + if _, set := os.LookupEnv("WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS"); set { + return + } + if unprivilegedUsernsAllowed() { + return + } + _ = os.Setenv("WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS", "1") +} + +// unprivilegedUsernsAllowed reports whether the kernel currently permits +// unprivileged user namespaces, which WebKit's bwrap sandbox needs. It reads +// the relevant procfs knobs; on a kernel that doesn't expose them (older or +// hardened), it conservatively assumes namespaces are available so we don't +// needlessly weaken the sandbox. +func unprivilegedUsernsAllowed() bool { + // Debian/Ubuntu legacy switch: 0 disables unprivileged user namespaces. + if v, err := os.ReadFile("/proc/sys/kernel/unprivileged_userns_clone"); err == nil { + if strings.TrimSpace(string(v)) == "0" { + return false + } + } + // Ubuntu 24.04+ AppArmor restriction: non-zero restricts/blocks them. + if v, err := os.ReadFile("/proc/sys/kernel/apparmor_restrict_unprivileged_userns"); err == nil { + if strings.TrimSpace(string(v)) != "0" { + return false + } + } + return true +} + // On Linux, the system tray provider may require the menu to be recreated // rather than updated in place. The rebuildExitNodeMenu method in tray.go // already handles this by removing and re-adding items; no additional