Search Linux Wireless

[PATCH] wifi: cfg80211: fix bss rbn double erase issue

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



If cfg80211_update_assoc_bss_entry call rb_insert_bss re-insert bss
failed because cmp_bss return 0, this bss->rbn will continue to hold
expired data, such as __rd_parent_color.
And this bss still in rdev->bss_list, maybe double erase in
__cfg80211_bss_expire later.
Double erase a rbtree node(with expired parent and color data) maybe
corrupt rbtree, so add a in_rbtree flag to fix this issue.

Signed-off-by: Jiazi Li <jiazi.li@xxxxxxxxxxxxx>
---
 net/wireless/core.h |  1 +
 net/wireless/scan.c | 11 ++++++++---
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/net/wireless/core.h b/net/wireless/core.h
index 79b1c6d17847..36dc1e9de6b9 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -178,6 +178,7 @@ struct cfg80211_internal_bss {
 	unsigned long ts;
 	unsigned long refcount;
 	atomic_t hold;
+	bool in_rbtree;
 
 	/* time at the start of the reception of the first octet of the
 	 * timestamp field of the last beacon/probe received for this BSS.
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 8d114faf4842..d54cb47c1be6 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -202,7 +202,8 @@ static bool __cfg80211_unlink_bss(struct cfg80211_registered_device *rdev,
 
 	list_del_init(&bss->list);
 	list_del_init(&bss->pub.nontrans_list);
-	rb_erase(&bss->rbn, &rdev->bss_tree);
+	if (bss->in_rbtree)
+		rb_erase(&bss->rbn, &rdev->bss_tree);
 	rdev->bss_entries--;
 	WARN_ONCE((rdev->bss_entries == 0) ^ list_empty(&rdev->bss_list),
 		  "rdev bss entries[%d]/list[empty:%d] corruption\n",
@@ -1563,6 +1564,7 @@ static void rb_insert_bss(struct cfg80211_registered_device *rdev,
 
 		if (WARN_ON(!cmp)) {
 			/* will sort of leak this BSS */
+			bss->in_rbtree = false;
 			return;
 		}
 
@@ -1572,6 +1574,7 @@ static void rb_insert_bss(struct cfg80211_registered_device *rdev,
 			p = &(*p)->rb_right;
 	}
 
+	bss->in_rbtree = true;
 	rb_link_node(&bss->rbn, parent, p);
 	rb_insert_color(&bss->rbn, &rdev->bss_tree);
 }
@@ -3061,7 +3064,8 @@ void cfg80211_update_assoc_bss_entry(struct wireless_dev *wdev,
 			rdev->bss_generation++;
 	}
 
-	rb_erase(&cbss->rbn, &rdev->bss_tree);
+	if (cbss->in_rbtree)
+		rb_erase(&cbss->rbn, &rdev->bss_tree);
 	rb_insert_bss(rdev, cbss);
 	rdev->bss_generation++;
 
@@ -3070,7 +3074,8 @@ void cfg80211_update_assoc_bss_entry(struct wireless_dev *wdev,
 				 nontrans_list) {
 		bss = bss_from_pub(nontrans_bss);
 		bss->pub.channel = chan;
-		rb_erase(&bss->rbn, &rdev->bss_tree);
+		if (bss->in_rbtree)
+			rb_erase(&bss->rbn, &rdev->bss_tree);
 		rb_insert_bss(rdev, bss);
 		rdev->bss_generation++;
 	}
-- 
2.17.1




[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux