Repository navigation
fix: open the window unsandboxed where Ubuntu denies the namespace's id maps - #590
Merged
Merged
Conversation
Chromium looks for chrome-sandbox in cef/, beside libcef.so, not beside lich-shell. The deb, rpm and AUR packages installed a root-owned 4755 copy beside lich-shell and left the one in cef/ at 755, so on a desktop that denies unprivileged user namespaces (Ubuntu's AppArmor policy) Chromium found an unusable helper and aborted the window with SIGTRAP. nfpm cannot mark a file inside the window's tree setuid: a second entry for the same destination collides, and the archlinux packager drops a setuid bit read from the source file. The mode is set from the install script instead, wired to post_upgrade for pacman too. The AUR PKGBUILD chmods the copy in cef/, and lich-shell's --no-sandbox decision checks that same file.
# Conflicts: # CHANGELOG.md
ubuntu-latest enforces kernel.apparmor_restrict_unprivileged_userns, the policy that lets lich-shell enter a user namespace and denies the id maps inside it. The step assembles the window the way a tarball ships it, with a helper nobody made setuid, and asserts it opens unsandboxed and stays up. Committed ahead of the fix, so the run on this commit shows the crash on a real AppArmor kernel.
lich-shell decided whether Chromium could sandbox by forking a child that only called unshare(CLONE_NEWUSER). Ubuntu's AppArmor policy lets that call succeed and denies the id maps inside the namespace, so the shell kept the sandbox on, Chromium's own probe failed, and its fallback to a setuid helper that a tarball cannot own aborted the window with SIGTRAP. The child now follows Credentials::CanCreateProcessInNewUserNS as Chromium 150 has it: deny setgroups, map its own gid and uid, drop every capability, enter a second user namespace. Where any step fails the window opens with --no-sandbox, as docs/ceilings.md promises for a tarball on Ubuntu.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follows #587, which put the setuid bit on the helper Chromium actually reads.
The probe said yes where Chromium says no
can_create_user_namespace()only calledunshare(CLONE_NEWUSER)in a forked child. Ubuntu 23.10 and later (kernel.apparmor_restrict_unprivileged_userns=1) let that call succeed and deny what follows inside the namespace. lich-shell therefore kept the sandbox on, Chromium's own probe failed, Chromium fell back to the setuid helper, and a helper that is not root 4755 (any tarball) aborted the browser process with SIGTRAP, exit 133. The ceilings bullet promised the opposite: a tarball on Ubuntu runs unsandboxed under Chrome's warning bar.The child now does what Chromium 150's does
Read from
sandbox/linux/services/credentials.cconbranch-heads/7871(CEF 150.0.10 is Chromium 150.0.7871.101),Credentials::CanCreateProcessInNewUserNS: enter a user namespace, writedenyto/proc/self/setgroupswhere the kernel has it, map its own gid and then uid one wide, drop every capability withcapset, andunshare(CLONE_NEWUSER)once more. The map lines are formatted before the fork; the child makes raw syscalls and_exitonly.Not mirrored: Chromium's
GetRESIdsprecondition (real, effective and saved ids agree). Only a setuid or setgid lich-shell fails it, and Chromium then refuses to start with the sandbox on at all.Proof
Local, emulating the shape. This machine has no AppArmor, so Landlock stands in:
setpriv --landlock-access fs:write-filewith write access allowed beneath every top-level directory except/proc. Under itunshare --user trueexits 0 andunshare --user --map-root-user truefails withcannot open /proc/self/uid_map: Permission denied, the denial bwrap reported on a real Ubuntu desktop. The window, launched with--ozone-platform=headlessand no display:FATAL:setuid_sandbox_host.cc:166 The SUID sandbox helper binary was found, but is not configured correctlyopening the window unsandboxed, still up at 20 sReal AppArmor, in CI. GitHub's ubuntu-24.04 runner enforces the restriction (actions/runner-images#10443; the image change to lift it, actions/runner-images#11489, was closed). The new step in the
shelljob checks that the sysctl reads 1, assembles the window the way a tarball ships it, and requires it to stay up unsandboxed. It landed one commit ahead of the fix, so the two runs are the before and after:the window did not open unsandboxed (exit 133)overFATAL:sandbox/linux/suid/client/setuid_sandbox_host.cc:166 The SUID sandbox helper binary was found, but is not configured correctly ... /home/runner/work/_temp/shell/cef/chrome-sandbox, the crash Ubuntu users hit.Still unproven: a real Ubuntu desktop session, and #587's package path (a root 4755 helper keeping the sandbox on under the same policy).
Test plan
cargo fmt --check,cargo clippy --release --all-targets -- -D warnings,cargo test --release(14 passed)maps_only_its_own_id_into_the_namespace; the fork itself is the documented coverage exceptionmain, no fix): the step fails on the runner with exit 133 and the helper FATAL