diff --git a/sys/dev/raid/mfi/mfi.c b/sys/dev/raid/mfi/mfi.c --- a/sys/dev/raid/mfi/mfi.c +++ b/sys/dev/raid/mfi/mfi.c @@ -2950,6 +2950,10 @@ ioc = (struct mfi_ioc_packet *)arg; int adapter; + if (ioc->mfi_sge_count > MAX_IOCTL_SGE) { + error = EINVAL; + return (error); + } adapter = ioc->mfi_adapter_no; if (device_get_unit(sc->mfi_dev) == 0 && adapter != 0) { devclass = devclass_find("mfi"); @@ -3015,6 +3019,12 @@ for (i = 0; i < ioc->mfi_sge_count; i++) { addr = ioc->mfi_sgl[i].iov_base; len = ioc->mfi_sgl[i].iov_len; + if ((size_t)(temp - data) + len > cm->cm_len) { + error = EINVAL; + device_printf(sc->mfi_dev, + "SGE length exceeds data buffer\n"); + goto out; + } error = copyin(addr, temp, len); if (error != 0) { device_printf(sc->mfi_dev, @@ -3064,6 +3074,12 @@ for (i = 0; i < ioc->mfi_sge_count; i++) { addr = ioc->mfi_sgl[i].iov_base; len = ioc->mfi_sgl[i].iov_len; + if ((size_t)(temp - data) + len > cm->cm_len) { + error = EINVAL; + device_printf(sc->mfi_dev, + "SGE length exceeds data buffer\n"); + goto out; + } error = copyout(temp, addr, len); if (error != 0) { device_printf(sc->mfi_dev, @@ -3251,6 +3267,13 @@ temp = data; if (cm->cm_flags & MFI_CMD_DATAOUT) { for (i = 0; i < l_ioc.lioc_sge_count; i++) { + if ((size_t)(temp - data) + + l_ioc.lioc_sgl[i].iov_len > cm->cm_len) { + error = EINVAL; + device_printf(sc->mfi_dev, + "SGE length exceeds data buffer\n"); + goto out; + } error = copyin(PTRIN(l_ioc.lioc_sgl[i].iov_base), temp, l_ioc.lioc_sgl[i].iov_len); @@ -3293,6 +3316,13 @@ temp = data; if (cm->cm_flags & MFI_CMD_DATAIN) { for (i = 0; i < l_ioc.lioc_sge_count; i++) { + if ((size_t)(temp - data) + + l_ioc.lioc_sgl[i].iov_len > cm->cm_len) { + error = EINVAL; + device_printf(sc->mfi_dev, + "SGE length exceeds data buffer\n"); + goto out; + } error = copyout(temp, PTRIN(l_ioc.lioc_sgl[i].iov_base), l_ioc.lioc_sgl[i].iov_len);