]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: iwlwifi: mvm: validate MCC header before n_channels
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Tue, 14 Jul 2026 11:19:57 +0000 (14:19 +0300)
committerMiri Korenblit <miriam.rachel.korenblit@intel.com>
Tue, 14 Jul 2026 17:45:20 +0000 (20:45 +0300)
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>
drivers/net/wireless/intel/iwlwifi/mvm/nvm.c

index 953218f1e025a7343975b1b22239423029cde2cc..f76e57399c1f3323bbd700f74591d3dc84535cf4 100644 (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;
                }