DF-3384 / verdict.json
{ "finding_id": "DF-3384", "status": "not_reproduced", "reproduced": 0, "impact": "none", "confidence": "likely", "verdict": "bpfread() unconditionally executes bd_fbuf = bd_hbuf after uiomove(); if the reader blocks inside uiomove (user page fault releases bpf_token) and a concurrent BIOCFLUSH on a dupd fd ran bpf_resetd() meanwhile, the hold-buffer pointer parked in bd_fbuf is lost (permanent kmalloc leak), and after the next immediate-mode read the store slot is NULL, making catchpacket() write the bpf header through hp = bd_sbuf+curlen == NULL (kernel write to address 0). Code interleaving is certain from arithmetic on bpf.c:541-545 vs 674-686 and ROTATE_BUFFERS semantics, but it did NOT reproduce on this guest across three strategies (timing scan over 128 anon zero-fill faults x200 attempts; continuous BIOCFLUSH spam x60; flush spam against cold evicted file-backed pages of a 3.5GiB file, 7+ min) - on this virtualized host the copyout fault never yields bpf_token long enough for the flusher to acquire it mid-copy. Impact if landed: one bd_bufsize-byte kernel memory leak per win plus a NULL-address write (DoS); requires two threads sharing a bpf fd (privileged device). not_reproduced (timing), defect likely.", "exploit_chain": "", "evidence": [ "run.log: v1/v2/v3/v4 attempt summaries, all survived", "VERDICT.md: full interleaving derivation and why each variant failed" ], "kernel_refs": [ "sys/net/bpf.c:541-545", "sys/net/bpf.c:674-686", "sys/net/bpf.c:475-531", "sys/net/bpf.c:439-444", "sys/net/bpf.c:1455-1463" ], "poc_changes": "Evolved through 4 revisions: single-shot stagger -> timing scan with 512KiB hold buffer (128 faults per uiomove) -> flush-spam thread -> cold file-backed read buffer (3.5GiB file written past RAM to force eviction).", "attempts": 3, "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": 1500, "guest_dirty": 0, "build_cmd": "cc -O -o trigger trigger.c -pthread", "run_cmd": "./trigger", "code_hash": "bea2a5922e90b8791222172b57562ec3b17dd882339999557dae3b9b1b69ee9e", "notes": "The NULL-write consequence is mitigated by the bd_sbuf==NULL guard in the validated DF-3381 fix.diff; the leak itself needs a reader-active flag around uiomove (upstream-grade rework).", "recommended_fix": "Guard catchpacket against bd_sbuf==NULL (in fix.diff) and stop bpfread from clobbering bd_fbuf when bd_hbuf changed under it (e.g. re-check after uiomove, or a bd_reading flag consulted by bpf_resetd).", "fix_status": "not_testable", "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #1: Fri Sep 11 22:24:51 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64 (fix.diff applied; make nativekernel + installkernel in guest)", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "Baseline race never reproduced on this guest (3 strategies), so patched-vs-baseline comparison is not meaningful; the bd_sbuf==NULL catchpacket guard from the validated fix.diff is present in the patched kernel regardless.", "fix_evidence": [ "run.log", "VERDICT.md" ] } |