diff options
author | Johannes Berg <johannes.berg@intel.com> | 2012-06-05 06:16:50 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-06-05 14:27:30 -0400 |
commit | 463454b5dbd8dbab6e2fc6c557329e5b811b9c32 (patch) | |
tree | dd1ada2ac52ffe607a599b3b01854b5869ec6dca /net | |
parent | 0e1fa7ef25004b9c1a14147bce61c15c2f1c6744 (diff) |
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: Mohammed Shafi Shajakhan <mohammed@qca.qualcomm.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/wireless/util.c | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/net/wireless/util.c b/net/wireless/util.c index 55d99466babb..8f2d68fc3a44 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -935,6 +935,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, | |||
935 | enum nl80211_iftype iftype) | 935 | enum nl80211_iftype iftype) |
936 | { | 936 | { |
937 | struct wireless_dev *wdev_iter; | 937 | struct wireless_dev *wdev_iter; |
938 | u32 used_iftypes = BIT(iftype); | ||
938 | int num[NUM_NL80211_IFTYPES]; | 939 | int num[NUM_NL80211_IFTYPES]; |
939 | int total = 1; | 940 | int total = 1; |
940 | int i, j; | 941 | int i, j; |
@@ -961,6 +962,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, | |||
961 | 962 | ||
962 | num[wdev_iter->iftype]++; | 963 | num[wdev_iter->iftype]++; |
963 | total++; | 964 | total++; |
965 | used_iftypes |= BIT(wdev_iter->iftype); | ||
964 | } | 966 | } |
965 | mutex_unlock(&rdev->devlist_mtx); | 967 | mutex_unlock(&rdev->devlist_mtx); |
966 | 968 | ||
@@ -970,6 +972,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, | |||
970 | for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) { | 972 | for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) { |
971 | const struct ieee80211_iface_combination *c; | 973 | const struct ieee80211_iface_combination *c; |
972 | struct ieee80211_iface_limit *limits; | 974 | struct ieee80211_iface_limit *limits; |
975 | u32 all_iftypes = 0; | ||
973 | 976 | ||
974 | c = &rdev->wiphy.iface_combinations[i]; | 977 | c = &rdev->wiphy.iface_combinations[i]; |
975 | 978 | ||
@@ -984,6 +987,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, | |||
984 | if (rdev->wiphy.software_iftypes & BIT(iftype)) | 987 | if (rdev->wiphy.software_iftypes & BIT(iftype)) |
985 | continue; | 988 | continue; |
986 | for (j = 0; j < c->n_limits; j++) { | 989 | for (j = 0; j < c->n_limits; j++) { |
990 | all_iftypes |= limits[j].types; | ||
987 | if (!(limits[j].types & BIT(iftype))) | 991 | if (!(limits[j].types & BIT(iftype))) |
988 | continue; | 992 | continue; |
989 | if (limits[j].max < num[iftype]) | 993 | if (limits[j].max < num[iftype]) |
@@ -991,7 +995,20 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, | |||
991 | limits[j].max -= num[iftype]; | 995 | limits[j].max -= num[iftype]; |
992 | } | 996 | } |
993 | } | 997 | } |
994 | /* yay, it fits */ | 998 | |
999 | /* | ||
1000 | * Finally check that all iftypes that we're currently | ||
1001 | * using are actually part of this combination. If they | ||
1002 | * aren't then we can't use this combination and have | ||
1003 | * to continue to the next. | ||
1004 | */ | ||
1005 | if ((all_iftypes & used_iftypes) != used_iftypes) | ||
1006 | goto cont; | ||
1007 | |||
1008 | /* | ||
1009 | * This combination covered all interface types and | ||
1010 | * supported the requested numbers, so we're good. | ||
1011 | */ | ||
995 | kfree(limits); | 1012 | kfree(limits); |
996 | return 0; | 1013 | return 0; |
997 | cont: | 1014 | cont: |