aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/tx.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2015-03-01 02:10:12 -0500
committerJohannes Berg <johannes.berg@intel.com>2015-03-04 04:34:11 -0500
commit88724a81b4ac2a755bf9c532cdbee08a52803852 (patch)
tree7c73b370322b85288b70dd3a8313bd10f27b8657 /net/mac80211/tx.c
parent0b4e11074a933937ee75be371d32bf91a0051419 (diff)
mac80211: check and dequeue skb in ieee80211_tx_prepare_skb()
The ieee80211_tx_prepare_skb() function currently entirely ignores the fact that the SKB that is passed in might be split into more than one due to fragmentation and doesn't check the list of skbs that the TX handlers may create. In case this happens, it would leak them. Fix this and also don't leave the skb next/prev pointers dangling pointing to the on-stack sk_buff_head. Reported-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r--net/mac80211/tx.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index a23a84e93e80..7e7de811e6ad 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1420,6 +1420,7 @@ bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw,
1420 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 1420 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
1421 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1421 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1422 struct ieee80211_tx_data tx; 1422 struct ieee80211_tx_data tx;
1423 struct sk_buff *skb2;
1423 1424
1424 if (ieee80211_tx_prepare(sdata, &tx, skb) == TX_DROP) 1425 if (ieee80211_tx_prepare(sdata, &tx, skb) == TX_DROP)
1425 return false; 1426 return false;
@@ -1438,6 +1439,14 @@ bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw,
1438 *sta = NULL; 1439 *sta = NULL;
1439 } 1440 }
1440 1441
1442 /* this function isn't suitable for fragmented data frames */
1443 skb2 = __skb_dequeue(&tx.skbs);
1444 if (WARN_ON(skb2 != skb || !skb_queue_empty(&tx.skbs))) {
1445 ieee80211_free_txskb(hw, skb2);
1446 ieee80211_purge_tx_queue(hw, &tx.skbs);
1447 return false;
1448 }
1449
1441 return true; 1450 return true;
1442} 1451}
1443EXPORT_SYMBOL(ieee80211_tx_prepare_skb); 1452EXPORT_SYMBOL(ieee80211_tx_prepare_skb);