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)