wifi: iwlwifi: mvm: validate TX_CMD response layout

TX_CMD parsing uses frame_count to walk status entries and then
read the trailing SCD SSN. Make the minimum-length check follow
that exact runtime layout calculation before parsing the payload.

For new TX API, reject TX_CMD responses with frame_count != 1 and
warn/return in the aggregation handler to document that aggregated
accounting is expected via BA notifications.

Assisted-by: GitHubCopilot:gpt-5.3-codex
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20260715215523.0474ee89bab9.I84f151aabecb8921b587da092f29f78c47128f0f@changeid
This commit is contained in:
Emmanuel Grumbach 2026-07-15 21:57:03 +03:00 committed by Miri Korenblit
parent 7786233bff
commit 8d70881707

View File

@ -1544,6 +1544,17 @@ static inline u32 iwl_mvm_get_scd_ssn(struct iwl_mvm *mvm,
return val & 0xFFF;
}
static inline size_t iwl_mvm_tx_resp_min_len(struct iwl_mvm *mvm,
struct iwl_tx_resp *tx_resp)
{
struct agg_tx_status *agg_status =
iwl_mvm_get_agg_status(mvm, tx_resp);
/* The aggregate response ends with a trailing SCD SSN __le32 word. */
return (u8 *)(agg_status + tx_resp->frame_count) - (u8 *)tx_resp +
sizeof(__le32);
}
static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
struct iwl_rx_packet *pkt)
{
@ -1847,6 +1858,9 @@ static void iwl_mvm_rx_tx_cmd_agg(struct iwl_mvm *mvm,
int queue = SEQ_TO_QUEUE(sequence);
struct ieee80211_sta *sta;
if (WARN_ON_ONCE(iwl_mvm_has_new_tx_api(mvm)))
return;
if (WARN_ON_ONCE(queue < IWL_MVM_DQA_MIN_DATA_QUEUE &&
(queue != IWL_MVM_DQA_BSS_CLIENT_QUEUE)))
return;
@ -1881,6 +1895,26 @@ void iwl_mvm_rx_tx_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_tx_resp *tx_resp = (void *)pkt->data;
size_t min_len;
if (IWL_FW_CHECK(mvm, !tx_resp->frame_count,
"invalid TX_CMD frame_count %u\n",
tx_resp->frame_count))
return;
if (IWL_FW_CHECK(mvm,
iwl_mvm_has_new_tx_api(mvm) &&
tx_resp->frame_count != 1,
"invalid TX_CMD frame_count %u for new TX API\n",
tx_resp->frame_count))
return;
min_len = iwl_mvm_tx_resp_min_len(mvm, tx_resp);
if (IWL_FW_CHECK(mvm, iwl_rx_packet_payload_len(pkt) < min_len,
"invalid TX_CMD len %u (frame_count %u, min %zu)\n",
iwl_rx_packet_payload_len(pkt), tx_resp->frame_count,
min_len))
return;
if (tx_resp->frame_count == 1)
iwl_mvm_rx_tx_cmd_single(mvm, pkt);