⬢ DragonFlyBSD Kernel Audit
DF-3273 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-3273",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "Unauthenticated PPP peer panics the kernel with ONE frame: LCP CONF-NAK with h->len=0 (ident 0 matches the initial confid, or is read off the wire). sppp_cp_input only re-validates len<4 for CONF_REQ; CONF_NAK/CONF_REJ are dispatched with len 0..3 to the RCN handlers, whose len -= 4; kmalloc(len, M_TEMP, M_INTWAIT) becomes kmalloc(0xFFFFFFFFFFFFFFFC). round_page() wraps the size to 0, the degenerate oversized allocation path corrupts the kernel map, and the kernel panics (vm_map_entry_link: dup addr map via kmem_slab_alloc <- _kmalloc). Deterministic across resets on the stock INVARIANTS guest. Same bug in all six RCN handlers (lcp/ipcp/ipv6cp x rej/nak). fix.diff adds the missing len<4 guard to the CONF_NAK/CONF_REJ arm; validated: frame rejected, no panic, LCP still negotiates.",
  "exploit_chain": "single 8-byte frame ff03c021 03 00 0000 -> negative-length kmalloc -> allocator panic (remote DoS; no memory-control primitive)",
  "evidence": [
    "findings/poc/DF-3273/panic.txt: panic: vm_map_entry_link: dup addr map ... kmem_slab_alloc+0x145 <- _kmalloc+0x5be, captured from the serial console of the baseline run",
    "findings/poc/DF-3273/VERDICT.md: full path trace incl. round_page wrap"
  ],
  "kernel_refs": [
    "sys/net/sppp/if_spppsubr.c:1412",
    "sys/net/sppp/if_spppsubr.c:1417",
    "sys/net/sppp/if_spppsubr.c:1541",
    "sys/net/sppp/if_spppsubr.c:2492",
    "sys/kern/kern_slaballoc.c:942",
    "sys/kern/kern_slaballoc.c:1706"
  ],
  "poc_changes": "Standalone C trigger only (8-byte frame write to the harness device); no fixes needed beyond the harness itself (see DF-3272 pack).",
  "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": 300,
  "guest_dirty": 0,
  "build_cmd": "cd /root/poc && make && cc -O2 -o poc_3273 poc_3273.c   (fix build: cd /usr/src/sys/net/sppp && make)",
  "run_cmd": "kldload /root/poc/sppp_harness.ko && /root/poc/poc_3273",
  "code_hash": "d1d767baaf493e6985d413b67dedcf2855d0873e982b5cf3ce91908a672837e5",
  "notes": "Legacy (PPP) bucket. Panic fires inside the allocation itself on the INVARIANTS kernel; on non-INVARIANTS builds the degenerate chunk pointer reaches kfree and trips z_Magic checks / faults on unmapped kernel_map space -- fatal either way. reachability requires only that a sppp interface exists (any netgraph7/ng_sppp or sync-serial driver attach).",
  "recommended_fix": "Add the missing len<4 guard to the CONF_NAK/CONF_REJ arm of sppp_cp_input (mirroring the CONF_REQ guard at if_spppsubr.c:1417).",
  "fix_status": "fixed",
  "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:54 UTC 2026 (sppp.ko rebuilt from patched /usr/src/sys/net/sppp, cc 8.3 -Werror clean)",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "Patched sppp.ko: poc_3273 injects the same frame, write() returns 8, kernel stays up (frame dropped as ierror); DF-3272 driver on the same patched module completes a normal LCP negotiation, so no regression.",
  "fix_evidence": [
    "findings/poc/DF-3273/panic.txt (baseline)",
    "findings/poc/DF-3273/fix.diff",
    "DF-3272 pack run.fixed.log (same patched module, negotiation healthy)"
  ]
}