wifi: cfg80211: annotate iftype_data pointer with sparse
authorJohannes Berg <johannes.berg@intel.com>
Mon, 28 Aug 2023 07:54:39 +0000 (09:54 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 11 Sep 2023 09:27:23 +0000 (11:27 +0200)
There were are a number of cases in mac80211 and iwlwifi (at
least) that used the sband->iftype_data pointer directly,
instead of using the accessors to find the right array entry
to use.

Make sparse warn when such a thing is done.

To not have a lot of casts, add two helper functions/macros

 - ieee80211_set_sband_iftype_data()
 - for_each_sband_iftype_data()

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
16 files changed:
drivers/net/wireless/ath/ath11k/mac.c
drivers/net/wireless/ath/ath12k/mac.c
drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
drivers/net/wireless/mediatek/mt76/mt7915/init.c
drivers/net/wireless/mediatek/mt76/mt7921/main.c
drivers/net/wireless/mediatek/mt76/mt7996/init.c
drivers/net/wireless/quantenna/qtnfmac/commands.c
drivers/net/wireless/quantenna/qtnfmac/core.c
drivers/net/wireless/realtek/rtw89/core.c
drivers/net/wireless/realtek/rtw89/regd.c
drivers/net/wireless/virtual/mac80211_hwsim.c
include/net/cfg80211.h
net/mac80211/main.c
net/wireless/chan.c
net/wireless/core.c
net/wireless/nl80211.c

index c071bf5841af60e67cc2b815e732f4bca86e63c8..6ed036b51dba85a3139a78691319b0e002815969 100644 (file)
@@ -5893,8 +5893,9 @@ static void ath11k_mac_setup_he_cap(struct ath11k *ar,
                                               ar->mac.iftype[NL80211_BAND_2GHZ],
                                               NL80211_BAND_2GHZ);
                band = &ar->mac.sbands[NL80211_BAND_2GHZ];
-               band->iftype_data = ar->mac.iftype[NL80211_BAND_2GHZ];
-               band->n_iftype_data = count;
+               _ieee80211_set_sband_iftype_data(band,
+                                                ar->mac.iftype[NL80211_BAND_2GHZ],
+                                                count);
        }
 
        if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP) {
@@ -5902,8 +5903,9 @@ static void ath11k_mac_setup_he_cap(struct ath11k *ar,
                                               ar->mac.iftype[NL80211_BAND_5GHZ],
                                               NL80211_BAND_5GHZ);
                band = &ar->mac.sbands[NL80211_BAND_5GHZ];
-               band->iftype_data = ar->mac.iftype[NL80211_BAND_5GHZ];
-               band->n_iftype_data = count;
+               _ieee80211_set_sband_iftype_data(band,
+                                                ar->mac.iftype[NL80211_BAND_5GHZ],
+                                                count);
        }
 
        if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP &&
@@ -5912,8 +5914,9 @@ static void ath11k_mac_setup_he_cap(struct ath11k *ar,
                                               ar->mac.iftype[NL80211_BAND_6GHZ],
                                               NL80211_BAND_6GHZ);
                band = &ar->mac.sbands[NL80211_BAND_6GHZ];
-               band->iftype_data = ar->mac.iftype[NL80211_BAND_6GHZ];
-               band->n_iftype_data = count;
+               _ieee80211_set_sband_iftype_data(band,
+                                                ar->mac.iftype[NL80211_BAND_6GHZ],
+                                                count);
        }
 }
 
index 88346e66bb753e93e2cd85905386d09a2b866b9f..24113709972d3605c6b9af677d075379764580b9 100644 (file)
@@ -4647,8 +4647,8 @@ static void ath12k_mac_setup_sband_iftype_data(struct ath12k *ar,
                                                          ar->mac.iftype[band],
                                                          band);
                sband = &ar->mac.sbands[band];
