Commit fc3e3bf5 authored by David S. Miller's avatar David S. Miller
Browse files

Merge tag 'mac80211-for-davem-2018-09-03' of...

Merge tag 'mac80211-for-davem-2018-09-03' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211



Johannes Berg says:

====================
Here are quite a large number of fixes, notably:
 * various A-MSDU building fixes (currently only affects mt76)
 * syzkaller & spectre fixes in hwsim
 * TXQ vs. teardown fix that was causing crashes
 * embed WMM info in reg rule, bad code here had been causing crashes
 * one compilation issue with fix from Arnd (rfkill-gpio includes)
 * fixes for a race and bad data during/after channel switch
 * nl80211: a validation fix, attribute type & unit fixes
along with other small fixes.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a484ef34 c6e57b38
Loading
Loading
Loading
Loading
+5 −45
Original line number Diff line number Diff line
@@ -985,15 +985,12 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
	const u8 *nvm_chan = cfg->nvm_type == IWL_NVM_EXT ?
			     iwl_ext_nvm_channels : iwl_nvm_channels;
	struct ieee80211_regdomain *regd, *copy_rd;
	int size_of_regd, regd_to_copy, wmms_to_copy;
	int size_of_wmms = 0;
	int size_of_regd, regd_to_copy;
	struct ieee80211_reg_rule *rule;
	struct ieee80211_wmm_rule *wmm_rule, *d_wmm, *s_wmm;
	struct regdb_ptrs *regdb_ptrs;
	enum nl80211_band band;
	int center_freq, prev_center_freq = 0;
	int valid_rules = 0, n_wmms = 0;
	int i;
	int valid_rules = 0;
	bool new_rule;
	int max_num_ch = cfg->nvm_type == IWL_NVM_EXT ?
			 IWL_NVM_NUM_CHANNELS_EXT : IWL_NVM_NUM_CHANNELS;
@@ -1012,11 +1009,7 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
		sizeof(struct ieee80211_regdomain) +
		num_of_ch * sizeof(struct ieee80211_reg_rule);

	if (geo_info & GEO_WMM_ETSI_5GHZ_INFO)
		size_of_wmms =
			num_of_ch * sizeof(struct ieee80211_wmm_rule);

	regd = kzalloc(size_of_regd + size_of_wmms, GFP_KERNEL);
	regd = kzalloc(size_of_regd, GFP_KERNEL);
	if (!regd)
		return ERR_PTR(-ENOMEM);

@@ -1030,8 +1023,6 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
	regd->alpha2[0] = fw_mcc >> 8;
	regd->alpha2[1] = fw_mcc & 0xff;

	wmm_rule = (struct ieee80211_wmm_rule *)((u8 *)regd + size_of_regd);

	for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) {
		ch_flags = (u16)__le32_to_cpup(channels + ch_idx);
		band = (ch_idx < NUM_2GHZ_CHANNELS) ?
@@ -1085,26 +1076,10 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
		    band == NL80211_BAND_2GHZ)
			continue;

		if (!reg_query_regdb_wmm(regd->alpha2, center_freq,
					 &regdb_ptrs[n_wmms].token, wmm_rule)) {
			/* Add only new rules */
			for (i = 0; i < n_wmms; i++) {
				if (regdb_ptrs[i].token ==
				    regdb_ptrs[n_wmms].token) {
					rule->wmm_rule = regdb_ptrs[i].rule;
					break;
				}
			}
			if (i == n_wmms) {
				rule->wmm_rule = wmm_rule;
				regdb_ptrs[n_wmms++].rule = wmm_rule;
				wmm_rule++;
			}
		}
		reg_query_regdb_wmm(regd->alpha2, center_freq, rule);
	}

	regd->n_reg_rules = valid_rules;
	regd->n_wmm_rules = n_wmms;

	/*
	 * Narrow down regdom for unused regulatory rules to prevent hole
@@ -1113,28 +1088,13 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
	regd_to_copy = sizeof(struct ieee80211_regdomain) +
		valid_rules * sizeof(struct ieee80211_reg_rule);

	wmms_to_copy = sizeof(struct ieee80211_wmm_rule) * n_wmms;

	copy_rd = kzalloc(regd_to_copy + wmms_to_copy, GFP_KERNEL);
	copy_rd = kzalloc(regd_to_copy, GFP_KERNEL);
	if (!copy_rd) {
		copy_rd = ERR_PTR(-ENOMEM);
		goto out;
	}

	memcpy(copy_rd, regd, regd_to_copy);
	memcpy((u8 *)copy_rd + regd_to_copy, (u8 *)regd + size_of_regd,
	       wmms_to_copy);

	d_wmm = (struct ieee80211_wmm_rule *)((u8 *)copy_rd + regd_to_copy);
	s_wmm = (struct ieee80211_wmm_rule *)((u8 *)regd + size_of_regd);

	for (i = 0; i < regd->n_reg_rules; i++) {
		if (!regd->reg_rules[i].wmm_rule)
			continue;

		copy_rd->reg_rules[i].wmm_rule = d_wmm +
			(regd->reg_rules[i].wmm_rule - s_wmm);
	}

out:
	kfree(regdb_ptrs);
+9 −3
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@
#include <net/net_namespace.h>
#include <net/netns/generic.h>
#include <linux/rhashtable.h>
#include <linux/nospec.h>
#include "mac80211_hwsim.h"

#define WARN_QUEUE 100
@@ -2820,9 +2821,6 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
				IEEE80211_VHT_CAP_SHORT_GI_80 |
				IEEE80211_VHT_CAP_SHORT_GI_160 |
				IEEE80211_VHT_CAP_TXSTBC |
				IEEE80211_VHT_CAP_RXSTBC_1 |
				IEEE80211_VHT_CAP_RXSTBC_2 |
				IEEE80211_VHT_CAP_RXSTBC_3 |
				IEEE80211_VHT_CAP_RXSTBC_4 |
				IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
			sband->vht_cap.vht_mcs.rx_mcs_map =
@@ -3317,6 +3315,11 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
	if (info->attrs[HWSIM_ATTR_CHANNELS])
		param.channels = nla_get_u32(info->attrs[HWSIM_ATTR_CHANNELS]);

	if (param.channels < 1) {
		GENL_SET_ERR_MSG(info, "must have at least one channel");
		return -EINVAL;
	}

	if (param.channels > CFG80211_MAX_NUM_DIFFERENT_CHANNELS) {
		GENL_SET_ERR_MSG(info, "too many channels specified");
		return -EINVAL;
@@ -3350,6 +3353,9 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
			kfree(hwname);
			return -EINVAL;
		}

		idx = array_index_nospec(idx,
					 ARRAY_SIZE(hwsim_world_regdom_custom));
		param.regd = hwsim_world_regdom_custom[idx];
	}

+2 −2
Original line number Diff line number Diff line
@@ -4865,8 +4865,8 @@ const char *reg_initiator_name(enum nl80211_reg_initiator initiator);
 *
 * Return: 0 on success. -ENODATA.
 */
