diff options
Diffstat (limited to 'net/wireless')
| -rw-r--r-- | net/wireless/ibss.c | 5 | ||||
| -rw-r--r-- | net/wireless/mesh.c | 25 | ||||
| -rw-r--r-- | net/wireless/mlme.c | 6 | ||||
| -rw-r--r-- | net/wireless/nl80211.c | 77 | ||||
| -rw-r--r-- | net/wireless/scan.c | 5 | ||||
| -rw-r--r-- | net/wireless/sme.c | 2 | ||||
| -rw-r--r-- | net/wireless/trace.h | 12 | ||||
| -rw-r--r-- | net/wireless/wext-core.c | 13 | ||||
| -rw-r--r-- | net/wireless/wext-proc.c | 1 | 
9 files changed, 105 insertions, 41 deletions
| diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index 413d4f4e6334..a1d10993d08a 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c @@ -126,6 +126,11 @@ static int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,  	wdev->ibss_fixed = params->channel_fixed;  	wdev->ibss_dfs_possible = params->userspace_handles_dfs;  	wdev->chandef = params->chandef; +	if (connkeys) { +		params->wep_keys = connkeys->params; +		params->wep_tx_key = connkeys->def; +	} +  #ifdef CONFIG_CFG80211_WEXT  	wdev->wext.ibss.chandef = params->chandef;  #endif diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 51aa55618ef7..b12da6ef3c12 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c @@ -170,9 +170,28 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,  		enum nl80211_bss_scan_width scan_width;  		struct ieee80211_supported_band *sband =  				rdev->wiphy.bands[setup->chandef.chan->band]; -		scan_width = cfg80211_chandef_to_scan_width(&setup->chandef); -		setup->basic_rates = ieee80211_mandatory_rates(sband, -							       scan_width); + +		if (setup->chandef.chan->band == NL80211_BAND_2GHZ) { +			int i; + +			/* +			 * Older versions selected the mandatory rates for +			 * 2.4 GHz as well, but were broken in that only +			 * 1 Mbps was regarded as a mandatory rate. Keep +			 * using just 1 Mbps as the default basic rate for +			 * mesh to be interoperable with older versions. +			 */ +			for (i = 0; i < sband->n_bitrates; i++) { +				if (sband->bitrates[i].bitrate == 10) { +					setup->basic_rates = BIT(i); +					break; +				} +			} +		} else { +			scan_width = cfg80211_chandef_to_scan_width(&setup->chandef); +			setup->basic_rates = ieee80211_mandatory_rates(sband, +								       scan_width); +		}  	}  	err = cfg80211_chandef_dfs_required(&rdev->wiphy, diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index e7c64a8dce54..bbb9907bfa86 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -692,7 +692,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,  	return rdev_mgmt_tx(rdev, wdev, params, cookie);  } -bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm, +bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_dbm,  		      const u8 *buf, size_t len, u32 flags)  {  	struct wiphy *wiphy = wdev->wiphy; @@ -708,7 +708,7 @@ bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm,  		cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE);  	u16 stype; -	trace_cfg80211_rx_mgmt(wdev, freq, sig_mbm); +	trace_cfg80211_rx_mgmt(wdev, freq, sig_dbm);  	stype = (le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE) >> 4;  	if (!(stypes->rx & BIT(stype))) { @@ -735,7 +735,7 @@ bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm,  		/* Indicate the received Action frame to user space */  		if (nl80211_send_mgmt(rdev, wdev, reg->nlportid, -				      freq, sig_mbm, +				      freq, sig_dbm,  				      buf, len, flags, GFP_ATOMIC))  			continue; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 542a4fc0a8d7..9c0dcc8324b0 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -16,6 +16,7 @@  #include <linux/nl80211.h>  #include <linux/rtnetlink.h>  #include <linux/netlink.h> +#include <linux/nospec.h>  #include <linux/etherdevice.h>  #include <net/net_namespace.h>  #include <net/genetlink.h> @@ -734,11 +735,12 @@ struct key_parse {  	bool def_uni, def_multi;  }; -static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k) +static int nl80211_parse_key_new(struct genl_info *info, struct nlattr *key, +				 struct key_parse *k)  {  	struct nlattr *tb[NL80211_KEY_MAX + 1];  	int err = nla_parse_nested(tb, NL80211_KEY_MAX, key, -				   nl80211_key_policy, NULL); +				   nl80211_key_policy, info->extack);  	if (err)  		return err; @@ -771,7 +773,8 @@ static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k)  	if (tb[NL80211_KEY_TYPE]) {  		k->type = nla_get_u32(tb[NL80211_KEY_TYPE]);  		if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES) -			return -EINVAL; +			return genl_err_attr(info, -EINVAL, +					     tb[NL80211_KEY_TYPE]);  	}  	if (tb[NL80211_KEY_DEFAULT_TYPES]) { @@ -779,7 +782,8 @@ static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k)  		err = nla_parse_nested(kdt, NUM_NL80211_KEY_DEFAULT_TYPES - 1,  				       tb[NL80211_KEY_DEFAULT_TYPES], -				       nl80211_key_default_policy, NULL); +				       nl80211_key_default_policy, +				       info->extack);  		if (err)  			return err; @@ -820,8 +824,10 @@ static int nl80211_parse_key_old(struct genl_info *info, struct key_parse *k)  	if (info->attrs[NL80211_ATTR_KEY_TYPE]) {  		k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]); -		if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES) +		if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES) { +			GENL_SET_ERR_MSG(info, "key type out of range");  			return -EINVAL; +		}  	}  	if (info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES]) { @@ -850,31 +856,42 @@ static int nl80211_parse_key(struct genl_info *info, struct key_parse *k)  	k->type = -1;  	if (info->attrs[NL80211_ATTR_KEY]) -		err = nl80211_parse_key_new(info->attrs[NL80211_ATTR_KEY], k); +		err = nl80211_parse_key_new(info, info->attrs[NL80211_ATTR_KEY], k);  	else  		err = nl80211_parse_key_old(info, k);  	if (err)  		return err; -	if (k->def && k->defmgmt) +	if (k->def && k->defmgmt) { +		GENL_SET_ERR_MSG(info, "key with def && defmgmt is invalid");  		return -EINVAL; +	}  	if (k->defmgmt) { -		if (k->def_uni || !k->def_multi) +		if (k->def_uni || !k->def_multi) { +			GENL_SET_ERR_MSG(info, "defmgmt key must be mcast");  			return -EINVAL; +		}  	}  	if (k->idx != -1) {  		if (k->defmgmt) { -			if (k->idx < 4 || k->idx > 5) +			if (k->idx < 4 || k->idx > 5) { +				GENL_SET_ERR_MSG(info, +						 "defmgmt key idx not 4 or 5");  				return -EINVAL; +			}  		} else if (k->def) { -			if (k->idx < 0 || k->idx > 3) +			if (k->idx < 0 || k->idx > 3) { +				GENL_SET_ERR_MSG(info, "def key idx not 0-3");  				return -EINVAL; +			}  		} else { -			if (k->idx < 0 || k->idx > 5) +			if (k->idx < 0 || k->idx > 5) { +				GENL_SET_ERR_MSG(info, "key idx not 0-5");  				return -EINVAL; +			}  		}  	} @@ -883,8 +900,9 @@ static int nl80211_parse_key(struct genl_info *info, struct key_parse *k)  static struct cfg80211_cached_keys *  nl80211_parse_connkeys(struct cfg80211_registered_device *rdev, -		       struct nlattr *keys, bool *no_ht) +		       struct genl_info *info, bool *no_ht)  { +	struct nlattr *keys = info->attrs[NL80211_ATTR_KEYS];  	struct key_parse parse;  	struct nlattr *key;  	struct cfg80211_cached_keys *result; @@ -909,17 +927,22 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,  		memset(&parse, 0, sizeof(parse));  		parse.idx = -1; -		err = nl80211_parse_key_new(key, &parse); +		err = nl80211_parse_key_new(info, key, &parse);  		if (err)  			goto error;  		err = -EINVAL;  		if (!parse.p.key)  			goto error; -		if (parse.idx < 0 || parse.idx > 3) +		if (parse.idx < 0 || parse.idx > 3) { +			GENL_SET_ERR_MSG(info, "key index out of range [0-3]");  			goto error; +		}  		if (parse.def) { -			if (def) +			if (def) { +				GENL_SET_ERR_MSG(info, +						 "only one key can be default");  				goto error; +			}  			def = 1;  			result->def = parse.idx;  			if (!parse.def_uni || !parse.def_multi) @@ -932,6 +955,7 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,  			goto error;  		if (parse.p.cipher != WLAN_CIPHER_SUITE_WEP40 &&  		    parse.p.cipher != WLAN_CIPHER_SUITE_WEP104) { +			GENL_SET_ERR_MSG(info, "connect key must be WEP");  			err = -EINVAL;  			goto error;  		} @@ -947,6 +971,7 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,  	if (result->def < 0) {  		err = -EINVAL; +		GENL_SET_ERR_MSG(info, "need a default/TX key");  		goto error;  	} @@ -2056,20 +2081,22 @@ static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = {  static int parse_txq_params(struct nlattr *tb[],  			    struct ieee80211_txq_params *txq_params)  { +	u8 ac; +  	if (!tb[NL80211_TXQ_ATTR_AC] || !tb[NL80211_TXQ_ATTR_TXOP] ||  	    !tb[NL80211_TXQ_ATTR_CWMIN] || !tb[NL80211_TXQ_ATTR_CWMAX] ||  	    !tb[NL80211_TXQ_ATTR_AIFS])  		return -EINVAL; -	txq_params->ac = nla_get_u8(tb[NL80211_TXQ_ATTR_AC]); +	ac = nla_get_u8(tb[NL80211_TXQ_ATTR_AC]);  	txq_params->txop = nla_get_u16(tb[NL80211_TXQ_ATTR_TXOP]);  	txq_params->cwmin = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMIN]);  	txq_params->cwmax = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMAX]);  	txq_params->aifs = nla_get_u8(tb[NL80211_TXQ_ATTR_AIFS]); -	if (txq_params->ac >= NL80211_NUM_ACS) +	if (ac >= NL80211_NUM_ACS)  		return -EINVAL; - +	txq_params->ac = array_index_nospec(ac, NL80211_NUM_ACS);  	return 0;  } @@ -7820,6 +7847,11 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,  			      intbss->ts_boottime, NL80211_BSS_PAD))  		goto nla_put_failure; +	if (!nl80211_put_signal(msg, intbss->pub.chains, +				intbss->pub.chain_signal, +				NL80211_BSS_CHAIN_SIGNAL)) +		goto nla_put_failure; +  	switch (rdev->wiphy.signal_type) {  	case CFG80211_SIGNAL_TYPE_MBM:  		if (nla_put_u32(msg, NL80211_BSS_SIGNAL_MBM, res->signal)) @@ -8616,9 +8648,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)  	if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {  		bool no_ht = false; -		connkeys = nl80211_parse_connkeys(rdev, -					  info->attrs[NL80211_ATTR_KEYS], -					  &no_ht); +		connkeys = nl80211_parse_connkeys(rdev, info, &no_ht);  		if (IS_ERR(connkeys))  			return PTR_ERR(connkeys); @@ -9022,8 +9052,7 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)  	}  	if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) { -		connkeys = nl80211_parse_connkeys(rdev, -					  info->attrs[NL80211_ATTR_KEYS], NULL); +		connkeys = nl80211_parse_connkeys(rdev, info, NULL);  		if (IS_ERR(connkeys))  			return PTR_ERR(connkeys);  	} @@ -13948,7 +13977,7 @@ void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,  	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||  	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || -	    (from_ap && reason && +	    (reason &&  	     nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason)) ||  	    (from_ap &&  	     nla_put_flag(msg, NL80211_ATTR_DISCONNECTED_BY_AP)) || diff --git a/net/wireless/scan.c b/net/wireless/scan.c index f6c5fe482506..d36c3eb7b931 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -981,6 +981,9 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,  		found->ts = tmp->ts;  		found->ts_boottime = tmp->ts_boottime;  		found->parent_tsf = tmp->parent_tsf; +		found->pub.chains = tmp->pub.chains; +		memcpy(found->pub.chain_signal, tmp->pub.chain_signal, +		       IEEE80211_MAX_CHAINS);  		ether_addr_copy(found->parent_bssid, tmp->parent_bssid);  	} else {  		struct cfg80211_internal_bss *new; @@ -1233,6 +1236,8 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy,  	tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);  	tmp.ts_boottime = data->boottime_ns;  	tmp.parent_tsf = data->parent_tsf; +	tmp.pub.chains = data->chains; +	memcpy(tmp.pub.chain_signal, data->chain_signal, IEEE80211_MAX_CHAINS);  	ether_addr_copy(tmp.parent_bssid, data->parent_bssid);  	signal_valid = abs(data->chan->center_freq - channel->center_freq) <= diff --git a/net/wireless/sme.c b/net/wireless/sme.c index fdb3646274a5..701cfd7acc1b 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -1032,6 +1032,8 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,  	wdev->current_bss = NULL;  	wdev->ssid_len = 0;  	wdev->conn_owner_nlportid = 0; +	kzfree(wdev->connect_keys); +	wdev->connect_keys = NULL;  	nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap); diff --git a/net/wireless/trace.h b/net/wireless/trace.h index f3353fe5b35b..bcfedd39e7a3 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h @@ -2544,20 +2544,20 @@ DEFINE_EVENT(cfg80211_netdev_mac_evt, cfg80211_del_sta,  );  TRACE_EVENT(cfg80211_rx_mgmt, -	TP_PROTO(struct wireless_dev *wdev, int freq, int sig_mbm), -	TP_ARGS(wdev, freq, sig_mbm), +	TP_PROTO(struct wireless_dev *wdev, int freq, int sig_dbm), +	TP_ARGS(wdev, freq, sig_dbm),  	TP_STRUCT__entry(  		WDEV_ENTRY  		__field(int, freq) -		__field(int, sig_mbm) +		__field(int, sig_dbm)  	),  	TP_fast_assign(  		WDEV_ASSIGN;  		__entry->freq = freq; -		__entry->sig_mbm = sig_mbm; +		__entry->sig_dbm = sig_dbm;  	), -	TP_printk(WDEV_PR_FMT ", freq: %d, sig mbm: %d", -		  WDEV_PR_ARG, __entry->freq, __entry->sig_mbm) +	TP_printk(WDEV_PR_FMT ", freq: %d, sig dbm: %d", +		  WDEV_PR_ARG, __entry->freq, __entry->sig_dbm)  );  TRACE_EVENT(cfg80211_mgmt_tx_status, diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c index 6cdb054484d6..9efbfc753347 100644 --- a/net/wireless/wext-core.c +++ b/net/wireless/wext-core.c @@ -1035,18 +1035,23 @@ static int ioctl_standard_call(struct net_device *	dev,  } -int wext_handle_ioctl(struct net *net, struct iwreq *iwr, unsigned int cmd, -		      void __user *arg) +int wext_handle_ioctl(struct net *net, unsigned int cmd, void __user *arg)  {  	struct iw_request_info info = { .cmd = cmd, .flags = 0 }; +	struct iwreq iwr;  	int ret; -	ret = wext_ioctl_dispatch(net, iwr, cmd, &info, +	if (copy_from_user(&iwr, arg, sizeof(iwr))) +		return -EFAULT; + +	iwr.ifr_name[sizeof(iwr.ifr_name) - 1] = 0; + +	ret = wext_ioctl_dispatch(net, &iwr, cmd, &info,  				  ioctl_standard_call,  				  ioctl_private_call);  	if (ret >= 0 &&  	    IW_IS_GET(cmd) && -	    copy_to_user(arg, iwr, sizeof(struct iwreq))) +	    copy_to_user(arg, &iwr, sizeof(struct iwreq)))  		return -EFAULT;  	return ret; diff --git a/net/wireless/wext-proc.c b/net/wireless/wext-proc.c index e98a01c1034f..5511f989ef47 100644 --- a/net/wireless/wext-proc.c +++ b/net/wireless/wext-proc.c @@ -133,7 +133,6 @@ static int seq_open_wireless(struct inode *inode, struct file *file)  }  static const struct file_operations wireless_seq_fops = { -	.owner	 = THIS_MODULE,  	.open    = seq_open_wireless,  	.read    = seq_read,  	.llseek  = seq_lseek, |