tws_cam_attach error symmetry: missing return after cam_sim_alloc failure -> xpt_bus_register(NULL) NULL-deref panic at attach; sc->sim left dangling/registered on later failure paths
Summary
cam_sim_alloc failure is logged but not returned; execution continues to xpt_bus_register(NULL) which immediately writes sim->bus_id - NULL panic under memory pressure. The bus_register failure NULLs sc->sim but the create_path failure frees the sim WITHOUT NULLing it (latent double-free for later detach), and the scan failure leaks the registered bus/SIM. Return+NULL+unwind fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4402 Β· 6 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 1.9 KB | β raw | |
| VERDICT.md | β | 2.0 KB | β raw | |
| trigger.c | β | 547 B | view raw | |
| fix.diff | β | 1.0 KB | view raw | |
| verdict.json | β | 2.2 KB | view raw | |
| env.txt | β | 541 B | view raw |
DF-4402 β tws_cam_attach() error symmetry: missing return after cam_sim_alloc failure, dangling sc->sim
What
sys/dev/raid/tws/tws_cam.c:136-202 (tws_cam_attach):
-
Missing error return (boot-time NULL deref):
c sc->sim = cam_sim_alloc(...); cam_simq_release(devq); if (sc->sim == NULL) { tws_log(sc, CAM_SIM_ALLOC); /* logged... and falls through! */ } lockmgr(&sc->sim_lock, LK_EXCLUSIVE); if (xpt_bus_register(sc->sim, 0) != CAM_SUCCESS) { /* sc->sim == NULL */On allocation failure the driver registers a NULL SIM.xpt_bus_register()dereferencessimimmediately (sys/bus/cam/cam_xpt.c:4304sim_lock_assert_owned(sim->lock)βsim->lockon NULL;:4306sim->bus_id = buswrite through NULL) β NULL-pointer kernel panic during attach. Reachable under memory pressure at boot/driver-load. -
Dangling
sc->simon the xpt_create_path failure path (latent double-free): thexpt_bus_registerfailure path NULLssc->sim(:180) but thexpt_create_pathfailure path (:185-193) frees the sim (cam_sim_free(sc->sim)) without NULLing it β any latertws_cam_detach()(:211-214, xpt_bus_deregister + cam_sim_free again) would double-free / UAF. Todaytws_attach'sattach_fail_4(tws.c:309-316) happens not to calltws_cam_detach, so this half is latent β but it is exactly the asymmetry that turns any future caller into a double free. -
tws_bus_scanfailure leaks the registered bus/SIM (:194-198returns error without deregistration).
Impact
(1) is a denial-of-service (kernel panic) gated on cam_sim_alloc failing β
memory pressure during device attach. (2)/(3) are error-path hygiene with
latent UAF potential. Low severity: attach-time, resource-pressure-gated.
Status
Cannot be exercised on the audit guest (no 3ware HBA); (1) proven by
xpt_bus_register's immediate dereference β see VERDICT.md.
VERDICT β DF-4402
Status: inconclusive (hardware-gated attach path).
Proof
tws_cam_attach(tws_cam.c:167-175):c sc->sim = cam_sim_alloc(tws_action, tws_poll, "tws", sc, ..., devq); cam_simq_release(devq); if (sc->sim == NULL) { tws_log(sc, CAM_SIM_ALLOC); } /* no return! */- Execution continues to
xpt_bus_register(sc->sim, 0)(:178) withsc->sim == NULL.xpt_bus_register(sys/bus/cam/cam_xpt.c:4298-4306) first executessim_lock_assert_owned(sim->lock)β a NULL deref read on INVARIANTS builds β and unconditionallysim->bus_id = bus(:4306) β a NULL-pointer write on production builds. Kernel panic at attach. - Asymmetry evidence: the bus-register failure path knows the correct
pattern β
cam_sim_free(sc->sim); sc->sim = NULL;(:179-180) β while the create-path failure path (:188-190) and bus-scan failure path (:194-198) omit it, leavingsc->simdangling/registered respectively. tws_cam_detach(:204-216) callsxpt_bus_deregister(cam_sim_path(sc->sim))andcam_sim_free(sc->sim)guarded only byif (sc->sim)β a stale non-NULL pointer double-frees.
Trigger
Boot or kldload the driver when kernel memory is exhausted enough for
cam_sim_alloc (kmalloc of struct cam_sim) to fail. Not reproducible on the
audit guest (no 3ware PCI device β probe never succeeds).
Impact ceiling
Panic at attach (DoS); latent double-free in detach if any future caller invokes
tws_cam_detach after a partially-failed attach. Severity Low (requires
allocation failure at attach; boot-time/privileged context).
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
not_testablefix.diff adds the missing return and symmetric cleanup; not validatable on the guest (no controller, no controllable kmalloc failure at attach).
fix.diff
Confirmed kernel references
Detail
Evidence (decisive lines)
VERDICT.md; fix.diff (return ENOMEM; NULL sc->sim on both failure paths; unwind on scan failure); trigger.c (reproduction conditions)
PoC changes
no seed; conditions stub only
Verified recommended fix
Return ENOMEM immediately when cam_sim_alloc fails; NULL sc->sim after cam_sim_free on every failure path; unwind registration on bus-scan failure.
Verdict
Certain from source. tws_cam_attach logs but does not return on cam_sim_alloc failure (tws_cam.c:173-175), then calls xpt_bus_register(sc->sim==NULL) at :178 β xpt_bus_register immediately dereferences sim (sim->lock assert, then sim->bus_id = bus write at sys/bus/cam/cam_xpt.c:4304-4306) -> NULL-pointer write/panic during attach under memory pressure. Additionally the xpt_create_path failure path frees the sim without NULLing sc->sim (:185-193, contrast :180), leaving a latent double-free for any later tws_cam_detach (:211-214), and the tws_bus_scan failure path leaks the registered bus/SIM (:194-198). Hardware-gated: guest has no 3ware HBA.
No comments yet.