# DF-5773 — `handle_term()` in a reforked vkernel child runs `kill(0, SIGTERM)`: process-group-wide TERM splash + self-re-arming signal storm

**File:** `sys/platform/vkernel64/platform/init.c`
**Lines:** 204-230 (monitor loop, sigaction placement), 500-506 (`handle_term`)
**Severity:** Medium (DoS + collateral kill of the launching process group)
**Status:** mechanism reproduced on-guest (faithful extraction); in-vkernel trigger line-certain but gated on a sibling stock bug (see VERDICT.md). Fix validated.

## What to build / run (guest, root)

Two layers of evidence:

1. **Mechanism (decisive)** — `storm_demo.c` is a byte-faithful extraction of
   init.c's monitor/child structure (fork loop, sigaction placement after
   fork, `handle_term` doing `kill(childpid, sig)`, exit-32 reboot cycle):

   ```
   cc -O -o storm_demo storm_demo.c
   sh run_storm_demo.sh 3          # bystander in pgrp + TERM in gen-2 window
   ```

   Vulnerable baseline (`baseline_storm.obs`): 85× `RUNNER_GOT_SIGTERM`,
   `BYSTANDER_DEAD_BY_SPLASH`, `DEMO_STILL_ALIVE_AFTER_SECOND_TERM_storm_wedged`.

   Fixed build (`storm_demo_fixed.c` = guard added): 0 runner hits,
   `BYSTANDER_ALIVE` — the splash and the storm are gone.

2. **In-vkernel (documented, gated)** — `run5773.sh` drives the real vkernel:
   boot `/vkroot.img` to the single-user shell, run `/bin/reboot2` (direct
   `reboot(2)` RB_AUTOBOOT from process context) to complete
   `kern_reboot -> cpu_reset() -> exit(EX_VKERNEL_REBOOT)`, which makes the
   monitor refork; child #2 then INHERITS `handle_term` with
   `childpid == 0`, and a TERM burst in its early-boot window would execute
   `kill(0, SIGTERM)`. On this stock snapshot the reboot path panics first
   (`naccess` NULL deref, fault VA 0x58 — sibling bug, see VERDICT.md), so
   child #2 is never reached; `reboot2.c` and `run5773.sh` are kept as the
   ready-to-run rig for when that sibling is fixed
   (`unblock_DF-5561.diff` already applied here moves the panic from the
   pre-sync no-op to the post-sync `naccess` fault).

## Expected output

* storm_demo (vulnerable): runner trap fires in a tight loop (85+ hits in
  ~3 s), the bystander `sleep` is killed by the group splash, the demo pair
  survives a second TERM at ~100% CPU (only `kill -9` works).
* storm_demo_fixed: zero runner hits, bystander alive, demo cycles normally.

## Fix

`fix.diff` hunk 1: only the monitor (`childpid > 0`) may forward.
