Problem
docs/rootless.md recommends kernel.apparmor_restrict_unprivileged_userns=0 in two places:
- "Distribution-specific hint" → "Ubuntu, 24.04 or later"
- "Troubleshooting" →
fork/exec /proc/self/exe: permission denied entry
That sysctl turns the restriction off system-wide, so every unprivileged binary on the host regains the ability to create user namespaces — which is exactly the attack surface Ubuntu 24.04 introduced the restriction to close. Presenting it as the primary fix is a step backwards, security-wise.
Proposal
Document a per-binary AppArmor profile as the preferred approach, and keep the sysctl as a fallback. This is what rootlesskit's own CI does:
https://github.com/rootless-containers/rootlesskit/blob/70434a48ddd6e1e0c8a6549323a5261ddb845b37/.github/workflows/main.yaml#L27
Something like:
cat <<EOT | sudo tee /etc/apparmor.d/usr.local.bin.rootlesskit
abi <abi/4.0>,
include <tunables/global>
/usr/local/bin/rootlesskit flags=(unconfined) {
userns,
}
EOT
sudo systemctl restart apparmor.service
Since buildkitd is launched via rootlesskit, it is rootlesskit that creates the user namespace, so the profile only needs to cover that binary. This grants userns to rootlesskit alone and leaves the restriction in place for everything else on the host.
The path in the profile (and the file name) must match wherever rootlesskit is actually installed, so the doc should call that out.
Problem
docs/rootless.mdrecommendskernel.apparmor_restrict_unprivileged_userns=0in two places:fork/exec /proc/self/exe: permission deniedentryThat sysctl turns the restriction off system-wide, so every unprivileged binary on the host regains the ability to create user namespaces — which is exactly the attack surface Ubuntu 24.04 introduced the restriction to close. Presenting it as the primary fix is a step backwards, security-wise.
Proposal
Document a per-binary AppArmor profile as the preferred approach, and keep the sysctl as a fallback. This is what rootlesskit's own CI does:
https://github.com/rootless-containers/rootlesskit/blob/70434a48ddd6e1e0c8a6549323a5261ddb845b37/.github/workflows/main.yaml#L27
Something like:
Since
buildkitdis launched viarootlesskit, it is rootlesskit that creates the user namespace, so the profile only needs to cover that binary. This grantsusernsto rootlesskit alone and leaves the restriction in place for everything else on the host.The path in the profile (and the file name) must match wherever rootlesskit is actually installed, so the doc should call that out.