Commit 1d182885 authored by Felix Fietkau's avatar Felix Fietkau Committed by Johannes Berg
Browse files

mac80211: fix memory leak on filtered powersave frames



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: default avatarTobias Waldvogel <tobias.waldvogel@gmail.com>
Fixes: 3318111c ("mac80211: reduce duplication in tx status functions")
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
Link: https://lore.kernel.org/r/20201111183359.43528-1-nbd@nbd.name


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 94e2bd0b
Loading
Loading
Loading
Loading
+8 −10
Original line number Diff line number Diff line
@@ -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 */