wifi: iwlwifi: fw: validate SMEM response size

The SMEM parsers cast firmware response payloads directly to shared
memory configuration structures. A short response can leave fields
outside the received payload while the driver still dereferences them.

Check the response payload length before reading the base fields in
both parser variants. Require the full legacy extended layout before
reading internal TX FIFO data. Valid responses keep the same parsed
values.

Signed-off-by: Shahar Tzarfati <shahar.tzarfati@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20260715215523.fbdb0016a91d.I5f6c6e04589a24a233559191170ccb43372dee63@changeid
This commit is contained in:
Shahar Tzarfati 2026-07-15 21:57:05 +03:00 committed by Miri Korenblit
parent 408d7da382
commit a31b0e535f

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2012-2014, 2018-2021, 2025 Intel Corporation
* Copyright (C) 2012-2014, 2018-2021, 2025-2026 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@ -14,9 +14,17 @@ static void iwl_parse_shared_mem_22000(struct iwl_fw_runtime *fwrt,
{
struct iwl_shared_mem_cfg *mem_cfg = (void *)pkt->data;
int i, lmac;
int lmac_num = le32_to_cpu(mem_cfg->lmac_num);
u8 api_ver = iwl_fw_lookup_notif_ver(fwrt->fw, SYSTEM_GROUP,
SHARED_MEM_CFG_CMD, 0);
int lmac_num;
u8 api_ver;
if (IWL_FW_CHECK(fwrt, iwl_rx_packet_payload_len(pkt) <
offsetofend(struct iwl_shared_mem_cfg, lmac_smem[1]),
"bad shared mem notification size\n"))
return;
lmac_num = le32_to_cpu(mem_cfg->lmac_num);
api_ver = iwl_fw_lookup_notif_ver(fwrt->fw, SYSTEM_GROUP,
SHARED_MEM_CFG_CMD, 0);
/* Note: notification has 3 entries, but we only expect 2 */
if (IWL_FW_CHECK(fwrt, lmac_num > ARRAY_SIZE(fwrt->smem_cfg.lmac),
@ -30,7 +38,7 @@ static void iwl_parse_shared_mem_22000(struct iwl_fw_runtime *fwrt,
if (api_ver >= 4 &&
!IWL_FW_CHECK(fwrt, iwl_rx_packet_payload_len(pkt) < sizeof(*mem_cfg),
"bad shared mem notification size\n")) {
"bad shared mem notification size (v4)\n")) {
fwrt->smem_cfg.rxfifo2_control_size =
le32_to_cpu(mem_cfg->rxfifo2_control_size);
}
@ -53,6 +61,11 @@ static void iwl_parse_shared_mem(struct iwl_fw_runtime *fwrt,
struct iwl_shared_mem_cfg_v2 *mem_cfg = (void *)pkt->data;
int i;
if (IWL_FW_CHECK(fwrt, iwl_rx_packet_payload_len(pkt) <
offsetof(struct iwl_shared_mem_cfg_v2, rxfifo_addr),
"bad shared mem notification size\n"))
return;
fwrt->smem_cfg.num_lmacs = 1;
fwrt->smem_cfg.num_txfifo_entries = ARRAY_SIZE(mem_cfg->txfifo_size);
@ -67,6 +80,11 @@ static void iwl_parse_shared_mem(struct iwl_fw_runtime *fwrt,
/* new API has more data, from rxfifo_addr field and on */
if (fw_has_capa(&fwrt->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) {
if (IWL_FW_CHECK(fwrt, iwl_rx_packet_payload_len(pkt) <
sizeof(*mem_cfg),
"bad shared mem notification size (extend)\n"))
return;
BUILD_BUG_ON(sizeof(fwrt->smem_cfg.internal_txfifo_size) !=
sizeof(mem_cfg->internal_txfifo_size));