-               sband->iftype_data = ar->mac.iftype[band];
-               sband->n_iftype_data = count;
+               _ieee80211_set_sband_iftype_data(sband, ar->mac.iftype[band],
+                                                count);
        }
 
        if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP) {
@@ -4657,8 +4657,8 @@ static void ath12k_mac_setup_sband_iftype_data(struct ath12k *ar,
                                                          ar->mac.iftype[band],
                                                          band);
                sband = &ar->mac.sbands[band];
-               sband->iftype_data = ar->mac.iftype[band];
-               sband->n_iftype_data = count;
+               _ieee80211_set_sband_iftype_data(sband, ar->mac.iftype[band],
+                                                count);
        }
 
        if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP &&
@@ -4668,8 +4668,8 @@ static void ath12k_mac_setup_sband_iftype_data(struct ath12k *ar,
                                                          ar->mac.iftype[band],
                                                          band);
                sband = &ar->mac.sbands[band];
-               sband->iftype_data = ar->mac.iftype[band];
-               sband->n_iftype_data = count;
+               _ieee80211_set_sband_iftype_data(sband, ar->mac.iftype[band],
+                                                count);
        }
 }
 
index 31176897b74638e7712b4901ebe99570b417ba4e..cff1f97536e31f093389af32e3bafa6ebd9c09da 100644 (file)
@@ -1077,8 +1077,8 @@ static void iwl_init_he_hw_capab(struct iwl_trans *trans,
 
        memcpy(iftype_data, iwl_he_eht_capa, sizeof(iwl_he_eht_capa));
 
-       sband->iftype_data = iftype_data;
-       sband->n_iftype_data = ARRAY_SIZE(iwl_he_eht_capa);
+       _ieee80211_set_sband_iftype_data(sband, iftype_data,
+                                        ARRAY_SIZE(iwl_he_eht_capa));
 
        for (i = 0; i < sband->n_iftype_data; i++)
                iwl_nvm_fixup_sband_iftd(trans, data, sband, &iftype_data[i],
index 35fdf4f98d80bad7f00eedf7b759da3bc15de7d1..b27d04e02abaa5897256ddbcb08d69ed1be47b7d 100644 (file)
@@ -1127,8 +1127,7 @@ void mt7915_set_stream_he_caps(struct mt7915_phy *phy)
                n = mt7915_init_he_caps(phy, NL80211_BAND_2GHZ, data);
 
                band = &phy->mt76->sband_2g.sband;
-               band->iftype_data = data;
-               band->n_iftype_data = n;
+               _ieee80211_set_sband_iftype_data(band, data, n);
        }
 
        if (phy->mt76->cap.has_5ghz) {
@@ -1136,8 +1135,7 @@ void mt7915_set_stream_he_caps(struct mt7915_phy *phy)
                n = mt7915_init_he_caps(phy, NL80211_BAND_5GHZ, data);
 
                band = &phy->mt76->sband_5g.sband;
-               band->iftype_data = data;
-               band->n_iftype_data = n;
+               _ieee80211_set_sband_iftype_data(band, data, n);
        }
 
        if (phy->mt76->cap.has_6ghz) {
@@ -1145,8 +1143,7 @@ void mt7915_set_stream_he_caps(struct mt7915_phy *phy)
                n = mt7915_init_he_caps(phy, NL80211_BAND_6GHZ, data);
 
                band = &phy->mt76->sband_6g.sband;
-               band->iftype_data = data;
-               band->n_iftype_data = n;
+               _ieee80211_set_sband_iftype_data(band, data, n);
        }
 }
 
index 0844d28b3223dabed3ffe3dec15f62327851ab62..62e6da1386aa4f7d992545fd56b8063f9344e4e1 100644 (file)
@@ -196,8 +196,7 @@ void mt7921_set_stream_he_caps(struct mt792x_phy *phy)
                n = mt7921_init_he_caps(phy, NL80211_BAND_2GHZ, data);
 
                band = &phy->mt76->sband_2g.sband;
