aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2017-10-27 00:50:06 -0400
committerDavid S. Miller <davem@davemloft.net>2017-10-27 00:50:06 -0400
commit9618aec3349b7669b6bf123c7c6121789cb82861 (patch)
tree6a4d6f63a900b5e8a5ccaf1c34c0635bf042d276
parent78e0ea6791d7baafb8a0ca82b1bd0c7b3453c919 (diff)
parentcfbb0d90a7abb289edc91833d0905931f8805f12 (diff)
Merge tag 'mac80211-for-davem-2017-10-25' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211
Johannes Berg says: ==================== pull-request: mac80211 2017-10-25 Here are: * follow-up fixes for the WoWLAN security issue, to fix a partial TKIP key material problem and to use crypto_memneq() * a change for better enforcement of FQ's memory limit * a disconnect/connect handling fix, and * a user rate mask validation fix ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/fq_impl.h9
-rw-r--r--net/mac80211/cfg.c12
-rw-r--r--net/mac80211/key.c37
-rw-r--r--net/wireless/sme.c50
4 files changed, 88 insertions, 20 deletions
diff --git a/include/net/fq_impl.h b/include/net/fq_impl.h
index 4e6131cd3f43..ac1a2317941e 100644
--- a/include/net/fq_impl.h
+++ b/include/net/fq_impl.h
@@ -146,6 +146,7 @@ static void fq_tin_enqueue(struct fq *fq,
146 fq_flow_get_default_t get_default_func) 146 fq_flow_get_default_t get_default_func)
147{ 147{
148 struct fq_flow *flow; 148 struct fq_flow *flow;
149 bool oom;
149 150
150 lockdep_assert_held(&fq->lock); 151 lockdep_assert_held(&fq->lock);
151 152
@@ -167,8 +168,8 @@ static void fq_tin_enqueue(struct fq *fq,
167 } 168 }
168 169
169 __skb_queue_tail(&flow->queue, skb); 170 __skb_queue_tail(&flow->queue, skb);
170 171 oom = (fq->memory_usage > fq->memory_limit);
171 if (fq->backlog > fq->limit || fq->memory_usage > fq->memory_limit) { 172 while (fq->backlog > fq->limit || oom) {
172 flow = list_first_entry_or_null(&fq->backlogs, 173 flow = list_first_entry_or_null(&fq->backlogs,
173 struct fq_flow, 174 struct fq_flow,
174 backlogchain); 175 backlogchain);
@@ -183,8 +184,10 @@ static void fq_tin_enqueue(struct fq *fq,
183 184
184 flow->tin->overlimit++; 185 flow->tin->overlimit++;
185 fq->overlimit++; 186 fq->overlimit++;
186 if (fq->memory_usage > fq->memory_limit) 187 if (oom) {
187 fq->overmemory++; 188 fq->overmemory++;
189 oom = (fq->memory_usage > fq->memory_limit);
190 }
188 } 191 }
189} 192}
190 193
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index a354f1939e49..fb15d3b97cb2 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2727,12 +2727,6 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
2727 if (!ieee80211_sdata_running(sdata)) 2727 if (!ieee80211_sdata_running(sdata))
2728 return -ENETDOWN; 2728 return -ENETDOWN;
2729 2729
2730 if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL)) {
2731 ret = drv_set_bitrate_mask(local, sdata, mask);
2732 if (ret)
2733 return ret;
2734 }
2735
2736 /* 2730 /*
2737 * If active validate the setting and reject it if it doesn't leave 2731 * If active validate the setting and reject it if it doesn't leave
2738 * at least one basic rate usable, since we really have to be able 2732 * at least one basic rate usable, since we really have to be able
@@ -2748,6 +2742,12 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
2748 return -EINVAL; 2742 return -EINVAL;
2749 } 2743 }
2750 2744
2745 if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL)) {
2746 ret = drv_set_bitrate_mask(local, sdata, mask);
2747 if (ret)
2748 return ret;
2749 }
2750
2751 for (i = 0; i < NUM_NL80211_BANDS; i++) { 2751 for (i = 0; i < NUM_NL80211_BANDS; i++) {
2752 struct ieee80211_supported_band *sband = wiphy->bands[i]; 2752 struct ieee80211_supported_band *sband = wiphy->bands[i];
2753 int j; 2753 int j;
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index ae995c8480db..938049395f90 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -19,6 +19,7 @@
19#include <linux/slab.h> 19#include <linux/slab.h>
20#include <linux/export.h> 20#include <linux/export.h>
21#include <net/mac80211.h> 21#include <net/mac80211.h>
22#include <crypto/algapi.h>
22#include <asm/unaligned.h> 23#include <asm/unaligned.h>
23#include "ieee80211_i.h" 24#include "ieee80211_i.h"
24#include "driver-ops.h" 25#include "driver-ops.h"
@@ -609,6 +610,39 @@ void ieee80211_key_free_unused(struct ieee80211_key *key)
609 ieee80211_key_free_common(key); 610 ieee80211_key_free_common(key);
610} 611}
611 612
613static bool ieee80211_key_identical(struct ieee80211_sub_if_data *sdata,
614 struct ieee80211_key *old,
615 struct ieee80211_key *new)
616{
617 u8 tkip_old[WLAN_KEY_LEN_TKIP], tkip_new[WLAN_KEY_LEN_TKIP];
618 u8 *tk_old, *tk_new;
619
620 if (!old || new->conf.keylen != old->conf.keylen)
621 return false;
622
623 tk_old = old->conf.key;
624 tk_new = new->conf.key;
625
626 /*
627 * In station mode, don't compare the TX MIC key, as it's never used
628 * and offloaded rekeying may not care to send it to the host. This
629 * is the case in iwlwifi, for example.
630 */
631 if (sdata->vif.type == NL80211_IFTYPE_STATION &&
632 new->conf.cipher == WLAN_CIPHER_SUITE_TKIP &&
633 new->conf.keylen == WLAN_KEY_LEN_TKIP &&
634 !(new->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
635 memcpy(tkip_old, tk_old, WLAN_KEY_LEN_TKIP);
636 memcpy(tkip_new, tk_new, WLAN_KEY_LEN_TKIP);
637 memset(tkip_old + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY, 0, 8);
638 memset(tkip_new + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY, 0, 8);
639 tk_old = tkip_old;
640 tk_new = tkip_new;
641 }
642
643 return !crypto_memneq(tk_old, tk_new, new->conf.keylen);
644}
645
612int ieee80211_key_link(struct ieee80211_key *key, 646int ieee80211_key_link(struct ieee80211_key *key,
613 struct ieee80211_sub_if_data *sdata, 647 struct ieee80211_sub_if_data *sdata,
614 struct sta_info *sta) 648 struct sta_info *sta)
@@ -634,8 +668,7 @@ int ieee80211_key_link(struct ieee80211_key *key,
634 * Silently accept key re-installation without really installing the 668 * Silently accept key re-installation without really installing the
635 * new version of the key to avoid nonce reuse or replay issues. 669 * new version of the key to avoid nonce reuse or replay issues.
636 */ 670 */
637 if (old_key && key->conf.keylen == old_key->conf.keylen && 671 if (ieee80211_key_identical(sdata, old_key, key)) {
638 !memcmp(key->conf.key, old_key->conf.key, key->conf.keylen)) {
639 ieee80211_key_free_unused(key); 672 ieee80211_key_free_unused(key);
640 ret = 0; 673 ret = 0;
641 goto out; 674 goto out;
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 0a49b88070d0..b6533ecbf5b1 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -522,11 +522,6 @@ static int cfg80211_sme_connect(struct wireless_dev *wdev,
522 return -EOPNOTSUPP; 522 return -EOPNOTSUPP;
523 523
524 if (wdev->current_bss) { 524 if (wdev->current_bss) {
525 if (!prev_bssid)
526 return -EALREADY;
527 if (prev_bssid &&
528 !ether_addr_equal(prev_bssid, wdev->current_bss->pub.bssid))
529 return -ENOTCONN;
530 cfg80211_unhold_bss(wdev->current_bss); 525 cfg80211_unhold_bss(wdev->current_bss);
531 cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub); 526 cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub);
532 wdev->current_bss = NULL; 527 wdev->current_bss = NULL;
@@ -1063,11 +1058,35 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
1063 1058
1064 ASSERT_WDEV_LOCK(wdev); 1059 ASSERT_WDEV_LOCK(wdev);
1065 1060
1066 if (WARN_ON(wdev->connect_keys)) { 1061 /*
1067 kzfree(wdev->connect_keys); 1062 * If we have an ssid_len, we're trying to connect or are
1068 wdev->connect_keys = NULL; 1063 * already connected, so reject a new SSID unless it's the
1064 * same (which is the case for re-association.)
1065 */
1066 if (wdev->ssid_len &&
1067 (wdev->ssid_len != connect->ssid_len ||
1068 memcmp(wdev->ssid, connect->ssid, wdev->ssid_len)))
1069 return -EALREADY;
1070
1071 /*
1072 * If connected, reject (re-)association unless prev_bssid
1073 * matches the current BSSID.
1074 */
1075 if (wdev->current_bss) {
1076 if (!prev_bssid)
1077 return -EALREADY;
1078 if (!ether_addr_equal(prev_bssid, wdev->current_bss->pub.bssid))
1079 return -ENOTCONN;
1069 } 1080 }
1070 1081
1082 /*
1083 * Reject if we're in the process of connecting with WEP,
1084 * this case isn't very interesting and trying to handle
1085 * it would make the code much more complex.
1086 */
1087 if (wdev->connect_keys)
1088 return -EINPROGRESS;
1089
1071 cfg80211_oper_and_ht_capa(&connect->ht_capa_mask, 1090 cfg80211_oper_and_ht_capa(&connect->ht_capa_mask,
1072 rdev->wiphy.ht_capa_mod_mask); 1091 rdev->wiphy.ht_capa_mod_mask);
1073 1092
@@ -1118,7 +1137,12 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
1118 1137
1119 if (err) { 1138 if (err) {
1120 wdev->connect_keys = NULL; 1139 wdev->connect_keys = NULL;
1121 wdev->ssid_len = 0; 1140 /*
1141 * This could be reassoc getting refused, don't clear
1142 * ssid_len in that case.
1143 */
1144 if (!wdev->current_bss)
1145 wdev->ssid_len = 0;
1122 return err; 1146 return err;
1123 } 1147 }
1124 1148
@@ -1145,6 +1169,14 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
1145 else if (wdev->ssid_len) 1169 else if (wdev->ssid_len)
1146 err = rdev_disconnect(rdev, dev, reason); 1170 err = rdev_disconnect(rdev, dev, reason);
1147 1171
1172 /*
1173 * Clear ssid_len unless we actually were fully connected,
1174 * in which case cfg80211_disconnected() will take care of
1175 * this later.
1176 */
1177 if (!wdev->current_bss)
1178 wdev->ssid_len = 0;
1179
1148 return err; 1180 return err;
1149} 1181}
1150 1182