XPT_RESET_DEV dereferences softc->atadev[tid] with no NULL or bounds check
Summary
atapi_action XPT_RESET_DEV case directly dereferences softc->atadev[ccb_h->target_id]->dev without NULL guard that XPT_PATH_INQ (:385) and XPT_SCSI_IO (:490) apply. If ATAPI device removed (atadev[tid]=NULL by reinit_bus) but CAM path not yet torn down CAM dispatches XPT_RESET_DEV causing NULL deref panic. No bounds check: atadev[] has 2 slots target_id can be CAM_TARGET_WILDCARD. Reachable via atacontrol reset or hot-plug race. [VERIFIED pass2: reproduced - XPT_RESET_DEV with atadev 0 NULL panics at the exact verbatim deref Fatal trap 12 VA 0; DEV_NOT_THERE fix A/B guest survives]
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-2501 Β· 9 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 1005 B | β raw | |
| VERDICT.md | β | 2.3 KB | β raw | |
| build.sh | β | 99 B | view raw | |
| run.log | β | 371 B | view raw | |
| env.txt | β | 963 B | view raw | |
| fix.diff | β | 994 B | view raw | |
| manifest.json | β | 783 B | view raw | |
| verdict.json | β | 2.3 KB | view raw | |
| panic.txt | β | 370 B | view raw |
DF-2501 -- XPT_RESET_DEV dereferences softc->atadev[tid] with no NULL/bounds check
Verification used the shared rig tree at /root/rigs on the audit guest (see manifest). The rig for this finding: dfv_acam (rig.c = harness, gen.sh = verbatim extractor, dfv_*_extract.h = generated production text). The decisive outputs below were captured live on the guest during the 2026-10-24 verification session; full session logs are summarized per run.
Build
sh build.sh # extracts verbatim driver text + builds the KLD
Run (guest, root)
kldload ./dfv_rig.ko
kldload dfv_acam.ko; sysctl kern.dfv_acam_run=1 # panics the stock kernel
Expected
panic.txt: Fatal trap 12 at dfv_acam_sysctl (inlined verbatim atapi_action XPT_RESET_DEV), fault VA 0x0; fixed: xpt_done(status=0x8) CAM_DEV_NOT_THERE.
Fix validation
fix.diff adds the same NULL/bounds guard XPT_SCSI_IO uses; A/B survives with CAM_DEV_NOT_THERE.
Verdict: reproduced / impact=panic (see verdict.json, VERDICT.md)
DF-2501 verdict -- XPT_RESET_DEV dereferences softc->atadev[tid] with no NULL/bounds check
status: reproduced reproduced: 1 impact: panic confidence: certain attempts: 2 runtime_sec: 700
The verbatim atapi_action XPT_RESET_DEV case (atapi-cam.c:428-432) evaluates softc->atadev[tid]->dev with neither the NULL guard XPT_PATH_INQ applies at :385 nor the guard XPT_SCSI_IO applies at :490. Dispatching XPT_RESET_DEV with atadev[0] == NULL (the state reinit_bus leaves behind) panicked the kernel at the exact deref: Fatal trap 12, fault VA 0x0, stopped at the movq through the NULL atadev - the precise instruction the finding cites. Fixed source A/B: the same dispatch returns CAM_DEV_NOT_THERE (xpt_done status=0x8 logged) and the guest survives. Trigger model per the filing: CAM dispatch racing atacontrol reinit/hot-plug - privileged/physical context; the pass(4) route to XPT_RESET_DEV is also gated by raw-device permissions on this system.
Evidence (decisive lines)
(kernel serial console) Fatal user address access from kernel mode from sysctl at ffffffff82606e66 Fatal trap 12: page fault while in kernel mode fault virtual address = 0x0 Stopped at dfv_acam_sysctl+0x116: movq (%rax),%rcx <- atadev[tid]->dev, rax=0 --- fixed source A/B --- DF2501: log: xpt_done(status=0x8) <- CAM_DEV_NOT_THERE, guest survives
Panic
Fatal user address access from kernel mode from sysctl at ffffffff82606e66 Fatal trap 12: page fault while in kernel mode fault virtual address = 0x0 fault code = supervisor read data, page not present Stopped at dfv_acam_sysctl+0x116: movq (%rax),%rcx (trace: verbatim atapi_action XPT_RESET_DEV -> softc->atadev[0]->dev with atadev[0]=NULL, atapi-cam.c:432)
Exploit chain / privesc assessment
deterministic kernel NULL-deref panic; privesc ceiling: none (DoS).
Fix + A/B
fix.diff adds the same NULL/bounds guard XPT_SCSI_IO uses; A/B survives with CAM_DEV_NOT_THERE.
Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
Fix verification
fixedConfirmed kernel references
Detail
Exploit chain
deterministic kernel NULL-deref panic; privesc ceiling: none (DoS).
Evidence (decisive lines)
panic.txt: Fatal trap 12 at dfv_acam_sysctl (inlined verbatim atapi_action XPT_RESET_DEV), fault VA 0x0; fixed: xpt_done(status=0x8) CAM_DEV_NOT_THERE.
PoC changes
verbatim atapi_action + struct extraction; ATA transport interposed; get_mplock stubs (not exported to KLDs on this kernel).
Verified recommended fix
NULL/bounds guard atadev[tid] in XPT_RESET_DEV like XPT_SCSI_IO
Verdict
The verbatim atapi_action XPT_RESET_DEV case (atapi-cam.c:428-432) evaluates softc->atadev[tid]->dev with neither the NULL guard XPT_PATH_INQ applies at :385 nor the guard XPT_SCSI_IO applies at :490. Dispatching XPT_RESET_DEV with atadev[0] == NULL (the state reinit_bus leaves behind) panicked the kernel at the exact deref: Fatal trap 12, fault VA 0x0, stopped at the movq through the NULL atadev - the precise instruction the finding cites. Fixed source A/B: the same dispatch returns CAM_DEV_NOT_THERE (xpt_done status=0x8 logged) and the guest survives. Trigger model per the filing: CAM dispatch racing atacontrol reinit/hot-plug - privileged/physical context; the pass(4) route to XPT_RESET_DEV is also gated by raw-device permissions on this system.
No comments yet.