aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/tx.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2010-07-22 11:11:28 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-07-26 15:32:42 -0400
commitec25acc46a62db98baaa9b221f33b66af09a1964 (patch)
tree78e577f444850b70415120bf9a68a642ee8960fa /net/mac80211/tx.c
parentbd75eb854300c7e09eaf067572498abdeb9d3424 (diff)
mac80211: fix sta assignment
I just had the following: WARNING: at drivers/net/wireless/iwlwifi/iwl-agn-tx.c:574 iwlagn_tx_skb+0x1576/0x15f0 [iwlagn]() Call Trace: <IRQ> [<ffffffff8105c5df>] warn_slowpath_common+0x7f/0xc0 [<ffffffff8105c63a>] warn_slowpath_null+0x1a/0x20 [<ffffffffa0290b46>] iwlagn_tx_skb+0x1576/0x15f0 [iwlagn] [<ffffffffa027076c>] iwl_mac_tx+0x5c/0x260 [iwlagn] [<ffffffffa01bdf5b>] __ieee80211_tx+0x10b/0x1a0 [mac80211] [<ffffffffa01bfb86>] ieee80211_tx_pending+0x186/0x2d0 [mac80211] [<ffffffff81062ea5>] tasklet_action+0x125/0x130 [<ffffffff810634a6>] __do_softirq+0x106/0x270 [<ffffffff8100c09c>] call_softirq+0x1c/0x30 iwlagn 0000:02:00.0: Attempting to modify non-existing station 107 Note that 107 == 0x6b which is slab poison. The reason is that mac80211 passed a freed station pointer to mac80211, because as it happened iwlwifi reset itself while mac80211 was disconnecting from the network. It turns out that we do take care to look up the station pointer in ieee80211_tx_pending_skb, but then don't use it, which obviously is a bug. Fix this by removing the ieee80211_tx_h_sta handler and assigning the station pointer directly. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r--net/mac80211/tx.c17
1 files changed, 5 insertions, 12 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 698d4718b1a4..2f8182dc94a1 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -576,17 +576,6 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
576} 576}
577 577
578static ieee80211_tx_result debug_noinline 578static ieee80211_tx_result debug_noinline
579ieee80211_tx_h_sta(struct ieee80211_tx_data *tx)
580{
581 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
582
583 if (tx->sta && tx->sta->uploaded)
584 info->control.sta = &tx->sta->sta;
585
586 return TX_CONTINUE;
587}
588
589static ieee80211_tx_result debug_noinline
590ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) 579ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
591{ 580{
592 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); 581 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
@@ -1307,6 +1296,11 @@ static int __ieee80211_tx(struct ieee80211_local *local,
1307 break; 1296 break;
1308 } 1297 }
1309 1298
1299 if (sta && sta->uploaded)
1300 info->control.sta = &sta->sta;
1301 else
1302 info->control.sta = NULL;
1303
1310 ret = drv_tx(local, skb); 1304 ret = drv_tx(local, skb);
1311 if (WARN_ON(ret != NETDEV_TX_OK && skb->len != len)) { 1305 if (WARN_ON(ret != NETDEV_TX_OK && skb->len != len)) {
1312 dev_kfree_skb(skb); 1306 dev_kfree_skb(skb);
@@ -1346,7 +1340,6 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
1346 CALL_TXH(ieee80211_tx_h_check_assoc); 1340 CALL_TXH(ieee80211_tx_h_check_assoc);
1347 CALL_TXH(ieee80211_tx_h_ps_buf); 1341 CALL_TXH(ieee80211_tx_h_ps_buf);
1348 CALL_TXH(ieee80211_tx_h_select_key); 1342 CALL_TXH(ieee80211_tx_h_select_key);
1349 CALL_TXH(ieee80211_tx_h_sta);
1350 if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)) 1343 if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL))
1351 CALL_TXH(ieee80211_tx_h_rate_ctrl); 1344 CALL_TXH(ieee80211_tx_h_rate_ctrl);
1352 1345