diff options
author | David S. Miller <davem@davemloft.net> | 2017-06-13 13:34:13 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-06-13 13:34:13 -0400 |
commit | c5549ee40112f2511a794c9aad7eb6ac5f18b0eb (patch) | |
tree | bcd773cb87894e264be36091891eaee194038551 | |
parent | ace17c369295f088dc8ac8ff468602646fa5cced (diff) | |
parent | b3dd8279659f14f3624bb32559782d699fa6f7d1 (diff) |
Merge tag 'mac80211-for-davem-2017-06-13' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211
Johannes Berg says:
====================
Some fixes:
* Avi fixes some fallout from my mac80211 RX flags changes
* Emmanuel fixes an issue with adhering to the spec, and
an oversight in the SMPS management code
* Jason's patch makes mac80211 use constant-time memory
comparisons for message authentication, to avoid having
potentially observable timing differences
* my fix makes mac80211 set the basic rates bitmap before
the channel so the next update to the driver has more
consistent data - this required another rework patch to
remove some useless 5/10 MHz code that can never be hit
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/mac80211/cfg.c | 2 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 2 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 62 | ||||
-rw-r--r-- | net/mac80211/rx.c | 6 | ||||
-rw-r--r-- | net/mac80211/wpa.c | 9 |
5 files changed, 44 insertions, 37 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 6c2e6060cd54..4a388fe8c2d1 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -902,6 +902,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
902 | default: | 902 | default: |
903 | return -EINVAL; | 903 | return -EINVAL; |
904 | } | 904 | } |
905 | sdata->u.ap.req_smps = sdata->smps_mode; | ||
906 | |||
905 | sdata->needed_rx_chains = sdata->local->rx_chains; | 907 | sdata->needed_rx_chains = sdata->local->rx_chains; |
906 | 908 | ||
907 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; | 909 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 665501ac358f..5e002f62c235 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -1531,7 +1531,7 @@ ieee80211_have_rx_timestamp(struct ieee80211_rx_status *status) | |||
1531 | return true; | 1531 | return true; |
1532 | /* can't handle non-legacy preamble yet */ | 1532 | /* can't handle non-legacy preamble yet */ |
1533 | if (status->flag & RX_FLAG_MACTIME_PLCP_START && | 1533 | if (status->flag & RX_FLAG_MACTIME_PLCP_START && |
1534 | status->encoding != RX_ENC_LEGACY) | 1534 | status->encoding == RX_ENC_LEGACY) |
1535 | return true; | 1535 | return true; |
1536 | return false; | 1536 | return false; |
1537 | } | 1537 | } |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 0ea9712bd99e..cc8e6ea1b27e 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -601,7 +601,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
601 | struct ieee80211_supported_band *sband; | 601 | struct ieee80211_supported_band *sband; |
602 | struct ieee80211_chanctx_conf *chanctx_conf; | 602 | struct ieee80211_chanctx_conf *chanctx_conf; |
603 | struct ieee80211_channel *chan; | 603 | struct ieee80211_channel *chan; |
604 | u32 rate_flags, rates = 0; | 604 | u32 rates = 0; |
605 | 605 | ||
606 | sdata_assert_lock(sdata); | 606 | sdata_assert_lock(sdata); |
607 | 607 | ||
@@ -612,7 +612,6 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
612 | return; | 612 | return; |
613 | } | 613 | } |
614 | chan = chanctx_conf->def.chan; | 614 | chan = chanctx_conf->def.chan; |
615 | rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def); | ||
616 | rcu_read_unlock(); | 615 | rcu_read_unlock(); |
617 | sband = local->hw.wiphy->bands[chan->band]; | 616 | sband = local->hw.wiphy->bands[chan->band]; |
618 | shift = ieee80211_vif_get_shift(&sdata->vif); | 617 | shift = ieee80211_vif_get_shift(&sdata->vif); |
@@ -636,9 +635,6 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
636 | */ | 635 | */ |
637 | rates_len = 0; | 636 | rates_len = 0; |
638 | for (i = 0; i < sband->n_bitrates; i++) { | 637 | for (i = 0; i < sband->n_bitrates; i++) { |
639 | if ((rate_flags & sband->bitrates[i].flags) | ||
640 | != rate_flags) | ||
641 | continue; | ||
642 | rates |= BIT(i); | 638 | rates |= BIT(i); |
643 | rates_len++; | 639 | rates_len++; |
644 | } | 640 | } |
@@ -2818,7 +2814,7 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband, | |||
2818 | u32 *rates, u32 *basic_rates, | 2814 | u32 *rates, u32 *basic_rates, |
2819 | bool *have_higher_than_11mbit, | 2815 | bool *have_higher_than_11mbit, |
2820 | int *min_rate, int *min_rate_index, | 2816 | int *min_rate, int *min_rate_index, |
2821 | int shift, u32 rate_flags) | 2817 | int shift) |
2822 | { | 2818 | { |
2823 | int i, j; | 2819 | int i, j; |
2824 | 2820 | ||
@@ -2846,8 +2842,6 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband, | |||
2846 | int brate; | 2842 | int brate; |
2847 | 2843 | ||
2848 | br = &sband->bitrates[j]; | 2844 | br = &sband->bitrates[j]; |
2849 | if ((rate_flags & br->flags) != rate_flags) | ||
2850 | continue; | ||
2851 | 2845 | ||
2852 | brate = DIV_ROUND_UP(br->bitrate, (1 << shift) * 5); | 2846 | brate = DIV_ROUND_UP(br->bitrate, (1 << shift) * 5); |
2853 | if (brate == rate) { | 2847 | if (brate == rate) { |
@@ -4398,40 +4392,32 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
4398 | return -ENOMEM; | 4392 | return -ENOMEM; |
4399 | } | 4393 | } |
4400 | 4394 | ||
4401 | if (new_sta || override) { | 4395 | /* |
4402 | err = ieee80211_prep_channel(sdata, cbss); | 4396 | * Set up the information for the new channel before setting the |
4403 | if (err) { | 4397 | * new channel. We can't - completely race-free - change the basic |
4404 | if (new_sta) | 4398 | * rates bitmap and the channel (sband) that it refers to, but if |
4405 | sta_info_free(local, new_sta); | 4399 | * we set it up before we at least avoid calling into the driver's |
4406 | return -EINVAL; | 4400 | * bss_info_changed() method with invalid information (since we do |
4407 | } | 4401 | * call that from changing the channel - only for IDLE and perhaps |
4408 | } | 4402 | * some others, but ...). |
4409 | 4403 | * | |
4404 | * So to avoid that, just set up all the new information before the | ||
4405 | * channel, but tell the driver to apply it only afterwards, since | ||
4406 | * it might need the new channel for that. | ||
4407 | */ | ||
4410 | if (new_sta) { | 4408 | if (new_sta) { |
4411 | u32 rates = 0, basic_rates = 0; | 4409 | u32 rates = 0, basic_rates = 0; |
4412 | bool have_higher_than_11mbit; | 4410 | bool have_higher_than_11mbit; |
4413 | int min_rate = INT_MAX, min_rate_index = -1; | 4411 | int min_rate = INT_MAX, min_rate_index = -1; |
4414 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
4415 | const struct cfg80211_bss_ies *ies; | 4412 | const struct cfg80211_bss_ies *ies; |
4416 | int shift = ieee80211_vif_get_shift(&sdata->vif); | 4413 | int shift = ieee80211_vif_get_shift(&sdata->vif); |
4417 | u32 rate_flags; | ||
4418 | |||
4419 | rcu_read_lock(); | ||
4420 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
4421 | if (WARN_ON(!chanctx_conf)) { | ||
4422 | rcu_read_unlock(); | ||
4423 | sta_info_free(local, new_sta); | ||
4424 | return -EINVAL; | ||
4425 | } | ||
4426 | rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def); | ||
4427 | rcu_read_unlock(); | ||
4428 | 4414 | ||
4429 | ieee80211_get_rates(sband, bss->supp_rates, | 4415 | ieee80211_get_rates(sband, bss->supp_rates, |
4430 | bss->supp_rates_len, | 4416 | bss->supp_rates_len, |
4431 | &rates, &basic_rates, | 4417 | &rates, &basic_rates, |
4432 | &have_higher_than_11mbit, | 4418 | &have_higher_than_11mbit, |
4433 | &min_rate, &min_rate_index, | 4419 | &min_rate, &min_rate_index, |
4434 | shift, rate_flags); | 4420 | shift); |
4435 | 4421 | ||
4436 | /* | 4422 | /* |
4437 | * This used to be a workaround for basic rates missing | 4423 | * This used to be a workaround for basic rates missing |
@@ -4489,8 +4475,22 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
4489 | sdata->vif.bss_conf.sync_dtim_count = 0; | 4475 | sdata->vif.bss_conf.sync_dtim_count = 0; |
4490 | } | 4476 | } |
4491 | rcu_read_unlock(); | 4477 | rcu_read_unlock(); |
4478 | } | ||
4492 | 4479 | ||
4493 | /* tell driver about BSSID, basic rates and timing */ | 4480 | if (new_sta || override) { |
4481 | err = ieee80211_prep_channel(sdata, cbss); | ||
4482 | if (err) { | ||
4483 | if (new_sta) | ||
4484 | sta_info_free(local, new_sta); | ||
4485 | return -EINVAL; | ||
4486 | } | ||
4487 | } | ||
4488 | |||
4489 | if (new_sta) { | ||
4490 | /* | ||
4491 | * tell driver about BSSID, basic rates and timing | ||
4492 | * this was set up above, before setting the channel | ||
4493 | */ | ||
4494 | ieee80211_bss_info_change_notify(sdata, | 4494 | ieee80211_bss_info_change_notify(sdata, |
4495 | BSS_CHANGED_BSSID | BSS_CHANGED_BASIC_RATES | | 4495 | BSS_CHANGED_BSSID | BSS_CHANGED_BASIC_RATES | |
4496 | BSS_CHANGED_BEACON_INT); | 4496 | BSS_CHANGED_BEACON_INT); |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 1f75280ba26c..3674fe3d67dc 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1613,12 +1613,16 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1613 | */ | 1613 | */ |
1614 | if (!ieee80211_hw_check(&sta->local->hw, AP_LINK_PS) && | 1614 | if (!ieee80211_hw_check(&sta->local->hw, AP_LINK_PS) && |
1615 | !ieee80211_has_morefrags(hdr->frame_control) && | 1615 | !ieee80211_has_morefrags(hdr->frame_control) && |
1616 | !ieee80211_is_back_req(hdr->frame_control) && | ||
1616 | !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && | 1617 | !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && |
1617 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || | 1618 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || |
1618 | rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && | 1619 | rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && |
1619 | /* PM bit is only checked in frames where it isn't reserved, | 1620 | /* |
1621 | * PM bit is only checked in frames where it isn't reserved, | ||
1620 | * in AP mode it's reserved in non-bufferable management frames | 1622 | * in AP mode it's reserved in non-bufferable management frames |
1621 | * (cf. IEEE 802.11-2012 8.2.4.1.7 Power Management field) | 1623 | * (cf. IEEE 802.11-2012 8.2.4.1.7 Power Management field) |
1624 | * BAR frames should be ignored as specified in | ||
1625 | * IEEE 802.11-2012 10.2.1.2. | ||
1622 | */ | 1626 | */ |
1623 | (!ieee80211_is_mgmt(hdr->frame_control) || | 1627 | (!ieee80211_is_mgmt(hdr->frame_control) || |
1624 | ieee80211_is_bufferable_mmpdu(hdr->frame_control))) { | 1628 | ieee80211_is_bufferable_mmpdu(hdr->frame_control))) { |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index c1ef22df865f..cc19614ff4e6 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <asm/unaligned.h> | 17 | #include <asm/unaligned.h> |
18 | #include <net/mac80211.h> | 18 | #include <net/mac80211.h> |
19 | #include <crypto/aes.h> | 19 | #include <crypto/aes.h> |
20 | #include <crypto/algapi.h> | ||
20 | 21 | ||
21 | #include "ieee80211_i.h" | 22 | #include "ieee80211_i.h" |
22 | #include "michael.h" | 23 | #include "michael.h" |
@@ -153,7 +154,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | |||
153 | data_len = skb->len - hdrlen - MICHAEL_MIC_LEN; | 154 | data_len = skb->len - hdrlen - MICHAEL_MIC_LEN; |
154 | key = &rx->key->conf.key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY]; | 155 | key = &rx->key->conf.key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY]; |
155 | michael_mic(key, hdr, data, data_len, mic); | 156 | michael_mic(key, hdr, data, data_len, mic); |
156 | if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0) | 157 | if (crypto_memneq(mic, data + data_len, MICHAEL_MIC_LEN)) |
157 | goto mic_fail; | 158 | goto mic_fail; |
158 | 159 | ||
159 | /* remove Michael MIC from payload */ | 160 | /* remove Michael MIC from payload */ |
@@ -1048,7 +1049,7 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx) | |||
1048 | bip_aad(skb, aad); | 1049 | bip_aad(skb, aad); |
1049 | ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad, | 1050 | ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad, |
1050 | skb->data + 24, skb->len - 24, mic); | 1051 | skb->data + 24, skb->len - 24, mic); |
1051 | if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { | 1052 | if (crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) { |
1052 | key->u.aes_cmac.icverrors++; | 1053 | key->u.aes_cmac.icverrors++; |
1053 | return RX_DROP_UNUSABLE; | 1054 | return RX_DROP_UNUSABLE; |
1054 | } | 1055 | } |
@@ -1098,7 +1099,7 @@ ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx) | |||
1098 | bip_aad(skb, aad); | 1099 | bip_aad(skb, aad); |
1099 | ieee80211_aes_cmac_256(key->u.aes_cmac.tfm, aad, | 1100 | ieee80211_aes_cmac_256(key->u.aes_cmac.tfm, aad, |
1100 | skb->data + 24, skb->len - 24, mic); | 1101 | skb->data + 24, skb->len - 24, mic); |
1101 | if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { | 1102 | if (crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) { |
1102 | key->u.aes_cmac.icverrors++; | 1103 | key->u.aes_cmac.icverrors++; |
1103 | return RX_DROP_UNUSABLE; | 1104 | return RX_DROP_UNUSABLE; |
1104 | } | 1105 | } |
@@ -1202,7 +1203,7 @@ ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx) | |||
1202 | if (ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce, | 1203 | if (ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce, |
1203 | skb->data + 24, skb->len - 24, | 1204 | skb->data + 24, skb->len - 24, |
1204 | mic) < 0 || | 1205 | mic) < 0 || |
1205 | memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { | 1206 | crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) { |
1206 | key->u.aes_gmac.icverrors++; | 1207 | key->u.aes_gmac.icverrors++; |
1207 | return RX_DROP_UNUSABLE; | 1208 | return RX_DROP_UNUSABLE; |
1208 | } | 1209 | } |