|
Takashi Iwai |
ab97d8 |
From: Johannes Berg <johannes.berg@intel.com>
|
|
Takashi Iwai |
ab97d8 |
Date: Fri, 30 Sep 2022 23:44:23 +0200
|
|
Takashi Iwai |
ab97d8 |
Subject: [PATCH] wifi: cfg80211: fix BSS refcounting bugs
|
|
Takashi Iwai |
ab97d8 |
Mime-version: 1.0
|
|
Takashi Iwai |
ab97d8 |
Content-type: text/plain; charset=UTF-8
|
|
Takashi Iwai |
ab97d8 |
Content-transfer-encoding: 8bit
|
|
Takashi Iwai |
ab97d8 |
Patch-mainline: Not yet, embargoed
|
|
Takashi Iwai |
ab97d8 |
References: CVE-2022-42720 bsc#1204059
|
|
Takashi Iwai |
ab97d8 |
|
|
Takashi Iwai |
ab97d8 |
There are multiple refcounting bugs related to multi-BSSID:
|
|
Takashi Iwai |
ab97d8 |
- In bss_ref_get(), if the BSS has a hidden_beacon_bss, then
|
|
Takashi Iwai |
ab97d8 |
the bss pointer is overwritten before checking for the
|
|
Takashi Iwai |
ab97d8 |
transmitted BSS, which is clearly wrong. Fix this by using
|
|
Takashi Iwai |
ab97d8 |
the bss_from_pub() macro.
|
|
Takashi Iwai |
ab97d8 |
|
|
Takashi Iwai |
ab97d8 |
- In cfg80211_bss_update() we copy the transmitted_bss pointer
|
|
Takashi Iwai |
ab97d8 |
from tmp into new, but then if we release new, we'll unref
|
|
Takashi Iwai |
ab97d8 |
it erroneously. We already set the pointer and ref it, but
|
|
Takashi Iwai |
ab97d8 |
need to NULL it since it was copied from the tmp data.
|
|
Takashi Iwai |
ab97d8 |
|
|
Takashi Iwai |
ab97d8 |
- In cfg80211_inform_single_bss_data(), if adding to the non-
|
|
Takashi Iwai |
ab97d8 |
transmitted list fails, we unlink the BSS and yet still we
|
|
Takashi Iwai |
ab97d8 |
return it, but this results in returning an entry without
|
|
Takashi Iwai |
ab97d8 |
a reference. We shouldn't return it anyway if it was broken
|
|
Takashi Iwai |
ab97d8 |
enough to not get added there.
|
|
Takashi Iwai |
ab97d8 |
|
|
Takashi Iwai |
ab97d8 |
This fixes CVE-2022-42720.
|
|
Takashi Iwai |
ab97d8 |
|
|
Takashi Iwai |
ab97d8 |
Reported-by: Sönke Huster <shuster@seemoo.tu-darmstadt.de>
|
|
Takashi Iwai |
ab97d8 |
Tested-by: Sönke Huster <shuster@seemoo.tu-darmstadt.de>
|
|
Takashi Iwai |
ab97d8 |
Fixes: a3584f56de1c ("cfg80211: Properly track transmitting and non-transmitting BSS")
|
|
Takashi Iwai |
ab97d8 |
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
|
Takashi Iwai |
ab97d8 |
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
Takashi Iwai |
ab97d8 |
|
|
Takashi Iwai |
ab97d8 |
---
|
|
Takashi Iwai |
ab97d8 |
net/wireless/scan.c | 27 ++++++++++++++-------------
|
|
Takashi Iwai |
ab97d8 |
1 file changed, 14 insertions(+), 13 deletions(-)
|
|
Takashi Iwai |
ab97d8 |
|
|
Takashi Iwai |
ab97d8 |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
|
|
Takashi Iwai |
ab97d8 |
index 5382fc2003db..94a8679ca388 100644
|
|
Takashi Iwai |
ab97d8 |
--- a/net/wireless/scan.c
|
|
Takashi Iwai |
ab97d8 |
+++ b/net/wireless/scan.c
|
|
Takashi Iwai |
ab97d8 |
@@ -143,18 +143,12 @@ static inline void bss_ref_get(struct cfg80211_registered_device *rdev,
|
|
Takashi Iwai |
ab97d8 |
lockdep_assert_held(&rdev->bss_lock);
|
|
Takashi Iwai |
ab97d8 |
|
|
Takashi Iwai |
ab97d8 |
bss->refcount++;
|
|
Takashi Iwai |
ab97d8 |
- if (bss->pub.hidden_beacon_bss) {
|
|
Takashi Iwai |
ab97d8 |
- bss = container_of(bss->pub.hidden_beacon_bss,
|
|
Takashi Iwai |
ab97d8 |
- struct cfg80211_internal_bss,
|
|
Takashi Iwai |
ab97d8 |
- pub);
|
|
Takashi Iwai |
ab97d8 |
- bss->refcount++;
|
|
Takashi Iwai |
ab97d8 |
- }
|
|
Takashi Iwai |
ab97d8 |
- if (bss->pub.transmitted_bss) {
|
|
Takashi Iwai |
ab97d8 |
- bss = container_of(bss->pub.transmitted_bss,
|
|
Takashi Iwai |
ab97d8 |
- struct cfg80211_internal_bss,
|
|
Takashi Iwai |
ab97d8 |
- pub);
|
|
Takashi Iwai |
ab97d8 |
- bss->refcount++;
|
|
Takashi Iwai |
ab97d8 |
- }
|
|
Takashi Iwai |
ab97d8 |
+
|
|
Takashi Iwai |
ab97d8 |
+ if (bss->pub.hidden_beacon_bss)
|
|
Takashi Iwai |
ab97d8 |
+ bss_from_pub(bss->pub.hidden_beacon_bss)->refcount++;
|
|
Takashi Iwai |
ab97d8 |
+
|
|
Takashi Iwai |
ab97d8 |
+ if (bss->pub.transmitted_bss)
|
|
Takashi Iwai |
ab97d8 |
+ bss_from_pub(bss->pub.transmitted_bss)->refcount++;
|
|
Takashi Iwai |
ab97d8 |
}
|
|
Takashi Iwai |
ab97d8 |
|
|
Takashi Iwai |
ab97d8 |
static inline void bss_ref_put(struct cfg80211_registered_device *rdev,
|
|
Takashi Iwai |
ab97d8 |
@@ -1739,6 +1733,8 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
|
|
Takashi Iwai |
ab97d8 |
new->refcount = 1;
|
|
Takashi Iwai |
ab97d8 |
INIT_LIST_HEAD(&new->hidden_list);
|
|
Takashi Iwai |
ab97d8 |
INIT_LIST_HEAD(&new->pub.nontrans_list);
|
|
Takashi Iwai |
ab97d8 |
+ /* we'll set this later if it was non-NULL */
|
|
Takashi Iwai |
ab97d8 |
+ new->pub.transmitted_bss = NULL;
|
|
Takashi Iwai |
ab97d8 |
|
|
Takashi Iwai |
ab97d8 |
if (rcu_access_pointer(tmp->pub.proberesp_ies)) {
|
|
Takashi Iwai |
ab97d8 |
hidden = rb_find_bss(rdev, tmp, BSS_CMP_HIDE_ZLEN);
|
|
Takashi Iwai |
ab97d8 |
@@ -2021,10 +2017,15 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,
|
|
Takashi Iwai |
ab97d8 |
spin_lock_bh(&rdev->bss_lock);
|
|
Takashi Iwai |
ab97d8 |
if (cfg80211_add_nontrans_list(non_tx_data->tx_bss,
|
|
Takashi Iwai |
ab97d8 |
&res->pub)) {
|
|
Takashi Iwai |
ab97d8 |
- if (__cfg80211_unlink_bss(rdev, res))
|
|
Takashi Iwai |
ab97d8 |
+ if (__cfg80211_unlink_bss(rdev, res)) {
|
|
Takashi Iwai |
ab97d8 |
rdev->bss_generation++;
|
|
Takashi Iwai |
ab97d8 |
+ res = NULL;
|
|
Takashi Iwai |
ab97d8 |
+ }
|
|
Takashi Iwai |
ab97d8 |
}
|
|
Takashi Iwai |
ab97d8 |
spin_unlock_bh(&rdev->bss_lock);
|
|
Takashi Iwai |
ab97d8 |
+
|
|
Takashi Iwai |
ab97d8 |
+ if (!res)
|
|
Takashi Iwai |
ab97d8 |
+ return NULL;
|
|
Takashi Iwai |
ab97d8 |
}
|
|
Takashi Iwai |
ab97d8 |
|
|
Takashi Iwai |
ab97d8 |
trace_cfg80211_return_bss(&res->pub);
|
|
Takashi Iwai |
ab97d8 |
--
|
|
Takashi Iwai |
ab97d8 |
2.35.3
|
|
Takashi Iwai |
ab97d8 |
|