Summary
pkg/apparmor/internal/supported/supported.go returns "AppArmor is not supported on rootless containers" unconditionally when unshare.IsRootless() is true. The comment in apparmor_linux.go justifies this as "requires root", but aa_change_onexec() operates by writing to /proc/self/attr/exec — this does not require elevated privileges and works from unprivileged processes on kernels that support it.
The result is that podman info reports apparmorEnabled: false on rootless systems with AppArmor fully operational, and apparmor_profile in containers.conf is silently ignored.
Affected files
pkg/apparmor/internal/supported/supported.go — IsSupported() hard-gates on IsRootless()
pkg/apparmor/apparmor_linux.go — lines 86–87, 152–153, 265–269
Comparison with Docker
Docker applies docker-default to all containers automatically. Switching to rootless Podman silently removes this layer without warning.
Proposed fix
Replace the unconditional IsRootless() guard with a runtime capability probe:
- Attempt
aa_change_onexec() with a known-loaded profile in a test exec
- If it succeeds, AppArmor is usable in this rootless context
- If it returns
EPERM/EACCES, fall back gracefully and log a clear warning
This respects kernel-level restrictions (apparmor_restrict_unprivileged_unconfined) without hardcoding a blanket "rootless = no AppArmor" rule. The existing verifierImpl interface already provides the right abstraction for mocking this in tests.
Environment
- containers/common:
0.57.4
- Kernel:
6.17.0 (Ubuntu)
apparmor_restrict_unprivileged_unconfined: 0
apparmor_restrict_unprivileged_userns: 1
Summary
pkg/apparmor/internal/supported/supported.goreturns"AppArmor is not supported on rootless containers"unconditionally whenunshare.IsRootless()is true. The comment inapparmor_linux.gojustifies this as "requires root", butaa_change_onexec()operates by writing to/proc/self/attr/exec— this does not require elevated privileges and works from unprivileged processes on kernels that support it.The result is that
podman inforeportsapparmorEnabled: falseon rootless systems with AppArmor fully operational, andapparmor_profileincontainers.confis silently ignored.Affected files
pkg/apparmor/internal/supported/supported.go—IsSupported()hard-gates onIsRootless()pkg/apparmor/apparmor_linux.go— lines 86–87, 152–153, 265–269Comparison with Docker
Docker applies
docker-defaultto all containers automatically. Switching to rootless Podman silently removes this layer without warning.Proposed fix
Replace the unconditional
IsRootless()guard with a runtime capability probe:aa_change_onexec()with a known-loaded profile in a test execEPERM/EACCES, fall back gracefully and log a clear warningThis respects kernel-level restrictions (
apparmor_restrict_unprivileged_unconfined) without hardcoding a blanket "rootless = no AppArmor" rule. The existingverifierImplinterface already provides the right abstraction for mocking this in tests.Environment
0.57.46.17.0(Ubuntu)apparmor_restrict_unprivileged_unconfined:0apparmor_restrict_unprivileged_userns:1