-               band->iftype_data = data;
-               band->n_iftype_data = n;
+               _ieee80211_set_sband_iftype_data(band, data, n);
        }
 
        if (phy->mt76->cap.has_5ghz) {
@@ -205,16 +204,14 @@ void mt7921_set_stream_he_caps(struct mt792x_phy *phy)
                n = mt7921_init_he_caps(phy, NL80211_BAND_5GHZ, data);
 
                band = &phy->mt76->sband_5g.sband;
-               band->iftype_data = data;
-               band->n_iftype_data = n;
+               _ieee80211_set_sband_iftype_data(band, data, n);
 
                if (phy->mt76->cap.has_6ghz) {
                        data = phy->iftype[NL80211_BAND_6GHZ];
                        n = mt7921_init_he_caps(phy, NL80211_BAND_6GHZ, data);
 
                        band = &phy->mt76->sband_6g.sband;
-                       band->iftype_data = data;
-                       band->n_iftype_data = n;
+                       _ieee80211_set_sband_iftype_data(band, data, n);
                }
        }
 }
index 26e03b28935f2f00d53a45c71a652a67ae7ad118..0d6cc214ce1063261942cfbf7a8a093bbd29a39f 100644 (file)
@@ -827,8 +827,7 @@ __mt7996_set_stream_he_eht_caps(struct mt7996_phy *phy,
                n++;
        }
 
-       sband->iftype_data = data;
-       sband->n_iftype_data = n;
+       _ieee80211_set_sband_iftype_data(sband, data, n);
 }
 
 void mt7996_set_stream_he_eht_caps(struct mt7996_phy *phy)
index 68ae9c7ea95abba14c79fe2c3e888db2a4aabb1c..9540ad6196d727ab23815db03d59fb4642e49e60 100644 (file)
@@ -1335,7 +1335,7 @@ static int qtnf_cmd_band_fill_iftype(const u8 *data,
                return -EINVAL;
        }
 
-       kfree(band->iftype_data);
+       kfree((__force void *)band->iftype_data);
        band->iftype_data = NULL;
        band->n_iftype_data = tlv->n_iftype_data;
        if (band->n_iftype_data == 0)
@@ -1347,7 +1347,8 @@ static int qtnf_cmd_band_fill_iftype(const u8 *data,
                band->n_iftype_data = 0;
                return -ENOMEM;
        }
-       band->iftype_data = iftype_data;
+
+       _ieee80211_set_sband_iftype_data(band, iftype_data, tlv->n_iftype_data);
 
        for (i = 0; i < band->n_iftype_data; i++)
                qtnf_cmd_conv_iftype(iftype_data++, &tlv->iftype_data[i]);
index 2a63ffdc4b2c10ac4056bef3cc0af29b1e6ebf2f..677bac83533057f68ba32f8d7468a1e2a68ff541 100644 (file)
@@ -535,7 +535,7 @@ static void qtnf_core_mac_detach(struct qtnf_bus *bus, unsigned int macid)
                if (!wiphy->bands[band])
                        continue;
 
-               kfree(wiphy->bands[band]->iftype_data);
+               kfree((__force void *)wiphy->bands[band]->iftype_data);
                wiphy->bands[band]->n_iftype_data = 0;
 
                kfree(wiphy->bands[band]->channels);
index 856f3543eff2ab3983961fc4dbbf9264adf6cc28..fc686954b3ddbb739ff9b6e7850620fd0d12b2f8 100644 (file)
@@ -3359,8 +3359,7 @@ static void rtw89_init_he_cap(struct rtw89_dev *rtwdev,
                idx++;
        }
 
-       sband->iftype_data = iftype_data;
-       sband->n_iftype_data = idx;
+       _ieee80211_set_sband_iftype_data(sband, iftype_data, idx);
 }
 
 static int rtw89_core_set_supported_band(struct rtw89_dev *rtwdev)
@@ -3405,11 +3404,11 @@ err:
        hw->wiphy->bands[NL80211_BAND_5GHZ] = NULL;
        hw->wiphy->bands[NL80211_BAND_6GHZ] = NULL;
        if (sband_2ghz)
-               kfree(sband_2ghz->iftype_data);
+               kfree((__force void *)sband_2ghz->iftype_data);
        if (sband_5ghz)
