lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date:   Thu, 24 Nov 2022 23:13:49 +0800
From:   Zhang Xiaoxu <zhangxiaoxu5@...wei.com>
To:     <linux-wireless@...r.kernel.org>, <netdev@...r.kernel.org>,
        <kvalo@...nel.org>, <davem@...emloft.net>, <edumazet@...gle.com>,
        <kuba@...nel.org>, <pabeni@...hat.com>,
        <ajay.kathat@...rochip.com>, <claudiu.beznea@...rochip.com>,
        <zhangxiaoxu5@...wei.com>
Subject: [PATCH wireless] wifi: wilc1000: Fix UAF in wilc_netdev_cleanup() when iterator the RCU list

There is a UAF read when remove the wilc1000_spi module:

 BUG: KASAN: use-after-free in wilc_netdev_cleanup.cold+0xc4/0xe0 [wilc1000]
 Read of size 8 at addr ffff888116846900 by task rmmod/386

 CPU: 2 PID: 386 Comm: rmmod Tainted: G                 N 6.1.0-rc6+ #8
 Call Trace:
  dump_stack_lvl+0x68/0x85
  print_report+0x16c/0x4a3
  kasan_report+0x95/0x190
  wilc_netdev_cleanup.cold+0xc4/0xe0
  wilc_bus_remove+0x52/0x60
  spi_remove+0x46/0x60
  device_remove+0x73/0xc0
  device_release_driver_internal+0x12d/0x210
  driver_detach+0x84/0x100
  bus_remove_driver+0x90/0x120
  driver_unregister+0x4f/0x80
  __x64_sys_delete_module+0x2fc/0x440
  do_syscall_64+0x38/0x90
  entry_SYSCALL_64_after_hwframe+0x63/0xcd

Since set 'needs_free_netdev=true' when initialize the net device, the
net device will be freed when unregister, then use the freed 'vif' to
find the next will UAF read.

Let's unregister the net device after removed from wilc list to avoid
the UAF.

Fixes: 8399918f3056 ("staging: wilc1000: use RCU list to maintain vif interfaces list")
Signed-off-by: Zhang Xiaoxu <zhangxiaoxu5@...wei.com>
---
 drivers/net/wireless/microchip/wilc1000/netdev.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/microchip/wilc1000/netdev.c b/drivers/net/wireless/microchip/wilc1000/netdev.c
index 9b319a455b96..d6374bfd7650 100644
--- a/drivers/net/wireless/microchip/wilc1000/netdev.c
+++ b/drivers/net/wireless/microchip/wilc1000/netdev.c
@@ -879,6 +879,7 @@ void wilc_netdev_cleanup(struct wilc *wilc)
 {
 	struct wilc_vif *vif;
 	int srcu_idx, ifc_cnt = 0;
+	LIST_HEAD(list_kill);
 
 	if (!wilc)
 		return;
@@ -888,16 +889,14 @@ void wilc_netdev_cleanup(struct wilc *wilc)
 		wilc->firmware = NULL;
 	}
 
+	rtnl_lock();
 	srcu_idx = srcu_read_lock(&wilc->srcu);
 	list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
 		if (vif->ndev)
-			unregister_netdev(vif->ndev);
+			unregister_netdevice_queue(vif->ndev, &list_kill);
 	}
 	srcu_read_unlock(&wilc->srcu, srcu_idx);
 
-	wilc_wfi_deinit_mon_interface(wilc, false);
-	destroy_workqueue(wilc->hif_workqueue);
-
 	while (ifc_cnt < WILC_NUM_CONCURRENT_IFC) {
 		mutex_lock(&wilc->vif_mutex);
 		if (wilc->vif_num <= 0) {
@@ -914,6 +913,12 @@ void wilc_netdev_cleanup(struct wilc *wilc)
 		ifc_cnt++;
 	}
 
+	unregister_netdevice_many(&list_kill);
+	rtnl_unlock();
+
+	wilc_wfi_deinit_mon_interface(wilc, false);
+	destroy_workqueue(wilc->hif_workqueue);
+
 	wilc_wlan_cfg_deinit(wilc);
 	wlan_deinit_locks(wilc);
 	wiphy_unregister(wilc->wiphy);
-- 
2.31.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