DF-2681 / verdict.json
{ "finding_id": "DF-2681", "status": "reproduced", "reproduced": 1, "impact": "dos", "confidence": "certain", "verdict": "bus_generic_delete_resource() (sys/kern/subr_bus.c:3144-3149) dispatches BUS_DELETE_RESOURCE() on 'dev' instead of 'dev->parent' (every sibling wrapper propagates to the parent), so any driver that installs this exported generic default as its bus_delete_resource method re-enters it forever. Reproduced with dfrec.ko, a minimal nexus bus driver doing exactly that: on kldload the console shows 'dfrec: attached, calling bus_delete_resource() on child' and kldload never returns; kldstat/ps hang, clean shutdown times out, the guest had to be force-killed (the -O2 tail call compiles to a jmp -> unbounded kernel loop holding the module lock; non-tail-call layouts overflow the kernel stack instead). Latent in-tree (no current driver installs it) but shipped as the documented generic default in sys/sys/bus.h:274.", "exploit_chain": "", "evidence": "run.log (kldload wedge narrative with timestamps); dfrec.c (PoC driver); boot.log serial excerpt in VERDICT.md; fix.diff (one-line dev->parent fix)", "kernel_refs": [ "sys/kern/subr_bus.c:3144", "sys/kern/subr_bus.c:3148", "sys/sys/bus.h:274", "sys/kern/subr_kobj.c:160-191 (method dispatch on first arg)" ], "poc_changes": "PoC authored fresh; initial compile needed the 'dragonfly -> /usr/src/sys' kmod symlink and bus_if.h/device_if.h in SRCS.", "attempts": 2, "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": 1, "build_cmd": "cd /tmp/df2681 && ln -sf /usr/src/sys dragonfly && make", "run_cmd": "kldload /tmp/df2681/dfrec.ko (expect: never returns; system wedges)", "code_hash": "06a233a25d0aacd164c1e36e5def012bc70d7bb698250ec7d3ef57723931c16d (dfrec.c)", "notes": "Guest wedged hard enough that it could not be shut down (force-killed from host, snapshot reset). Not fix-validated by rebuild (Low severity, latent): one-line fix swaps dev -> dev->parent, matching all sibling wrappers; with it, dispatch terminates at the first implementing ancestor or the kobj default (kobj_error_method -> ENXIO). fix_status=inconclusive for the record.", "recommended_fix": "In bus_generic_delete_resource(), dispatch BUS_DELETE_RESOURCE(dev->parent, ...) instead of BUS_DELETE_RESOURCE(dev, ...)." } |