Skip to content

AppArmor signal DENIED for SIGURG on kernel 6.17 with profile stacking #13625

@lexfrei

Description

@lexfrei

Summary

On kernel 6.17 with AppArmor profile stacking enabled, Go processes running under the cri-containerd.apparmor.d profile trigger AppArmor DENIED audit events when sending SIGURG (used by Go runtime for goroutine preemption since Go 1.14).

The root cause is that the containerd AppArmor template's signal rule does not account for stacked profile peer names.

Environment

  • OS: Ubuntu 25.10 (questing), aarch64
  • Kernel: 6.17.0-1007-raspi
  • AppArmor parser: 5.0.0~alpha1
  • AppArmor stacking: enabled (/sys/kernel/security/apparmor/features/domain/stack = yes)
  • k3s: v1.35.0+k3s3
  • Embedded containerd: v2.1.5-k3s1 (go1.25.5)

Symptoms

Hundreds of AppArmor DENIED audit entries in dmesg from any Go binary that uses exec-based liveness/readiness probes (each probe spawns a new Go process that uses SIGURG internally):

audit: type=1400 apparmor="DENIED" operation="signal" class="signal" profile="cri-containerd.apparmor.d" pid=1814255 comm="bao" requested_mask="send" denied_mask="send" signal=urg peer="cri-containerd.apparmor.d//&unconfined"
audit: type=1400 apparmor="DENIED" operation="signal" class="signal" profile="cri-containerd.apparmor.d" pid=1814255 comm="bao" requested_mask="receive" denied_mask="receive" signal=urg peer="cri-containerd.apparmor.d//&unconfined"

Root Cause

The containerd AppArmor template (from containerd/containerd#4467, March 2021) includes:

signal (send,receive) peer={{.Name}},

Which expands to:

signal (send,receive) peer=cri-containerd.apparmor.d,

On kernel 6.17 with AppArmor stacking enabled, the peer name includes the stacking suffix: cri-containerd.apparmor.d//&unconfined. The rule does not match because cri-containerd.apparmor.dcri-containerd.apparmor.d//&unconfined.

Related

  • containerd/containerd#12726 — AppArmor policy disallows Unix domain sockets on kernel 6.17 (same root cause: AppArmor behavior change on 6.17)
  • containerd/containerd#12864 — Fix adds abi <abi/3.0> to template, but only addresses Unix socket issue; signal peer matching with stacking is not covered
  • containerd/containerd#4467 — Original signal mediation fix (2021), does not account for profile stacking

Expected Fix

The signal rule in the AppArmor template should match stacked peer names. Possible approaches:

  1. Use a glob/wildcard: signal (send,receive) peer=cri-containerd.apparmor.d//**,
  2. Add explicit stacked peer: signal (send,receive) peer=cri-containerd.apparmor.d//&unconfined,
  3. Verify if pinning abi <abi/3.0> (from PR [release-1.34] Add opencontainers/runc pin to v1.3.1 #12864) also resolves signal peer matching — if so, pulling that fix into k3s's embedded containerd would be sufficient

Workaround

Set AppArmor profile to Unconfined on affected pods via annotation:

annotations:
  container.apparmor.security.beta.kubernetes.io/<container-name>: unconfined

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/upstream-issueThis issue appears to be caused by an upstream bug

    Type

    Projects

    Status

    No status

    Status

    Stalled

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions