DF-4783 / verdict.json
{ "finding_id": "DF-4783", "status": "not_reproduced", "reproduced": 0, "impact": "none", "confidence": "likely", "verdict": "mmcsd_detach (mmcsd.c:209-248) does not exclude the data path \u2014 mmcsd_strategy (mmcsd.c:310-311) resolves si_drv1 and takes sc_lock with no synchronization against lockuninit (mmcsd.c:245) and the newbus softc free, and si_drv1 is never cleared \u2014 a genuine CWE-362/416 in-flight-stall race (card removal / hot-unplug / kldunload during I/O). On a real emulated SDHCI+card (QEMU sdhci-pci), faithful fd-pinned workloads survive: a holder process gets EBADF after teardown (dead_dev_ops revector, 10101 OK reads) and 8 holders x 10 removal/re-insert cycles complete without a panic. An over-strong kernel hammer (dev_dstrategy without the cdev reference in-tree callers hold) panicked 3/3 fresh boots inside the window (dev_dstrategy+0x1b / lockmgr_exclusive+0x5d), but that is a caller-contract violation, not a reachable primitive \u2014 hence not_reproduced. Mechanism certain by inspection; exploit window narrow; fix mirrors the validated DF-4646 nvme shape.", "exploit_chain": "", "evidence": "VERDICT.md (full story); panic-run1..3.txt (3/3 kernel-hammer panics); userbat.log + run.log RUN A/B (faithful holders survive, EBADF revector); mmhold.c/mmcrace.c (rig)", "kernel_refs": [ "sys/dev/disk/mmcsd/mmcsd.c:209", "sys/dev/disk/mmcsd/mmcsd.c:233", "sys/dev/disk/mmcsd/mmcsd.c:245", "sys/dev/disk/mmcsd/mmcsd.c:286", "sys/dev/disk/mmcsd/mmcsd.c:304", "sys/dev/disk/mmcsd/mmcsd.c:310", "sys/dev/disk/mmcsd/mmcsd.c:312", "sys/bus/mmc/mmc.c:259", "sys/dev/disk/sdhci/sdhci.c:874" ], "poc_changes": "Rig written from scratch. Three generations: (1) sysctl-context device_delete_child self-deadlocks on sysctllock via device_sysctl_fini \u2014 moved all actions to a worker kthread; (2) standalone struct bio panics push_bio (too many layers) because the whole-disk cdev routes through subr_diskslice \u2014 bios must use the bufs embedded b_bio1; (3) kernel dev_dopen does not pin the cdev (no sysref) \u2014 the hammer raced a freed cdev (3/3 panics), which is how the faithful-holder distinction was established. QEMU sdhci data transfers wedge (inhibit bit) after first MULTI read \u2014 irrelevant to the race; strategy/queue path is exercised identically on EIO.", "attempts": 6, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 x86_64 (QEMU 7.2.22, -device sdhci-pci + sd-card)", "runtime_sec": 4500, "guest_dirty": 0, "build_cmd": "cd /root/mmcrig && make && cc -O2 -o mmhold mmhold.c", "run_cmd": "kldload ./mmcrace.ko; nohup ./mmhold &; sysctl hw.mmcrace.action=1 (faithful) / action=10+1+2 cycles (aggressive)", "code_hash": "28c5f6c60ade19bf2c6c6cf48854a439ee80a9246c9e45e808c2a9b799abc68b", "notes": "Faithful battery 10 cycles clean; 3/3 aggressive-harness panics retained as serialization evidence. Related but separate: DF-1874/2479/2480 (known block-math family) not re-tested.", "recommended_fix": "Set a gone flag + drain in-flight strategy/open callers under sc_lock before disk_destroy/lockuninit, clear the raw cdevs si_drv1, and move the bio queue flush under the lock (see fix.diff).", "fix_status": "not_tested", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "not build-validated: faithful baseline did not reproduce, so a patched-kernel comparison would be vacuous; fix.diff mirrors the shape validated for DF-4646 (nvme)", "fix_evidence": "fix.diff" } |