2022-09-26 08:45:16

by Xiaoke Wang

[permalink] [raw]
Subject: [PATCH v3] staging: rtl8723bs: fix potential memory leak in _rtw_init_xmit_priv()

From: Xiaoke Wang <[email protected]>

In _rtw_init_xmit_priv(), there are seven error paths for allocation
failures without releasing the resources but directly goto `exit`, while
the exit section only executes `return res;`, which can lead to various
memory leaks.

To properly release them, this patch unifies the error handlers of
_rtw_init_xmit_priv() and several error handling paths are added.
According to the allocation sequence, each error will jump to its
corresponding error handling tag.

As there is no proper device to test with, no runtime testing was
performed.

Signed-off-by: Xiaoke Wang <[email protected]>
---
ChangeLog:
v1->v2 update the description.
v2->v3 update the description.
drivers/staging/rtl8723bs/core/rtw_xmit.c | 50 +++++++++++++++++------
1 file changed, 37 insertions(+), 13 deletions(-)

diff --git a/drivers/staging/rtl8723bs/core/rtw_xmit.c b/drivers/staging/rtl8723bs/core/rtw_xmit.c
index 528f920..b288b04 100644
--- a/drivers/staging/rtl8723bs/core/rtw_xmit.c
+++ b/drivers/staging/rtl8723bs/core/rtw_xmit.c
@@ -112,7 +112,7 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)

if (!pxmitpriv->pallocated_xmitbuf) {
res = _FAIL;
- goto exit;
+ goto free_frame_buf;
}

pxmitpriv->pxmitbuf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(pxmitpriv->pallocated_xmitbuf), 4);
@@ -132,7 +132,7 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
msleep(10);
res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ), true);
if (res == _FAIL)
- goto exit;
+ goto free_xmitbuf;
}

pxmitbuf->phead = pxmitbuf->pbuf;
@@ -162,7 +162,7 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
if (!pxmitpriv->xframe_ext_alloc_addr) {
pxmitpriv->xframe_ext = NULL;
res = _FAIL;
- goto exit;
+ goto free_xmitbuf;
}
pxmitpriv->xframe_ext = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(pxmitpriv->xframe_ext_alloc_addr), 4);
pxframe = (struct xmit_frame *)pxmitpriv->xframe_ext;
@@ -195,7 +195,7 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)

if (!pxmitpriv->pallocated_xmit_extbuf) {
res = _FAIL;
- goto exit;
+ goto free_xframe_ext;
}

pxmitpriv->pxmit_extbuf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(pxmitpriv->pallocated_xmit_extbuf), 4);
@@ -210,10 +210,8 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
pxmitbuf->buf_tag = XMITBUF_MGNT;

res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, MAX_XMIT_EXTBUF_SZ + XMITBUF_ALIGN_SZ, true);
- if (res == _FAIL) {
- res = _FAIL;
- goto exit;
- }
+ if (res == _FAIL)
+ goto free_xmit_extbuf;

pxmitbuf->phead = pxmitbuf->pbuf;
pxmitbuf->pend = pxmitbuf->pbuf + MAX_XMIT_EXTBUF_SZ;
@@ -240,10 +238,8 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
pxmitbuf->buf_tag = XMITBUF_CMD;

res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, MAX_CMDBUF_SZ+XMITBUF_ALIGN_SZ, true);
- if (res == _FAIL) {
- res = _FAIL;
- goto exit;
- }
+ if (res == _FAIL)
+ goto free_cmd_xmitbuf;

pxmitbuf->phead = pxmitbuf->pbuf;
pxmitbuf->pend = pxmitbuf->pbuf + MAX_CMDBUF_SZ;
@@ -255,7 +251,7 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)

res = rtw_alloc_hwxmits(padapter);
if (res == _FAIL)
- goto exit;
+ goto free_cmd_xmitbuf;
rtw_init_hwxmits(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);

for (i = 0; i < 4; i++)
@@ -267,6 +263,34 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)

rtw_hal_init_xmit_priv(padapter);

+ return res;
+
+free_cmd_xmitbuf:
+ while (i--) {
+ pxmitbuf = &pxmitpriv->pcmd_xmitbuf[i];
+ if (pxmitbuf)
+ rtw_os_xmit_resource_free(padapter, pxmitbuf, MAX_CMDBUF_SZ + XMITBUF_ALIGN_SZ, true);
+ }
+ i = NR_XMIT_EXTBUFF;
+free_xmit_extbuf:
+ pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf;
+ while (i--) {
+ rtw_os_xmit_resource_free(padapter, pxmitbuf, (MAX_XMIT_EXTBUF_SZ + XMITBUF_ALIGN_SZ), true);
+ pxmitbuf++;
+ }
+ vfree(pxmitpriv->pallocated_xmit_extbuf);
+free_xframe_ext:
+ vfree(pxmitpriv->xframe_ext_alloc_addr);
+ i = NR_XMITBUFF;
+free_xmitbuf:
+ pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf;
+ while (i--) {
+ rtw_os_xmit_resource_free(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ), true);
+ pxmitbuf++;
+ }
+ vfree(pxmitpriv->pallocated_xmitbuf);
+free_frame_buf:
+ vfree(pxmitpriv->pallocated_frame_buf);
exit:
return res;
}
--


2022-09-27 08:13:41

by Dan Carpenter

[permalink] [raw]
Subject: Re: [PATCH v3] staging: rtl8723bs: fix potential memory leak in _rtw_init_xmit_priv()

On Mon, Sep 26, 2022 at 03:54:57PM +0800, [email protected] wrote:
> From: Xiaoke Wang <[email protected]>
>
> In _rtw_init_xmit_priv(), there are seven error paths for allocation
> failures without releasing the resources but directly goto `exit`, while
> the exit section only executes `return res;`, which can lead to various
> memory leaks.
>
> To properly release them, this patch unifies the error handlers of
> _rtw_init_xmit_priv() and several error handling paths are added.
> According to the allocation sequence, each error will jump to its
> corresponding error handling tag.
>
> As there is no proper device to test with, no runtime testing was
> performed.
>
> Signed-off-by: Xiaoke Wang <[email protected]>

This seems to introduce a similar use after free as mentioned in the
change to the other rtl driver.

list_add() followed by a free.

regards,
dan carpenter