net: kcm: fix direct access to bv_len
[platform/kernel/linux-rpi.git] / net / wireless / scan.c
index 939deec..04ef7cd 100644 (file)
@@ -1829,8 +1829,12 @@ __cfg80211_bss_update(struct cfg80211_registered_device *rdev,
                                list_add(&new->hidden_list,
                                         &hidden->hidden_list);
                                hidden->refcount++;
+
+                               ies = (void *)rcu_dereference(new->pub.beacon_ies);
                                rcu_assign_pointer(new->pub.beacon_ies,
                                                   hidden->pub.beacon_ies);
+                               if (ies)
+                                       kfree_rcu(ies, rcu_head);
                        }
                } else {
                        /*
@@ -2125,7 +2129,7 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,
        if (!res)
                goto drop;
 
-       rdev_inform_bss(rdev, &res->pub, ies, data->drv_data);
+       rdev_inform_bss(rdev, &res->pub, ies, drv_data->drv_data);
 
        if (data->bss_source == BSS_SOURCE_MBSSID) {
                /* this is a nontransmitting bss, we need to add it to
@@ -2358,8 +2362,8 @@ ssize_t cfg80211_defragment_element(const struct element *elem, const u8 *ies,
 
        /* elem might be invalid after the memmove */
        next = (void *)(elem->data + elem->datalen);
-
        elem_datalen = elem->datalen;
+
        if (elem->id == WLAN_EID_EXTENSION) {
                copied = elem->datalen - 1;
                if (copied > data_len)
@@ -2380,7 +2384,7 @@ ssize_t cfg80211_defragment_element(const struct element *elem, const u8 *ies,
 
        for (elem = next;
             elem->data < ies + ieslen &&
-               elem->data + elem->datalen < ies + ieslen;
+               elem->data + elem->datalen <= ies + ieslen;
             elem = next) {
                /* elem might be invalid after the memmove */
                next = (void *)(elem->data + elem->datalen);
@@ -2569,10 +2573,12 @@ cfg80211_tbtt_info_for_mld_ap(const u8 *ie, size_t ielen, u8 mld_id, u8 link_id,
        return false;
 }
 
-static void cfg80211_parse_ml_sta_data(struct wiphy *wiphy,
-                                      struct cfg80211_inform_single_bss_data *tx_data,
-                                      struct cfg80211_bss *source_bss,
-                                      gfp_t gfp)
+static void
+cfg80211_parse_ml_elem_sta_data(struct wiphy *wiphy,
+                               struct cfg80211_inform_single_bss_data *tx_data,
+                               struct cfg80211_bss *source_bss,
+                               const struct element *elem,
+                               gfp_t gfp)
 {
        struct cfg80211_inform_single_bss_data data = {
                .drv_data = tx_data->drv_data,
@@ -2581,7 +2587,6 @@ static void cfg80211_parse_ml_sta_data(struct wiphy *wiphy,
                .bss_source = BSS_SOURCE_STA_PROFILE,
        };
        struct ieee80211_multi_link_elem *ml_elem;
-       const struct element *elem;
        struct cfg80211_mle *mle;
        u16 control;
        u8 *new_ie;
@@ -2591,15 +2596,7 @@ static void cfg80211_parse_ml_sta_data(struct wiphy *wiphy,
        const u8 *pos;
        u8 i;
 
-       if (!source_bss)
-               return;
-
-       if (tx_data->ftype != CFG80211_BSS_FTYPE_PRESP)
-               return;
-
-       elem = cfg80211_find_ext_elem(WLAN_EID_EXT_EHT_MULTI_LINK,
-                                     tx_data->ie, tx_data->ielen);
-       if (!elem || !ieee80211_mle_size_ok(elem->data + 1, elem->datalen - 1))
+       if (!ieee80211_mle_size_ok(elem->data + 1, elem->datalen - 1))
                return;
 
        ml_elem = (void *)elem->data + 1;
@@ -2625,8 +2622,11 @@ static void cfg80211_parse_ml_sta_data(struct wiphy *wiphy,
        /* MLD capabilities and operations */
        pos += 2;
 
-       /* Not included when the (nontransmitted) AP is responding itself,
-        * but defined to zero then (Draft P802.11be_D3.0, 9.4.2.170.2)
+       /*
+        * The MLD ID of the reporting AP is always zero. It is set if the AP
+        * is part of an MBSSID set and will be non-zero for ML Elements
+        * relating to a nontransmitted BSS (matching the Multi-BSSID Index,
+        * Draft P802.11be_D3.2, 35.3.4.2)
         */
        if (u16_get_bits(control, IEEE80211_MLC_BASIC_PRES_MLD_ID)) {
                mld_id = *pos;
@@ -2731,6 +2731,25 @@ out:
        kfree(mle);
 }
 
+static void cfg80211_parse_ml_sta_data(struct wiphy *wiphy,
+                                      struct cfg80211_inform_single_bss_data *tx_data,
+                                      struct cfg80211_bss *source_bss,
+                                      gfp_t gfp)
+{
+       const struct element *elem;
+
+       if (!source_bss)
+               return;
+
+       if (tx_data->ftype != CFG80211_BSS_FTYPE_PRESP)
+               return;
+
+       for_each_element_extid(elem, WLAN_EID_EXT_EHT_MULTI_LINK,
+                              tx_data->ie, tx_data->ielen)
+               cfg80211_parse_ml_elem_sta_data(wiphy, tx_data, source_bss,
+                                               elem, gfp);
+}
+
 struct cfg80211_bss *
 cfg80211_inform_bss_data(struct wiphy *wiphy,
                         struct cfg80211_inform_bss *data,