Unbounded waits and ignored reinit errors: mps_wait_command(...,0) sleeps forever, mps_reinit ignores mps_reregister_events() failure leaving the simq frozen permanently
Summary
(1) mps_wait_command with timeout==0 sleeps indefinitely; mps_read_config_page passes 0 - a silent-but-not-faulted IOC (watchdog reinitializes only on FAULT) hangs the config thread forever. (2) mps_reinit discards reregister_events' return; on failure mpssas_startup never fires so the simq frozen in handle_reinit is never released - all adapter I/O wedged until reboot. (3) reregister_events treats EINPROGRESS as failure although the async callback still completes - entering the wedge spuriously. Finite-timeout + honor-error + accept-EINPROGRESS fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4078 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| verdict.json | β | 2.2 KB | view raw | |
| README.md | β | 332 B | β raw | |
| VERDICT.md | β | 1.7 KB | β raw | |
| fix.diff | β | 651 B | view raw | |
| manifest.json | β | 720 B | view raw |
DF-4078 β mps unbounded waits and ignored reinit errors can wedge the adapter permanently
Files/lines: mps.c:2129 + :2221 (infinite lksleep), :353 (ignored mps_reregister_events error), :1769-1772 (EINPROGRESS treated as failure); mps_sas.c:1091 (frozen simq) Source-level finding; chip-gated DoS. See VERDICT.md.
DF-4078 VERDICT β source-level likely, chip-gated (permanent I/O hang / thread hang)
(1) Indefinite sleep with timeout == 0
mps_wait_command():2129 lksleep(cm, &sc->mps_lock, 0, "mpswait", timeout*hz) β with timeout 0
DragonFly sleeps forever. mps_read_config_page():2221 passes 0. A silent-but-not-faulted IOC
(the periodic watchdog calls mps_reinit only on MPI2_IOC_STATE_FAULT, mps.c:1247-1252) hangs the
config-path thread indefinitely (attach / CAM contexts).
(2) mps_reinit ignores mps_reregister_events() failure
mps_reinit():353 calls mps_reregister_events(sc) and discards the return. On failure
(mps_alloc_command EBUSY from an exhausted pool, or bus_dmamap_load error) the completion that
would call mpssas_startup() (mps_reregister_events_complete:1654) never fires; the simq frozen in
mpssas_handle_reinit (mps_sas.c:1091 xpt_freeze_simq) is never released β every I/O on the adapter
wedges until reboot.
(3) EINPROGRESS mishandled
mps_reregister_events():1769-1772 treats mps_map_command() EINPROGRESS as a failure return, though the async DMA-map callback will still enqueue and complete the request β a spurious entry into exactly the failure path of (2).
DoS only; no memory corruption. Confidence 'likely' (needs a misbehaving/exhausted IOC+pool state).
Fix
Finite timeout at :2221; check and retry/fail loudly on :353; accept EINPROGRESS at :1769.
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_testableHardware-gated finding (no AMD VegaM GPU / no LSI mps controller on the audit guest): fix authored at source level (fix.diff) but not build/boot-validated.
fix.diff in this pack; authored post-analysis, not hardware-validated.
Confirmed kernel references
Detail
Evidence (decisive lines)
mps.c:2129 lksleep with timeout*hz; :2221 caller passes 0; :353 unchecked mps_reregister_events(); mps_sas.c:1091 xpt_freeze_simq
PoC changes
n/a (source-level)
Verified recommended fix
Pass a finite timeout at :2221; check and act on mps_reregister_events() failure (retry or fail the reinit); treat EINPROGRESS as success in mps_reregister_events().
Verdict
Source-level likely, chip-gated permanent hangs. (1) mps_wait_command():2129 does lksleep(cm, ..., timeout*hz); mps_read_config_page() passes timeout == 0 at :2221 => indefinite sleep. A silent-but-not-faulted IOC (periodic watchdog only calls mps_reinit on MPI2_IOC_STATE_FAULT) hangs the config-path thread forever. (2) mps_reinit():353 ignores the return of mps_reregister_events(); if it fails (EBUSY from an exhausted command pool, or bus_dmamap_load error), the completion that would call mpssas_startup() never fires, so the simq frozen in mpssas_handle_reinit (mps_sas.c:1091) is never released => all adapter I/O wedged until reboot. (3) mps_reregister_events():1769-1772 treats mps_map_command() EINPROGRESS as a failure although the async map callback will still enqueue and complete the request, needlessly entering that failure path.
No comments yet.