-               kfree(sband_5ghz->iftype_data);
+               kfree((__force void *)sband_5ghz->iftype_data);
        if (sband_6ghz)
-               kfree(sband_6ghz->iftype_data);
+               kfree((__force void *)sband_6ghz->iftype_data);
        kfree(sband_2ghz);
        kfree(sband_5ghz);
        kfree(sband_6ghz);
@@ -3421,11 +3420,11 @@ static void rtw89_core_clr_supported_band(struct rtw89_dev *rtwdev)
        struct ieee80211_hw *hw = rtwdev->hw;
 
        if (hw->wiphy->bands[NL80211_BAND_2GHZ])
-               kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]->iftype_data);
+               kfree((__force void *)hw->wiphy->bands[NL80211_BAND_2GHZ]->iftype_data);
        if (hw->wiphy->bands[NL80211_BAND_5GHZ])
-               kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]->iftype_data);
+               kfree((__force void *)hw->wiphy->bands[NL80211_BAND_5GHZ]->iftype_data);
        if (hw->wiphy->bands[NL80211_BAND_6GHZ])
-               kfree(hw->wiphy->bands[NL80211_BAND_6GHZ]->iftype_data);
+               kfree((__force void *)hw->wiphy->bands[NL80211_BAND_6GHZ]->iftype_data);
        kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]);
        kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]);
        kfree(hw->wiphy->bands[NL80211_BAND_6GHZ]);
index 9e2328db1865603d2fb7597fdb2023ce8c4232c2..c956a8b971c60a31691f1fe0afca4d535b5bfcac 100644 (file)
@@ -377,7 +377,7 @@ bottom:
                return;
 
        wiphy->bands[NL80211_BAND_6GHZ] = NULL;
-       kfree(sband->iftype_data);
+       kfree((__force void *)sband->iftype_data);
        kfree(sband);
 }
 
