Skip to content

fix(windows): terminate owned Job descendants after parent exit - #50

Merged
senamakel merged 19 commits into
epic/7328-security-busfrom
tinybox-27-owned-child
Oct 24, 2026
Merged

senamakel merged 19 commits into
epic/7328-security-busfrom
tinybox-27-owned-child

Conversation

@senamakel

Copy link
Copy Markdown
Owner

Summary

Fixes the Windows owned-child lifecycle edge where the direct AppContainer parent exits before a descendant. The owned process wrapper must still terminate its Job Object so descendants cannot outlive a caller's explicit cleanup. The regression launches a controlled long-lived descendant, waits for its parent to exit, then verifies OwnedChild::terminate reaps it.

This is a bounded lifecycle fix on top of the existing owned-child API. Captured stdin/stdout/stderr and suspended-create → Job assignment → resume remain intact. Memory and active-process limits remain supported; CPU enforcement remains Unsupported and deferred. This does not close tinybox#27.

Refs tinyhumansai#27
Part of tinyhumansai/openhuman#7328

Validation

  • Regression-first Windows test compiles for x86_64-pc-windows-gnu; hosted Windows AppContainer lane will provide runtime evidence.
  • cargo fmt --all

senamakel and others added 19 commits October 23, 2026 23:11
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Co-authored-by: Medulla <medulla@tinyhumans.ai>
The descendant parent probe now spawns cmd.exe running a long ping instead of
re-launching the test executable, since Windows denies launching the test
binary from inside an AppContainer. The PID is written directly after spawn,
so the child probe test and its readiness polling loop are no longer needed.

Auto-committed-on: cuttlefish
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Wrap the process open, exit code, terminate, and wait calls in the
appcontainer descendant termination test with error messages that name the
failing step and PID, so a failure points at the specific operation instead
of a bare OS error.

Auto-committed-on: cuttlefish
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Reformatted the descendant termination test to satisfy rustfmt line
wrapping, with no change to the assertions or their behaviour.

Auto-committed-on: cuttlefish
Co-authored-by: Medulla <medulla@tinyhumans.ai>
The descendant process now runs timeout.exe instead of ping so it stays
alive for a fixed duration without depending on network behaviour. When
the descendant exits before the parent, the assertion now includes its
captured stdout and stderr to make the failure easier to diagnose.

Auto-committed-on: cuttlefish
Co-authored-by: Medulla <medulla@tinyhumans.ai>
The Windows descendant probe now launches timeout.exe directly instead of
wrapping it in cmd.exe, since the container denies launching the test
executable and the extra shell layer was unnecessary. A short readiness
loop was added so the probe fails with captured output if the descendant
exits before its PID is recorded.

Auto-committed-on: cuttlefish
Co-authored-by: Medulla <medulla@tinyhumans.ai>
The descendant fixture now launches PowerShell with Start-Sleep instead of
timeout.exe, since timeout reads the inherited stdin pipe and could exit
before the parent records its PID. Error messages were updated to name the
new utility.

Auto-committed-on: cuttlefish
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Set TEMP and TMP to the jail root when spawning the descendant probe
process so the child does not fall back to the system temp directory
outside the AppContainer.

Auto-committed-on: cuttlefish
Co-authored-by: Medulla <medulla@tinyhumans.ai>
The AppContainer descendant probe now points LOCALAPPDATA, APPDATA and
USERPROFILE at the test root alongside TEMP and TMP, so the spawned
PowerShell process cannot read or write the real user profile while the
test runs.

Auto-committed-on: cuttlefish
Co-authored-by: Medulla <medulla@tinyhumans.ai>
The AppContainer descendant probe pointed LOCALAPPDATA, TEMP and TMP at the
test root, which the child process could not write to. The probe now creates a
LocalAppData/Temp directory under the root and points those variables at it so
the spawned process can start successfully.

Auto-committed-on: cuttlefish
Co-authored-by: Medulla <medulla@tinyhumans.ai>
The descendant probe now launches cscript with a wait script written under the granted working directory instead of PowerShell with redirected temp paths, since the script host does not read stdin or depend on host temp locations. Error messages were updated to name cscript.

Auto-committed-on: cuttlefish
Co-authored-by: Medulla <medulla@tinyhumans.ai>
The AppContainer descendant probe now spawns a bounded cmd.exe built-in
loop instead of writing and running a VBScript through cscript, avoiding
the script file and its host temp path handling while still keeping the
descendant alive for inspection.

Auto-committed-on: cuttlefish
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Reduce the busy-loop iteration count and the deadline in the AppContainer
descendant probe so the test no longer spends seconds spinning before it
checks the child. The probe only needs the descendant to stay alive briefly,
so the shorter wait keeps the same coverage without the long delay.

Auto-committed-on: cuttlefish
Co-authored-by: Medulla <medulla@tinyhumans.ai>
…eadline

The busy loop in the AppContainer descendant probe now iterates a million
times instead of a hundred thousand, and the parent's wait deadline drops
from 100ms to 25ms. This makes the child reliably outlive the parent's
probe window so the test exercises the intended race.

Auto-committed-on: cuttlefish
Co-authored-by: Medulla <medulla@tinyhumans.ai>
The parent probe's stdout and stderr are now read after the descendant
cleanup assertions instead of before them, so the pipes stay open until
the child has fully exited and the reads cannot block the termination
checks. The failure message no longer embeds the captured output, and
read errors are wrapped with context.

Auto-committed-on: cuttlefish
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Terminating an AppContainer process now tears down the Job object first
instead of returning early when the direct process has already exited,
since descendants may still be running under that Job. The fallback still
treats a Job termination error as idempotent only when the direct process
is known to be gone.

Auto-committed-on: cuttlefish
Co-authored-by: Medulla <medulla@tinyhumans.ai>
@senamakel
senamakel merged commit 9ee34e2 into epic/7328-security-bus Oct 24, 2026
20 checks passed
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.

1 participant