DF-2950 / verdict.json
{ "finding_id": "DF-2950", "status": "reproduced", "reproduced": 1, "impact": "dos", "confidence": "certain", "verdict": "On the stock INVARIANTS guest, a plain jail(2) tenant with uid 0 inside the jail successfully wrote host-global MIBs: kern.securelevel -1->1 (rc=0), after which HOST root got EPERM lowering it (irreversible host-admin DoS), plus kern.hostid 0->4242, kern.domainname ->pwned-by-jail, kern.maxposixlocksperuid 32528->1, kern.tls_extra->777. Root cause: sysctl_root's only write gate is caps_priv_check(SYSCAP_NOSYSCTL_WR) (kern_sysctl.c:1447), which the group-2 meta rewrite (kern_caps.c:337-341) turns into SYSCAP_SENSITIVEROOT, blanket-allowed in jails (kern_jail.c:856-857); none of the kern_mib.c RW oids have a jail check and CTLFLAG_PRISON (sysctl.h:97) is consulted nowhere. Control cases: jailed nobody EPERM, host unpriv EPERM - the gate is specifically jail-blind for jailed uid-0. Jailed-root hostname write without the SET_HOSTNAME cap additionally re-triggered known DF-0181's XLOCK leak live (guest wedged; corroboration file). fix.diff (kern_sysctl.c: enforce CTLFLAG_PRISON for jailed writes) built via make nativekernel and validated: jailed uid-0 now EPERM on all tested oids, host root unaffected.", "exploit_chain": "host-root creates jail for untrusted tenant -> attacker holds uid 0 inside jail -> sysctl -w kern.securelevel=1 -> host-global irreversible ratchet (host root cannot lower; CTLFLAG_SECURE sysctls permanently locked at level>=1) -> permanent host administration denial-of-service; same gate permits host/cross-jail corruption of kern.hostid, kern.domainname, kern.bootfile/kernelname, kern.maxprocperuid, kern.maxposixlocksperuid, kern.tls_extra", "evidence": [ "run.2.log:14 kern.securelevel: -1 -> 1 (jailed uid-0, rc=0)", "run.2.log:19-20 host root: sysctl: kern.securelevel=0: Operation not permitted", "run.2.log:27-32 kern.hostid 0->4242, kern.domainname ->pwned-by-jail from jail", "run.2.log:40-47 jailed nobody EPERM + host unpriv (su maxx) EPERM control cases", "run.2.log:52-55 kern.maxposixlocksperuid 32528->1, kern.tls_extra 6144->777 from jail", "run.log:53-55 + df0181_live_corroboration.txt: incidental live re-trigger of DF-0181 XLOCK wedge (guest down)", "fixtest.log: jailed uid-0 EPERM on all oids under patched kernel #1; host root write still OK" ], "kernel_refs": [ "sys/kern/kern_mib.c:248-264", "sys/kern/kern_mib.c:266-271", "sys/kern/kern_mib.c:178-181", "sys/kern/kern_mib.c:142-153", "sys/kern/kern_sysctl.c:1445-1450", "sys/kern/kern_caps.c:328-348", "sys/kern/kern_jail.c:854-891", "sys/sys/sysctl.h:97" ], "poc_changes": "Seed sketch corrected: step [5] of run 1 mislabeled host-root as unprivileged (runs inside the root ssh session); run 2 uses su -m maxx for a genuine unprivileged host-user control. Jail-hostname-write step removed from run 2 because on this guest the jail lacks PRISON_CAP_SYS_SET_HOSTNAME and the write exercises known DF-0181 (XLOCK leak -> guest wedge), truncating run 1; that wedge is preserved as side-evidence.", "attempts": 2, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "runtime_sec": 300, "guest_dirty": 0, "build_cmd": "none (shell PoC; jail(8)+sysctl(8) from base system)", "run_cmd": "dfbsd-qemu/vm.sh run_root \"$(cat poc_jail_sysctl2.sh)\" # see run.2.log", "code_hash": "76ca18745579bee1bcb29ce681ceb7123529742484953546ebd95d397cdc6343", "notes": "Same root-cause family as DF-2800 (group-2 blanket allow) but distinct sink/file/impact - DF-2800 covered settimeofday family only. Related: DF-0181 still unfixed (confirmed live). Fix validation: make -j4 nativekernel KERNCONF=X86_64_GENERIC rc=0; guest reset to stock after testing.", "recommended_fix": "In sysctl_root (kern_sysctl.c), deny writes from jailed creds unless the oid has CTLFLAG_PRISON; see fix.diff (also makes the documented-but-dead CTLFLAG_PRISON flag meaningful).", "fix_status": "fixed", "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #1: Fri Sep 4 00:17:28 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "Patched kernel (#1, nativekernel build with fix.diff): jailed uid-0 gets EPERM on kern.securelevel/kern.hostid/kern.domainname/kern.maxposixlocksperuid and values stay unchanged; jail-scoped kern.hostname read still works; host root write (kern.hostid=99) still works. No over-restriction observed. Baseline had reproduced=1 on stock #0.", "fix_evidence": [ "fixtest.log:F1 jailed uid-0 EPERM, kern.securelevel stays -1", "fixtest.log:F2 hostid/domainname/maxposixlocks EPERM, values unchanged", "fixtest.log:F3 jail hostname read OK (df2950fc)", "fixtest.log:F4 host root kern.hostid 0->99 OK" ] } |