Skip to contentSkip to conversation

staging: rtl8723bs: fix several memory-safety bugs

PATCH In review Yi Cong 2 participants 6 messages Jul 31 – Sep 1 Staging

lore
Share & tools
lore

Yi Cong

author
#0 lore raw

v3 cover staging: rtl8723bs: fix several memory-safety bugs

From: Yi Cong <[email protected]>

This small series fixes four memory-safety / resource-management bugs in the rtl8723bs SDIO staging driver.

v3:
- Add tag "Assisted-by" for each patch.

v2:
- Remove some redundant comments in patch 2 and patch 3.

v1:
- https://lore.kernel.org/all/[email protected]/

All four are tagged:

Fixes 554c0a3abf21 ("staging: Add rtl8723bs sdio wifi driver")

1/4 - kfree() used on a vzalloc() allocation (HalData) in the probe
error path.
2/4 - double free / UAF when register_netdev() fails: the error label
frees objects that the caller also frees.
3/4 - NULL deref in c2h_wk_callback() when the re-read allocation under
memory pressure fails.
4/4 - NULL deref on a bcmc station lookup in the 802.11 defrag path,
reachable from a fragment with an unknown transmitter address.

Yi Cong (4):
staging: rtl8723bs: free HalData with vfree, not kfree
staging: rtl8723bs: fix double free when register_netdev() fails
staging: rtl8723bs: fix NULL deref in c2h_wk_callback() on alloc
failure
staging: rtl8723bs: fix NULL deref on bcmc station lookup in defrag
path

 drivers/staging/rtl8723bs/core/rtw_cmd.c     |  3 ++-
 drivers/staging/rtl8723bs/core/rtw_recv.c    |  5 ++++-
 drivers/staging/rtl8723bs/os_dep/os_intfs.c  | 14 ++------------
 drivers/staging/rtl8723bs/os_dep/sdio_intf.c |  2 +-
 4 files changed, 9 insertions(+), 15 deletions(-)
Signature · 1 line
2.25.1
author
#1 lore raw

PATCH v3 1/4 staging: rtl8723bs: free HalData with vfree, not kfree

From: Yi Cong <[email protected]>

In the probe error path of rtw_sdio_if1_init(), HalData is released with kfree(), but it is allocated with vzalloc() in rtw_hal_data_init(). Freeing a vmalloc allocation with kfree() is undefined behaviour and can corrupt the allocator.

Use rtw_hal_data_deinit() instead, which calls vfree() and is the matching deallocator used on the normal tear-down path. It also NULLs the pointer and clears hal_data_sz, making it safe to call here.

Fixes 554c0a3abf21 ("staging: Add rtl8723bs sdio wifi driver")
Assisted-by GLM:5.2
---
 drivers/staging/rtl8723bs/os_dep/sdio_intf.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/staging/rtl8723bs/os_dep/sdio_intf.c +1 -1
