staging: r8188eu: fix potential memory leak in _rtw_init_xmit_priv()
authorXiaoke Wang <xkernel.wang@foxmail.com>
Tue, 13 Sep 2022 13:24:05 +0000 (21:24 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 24 Sep 2022 11:08:44 +0000 (13:08 +0200)
In _rtw_init_xmit_priv(), there are several error paths for allocation
failures just jump to the `exit` section. However, there is no action
will be performed, so the allocated resources are not properly released,
which leads to various memory leaks.

To properly release them, this patch unifies the error handling code and
several error handling paths are added.
According to the allocation sequence, if the validation fails, it will
jump to its corresponding error tag to release the resources.

Tested-by: Philipp Hortmann <philipp.g.hortmann@gmail.com> # Edimax N150
Signed-off-by: Xiaoke Wang <xkernel.wang@foxmail.com>
Link: https://lore.kernel.org/r/tencent_DB57E4F270F4539485C32B05FDAF8394310A@qq.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/r8188eu/core/rtw_xmit.c

index 13ecd108c86b671d08c4216918c619350afeaf9d..fbbbdf2856c675d90d9cfded6ecf61d2f968a8fb 100644 (file)
@@ -134,7 +134,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 *)ALIGN((size_t)(pxmitpriv->pallocated_xmitbuf), 4);
@@ -156,7 +156,7 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
                        msleep(10);
                        res = rtw_xmit_resource_alloc(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ));
                        if (res == _FAIL)
-                               goto exit;
+                               goto free_xmitbuf;
                }
 
                pxmitbuf->flags = XMIT_VO_QUEUE;
@@ -174,7 +174,7 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
 
        if (!pxmitpriv->pallocated_xmit_extbuf) {
                res = _FAIL;
-               goto exit;
+               goto free_xmitbuf;
        }
 
        pxmitpriv->pxmit_extbuf = (u8 *)ALIGN((size_t)(pxmitpriv->pallocated_xmit_extbuf), 4);
@@ -191,7 +191,7 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
                res = rtw_xmit_resource_alloc(padapter, pxmitbuf, max_xmit_extbuf_size + XMITBUF_ALIGN_SZ);
                if (res == _FAIL) {
                        res = _FAIL;
-                       goto exit;
+                       goto free_xmit_extbuf;
                }
 
                list_add_tail(&pxmitbuf->list, &pxmitpriv->free_xmit_extbuf_queue.queue);
@@ -202,7 +202,7 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
 
        if (rtw_alloc_hwxmits(padapter)) {
                res = _FAIL;
-               goto exit;
+               goto free_xmit_extbuf;
        }
 
        rtw_init_hwxmits(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
@@ -226,8 +226,26 @@ s32        _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
 
        rtl8188eu_init_xmit_priv(padapter);
 
-exit:
+       return _SUCCESS;
 
+free_xmit_extbuf:
+       pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf;
+       while (i--) {
+               rtw_xmit_resource_free(padapter, pxmitbuf, (max_xmit_extbuf_size + XMITBUF_ALIGN_SZ));
+               pxmitbuf++;
+       }
+       vfree(pxmitpriv->pallocated_xmit_extbuf);
+       i = NR_XMITBUFF;
+free_xmitbuf:
+       pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf;
+       while (i--) {
+               rtw_xmit_resource_free(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ));
+               pxmitbuf++;
+       }
+       vfree(pxmitpriv->pallocated_xmitbuf);
+free_frame_buf:
+       vfree(pxmitpriv->pallocated_frame_buf);
+exit:
        return res;
 }