Osegi
Software·2 min read

Ubuntu 26.04 Kernel Update Breaks Containers via AppArmor Change

A security patch in the Ubuntu 26.04 kernel changes how AppArmor stacks profiles, causing signal denials in containers and hanging gosu, PostgreSQL and Percona pods.

Server rack with terminal output showing AppArmor denied signal errors from a container running on an Ubuntu host.
Image: Хабр

A recent kernel update for Ubuntu 26.04 can silently break containerized workloads. An engineer who hit the problem while resizing a Kubernetes node group describes how a security fix to AppArmor made containers reject signals, even between processes of the same user.

What goes wrong

The regression affects Ubuntu 26.04 or kernels with the backport from 7.0.0-41 and later, including cloud builds such as linux-aws and linux-azure. It requires the setting kernel.apparmor_restrict_unprivileged_unconfined=1, which is the default in 26.04, and containerd or Docker with the standard AppArmor profile. That covers almost any Kubernetes, k3s, RKE2 or Docker host.

Symptoms include Permission denied on kill inside a container despite matching uid and no seccomp; gosu and other Go binaries calling setuid spinning at 100% CPU with no logs; and PostgreSQL failing with «could not signal for checkpoint: Permission denied». The kernel log shows apparmor="DENIED" operation="signal" with the peer cri-containerd.apparmor.d//&unconfined.

The author first noticed it when several Percona Operator for MySQL (PXC) pods would not start after the nodes were rebooted. A quick workaround was disabling AppArmor in the cluster's custom resource, or sending the signal from the node as root. The application pods then hung because gosu never completed, which required changes to a Helm chart.

The mechanism

Since February 2025 Ubuntu has restricted unconfined processes without CAP_MAC_OVERRIDE from simply switching profiles; the new profile is stacked on top of unconfined instead. Commit 08c2f7c8d4b1, tied to CVE-2026-90231, closed a bypass and now enforces stacking on exec as well. Because runc drops capabilities before exec, every container with the default profile runs under the composite label cri-containerd.apparmor.d//&unconfined (docker-default//&unconfined in Docker).

The containerd profile template only allows signals and ptrace from the exact name cri-containerd.apparmor.d. The composite label does not match, so the kernel denies signals even between threads in one container.

Timeline and status

The last unaffected kernel is 7.0.0-38.38. Version 7.0.0-42.42 reached resolute-updates, with bug reports and containerd#14485 opened the same day, and a profile fix was proposed in containerd PR #14487. When 7.0.0-42.42 landed in resolute-security, unattended-upgrades began installing it, triggering outages after node reboots. 7.0.0-43.43 keeps the symptoms, and 7.0.0-44.44 is in proposed. Reports differ on whether 7.0.0-41 or only -42 is the first bad version.

Apps worth a look

SUMO: the number puzzle

Tap the right tiles, add them up, hit the target. Easy to learn, hard to master. Free, for all ages.

Tags:ubuntuapparmorkubernetescontainerdlinux kerneldocker

More from this day

See all →

More in: Software

See all →