UPSTREAM: wifi: cfg80211: update hidden BSSes to avoid WARN_ON

commit c90b93b5b782891ebfda49d4e5da36632fefd5d1 upstream.

When updating beacon elements in a non-transmitted BSS,
also update the hidden sub-entries to the same beacon
elements, so that a future update through other paths
won't trigger a WARN_ON().

The warning is triggered because the beacon elements in
the hidden BSSes that are children of the BSS should
always be the same as in the parent.

Bug: 254180332
Reported-by: Sönke Huster <shuster@seemoo.tu-darmstadt.de>
Tested-by: Sönke Huster <shuster@seemoo.tu-darmstadt.de>
Fixes: 0b8fb8235b ("cfg80211: Parsing of Multiple BSSID information in scanning")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Lee Jones <joneslee@google.com>
Change-Id: Id6db4b0a1a7b7fa1ae300b69aa6176b5a429dff0
This commit is contained in:
Johannes Berg 2022-10-05 23:11:43 +02:00 committed by Treehugger Robot
parent fa35741b59
commit df86d024f6

View File

@ -1094,6 +1094,23 @@ struct cfg80211_non_tx_bss {
u8 bssid_index; u8 bssid_index;
}; };
static void cfg80211_update_hidden_bsses(struct cfg80211_internal_bss *known,
const struct cfg80211_bss_ies *new_ies,
const struct cfg80211_bss_ies *old_ies)
{
struct cfg80211_internal_bss *bss;
/* Assign beacon IEs to all sub entries */
list_for_each_entry(bss, &known->hidden_list, hidden_list) {
const struct cfg80211_bss_ies *ies;
ies = rcu_access_pointer(bss->pub.beacon_ies);
WARN_ON(ies != old_ies);
rcu_assign_pointer(bss->pub.beacon_ies, new_ies);
}
}
static bool static bool
cfg80211_update_known_bss(struct cfg80211_registered_device *rdev, cfg80211_update_known_bss(struct cfg80211_registered_device *rdev,
struct cfg80211_internal_bss *known, struct cfg80211_internal_bss *known,
@ -1117,7 +1134,6 @@ cfg80211_update_known_bss(struct cfg80211_registered_device *rdev,
kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head); kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head);
} else if (rcu_access_pointer(new->pub.beacon_ies)) { } else if (rcu_access_pointer(new->pub.beacon_ies)) {
const struct cfg80211_bss_ies *old; const struct cfg80211_bss_ies *old;
struct cfg80211_internal_bss *bss;
if (known->pub.hidden_beacon_bss && if (known->pub.hidden_beacon_bss &&
!list_empty(&known->hidden_list)) { !list_empty(&known->hidden_list)) {
@ -1145,16 +1161,7 @@ cfg80211_update_known_bss(struct cfg80211_registered_device *rdev,
if (old == rcu_access_pointer(known->pub.ies)) if (old == rcu_access_pointer(known->pub.ies))
rcu_assign_pointer(known->pub.ies, new->pub.beacon_ies); rcu_assign_pointer(known->pub.ies, new->pub.beacon_ies);
/* Assign beacon IEs to all sub entries */ cfg80211_update_hidden_bsses(known, new->pub.beacon_ies, old);
list_for_each_entry(bss, &known->hidden_list, hidden_list) {
const struct cfg80211_bss_ies *ies;
ies = rcu_access_pointer(bss->pub.beacon_ies);
WARN_ON(ies != old);
rcu_assign_pointer(bss->pub.beacon_ies,
new->pub.beacon_ies);
}
if (old) if (old)
kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head); kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head);
@ -1784,6 +1791,8 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
} else { } else {
old = rcu_access_pointer(nontrans_bss->beacon_ies); old = rcu_access_pointer(nontrans_bss->beacon_ies);
rcu_assign_pointer(nontrans_bss->beacon_ies, new_ies); rcu_assign_pointer(nontrans_bss->beacon_ies, new_ies);
cfg80211_update_hidden_bsses(bss_from_pub(nontrans_bss),
new_ies, old);
rcu_assign_pointer(nontrans_bss->ies, new_ies); rcu_assign_pointer(nontrans_bss->ies, new_ies);
if (old) if (old)
kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head); kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head);