DF-2586 — OOB read proof (panic signature interpretation) ========================================================= The decisive PoC sets the buggy geometry via kvm_write (root-only state setup that shortcuts the timing of the natural msgbuf_clear path): msg_bufx = msg_size -> xindex_modulo == 0 msg_bufr = msg_size/2 + 100000 -> rindex_modulo > msg_size/2 Then issues sysctlbyname("kern.msgbuf", buf, 1MiB_oldlen). On the UNPATCHED #0 kernel this PANICS: panic: assertion "obj != NULL" failed in vm_object_hold_shared at vm_object.c:330 --- trap 0xc, rip=std_copyout+0x15a --- std_copyout() at std_copyout+0x15a Trap 0xc = page fault raised INSIDE std_copyout's source-side read. The buggy branch-3 length (n - rindex_modulo) underflows to ~4.095 billion (u_int), sysctl_old_user clips it to the 1 MiB oldlen, and copyout reads 1 MiB starting at msg_ptr + rindex_modulo -- running PAST msg_ptr + msg_size into unmapped kernel memory -> fault -> KASSERT(obj != NULL) panic. This is DECISIVE proof the buggy code path is an OOB read. Had the adjacent memory been mapped (it usually is, just past the msgbuf), the same read would have LEAKED kernel-heap residue to userspace instead of crashing. REACHABILITY (honest): the OOB-underflow geometry requires msg_bufr to be "stale" (modulo > msg_size/2). In steady state msg_bufr tracks msg_bufx - msg_size + 2048 so rindex_modulo==2048 and the bug is only a benign 2048-byte UNDER-read (no OOB, no leak). The stale state is produced ONLY by root writing kern.msgbuf_clear=1 (msg_bufr := msg_bufx). An unprivileged user cannot trigger the OOB -- verified by polling (see unpriv log). So the bug's realistic impact ceiling is: root-triggerable local kernel OOB read / panic (does NOT cross a privilege boundary; root->root + DoS). The code fix is still warranted -- it's a real latent OOB defect. Decisive run output was lost to the panic (ssh channel died before flush); the boot.log panic above is the proof. (geometry_steady.txt shows the natural steady-state branch decision before the trigger.)