--- a/sys/bus/iicbus/iic.c +++ b/sys/bus/iicbus/iic.c @@ -355,6 +355,17 @@ break; case I2CRDWR: + /* + * DF-2312: nmsgs is a fully user-controlled u32 used directly + * as the multiplier of two M_WAITOK kmallocs (16*nmsgs and + * 8*nmsgs bytes); a single ioctl with nmsgs=0x8000000 requests + * a 2 GiB chunk and panics the kernel in _kmalloc ("malloc + * limit exceeded"). Cap it. + */ + if (d->nmsgs == 0 || d->nmsgs > 4096) { + error = EINVAL; + break; + } buf = kmalloc(sizeof(*d->msgs) * d->nmsgs, M_TEMP, M_WAITOK); usrbufs = kmalloc(sizeof(void *) * d->nmsgs, M_TEMP, M_ZERO | M_WAITOK); error = copyin(d->msgs, buf, sizeof(*d->msgs) * d->nmsgs);