Repository navigation
supervisor v0.0.73 crashes in rootless Podman: drop_capability_bounding_set() EPERM with non-empty bounding set #2069
Description
Agent Diagnostic
- Investigated the outage triggered by supervisor
:latestre-tagging to v0.0.73 on 2026-06-30 - Traced the crash to
drop_capability_bounding_set()incrates/openshell-supervisor-process/src/process.rs, introduced by PR fix(supervisor): drop sandbox child capability bounding set #2001 - Ran a diagnostic GitHub Actions workflow on
ubuntu-24.04runners testing supervisor versions 0.0.63, 0.0.72, 0.0.73, and:latest - Confirmed
apparmor_restrict_unprivileged_userns=1is active on GHA runners — AppArmor deniesCAP_SETPCAPoperations inside rootless Podman user namespaces - Verified via
dmesgaudit log:apparmor="DENIED" operation="capable" profile="unprivileged_userns" capability=21 capname="sys_admin" - Performed A/B test: supervisor 0.0.63 and 0.0.72 create sandboxes successfully; 0.0.73 crashes during sandbox creation
- Confirmed the same crash on macOS + Podman machine (Fedora 41 CoreOS aarch64)
- Reviewed PR fix(supervisor): drop sandbox child capability bounding set #2001 comments — a reviewer explicitly warned: "this still fails closed incorrectly for the Podman path" and "the regression test skips when
CAP_SETPCAPis unavailable, so it would not catch the Podman-relevant failure mode" - Did not use the repo's
.agents/skills/skills (investigation was done from a downstream consumer's perspective using GHA diagnostics,ghCLI, and code review of the relevant crates) - Agent could not resolve this — the fix requires changes to
validate_capability_bounding_set_clear()in the supervisor crate
Description
OpenShell v0.0.73 supervisor crashes during sandbox creation in rootless Podman on hosts where AppArmor restricts unprivileged user namespaces (apparmor_restrict_unprivileged_userns=1, the default on Ubuntu 24.04).
PR #2001 added drop_capability_bounding_set() which calls capctl::caps::bounding::clear(), requiring effective CAP_SETPCAP. PR #2001 also added SETPCAP to the Podman driver's cap_add to provide this capability. However, on Ubuntu 24.04 with apparmor_restrict_unprivileged_userns=1, AppArmor transitions processes entering user namespaces (which rootless Podman creates) into the unprivileged_userns profile. This profile denies capability operations at the kernel level — so bounding::clear() returns EPERM even though Podman granted SETPCAP.
The fallback in validate_capability_bounding_set_clear() handles:
Ok(())+ empty set → successEPERM+ empty set → tolerated (set already clear)EPERM+ non-empty set → fatal error ← this is the unhandled case
In rootless Podman, the bounding set retains SYS_ADMIN, NET_ADMIN, SETPCAP, etc. from --cap-add, so the third branch fires and the supervisor exits.
This is distinct from #2068 (:latest pinning). #2068 addresses which version gets pulled; this issue addresses a crash bug in v0.0.73 that must be fixed for the version to work in rootless Podman environments.
Reproduction Steps
On any Ubuntu 24.04 host or GitHub Actions ubuntu-24.04 runner:
-
Run a sandbox with supervisor v0.0.72 (pre-PR-2001) — succeeds:
# Configure gateway.toml with: # supervisor_image = "ghcr.io/nvidia/openshell/supervisor:0.0.72" openshell sandbox create --from base # → sandbox Ready
-
Run a sandbox with supervisor v0.0.73 (post-PR-2001) — crashes:
# Configure gateway.toml with: # supervisor_image = "ghcr.io/nvidia/openshell/supervisor:0.0.73" openshell sandbox create --from base # → "sandbox is not ready" — supervisor exits with EPERM during drop_privileges()
The crash occurs during sandbox creation when drop_privileges() calls drop_capability_bounding_set() for a child process — not at startup or --version.
Environment
- GitHub Actions
ubuntu-24.04runner (image20260622.220.1, kernel6.17.0-1018-azure) apparmor_restrict_unprivileged_userns = 1(Ubuntu 24.04 default)- Podman 4.9.3 (rootless)
- Also reproduced on macOS + Podman machine (Fedora 41 CoreOS aarch64)
- Supervisor image:
ghcr.io/nvidia/openshell/supervisor:0.0.73(=:latestas of 2026-06-30T15:31Z)
Logs
# AppArmor audit from dmesg on GHA runner:
audit: type=1400 apparmor="DENIED" operation="capable" class="cap"
profile="unprivileged_userns" pid=2536 comm="unshare"
capability=21 capname="sys_admin"
# Supervisor error (from issue #2067 report, same root cause):
WARN openshell_supervisor_network::proxy: host.openshell.internal maps to a non-link-local IP; trusted-gateway SSRF exemption disabled
WARN openshell_supervisor_process::netns: Failed to delete network namespace
Error: × Invalid argument (os error 22)
Suggested Fix
validate_capability_bounding_set_clear() needs a fourth branch for EPERM + non-empty bounding set:
- Log a warning and continue — the child is already constrained by seccomp + Landlock + the container's own restrictions
- Or: probe
CAP_SETPCAPeffectiveness before callingbounding::clear(), and skip when ineffective
The PR #2001 reviewer also noted: "The current regression test skips when CAP_SETPCAP is unavailable, so it would not catch the Podman-relevant failure mode." Adding a rootless Podman CI test target would prevent future regressions.
Workaround
Pin the supervisor image to a pre-v0.0.73 version in gateway.toml:
[podman]
supervisor_image = "ghcr.io/nvidia/openshell/supervisor:0.0.72"Related
- Podman and Kubernetes drivers default supervisor image to :latest instead of pinning to gateway version #2068 — supervisor
:latestpinning (complementary fix, addresses the mutable tag problem) - PR fix(supervisor): drop sandbox child capability bounding set #2001 — the PR that introduced the regression
- Allow sandbox supervisor to skip inner network namespace creation on hardened / immutable hosts (rootless Podman, dm-verity, overlayroot) #1194 —
ip netns addfails on hardened/immutable hosts (same class of rootless restrictions) - feat: Kubernetes support on AppArmor-enabled host nodes #1643 — AppArmor blocking sandbox namespace creation on Kubernetes (fixed with AppArmor profile loader)
Agent-First Checklist
- I pointed my agent at the repo and had it investigate this issue
- I loaded relevant skills (e.g.,
debug-openshell-cluster,debug-inference,openshell-cli) - My agent could not resolve this — the diagnostic above explains why
Activity
johntmyers commentedon Jun 30, 2026
thanks @waynesun09 - do you want to send a PR? If so we can get it reviewed and merged asap.
waynesun09 commentedon Jun 30, 2026
Sure, I'm working on it now.
test(ci): add rootless capability regression test on ubuntu-24.04
fix(supervisor): tolerate non-empty bounding set when CAP_SETPCAP is …
test(ci): add rootless capability regression test on ubuntu-24.04
test(ci): add rootless capability regression test on ubuntu-24.04
waynesun09 commentedon Jun 30, 2026
@johntmyers I have a fix ready for this (PR #2072) but it was auto-closed by the vouch gate since I'm a first-time contributor. Could you vouch me so I can reopen the PR?
waynesun09 commentedon Jun 30, 2026
@johntmyers I've been vouched and PR is opened at:
#2075
fix(supervisor): tolerate non-empty bounding set when CAP_SETPCAP is …
test(ci): add rootless capability regression test on ubuntu-24.04
test(ci): add rootless capability regression test on ubuntu-24.04
test(ci): add rootless capability regression test on ubuntu-24.04
fix(supervisor): tolerate non-empty bounding set when CAP_SETPCAP is …
fix(supervisor): tolerate non-empty bounding set when CAP_SETPCAP is …
fix(supervisor): tolerate non-empty bounding set when CAP_SETPCAP is …
fix(supervisor): tolerate non-empty bounding set when CAP_SETPCAP is …
fix(supervisor): tolerate non-empty bounding set when CAP_SETPCAP is …
test(ci): add rootless capability regression test on ubuntu-24.04
fix(supervisor): tolerate non-empty bounding set when CAP_SETPCAP is …
fix(supervisor): fail fast with diagnostic error when CAP_SETPCAP is …
github-actions commentedon Jul 15, 2026
This issue has had no activity for 14 days and is now marked stale. It may be closed in 7 days if there is no further activity. Comment or remove the state:stale label to keep it open.