# DF-2738 verdict

**status: reproduced** (2 clean runs, run.log / run.2.log)
**impact: dos** (host-global kernel-state rewrite from inside a jail;
arbitrary host availability/integrity impact, e.g. kern.maxfiles;
closest enum is dos — the ceiling includes host-wide integrity changes
such as kern.sugid_coredump=1 and kern.securelevel raising)
**confidence: certain**

## Root cause chain (path:line)

1. `sysctl_root` write gate — sys/kern/kern_sysctl.c:1438-1450:
   requires CTLFLAG_WR, honors CTLFLAG_SECURE vs securelevel, then
   `caps_priv_check(td->td_ucred, SYSCAP_NOSYSCTL_WR)`. No prison check.
2. `caps_priv_check` — sys/kern/kern_caps.c:311-341 — passes uid-0
   through, delegates jail policy to `prison_priv_check`.
3. `prison_priv_check` — sys/kern/kern_jail.c:839-905 — for jailed
   creds, `SYSCAP_NOSYSCTL_WR` falls in the "group 2 allowed" list
   (kern_jail.c:883-885) → returns 0 (permitted).
4. `CTLFLAG_PRISON` (sys/sys/sysctl.h:97, comment "Prisoned roots can
   fiddle") — tree-wide grep finds zero enforcement; only 3 nodes set it
   (kern_mib.c:242, if_fxp.c:507,511) and one handler (kern_hostname,
   kern_mib.c:214-235) implements jail semantics itself.

⇒ jailed uid-0 passes every write gate for plain RW variables.

## Reproduction (INVARIANTS guest, DragonFly 6.5-DEVELOPMENT #0 X86_64_GENERIC)

Static writer `jailwrite.c` (no jail filesystem dependencies) executed
via legacy `jail(8)` as uid 0 inside `jtest-DF2738`:

    write kern.sugid_coredump=1   -> r=0 WROTE-HOST-GLOBAL
    write kern.maxfiles=130112    -> r=0 WROTE-HOST-GLOBAL
    write debug.sysctl=0          -> r=0 WROTE-HOST-GLOBAL
    write kern.securelevel=-1     -> r=0 WROTE-HOST-GLOBAL
    HOST AFTER: kern.sugid_coredump = 1   (was 0; mutated from inside the jail)

Two consecutive runs identical (4/4 writes). Host state restored each
time. Unprivileged non-root writes remain EPERM (control test in the
DF-2737 prober: `write debug.sysctl -> EPERM` for uid 1001).

Setup note: the *setup* (creating the jail) needs real root — that is
the deployment model under test (hosting provider grants customers root
inside jails); the attacker position is "uid 0 confined in a jail",
which the kernel promises to contain.

## Exploit ceiling

Arbitrary host-global kernel variable writes from a jailed root:
host-wide DoS (kern.maxfiles/maxproc knobs), shared network-stack
reconfiguration (net.*), kern.sugid_coredump=1 (host setuid core dumps
→ host credential disclosure assist), kern.securelevel manipulation
while host securelevel <= 0. Not a direct host uid=0 primitive; classed
as a jail-confinement / integrity+availability break.

## Fix validation

`fix.diff`: dispatcher jail gate + CTLFLAG_PRISON for kern.proc.args.
- `git apply --check`: clean.
- Applied inside the guest's /usr/src; both touched objects rebuilt with
  the stock kernel CFLAGS incl. -Werror: OK (build_fix.log); guest
  source then reverted to pristine (md5 verified equal to the audit
  tree).
- Full kernel build + boot + in-jail re-test NOT performed (Medium
  severity, non-corruption; compile-verified 5-line gate whose shape
  mirrors the already-runtime-proven ANYBODY/caps gate) →
  fix_status: inconclusive (compiled, not boot-validated).
