Skip to contentSkip to conversation

staging: rtl8723bs: fix several memory-safety bugs

PATCH Superseded Yi Cong 3 participants 7 messages Jul 29 – Jul 30 Staging

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore

Yi Cong

author
#0 lore raw

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.

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     |  6 ++++++
 drivers/staging/rtl8723bs/core/rtw_recv.c    |  5 ++++-
 drivers/staging/rtl8723bs/os_dep/os_intfs.c  | 10 ++++++----
 drivers/staging/rtl8723bs/os_dep/sdio_intf.c |  2 +-
 4 files changed, 17 insertions(+), 6 deletions(-)
Signature · 1 line
2.25.1
author
#1 lore raw

PATCH 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")
---
 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 c43a0391a5ca..f7ec09310ce9 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 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")
---
 drivers/staging/rtl8723bs/os_dep/os_intfs.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/staging/rtl8723bs/os_dep/os_intfs.c +6 -4
index f31196f54b3e..ac401042faf4 100644
@@ -773,10 +773,12 @@ static int _rtw_drv_register_netdev(struct adapter *padapter, char *name)
 
 error_register_netdev:
 
-	rtw_free_drv_sw(padapter);
-
-	rtw_free_netdev(pnetdev);
-
+	/* Let the caller (rtw_drv_init -> rtw_sdio_if1_deinit) release the
+	 * adapter and netdev. Freeing them here would lead to a double free:
+	 * rtw_drv_init() still holds a non-NULL if1 and calls
+	 * rtw_sdio_if1_deinit(), which invokes rtw_free_drv_sw() and
+	 * rtw_free_netdev() again on the already-freed objects.
+	 */
 	return ret;
 }
 
Signature · 1 line
2.25.1
#3 lore raw

Re: [PATCH 2/4] staging: rtl8723bs: fix double free when register_netdev() fails

Quoted 28 lines · 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")
---
 drivers/staging/rtl8723bs/os_dep/os_intfs.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/staging/rtl8723bs/os_dep/os_intfs.c +0 -0
index f31196f54b3e..ac401042faf4 100644
@@ -773,10 +773,12 @@ static int _rtw_drv_register_netdev(struct adapter *padapter, char *name)
 
 error_register_netdev:
 

drivers/staging/rtl8723bs/os_dep/os_intfs.c static int _rtw_drv_register_netdev(struct adapter *padapter, char *name) · line 781

Quoted 10 lines
drivers/staging/rtl8723bs/os_dep/os_intfs.c +6 -4
-	rtw_free_drv_sw(padapter);
-
-	rtw_free_netdev(pnetdev);
-
+	/* Let the caller (rtw_drv_init -> rtw_sdio_if1_deinit) release the
+	 * adapter and netdev. Freeing them here would lead to a double free:
+	 * rtw_drv_init() still holds a non-NULL if1 and calls
+	 * rtw_sdio_if1_deinit(), which invokes rtw_free_drv_sw() and
+	 * rtw_free_netdev() again on the already-freed objects.
+	 */

No need for this comment. These weren't allocated in _rtw_drv_register_netdev() and no one really expects them to be freed here either. AI always adds obvious comments but eventually the kernel will turn into the Terms of Service text which no one can possibly read in a life time.

regards,
dan carpenter

author
#4 lore raw

PATCH 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")
---
 drivers/staging/rtl8723bs/core/rtw_cmd.c | 6 ++++++
 1 file changed, 6 insertions(+)
drivers/staging/rtl8723bs/core/rtw_cmd.c +6 -0
index b932670f5d63..8dc700b9f2e9 100644
@@ -1716,6 +1716,12 @@ static void c2h_wk_callback(struct work_struct *work)
 					kfree(c2h_evt);
 					continue;
 				}
+			} else {
+				/* Give up this event; re-allocation failed. Falling
+				 * through would dereference the NULL c2h_evt in
+				 * rtw_hal_c2h_valid() below.
+				 */
+				continue;
 			}
 		}
 
Signature · 1 line
2.25.1
author
#5 lore raw

PATCH 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")
---
 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 86c5e2c4e7dd..ffcee431caf5 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
maintainer
#6 lore raw
In reply to Yi Cong
Quoted 26 lines · Yi Cong

From: Yi Cong <[email protected]>

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

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

Quoted 5 lines
 drivers/staging/rtl8723bs/core/rtw_cmd.c     |  6 ++++++
 drivers/staging/rtl8723bs/core/rtw_recv.c    |  5 ++++-
 drivers/staging/rtl8723bs/os_dep/os_intfs.c  | 10 ++++++----
 drivers/staging/rtl8723bs/os_dep/sdio_intf.c |  2 +-
 4 files changed, 17 insertions(+), 6 deletions(-)

Did you forget to document the tool you used to find and fix these issues?

thanks,

greg k-h