# DF-4053 — VERDICT

**REPRODUCED on live hardware path** (functional manifestation) + source-certain
memory-corruption primitive that stock QEMU cannot fire (device-gated).

## What was reproduced (baseline stock kernel #0, real vtscsi0)

Guest booted from the with-src snapshot with a temporary QEMU launcher adding
`-device virtio-scsi-pci,id=scsi0` + `-drive vtscsi-disk.img (raw) -device
scsi-hd` (vm.sh untouched; the root disk needs an explicit `bootindex=0`,
otherwise SeaBIOS hangs — see README). virtio_scsi is in X86_64_GENERIC, so
vtscsi0 attaches with da0/pass0 (env.txt).

An out-of-range READ(10) (LBA 0xfffffff0 on the 64 MB disk) makes QEMU's
scsi-hd return CHECK CONDITION with an 18-byte sense (ILLEGAL REQUEST,
ASC 0x21). On the stock kernel:

    ccb_h.status     = 0xcc CAM_AUTOSNS_VALID CAM_SCSI_STATUS_ERROR
    csio.scsi_status = 0x02 (CHECK CONDITION)
    csio.sense_resid = 237        <- 255-237 = device returned 18 sense bytes
    csio.sense_data[0..31] = all 0x00
    camcontrol: "Sense Error Code 0x0"

The resid arithmetic proves `cmd_resp->sense_len == 18` (also 32-14=18 in the
sense_len=32 run), so `virtio_scsi.c:1383` executed the autosense branch — and
sense_data stayed all-zero anyway. The only way that happens with this code is
the memcpy at :1393 copying FROM the just-bzero()ed csio->sense_data INTO
cmd_resp->sense (dst/src swapped vs FreeBSD, verified against
freebsd-src release/11.4.0 `memcpy(&csio->sense_data, cmd_resp->sense, ...)`).
100% of runs.

## What is source-certain but device-gated (the heap-overflow half)

Copy length = `csio->sense_len - csio->sense_resid` = min(device sense_len,
ccb sense_len). Kernel periphs always use SSD_FULL_SIZE=32 (bounded, safe —
which is why the bug survived as "autosense mysteriously broken"). pass(4)
CAMIOCOMMAND merges the user ccb wholesale (`xpt_merge_ccb`) with sense_len
unvalidated up to 255 (the sense_len=255 run above shows the value flows
straight into the driver's math). A malicious virtio-scsi backend announcing
sense_len >= 97 then makes the driver write up to 255 bytes into
`vsr_uresp.cmd.sense[96]` (offset 12 of the union in struct vtscsi_request):
~159 bytes past the field — `vsr_callout` (function/arg pointers) and
`vsr_link` (TAILQ next/prev) are overwritten, and ~80 bytes land past the end
of the contigmalloc'd (~268-byte) request; the next dequeue's TAILQ_REMOVE
performs `*tqe_prev = tqe_next` through the corrupted link (write-what/where
shaped by 16 user-controlled CDB bytes at a known offset). Stock QEMU clamps
device sense_len to the negotiated sense_size=96, so the write half cannot be
fired by an unmodified QEMU 7.2 — it needs exactly the malicious-backend
threat model this driver is audited under (plus root access to /dev/pass0,
which caps severity at Medium, same tier as the device-only DF-1352).

## Fix validation (mandatory for memory-corruption class)

fix.diff restores the FreeBSD copy direction and bounds the length
(`MIN(len, sizeof(csio->sense_data))`), closing BOTH directions (the reversed
copy also OOB-reads the CCB when len > 32). Batched with DF-4054's fix, built
(`make nativekernel` RC=0), installed, rebooted into kernel #1 (fix_build.log).
Same trigger on the patched kernel:

    csio.sense_resid = 237
    csio.sense_data = 70 00 05 00 00 00 00 0a 00 00 00 00 21 00 00 00
    VERDICT: sense_data is REAL — sense key=0x05 ASC=0x21 ASCQ=0x00
    camcontrol: "ILLEGAL REQUEST asc:21,0 / Logical block address out of range"

Behavior delta is exactly the fix; resid math unchanged (device still returns
18 bytes). The zero-sense bug is GONE.

## Kernel references (re-verified line-by-line during verification)

- sys/dev/virtual/virtio/scsi/virtio_scsi.c:1392-1394 (swapped memcpy + bzero)
- sys/dev/virtual/virtio/scsi/virtio_scsi.h:53-60 (sense[96], packed resp)
- sys/dev/virtual/virtio/scsi/virtio_scsivar.h:113-137 (vsr_uresp/vsr_callout/vsr_link)
- sys/bus/cam/cam_ccb.h:602,606 (sense_data[32], sense_len u_int8_t)
- sys/bus/cam/scsi/scsi_all.h:911-953 (32-byte scsi_sense_data, SSD_FULL_SIZE)
- sys/bus/cam/scsi/scsi_pass.c:462-505 + xpt_merge_ccb (cam_xpt.c:3888-3898 — wholesale user ccb merge, no sense_len validation)
- FreeBSD release/11.4.0 sys/dev/virtio/scsi/virtio_scsi.c:1333-1335 (correct order)

## Classification

status=reproduced (the defect executes live on a real vtscsi0; the
memory-corruption direction is bounded away only by stock-QEMU's 96-byte
sense clamp + the root-only pass path), impact=none at runtime (no panic /
leak / escalation fired on stock QEMU — and none is possible without a
modified backend), confidence=certain. Severity filed as Medium (device-driven
heap OOB write, privileged-trigger preconditions; see finding markdown).

## 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.
