Forcing Namespace Sandbox in Chrome & Electron

There seems to be a problem in certain linux distributions where user namespace is disabled. (eg: debian, archlinux)
This affects sandboxing in google chrome/chromium as well as applications built on electron (eg: discord, slack, brave, atom, keybase, github desktop)

chrome_chromiumelectron_ico

electron_apps

To check if you are affected, go to chrome://sandbox, if you see Namespace Sandbox: No you are affected.

Background

Google Chrome (& Chromium) on linux uses various technologies for different layers of sandboxing & despite people noting possible security problems with the use of SUID sandboxing google still continue to support it (for legacy/compatibility).
Chrome supports user namespaces for Layer-1 sandboxing as well as using seccomp-bpf for Layer-2.

Looking at the chromium mailing list you can see some points against the use of setuid (from 2013).

The setuid sandbox has to go:
- For each "chroot me" event, the current mechanism requires having previously started a setuid helper.
This is not compatible with a more generic and universal Zygote.
It is in conflict with the flexibility we want for Mojo.
- chroot helpers are tied to new PID and network namespaces.
Again, this conflicts with flexibility as network namespaces use a lot of kernel memory.
- Shipping a setuid binary on Linux and on Chrome OS is bad for security.
- Having to update a setuid executable on our bots when we want to make changes is problematic

The Problem

Although user namespace has been supported by the linux kernel since 3.8 it is not enabled by default on some linux distributions. (So far I have only noticed this on Archlinux & Debian)

archlinux debian

If you check your lxc config you may think everything is fine.

$ lxc-checkconfig
--- Namespaces ---
Namespaces: enabled
Utsname namespace: enabled
Ipc namespace: enabled
Pid namespace: enabled
User namespace: enabled
Network namespace: enabled

If you check your kernel config you will probably find user namespace is enabled

zcat /proc/config.gz | grep CONFIG_USER_NS
CONFIG_USER_NS=y

But if you check chrome / chromium chrome://sandbox will show the namespace sandbox is not being used.
This is because unprivileged_userns_clone variable is disabled.

sysctl kernel.unprivileged_userns_clone
kernel.unprivileged_userns_clone = 0

You will need to enable this in order to use the namespace sandbox.

The Fix

To fix this you need to enable the unprivileged_userns_clone variable in the kernel.

sudo sysctl -w kernel.unprivileged_userns_clone=1

Now when you run chromium, chrome://sandbox should show the namespace sandbox is enabled.
To make this change permanent add the user namespace setting to sysctl.d.

sudo sh -c "echo 'kernel.unprivileged_userns_clone=1' > /etc/sysctl.d/00-userns.conf"

Forcing Namespace Sandbox

I added a check in my chrome script on github to check if user namespace is enabled before executng chromium. (if it is not enabled you get an error message with information on google chromium sandboxing on linux)

# Check if user namespaces is enabled (for sandbox)
# Note: this is to enforce user namespaces for Layer-1 sandbox
if [[ ! (-r /proc/sys/kernel/unprivileged_userns_clone && $(< /proc/sys/kernel/unprivileged_userns_clone) == 1 && -n $(zcat /proc/config.gz | grep CONFIG_USER_NS=y) ) ]]; then
    echo "User namespaces are not detected as enabled on your system, this is required for Layer-1 sandbox"
    echo "No usable sandbox! Update your kernel or see https://github.com/chromium/chromium/blob/master/docs/linux_sandboxing.md for more information."
    exit 1
fi

More information regarding chromium sandboxing on linux can be found on github & googlesource

comments powered by Disqus