⬢ DragonFlyBSD Kernel Audit
DF-2298 / fix.diff
← back to finding ↓ download raw
--- a/sys/bus/firewire/fwdma.c	2026-10-12 07:05:45.182825872 +0000
+++ b/sys/bus/firewire/fwdma.c	2026-10-12 07:05:55.026698338 +0000
@@ -150,6 +150,18 @@
 	bus_size_t ssize;
 	int nseg;
 
+	/*
+	 * esize and n come from the FW_SSTBUF ioctl (userspace ints,
+	 * fwdev.c fwdev_allocbuf).  esize == 0 divides by zero in
+	 * rounddown() below; esize < 0 makes ssize == 0 and divides by
+	 * zero in howmany(); n <= 0 (e.g. nchunk*npacket == 0 after
+	 * signed overflow) makes nseg == 0 so the returned object has a
+	 * zero-length seg[] array that callers index out of bounds
+	 * (fwdma.h fwdma_v_addr/fwdma_bus_addr).
+	 */
+	if (esize <= 0 || n <= 0)
+		return (NULL);
+
 	if (esize > PAGE_SIZE) {
 		/* round up to PAGE_SIZE */
 		esize = ssize = roundup2(esize, PAGE_SIZE);
--- a/sys/bus/firewire/fwdev.c	2026-10-12 07:05:45.182825872 +0000
+++ b/sys/bus/firewire/fwdev.c	2026-10-12 07:20:59.630843407 +0000
@@ -97,6 +97,17 @@
 {
 	int i;
 
+	/*
+	 * FW_SSTBUF bcopy()s this struct straight from userspace
+	 * (fwdev.c fw_ioctl) with no validation.  Reject degenerate and
+	 * overflow-capable values before they reach the kmallocs and the
+	 * nchunk*npacket element count handed to fwdma_malloc_multiseg().
+	 */
+	if (b->psize == 0 || b->psize > 0x7fffffff ||
+	    b->nchunk == 0 || b->npacket == 0 ||
+	    b->npacket > (unsigned int)0x7fffffff / b->nchunk)
+		return (EINVAL);
+
 	if (q->flag & (FWXFERQ_RUNNING | FWXFERQ_EXTBUF))
 		return(EBUSY);