⬢ DragonFlyBSD Kernel Audit
DF-3516 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-3516",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "Deterministic kernel NULL-deref panic reproduced on the stock guest: after NGM_SHUTDOWN shuts the socket node down (ngs_rmnode NULLs pcbp->sockdata and frees the ngsock while the control socket stays open), connect() on that socket passes soconnect (no SS_ISDISCONNECTED gate) into ng_connect_cntl which dereferences sockdata->node -> Fatal trap 12, fault vaddr 0x0, Stopped at ngc_connect+0x52: movq (%r13),%rdi. Root-gated (control sockets require caps_priv_check SYSCAP_RESTRICTEDROOT), no write primitive, so impact is privileged local DoS, not privesc. Fix validated at module level: with the two NULL checks applied, the identical PoC returns ENOTCONN (errno 57) with no panic and the NGM_SHUTDOWN good path still works.",
  "exploit_chain": "socket(AF_NETGRAPH,SOCK_DGRAM,NG_CONTROL) + bind name + sendto(NGM_SHUTDOWN to own node) [ngs_rmnode: sockdata=NULL, socket stays open] + connect(node:hook path) -> ng_connect_cntl -> NULL->node load at offset 0 -> page fault -> kernel panic",
  "evidence": "panic.txt + run.log (Fatal trap 12, vaddr 0x0, ngc_connect+0x52); run.fix.log (patched module: connect=-1 errno=57 ENOTCONN, guest alive); df3516.c (final PoC); fix.diff (validated)",
  "kernel_refs": [
    "sys/netgraph/socket/ng_socket.c:257",
    "sys/netgraph/socket/ng_socket.c:694",
    "sys/netgraph/socket/ng_socket.c:701",
    "sys/netgraph/socket/ng_socket.c:910",
    "sys/netgraph/socket/ng_socket.c:357",
    "sys/netgraph/netgraph/ng_base.c:1256",
    "sys/kern/uipc_socket.c:685"
  ],
  "poc_changes": "Fixed NG_CONTROL (2, not 1) via system header; second sendto replaced with connect() after observing sosends EPIPE/SIGPIPE gate (EXIT=141) blocks that route; connect address must be node:hook (ng_path_parse rejects empty hook with EINVAL before the deref); added SIGPIPE ignore.",
  "attempts": 4,
  "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": 420,
  "guest_dirty": 0,
  "build_cmd": "cc -O -o /root/df3516 /root/df3516.c   (in-guest, after kldload netgraph.ko + ng_socket.ko)",
  "run_cmd": "/root/df3516   (as root; expect: sendto=52, then panic on connect)",
  "code_hash": "a3825b14acdab0a0d4523855bb3281c1a6369c7ed3f1368379029445e4b81eef",
  "fix_status": "fixed",
  "fix_notes": "fix.diff adds sockdata==NULL -> ENOTCONN guards in ngc_send and ng_connect_cntl (same discipline as ngd_send:357/ng_bind:714). Validated by module rebuild + reload in guest: panic gone, ENOTCONN returned, good-path NGM_SHUTDOWN send unaffected. Repo sys/ untouched; guest reset clean afterwards.",
  "notes": "sendto-after-shutdown is NOT reachable (sosend EPIPE gate) - connect() is the reachable route; both missing checks fixed. Severity Medium: deterministic panic via stock socket API, but requires a root-held control socket.",
  "recommended_fix": "Add pcbp->sockdata/sockdata NULL checks returning ENOTCONN in ngc_send and ng_connect_cntl (see fix.diff)."
}