1: 85a8b596cf3c ! 1: b4d921e0b2f2 wifi: mwifiex: bound SDIO fw dump count by memory table size @@ Metadata ## Commit message ## wifi: mwifiex: bound SDIO fw dump count by memory table size  - mwifiex_sdio_fw_dump() reads the number of memory regions (dump_num) from - a device register and uses it to index the static 15-entry - mem_type_mapping_tbl[] without any bounds check. A bogus device can - report a dump_num larger than the table, making each loop iteration - store a vmalloc pointer and a device-controlled size past the end - of the table into adjacent .data (up to ~5.7KB when dump_num is 255). + mwifiex_sdio_fw_dump() reads the number of memory regions (dump_num) + from a device register and uses it to index the static 15-entry + mem_type_mapping_tbl[] without any bounds check. A bogus device can + report a dump_num larger than the table; each out-of-table loop + iteration then reads entry->mem_name and entry->done_flag and stores + a vmalloc pointer and a device-controlled size past the end of the + table, into adjacent .data (up to ~5.6KiB when dump_num is 255).  The dump path runs after command timeouts or firmware crashes, so a - bogus device can first force an error to trigger the dump and - then report a bogus dump_num. + bogus device can first force an error to trigger the dump and then + report a bogus dump_num.  - Aborting the dump only loses the firmware snapshot; the card reset - that follows is unaffected, so error recovery still completes. + Limit dump_num to the table size instead of aborting the dump. This + is not expected to change the behavior on normal devices.  Discovered by Atuin - Automated Vulnerability Discovery Engine.  @@ drivers/net/wireless/marvell/mwifiex/sdio.c: static void mwifiex_sdio_fw_dump(st mwifiex_dbg(adapter, ERROR, "SDIO read memory length err\n"); goto done; } -+ if (dump_num > ARRAY_SIZE(mem_type_mapping_tbl)) { -+ mwifiex_dbg(adapter, ERROR, -+ "Invalid fw dump num: %d\n", dump_num); -+ goto done; -+ } ++ /* Limit the dump count to the memory table size */ ++ if (dump_num > ARRAY_SIZE(mem_type_mapping_tbl)) ++ dump_num = ARRAY_SIZE(mem_type_mapping_tbl);  /* Read the length of every memory which will dump */ for (idx = 0; idx < dump_num; idx++) {