DF-5672 / verdict.json
{ "finding_id": "DF-5672", "status": "reproduced", "reproduced": true, "impact": "none", "confidence": "certain", "verdict": "pc64 twin of DF-5671, live-verified: the comment at ipl_funcs.c:37-43 claims gd_spending may be manipulated by interrupts or other cpus and that setbits uses a locked or, making simple cases MP safe, but ipl_funcs.c:49 emits atomic_set_int_nonlocked \u2014 an UNLOCKED orl (atomic.h:110-115/:128, self-described as local-interrupt-safe only at atomic.h:72-74). Disassembly of the running 6-CPU guest kernel shows every generated pend function as orl $bit,0x42cc(%rax) (no lock prefix) followed by lock orl $0x2,0x18(%rax) \u2014 only the gd_reqflags store is locked. Both comment assertions are false: exhaustive grep proves gd_spending/gd_sdelayed are only ever RMWd by their owning CPU (DO_SETBITS resolves mdcpu at ipl_funcs.c:48; clears are same-CPU btrl at ipl.s:275/431; cross-CPU work goes via Xipi + gd_npoll/gd_ipimask at lwkt_ipiq.c:308-315, never via a foreign gd_spending; live ipiq_count climbing 6707->7955 with the system stable). The unlocked OR is therefore safe by construction today \u2014 impact none \u2014 but the comment is a trap: anyone adding a cross-CPU accessor trusting the locked or / MP safe claim gets silent lost-update pend drops (missed softints, taskqueue/tty stalls, potential hang). Comment-only defect; documentation fix supplied.", "exploit_chain": "", "evidence": "findings/poc/DF-5672/run.log \u2014 decisive lines: setsofttty @ 0xffffffff80c1bf00: orl $0x1,0x42cc(%rax) (UNLOCKED spending store) immediately followed by lock orl $0x2,0x18(%rax) (locked reqflags store); same shape for setdelayed (xchg 0x42d0 + unlocked or 0x42cc), setsoftcamnet/cambio/vm/tq, schedsofttty (0x42d0), setsoftcrypto (tail-jmp setsoftcamnet per interrupt.h:81); == splz block shows incl 0xd4(%rbx) self-guard; counters show live ipiq traffic. VERDICT.md carries the full writer-inventory grep and the negative results for checklist (b)/(c)/(d).", "kernel_refs": [ "sys/platform/pc64/x86_64/ipl_funcs.c:37-43", "sys/platform/pc64/x86_64/ipl_funcs.c:44-51", "sys/platform/pc64/x86_64/ipl_funcs.c:53-67", "sys/cpu/x86_64/include/atomic.h:72-74", "sys/cpu/x86_64/include/atomic.h:110-115", "sys/cpu/x86_64/include/atomic.h:128", "sys/platform/pc64/include/globaldata.h:76-77", "sys/platform/pc64/x86_64/ipl.s:275", "sys/platform/pc64/x86_64/ipl.s:431", "sys/kern/lwkt_ipiq.c:308-315", "sys/cpu/x86_64/include/cpu.h:73-87", "sys/kern/kern_clock.c:873" ], "poc_changes": "n/a \u2014 finding verified by live disassembly of the running guest kernel (objdump/nm on /boot/kernel/kernel) plus source writer-inventory; no compiled trigger needed for a comment-vs-emission divergence.", "attempts": 1, "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": 42, "guest_dirty": 0, "build_cmd": "none (objdump -d of /boot/kernel/kernel on the live guest)", "run_cmd": "findings/poc/DF-5672/run.sh (dfbsd-qemu/vm.sh run_root objdump/nm pipeline -> run.log)", "code_hash": "c623631878f41ac13336d8e7e2026231f35d7c750ae5426707f540776f1da80f", "notes": "Pass-2 negatives documented in VERDICT.md: (b) no DF-5586-class ungated splz on pc64 \u2014 doreti gates at ipl.s:142-143, splz self-guards at ipl.s:355 (live: incl 0xd4(%rbx)), splz_check/lwkt_maybe_splz gated at lwkt_thread.c:1073-1077/1095-1099; (c) unpend bit math clean \u2014 SWI bits 0..6 in 32-bit word (interrupt.h:78-91), intr=192..198 within MAX_HARDINTS=192..+64 (interrupt.h:66-69), btrl/jnc recheck race-safe; (d) all 13 setsoft*/setdelayed call sites CPU-local (kern_clock.c:873, subr_taskqueue.c:532, busdma_machdep.c:1432, cam_xpt.c:4919, sio.c:1898-1998, usb_serial.c:2039, ng_bt3c_pccard.c:775); pend-on-foreign-CPU structurally impossible (void f(void) + mdcpu). No memory-safety surface: only compile-time constants ORd into per-CPU words.", "recommended_fix": "Rewrite the ipl_funcs.c:37-43 comment to state the real invariant (strictly per-CPU gd_spending/gd_sdelayed; nonlocked OR safe only because each CPU RMWs its own word; do not add cross-CPU accessors) \u2014 see fix.diff.", "fix_status": "not_testable", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff is comment-only (zero code delta \u2014 no instruction changes, verified by inspection of the diff against ipl_funcs.c:37-43). A patched-kernel rebuild+re-run would produce byte-identical disassembly, so there is no observable runtime delta to validate; classification not_testable per the fix-validation vocabulary. Baseline (pre-fix) divergence reproduced live in run.log.", "fix_evidence": "findings/poc/DF-5672/fix.diff (comment-only: no lines outside the /* ... */ block changed); baseline divergence in run.log." } |