wifi: cfg80211: ensure cfg80211_bss_update frees IEs on error
authorBenjamin Berg <benjamin.berg@intel.com>
Wed, 20 Dec 2023 11:41:42 +0000 (13:41 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Thu, 21 Dec 2023 19:35:15 +0000 (20:35 +0100)
cfg80211_bss_update is expected to consume the IEs that are passed into
it in the temporary internal BSS. This did not happen in some error
cases (which are also WARN_ON paths), so change the code to use a common
label and use that everywhere.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://msgid.link/20231220133549.8e72ea105e17.Ic81e9431e980419360e97502ce8c75c58793f05a@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/wireless/scan.c

index 68ba446067acd09e0fa45731e13b8af68ffd3150..f7fd7ea0e935f43ebd815a263a66081a63d9a390 100644 (file)
@@ -1818,15 +1818,15 @@ __cfg80211_bss_update(struct cfg80211_registered_device *rdev,
                      bool signal_valid, unsigned long ts)
 {
        struct cfg80211_internal_bss *found = NULL;
+       struct cfg80211_bss_ies *ies;
 
        if (WARN_ON(!tmp->pub.channel))
-               return NULL;
+               goto free_ies;
 
        tmp->ts = ts;
 
-       if (WARN_ON(!rcu_access_pointer(tmp->pub.ies))) {
-               return NULL;
-       }
+       if (WARN_ON(!rcu_access_pointer(tmp->pub.ies)))
+               goto free_ies;
 
        found = rb_find_bss(rdev, tmp, BSS_CMP_REGULAR);
 
@@ -1836,7 +1836,6 @@ __cfg80211_bss_update(struct cfg80211_registered_device *rdev,
        } else {
                struct cfg80211_internal_bss *new;
                struct cfg80211_internal_bss *hidden;
-               struct cfg80211_bss_ies *ies;
 
                /*
                 * create a copy -- the "res" variable that is passed in
@@ -1845,15 +1844,8 @@ __cfg80211_bss_update(struct cfg80211_registered_device *rdev,
                 */
                new = kzalloc(sizeof(*new) + rdev->wiphy.bss_priv_size,
                              GFP_ATOMIC);
-               if (!new) {
-                       ies = (void *)rcu_dereference(tmp->pub.beacon_ies);
-                       if (ies)
-                               kfree_rcu(ies, rcu_head);
-                       ies = (void *)rcu_dereference(tmp->pub.proberesp_ies);
-                       if (ies)
-                               kfree_rcu(ies, rcu_head);
-                       return NULL;
-               }
+               if (!new)
+                       goto free_ies;
                memcpy(new, tmp, sizeof(*new));
                new->refcount = 1;
                INIT_LIST_HEAD(&new->hidden_list);
@@ -1913,6 +1905,16 @@ __cfg80211_bss_update(struct cfg80211_registered_device *rdev,
        bss_ref_get(rdev, found);
 
        return found;
+
+free_ies:
+       ies = (void *)rcu_dereference(tmp->pub.beacon_ies);
+       if (ies)
+               kfree_rcu(ies, rcu_head);
+       ies = (void *)rcu_dereference(tmp->pub.proberesp_ies);
+       if (ies)
+               kfree_rcu(ies, rcu_head);
+
+       return NULL;
 }
 
 struct cfg80211_internal_bss *