Commit c3e7724b6bc2f25e46c38dbe68f09d71fafeafb8

Authored by Felix Fietkau
Committed by John W. Linville
1 parent 5bcbc3fcbd

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: Felix Fietkau <nbd@openwrt.org>
Cc: stable@vger.kernel.org
Signed-off-by: John W. Linville <linville@tuxdriver.com>

Showing 2 changed files with 14 additions and 12 deletions Side-by-side Diff

net/mac80211/status.c
... ... @@ -34,7 +34,7 @@
34 34 skb_queue_len(&local->skb_queue_unreliable);
35 35 while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT &&
36 36 (skb = skb_dequeue(&local->skb_queue_unreliable))) {
37   - dev_kfree_skb_irq(skb);
  37 + ieee80211_free_txskb(hw, skb);
38 38 tmp--;
39 39 I802_DEBUG_INC(local->tx_status_drop);
40 40 }
... ... @@ -159,7 +159,7 @@
159 159 "dropped TX filtered frame, queue_len=%d PS=%d @%lu\n",
160 160 skb_queue_len(&sta->tx_filtered[ac]),
161 161 !!test_sta_flag(sta, WLAN_STA_PS_STA), jiffies);
162   - dev_kfree_skb(skb);
  162 + ieee80211_free_txskb(&local->hw, skb);
163 163 }
164 164  
165 165 static void ieee80211_check_pending_bar(struct sta_info *sta, u8 *addr, u8 tid)
... ... @@ -354,7 +354,7 @@
354 354 total += skb_queue_len(&sta->ps_tx_buf[ac]);
355 355 if (skb) {
356 356 purged++;
357   - dev_kfree_skb(skb);
  357 + ieee80211_free_txskb(&local->hw, skb);
358 358 break;
359 359 }
360 360 }
... ... @@ -466,7 +466,7 @@
466 466 ps_dbg(tx->sdata,
467 467 "STA %pM TX buffer for AC %d full - dropping oldest frame\n",
468 468 sta->sta.addr, ac);
469   - dev_kfree_skb(old);
  469 + ieee80211_free_txskb(&local->hw, old);
470 470 } else
471 471 tx->local->total_ps_buffered++;
472 472  
... ... @@ -1103,7 +1103,7 @@
1103 1103 spin_unlock(&tx->sta->lock);
1104 1104  
1105 1105 if (purge_skb)
1106   - dev_kfree_skb(purge_skb);
  1106 + ieee80211_free_txskb(&tx->local->hw, purge_skb);
1107 1107 }
1108 1108  
1109 1109 /* reset session timer */
... ... @@ -1214,7 +1214,7 @@
1214 1214 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
1215 1215 if (WARN_ON_ONCE(q >= local->hw.queues)) {
1216 1216 __skb_unlink(skb, skbs);
1217   - dev_kfree_skb(skb);
  1217 + ieee80211_free_txskb(&local->hw, skb);
1218 1218 continue;
1219 1219 }
1220 1220 #endif
... ... @@ -1356,7 +1356,7 @@
1356 1356 if (unlikely(res == TX_DROP)) {
1357 1357 I802_DEBUG_INC(tx->local->tx_handlers_drop);
1358 1358 if (tx->skb)
1359   - dev_kfree_skb(tx->skb);
  1359 + ieee80211_free_txskb(&tx->local->hw, tx->skb);
1360 1360 else
1361 1361 __skb_queue_purge(&tx->skbs);
1362 1362 return -1;
... ... @@ -1393,7 +1393,7 @@
1393 1393 res_prepare = ieee80211_tx_prepare(sdata, &tx, skb);
1394 1394  
1395 1395 if (unlikely(res_prepare == TX_DROP)) {
1396   - dev_kfree_skb(skb);
  1396 + ieee80211_free_txskb(&local->hw, skb);
1397 1397 goto out;
1398 1398 } else if (unlikely(res_prepare == TX_QUEUED)) {
1399 1399 goto out;
... ... @@ -1465,7 +1465,7 @@
1465 1465 headroom = max_t(int, 0, headroom);
1466 1466  
1467 1467 if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) {
1468   - dev_kfree_skb(skb);
  1468 + ieee80211_free_txskb(&local->hw, skb);
1469 1469 rcu_read_unlock();
1470 1470 return;
1471 1471 }
... ... @@ -2050,8 +2050,10 @@
2050 2050 head_need += IEEE80211_ENCRYPT_HEADROOM;
2051 2051 head_need += local->tx_headroom;
2052 2052 head_need = max_t(int, 0, head_need);
2053   - if (ieee80211_skb_resize(sdata, skb, head_need, true))
2054   - goto fail;
  2053 + if (ieee80211_skb_resize(sdata, skb, head_need, true)) {
  2054 + ieee80211_free_txskb(&local->hw, skb);
  2055 + return NETDEV_TX_OK;
  2056 + }
2055 2057 }
2056 2058  
2057 2059 if (encaps_data) {
... ... @@ -2184,7 +2186,7 @@
2184 2186 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
2185 2187  
2186 2188 if (WARN_ON(!info->control.vif)) {
2187   - kfree_skb(skb);
  2189 + ieee80211_free_txskb(&local->hw, skb);
2188 2190 continue;
2189 2191 }
2190 2192