]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blobdiff - src/patches/linux/linux-5.15-wifi-security-patches-4.patch
linux: Add upstream patches for CVE-2022-4{1674,2719-2722}
[people/pmueller/ipfire-2.x.git] / src / patches / linux / linux-5.15-wifi-security-patches-4.patch
diff --git a/src/patches/linux/linux-5.15-wifi-security-patches-4.patch b/src/patches/linux/linux-5.15-wifi-security-patches-4.patch
new file mode 100644 (file)
index 0000000..bd24390
--- /dev/null
@@ -0,0 +1,96 @@
+From bfe29873454f38eb1a511a76144ad1a4848ca176 Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Fri, 30 Sep 2022 23:44:23 +0200
+Subject: [PATCH] wifi: cfg80211: fix BSS refcounting bugs
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf8
+Content-Transfer-Encoding: 8bit
+
+commit 0b7808818cb9df6680f98996b8e9a439fa7bcc2f upstream.
+
+There are multiple refcounting bugs related to multi-BSSID:
+ - In bss_ref_get(), if the BSS has a hidden_beacon_bss, then
+   the bss pointer is overwritten before checking for the
+   transmitted BSS, which is clearly wrong. Fix this by using
+   the bss_from_pub() macro.
+
+ - In cfg80211_bss_update() we copy the transmitted_bss pointer
+   from tmp into new, but then if we release new, we'll unref
+   it erroneously. We already set the pointer and ref it, but
+   need to NULL it since it was copied from the tmp data.
+
+ - In cfg80211_inform_single_bss_data(), if adding to the non-
+   transmitted list fails, we unlink the BSS and yet still we
+   return it, but this results in returning an entry without
+   a reference. We shouldn't return it anyway if it was broken
+   enough to not get added there.
+
+This fixes CVE-2022-42720.
+
+Reported-by: Sönke Huster <shuster@seemoo.tu-darmstadt.de>
+Tested-by: Sönke Huster <shuster@seemoo.tu-darmstadt.de>
+Fixes: a3584f56de1c ("cfg80211: Properly track transmitting and non-transmitting BSS")
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/wireless/scan.c | 27 ++++++++++++++-------------
+ 1 file changed, 14 insertions(+), 13 deletions(-)
+
+diff --git a/net/wireless/scan.c b/net/wireless/scan.c
+index 04c9b78b3fec..2e576714e989 100644
+--- a/net/wireless/scan.c
++++ b/net/wireless/scan.c
+@@ -143,18 +143,12 @@ static inline void bss_ref_get(struct cfg80211_registered_device *rdev,
+       lockdep_assert_held(&rdev->bss_lock);
+       bss->refcount++;
+-      if (bss->pub.hidden_beacon_bss) {
+-              bss = container_of(bss->pub.hidden_beacon_bss,
+-                                 struct cfg80211_internal_bss,
+-                                 pub);
+-              bss->refcount++;
+-      }
+-      if (bss->pub.transmitted_bss) {
+-              bss = container_of(bss->pub.transmitted_bss,
+-                                 struct cfg80211_internal_bss,
+-                                 pub);
+-              bss->refcount++;
+-      }
++
++      if (bss->pub.hidden_beacon_bss)
++              bss_from_pub(bss->pub.hidden_beacon_bss)->refcount++;
++
++      if (bss->pub.transmitted_bss)
++              bss_from_pub(bss->pub.transmitted_bss)->refcount++;
+ }
+ static inline void bss_ref_put(struct cfg80211_registered_device *rdev,
+@@ -1743,6 +1737,8 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
+               new->refcount = 1;
+               INIT_LIST_HEAD(&new->hidden_list);
+               INIT_LIST_HEAD(&new->pub.nontrans_list);
++              /* we'll set this later if it was non-NULL */
++              new->pub.transmitted_bss = NULL;
+               if (rcu_access_pointer(tmp->pub.proberesp_ies)) {
+                       hidden = rb_find_bss(rdev, tmp, BSS_CMP_HIDE_ZLEN);
+@@ -1983,10 +1979,15 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,
+               spin_lock_bh(&rdev->bss_lock);
+               if (cfg80211_add_nontrans_list(non_tx_data->tx_bss,
+                                              &res->pub)) {
+-                      if (__cfg80211_unlink_bss(rdev, res))
++                      if (__cfg80211_unlink_bss(rdev, res)) {
+                               rdev->bss_generation++;
++                              res = NULL;
++                      }
+               }
+               spin_unlock_bh(&rdev->bss_lock);
++
++              if (!res)
++                      return NULL;
+       }
+       trace_cfg80211_return_bss(&res->pub);
+-- 
+2.30.2
+