DF-4014 / fix.diff
diff --git a/sys/dev/raid/mps/mps_user.c b/sys/dev/raid/mps/mps_user.c --- a/sys/dev/raid/mps/mps_user.c 2026-09-17 14:20:44.418606509 +0000 +++ b/sys/dev/raid/mps/mps_user.c 2026-09-17 14:20:44.434606304 +0000 @@ -838,9 +838,18 @@ err = mps_wait_command(sc, cm, 30); if (err != 0) { + /* + * DF-4014: on timeout the command is still owned + * by the chip; freeing it hands a live SMID back + * to the free list while the chip still DMAs into + * it (use-after-free). Abandon it instead — it + * is reclaimed on the next diag reset (same policy + * as the config-page timeouts). + */ err = EIO; mps_dprint(sc, MPS_FAULT, "%s: task management failed", __func__); + goto Ret; } /* * Copy the reply data and sense data to user space. @@ -972,13 +981,21 @@ mps_lock(sc); + /* + * DF-4014: mps_wait_command() returning ETIMEDOUT leaves the + * command enqueued with the chip and its SGL pointing at + * cm->cm_data. The old error path kfree'd cm->cm_data and + * mps_free_command()'d the slot immediately — + * free-while-in-flight. Abandon the command (reclaimed at the + * next diag reset). + */ err = mps_wait_command(sc, cm, 30); if (err) { mps_printf(sc, "%s: invalid request: error %d\n", __func__, err); mps_unlock(sc); - goto RetFreeUnlocked; + goto Ret; } /* |