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

Commit 463454b5 authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville
Browse files

cfg80211: fix interface combinations check



If a given interface combination doesn't contain
a required interface type then we missed checking
that and erroneously allowed it even though iface
type wasn't there at all. Add a check that makes
sure that all interface types are accounted for.

Cc: stable@kernel.org
Reported-by: default avatarMohammed Shafi Shajakhan <mohammed@qca.qualcomm.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 0e1fa7ef
Loading
Loading
Loading
Loading
+18 −1
Original line number Original line Diff line number Diff line
@@ -935,6 +935,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
				  enum nl80211_iftype iftype)
				  enum nl80211_iftype iftype)
{
{
	struct wireless_dev *wdev_iter;
	struct wireless_dev *wdev_iter;
	u32 used_iftypes = BIT(iftype);
	int num[NUM_NL80211_IFTYPES];
	int num[NUM_NL80211_IFTYPES];
	int total = 1;
	int total = 1;
	int i, j;
	int i, j;
@@ -961,6 +962,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,


		num[wdev_iter->iftype]++;
		num[wdev_iter->iftype]++;
		total++;
		total++;
		used_iftypes |= BIT(wdev_iter->iftype);
	}
	}
	mutex_unlock(&rdev->devlist_mtx);
	mutex_unlock(&rdev->devlist_mtx);


@@ -970,6 +972,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
	for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) {
	for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) {
		const struct ieee80211_iface_combination *c;
		const struct ieee80211_iface_combination *c;
		struct ieee80211_iface_limit *limits;
		struct ieee80211_iface_limit *limits;
		u32 all_iftypes = 0;


		c = &rdev->wiphy.iface_combinations[i];
		c = &rdev->wiphy.iface_combinations[i];


@@ -984,6 +987,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
			if (rdev->wiphy.software_iftypes & BIT(iftype))
			if (rdev->wiphy.software_iftypes & BIT(iftype))
				continue;
				continue;
			for (j = 0; j < c->n_limits; j++) {
			for (j = 0; j < c->n_limits; j++) {
				all_iftypes |= limits[j].types;
				if (!(limits[j].types & BIT(iftype)))
				if (!(limits[j].types & BIT(iftype)))
					continue;
					continue;
				if (limits[j].max < num[iftype])
				if (limits[j].max < num[iftype])
@@ -991,7 +995,20 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
				limits[j].max -= num[iftype];
				limits[j].max -= num[iftype];
			}
			}
		}
		}
		/* yay, it fits */

		/*
		 * Finally check that all iftypes that we're currently
		 * using are actually part of this combination. If they
		 * aren't then we can't use this combination and have
		 * to continue to the next.
		 */
		if ((all_iftypes & used_iftypes) != used_iftypes)
			goto cont;

		/*
		 * This combination covered all interface types and
		 * supported the requested numbers, so we're good.
		 */
		kfree(limits);
		kfree(limits);
		return 0;
		return 0;
 cont:
 cont: