From 543d1b92d5500841e70f15e79d197bbffed36561 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 13 Jan 2012 14:17:59 +0100 Subject: mac80211: fix no-op authorized transitions When userspace attempts to authorize a station that is already authorized, nothing happens as you'd expect. Similarly, when it unauthorizes a station that is associated, nothing happens. However, when it unauthorizes a station that isn't even associated yet, we erroneously try to move the station to associated. This seems to happen occasionally as a result of a race when wpa_supplicant attempts to unauthorize the port in managed mode. Particularly with my new patches to keep stations, it can then move a station into ASSOCIATED state before we have really associated, which is really confusing. I introduced this bug in "mac80211: refactor station state transitions" Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index e60df48fa4d4..296620d6ca0c 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -791,7 +791,7 @@ static int sta_apply_parameters(struct ieee80211_local *local, if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) ret = sta_info_move_state_checked(sta, IEEE80211_STA_AUTHORIZED); - else + else if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) ret = sta_info_move_state_checked(sta, IEEE80211_STA_ASSOC); if (ret) -- cgit v1.2.1 From 74b8cc3d592e5e884123eb99960a9f064223eaab Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sat, 14 Jan 2012 21:52:17 +0100 Subject: Net, mac80211: Fix resource leak in ieee80211_rx_h_mesh_fwding() We may leak the 'fwd_skb' we skb_copy() in ieee80211_rx_h_mesh_fwding() if we take the 'else' branch in the 'if' statement just below. If we take that branch we'll end up returning from the function and since we've not assigned 'fwd_skb' to anything at that point, we leak it when the variable goes out of scope. The simple fix seems to be to just kfree_skb(fwd_skb); just before we return. That is what this patch does. Signed-off-by: Jesper Juhl Signed-off-by: John W. Linville --- net/mac80211/rx.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index f407427c642f..751409120769 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1979,6 +1979,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) mesh_path_error_tx(ifmsh->mshcfg.element_ttl, fwd_hdr->addr3, 0, reason, fwd_hdr->addr2, sdata); IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route); + kfree_skb(fwd_skb); return RX_DROP_MONITOR; } -- cgit v1.2.1 From d32a102819eef99d4d87019266bea208447be0a0 Mon Sep 17 00:00:00 2001 From: Yoni Divinsky Date: Mon, 16 Jan 2012 15:18:59 +0200 Subject: mac80211: fix tx->skb NULL pointer dereference In function ieee80211_tx_h_encrypt the var info was initialized from tx->skb, since the fucntion is called after the function ieee80211_tx_h_fragment tx->skb is not valid anymore. Signed-off-by: Yoni Divinsky Signed-off-by: John W. Linville --- net/mac80211/tx.c | 10 +--------- net/mac80211/wpa.c | 19 +++++++++++++++++++ net/mac80211/wpa.h | 2 ++ 3 files changed, 22 insertions(+), 9 deletions(-) (limited to 'net') diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index edcd1c7ab83f..e05667cd5e76 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1001,8 +1001,6 @@ ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) static ieee80211_tx_result debug_noinline ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx) { - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); - if (!tx->key) return TX_CONTINUE; @@ -1017,13 +1015,7 @@ ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx) case WLAN_CIPHER_SUITE_AES_CMAC: return ieee80211_crypto_aes_cmac_encrypt(tx); default: - /* handle hw-only algorithm */ - if (info->control.hw_key) { - ieee80211_tx_set_protected(tx); - return TX_CONTINUE; - } - break; - + return ieee80211_crypto_hw_encrypt(tx); } return TX_DROP; diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 422b79851ec5..b758350919ff 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -643,3 +643,22 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx) return RX_CONTINUE; } + +ieee80211_tx_result +ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx) +{ + struct sk_buff *skb; + struct ieee80211_tx_info *info = NULL; + + skb_queue_walk(&tx->skbs, skb) { + info = IEEE80211_SKB_CB(skb); + + /* handle hw-only algorithm */ + if (!info->control.hw_key) + return TX_DROP; + } + + ieee80211_tx_set_protected(tx); + + return TX_CONTINUE; +} diff --git a/net/mac80211/wpa.h b/net/mac80211/wpa.h index baba0608313e..07e33f899c71 100644 --- a/net/mac80211/wpa.h +++ b/net/mac80211/wpa.h @@ -32,5 +32,7 @@ ieee80211_tx_result ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx); ieee80211_rx_result ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx); +ieee80211_tx_result +ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx); #endif /* WPA_H */ -- cgit v1.2.1 From 544204733a20200951c271f81c74930ba5424638 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Tue, 17 Jan 2012 09:22:49 +0100 Subject: mac80211: Fix possible race between sta_unblock and network softirq All other code paths in sta_unblock synchronize with the network softirq by using local_bh_disable/enable. Do the same around ieee80211_sta_ps_deliver_wakeup. Signed-off-by: Helmut Schaa Signed-off-by: John W. Linville --- net/mac80211/sta_info.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 3c428d4839c7..ff11f6bf8266 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -238,9 +238,11 @@ static void sta_unblock(struct work_struct *wk) if (sta->dead) return; - if (!test_sta_flag(sta, WLAN_STA_PS_STA)) + if (!test_sta_flag(sta, WLAN_STA_PS_STA)) { + local_bh_disable(); ieee80211_sta_ps_deliver_wakeup(sta); - else if (test_and_clear_sta_flag(sta, WLAN_STA_PSPOLL)) { + local_bh_enable(); + } else if (test_and_clear_sta_flag(sta, WLAN_STA_PSPOLL)) { clear_sta_flag(sta, WLAN_STA_PS_DRIVER); local_bh_disable(); -- cgit v1.2.1