mirror of
https://github.com/torvalds/linux.git
synced 2024-12-11 13:41:55 +00:00
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 -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEH1e1rEeCd0AIMq6MB8qZga/fl8QFAlnwmYYACgkQB8qZga/f l8RsaA/+JmY4UM3mf/W7PDNDxDyhXOHEboJJzQ4lDZPzouTD0AJPSRrYOw1OqUmw LRnHizz2P75YT0WT7Esqa68eU1y2akiA8uzEIhgczwMDGO2w9M6Ca74UPw2+GGsV KQGKHY/GRZ4uAD+8K+mUvHUtIpomFyt3mrM0qvxu4Sw3UAe5bS3StLwJ+jJ34cp/ A9odYOUnCgzN7ZilPqfn5aApYI60nBtsAgbqFxoVp2rDCJXMuXA2d9q00HErCFzj NT4r9JfaXTMgbywxd5QJaS4b4/Xdq2sEFXBNN/ElKgA3bOGGfmW0BGIx64+D2wMi gPv0a7MeX45keyA0uIljxzyxMmNsI37MDCg2Px153BblI4zuxUBD/Dd9ankzW34r PZ1FX6txVDgE1xTshPUar2hn33Ju6rL1/+H4eQqB8vRiN73j/ri4JT+SWTtrJgXE yAx9AXzfOwVUV3FlmpXIuIlqgV1iOcCTR9UoramUNoqZSJmd0lX2M0I55DGjfaJe JYjGYofP1Cbqsw8TdI2QsRanPt9/kFgTnAkGbse3o+/X+CMAzOiIPFawR8PwbdaZ aH35+HQJz432IKu5i3csh3f3qV2Vgj4i1ogV2CEDBLjKDCMNZ6py0NATNMAkkjWS ULlHLV96YEEyh2Lv5s7pZ7HMbBc+3IQ7xmsukkczfv1cUIHnS8E= =6b1o -----END PGP SIGNATURE----- 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>
This commit is contained in:
commit
9618aec334
@ -146,6 +146,7 @@ static void fq_tin_enqueue(struct fq *fq,
|
||||
fq_flow_get_default_t get_default_func)
|
||||
{
|
||||
struct fq_flow *flow;
|
||||
bool oom;
|
||||
|
||||
lockdep_assert_held(&fq->lock);
|
||||
|
||||
@ -167,8 +168,8 @@ static void fq_tin_enqueue(struct fq *fq,
|
||||
}
|
||||
|
||||
__skb_queue_tail(&flow->queue, skb);
|
||||
|
||||
if (fq->backlog > fq->limit || fq->memory_usage > fq->memory_limit) {
|
||||
oom = (fq->memory_usage > fq->memory_limit);
|
||||
while (fq->backlog > fq->limit || oom) {
|
||||
flow = list_first_entry_or_null(&fq->backlogs,
|
||||
struct fq_flow,
|
||||
backlogchain);
|
||||
@ -183,8 +184,10 @@ static void fq_tin_enqueue(struct fq *fq,
|
||||
|
||||
flow->tin->overlimit++;
|
||||
fq->overlimit++;
|
||||
if (fq->memory_usage > fq->memory_limit)
|
||||
if (oom) {
|
||||
fq->overmemory++;
|
||||
oom = (fq->memory_usage > fq->memory_limit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2727,12 +2727,6 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
return -ENETDOWN;
|
||||
|
||||
if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL)) {
|
||||
ret = drv_set_bitrate_mask(local, sdata, mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* If active validate the setting and reject it if it doesn't leave
|
||||
* 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,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL)) {
|
||||
ret = drv_set_bitrate_mask(local, sdata, mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_NL80211_BANDS; i++) {
|
||||
struct ieee80211_supported_band *sband = wiphy->bands[i];
|
||||
int j;
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/export.h>
|
||||
#include <net/mac80211.h>
|
||||
#include <crypto/algapi.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include "ieee80211_i.h"
|
||||
#include "driver-ops.h"
|
||||
@ -609,6 +610,39 @@ void ieee80211_key_free_unused(struct ieee80211_key *key)
|
||||
ieee80211_key_free_common(key);
|
||||
}
|
||||
|
||||
static bool ieee80211_key_identical(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_key *old,
|
||||
struct ieee80211_key *new)
|
||||
{
|
||||
u8 tkip_old[WLAN_KEY_LEN_TKIP], tkip_new[WLAN_KEY_LEN_TKIP];
|
||||
u8 *tk_old, *tk_new;
|
||||
|
||||
if (!old || new->conf.keylen != old->conf.keylen)
|
||||
return false;
|
||||
|
||||
tk_old = old->conf.key;
|
||||
tk_new = new->conf.key;
|
||||
|
||||
/*
|
||||
* In station mode, don't compare the TX MIC key, as it's never used
|
||||
* and offloaded rekeying may not care to send it to the host. This
|
||||
* is the case in iwlwifi, for example.
|
||||
*/
|
||||
if (sdata->vif.type == NL80211_IFTYPE_STATION &&
|
||||
new->conf.cipher == WLAN_CIPHER_SUITE_TKIP &&
|
||||
new->conf.keylen == WLAN_KEY_LEN_TKIP &&
|
||||
!(new->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
|
||||
memcpy(tkip_old, tk_old, WLAN_KEY_LEN_TKIP);
|
||||
memcpy(tkip_new, tk_new, WLAN_KEY_LEN_TKIP);
|
||||
memset(tkip_old + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY, 0, 8);
|
||||
memset(tkip_new + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY, 0, 8);
|
||||
tk_old = tkip_old;
|
||||
tk_new = tkip_new;
|
||||
}
|
||||
|
||||
return !crypto_memneq(tk_old, tk_new, new->conf.keylen);
|
||||
}
|
||||
|
||||
int ieee80211_key_link(struct ieee80211_key *key,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
struct sta_info *sta)
|
||||
@ -634,8 +668,7 @@ int ieee80211_key_link(struct ieee80211_key *key,
|
||||
* Silently accept key re-installation without really installing the
|
||||
* new version of the key to avoid nonce reuse or replay issues.
|
||||
*/
|
||||
if (old_key && key->conf.keylen == old_key->conf.keylen &&
|
||||
!memcmp(key->conf.key, old_key->conf.key, key->conf.keylen)) {
|
||||
if (ieee80211_key_identical(sdata, old_key, key)) {
|
||||
ieee80211_key_free_unused(key);
|
||||
ret = 0;
|
||||
goto out;
|
||||
|
@ -522,11 +522,6 @@ static int cfg80211_sme_connect(struct wireless_dev *wdev,
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (wdev->current_bss) {
|
||||
if (!prev_bssid)
|
||||
return -EALREADY;
|
||||
if (prev_bssid &&
|
||||
!ether_addr_equal(prev_bssid, wdev->current_bss->pub.bssid))
|
||||
return -ENOTCONN;
|
||||
cfg80211_unhold_bss(wdev->current_bss);
|
||||
cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub);
|
||||
wdev->current_bss = NULL;
|
||||
@ -1063,11 +1058,35 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
|
||||
|
||||
ASSERT_WDEV_LOCK(wdev);
|
||||
|
||||
if (WARN_ON(wdev->connect_keys)) {
|
||||
kzfree(wdev->connect_keys);
|
||||
wdev->connect_keys = NULL;
|
||||
/*
|
||||
* If we have an ssid_len, we're trying to connect or are
|
||||
* already connected, so reject a new SSID unless it's the
|
||||
* same (which is the case for re-association.)
|
||||
*/
|
||||
if (wdev->ssid_len &&
|
||||
(wdev->ssid_len != connect->ssid_len ||
|
||||
memcmp(wdev->ssid, connect->ssid, wdev->ssid_len)))
|
||||
return -EALREADY;
|
||||
|
||||
/*
|
||||
* If connected, reject (re-)association unless prev_bssid
|
||||
* matches the current BSSID.
|
||||
*/
|
||||
if (wdev->current_bss) {
|
||||
if (!prev_bssid)
|
||||
return -EALREADY;
|
||||
if (!ether_addr_equal(prev_bssid, wdev->current_bss->pub.bssid))
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reject if we're in the process of connecting with WEP,
|
||||
* this case isn't very interesting and trying to handle
|
||||
* it would make the code much more complex.
|
||||
*/
|
||||
if (wdev->connect_keys)
|
||||
return -EINPROGRESS;
|
||||
|
||||
cfg80211_oper_and_ht_capa(&connect->ht_capa_mask,
|
||||
rdev->wiphy.ht_capa_mod_mask);
|
||||
|
||||
@ -1118,7 +1137,12 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
|
||||
|
||||
if (err) {
|
||||
wdev->connect_keys = NULL;
|
||||
wdev->ssid_len = 0;
|
||||
/*
|
||||
* This could be reassoc getting refused, don't clear
|
||||
* ssid_len in that case.
|
||||
*/
|
||||
if (!wdev->current_bss)
|
||||
wdev->ssid_len = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1145,6 +1169,14 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
|
||||
else if (wdev->ssid_len)
|
||||
err = rdev_disconnect(rdev, dev, reason);
|
||||
|
||||
/*
|
||||
* Clear ssid_len unless we actually were fully connected,
|
||||
* in which case cfg80211_disconnected() will take care of
|
||||
* this later.
|
||||
*/
|
||||
if (!wdev->current_bss)
|
||||
wdev->ssid_len = 0;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user