Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 584991dc authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville
Browse files

cfg80211: validate scan channels



Currently it is possible to request a scan on only
disabled channels, which could be problematic for
some drivers. Reject such scans, and also ignore
disabled channels that are given. This resuls in
the scan begin/end event only including channels
that are actually used.

This makes the mac80211 check for disabled channels
superfluous. At the same time, remove the no-IBSS
check from mac80211 -- nothing says that we should
not find any networks on channels that cannot be
used for an IBSS, even when operating in IBSS mode.

Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 6c085227
Loading
Loading
Loading
Loading
+2 −11
Original line number Original line Diff line number Diff line
@@ -614,22 +614,13 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
{
{
	int skip;
	int skip;
	struct ieee80211_channel *chan;
	struct ieee80211_channel *chan;
	struct ieee80211_sub_if_data *sdata = local->scan_sdata;


	skip = 0;
	skip = 0;
	chan = local->scan_req->channels[local->scan_channel_idx];
	chan = local->scan_req->channels[local->scan_channel_idx];


	if (chan->flags & IEEE80211_CHAN_DISABLED ||
	    (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
	     chan->flags & IEEE80211_CHAN_NO_IBSS))
		skip = 1;

	if (!skip) {
	local->scan_channel = chan;
	local->scan_channel = chan;
		if (ieee80211_hw_config(local,
	if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL))
					IEEE80211_CONF_CHANGE_CHANNEL))
		skip = 1;
		skip = 1;
	}


	/* advance state machine to next channel/band */
	/* advance state machine to next channel/band */
	local->scan_channel_idx++;
	local->scan_channel_idx++;
+27 −7
Original line number Original line Diff line number Diff line
@@ -2988,7 +2988,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
		goto out;
		goto out;
	}
	}


	request->n_channels = n_channels;
	if (n_ssids)
	if (n_ssids)
		request->ssids = (void *)&request->channels[n_channels];
		request->ssids = (void *)&request->channels[n_channels];
	request->n_ssids = n_ssids;
	request->n_ssids = n_ssids;
@@ -2999,32 +2998,53 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
			request->ie = (void *)(request->channels + n_channels);
			request->ie = (void *)(request->channels + n_channels);
	}
	}


	i = 0;
	if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
	if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
		/* user specified, bail out if channel not found */
		/* user specified, bail out if channel not found */
		request->n_channels = n_channels;
		i = 0;
		nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_FREQUENCIES], tmp) {
		nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_FREQUENCIES], tmp) {
			request->channels[i] = ieee80211_get_channel(wiphy, nla_get_u32(attr));
			struct ieee80211_channel *chan;
			if (!request->channels[i]) {

			chan = ieee80211_get_channel(wiphy, nla_get_u32(attr));

			if (!chan) {
				err = -EINVAL;
				err = -EINVAL;
				goto out_free;
				goto out_free;
			}
			}

			/* ignore disabled channels */
			if (chan->flags & IEEE80211_CHAN_DISABLED)
				continue;

			request->channels[i] = chan;
			i++;
			i++;
		}
		}
	} else {
	} else {
		/* all channels */
		/* all channels */
		i = 0;
		for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
		for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
			int j;
			int j;
			if (!wiphy->bands[band])
			if (!wiphy->bands[band])
				continue;
				continue;
			for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
			for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
				request->channels[i] = &wiphy->bands[band]->channels[j];
				struct ieee80211_channel *chan;

				chan = &wiphy->bands[band]->channels[j];

				if (chan->flags & IEEE80211_CHAN_DISABLED)
					continue;

				request->channels[i] = chan;
				i++;
				i++;
			}
			}
		}
		}
	}
	}


	if (!i) {
		err = -EINVAL;
		goto out_free;
	}

	request->n_channels = i;

	i = 0;
	i = 0;
	if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) {
	if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) {
		nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) {
		nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) {
+6 −0
Original line number Original line Diff line number Diff line
@@ -650,9 +650,15 @@ int cfg80211_wext_siwscan(struct net_device *dev,
	i = 0;
	i = 0;
	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
		int j;
		int j;

		if (!wiphy->bands[band])
		if (!wiphy->bands[band])
			continue;
			continue;

		for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
		for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
			/* ignore disabled channels */
			if (wiphy->bands[band]->channels[j].flags &
						IEEE80211_CHAN_DISABLED)
				continue;


			/* If we have a wireless request structure and the
			/* If we have a wireless request structure and the
			 * wireless request specifies frequencies, then search
			 * wireless request specifies frequencies, then search