index f5a0880da3fcc3978a2509b6dd7f84eaccc39d2d..36f2d2388ddd6e9c85fa3f2e5ed9fe7e0daa4853 100644 (file)
@@ -4899,25 +4899,19 @@ static const struct ieee80211_sband_iftype_data sband_capa_6ghz[] = {
 
 static void mac80211_hwsim_sband_capab(struct ieee80211_supported_band *sband)
 {
-       u16 n_iftype_data;
-
-       if (sband->band == NL80211_BAND_2GHZ) {
-               n_iftype_data = ARRAY_SIZE(sband_capa_2ghz);
-               sband->iftype_data =
-                       (struct ieee80211_sband_iftype_data *)sband_capa_2ghz;
-       } else if (sband->band == NL80211_BAND_5GHZ) {
-               n_iftype_data = ARRAY_SIZE(sband_capa_5ghz);
-               sband->iftype_data =
-                       (struct ieee80211_sband_iftype_data *)sband_capa_5ghz;
-       } else if (sband->band == NL80211_BAND_6GHZ) {
-               n_iftype_data = ARRAY_SIZE(sband_capa_6ghz);
-               sband->iftype_data =
-                       (struct ieee80211_sband_iftype_data *)sband_capa_6ghz;
-       } else {
-               return;
+       switch (sband->band) {
+       case NL80211_BAND_2GHZ:
+               ieee80211_set_sband_iftype_data(sband, sband_capa_2ghz);
+               break;
+       case NL80211_BAND_5GHZ:
+               ieee80211_set_sband_iftype_data(sband, sband_capa_5ghz);
+               break;
+       case NL80211_BAND_6GHZ:
+               ieee80211_set_sband_iftype_data(sband, sband_capa_6ghz);
+               break;
+       default:
+               break;
        }
-
-       sband->n_iftype_data = n_iftype_data;
 }
 
 #ifdef CONFIG_MAC80211_MESH
index aa9c26a03f3067ed5657d3566b7e029dd630b7d1..922fd9e0d9b417ed2f7cce00cefb2063b7467e4a 100644 (file)
@@ -410,6 +410,19 @@ struct ieee80211_sta_eht_cap {
        u8 eht_ppe_thres[IEEE80211_EHT_PPE_THRES_MAX_LEN];
 };
 
+/* sparse defines __CHECKER__; see Documentation/dev-tools/sparse.rst */
+#ifdef __CHECKER__
+/*
+ * This is used to mark the sband->iftype_data pointer which is supposed
+ * to be an array with special access semantics (per iftype), but a lot
+ * of code got it wrong in the past, so with this marking sparse will be
+ * noisy when the pointer is used directly.
+ */
+# define __iftd                __attribute__((noderef, address_space(__iftype_data)))
+#else
+# define __iftd
+#endif /* __CHECKER__ */
+
 /**
  * struct ieee80211_sband_iftype_data - sband data per interface type
  *
@@ -543,9 +556,47 @@ struct ieee80211_supported_band {
        struct ieee80211_sta_s1g_cap s1g_cap;
        struct ieee80211_edmg edmg_cap;
        u16 n_iftype_data;
-       const struct ieee80211_sband_iftype_data *iftype_data;
+       const struct ieee80211_sband_iftype_data __iftd *iftype_data;
 };
 
+/**
+ * _ieee80211_set_sband_iftype_data - set sband iftype data array
+ * @sband: the sband to initialize
+ * @iftd: the iftype data array pointer
+ * @n_iftd: the length of the iftype data array
+ *
+ * Set the sband iftype data array; use this where the length cannot
+ * be derived from the ARRAY_SIZE() of the argument, but prefer
+ * ieee80211_set_sband_iftype_data() where it can be used.
+ */
+static inline void
+_ieee80211_set_sband_iftype_data(struct ieee80211_supported_band *sband,
+                                const struct ieee80211_sband_iftype_data *iftd,
+                                u16 n_iftd)
+{
+       sband->iftype_data = (const void __iftd __force *)iftd;
+       sband->n_iftype_data = n_iftd;
+}
+
+/**
+ * ieee80211_set_sband_iftype_data - set sband iftype data array
+ * @sband: the sband to initialize
+ * @iftd: the iftype data array
+ */
+#define ieee80211_set_sband_iftype_data(sband, iftd)   \
+       _ieee80211_set_sband_iftype_data(sband, iftd, ARRAY_SIZE(iftd))
+
+/**
+ * for_each_sband_iftype_data - iterate sband iftype data entries
+ * @sband: the sband whose iftype_data array to iterate
+ * @i: iterator counter
+ * @iftd: iftype data pointer to set
+ */
+#define for_each_sband_iftype_data(sband, i, iftd)                             \
+       for (i = 0, iftd = (const void __force *)&(sband)->iftype_data[i];      \
+            i < (sband)->n_iftype_data;                                        \
+            i++, iftd = (const void __force *)&(sband)->iftype_data[i])
+
 /**
  * ieee80211_get_sband_iftype_data - return sband data for a given iftype
  * @sband: the sband to search for the STA on
@@ -557,6 +608,7 @@ static inline const struct ieee80211_sband_iftype_data *
 ieee80211_get_sband_iftype_data(const struct ieee80211_supported_band *sband,
                                u8 iftype)
 {
+       const struct ieee80211_sband_iftype_data *data;
        int i;
 
        if (WARN_ON(iftype >= NL80211_IFTYPE_MAX))
@@ -565,10 +617,7 @@ ieee80211_get_sband_iftype_data(const struct ieee80211_supported_band *sband,
        if (iftype == NL80211_IFTYPE_AP_VLAN)
                iftype = NL80211_IFTYPE_AP;
 
-       for (i = 0; i < sband->n_iftype_data; i++)  {
-               const struct ieee80211_sband_iftype_data *data =
-                       &sband->iftype_data[i];
-
+       for_each_sband_iftype_data(sband, i, data) {
                if (data->types_mask & BIT(iftype))
                        return data;
        }
index eabf6c1bf3ff35cd2f2226e0fa41780ccedc01b9..bf8f72c412ee0d5b891586a6f4ce66a618433589 100644 (file)
@@ -1066,6 +1066,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
        supp_he = false;
        supp_eht = false;
        for (band = 0; band < NUM_NL80211_BANDS; band++) {
+               const struct ieee80211_sband_iftype_data *iftd;
                struct ieee80211_supported_band *sband;
 
                sband = local->hw.wiphy->bands[band];
@@ -1112,11 +1113,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
                supp_ht = supp_ht || sband->ht_cap.ht_supported;
                supp_vht = supp_vht || sband->vht_cap.vht_supported;
 
-               for (i = 0; i < sband->n_iftype_data; i++) {
-                       const struct ieee80211_sband_iftype_data *iftd;
-
-                       iftd = &sband->iftype_data[i];
-
+               for_each_sband_iftype_data(sband, i, iftd) {
                        supp_he = supp_he || iftd->he_cap.has_he;
                        supp_eht = supp_eht || iftd->eht_cap.has_eht;
                }
index 2af3aaee749398684f971e7dd884ff8ab6ac4f7d..842190dfa100f880da16de4ec8e317dfd8688ea7 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright 2009      Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
- * Copyright 2018-2022 Intel Corporation
+ * Copyright 2018-2023 Intel Corporation
  */
 
 #include <linux/export.h>
@@ -1162,8 +1162,7 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
                if (!sband)
                        return false;
 
-               for (i = 0; i < sband->n_iftype_data; i++) {
-                       iftd = &sband->iftype_data[i];
+               for_each_sband_iftype_data(sband, i, iftd) {
                        if (!iftd->eht_cap.has_eht)
                                continue;
 
index c419177278da292ed653178d27c3e403581ccfde..b0f6ae3ce78fa6144bb0f9ebc54beb66c5e54dc5 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright 2006-2010         Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright 2015-2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2022 Intel Corporation
+ * Copyright (C) 2018-2023 Intel Corporation
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -821,6 +821,7 @@ int wiphy_register(struct wiphy *wiphy)
 
        /* sanity check supported bands/channels */
        for (band = 0; band < NUM_NL80211_BANDS; band++) {
+               const struct ieee80211_sband_iftype_data *iftd;
                u16 types = 0;
                bool have_he = false;
 
@@ -877,14 +878,11 @@ int wiphy_register(struct wiphy *wiphy)
                                return -EINVAL;
                }
 
-               for (i = 0; i < sband->n_iftype_data; i++) {
-                       const struct ieee80211_sband_iftype_data *iftd;
+               for_each_sband_iftype_data(sband, i, iftd) {
                        bool has_ap, has_non_ap;
                        u32 ap_bits = BIT(NL80211_IFTYPE_AP) |
                                      BIT(NL80211_IFTYPE_P2P_GO);
 
-                       iftd = &sband->iftype_data[i];
-
                        if (WARN_ON(!iftd->types_mask))
                                return -EINVAL;
                        if (WARN_ON(types & iftd->types_mask))
index 71a0a6e34bdb8d3f239e4bdfa01e774406866391..ab0aea7dca7dcb8d726ba9d53bbf3936c2b13c4d 100644 (file)
@@ -1913,20 +1913,20 @@ static int nl80211_send_band_rateinfo(struct sk_buff *msg,
                struct nlattr *nl_iftype_data =
                        nla_nest_start_noflag(msg,
                                              NL80211_BAND_ATTR_IFTYPE_DATA);
+               const struct ieee80211_sband_iftype_data *iftd;
                int err;
 
                if (!nl_iftype_data)
                        return -ENOBUFS;
 
-               for (i = 0; i < sband->n_iftype_data; i++) {
+               for_each_sband_iftype_data(sband, i, iftd) {
                        struct nlattr *iftdata;
 
                        iftdata = nla_nest_start_noflag(msg, i + 1);
                        if (!iftdata)
                                return -ENOBUFS;
 
-                       err = nl80211_send_iftype_data(msg, sband,
-                                                      &sband->iftype_data[i]);
+                       err = nl80211_send_iftype_data(msg, sband, iftd);
                        if (err)
                                return err;