# DF-4010 — mpr_user_pass_thru leaks cm->cm_data (and its dmamap mapping) across the reinit path

## What

When a pass-thru command times out, `mpr_wait_command()` (sys/dev/raid/mpr/
mpr.c:3604-3618) performs an IOC reinit; if the reinit reallocated the queues
it sets `*cmp = NULL` to tell the caller the command was freed internally.
`mpr_user_pass_thru()` then takes the error branch:

```c
err = mpr_wait_command(sc, &cm, 30, CAN_SLEEP);   /* mpr_user.c:1050 */
if (err || (cm == NULL)) {
        ...
        goto RetFree;                             /* mpr_user.c:1052-1056 */
}
...
RetFree:
if (cm != NULL) {
        if (cm->cm_data)
                kfree(cm->cm_data, M_MPRUSER);    /* mpr_user.c:1149-1151 */
        mpr_free_command(sc, cm);
}
```

With `cm == NULL`, the `kfree(cm->cm_data)` is skipped — but the reinit path
that freed the command does **not** free `cm->cm_data` either:
`mpr_free_command()` (mprvar.h:568-611) merely sets `cm->cm_data = NULL`
without freeing. The user-controlled buffer (`kmalloc(MAX(DataSize,
DataOutSize))`, mpr_user.c:904-909 — DataSize/DataOutSize are raw user u32s)
is therefore **leaked**, together with any `bus_dmamap` mapping loaded onto
it (`mpr_map_command` → `bus_dmamap_load` during execution; the unload at
mpr_user.c:1067 only runs on the success path).

## Impact

Kernel-memory + dmamap resource leak from the operator-group ioctl surface.
Each cycle costs a 30 s timeout plus a full IOC reset, so exhaustion is slow
but unbounded; with large DataSize values (e.g. 64 MB) dozens of iterations
materially consume kmem and dmamap segments, degrading the driver for all
users (resource-exhaustion DoS). No memory-corruption shape found on this
path (contrast `mpr_user_command()`, which frees its `buf` unconditionally
at mpr_user.c:734-735 — the pass-thru path is the one that leaks).

## Verification posture

Source-level certain; live trigger needs an mpr controller whose commands
time out (30 s) followed by a reallocation-triggering reinit — no LSI SAS
hardware on the audit guest, so not live-reproduced (pack documents the
path:line trace; no replication needed for a Low resource-leak finding).

## Fix sketch

```diff
--- a/sys/dev/raid/mpr/mpr_user.c
+++ b/sys/dev/raid/mpr/mpr_user.c
@@
 	if (err || (cm == NULL)) {
 		mpr_printf(sc, "%s: invalid request: error %d\n", __func__,
 		    err);
+		if ((cm == NULL) && (data != NULL)) {   /* command freed by reinit */
+			/* cm_data was kmalloc'd here and is not freed by
+			 * mpr_free_command(); free it to avoid leaking it
+			 * (and its dmamap mapping) across the reset. */
+			...
+		}
 		goto RetFree;
 	}
```
(The clean fix requires mpr_wait_command/mpr_realloc to hand back the
orphaned `cm_data` pointer, or pass-thru to keep its own reference for the
error path.)
