DragonFlyBSD Kernel Audit
DF-1091 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/bus/smbus/amdsmb/amdsmb.c b/sys/bus/smbus/amdsmb/amdsmb.c
index 0000000..1111111 100644
--- a/sys/bus/smbus/amdsmb/amdsmb.c
+++ b/sys/bus/smbus/amdsmb/amdsmb.c
@@ -531,6 +531,21 @@
 
 	if ((error = amdsmb_wait(sc)) == SMB_ENOERR) {
 		amdsmb_ec_read(sc, SMB_BCNT, &len);
+		/*
+		 * SMB_BCNT is the byte count supplied by the SMBus/I2C
+		 * slave and is therefore attacker-controlled (a malicious
+		 * or spec-violating peripheral may return any value 0..255;
+		 * the SMBus 32-byte block limit does not apply in I2C
+		 * pass-through mode).  SMB_DATA is a 32-byte register file
+		 * (amdsmb.c:75: offsets 0x04..0x23); reading SMB_DATA+i for
+		 * i >= 32 overruns into SMB_BCNT/SMB_ALRM_A/SMB_ALRM_D and
+		 * follow-on EC space.  Clamp both the MMIO-read loop bound and the value
+		 * returned to the caller so the SMBus 32-byte block
+		 * invariant holds regardless of what the slave reports.
+		 * DF-1091.
+		 */
+		if (len > 32)
+			len = 32;
 		for (i = 0; i < len; i++) {
 			amdsmb_ec_read(sc, SMB_DATA + i, &data);
 			if (i < *count)