]> www.infradead.org Git - users/hch/misc.git/commitdiff
wifi: nl80211: strict checking attributes for NL80211_CMD_SET_BSS
authorArend van Spriel <arend.vanspriel@broadcom.com>
Sun, 17 Aug 2025 19:04:34 +0000 (21:04 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Thu, 4 Sep 2025 09:19:02 +0000 (11:19 +0200)
Assure user-space only modifies attributes for NL80211_CMD_SET_BSS
that are supported by the driver. This stricter checking is only done
when user-space commits to it by including NL80211_ATTR_BSS_PARAM.

Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Link: https://patch.msgid.link/20250817190435.1495094-4-arend.vanspriel@broadcom.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/uapi/linux/nl80211.h
net/wireless/nl80211.c

index 6c07100fc01f48a0317fb1b5fbf92eee44540122..aed0b4c5d5e8c6be72425178ce0250f1cde599cc 100644 (file)
@@ -2931,7 +2931,10 @@ enum nl80211_commands {
  *     @enum nl80211_s1g_short_beacon_attrs for the attribute definitions.
  *
  * @NL80211_ATTR_BSS_PARAM: nested attribute used with %NL80211_CMD_GET_WIPHY
- *     which indicates which BSS parameters can be modified.
+ *     which indicates which BSS parameters can be modified. The attribute can
+ *     also be used as flag attribute by user-space in %NL80211_CMD_SET_BSS to
+ *     indicate that it wants strict checking on the BSS parameters to be
+ *     modified.
  *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
index 153644a040723af474fb29121a9f930fffc3f9b4..99e2aadc65f74720f6a1be6a07862725d9a0abf8 100644 (file)
@@ -879,6 +879,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
        [NL80211_ATTR_S1G_LONG_BEACON_PERIOD] = NLA_POLICY_MIN(NLA_U8, 2),
        [NL80211_ATTR_S1G_SHORT_BEACON] =
                NLA_POLICY_NESTED(nl80211_s1g_short_beacon),
+       [NL80211_ATTR_BSS_PARAM] = { .type = NLA_FLAG },
 };
 
 /* policy for the key attributes */
@@ -9083,6 +9084,8 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
        struct net_device *dev = info->user_ptr[1];
        struct bss_parameters params;
        u32 bss_param_support = rdev->wiphy.bss_param_support;
+       u32 changed = 0;
+       bool strict;
 
        memset(&params, 0, sizeof(params));
        params.link_id = nl80211_link_id_or_invalid(info->attrs);
@@ -9095,26 +9098,54 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
        params.p2p_ctwindow = -1;
        params.p2p_opp_ps = -1;
 
-       if (info->attrs[NL80211_ATTR_BSS_CTS_PROT])
+       strict = nla_get_flag(info->attrs[NL80211_ATTR_BSS_PARAM]);
+       if (info->attrs[NL80211_ATTR_BSS_CTS_PROT]) {
+               if (strict && !(bss_param_support & WIPHY_BSS_PARAM_CTS_PROT))
+                       return -EINVAL;
                params.use_cts_prot =
                    nla_get_u8(info->attrs[NL80211_ATTR_BSS_CTS_PROT]);
-       if (info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE])
+               changed |= WIPHY_BSS_PARAM_CTS_PROT;
+       }
+       if (info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE]) {
+               if (strict &&
+                   !(bss_param_support & WIPHY_BSS_PARAM_SHORT_PREAMBLE))
+                       return -EINVAL;
                params.use_short_preamble =
                    nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE]);
-       if (info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME])
+               changed |= WIPHY_BSS_PARAM_SHORT_PREAMBLE;
+       }
+       if (info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]) {
+               if (strict &&
+                   !(bss_param_support & WIPHY_BSS_PARAM_SHORT_SLOT_TIME))
+                       return -EINVAL;
                params.use_short_slot_time =
                    nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]);
+               changed |= WIPHY_BSS_PARAM_SHORT_SLOT_TIME;
+       }
        if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
+               if (strict &&
+                   !(bss_param_support & WIPHY_BSS_PARAM_BASIC_RATES))
+                       return -EINVAL;
                params.basic_rates =
                        nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
                params.basic_rates_len =
                        nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
+               changed |= WIPHY_BSS_PARAM_BASIC_RATES;
        }
-       if (info->attrs[NL80211_ATTR_AP_ISOLATE])
-               params.ap_isolate = !!nla_get_u8(info->attrs[NL80211_ATTR_AP_ISOLATE]);
-       if (info->attrs[NL80211_ATTR_BSS_HT_OPMODE])
+       if (info->attrs[NL80211_ATTR_AP_ISOLATE]) {
+               if (strict && !(bss_param_support & WIPHY_BSS_PARAM_AP_ISOLATE))
+                       return -EINVAL;
+               params.ap_isolate =
+                       !!nla_get_u8(info->attrs[NL80211_ATTR_AP_ISOLATE]);
+               changed |= WIPHY_BSS_PARAM_AP_ISOLATE;
+       }
+       if (info->attrs[NL80211_ATTR_BSS_HT_OPMODE]) {
+               if (strict && !(bss_param_support & WIPHY_BSS_PARAM_HT_OPMODE))
+                       return -EINVAL;
                params.ht_opmode =
                        nla_get_u16(info->attrs[NL80211_ATTR_BSS_HT_OPMODE]);
+               changed |= WIPHY_BSS_PARAM_HT_OPMODE;
+       }
 
        if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
                if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
@@ -9124,6 +9155,7 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
                if (params.p2p_ctwindow != 0 &&
                    !(bss_param_support & WIPHY_BSS_PARAM_P2P_CTWINDOW))
                        return -EINVAL;
+               changed |= WIPHY_BSS_PARAM_P2P_CTWINDOW;
        }
 
        if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
@@ -9132,9 +9164,11 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
                if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
                        return -EINVAL;
                tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
+               if (tmp && !(bss_param_support & WIPHY_BSS_PARAM_P2P_OPPPS))
+                       return -EINVAL;
                params.p2p_opp_ps = tmp;
                if (params.p2p_opp_ps &&
-                   !(bss_param_support & WIPHY_BSS_PARAM_P2P_OPPPS))
+                   !(rdev->wiphy.bss_param_support & WIPHY_BSS_PARAM_P2P_OPPPS))
                        return -EINVAL;
        }
 
@@ -9145,6 +9179,10 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
            dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
                return -EOPNOTSUPP;
 
+       changed &= rdev->wiphy.bss_param_support;
+       if (!changed)
+               return 0;
+
        return rdev_change_bss(rdev, dev, &params);
 }