# DF-1185 — arcmsr_iop_message_xfer heap OOB write

## Bug (confirmed in source)
`sys/dev/raid/arcmsr/arcmsr.c:2604-2624` (function
`arcmsr_iop_message_xfer`):

```c
transfer_len = pccb->csio.dxfer_len;        // attacker-controlled
...
if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) {  // ONLY rejects too-large
    retvalue = ARCMSR_MESSAGE_FAIL;
    goto message_out;
}
pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer;  // buffer is dxfer_len bytes
...
case ARCMSR_MESSAGE_READ_RQBUFFER: {
    u_int8_t *ptmpQbuffer = pcmdmessagefld->messagedatabuffer;   // offset 28
    int32_t allxfer_len = 0;
    ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
    while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex)
        && (allxfer_len < 1031)) {
        pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex];
        *ptmpQbuffer = *pQbuffer;        // writes up to 1031 bytes
        ...
        ptmpQbuffer++;
        allxfer_len++;
    }
    ...
    pcmdmessagefld->cmdmessage.Length = allxfer_len;       // also writes at offset
    pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
}
```

`struct CMD_MESSAGE_FIELD` (`arcmsr.h:207-210`):
```c
struct CMD_MESSAGE_FIELD {
    struct CMD_MESSAGE cmdmessage;       // 28 bytes
    u_int8_t messagedatabuffer[1032];
};
```

The function casts the user-supplied CAM buffer of `dxfer_len` bytes to
a `struct CMD_MESSAGE_FIELD *` (which is ~1060 bytes) and then writes
into `messagedatabuffer` (offset 28).  If `dxfer_len = 32`, the writes
go up to **1031 bytes past the actual 32-byte CAM allocation** — CWE-787
heap OOB write.  The write content comes from the prior `WRITE_WQBUFFER`
queue (attacker-controlled via a preceding
`ARCMSR_MESSAGE_WRITE_WQBUFFER` ioctl), so an attacker who can prime the
queue can choose most of the bytes written.

## Caller chain (arcmsr.c)
```c
arcmsr_action() case XPT_SCSI_IO:
    if (target == 16)
        arcmsr_handle_virtual_command(acb, pccb);   // line 3010
...
arcmsr_handle_virtual_command():
    case WRITE_BUFFER:
    case READ_BUFFER:
        arcmsr_iop_message_xfer(acb, pccb);         // line 2978
```

The `target_id == 16` "virtual device for iop message transfer" exists
only on a SCSI bus registered by arcmsr's `arcmsr_attach()` — which only
runs when arcmsr's PCI probe finds an Areca RAID controller (PCI vendor
0x17D3).

## Trigger model
- Requires a real Areca RAID controller (none on this guest).
- Requires root or operator-group access to the arcmsr-backed
  `/dev/passN` (mode 0600 root:operator — verified on guest).  The maxx
  user (uid 1001, not in operator) cannot open any pass device.
- CVSS `AV:L/AC:L/PR:H/UI:N/S:U:C:H/I:H/A:H` — root/operator → kernel
  memory corruption.  Not an unprivileged-local-to-root escalation.

## On this guest
The arcmsr driver IS compiled into the GENERIC kernel (config line 113)
and IS loaded, but with no Areca hardware on the PCI bus, no acb is
allocated, no SIM is registered, and no `/dev/passN` is backed by
arcmsr.  The only pass device (pass0) is backed by ahci for the QEMU
DVD-ROM, so a CDB with target_id=16 goes to ahci, not arcmsr.

`harness.c` builds a CAM XPT_SCSI_IO CCB targeting `/dev/pass0` with
target_id=16 and `dxfer_len=32`.  As maxx it fails to open the device
(EPERM, mode 0600).  As root it would return CAM_SEL_TIMEOUT (ahci
has no target 16) — confirming the trigger mechanism is exercisable
from userspace AND that the kernel side never reaches
`arcmsr_iop_message_xfer` on this guest.

## Reproduce
```
ssh dfbsd-maxx "cd poc/DF-1185 && ./build.sh && ./run.sh"  # EPERM
ssh dfbsd     "cd /root/poc/DF-1185 && ./run.sh"           # CAM_SEL_TIMEOUT
```

## Recommended fix
Require `transfer_len == sizeof(struct CMD_MESSAGE_FIELD)` (not just
`<=`) so the aliasing cast is always within the CAM allocation.  Full
patch in `fix.diff`. **Matches** the finding proposal.