int reg_query_regdb_wmm(char *alpha2, int freq, u32 *ptr,
			struct ieee80211_wmm_rule *rule);
int reg_query_regdb_wmm(char *alpha2, int freq,
			struct ieee80211_reg_rule *rule);

/*
 * callbacks for asynchronous cfg80211 methods, notification
+2 −2
Original line number Diff line number Diff line
@@ -217,15 +217,15 @@ struct ieee80211_wmm_rule {
struct ieee80211_reg_rule {
	struct ieee80211_freq_range freq_range;
	struct ieee80211_power_rule power_rule;
	struct ieee80211_wmm_rule *wmm_rule;
	struct ieee80211_wmm_rule wmm_rule;
	u32 flags;
	u32 dfs_cac_ms;
	bool has_wmm;
};

struct ieee80211_regdomain {
	struct rcu_head rcu_head;
	u32 n_reg_rules;
	u32 n_wmm_rules;
	char alpha2[3];
	enum nl80211_dfs_regions dfs_region;
	struct ieee80211_reg_rule reg_rules[];
+11 −11
Original line number Diff line number Diff line
@@ -947,8 +947,8 @@ static void ieee80211_rx_mgmt_deauth_ibss(struct ieee80211_sub_if_data *sdata,
	if (len < IEEE80211_DEAUTH_FRAME_LEN)
		return;

	ibss_dbg(sdata, "RX DeAuth SA=%pM DA=%pM BSSID=%pM (reason: %d)\n",
		 mgmt->sa, mgmt->da, mgmt->bssid, reason);
	ibss_dbg(sdata, "RX DeAuth SA=%pM DA=%pM\n", mgmt->sa, mgmt->da);
	ibss_dbg(sdata, "\tBSSID=%pM (reason: %d)\n", mgmt->bssid, reason);
	sta_info_destroy_addr(sdata, mgmt->sa);
}

@@ -966,9 +966,9 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
	auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
	auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);

	ibss_dbg(sdata,
		 "RX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=%d)\n",
		 mgmt->sa, mgmt->da, mgmt->bssid, auth_transaction);
	ibss_dbg(sdata, "RX Auth SA=%pM DA=%pM\n", mgmt->sa, mgmt->da);
	ibss_dbg(sdata, "\tBSSID=%pM (auth_transaction=%d)\n",
		 mgmt->bssid, auth_transaction);

	if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1)
		return;
@@ -1175,10 +1175,10 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
		rx_timestamp = drv_get_tsf(local, sdata);
	}

	ibss_dbg(sdata,
		 "RX beacon SA=%pM BSSID=%pM TSF=0x%llx BCN=0x%llx diff=%lld @%lu\n",
	ibss_dbg(sdata, "RX beacon SA=%pM BSSID=%pM TSF=0x%llx\n",
		 mgmt->sa, mgmt->bssid,
		 (unsigned long long)rx_timestamp,
		 (unsigned long long)rx_timestamp);
	ibss_dbg(sdata, "\tBCN=0x%llx diff=%lld @%lu\n",
		 (unsigned long long)beacon_timestamp,
		 (unsigned long long)(rx_timestamp - beacon_timestamp),
		 jiffies);
@@ -1537,9 +1537,9 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,

	tx_last_beacon = drv_tx_last_beacon(local);

	ibss_dbg(sdata,
		 "RX ProbeReq SA=%pM DA=%pM BSSID=%pM (tx_last_beacon=%d)\n",
		 mgmt->sa, mgmt->da, mgmt->bssid, tx_last_beacon);
	ibss_dbg(sdata, "RX ProbeReq SA=%pM DA=%pM\n", mgmt->sa, mgmt->da);
	ibss_dbg(sdata, "\tBSSID=%pM (tx_last_beacon=%d)\n",
		 mgmt->bssid, tx_last_beacon);

	if (!tx_last_beacon && is_multicast_ether_addr(mgmt->da))
		return;
Loading