Commit c3e7724b authored by Felix Fietkau's avatar Felix Fietkau Committed by John W. Linville

mac80211: use ieee80211_free_txskb to fix possible skb leaks

A few places free skbs using dev_kfree_skb even though they're called
after ieee80211_subif_start_xmit might have cloned it for tracking tx
status. Use ieee80211_free_txskb here to prevent skb leaks.
Signed-off-by: default avatarFelix Fietkau <nbd@openwrt.org>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 5bcbc3fc
...@@ -34,7 +34,7 @@ void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, ...@@ -34,7 +34,7 @@ void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
skb_queue_len(&local->skb_queue_unreliable); skb_queue_len(&local->skb_queue_unreliable);
while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT && while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT &&
(skb = skb_dequeue(&local->skb_queue_unreliable))) { (skb = skb_dequeue(&local->skb_queue_unreliable))) {
dev_kfree_skb_irq(skb); ieee80211_free_txskb(hw, skb);
tmp--; tmp--;
I802_DEBUG_INC(local->tx_status_drop); I802_DEBUG_INC(local->tx_status_drop);
} }
...@@ -159,7 +159,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, ...@@ -159,7 +159,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
"dropped TX filtered frame, queue_len=%d PS=%d @%lu\n", "dropped TX filtered frame, queue_len=%d PS=%d @%lu\n",
skb_queue_len(&sta->tx_filtered[ac]), skb_queue_len(&sta->tx_filtered[ac]),
!!test_sta_flag(sta, WLAN_STA_PS_STA), jiffies); !!test_sta_flag(sta, WLAN_STA_PS_STA), jiffies);
dev_kfree_skb(skb); ieee80211_free_txskb(&local->hw, skb);
} }
static void ieee80211_check_pending_bar(struct sta_info *sta, u8 *addr, u8 tid) static void ieee80211_check_pending_bar(struct sta_info *sta, u8 *addr, u8 tid)
......
...@@ -354,7 +354,7 @@ static void purge_old_ps_buffers(struct ieee80211_local *local) ...@@ -354,7 +354,7 @@ static void purge_old_ps_buffers(struct ieee80211_local *local)
total += skb_queue_len(&sta->ps_tx_buf[ac]); total += skb_queue_len(&sta->ps_tx_buf[ac]);
if (skb) { if (skb) {
purged++; purged++;
dev_kfree_skb(skb); ieee80211_free_txskb(&local->hw, skb);
break; break;
} }
} }
...@@ -466,7 +466,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) ...@@ -466,7 +466,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
ps_dbg(tx->sdata, ps_dbg(tx->sdata,
"STA %pM TX buffer for AC %d full - dropping oldest frame\n", "STA %pM TX buffer for AC %d full - dropping oldest frame\n",
sta->sta.addr, ac); sta->sta.addr, ac);
dev_kfree_skb(old); ieee80211_free_txskb(&local->hw, old);
} else } else
tx->local->total_ps_buffered++; tx->local->total_ps_buffered++;
...@@ -1103,7 +1103,7 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, ...@@ -1103,7 +1103,7 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
spin_unlock(&tx->sta->lock); spin_unlock(&tx->sta->lock);
if (purge_skb) if (purge_skb)
dev_kfree_skb(purge_skb); ieee80211_free_txskb(&tx->local->hw, purge_skb);
} }
/* reset session timer */ /* reset session timer */
...@@ -1214,7 +1214,7 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local, ...@@ -1214,7 +1214,7 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local,
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
if (WARN_ON_ONCE(q >= local->hw.queues)) { if (WARN_ON_ONCE(q >= local->hw.queues)) {
__skb_unlink(skb, skbs); __skb_unlink(skb, skbs);
dev_kfree_skb(skb); ieee80211_free_txskb(&local->hw, skb);
continue; continue;
} }
#endif #endif
...@@ -1356,7 +1356,7 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) ...@@ -1356,7 +1356,7 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
if (unlikely(res == TX_DROP)) { if (unlikely(res == TX_DROP)) {
I802_DEBUG_INC(tx->local->tx_handlers_drop); I802_DEBUG_INC(tx->local->tx_handlers_drop);
if (tx->skb) if (tx->skb)
dev_kfree_skb(tx->skb); ieee80211_free_txskb(&tx->local->hw, tx->skb);
else else
__skb_queue_purge(&tx->skbs); __skb_queue_purge(&tx->skbs);
return -1; return -1;
...@@ -1393,7 +1393,7 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, ...@@ -1393,7 +1393,7 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
res_prepare = ieee80211_tx_prepare(sdata, &tx, skb); res_prepare = ieee80211_tx_prepare(sdata, &tx, skb);
if (unlikely(res_prepare == TX_DROP)) { if (unlikely(res_prepare == TX_DROP)) {
dev_kfree_skb(skb); ieee80211_free_txskb(&local->hw, skb);
goto out; goto out;
} else if (unlikely(res_prepare == TX_QUEUED)) { } else if (unlikely(res_prepare == TX_QUEUED)) {
goto out; goto out;
...@@ -1465,7 +1465,7 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) ...@@ -1465,7 +1465,7 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
headroom = max_t(int, 0, headroom); headroom = max_t(int, 0, headroom);
if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) { if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) {
dev_kfree_skb(skb); ieee80211_free_txskb(&local->hw, skb);
rcu_read_unlock(); rcu_read_unlock();
return; return;
} }
...@@ -2050,8 +2050,10 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, ...@@ -2050,8 +2050,10 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
head_need += IEEE80211_ENCRYPT_HEADROOM; head_need += IEEE80211_ENCRYPT_HEADROOM;
head_need += local->tx_headroom; head_need += local->tx_headroom;
head_need = max_t(int, 0, head_need); head_need = max_t(int, 0, head_need);
if (ieee80211_skb_resize(sdata, skb, head_need, true)) if (ieee80211_skb_resize(sdata, skb, head_need, true)) {
goto fail; ieee80211_free_txskb(&local->hw, skb);
return NETDEV_TX_OK;
}
} }
if (encaps_data) { if (encaps_data) {
...@@ -2184,7 +2186,7 @@ void ieee80211_tx_pending(unsigned long data) ...@@ -2184,7 +2186,7 @@ void ieee80211_tx_pending(unsigned long data)
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
if (WARN_ON(!info->control.vif)) { if (WARN_ON(!info->control.vif)) {
kfree_skb(skb); ieee80211_free_txskb(&local->hw, skb);
continue; continue;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment