wifi: iwlwifi: mvm: validate MCC header before n_channels

MCC response parsing read n_channels from v8/v4/v3 response variants
before ensuring the payload contained the fixed response header.

Add a minimum payload-length check for each response version before
reading n_channels, and keep the existing exact-size validation for the
channels array payload.

Assisted-by: GitHub Copilot:gpt-5.3-codex
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Link: https://patch.msgid.link/20260714141909.cb2cef3d3e7e.Iee7b48614289da576de842157ad3730b7589a4b1@changeid
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
This commit is contained in:
Emmanuel Grumbach 2026-07-14 14:19:57 +03:00 committed by Miri Korenblit
parent b77c6f50b1
commit 77f33bed0c

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2012-2014, 2018-2019, 2021-2025 Intel Corporation
* Copyright (C) 2012-2014, 2018-2019, 2021-2026 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@ -416,6 +416,7 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
int ret, resp_ver;
u32 status;
int resp_len, n_channels;
unsigned int pkt_len;
u16 mcc;
if (WARN_ON_ONCE(!iwl_mvm_is_lar_supported(mvm)))
@ -431,6 +432,7 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
return ERR_PTR(ret);
pkt = cmd.resp_pkt;
pkt_len = iwl_rx_packet_payload_len(pkt);
resp_ver = iwl_fw_lookup_notif_ver(mvm->fw, IWL_ALWAYS_LONG_GROUP,
MCC_UPDATE_CMD, 0);
@ -439,9 +441,18 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
if (resp_ver >= 8) {
struct iwl_mcc_update_resp_v8 *mcc_resp_v8 = (void *)pkt->data;
if (IWL_FW_CHECK(mvm, pkt_len < sizeof(*mcc_resp_v8),
"MCC v8 response too short: %u\n", pkt_len)) {
resp_cp = ERR_PTR(-EINVAL);
goto exit;
}
n_channels = __le32_to_cpu(mcc_resp_v8->n_channels);
if (iwl_rx_packet_payload_len(pkt) !=
struct_size(mcc_resp_v8, channels, n_channels)) {
if (IWL_FW_CHECK(mvm,
pkt_len !=
struct_size(mcc_resp_v8, channels, n_channels),
"invalid MCC v8 response size: %u (n_channels=%d)\n",
pkt_len, n_channels)) {
resp_cp = ERR_PTR(-EINVAL);
goto exit;
}
@ -464,9 +475,18 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT)) {
struct iwl_mcc_update_resp_v4 *mcc_resp_v4 = (void *)pkt->data;
if (IWL_FW_CHECK(mvm, pkt_len < sizeof(*mcc_resp_v4),
"MCC v4 response too short: %u\n", pkt_len)) {
resp_cp = ERR_PTR(-EINVAL);
goto exit;
}
n_channels = __le32_to_cpu(mcc_resp_v4->n_channels);
if (iwl_rx_packet_payload_len(pkt) !=
struct_size(mcc_resp_v4, channels, n_channels)) {
if (IWL_FW_CHECK(mvm,
pkt_len !=
struct_size(mcc_resp_v4, channels, n_channels),
"invalid MCC v4 response size: %u (n_channels=%d)\n",
pkt_len, n_channels)) {
resp_cp = ERR_PTR(-EINVAL);
goto exit;
}
@ -489,9 +509,18 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
} else {
struct iwl_mcc_update_resp_v3 *mcc_resp_v3 = (void *)pkt->data;
if (IWL_FW_CHECK(mvm, pkt_len < sizeof(*mcc_resp_v3),
"MCC v3 response too short: %u\n", pkt_len)) {
resp_cp = ERR_PTR(-EINVAL);
goto exit;
}
n_channels = __le32_to_cpu(mcc_resp_v3->n_channels);
if (iwl_rx_packet_payload_len(pkt) !=
struct_size(mcc_resp_v3, channels, n_channels)) {
if (IWL_FW_CHECK(mvm,
pkt_len !=
struct_size(mcc_resp_v3, channels, n_channels),
"invalid MCC v3 response size: %u (n_channels=%d)\n",
pkt_len, n_channels)) {
resp_cp = ERR_PTR(-EINVAL);
goto exit;
}