DF-3547 / verdict.json
{ "finding_id": "DF-3547", "status": "build_failed", "reproduced": 0, "impact": "none", "confidence": "certain", "verdict": "Certain use-after-free by source analysis, not runtime-testable: ng_device_disconnect() (ng_device.c:299-307) calls DragonFlys asynchronous destroy_dev() (kern_conf.c:345-354 -> devfs_core.c:1113-1127 fire-and-forget lwkt message; no draining, no ops revocation, si_drv1 never cleared) and then immediately kfree()s priv, while ngdopen/ngdclose/ngdread/ngdwrite/ngdpoll (ng_device.c:334/351/411/454/481) still fetch priv via dev->si_drv1 \u2014 an open fd keeps dispatching through it (devfs_vnops.c:1272-1295). Runtime verification is impossible because sys/netgraph7/ng_device.c is FreeBSD-port rot that cannot compile (64 errors: no struct cdevsw/d_open_t/msleep/IF_LOCK/_IF_ENQUEUE/IFQ_IS_EMPTY/MTX_DEF/ifq_mtx in DF \u2014 build.log) and is wired into no build (no Makefile SUBDIR, no NETGRAPH7_DEVICE config). Root-only trigger bounds impact; latent until the port is completed. fix.diff (refcounted priv + si_drv1 cleared under lock) also not compile-testable for the same reason.", "exploit_chain": "", "evidence": "build.log (64 compile errors, out-of-tree kmod build on guest); env.txt (no ng_device.ko, no NETGRAPH7 in any kernel config, ng_etf/ng_rfc1490 load fine); VERDICT.md full path:line chain; fix.diff reference fix", "kernel_refs": [ "sys/netgraph7/ng_device.c:292", "sys/netgraph7/ng_device.c:299", "sys/netgraph7/ng_device.c:307", "sys/netgraph7/ng_device.c:334", "sys/netgraph7/ng_device.c:351", "sys/netgraph7/ng_device.c:411", "sys/netgraph7/ng_device.c:419", "sys/netgraph7/ng_device.c:454", "sys/netgraph7/ng_device.c:469", "sys/netgraph7/ng_device.c:481", "sys/kern/kern_conf.c:345", "sys/vfs/devfs/devfs_core.c:759", "sys/vfs/devfs/devfs_core.c:1113", "sys/vfs/devfs/devfs_core.c:1440", "sys/vfs/devfs/devfs_vnops.c:1272", "sys/netgraph7/socket/ng_socket.c:182" ], "poc_changes": "PoC authored fresh (stalefd.c + build.sh); no seed existed. Build harness had to replicate the in-tree include environment via symlinks because the file is unwired.", "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": 210, "guest_dirty": 0, "build_cmd": "cd /tmp/ngdev && cp /usr/src/sys/netgraph7/ng_device.c . && ln -s ng7 headers && printf KMOD=ng_device SRCS=ng_device.c Makefile && SYSDIR=/usr/src/sys make # -> 64 errors (build.log)", "run_cmd": "not runnable: module absent/unbuildable; intended sequence documented in run.sh (ngctl mkpeer . device dl dl; ./stalefd; ngctl rmhook; stale-fd read/write)", "code_hash": "d0a333f7c49c54b82b96f0c98bc18d94afd4854725c4cf93ae5ff3642906f2df", "notes": "memcorrupt bucket but dead code: file is 2008 FreeBSD import rot; both trigger sides require root (0600 device, root-only ng control plane). Companion findings: DF-3548 (lost wakeup, Low), DF-3549 (dead-code status, Info).", "recommended_fix": "Refcount struct ngd_private: acquire under ngd_mtx in every cdevsw method with a dying flag; clear si_drv1 under the lock before async destroy_dev; free priv on last release instead of in disconnect (fix.diff).", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "Fix validation impossible on this guest: the unmodified file itself does not compile (64 errors, build.log), so neither a baseline nor a single-fix kernel exercising this code can be built. fix.diff is a source-level reference fix (refcounted priv lifetime, si_drv1 detached under lock before async destroy_dev, free deferred to last cdevsw reference); it should be re-validated as part of completing the ng7 device port (DF-3549).", "fix_evidence": "build.log (file rot); VERDICT.md Why it could NOT be verified; no fix_build.log/fix_run.log possible" } |