]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: iwlwifi: mld: validate sta_mask before ffs() in BA session handlers
authorJunrui Luo <moonafterrain@outlook.com>
Thu, 2 Apr 2026 06:48:07 +0000 (14:48 +0800)
committerMiri Korenblit <miriam.rachel.korenblit@intel.com>
Tue, 26 May 2026 12:17:08 +0000 (15:17 +0300)
Three BA session handlers use ffs(ba_data->sta_mask) - 1 to derive a
station ID without checking that sta_mask is non-zero. When sta_mask is
zero, ffs() returns 0 and the subtraction wraps to 0xFFFFFFFF, causing
an out-of-bounds access on fw_id_to_link_sta[].

Add WARN_ON_ONCE(!ba_data->sta_mask) guards before each ffs() call,
consistent with the existing check in iwl_mld_ampdu_rx_start().

Reported-by: Yuhao Jiang <danisjiang@gmail.com>
Cc: stable@vger.kernel.org
Signed-off-by: Junrui Luo <moonafterrain@outlook.com>
Link: https://patch.msgid.link/SYBPR01MB788115C6CE873271A9A15A25AF51A@SYBPR01MB7881.ausprd01.prod.outlook.com
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
drivers/net/wireless/intel/iwlwifi/mld/agg.c

index 3bf36f8f687425f575abc437240ef1dc13ed04a8..e3627ad0321c8b3e41d491ef76a3213b1c702ec1 100644 (file)
@@ -64,6 +64,9 @@ static void iwl_mld_release_frames_from_notif(struct iwl_mld *mld,
        }
 
        /* pick any STA ID to find the pointer */
+       if (WARN_ON_ONCE(!ba_data->sta_mask))
+               goto out_unlock;
+
        sta_id = ffs(ba_data->sta_mask) - 1;
        link_sta = rcu_dereference(mld->fw_id_to_link_sta[sta_id]);
        if (WARN_ON_ONCE(IS_ERR_OR_NULL(link_sta) || !link_sta->sta))
@@ -166,6 +169,9 @@ void iwl_mld_del_ba(struct iwl_mld *mld, int queue,
                goto out_unlock;
 
        /* pick any STA ID to find the pointer */
+       if (WARN_ON_ONCE(!ba_data->sta_mask))
+               goto out_unlock;
+
        sta_id = ffs(ba_data->sta_mask) - 1;
        link_sta = rcu_dereference(mld->fw_id_to_link_sta[sta_id]);
        if (WARN_ON_ONCE(IS_ERR_OR_NULL(link_sta) || !link_sta->sta))
@@ -347,6 +353,9 @@ static void iwl_mld_rx_agg_session_expired(struct timer_list *t)
        }
 
        /* timer expired, pick any STA ID to find the pointer */
+       if (WARN_ON_ONCE(!ba_data->sta_mask))
+               goto unlock;
+
        sta_id = ffs(ba_data->sta_mask) - 1;
        link_sta = rcu_dereference(ba_data->mld->fw_id_to_link_sta[sta_id]);