DF-2817 / verdict.json
{ "finding_id": "DF-2817", "status": "reproduced", "reproduced": 1, "impact": "panic", "confidence": "certain", "verdict": "Reproduced on the stock INVARIANTS guest: the harness took exactly ONE token and called lwkt_token_swap(); lwkt_token.c computes ref2 = td_toks_stop-2 = base-1 and the kernel panicked with assertion ref2 >= &td->td_toks_base failed in lwkt_token_swap at lwkt_token.c:955 (full serial trace captured). This proves the API computes out-of-bounds tokrefs when called with fewer than two tokens; on INVARIANTS the lower-bound KKASSERT catches it, on production builds KKASSERT is a no-op (sys/sys/systm.h) and the code proceeds to write tok1/tok2 and counts through base-1/base-2, clobbering memory before td_toks_array (td_kfpuctx / td_toks_have per the layout) and repointing live tokens t_ref outside the array - silent mutual-exclusion break / memory corruption. All in-tree callers pair swap with two live gettokens (verified in pass 2), so this is defense-in-depth. On the fix kernel the same call returns cleanly (production-safe early bail, no panic).", "exploit_chain": "caller bug: token_swap with <2 held tokens -> production: refs at toks_array[-1]/[-2] -> OOB write of tr_tok/tr_count + garbage t_ref repoint -> mutual exclusion broken (INVARIANTS: clean panic instead)", "evidence": "panic.txt: full panic + backtrace from the serial console; fix kernel: T15 SURVIVED log line", "kernel_refs": [ "sys/kern/lwkt_token.c:952", "sys/kern/lwkt_token.c:955", "sys/kern/lwkt_token.c:961" ], "poc_changes": "none", "attempts": 1, "guest_uname": "DragonFly dfbsd 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": 60, "guest_dirty": 0, "build_cmd": "cd /root/h41 && make", "run_cmd": "kldload ./h41.ko; sysctl -w debug.h41.cmd=15 (PANICS on stock kernel)", "code_hash": "85d6e241caa2a7fb1fb44b80c7736a4e83c36d29314b0c96ce91769bc9bdf839", "notes": "Guest panicked during baseline and was reset; production corruption claim is compile-provable (KKASSERT no-op)", "recommended_fix": "Unconditional early return when fewer than two tokens are held", "fix_status": "fixed", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #1: Mon Oct 26 01:57:23 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64 (h41 fix kernel, all 41 hardening fixes applied)", "fix_verdict": "A/B: baseline kernel panicked (assertion at lwkt_token.c:955); fix kernel survives the identical call via the unconditional early-return guard (td->td_toks_stop < &td->td_toks_array[2]) - note td_toks_base is a macro over td_toks_array[0], the first fix attempt used td_toks_base[2] which does not compile." } |