mprsas_SSU_to_SATA_devices leaks mpr_lock on two error-path returns β permanent adapter deadlock at shutdown
Summary
The lock is taken at :1479; the xpt_alloc_ccb failure return at :1501 and xpt_create_path failure return at :1510 both hold the lock (unlock at :1541 after the loop). Every subsequent mpr_lock user - mpr_intr, the periodic callout, cam teardown/detach - deadlocks; shutdown wedges. out_unlock label fix (compile-validated).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4251 Β· 0 files| File | Type | Description | Size | |
|---|---|---|---|---|
| empty | ||||
Fix verification
fixedfixed: out_unlock restructure applied (with the DF-4250/4253 diffs) to pristine guest /usr/src, nativekernel rc=0, installed as kernel #1; identical dispatch on the patched production SSU returns with lockstatus==0 (released) where baseline leaked LK_EXCLUSIVE and wedged the kthread.
rig_fixed_run.log: '[df42rig] SSU RETURNED. post-call lockstatus=0 (lock released)' + RESULT bitmask 0x0; patched-function objdump in the same log shows jmp-to-common-unlock structure; fix_build.log full untrimmed build.
Confirmed kernel references
Detail
Evidence (decisive lines)
run.log (untrimmed): 'SSU RETURNED. post-call lockstatus=2 (mpr_lock STILL HELD -- LOCK LEAKED by the xpt_create_path error return)'; 'wedge check after 2s: kthread STILL BLOCKED on mpr_lock -- adapter DEADLOCKED'; 'after rig release: kthread proceeded (in production nothing ever releases -> permanent wedge)'. rig_fixed_run.log: patched kernel prints 'post-call lockstatus=0 (lock released)', bitmask 0x0 vs baseline 0x3; objdump of patched SSU shows error paths jumping to the common lockmgr_release block (goto out_unlock).
PoC changes
No seed PoC existed (previously 'untested'). Authored the address-dispatch path in the df42rig KLD (DF-1326 discipline: nm-resolved static symbol + 16-byte live-prologue verification + refusal on mismatch) with a real cam_devq/cam_sim whose path_id is forced to an unregistered bus to induce exactly the production xpt_create_path failure; bounded kthread wedge demonstration with owner-thread release so the guest stays healthy.
Verified recommended fix
route both SSU error returns through out_unlock so mpr_unlock always runs (fix.diff)
Verdict
REPRODUCED with production code on the live guest: the shipped kernel's static mprsas_SSU_to_SATA_devices (resolved via nm at 0xffffffff80592e10, 16-byte prologue-verified before every dispatch β the rig once REFUSED a mismatched prologue) was dispatched on an attach-faithful fabricated adapter whose cam_sim has a REAL cam_devq but path_id 0x77, an unregistered bus: xpt_create_path then returns CAM_PATH_INVALID (cam_xpt.c:3989-3991), exactly the production error condition at mpr_sas_lsi.c:1503-1511. xpt_alloc_ccb (real CAM) succeeded; the REAL production function returned at :1510 WITH sc->mpr_lock still held (lockstatus LK_EXCLUSIVE) β the leak. A kernel thread then called mpr_lock(sc) and stayed blocked >2s (the adapter-deadlock state every later mpr_lock user β mpr_intr, periodic callout, cam teardown β would hit permanently); the rig released the lock as the owning thread and the blocked thread proceeded, proving both the wedge and that production has no releaser. Repeated twice, bitmask 0x3 both times, guest healthy. Fix validated on a rebuilt kernel carrying the out_unlock restructure: identical dispatch on the patched production function returns with lockstatus==0 (lock released), no wedge.
No comments yet.