index c43a0391a5ca7..f7ec09310ce98 100644
@@ -286,7 +286,7 @@ static struct adapter *rtw_sdio_if1_init(struct dvobj_priv *dvobj, const struct
 
 free_hal_data:
 	if (status != _SUCCESS && padapter->HalData)
-		kfree(padapter->HalData);
+		rtw_hal_data_deinit(padapter);
 
 	if (status != _SUCCESS) {
 		rtw_wdev_unregister(padapter->rtw_wdev);
Signature · 1 line
2.25.1
author
#2 lore raw

PATCH v3 2/4 staging: rtl8723bs: fix double free when register_netdev() fails

In reply to Yi Cong

From: Yi Cong <[email protected]>

When register_netdev() fails, the error_register_netdev label in _rtw_drv_register_netdev() frees the adapter and netdev via rtw_free_drv_sw()/rtw_free_netdev() and then returns _FAIL.

The caller rtw_drv_init(), however, still holds a non-NULL if1 on this failure path and jumps to free_if1, where rtw_sdio_if1_deinit() invokes rtw_free_drv_sw() and rtw_free_netdev() again on the same already-freed objects, resulting in a double free / use-after-free.

Drop the freeing from error_register_netdev and let rtw_sdio_if1_deinit() perform the tear-down, which is the single owner for this path.

Fixes 554c0a3abf21 ("staging: Add rtl8723bs sdio wifi driver")
Assisted-by GLM:5.2
---
 drivers/staging/rtl8723bs/os_dep/os_intfs.c | 14 ++------------
 1 file changed, 2 insertions(+), 12 deletions(-)
drivers/staging/rtl8723bs/os_dep/os_intfs.c +2 -12
index f31196f54b3e0..84633a51e2db7 100644
@@ -754,7 +754,6 @@ u8 rtw_free_drv_sw(struct adapter *padapter)
 
 static int _rtw_drv_register_netdev(struct adapter *padapter, char *name)
 {
-	int ret = _SUCCESS;
 	struct net_device *pnetdev = padapter->pnetdev;
 
 	/* alloc netdev name */
@@ -765,19 +764,10 @@ static int _rtw_drv_register_netdev(struct adapter *padapter, char *name)
 
 	/* Tell the network stack we exist */
 	if (register_netdev(pnetdev) != 0) {
-		ret = _FAIL;
-		goto error_register_netdev;
+		return _FAIL;
 	}
 
-	return ret;
-
-error_register_netdev:
-
-	rtw_free_drv_sw(padapter);
-
-	rtw_free_netdev(pnetdev);
-
-	return ret;
+	return _SUCCESS;
 }
 
 int rtw_drv_register_netdev(struct adapter *if1)
Signature · 1 line
2.25.1
author
#3 lore raw

PATCH v3 3/4 staging: rtl8723bs: fix NULL deref in c2h_wk_callback() on alloc failure

In reply to Yi Cong

From: Yi Cong <[email protected]>

When the SDIO interrupt handler cannot allocate a c2h event buffer (GFP_ATOMIC under memory pressure) it pushes NULL onto c2h_queue as a "needs re-read" marker and wakes c2h_wk. In c2h_wk_callback(), if the re-allocation also fails, c2h_evt stays NULL and execution falls through to rtw_hal_c2h_valid(adapter, c2h_evt), whose underlying macro dereferences c2h_evt->id, causing a NULL pointer dereference panic.

C2H interrupts are produced by firmware/network events at runtime, so this is reachable under memory pressure. Add a continue in the re-allocation failure branch to give up this event instead of dereferencing NULL.

Fixes 554c0a3abf21 ("staging: Add rtl8723bs sdio wifi driver")
Assisted-by GLM:5.2
---
 drivers/staging/rtl8723bs/core/rtw_cmd.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/staging/rtl8723bs/core/rtw_cmd.c +2 -1
index b932670f5d63a..e9b1136dbf668 100644
@@ -1716,7 +1716,8 @@ static void c2h_wk_callback(struct work_struct *work)
 					kfree(c2h_evt);
 					continue;
 				}
-			}
+			} else
+				continue;
 		}
 
 		/* Special pointer to trigger c2h_evt_clear only */
Signature · 1 line
2.25.1
author
#4 lore raw

PATCH v3 4/4 staging: rtl8723bs: fix NULL deref on bcmc station lookup in defrag path

In reply to Yi Cong

From: Yi Cong <[email protected]>

In recvframe_chk_defrag(), when a fragment's transmitter address is unknown (no associated station) and the frame is not a data frame, the code looks up the broadcast/multicast station with rtw_get_bcmc_stainfo() and immediately dereferences the result to obtain defrag_q, without a NULL check. rtw_get_bcmc_stainfo() (a thin wrapper around rtw_get_stainfo()) can return NULL, for example if the bcmc station has not been or is no longer allocated.

Every other call site of rtw_get_bcmc_stainfo() in the driver checks the return value; this one was missed. A fragment with an unknown transmitter address received from the network (e.g. an injected/rogue management fragment) could thus trigger a NULL pointer dereference panic.

Check the return value and set pdefrag_q = NULL when no bcmc station is available, consistent with the adjacent data-frame branch (the later code already handles pdefrag_q == NULL).

Fixes 554c0a3abf21 ("staging: Add rtl8723bs sdio wifi driver")
Assisted-by GLM:5.2
---
 drivers/staging/rtl8723bs/core/rtw_recv.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/staging/rtl8723bs/core/rtw_recv.c +4 -1
index 86c5e2c4e7ddd..ffcee431caf55 100644
@@ -1146,7 +1146,10 @@ static union recv_frame *recvframe_chk_defrag(struct adapter *padapter, union re
 
 		if (type != WIFI_DATA_TYPE) {
 			psta = rtw_get_bcmc_stainfo(padapter);
-			pdefrag_q = &psta->sta_recvpriv.defrag_q;
+			if (psta)
+				pdefrag_q = &psta->sta_recvpriv.defrag_q;
+			else
+				pdefrag_q = NULL;
 		} else {
 			pdefrag_q = NULL;
 		}
Signature · 1 line
2.25.1