diff options
-rw-r--r-- | net/wireless/nl80211.c | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index b3d3cf8931cb..afeea32e04ad 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2250,6 +2250,7 @@ static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { }; static int parse_station_flags(struct genl_info *info, + enum nl80211_iftype iftype, struct station_parameters *params) { struct nlattr *flags[NL80211_STA_FLAG_MAX + 1]; @@ -2283,8 +2284,33 @@ static int parse_station_flags(struct genl_info *info, nla, sta_flags_policy)) return -EINVAL; - params->sta_flags_mask = (1 << __NL80211_STA_FLAG_AFTER_LAST) - 1; - params->sta_flags_mask &= ~1; + /* + * Only allow certain flags for interface types so that + * other attributes are silently ignored. Remember that + * this is backward compatibility code with old userspace + * and shouldn't be hit in other cases anyway. + */ + switch (iftype) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_AP_VLAN: + case NL80211_IFTYPE_P2P_GO: + params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) | + BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) | + BIT(NL80211_STA_FLAG_WME) | + BIT(NL80211_STA_FLAG_MFP); + break; + case NL80211_IFTYPE_P2P_CLIENT: + case NL80211_IFTYPE_STATION: + params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) | + BIT(NL80211_STA_FLAG_TDLS_PEER); + break; + case NL80211_IFTYPE_MESH_POINT: + params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHENTICATED) | + BIT(NL80211_STA_FLAG_MFP) | + BIT(NL80211_STA_FLAG_AUTHORIZED); + default: + return -EINVAL; + } for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++) if (flags[flag]) @@ -2585,7 +2611,7 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) if (!rdev->ops->change_station) return -EOPNOTSUPP; - if (parse_station_flags(info, ¶ms)) + if (parse_station_flags(info, dev->ieee80211_ptr->iftype, ¶ms)) return -EINVAL; if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) @@ -2731,7 +2757,7 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) if (!rdev->ops->add_station) return -EOPNOTSUPP; - if (parse_station_flags(info, ¶ms)) + if (parse_station_flags(info, dev->ieee80211_ptr->iftype, ¶ms)) return -EINVAL; switch (dev->ieee80211_ptr->iftype) { |