1

wifi: cfg80211: ensure cfg80211_bss_update frees IEs on error

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>
This commit is contained in:
Benjamin Berg 2023-12-20 13:41:42 +02:00 committed by Johannes Berg
parent 32af9a9e10
commit 31c5e92be5

View 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 *