OSDN Git Service

mac80211: fix memory leak on filtered powersave frames
authorFelix Fietkau <nbd@nbd.name>
Wed, 11 Nov 2020 18:33:57 +0000 (19:33 +0100)
committerJohannes Berg <johannes.berg@intel.com>
Thu, 12 Nov 2020 10:23:58 +0000 (11:23 +0100)
After the status rework, ieee80211_tx_status_ext is leaking un-acknowledged
packets for stations in powersave mode.
To fix this, move the code handling those packets from __ieee80211_tx_status
into ieee80211_tx_status_ext

Reported-by: Tobias Waldvogel <tobias.waldvogel@gmail.com>
Fixes: 3318111cf63d ("mac80211: reduce duplication in tx status functions")
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Link: https://lore.kernel.org/r/20201111183359.43528-1-nbd@nbd.name
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/status.c

index 6feb451..3485610 100644 (file)
@@ -49,7 +49,8 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
        int ac;
 
        if (info->flags & (IEEE80211_TX_CTL_NO_PS_BUFFER |
-                          IEEE80211_TX_CTL_AMPDU)) {
+                          IEEE80211_TX_CTL_AMPDU |
+                          IEEE80211_TX_CTL_HW_80211_ENCAP)) {
                ieee80211_free_txskb(&local->hw, skb);
                return;
        }
@@ -915,15 +916,6 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
                        ieee80211_mpsp_trigger_process(
                                ieee80211_get_qos_ctl(hdr), sta, true, acked);
 
-               if (!acked && test_sta_flag(sta, WLAN_STA_PS_STA)) {
-                       /*
-                        * The STA is in power save mode, so assume
-                        * that this TX packet failed because of that.
-                        */
-                       ieee80211_handle_filtered_frame(local, sta, skb);
-                       return;
-               }
-
                if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL) &&
                    (ieee80211_is_data(hdr->frame_control)) &&
                    (rates_idx != -1))
@@ -1150,6 +1142,12 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw,
                                                            -info->status.ack_signal);
                                }
                        } else if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
+                               /*
+                                * The STA is in power save mode, so assume
+                                * that this TX packet failed because of that.
+                                */
+                               if (skb)
+                                       ieee80211_handle_filtered_frame(local, sta, skb);
                                return;
                        } else if (noack_success) {
                                /* nothing to do here, do not account as lost */