diff --git a/sys/dev/netif/bwn/siba/siba_core.c b/sys/dev/netif/bwn/siba/siba_core.c --- a/sys/dev/netif/bwn/siba/siba_core.c +++ b/sys/dev/netif/bwn/siba/siba_core.c @@ -1405,7 +1405,25 @@ siba_sprom_r123(sprom, buf); } else if (siba->siba_chipid == 0x4321) { sprom->rev = 4; - siba_sprom_r45(sprom, buf); + /* + * rev 4/5/8 parsers index SPROM words beyond + * SIBA_SPROMSIZE_R123. Make sure the buffer we + * actually hold is large enough before dispatching + * to one of them, otherwise they read past the + * allocation. This can happen when a R123-sized + * image passes CRC (above) but its rev byte claims + * a later revision. + */ + if (siba->siba_spromsize < SIBA_SPROMSIZE_R4) { + device_printf(siba->siba_dev, + "SPROM rev %d requires %d words but only %d " + "read; falling back to rev 1\n", sprom->rev, + SIBA_SPROMSIZE_R4, siba->siba_spromsize); + sprom->rev = 1; + siba_sprom_r123(sprom, buf); + } else { + siba_sprom_r45(sprom, buf); + } } else { switch (sprom->rev) { case 1: @@ -1415,10 +1433,30 @@ break; case 4: case 5: - siba_sprom_r45(sprom, buf); + if (siba->siba_spromsize < SIBA_SPROMSIZE_R4) { + device_printf(siba->siba_dev, + "SPROM rev %d requires %d words but only " + "%d read; falling back to rev 1\n", + sprom->rev, SIBA_SPROMSIZE_R4, + siba->siba_spromsize); + sprom->rev = 1; + siba_sprom_r123(sprom, buf); + } else { + siba_sprom_r45(sprom, buf); + } break; case 8: - siba_sprom_r8(sprom, buf); + if (siba->siba_spromsize < SIBA_SPROMSIZE_R4) { + device_printf(siba->siba_dev, + "SPROM rev %d requires %d words but only " + "%d read; falling back to rev 1\n", + sprom->rev, SIBA_SPROMSIZE_R4, + siba->siba_spromsize); + sprom->rev = 1; + siba_sprom_r123(sprom, buf); + } else { + siba_sprom_r8(sprom, buf); + } break; default: device_printf(siba->siba_dev,