Skip to content

fix(execd): init-mode signal forwarding + execd-init e2e coverage (OSEP-0018) - #1546

Merged
hittyt merged 5 commits into
opensandbox-group:mainfrom
Pangjiping:feat/execd-init-e2e-signal-fix
Aug 17, 2026
Merged

fix(execd): init-mode signal forwarding + execd-init e2e coverage (OSEP-0018)#1546
hittyt merged 5 commits into
opensandbox-group:mainfrom
Pangjiping:feat/execd-init-e2e-signal-fix

Conversation

@Pangjiping

Copy link
Copy Markdown
Collaborator

Summary

Phase-1 (OSEP-0018) e2e coverage plus one real fix the new tests exposed.

1. Bug fix: in-namespace application signals leaked into /command

In init mode, runCommand/runBackgroundCommand still subscribed
forwardSignals and forwarded HUP/USR1/USR2/WINCH to the running /command
process group
, stacking with forwardInitSignals. An in-namespace
kill -HUP 1 therefore leaked the signal into whatever /command was running
and killed it (signal: hangup).

Fix: skip the subscription when init mode is active (initModeActive());
signals are owned by forwardInitSignals (forwarded to the entrypoint group,
SIGTERM triggers the shutdown sequence). Classic mode unchanged.

2. execd-init e2e additions (tests/python/tests/test_execd_init_e2e.py)

  • test_application_signal_forwarded_to_entrypoint — HUP reaches the
    entrypoint (reproduces the bug above; fails on old code)
  • test_entrypoint_exit_code_propagatesexit 42 observed on the docker
    bridge status (exited with code 42); k8s asserts state only
  • test_in_namespace_sigterm_kill1_stops_sandbox — interim-behavior pin
    (OSEP-0018 §3, R-a): in-namespace kill 1 still stops the sandbox; comment
    marks it to flip once the trusted out-of-band stop channel lands
  • test_fork_heavy_keeps_process_table_bounded — 20 fork-churn rounds, no
    zombies, bounded process count
  • test_hardening_reports_pid1 extended to assert signal_shield: true

3. chore: drop committed vmlinux BTF dump headers (-353k lines)

vmlinux_6_14_0*.h are kernel BTF dumps needed only at bpf2go generation
time; the generated bytecode is already embedded in the audit_bpf*.go
bindings, so builds/tests/execd-ebpf never touch them. Removed, gitignored,
regeneration documented in audit.bpf.c.

Verification

  • Local docker-bridge run of the full suite: 10 passed
  • go build ./..., go vet, CGO_ENABLED=1 go test -tags ebpf ./pkg/ebpf/,
    go test ./pkg/runtime/ all green
  • TestMergedView failures in pkg/isolation are pre-existing (verified by
    stashing this branch's changes) and unrelated
  • ruff + pyright clean on the test file

Out of scope

  • External SIGTERM graceful-shutdown e2e (server kill is SIGKILL+remove; unit
    tests cover terminateInit)
  • Hardening/Landlock/eBPF e2e (Phases 2–4, separate enablement)

In init mode, runCommand/runBackgroundCommand still subscribed
forwardSignals and forwarded HUP/USR1/USR2/WINCH to the running /command
process group, stacking with forwardInitSignals: an in-namespace
'kill -HUP 1' leaked the signal into the active /command and killed it.
The signal subscription is now skipped when init mode is active
(initModeActive); classic mode keeps today's behavior unchanged.

Also extends the execd-init e2e suite (test_execd_init_e2e.py) with
the Phase-1 contract gaps: application-signal forwarding to the
entrypoint (which reproduces the bug above), entrypoint exit-code
propagation to the runtime, in-namespace 'kill 1' interim behavior pin
(OSEP-0018 R-a), fork-heavy bounded process table, and the
signal_shield field on the capabilities endpoint.
The vmlinux_6_14_0*.h files are kernel BTF dumps (~353k lines) used only
at bpf2go generation time; the generated bytecode is already embedded in
the audit_bpf*.go bindings, so builds, tests, and the execd-ebpf variant
never need them. Removed from the repo and ignored via .gitignore;
audit.bpf.c documents how to regenerate (bpftool btf dump).

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 53ca5a644a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread components/execd/.gitignore Outdated
Comment thread tests/python/tests/test_execd_init_e2e.py
The kubernetes-mini-e2e changes matcher did not cover the execd init path,
so the nightly workflow's Execd-Init E2E job never ran on PRs touching
components/execd/ or tests/python/tests/test_execd_init_e2e.py.

@hittyt hittyt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

@hittyt
hittyt merged commit 96175e2 into opensandbox-group:main Aug 17, 2026
80 of 82 checks passed
lucadeg pushed a commit to lucadeg/OpenSandbox that referenced this pull request Aug 18, 2026
…EP-0018) (opensandbox-group#1546)

* fix(execd): gate command signal forwarding off in init mode (OSEP-0018)

In init mode, runCommand/runBackgroundCommand still subscribed
forwardSignals and forwarded HUP/USR1/USR2/WINCH to the running /command
process group, stacking with forwardInitSignals: an in-namespace
'kill -HUP 1' leaked the signal into the active /command and killed it.
The signal subscription is now skipped when init mode is active
(initModeActive); classic mode keeps today's behavior unchanged.

Also extends the execd-init e2e suite (test_execd_init_e2e.py) with
the Phase-1 contract gaps: application-signal forwarding to the
entrypoint (which reproduces the bug above), entrypoint exit-code
propagation to the runtime, in-namespace 'kill 1' interim behavior pin
(OSEP-0018 R-a), fork-heavy bounded process table, and the
signal_shield field on the capabilities endpoint.

* chore(execd): drop committed vmlinux BTF dump headers (OSEP-0018)

The vmlinux_6_14_0*.h files are kernel BTF dumps (~353k lines) used only
at bpf2go generation time; the generated bytecode is already embedded in
the audit_bpf*.go bindings, so builds, tests, and the execd-ebpf variant
never need them. Removed from the repo and ignored via .gitignore;
audit.bpf.c documents how to regenerate (bpftool btf dump).

* chore(execd): move vmlinux BTF dump ignore rule to root .gitignore

* fix(execd): extract command signal subscription helper to satisfy gocognit

* ci: run k8s Execd-Init E2E when execd or its e2e tests change

The kubernetes-mini-e2e changes matcher did not cover the execd init path,
so the nightly workflow's Execd-Init E2E job never ran on PRs touching
components/execd/ or tests/python/tests/test_execd_init_e2e.py.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component/execd size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants