⬢ DragonFlyBSD Kernel Audit
DF-3384 / verdict.json
← back to finding ↓ download raw
{
  "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"
  ]
}