mpssas_send_abort/mpssas_send_reset early -1 returns are ignored by every caller: targ->tm wedged forever, TM leaked, timed-out CCBs never returned to CAM, simq frozen for the life of the adapter (DF-3802 twin)
Summary
Both TM senders return -1 on a zero dev handle without unwinding: the TM is not freed, targ->tm is not cleared, and no TM timeout is armed on that leg. All five callers drop the return. Only TM completion handlers ever clear targ->tm - none will run - so later timeouts pile onto timedout_commands forever, the victim CCBs never reach xpt_done (XPT_ABORT is faked-success, so nothing can unwedge them), the high-priority TM leaks, and tm_count stays >=1 keeping the simq frozen. Provable trigger: mpssas_remove_volume clears targ->handle without draining targ->commands - unlike mpssas_remove_device which drains - and handle_reinit zeroes all handles without purging timedout_commands. Unprivileged IO outstanding on an IR volume being deleted wedges the entire adapter's I/O permanently. Port the accepted mpr DF-3802 fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3895 Β· 8 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 3.1 KB | β raw | |
| VERDICT.md | β | 3.1 KB | β raw | |
| run.sh | β | 111 B | view raw | |
| run.log | β | 482 B | view raw | |
| env.txt | β | 274 B | view raw | |
| fix.diff | β | 3.1 KB | view raw | |
| verdict.json | β | 2.8 KB | view raw | |
| manifest.json | β | 747 B | view raw |
DF-3895 β mpssas_send_abort/mpssas_send_reset early -1 returns are ignored by every caller: targ->tm wedged forever, TM leaked, unkillable CCBs, simq frozen permanently
File: sys/dev/raid/mps/mps_sas.c (pass 2). Twin of DF-3802 (mpr_sas.c).
What
Both task-management senders bail out early β without freeing the TM,
without clearing targ->tm, without arming the TM timeout β when the
target's handle has been cleared:
mpssas_send_reset(...) /* mps_sas.c:1296 */
target = tm->cm_targ;
if (target->handle == 0) {
mps_printf(...);
return -1; /* mps_sas.c:1307 β tm leaked, targ->tm still == tm */
}
mpssas_send_abort(...) /* mps_sas.c:1436 */
targ = cm->cm_targ;
if (targ->handle == 0) {
mps_printf(...);
return -1; /* mps_sas.c:1447 β same */
}
Every caller ignores the return value:
- mpssas_scsiio_timeout mps_sas.c:1531-1537 (mpssas_send_abort(sc, targ->tm, cm) β return dropped)
- mpssas_logical_unit_reset_complete mps_sas.c:1201-1204 (mpssas_send_abort), :1218-1220 (mpssas_send_reset escalation)
- mpssas_abort_complete mps_sas.c:1418 (mpssas_send_abort continuation), :1428-1430 (mpssas_send_reset escalation)
Consequence (permanent wedge)
After the ignored -1:
- targ->tm remains set. Only the TM completion handlers clear it
(mps_sas.c:1165, 1206, 1251, 1278, 1384, 1409) β and no TM was ever
sent, so none will run. Every later timeout on the target just queues
onto targ->timedout_commands (mps_sas.c:1524-1530) and is never
processed.
- The triggering CCBs are never returned to CAM β the upper periph waits
forever; even camcontrol abort cannot help because mpssas_action
fakes success for XPT_ABORT without aborting anything
(mps_sas.c:986-991).
- The TM command leaks (high-priority credit gone) and tm_count stays
β₯ 1, so the simq is frozen for the life of the adapter
(mps_sas.c:262-265) β no further I/O through this SIM at all.
Provable trigger (same asymmetry DF-3802 proved for mpr)
mpssas_remove_volume clears targ->handle = 0x0 on successful IR volume
removal (mps_sas.c:387-397) without draining targ->commands, unlike
its sibling mpssas_remove_device which explicitly completes all missed
commands (mps_sas.c:592-599, "Completing missed command"). Outstanding
volume I/O therefore survives the handle clear; if any of it subsequently
times out, mpssas_scsiio_timeout β mpssas_send_abort hits
targ->handle == 0 β -1 β wedge. The same zeroed-handle state also occurs
for every target during diag-reset rediscovery
(mpssas_handle_reinit, mps_sas.c:1113-1121), while timedout_commands
are not purged.
Build/run
run.sh records the hardware gate (no SAS2 HBA in guest).
Fix
Mirror the accepted DF-3802 fix (findings/poc/DF-3802/fix.diff): on the -1
paths, clear targ->tm, free the TM, and complete every queued timedout
command with CAM_DEV_NOT_THERE; additionally drain targ->commands in
mpssas_remove_volume like mpssas_remove_device does. See fix.diff.
DF-3895 β VERDICT
Status: not_reproduced (hardware-gated) β defect certain from source. Impact class (on real hardware): permanent adapter-wide I/O hang (DoS) + high-priority command leak; CCBs never returned to CAM.
Proof chain
- Early-exit-without-unwind sites:
-
sys/dev/raid/mps/mps_sas.c:1303-1307(mpssas_send_reset,target->handle == 0βreturn -1) -sys/dev/raid/mps/mps_sas.c:1443-1447(mpssas_send_abort,targ->handle == 0βreturn -1) In both,tmwas already associated (targ->tm == tm, set by the caller at mps_sas.c:1531, or carried through escalation) and nocallout_resethas been armed on this leg (those happen at mps_sas.c:1338/1466, after the handle check) β so nothing will ever complete or time this TM out. - All five call sites drop the return:
mps_sas.c:1203, 1218 (
mpssas_logical_unit_reset_complete), 1418, 1428 (mpssas_abort_complete), 1536 (mpssas_scsiio_timeout). - Wedge mechanics:
targ->tmis cleared only inside TM completion handlers (mps_sas.c:1165, 1206, 1251, 1278, 1384, 1409) β none of which will run; subsequent timeouts queue ontotarg->timedout_commandsforever (mps_sas.c:1522-1530); the victim CCBs never reachxpt_done; XPT_ABORT is faked-success (mps_sas.c:986-991) so nothing external can unwedge them;tm_countremains β₯1 (incremented inmpssas_alloc_tm, mps_sas.c:242) soxpt_release_simqnever happens (mps_sas.c:262-265) β the SIM queue is frozen for the life of the adapter. - Provable trigger (twin of the mpr DF-3802 proof):
mpssas_remove_volumezeroestarg->handle(mps_sas.c:387-397) after issuing the TM but without drainingtarg->commands, whilempssas_remove_devicedrains them ("Completing missed command", mps_sas.c:592-599). Outstanding volume I/O + a later timeout βmpssas_send_abortsees handle==0 β -1 β wedge. Additionally,mpssas_handle_reinitzeroes all target handles (mps_sas.c:1113-1121) without purgingtimedout_commands, so a timeout processed in the rediscovery window wedges identically.
Why not reproduced on this guest
No SAS2 HBA (env.txt, run.log); SIM never attaches; no mps command can time
out. On hardware the wedge is observable as: console spam from
mpssas_send_abort's mps_printf, camcontrol devlist hangs on that bus,
all mps I/O blocked, tm_count stuck at 1 in MPS_TRACE logs.
Exploitability
DoS. An unprivileged user with access to a volume/disk being deleted (or any target during diag-reset rediscovery) whose I/O stalls can wedge the entire adapter's I/O permanently. No memory-corruption primitive.
Fix validation
Not testable on this guest. fix.diff ports the accepted DF-3802 fix verbatim to mps (unwind on the -1 paths + drain in remove_volume).
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 ports the accepted DF-3802 mpr fix verbatim to mps; cannot be exercised on this guest (no SAS2 HBA).
findings/poc/DF-3895/fix.diff
Confirmed kernel references
Detail
Evidence (decisive lines)
VERDICT.md (path:line proof incl. remove_volume/remove_device asymmetry), env.txt, run.sh + run.log (hardware gate), fix.diff (ports the accepted DF-3802 fix)
PoC changes
Trigger needs real SAS2 hardware (volume delete or diag-reset rediscovery racing a timeout); run.sh records the hardware gate.
Verified recommended fix
On the -1 paths clear targ->tm, free the TM, and complete queued timedout commands with CAM_DEV_NOT_THERE; drain targ->commands in mpssas_remove_volume like mpssas_remove_device.
Verdict
mpssas_send_reset (mps_sas.c:1303-1307) and mpssas_send_abort (mps_sas.c:1443-1447) return -1 on a zero dev handle without unwinding β the TM is not freed, targ->tm is not cleared, and no TM timeout is armed on that leg. All five callers ignore the return (mps_sas.c:1203, 1218, 1418, 1428, 1536). Result: only TM completion handlers ever clear targ->tm (mps_sas.c:1165/1206/1251/1278/1384/1409), so the target is wedged forever β later timeouts pile onto timedout_commands (mps_sas.c:1522-1530), the victim CCBs never reach xpt_done (XPT_ABORT is faked-success at mps_sas.c:986-991 so nothing can unwedge them), the TM high-priority credit leaks, and tm_count stays >=1 keeping the simq frozen for the life of the adapter (mps_sas.c:262-265). Provable trigger, twin of DF-3802's mpr proof: mpssas_remove_volume clears targ->handle (mps_sas.c:389) without draining targ->commands, unlike mpssas_remove_device (mps_sas.c:592-599); mpssas_handle_reinit zeroes all handles (mps_sas.c:1113-1121) without purging timedout_commands. Not reproduced: guest has no SAS2 HBA, SIM never attaches; wedge mechanics certain from source.
No comments yet.