From 24229305112bed5d61363bb11b85dfc9a0b4fab9 Mon Sep 17 00:00:00 2001 From: xuxinchun1003 Date: Wed, 7 Oct 2026 07:42:31 +0800 Subject: [PATCH] fix: NULL-guard usbdev/bus_if in rwnx_close reset path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the vif_started==0 branch rwnx_close() evaluates usbdev->bus_if->state without checking usbdev. On the disconnect path aicwf_bus_deinit() runs before netdev close, so close observes usbdev==NULL and oopses (CR2=0x8, pinned by disassembly relocation rwnx_send_reset; field symptom: host hard-hang on physical unplug, reproduced x8 in the lab with this stack -> BUG=0 after this guard). In the unpatched tree the same expression reads a still-allocated DOWN-state object in the synchronous disconnect path — our earlier "latent UAF" phrasing is retracted (no freed-object access was observed or proven). Covers USB and SDIO variants. --- drivers/aic8800/aic8800_fdrv/rwnx_main.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/aic8800/aic8800_fdrv/rwnx_main.c b/drivers/aic8800/aic8800_fdrv/rwnx_main.c index 9180fe2..8881ccb 100644 --- a/drivers/aic8800/aic8800_fdrv/rwnx_main.c +++ b/drivers/aic8800/aic8800_fdrv/rwnx_main.c @@ -1666,9 +1666,16 @@ static int rwnx_close(struct net_device *dev) rwnx_ipc_tx_drain(rwnx_hw); #else #if defined(AICWF_USB_SUPPORT) - if (usbdev->bus_if->state != BUS_DOWN_ST && usbdev->state != USB_DOWN_ST) + /* 002 在 deinit 时摘 drvdata,disconnect→close 时序下本函数读到 + * usbdev=NULL:实测断开在此裸解引用 usbdev->bus_if 崩溃 + * (rwnx_close 偏移处 reloc=rwnx_send_reset,CR2=0x8)。 + * 上游 usbdev 为悬挂非空、此条件求值为假而侥幸跳过——本判空 + * 对两种情形给出同一语义:bus 已断 → 跳过 reset/重配。 */ + if (usbdev != NULL && usbdev->bus_if != NULL && + usbdev->bus_if->state != BUS_DOWN_ST && usbdev->state != USB_DOWN_ST) #else - if (sdiodev->bus_if->state != BUS_DOWN_ST) + if (sdiodev != NULL && sdiodev->bus_if != NULL && + sdiodev->bus_if->state != BUS_DOWN_ST) #endif { rwnx_send_reset(rwnx_hw);