# DF-3727 VERDICT

## Finding
`ciss_disable_adapter()` (`sys/dev/raid/ciss/ciss.c:3463-3507`) declares

```c
    cr_qhead_t          qh;              /* ciss.c:3465 */
```

and — unlike every other user of a local `cr_qhead_t` in this driver
(`ciss_intr` ciss.c:2109, `ciss_perf_msi_intr` ciss.c:2136, `ciss_cam_poll`
ciss.c:3194, `ciss_poll_request` ciss.c:2304) — **never calls
`STAILQ_INIT(&qh)`**. The first busy request is then enqueued:

```c
    ciss_enqueue_complete(cr, &qh);      /* ciss.c:3483 */
```

which expands (`sys/sys/queue.h:306-310`) to

```c
    (elm)->cr_link = NULL;
    *(head)->stqh_last = (elm);          /* WRITE through garbage pointer */
```

`STAILQ_INSERT_TAIL` in DragonFly has **no NULL/stqh_last guard**, so the
very first store writes the kernel address of the `ciss_request` through
whatever value the uninitialized stack slot holds. The subsequent
`ciss_dequeue_complete(sc, &qh)` (ciss.c:3487) additionally dereferences the
equally-uninitialized `qh.stqh_first` (`STAILQ_REMOVE_HEAD` reads
`STAILQ_NEXT(STAILQ_FIRST(head))` → wild read).

**Upstream divergence (proof this is a bug, not intent):** FreeBSD's
`ciss_disable_adapter()` contains `STAILQ_INIT(&qh);` right after the
declaration block (FreeBSD src sys/dev/ciss/ciss.c:3581). DragonFly's copy
(imported 2012 from FreeBSD 1.113 and diverging since) is missing it.

## Reachability
`ciss_disable_adapter` is called from `ciss_periodic()` (ciss.c:3395) when
the config-table heartbeat value is unchanged for 3 consecutive 10-second
ticks (ciss.c:3389-3398) — i.e. the adapter wedged/locked up — and at least
one request is BUSY (ciss.c:3477). On a system with real HP Smart Array
hardware under I/O load this is the standard "failing adapter" path, not an
exotic one: every hung controller with queued I/O that trips the 30 s
heartbeat watchdog executes this function.

## Primitive
- **Write:** `*(uint64_t*)GARBAGE = &sc->ciss_request[i]` — an
  uncontrolled-but-groomable kernel pointer value written to a
  stack-garbage-controlled kernel address. The stack slot in
  `ciss_disable_adapter`'s frame inherits whatever the prior user of that
  callout-thread stack depth left there (callout callbacks, earlier syscalls
  on the softclock thread); the harness demonstrates exactly this grooming.
- **Read:** list traversal through garbage `stqh_first` on dequeue.

Impact ceiling: kernel memory corruption → panic to potential exploitation
depending on the groomed value (the write VALUE is a kernel heap pointer,
limiting but not eliminating exploitation; the wild READ is a near-certain
panic).

## Verification (no HP Smart Array on the audit guest)
Faithful userspace replica (`harness.c`) with the exact `queue.h` macro text:
- `build.log`: gcc 8.3 emits `'qh.stqh_last' is used uninitialized in this
  function [-Wuninitialized]` on the -O2 build — the compiler independently
  confirms the defect.
- `run.log` (also run.2/run.3, 3/3 stable): the -O0 build lands the groom
  deterministically; output shows `[WILD WRITE] *(0x51000000) = 0x4023c0`
  (request pointer written at the groomed address) and
  `[BUG REPRODUCED]`.
- `-DFIXED` replica (adds `STAILQ_INIT(&qh)`): no write through garbage,
  list head consistent, `[FIXED]`.

## Fix validation
- `fix.diff`: one-line addition of `STAILQ_INIT(&qh);` — identical to
  FreeBSD upstream.
- `fix_apply.log`: `patch --dry-run` succeeds on the guest's clean
  `/usr/src` copy.
- `fix_build.log`: with **all 7 ciss pass-2 fixes applied**, `ciss.ko`
  rebuilt at `-Werror`, link rc=0.
- Harness `-DFIXED` run in `run.log`: wild write GONE (baseline reproduces,
  patched replica does not).

**Bottom line: reproduced (harness-level, hardware-gated path), kernel
wild-write primitive via uninitialized stack variable; fix is the missing
one-line STAILQ_INIT, validated at compile + replica level.**

## Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest `make -j6 nativekernel KERNCONF=X86_64_GENERIC` completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
