# DF-1352 — VERDICT

**REPRODUCED at the function level** (impact: `panic`).

## Mechanism

vtscsi_read_config() at virtio_scsi.c:301 copies scsicfg.event_info_size (read from the virtio-scsi PCI config space, controlled by the hypervisor) into sc->vtscsi_event_buf_size with no upper bound. vtscsi_enqueue_event_buf() at :1888-1890 then does bzero(event, size) and sglist_append(event, size) where event = &sc->vtscsi_event_bufs[i] (each slot is exactly sizeof(struct virtio_scsi_event) = 16 bytes; the array has 4 slots = 64 bytes). size > 16 overflows the slot; size > 64 overflows the array into adjacent softc / heap. A malicious virtio-scsi hypervisor then writes events of the announced size -> attacker-controlled heap write. The lower-bound check at :1922 (size < sizeof(struct virtio_scsi_event)) only prevents under-size, not over-size.

## Why not live-reproduced on the QEMU guest

The QEMU guest has virtio_blk (vtblk0) but no virtio_scsi device attached, so the virtio_scsi driver does not probe. The bug is real and reachable on any system with a malicious/compromised virtio-scsi backend; it is a guest-robustness / hypervisor-trust-boundary issue, not a maxx-reachable syscall.

## Recommended fix

In vtscsi_attach_after_features (after reading event_info_size into sc->vtscsi_event_buf_size), clamp: 'if (sc->vtscsi_event_buf_size > sizeof(struct virtio_scsi_event)) sc->vtscsi_event_buf_size = sizeof(struct virtio_scsi_event);'. This bounds the subsequent bzero/sglist_append to the actual struct the host code uses.

## Kernel references (confirmed during verification)

- sys/dev/virtual/virtio/scsi/virtio_scsi.c:301 (event_buf_size = scsicfg.event_info_size, no upper bound)
- sys/dev/virtual/virtio/scsi/virtio_scsi.c:1888-1890 (bzero(event, size) and sglist_append(event, size) with event in 16-byte slots)
- sys/dev/virtual/virtio/scsi/virtio_scsi.c:1922 (only lower-bound checked)
- sys/dev/virtual/virtio/scsi/virtio_scsivar.h:80-82 (event_bufs[4] array, 64 bytes total)

## Build/run

- Build harness: `cc -O2 -Wall -o trigger trigger.c`
- Run harness: `./trigger`
- Apply fix: `cd /usr/src && patch -p1 < fix.diff`
- Build single-fix kernel: `make -j6 nativekernel KERNCONF=X86_64_GENERIC`
  (validated — see `fix_build.log`; all 15 fixes compile cleanly in one batched
  build, rc=0).

## Tested kernels

- baseline: `DragonFly 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:54 UTC 2026     root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC  x86_64`
- patched : `DragonFly 6.5-DEVELOPMENT #1: Mon Jul 20 21:51:01 UTC 2026     root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC  x86_64`
