⬢ DragonFlyBSD Kernel Audit
DF-5506 / fix.diff
← back to finding ↓ download raw
--- a/sys/bus/smbus/amdsmb/amdsmb.c
+++ b/sys/bus/smbus/amdsmb/amdsmb.c
@@ -211,9 +211,9 @@
 {
 	int timeout = 500;
 
-	while (timeout-- && AMDSMB_ECINB(sc, EC_SC) & EC_SC_IBF)
+	while (timeout-- > 0 && AMDSMB_ECINB(sc, EC_SC) & EC_SC_IBF)
 		DELAY(1);
-	if (timeout == 0) {
+	if (timeout < 0) {
 		device_printf(sc->smbus, "timeout waiting for IBF to clear\n");
 		return (1);
 	}
@@ -225,9 +225,9 @@
 {
 	int timeout = 500;
 
-	while (timeout-- && ~AMDSMB_ECINB(sc, EC_SC) & EC_SC_OBF)
+	while (timeout-- > 0 && ~AMDSMB_ECINB(sc, EC_SC) & EC_SC_OBF)
 		DELAY(1);
-	if (timeout == 0) {
+	if (timeout < 0) {
 		device_printf(sc->smbus, "timeout waiting for OBF to set\n");
 		return (1);
 	}
@@ -281,20 +281,23 @@
 	int error, count;
 
 	AMDSMB_LOCK_ASSERT(sc);
-	amdsmb_ec_read(sc, SMB_PRTCL, &temp);
+	if (amdsmb_ec_read(sc, SMB_PRTCL, &temp) != 0)
+		return (SMB_EBUSERR);
 	if (temp != 0)
 	{
 		count = 10000;
 		do {
 			DELAY(500);
-			amdsmb_ec_read(sc, SMB_PRTCL, &temp);
-		} while (temp != 0 && count--);
-		if (count == 0)
+			if (amdsmb_ec_read(sc, SMB_PRTCL, &temp) != 0)
+				return (SMB_EBUSERR);
+		} while (temp != 0 && count-- > 0);
+		if (count < 0)
 			return (SMB_ETIMEOUT);
 	}
 
 	sts = 0;
-	amdsmb_ec_read(sc, SMB_STS, &sts);
+	if (amdsmb_ec_read(sc, SMB_STS, &sts) != 0)
+		return (SMB_EBUSERR);
 	sts &= SMB_STS_STATUS;
 	AMDSMB_DEBUG(kprintf("amdsmb: STS=0x%x\n", sts));
 
@@ -531,6 +534,10 @@
 
 	if ((error = amdsmb_wait(sc)) == SMB_ENOERR) {
 		amdsmb_ec_read(sc, SMB_BCNT, &len);
+		if (len > 32)
+			len = 32;	/* hw count is untrusted (DF-1091 family) */
+		if (len > *count)
+			len = *count;	/* never report more than we stored */
 		for (i = 0; i < len; i++) {
 			amdsmb_ec_read(sc, SMB_DATA + i, &data);
 			if (i < *count)