⬢ DragonFlyBSD Kernel Audit
DF-4424 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/virtual/virtio/block/virtio_blk.c
+++ b/sys/dev/virtual/virtio/block/virtio_blk.c
@@ -750,7 +750,13 @@ vtblk_alloc_disk(struct vtblk_softc *sc, struct virtio_blk_config *blkcfg)
 
 	sc->cdev->si_drv1 = sc;
 	sc->cdev->si_iosize_max = MAXPHYS;
+	/*
+	 * DF-4424: a negotiated SEG_MAX smaller than what a MAXPHYS
+	 * transfer can span overflows the per-queue sglist (EFBIG,
+	 * KASSERT panic under INVARIANTS, truncated descriptor chain
+	 * otherwise). Clamp the maximum transfer accordingly.
+	 */
+	if (sc->vtblk_max_nsegs < MAXPHYS / PAGE_SIZE + 1 + VTBLK_MIN_SEGMENTS)
+		sc->cdev->si_iosize_max =
+		    (sc->vtblk_max_nsegs - VTBLK_MIN_SEGMENTS) * PAGE_SIZE;
 	disk_setdiskinfo(&sc->vtblk_disk, &info);