mprsas_resetdev_complete dereferences a NULL task-management reply: XPT_RESET_DEV outstanding during a Diag Reset panics the kernel
Summary
mprsas_resetdev_complete is the only TM completion handler in the file without a cm_reply==NULL guard; it reads resp->IOCStatus/ResponseCode directly. mprsas_complete_all_commands - run by mprsas_handle_reinit during every Diag Reset - completes all outstanding commands with cm_reply=NULL then calls cm_complete. An XPT_RESET_DEV TM in flight at reset time (device error storms classically produce CAM RESET_DEV and controller reset together) faults on the NULL deref: kernel panic instead of recovery, and the ccb is never completed. Hardware-gated (no SAS3 HBA on the guest); fix.diff adds the guard mirroring mprsas_target_reset_complete.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3801 Β· 7 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 218 B | β raw | |
| VERDICT.md | β | 2.9 KB | β raw | |
| run.sh | β | 111 B | view raw | |
| env.txt | β | 855 B | view raw | |
| fix.diff | β | 1.3 KB | view raw | |
| verdict.json | β | 2.0 KB | view raw | |
| manifest.json | β | 446 B | view raw |
DF-3801 evidence pack
mprsas_resetdev_complete NULL-reply dereference β panic during Diag Reset.
Read VERDICT.md. fix.diff adds the missing guard. verdict.json:
not_reproduced (no SAS3 hardware on guest).
DF-3801 β mprsas_resetdev_complete dereferences a NULL reply β kernel panic during Diag Reset
- File:
sys/dev/raid/mpr/mpr_sas.c - Class: kernel NULL-deref panic (missing NULL check)
- Severity: Medium / Confidence: certain (statically provable)
- Status on guest: not_reproduced β no SAS3 HBA (see
env.txt)
Defect
Every task-management completion handler in this file guards against
cm_reply == NULL:
mprsas_abort_completeβmpr_sas.c:1545mprsas_logical_unit_reset_completeβmpr_sas.c:1300mprsas_target_reset_completeβmpr_sas.c:1395mprsas_remove_volumeβmpr_sas.c:383mprsas_remove_deviceβmpr_sas.c:582mprsas_remove_completeβmpr_sas.c:657
mprsas_resetdev_complete (mpr_sas.c:3384-3427) does not:
resp = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply; /* :3392 */
...
if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { /* :3400 β only bail */
...
}
mpr_dprint(sc, MPR_XINFO, "%s: IOCStatus = 0x%x ResponseCode = 0x%x\n",
__func__, le16toh(resp->IOCStatus), le32toh(resp->ResponseCode)); /* :3412-13 DEREF */
Reachability
mprsas_complete_all_commands() β run from mprsas_handle_reinit() during
every Diag Reset (mpr_reinit, e.g. from mprsas_tm_timeout
mpr_sas.c:1255-1270) β deliberately completes all outstanding commands with
cm->cm_reply = NULL and then invokes cm->cm_complete(sc, cm)
(mpr_sas.c:1173-1207).
If CAM error recovery has an XPT_RESET_DEV in flight (mprsas_action_resetdev
β tm->cm_complete = mprsas_resetdev_complete, mpr_sas.c:3372) at the moment
the controller is diag-reset, mprsas_resetdev_complete runs with
resp == NULL and faults on resp->IOCStatus β kernel panic.
Device error storms classically produce both events together: CAM escalates to
XPT_RESET_DEV while the HBA simultaneously needs a controller reset. Note
xpt_done(ccb) at mpr_sas.c:3426 is never reached, and the TM is never freed.
Fix
Add the same resp == NULL guard the sibling handlers have (see fix.diff);
on NULL, complete the ccb with CAM_REQ_CMP_ERR/CAM_SCSI_BUS_RESET and free
the TM.
Guest verification attempt
No SAS3 controller in the QEMU guest (pciconf -l: no LSI/Avago device;
camcontrol devlist: only ata0/ata1/xpt0 buses). mpr is compiled in
(pci/mpr registered) but mpr_attach never matches, so no XPT_RESET_DEV can
ever reach mprsas_action_resetdev. Not reproducible on this hardware; the
missing guard is provable from source with certainty. FreeBSD's mpr(4) carries
the identical defect in mprsas_resetdev_complete.
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 guard; cannot be exercised on this guest (no SAS3 HBA).
findings/poc/DF-3801/fix.diff
Confirmed kernel references
Detail
Evidence (decisive lines)
VERDICT.md (path:line proof), env.txt (no SAS3 HBA), fix.diff (NULL guard)
PoC changes
Trigger requires CAM error recovery racing a controller diag reset on real SAS3 hardware; run.sh records the hardware gate.
Verified recommended fix
Add resp == NULL guard (complete ccb with CAM_SCSI_BUS_RESET/CAM_REQ_CMP_ERR and free the TM), matching mprsas_target_reset_complete.
Verdict
mprsas_resetdev_complete (mpr_sas.c:3384) is the only TM completion handler in the file without a cm_reply==NULL guard; it dereferences resp->IOCStatus at mpr_sas.c:3412-3413. mprsas_complete_all_commands (mpr_sas.c:1173-1207) invokes cm_complete with cm_reply=NULL during every Diag Reset, so an XPT_RESET_DEV TM outstanding at reset time panics the kernel. Not reproduced on the guest: mpr driver present (pci/mpr) but no SAS3 PCI device exists, so no XPT_RESET_DEV can reach the SIM. The missing guard is certain from source; sibling handlers at mpr_sas.c:1300/1395/1545/383/582/657 all have it.
No comments yet.