# DF-4332 — hptmv read-only GUI ioctls walk array state with no driver lock (UAF race)

Files (walk sites under audit): `sys/dev/raid/hptmv/gui_lib.c`
* `get_array_flag` `:163-197` (`pMember[i]` derefs)
* `calc_rebuild_progress` `:208-224`
* `get_array_info`/`get_array_info_v2` `:243-245, 265-267`
* `hpt_get_logical_devices` `:496` (`while (pLogical->pParent)` walk)
* dispatcher: `hpt_default_ioctl` `:1134-1447`

Race counterpart (out-of-file, root cause of the missing serialization):
`sys/dev/raid/hptmv/ioctl.c:312-329` routes HPT_IOCTL_GET_* "directly" with
**no `lock_driver()`**, and `HPT_IOCTL_DELETE_ARRAY`
(`ioctl.c:219-263` → `hpt_delete_array` → blob `fDeleteArray`) also never
takes the driver lock, while the mutating ioctls
(CREATE_ARRAY / SET_* / ADD_*) *do* run under `lock_driver_idle` (`:357-371`).
`gui_lib.c`'s own header states the contract plainly
(`gui_lib.c:36-37`): "This implementation doesn't use any synchronization; the
caller must assure the proper context when calling these functions" — the
caller does not, for the whole read-only family and for DELETE_ARRAY.

## Trigger (requires HighPoint RocketRAID 18xx hardware)

Two concurrent root sysctl writes to `hw.hptmv.status`
(`hptproc.c:614-617`, gated by `SYSCAP_NOSYSCTL_WR`, `kern_sysctl.c:1446`):

* thread A: `HPT_IOCTL_GET_DEVICE_INFO {id = array X}` →
  `get_array_info` walks `X->u.array.pMember[0..bArnMember-1]` and copies
  `VDEV_TO_ID(pMember)` / `ArrayName` / flags to userspace;
* thread B: `HPT_IOCTL_DELETE_ARRAY {id = X}` → `fDeleteArray` frees X's
  member array tables (`mArFreeArrayTable`, cf. the mirrored free in
  `gui_lib.c:802-809`) and stamps.

Thread A then dereferences freed `PVDevice`s: UAF read → panic, or — if the
freed slab is untouched — copies **kernel heap pointers**
(`VDEV_TO_ID` = truncated `PVDevice`) and stale slab contents out via
`hptproc.c:315`.

## Guest status — NOT REPRODUCIBLE HERE

The audit guest has no HighPoint/Marvell PCI device:

```
# pciconf -l | grep -icE "11ab|hpt"
0
# sysctl -n hw.hptmv.status
sysctl: unknown oid 'hw.hptmv.status'     # hpt_status OID registered from attach
```

With `gIal_Adapter == NULL` the ioctl path NULL-derefs before reaching
gui_lib.c (already known: DF-1853). Verdict: **inconclusive — hardware
absent**; the race is established by code inspection only.

## Fix direction (not validated on this guest)

Serialize the read-only dispatch group and `DELETE_ARRAY` under the same
`lock_driver()`/`lock_driver_idle(pAdapter)` regime as the mutating ioctls
(one-line summary; a reviewed patch needs care: GET_* currently run lock-free
by design comment `ioctl.c:316`).
