⬢ DragonFlyBSD Kernel Audit
DF-4978 / fix.diff
← back to finding ↓ download raw
diff -ur a/sys/dev/misc/ipmi/ipmi.c b/sys/dev/misc/ipmi/ipmi.c
--- a/sys/dev/misc/ipmi/ipmi.c
+++ b/sys/dev/misc/ipmi/ipmi.c
@@ -446,6 +446,14 @@
 			return (error);
 		}
 		len = kreq->ir_replylen + 1;
+		/*
+		 * ir_replylen is transport-reported (BMC-controlled byte
+		 * count) and must never be trusted past the allocated
+		 * reply buffer (IPMI_MAX_RX for ioctl requests).
+		 */
+		if (kreq->ir_replybuflen != 0 &&
+		    len > kreq->ir_replybuflen + 1)
+			len = kreq->ir_replybuflen + 1;
 		if (recv->msg.data_len < len &&
 		    (cmd == IPMICTL_RECEIVE_MSG
 #ifdef IPMICTL_RECEIVE_MSG_32
diff -ur a/sys/dev/misc/ipmi/ipmi_ssif.c b/sys/dev/misc/ipmi/ipmi_ssif.c
--- a/sys/dev/misc/ipmi/ipmi_ssif.c
+++ b/sys/dev/misc/ipmi/ipmi_ssif.c
@@ -300,7 +300,13 @@
 	}
 
 done:
 	/* Save the total length and return success. */
+	/*
+	 * len accumulates every BMC-reported block byte count; clamp it
+	 * to the reply buffer or the ipmi.c consumer over-reads the heap.
+	 */
+	if (len > req->ir_replybuflen)
+		len = req->ir_replybuflen;
 	req->ir_replylen = len;
 	smbus_release_bus(smbus, dev);
 	return (1);