# DF-4213 — 16-byte memcpy out of a 4-byte reply field publishes stale reply-frame bytes as RAID sync progress

- **File**: `sys/dev/disk/mpt/mpt_raid.c` (+ `sys/dev/disk/mpt/mpilib/mpi_raid.h` as the type evidence)
- **Lines**: 578–581 (copy), 1327–1343 (producer), 1521–1536 (print)
- **Class**: OOB read within allocation / stale DMA data disclosure to console (CWE-125 / CWE-908)
- **Hardware gate**: LSI MPT Fusion RAID controller during volume resync

## Root cause

`mpt_raid_reply_frame_handler()` copies the reply's action data into the
per-request result:

```c
	action_result = REQ_TO_RAID_ACTION_RESULT(req);
	memcpy(&action_result->action_data, &reply->ActionData,
	    sizeof(action_result->action_data));           /* 16 bytes */
```

`action_data` is a union whose largest member is `MPI_RAID_VOL_INDICATOR`
(two U64s = **16 bytes**), but `MSG_RAID_ACTION_REPLY.ActionData` is a
**single U32** (offset 0x18, struct ends 0x1C — `mpi_raid.h`). The copy
therefore reads 12 bytes *past the reply message* into the remainder of the
256-byte reply frame (`MPT_REPLY_SIZE`, `mpt.h:816`) — bytes the IOC never
wrote for this reply, i.e. **residue of whatever reply previously occupied
the frame slot**.

## Where the stale bytes go

`mpt_refresh_raid_vol()` issues `MPI_RAID_ACTION_INDICATOR_STRUCT` with
`addr=0, len=0` (`mpt_raid.c:1327`) — **no SGE data buffer is supplied**, so
the IOC has nowhere to write the 16-byte progress indicator the MPI spec
returns via the ActionData SGE. The code then treats the 4 real + 12 stale
bytes as `sync_progress` (1336–1343) and `mpt_refresh_raid_data()` prints
them to console/log:

```c
	mpt_vol_prt(mpt, mpt_vol, "%ju of %ju blocks remaining\n", left, total);
```

Result: (a) the resync-progress feature can never report correct numbers
(functional bug), and (b) 96 bits of stale IOC-reply DMA residue are
disclosed to any reader of the console/dmesg on every resync status tick
(15-min interval while resync runs). Leak value is low (reply frames are
IOC-written reply data, not kernel pointers), hence severity Low.

## Verification status

**untested — hardware-gated** (no MPT HBA on the guest, `env.txt`). Source
certainty: struct sizes read directly from `mpi_raid.h`.

## Fix

`fix.diff` bounds the copy to the field that actually exists. (The complete
functional fix would also supply a real SGE buffer for the indicator, as
mps(4)/mpr(4) do.)
