--- 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);