Ubuntu · Boot & system hardening

Restrict unprivileged user namespaces with AppArmor

When it fails: Any local program can create unprivileged user namespaces. User namespaces give an unprivileged process root-like capabilities over kernel interfaces that are a frequent source of privilege escalation bugs.

CB-UBU-BOOT-016mediumactiveautomatedautomated fixprofile core

As released in v0.1.2 (beta). Current state.

Description

With kernel.apparmor_restrict_unprivileged_userns = 1, an unprivileged process can only create a user namespace when its AppArmor profile allows it (the userns rule). Unconfined programs get a namespace without any capability in it. Ubuntu ships profiles that grant the right to the programs that need it, such as browsers, Flatpak, LXC, Podman and Buildah.

Ubuntu turns it on by default in /usr/lib/sysctl.d/10-apparmor.conf from 24.04 on. The control guards against the common workaround of setting it back to 0 system-wide. Unlike kernel.unprivileged_userns_clone, it keeps namespaces available to the programs that are allowed to use them.

Rationale

Inside a user namespace, an unprivileged user holds capabilities such as CAP_NET_ADMIN or CAP_SYS_ADMIN over the namespace, which exposes large parts of the kernel (netfilter, filesystems, network stacks) to them. Many local privilege escalation exploits start by creating one. Restricting namespaces to profiled programs removes that entry point for everything else.

Impact

None on a default install. A program that needs user namespaces and has no AppArmor profile (a self-built browser, an application from outside the archive, some sandboxing or container tools) fails to start its sandbox. Give it a profile with the userns, rule in /etc/apparmor.d/ instead of turning the restriction off for the whole system.

Applies when

Versions: 24.0426.04

The sysctl only exists in Ubuntu kernels from 23.10 on. The 20.04 and 22.04 kernels do not have it.

Setting

Locationsysctl `kernel.apparmor_restrict_unprivileged_userns`, persisted in `/etc/sysctl.d/`
Default1
Recommended1

Audit

Run sysctl kernel.apparmor_restrict_unprivileged_userns. The value must be 1. Then check that no sysctl configuration file sets it to 0.

Automated: every check must pass. Scanners report each check by its id.

running

Running value of kernel.apparmor_restrict_unprivileged_userns.

key: kernel.apparmor_restrict_unprivileged_userns
value: 1

Remediation

Comment out every assignment of the key in /etc/sysctl.conf, /etc/sysctl.d/ and /run/sysctl.d/ (a file such as 99-userns.conf sorts after 60-cirsec.conf and wins), create /etc/sysctl.d/60-cirsec.conf containing kernel.apparmor_restrict_unprivileged_userns = 1, then run sysctl --system.

Restartnone
Disruptionlow

Rollback

Remove the line from /etc/sysctl.d/60-cirsec.conf and run sysctl --system. Commented-out assignments can be restored from the backup directory /var/backups/cirsec/.

set

# CB-UBU-BOOT-016: set kernel.apparmor_restrict_unprivileged_userns = 1 for good.
# The usual workaround puts "= 0" in a file such as /etc/sysctl.d/99-userns.conf, which sorts after
# 60-cirsec.conf and would win at the next boot: such assignments are commented out (with a backup).
k=kernel.apparmor_restrict_unprivileged_userns
re='^[[:space:]]*kernel[./]apparmor_restrict_unprivileged_userns[[:space:]]*='
c=/etc/sysctl.d/60-cirsec.conf
for f in /etc/sysctl.conf /etc/sysctl.d/*.conf /run/sysctl.d/*.conf; do
  [ -f "$f" ] && [ "$f" != "$c" ] || continue
  grep -Eq "$re" "$f" || continue
  cb_backup "$f"
  sed -i --follow-symlinks -E "s|$re|# Disabled by CIRSEC Baselines CB-UBU-BOOT-016: &|" "$f"
done
cb_backup "$c"
touch "$c"
sed -i '/^[[:space:]]*kernel\.apparmor_restrict_unprivileged_userns[[:space:]]*=/d' "$c"
printf '%s = 1\n' "$k" >>"$c"
sysctl -q -w "$k=1"

Handwritten code reads parameters from CB_<NAME> environment variables. Each release turns these fixes into remediate.sh and an Ansible role per profile: dry run by default, a fix runs only when its check fails.

References

Mappings

FrameworkIDRelation
NIST SP 800-53 Rev. 55.1.1AC-6related
NIST SP 800-53 Rev. 55.1.1CM-7related

How this control relates to the other framework's: equivalent, stricter, looser, partial or related.

Threats mitigated

People and lifecycle

Authors
Verified2026-10-19 by Sn0wAlice on 24.04, Proxmox VM, Ubuntu 24.04 cloud image, kernel 6.8.0-147-generic, BIOS boot. Passes on a fresh install (1); with /etc/sysctl.d/99-userns.conf setting 0 it fails, the fix comments it out; 1 kept after reboot; strict snap runs, unprivileged unshare -U refused.
Verified2026-10-19 by Sn0wAlice on 26.04, Proxmox VM, Ubuntu 26.04 cloud image, kernel 7.0.0-38-generic, BIOS boot. Passes on a fresh install (1); with /etc/sysctl.d/99-userns.conf setting 0 it fails, the fix comments it out; 1 kept after reboot; strict snap runs, unprivileged unshare -U refused.
Introduced inv0.1.0
Created, updated2026-10-19, 2026-10-19
Translationsfr