DragonFlyBSD Kernel Audit
DF-1258 / fix.diff
← back to finding ↓ download raw
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);