Commit c5549ee4 authored by David S. Miller's avatar David S. Miller

Merge tag 'mac80211-for-davem-2017-06-13' of...

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: default avatarDavid S. Miller <davem@davemloft.net>
parents ace17c36 b3dd8279
...@@ -902,6 +902,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, ...@@ -902,6 +902,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
default: default:
return -EINVAL; return -EINVAL;
} }
sdata->u.ap.req_smps = sdata->smps_mode;
sdata->needed_rx_chains = sdata->local->rx_chains; sdata->needed_rx_chains = sdata->local->rx_chains;
sdata->vif.bss_conf.beacon_int = params->beacon_interval; sdata->vif.bss_conf.beacon_int = params->beacon_interval;
......
...@@ -1531,7 +1531,7 @@ ieee80211_have_rx_timestamp(struct ieee80211_rx_status *status) ...@@ -1531,7 +1531,7 @@ ieee80211_have_rx_timestamp(struct ieee80211_rx_status *status)
return true; return true;
/* can't handle non-legacy preamble yet */ /* can't handle non-legacy preamble yet */
if (status->flag & RX_FLAG_MACTIME_PLCP_START && if (status->flag & RX_FLAG_MACTIME_PLCP_START &&
status->encoding != RX_ENC_LEGACY) status->encoding == RX_ENC_LEGACY)
return true; return true;
return false; return false;
} }
......
...@@ -601,7 +601,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) ...@@ -601,7 +601,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
struct ieee80211_chanctx_conf *chanctx_conf; struct ieee80211_chanctx_conf *chanctx_conf;
struct ieee80211_channel *chan; struct ieee80211_channel *chan;
u32 rate_flags, rates = 0; u32 rates = 0;
sdata_assert_lock(sdata); sdata_assert_lock(sdata);
...@@ -612,7 +612,6 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) ...@@ -612,7 +612,6 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
return; return;
} }
chan = chanctx_conf->def.chan; chan = chanctx_conf->def.chan;
rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def);
rcu_read_unlock(); rcu_read_unlock();
sband = local->hw.wiphy->bands[chan->band]; sband = local->hw.wiphy->bands[chan->band];
shift = ieee80211_vif_get_shift(&sdata->vif); shift = ieee80211_vif_get_shift(&sdata->vif);
...@@ -636,9 +635,6 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) ...@@ -636,9 +635,6 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
*/ */
rates_len = 0; rates_len = 0;
for (i = 0; i < sband->n_bitrates; i++) { for (i = 0; i < sband->n_bitrates; i++) {
if ((rate_flags & sband->bitrates[i].flags)
!= rate_flags)
continue;
rates |= BIT(i); rates |= BIT(i);
rates_len++; rates_len++;
} }
...@@ -2818,7 +2814,7 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband, ...@@ -2818,7 +2814,7 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
u32 *rates, u32 *basic_rates, u32 *rates, u32 *basic_rates,
bool *have_higher_than_11mbit, bool *have_higher_than_11mbit,
int *min_rate, int *min_rate_index, int *min_rate, int *min_rate_index,
int shift, u32 rate_flags) int shift)
{ {
int i, j; int i, j;
...@@ -2846,8 +2842,6 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband, ...@@ -2846,8 +2842,6 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
int brate; int brate;
br = &sband->bitrates[j]; br = &sband->bitrates[j];
if ((rate_flags & br->flags) != rate_flags)
continue;
brate = DIV_ROUND_UP(br->bitrate, (1 << shift) * 5); brate = DIV_ROUND_UP(br->bitrate, (1 << shift) * 5);
if (brate == rate) { if (brate == rate) {
...@@ -4398,40 +4392,32 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, ...@@ -4398,40 +4392,32 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
return -ENOMEM; return -ENOMEM;
} }
if (new_sta || override) { /*
err = ieee80211_prep_channel(sdata, cbss); * Set up the information for the new channel before setting the
if (err) { * new channel. We can't - completely race-free - change the basic
if (new_sta) * rates bitmap and the channel (sband) that it refers to, but if
sta_info_free(local, new_sta); * we set it up before we at least avoid calling into the driver's
return -EINVAL; * bss_info_changed() method with invalid information (since we do
} * call that from changing the channel - only for IDLE and perhaps
} * some others, but ...).
*
* So to avoid that, just set up all the new information before the
* channel, but tell the driver to apply it only afterwards, since
* it might need the new channel for that.
*/
if (new_sta) { if (new_sta) {
u32 rates = 0, basic_rates = 0; u32 rates = 0, basic_rates = 0;
bool have_higher_than_11mbit; bool have_higher_than_11mbit;
int min_rate = INT_MAX, min_rate_index = -1; int min_rate = INT_MAX, min_rate_index = -1;
struct ieee80211_chanctx_conf *chanctx_conf;
const struct cfg80211_bss_ies *ies; const struct cfg80211_bss_ies *ies;
int shift = ieee80211_vif_get_shift(&sdata->vif); int shift = ieee80211_vif_get_shift(&sdata->vif);
u32 rate_flags;
rcu_read_lock();
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (WARN_ON(!chanctx_conf)) {
rcu_read_unlock();
sta_info_free(local, new_sta);
return -EINVAL;
}
rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def);
rcu_read_unlock();
ieee80211_get_rates(sband, bss->supp_rates, ieee80211_get_rates(sband, bss->supp_rates,
bss->supp_rates_len, bss->supp_rates_len,
&rates, &basic_rates, &rates, &basic_rates,
&have_higher_than_11mbit, &have_higher_than_11mbit,
&min_rate, &min_rate_index, &min_rate, &min_rate_index,
shift, rate_flags); shift);
/* /*
* This used to be a workaround for basic rates missing * 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,8 +4475,22 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
sdata->vif.bss_conf.sync_dtim_count = 0; sdata->vif.bss_conf.sync_dtim_count = 0;
} }
rcu_read_unlock(); rcu_read_unlock();
}
/* tell driver about BSSID, basic rates and timing */ if (new_sta || override) {
err = ieee80211_prep_channel(sdata, cbss);
if (err) {
if (new_sta)
sta_info_free(local, new_sta);
return -EINVAL;
}
}
if (new_sta) {
/*
* tell driver about BSSID, basic rates and timing
* this was set up above, before setting the channel
*/
ieee80211_bss_info_change_notify(sdata, ieee80211_bss_info_change_notify(sdata,
BSS_CHANGED_BSSID | BSS_CHANGED_BASIC_RATES | BSS_CHANGED_BSSID | BSS_CHANGED_BASIC_RATES |
BSS_CHANGED_BEACON_INT); BSS_CHANGED_BEACON_INT);
......
...@@ -1613,12 +1613,16 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) ...@@ -1613,12 +1613,16 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
*/ */
if (!ieee80211_hw_check(&sta->local->hw, AP_LINK_PS) && if (!ieee80211_hw_check(&sta->local->hw, AP_LINK_PS) &&
!ieee80211_has_morefrags(hdr->frame_control) && !ieee80211_has_morefrags(hdr->frame_control) &&
!ieee80211_is_back_req(hdr->frame_control) &&
!(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) &&
(rx->sdata->vif.type == NL80211_IFTYPE_AP || (rx->sdata->vif.type == NL80211_IFTYPE_AP ||
rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
/* PM bit is only checked in frames where it isn't reserved, /*
* PM bit is only checked in frames where it isn't reserved,
* in AP mode it's reserved in non-bufferable management frames * in AP mode it's reserved in non-bufferable management frames
* (cf. IEEE 802.11-2012 8.2.4.1.7 Power Management field) * (cf. IEEE 802.11-2012 8.2.4.1.7 Power Management field)
* BAR frames should be ignored as specified in
* IEEE 802.11-2012 10.2.1.2.
*/ */
(!ieee80211_is_mgmt(hdr->frame_control) || (!ieee80211_is_mgmt(hdr->frame_control) ||
ieee80211_is_bufferable_mmpdu(hdr->frame_control))) { ieee80211_is_bufferable_mmpdu(hdr->frame_control))) {
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include <net/mac80211.h> #include <net/mac80211.h>
#include <crypto/aes.h> #include <crypto/aes.h>
#include <crypto/algapi.h>
#include "ieee80211_i.h" #include "ieee80211_i.h"
#include "michael.h" #include "michael.h"
...@@ -153,7 +154,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) ...@@ -153,7 +154,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
data_len = skb->len - hdrlen - MICHAEL_MIC_LEN; data_len = skb->len - hdrlen - MICHAEL_MIC_LEN;
key = &rx->key->conf.key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY]; key = &rx->key->conf.key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY];
michael_mic(key, hdr, data, data_len, mic); michael_mic(key, hdr, data, data_len, mic);
if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0) if (crypto_memneq(mic, data + data_len, MICHAEL_MIC_LEN))
goto mic_fail; goto mic_fail;
/* remove Michael MIC from payload */ /* remove Michael MIC from payload */
...@@ -1048,7 +1049,7 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx) ...@@ -1048,7 +1049,7 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx)
bip_aad(skb, aad); bip_aad(skb, aad);
ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad, ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad,
skb->data + 24, skb->len - 24, mic); skb->data + 24, skb->len - 24, mic);
if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { if (crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) {
key->u.aes_cmac.icverrors++; key->u.aes_cmac.icverrors++;
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
} }
...@@ -1098,7 +1099,7 @@ ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx) ...@@ -1098,7 +1099,7 @@ ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx)
bip_aad(skb, aad); bip_aad(skb, aad);
ieee80211_aes_cmac_256(key->u.aes_cmac.tfm, aad, ieee80211_aes_cmac_256(key->u.aes_cmac.tfm, aad,
skb->data + 24, skb->len - 24, mic); skb->data + 24, skb->len - 24, mic);
if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { if (crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) {
key->u.aes_cmac.icverrors++; key->u.aes_cmac.icverrors++;
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
} }
...@@ -1202,7 +1203,7 @@ ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx) ...@@ -1202,7 +1203,7 @@ ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx)
if (ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce, if (ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce,
skb->data + 24, skb->len - 24, skb->data + 24, skb->len - 24,
mic) < 0 || mic) < 0 ||
memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) {
key->u.aes_gmac.icverrors++; key->u.aes_gmac.icverrors++;
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment