diff options
Diffstat (limited to 'net/wireless')
| -rw-r--r-- | net/wireless/Makefile | 1 | ||||
| -rw-r--r-- | net/wireless/core.c | 21 | ||||
| -rw-r--r-- | net/wireless/core.h | 4 | ||||
| -rw-r--r-- | net/wireless/nl80211.c | 176 | ||||
| -rw-r--r-- | net/wireless/pmsr.c | 4 | ||||
| -rw-r--r-- | net/wireless/scan.c | 37 | ||||
| -rw-r--r-- | net/wireless/sme.c | 32 | ||||
| -rw-r--r-- | net/wireless/sysfs.c | 3 | ||||
| -rw-r--r-- | net/wireless/trace.h | 18 | ||||
| -rw-r--r-- | net/wireless/util.c | 4 | 
10 files changed, 253 insertions, 47 deletions
diff --git a/net/wireless/Makefile b/net/wireless/Makefile index 72a224ce8e0a..2eee93985ab0 100644 --- a/net/wireless/Makefile +++ b/net/wireless/Makefile @@ -39,6 +39,7 @@ $(obj)/extra-certs.c: $(CONFIG_CFG80211_EXTRA_REGDB_KEYDIR:"%"=%) \  	@(set -e; \  	  allf=""; \  	  for f in $^ ; do \ +	      test -f $$f || continue;\  	      # similar to hexdump -v -e '1/1 "0x%.2x," "\n"' \  	      thisf=$$(od -An -v -tx1 < $$f | \  	                   sed -e 's/ /\n/g' | \ diff --git a/net/wireless/core.c b/net/wireless/core.c index 037816163e70..45d9afcff6d5 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -514,7 +514,7 @@ use_default_name:  				   &rdev->rfkill_ops, rdev);  	if (!rdev->rfkill) { -		kfree(rdev); +		wiphy_free(&rdev->wiphy);  		return NULL;  	} @@ -859,6 +859,19 @@ int wiphy_register(struct wiphy *wiphy)  		return -EINVAL;  	} +	for (i = 0; i < rdev->wiphy.n_vendor_commands; i++) { +		/* +		 * Validate we have a policy (can be explicitly set to +		 * VENDOR_CMD_RAW_DATA which is non-NULL) and also that +		 * we have at least one of doit/dumpit. +		 */ +		if (WARN_ON(!rdev->wiphy.vendor_commands[i].policy)) +			return -EINVAL; +		if (WARN_ON(!rdev->wiphy.vendor_commands[i].doit && +			    !rdev->wiphy.vendor_commands[i].dumpit)) +			return -EINVAL; +	} +  #ifdef CONFIG_PM  	if (WARN_ON(rdev->wiphy.wowlan && rdev->wiphy.wowlan->n_patterns &&  		    (!rdev->wiphy.wowlan->pattern_min_len || @@ -1397,8 +1410,12 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,  		}  		break;  	case NETDEV_PRE_UP: -		if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) +		if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)) && +		    !(wdev->iftype == NL80211_IFTYPE_AP_VLAN && +		      rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP && +		      wdev->use_4addr))  			return notifier_from_errno(-EOPNOTSUPP); +  		if (rfkill_blocked(rdev->rfkill))  			return notifier_from_errno(-ERFKILL);  		break; diff --git a/net/wireless/core.h b/net/wireless/core.h index 84d36ca7a7ab..ee8388fe4a92 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -531,6 +531,10 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,  void cfg80211_stop_nan(struct cfg80211_registered_device *rdev,  		       struct wireless_dev *wdev); +struct cfg80211_internal_bss * +cfg80211_bss_update(struct cfg80211_registered_device *rdev, +		    struct cfg80211_internal_bss *tmp, +		    bool signal_valid, unsigned long ts);  #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS  #define CFG80211_DEV_WARN_ON(cond)	WARN_ON(cond)  #else diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index c391b560d986..fc83dd179c1a 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -304,8 +304,11 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {  	[NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },  	[NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 }, -	[NL80211_ATTR_MAC] = { .len = ETH_ALEN }, -	[NL80211_ATTR_PREV_BSSID] = { .len = ETH_ALEN }, +	[NL80211_ATTR_MAC] = { .type = NLA_EXACT_LEN_WARN, .len = ETH_ALEN }, +	[NL80211_ATTR_PREV_BSSID] = { +		.type = NLA_EXACT_LEN_WARN, +		.len = ETH_ALEN +	},  	[NL80211_ATTR_KEY] = { .type = NLA_NESTED, },  	[NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY, @@ -356,7 +359,10 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {  	[NL80211_ATTR_MESH_CONFIG] = { .type = NLA_NESTED },  	[NL80211_ATTR_SUPPORT_MESH_AUTH] = { .type = NLA_FLAG }, -	[NL80211_ATTR_HT_CAPABILITY] = { .len = NL80211_HT_CAPABILITY_LEN }, +	[NL80211_ATTR_HT_CAPABILITY] = { +		.type = NLA_EXACT_LEN_WARN, +		.len = NL80211_HT_CAPABILITY_LEN +	},  	[NL80211_ATTR_MGMT_SUBTYPE] = { .type = NLA_U8 },  	[NL80211_ATTR_IE] = NLA_POLICY_VALIDATE_FN(NLA_BINARY, @@ -386,7 +392,10 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {  	[NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },  	[NL80211_ATTR_PID] = { .type = NLA_U32 },  	[NL80211_ATTR_4ADDR] = { .type = NLA_U8 }, -	[NL80211_ATTR_PMKID] = { .len = WLAN_PMKID_LEN }, +	[NL80211_ATTR_PMKID] = { +		.type = NLA_EXACT_LEN_WARN, +		.len = WLAN_PMKID_LEN +	},  	[NL80211_ATTR_DURATION] = { .type = NLA_U32 },  	[NL80211_ATTR_COOKIE] = { .type = NLA_U64 },  	[NL80211_ATTR_TX_RATES] = { .type = NLA_NESTED }, @@ -448,7 +457,10 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {  	[NL80211_ATTR_WDEV] = { .type = NLA_U64 },  	[NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 },  	[NL80211_ATTR_AUTH_DATA] = { .type = NLA_BINARY, }, -	[NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN }, +	[NL80211_ATTR_VHT_CAPABILITY] = { +		.type = NLA_EXACT_LEN_WARN, +		.len = NL80211_VHT_CAPABILITY_LEN +	},  	[NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },  	[NL80211_ATTR_P2P_CTWINDOW] = NLA_POLICY_MAX(NLA_U8, 127),  	[NL80211_ATTR_P2P_OPPPS] = NLA_POLICY_MAX(NLA_U8, 1), @@ -484,7 +496,10 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {  	[NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY },  	[NL80211_ATTR_QOS_MAP] = { .type = NLA_BINARY,  				   .len = IEEE80211_QOS_MAP_LEN_MAX }, -	[NL80211_ATTR_MAC_HINT] = { .len = ETH_ALEN }, +	[NL80211_ATTR_MAC_HINT] = { +		.type = NLA_EXACT_LEN_WARN, +		.len = ETH_ALEN +	},  	[NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 },  	[NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 },  	[NL80211_ATTR_SOCKET_OWNER] = { .type = NLA_FLAG }, @@ -495,7 +510,10 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {  		NLA_POLICY_MAX(NLA_U8, IEEE80211_NUM_UPS - 1),  	[NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 },  	[NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 }, -	[NL80211_ATTR_MAC_MASK] = { .len = ETH_ALEN }, +	[NL80211_ATTR_MAC_MASK] = { +		.type = NLA_EXACT_LEN_WARN, +		.len = ETH_ALEN +	},  	[NL80211_ATTR_WIPHY_SELF_MANAGED_REG] = { .type = NLA_FLAG },  	[NL80211_ATTR_NETNS_FD] = { .type = NLA_U32 },  	[NL80211_ATTR_SCHED_SCAN_DELAY] = { .type = NLA_U32 }, @@ -507,15 +525,21 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {  	[NL80211_ATTR_MU_MIMO_GROUP_DATA] = {  		.len = VHT_MUMIMO_GROUPS_DATA_LEN  	}, -	[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR] = { .len = ETH_ALEN }, +	[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR] = { +		.type = NLA_EXACT_LEN_WARN, +		.len = ETH_ALEN +	},  	[NL80211_ATTR_NAN_MASTER_PREF] = NLA_POLICY_MIN(NLA_U8, 1),  	[NL80211_ATTR_BANDS] = { .type = NLA_U32 },  	[NL80211_ATTR_NAN_FUNC] = { .type = NLA_NESTED },  	[NL80211_ATTR_FILS_KEK] = { .type = NLA_BINARY,  				    .len = FILS_MAX_KEK_LEN }, -	[NL80211_ATTR_FILS_NONCES] = { .len = 2 * FILS_NONCE_LEN }, +	[NL80211_ATTR_FILS_NONCES] = { +		.type = NLA_EXACT_LEN_WARN, +		.len = 2 * FILS_NONCE_LEN +	},  	[NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED] = { .type = NLA_FLAG, }, -	[NL80211_ATTR_BSSID] = { .len = ETH_ALEN }, +	[NL80211_ATTR_BSSID] = { .type = NLA_EXACT_LEN_WARN, .len = ETH_ALEN },  	[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] = { .type = NLA_S8 },  	[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST] = {  		.len = sizeof(struct nl80211_bss_select_rssi_adjust) @@ -528,7 +552,7 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {  	[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] = { .type = NLA_U16 },  	[NL80211_ATTR_FILS_ERP_RRK] = { .type = NLA_BINARY,  					.len = FILS_ERP_MAX_RRK_LEN }, -	[NL80211_ATTR_FILS_CACHE_ID] = { .len = 2 }, +	[NL80211_ATTR_FILS_CACHE_ID] = { .type = NLA_EXACT_LEN_WARN, .len = 2 },  	[NL80211_ATTR_PMK] = { .type = NLA_BINARY, .len = PMK_MAX_LEN },  	[NL80211_ATTR_SCHED_SCAN_MULTI] = { .type = NLA_FLAG },  	[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT] = { .type = NLA_FLAG }, @@ -547,6 +571,9 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {  	[NL80211_ATTR_PEER_MEASUREMENTS] =  		NLA_POLICY_NESTED(nl80211_pmsr_attr_policy),  	[NL80211_ATTR_AIRTIME_WEIGHT] = NLA_POLICY_MIN(NLA_U16, 1), +	[NL80211_ATTR_SAE_PASSWORD] = { .type = NLA_BINARY, +					.len = SAE_PASSWORD_MAX_LEN }, +	[NL80211_ATTR_TWT_RESPONDER] = { .type = NLA_FLAG },  };  /* policy for the key attributes */ @@ -589,10 +616,13 @@ static const struct nla_policy  nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = {  	[NL80211_WOWLAN_TCP_SRC_IPV4] = { .type = NLA_U32 },  	[NL80211_WOWLAN_TCP_DST_IPV4] = { .type = NLA_U32 }, -	[NL80211_WOWLAN_TCP_DST_MAC] = { .len = ETH_ALEN }, +	[NL80211_WOWLAN_TCP_DST_MAC] = { +		.type = NLA_EXACT_LEN_WARN, +		.len = ETH_ALEN +	},  	[NL80211_WOWLAN_TCP_SRC_PORT] = { .type = NLA_U16 },  	[NL80211_WOWLAN_TCP_DST_PORT] = { .type = NLA_U16 }, -	[NL80211_WOWLAN_TCP_DATA_PAYLOAD] = { .len = 1 }, +	[NL80211_WOWLAN_TCP_DATA_PAYLOAD] = { .type = NLA_MIN_LEN, .len = 1 },  	[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ] = {  		.len = sizeof(struct nl80211_wowlan_tcp_data_seq)  	}, @@ -600,8 +630,8 @@ nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = {  		.len = sizeof(struct nl80211_wowlan_tcp_data_token)  	},  	[NL80211_WOWLAN_TCP_DATA_INTERVAL] = { .type = NLA_U32 }, -	[NL80211_WOWLAN_TCP_WAKE_PAYLOAD] = { .len = 1 }, -	[NL80211_WOWLAN_TCP_WAKE_MASK] = { .len = 1 }, +	[NL80211_WOWLAN_TCP_WAKE_PAYLOAD] = { .type = NLA_MIN_LEN, .len = 1 }, +	[NL80211_WOWLAN_TCP_WAKE_MASK] = { .type = NLA_MIN_LEN, .len = 1 },  };  #endif /* CONFIG_PM */ @@ -619,9 +649,18 @@ nl80211_coalesce_policy[NUM_NL80211_ATTR_COALESCE_RULE] = {  /* policy for GTK rekey offload attributes */  static const struct nla_policy  nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = { -	[NL80211_REKEY_DATA_KEK] = { .len = NL80211_KEK_LEN }, -	[NL80211_REKEY_DATA_KCK] = { .len = NL80211_KCK_LEN }, -	[NL80211_REKEY_DATA_REPLAY_CTR] = { .len = NL80211_REPLAY_CTR_LEN }, +	[NL80211_REKEY_DATA_KEK] = { +		.type = NLA_EXACT_LEN_WARN, +		.len = NL80211_KEK_LEN, +	}, +	[NL80211_REKEY_DATA_KCK] = { +		.type = NLA_EXACT_LEN_WARN, +		.len = NL80211_KCK_LEN, +	}, +	[NL80211_REKEY_DATA_REPLAY_CTR] = { +		.type = NLA_EXACT_LEN_WARN, +		.len = NL80211_REPLAY_CTR_LEN +	},  };  static const struct nla_policy @@ -635,7 +674,10 @@ static const struct nla_policy  nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1] = {  	[NL80211_SCHED_SCAN_MATCH_ATTR_SSID] = { .type = NLA_BINARY,  						 .len = IEEE80211_MAX_SSID_LEN }, -	[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID] = { .len = ETH_ALEN }, +	[NL80211_SCHED_SCAN_MATCH_ATTR_BSSID] = { +		.type = NLA_EXACT_LEN_WARN, +		.len = ETH_ALEN +	},  	[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI] = { .type = NLA_U32 },  	[NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI] =  		NLA_POLICY_NESTED(nl80211_match_band_rssi_policy), @@ -667,7 +709,10 @@ nl80211_nan_func_policy[NL80211_NAN_FUNC_ATTR_MAX + 1] = {  	[NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE] = { .type = NLA_FLAG },  	[NL80211_NAN_FUNC_FOLLOW_UP_ID] = { .type = NLA_U8 },  	[NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID] = { .type = NLA_U8 }, -	[NL80211_NAN_FUNC_FOLLOW_UP_DEST] = { .len = ETH_ALEN }, +	[NL80211_NAN_FUNC_FOLLOW_UP_DEST] = { +		.type = NLA_EXACT_LEN_WARN, +		.len = ETH_ALEN +	},  	[NL80211_NAN_FUNC_CLOSE_RANGE] = { .type = NLA_FLAG },  	[NL80211_NAN_FUNC_TTL] = { .type = NLA_U32 },  	[NL80211_NAN_FUNC_SERVICE_INFO] = { .type = NLA_BINARY, @@ -3420,8 +3465,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)  	if (info->attrs[NL80211_ATTR_IFTYPE])  		type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); -	if (!rdev->ops->add_virtual_intf || -	    !(rdev->wiphy.interface_modes & (1 << type))) +	if (!rdev->ops->add_virtual_intf)  		return -EOPNOTSUPP;  	if ((type == NL80211_IFTYPE_P2P_DEVICE || type == NL80211_IFTYPE_NAN || @@ -3440,6 +3484,11 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)  			return err;  	} +	if (!(rdev->wiphy.interface_modes & (1 << type)) && +	    !(type == NL80211_IFTYPE_AP_VLAN && params.use_4addr && +	      rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP)) +		return -EOPNOTSUPP; +  	err = nl80211_parse_mon_options(rdev, type, info, ¶ms);  	if (err < 0)  		return err; @@ -4057,7 +4106,10 @@ static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = {  				    .len = NL80211_MAX_SUPP_RATES },  	[NL80211_TXRATE_HT] = { .type = NLA_BINARY,  				.len = NL80211_MAX_SUPP_HT_RATES }, -	[NL80211_TXRATE_VHT] = { .len = sizeof(struct nl80211_txrate_vht)}, +	[NL80211_TXRATE_VHT] = { +		.type = NLA_EXACT_LEN_WARN, +		.len = sizeof(struct nl80211_txrate_vht), +	},  	[NL80211_TXRATE_GI] = { .type = NLA_U8 },  }; @@ -4398,6 +4450,8 @@ static bool nl80211_valid_auth_type(struct cfg80211_registered_device *rdev,  		return true;  	case NL80211_CMD_CONNECT:  		if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) && +		    !wiphy_ext_feature_isset(&rdev->wiphy, +					     NL80211_EXT_FEATURE_SAE_OFFLOAD) &&  		    auth_type == NL80211_AUTHTYPE_SAE)  			return false; @@ -4588,6 +4642,9 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)  			return PTR_ERR(params.acl);  	} +	params.twt_responder = +		    nla_get_flag(info->attrs[NL80211_ATTR_TWT_RESPONDER]); +  	nl80211_calculate_ap_params(¶ms);  	if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT]) @@ -4856,8 +4913,10 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,  	struct nlattr *sinfoattr, *bss_param;  	hdr = nl80211hdr_put(msg, portid, seq, flags, cmd); -	if (!hdr) +	if (!hdr) { +		cfg80211_sinfo_release_content(sinfo);  		return -1; +	}  	if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||  	    nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr) || @@ -8700,7 +8759,8 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)  static bool nl80211_valid_wpa_versions(u32 wpa_versions)  {  	return !(wpa_versions & ~(NL80211_WPA_VERSION_1 | -				  NL80211_WPA_VERSION_2)); +				  NL80211_WPA_VERSION_2 | +				  NL80211_WPA_VERSION_3));  }  static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) @@ -8936,6 +8996,16 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,  		settings->psk = nla_data(info->attrs[NL80211_ATTR_PMK]);  	} +	if (info->attrs[NL80211_ATTR_SAE_PASSWORD]) { +		if (!wiphy_ext_feature_isset(&rdev->wiphy, +					     NL80211_EXT_FEATURE_SAE_OFFLOAD)) +			return -EINVAL; +		settings->sae_pwd = +			nla_data(info->attrs[NL80211_ATTR_SAE_PASSWORD]); +		settings->sae_pwd_len = +			nla_len(info->attrs[NL80211_ATTR_SAE_PASSWORD]); +	} +  	return 0;  } @@ -12618,6 +12688,29 @@ static int nl80211_crit_protocol_stop(struct sk_buff *skb,  	return 0;  } +static int nl80211_vendor_check_policy(const struct wiphy_vendor_command *vcmd, +				       struct nlattr *attr, +				       struct netlink_ext_ack *extack) +{ +	if (vcmd->policy == VENDOR_CMD_RAW_DATA) { +		if (attr->nla_type & NLA_F_NESTED) { +			NL_SET_ERR_MSG_ATTR(extack, attr, +					    "unexpected nested data"); +			return -EINVAL; +		} + +		return 0; +	} + +	if (!(attr->nla_type & NLA_F_NESTED)) { +		NL_SET_ERR_MSG_ATTR(extack, attr, "expected nested data"); +		return -EINVAL; +	} + +	return nl80211_validate_nested(attr, vcmd->maxattr, vcmd->policy, +				       extack); +} +  static int nl80211_vendor_cmd(struct sk_buff *skb, struct genl_info *info)  {  	struct cfg80211_registered_device *rdev = info->user_ptr[0]; @@ -12676,11 +12769,16 @@ static int nl80211_vendor_cmd(struct sk_buff *skb, struct genl_info *info)  		if (info->attrs[NL80211_ATTR_VENDOR_DATA]) {  			data = nla_data(info->attrs[NL80211_ATTR_VENDOR_DATA]);  			len = nla_len(info->attrs[NL80211_ATTR_VENDOR_DATA]); + +			err = nl80211_vendor_check_policy(vcmd, +					info->attrs[NL80211_ATTR_VENDOR_DATA], +					info->extack); +			if (err) +				return err;  		}  		rdev->cur_cmd_info = info; -		err = rdev->wiphy.vendor_commands[i].doit(&rdev->wiphy, wdev, -							  data, len); +		err = vcmd->doit(&rdev->wiphy, wdev, data, len);  		rdev->cur_cmd_info = NULL;  		return err;  	} @@ -12767,6 +12865,13 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb,  	if (attrbuf[NL80211_ATTR_VENDOR_DATA]) {  		data = nla_data(attrbuf[NL80211_ATTR_VENDOR_DATA]);  		data_len = nla_len(attrbuf[NL80211_ATTR_VENDOR_DATA]); + +		err = nl80211_vendor_check_policy( +				&(*rdev)->wiphy.vendor_commands[vcmd_idx], +				attrbuf[NL80211_ATTR_VENDOR_DATA], +				cb->extack); +		if (err) +			return err;  	}  	/* 0 is the first index - add 1 to parse only once */ @@ -15035,7 +15140,9 @@ void nl80211_send_port_authorized(struct cfg80211_registered_device *rdev,  		return;  	} -	if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid)) +	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || +	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || +	    nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))  		goto nla_put_failure;  	genlmsg_end(msg, hdr); @@ -15325,6 +15432,19 @@ void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,  }  EXPORT_SYMBOL(cfg80211_remain_on_channel_expired); +void cfg80211_tx_mgmt_expired(struct wireless_dev *wdev, u64 cookie, +					struct ieee80211_channel *chan, +					gfp_t gfp) +{ +	struct wiphy *wiphy = wdev->wiphy; +	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); + +	trace_cfg80211_tx_mgmt_expired(wdev, cookie, chan); +	nl80211_send_remain_on_chan_event(NL80211_CMD_FRAME_WAIT_CANCEL, +					  rdev, wdev, cookie, chan, 0, gfp); +} +EXPORT_SYMBOL(cfg80211_tx_mgmt_expired); +  void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,  		      struct station_info *sinfo, gfp_t gfp)  { diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c index 1b190475359a..c09fbf09549d 100644 --- a/net/wireless/pmsr.c +++ b/net/wireless/pmsr.c @@ -1,6 +1,6 @@  /* SPDX-License-Identifier: GPL-2.0 */  /* - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018 - 2019 Intel Corporation   */  #ifndef __PMSR_H  #define __PMSR_H @@ -448,7 +448,7 @@ static int nl80211_pmsr_send_result(struct sk_buff *msg,  	if (res->ap_tsf_valid &&  	    nla_put_u64_64bit(msg, NL80211_PMSR_RESP_ATTR_AP_TSF, -			      res->host_time, NL80211_PMSR_RESP_ATTR_PAD)) +			      res->ap_tsf, NL80211_PMSR_RESP_ATTR_PAD))  		goto error;  	if (res->final && nla_put_flag(msg, NL80211_PMSR_RESP_ATTR_FINAL)) diff --git a/net/wireless/scan.c b/net/wireless/scan.c index c04f5451f89b..d66e6d4b7555 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -1092,17 +1092,17 @@ struct cfg80211_non_tx_bss {  };  /* Returned bss is reference counted and must be cleaned up appropriately. */ -static struct cfg80211_internal_bss * +struct cfg80211_internal_bss *  cfg80211_bss_update(struct cfg80211_registered_device *rdev,  		    struct cfg80211_internal_bss *tmp, -		    bool signal_valid) +		    bool signal_valid, unsigned long ts)  {  	struct cfg80211_internal_bss *found = NULL;  	if (WARN_ON(!tmp->pub.channel))  		return NULL; -	tmp->ts = jiffies; +	tmp->ts = ts;  	spin_lock_bh(&rdev->bss_lock); @@ -1425,7 +1425,8 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,  	signal_valid = abs(data->chan->center_freq - channel->center_freq) <=  		wiphy->max_adj_channel_rssi_comp; -	res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid); +	res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid, +				  jiffies);  	if (!res)  		return NULL; @@ -1601,12 +1602,12 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,  				continue;  			} -			if (seen_indices & BIT(mbssid_index_ie[2])) +			if (seen_indices & BIT_ULL(mbssid_index_ie[2]))  				/* We don't support legacy split of a profile */  				net_dbg_ratelimited("Partial info for BSSID index %d\n",  						    mbssid_index_ie[2]); -			seen_indices |= BIT(mbssid_index_ie[2]); +			seen_indices |= BIT_ULL(mbssid_index_ie[2]);  			non_tx_data->bssid_index = mbssid_index_ie[2];  			non_tx_data->max_bssid_indicator = elem->data[0]; @@ -1842,7 +1843,8 @@ cfg80211_inform_single_bss_frame_data(struct wiphy *wiphy,  	signal_valid = abs(data->chan->center_freq - channel->center_freq) <=  		wiphy->max_adj_channel_rssi_comp; -	res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid); +	res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid, +				  jiffies);  	if (!res)  		return NULL; @@ -1972,6 +1974,27 @@ out:  }  EXPORT_SYMBOL(cfg80211_unlink_bss); +void cfg80211_bss_iter(struct wiphy *wiphy, +		       struct cfg80211_chan_def *chandef, +		       void (*iter)(struct wiphy *wiphy, +				    struct cfg80211_bss *bss, +				    void *data), +		       void *iter_data) +{ +	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); +	struct cfg80211_internal_bss *bss; + +	spin_lock_bh(&rdev->bss_lock); + +	list_for_each_entry(bss, &rdev->bss_list, list) { +		if (!chandef || cfg80211_is_sub_chan(chandef, bss->pub.channel)) +			iter(wiphy, &bss->pub, iter_data); +	} + +	spin_unlock_bh(&rdev->bss_lock); +} +EXPORT_SYMBOL(cfg80211_bss_iter); +  #ifdef CONFIG_CFG80211_WEXT  static struct cfg80211_registered_device *  cfg80211_get_dev_from_ifindex(struct net *net, int ifindex) diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 7d34cb884840..7a6c38ddc65a 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -796,12 +796,36 @@ void cfg80211_connect_done(struct net_device *dev,  	u8 *next;  	if (params->bss) { -		/* Make sure the bss entry provided by the driver is valid. */  		struct cfg80211_internal_bss *ibss = bss_from_pub(params->bss); -		if (WARN_ON(list_empty(&ibss->list))) { -			cfg80211_put_bss(wdev->wiphy, params->bss); -			return; +		if (list_empty(&ibss->list)) { +			struct cfg80211_bss *found = NULL, *tmp = params->bss; + +			found = cfg80211_get_bss(wdev->wiphy, NULL, +						 params->bss->bssid, +						 wdev->ssid, wdev->ssid_len, +						 wdev->conn_bss_type, +						 IEEE80211_PRIVACY_ANY); +			if (found) { +				/* The same BSS is already updated so use it +				 * instead, as it has latest info. +				 */ +				params->bss = found; +			} else { +				/* Update with BSS provided by driver, it will +				 * be freshly added and ref cnted, we can free +				 * the old one. +				 * +				 * signal_valid can be false, as we are not +				 * expecting the BSS to be found. +				 * +				 * keep the old timestamp to avoid confusion +				 */ +				cfg80211_bss_update(rdev, ibss, false, +						    ibss->ts); +			} + +			cfg80211_put_bss(wdev->wiphy, tmp);  		}  	} diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c index 6ab32f6a1961..3ac1f48195d2 100644 --- a/net/wireless/sysfs.c +++ b/net/wireless/sysfs.c @@ -1,11 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only  /*   * This file provides /sys/class/ieee80211/<wiphy name>/   * and some default attributes.   *   * Copyright 2005-2006	Jiri Benc <jbenc@suse.cz>   * Copyright 2006	Johannes Berg <johannes@sipsolutions.net> - * - * This file is GPLv2 as found in COPYING.   */  #include <linux/device.h> diff --git a/net/wireless/trace.h b/net/wireless/trace.h index 2abfff925aac..4fbb91a511ae 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h @@ -2752,6 +2752,24 @@ TRACE_EVENT(cfg80211_ready_on_channel_expired,  		  WDEV_PR_ARG, __entry->cookie, CHAN_PR_ARG)  ); +TRACE_EVENT(cfg80211_tx_mgmt_expired, +	TP_PROTO(struct wireless_dev *wdev, u64 cookie, +		 struct ieee80211_channel *chan), +	TP_ARGS(wdev, cookie, chan), +	TP_STRUCT__entry( +		WDEV_ENTRY +		__field(u64, cookie) +		CHAN_ENTRY +	), +	TP_fast_assign( +		WDEV_ASSIGN; +		__entry->cookie = cookie; +		CHAN_ASSIGN(chan); +	), +	TP_printk(WDEV_PR_FMT ", cookie: %llu, " CHAN_PR_FMT, +		  WDEV_PR_ARG, __entry->cookie, CHAN_PR_ARG) +); +  TRACE_EVENT(cfg80211_new_sta,  	TP_PROTO(struct net_device *netdev, const u8 *mac_addr,  		 struct station_info *sinfo), diff --git a/net/wireless/util.c b/net/wireless/util.c index cf63b635afc0..1c39d6a2e850 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -1246,7 +1246,7 @@ static u32 cfg80211_calculate_bitrate_he(struct rate_info *rate)  	if (rate->he_dcm)  		result /= 2; -	return result; +	return result / 10000;  }  u32 cfg80211_calculate_bitrate(struct rate_info *rate) @@ -1998,7 +1998,7 @@ int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap,  			continue;  		if (supp >= mcs_encoding) { -			max_vht_nss = i; +			max_vht_nss = i + 1;  			break;  		}  	}  | 

