Skip to content

fix(runc): apply AppArmor profile after finalizeNamespace in standard_init - #5557

Merged
ktsakalozos-canonical merged 3 commits into
masterfrom
fix/runc-init-order-master
Jun 30, 2026
Merged

fix(runc): apply AppArmor profile after finalizeNamespace in standard_init#5557
ktsakalozos-canonical merged 3 commits into
masterfrom
fix/runc-init-order-master

Conversation

@ktsakalozos-canonical

Copy link
Copy Markdown
Contributor

Summary

Master counterpart of the runc init-order fix being landed on strict. Cherry-picks the same three commits onto master (which also builds runc v1.4.2).

  • fix(runc): apply AppArmor profile after finalizeNamespace in standard_init — Reorders the strict-mode runc v1.4.2 patch so the AppArmor profile change (and NoNewPrivileges) happen after finalizeNamespace runs setuid(2), mirroring setns_init_linux. Because the strict patches switch the profile immediately (aa_change_profile) instead of on exec, relabelling before setuid left the Go runtime's sibling threads under the old profile; glibc's NPTL setxid broadcast (SIGRTMIN+1) then crossed two AppArmor profiles and was denied by AppArmor 4.x, breaking pod creation for workloads with allowPrivilegeEscalation: false (e.g. metallb).
  • ci: grant security-events write permission for SARIF upload — Adds a job-scoped permissions block to upload_sarifs_matrix so codeql-action/upload-sarif can upload (fixes "Resource not accessible by integration").
  • ci: normalize permission comment formatting in build-snap workflow — Whitespace-only cleanup of the comments added above.

Notes

  • The runc patch file (strict-patches/v1.4.2/0003-...) is byte-identical to the version landing on strict.
  • A 1.35-strict counterpart is not included here: that branch builds runc v1.3.3 (no v1.4.2 patch dir), so the fix must be hand-ported to strict-patches/v1.3.3/0003-... separately.

…_init

Reorders the strict-mode runc v1.4.2 patch so the AppArmor profile change
(and NoNewPrivileges) happen after finalizeNamespace runs setuid(2),
mirroring setns_init_linux.

Because the strict patches switch the profile immediately
(aa_change_profile) instead of on exec, relabelling before setuid left the
Go runtime's sibling threads under snap.microk8s.daemon-containerd while
the calling thread moved to cri-containerd.apparmor.d. glibc's NPTL setxid
broadcast (SIGRTMIN+1) then crossed two AppArmor profiles and was denied
by AppArmor 4.x, breaking pod creation for workloads with
allowPrivilegeEscalation: false (e.g. metallb).

Doing setuid(2) while all threads share one profile keeps the broadcast
intra-profile and resolves the denials without any snapd changes.
The upload_sarifs_matrix job runs codeql-action/upload-sarif, which
requires security-events: write. With no permissions block declared the
token fell back to the restricted default and uploads failed with
"Resource not accessible by integration". Add a job-scoped permissions
block granting the minimal scopes needed (contents/actions read,
security-events write).

@louiseschmidtgen louiseschmidtgen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Context around the approval:

The problem: With our strict-snap patches switching the AppArmor profile immediately (aa_change_profile) instead of on-exec, calling ApplyProfile before setuid splits the Go runtime's sibling threads across two profiles. The kernel only changes the profile on the current thread (domain.c#L1433 — it doesn't broadcast to siblings. So when glibc's NPTL does the setuid(2) setxid broadcast (SIGRTMIN+1) across all threads, that signal crosses two profiles and AppArmor 4.x denies it → pod creation fails (e.g. metallb with allowPrivilegeEscalation: false).

The fix: Do the setuid broadcast first, while all threads still share one profile, then apply the locked-down profile + NNP to the current thread. The post-switch split is harmless because we have nothing left to broadcast to the siblings.

Why we can't just match upstream: Upstream defers the switch to exec, so the ordering never bites them. In a strict snap we need the profile active earlier than that, so this reordering is the best we can do.

@ktsakalozos-canonical
ktsakalozos-canonical merged commit d099c90 into master Jun 30, 2026
23 checks passed
@ktsakalozos-canonical
ktsakalozos-canonical deleted the fix/runc-init-order-master branch June 30, 2026 08:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants