From: Xiaoke Wang <xkernel.wang@xxxxxxxxxxx> In _r8712_init_xmit_priv(), if `pxmitbuf->pallocated_buf` is allocated in failure or `r8712_xmit_resource_alloc(padapter, pxmitbuf)` fails, then it just returns -ENOMEM but not releases the previous allocated resources, which leads to various memory leaks. To fix the memory leaks, this patch unifies the error handler in _r8712_init_xmit_priv(). Note that if `r8712_xmit_resource_alloc(padapter, pxmitbuf)` fails, we should call `kfree(pxmitbuf->pallocated_buf);` before goto the error section so that we do not need to concern the failed item. Signed-off-by: Xiaoke Wang <xkernel.wang@xxxxxxxxxxx> --- drivers/staging/rtl8712/rtl871x_xmit.c | 27 ++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c index 090345b..dcf3f76 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.c +++ b/drivers/staging/rtl8712/rtl871x_xmit.c @@ -117,11 +117,8 @@ int _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, _init_queue(&pxmitpriv->pending_xmitbuf_queue); pxmitpriv->pallocated_xmitbuf = kmalloc(NR_XMITBUFF * sizeof(struct xmit_buf) + 4, GFP_ATOMIC); - if (!pxmitpriv->pallocated_xmitbuf) { - kfree(pxmitpriv->pallocated_frame_buf); - pxmitpriv->pallocated_frame_buf = NULL; - return -ENOMEM; - } + if (!pxmitpriv->pallocated_xmitbuf) + goto free_frame_buf; pxmitpriv->pxmitbuf = pxmitpriv->pallocated_xmitbuf + 4 - ((addr_t)(pxmitpriv->pallocated_xmitbuf) & 3); pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf; @@ -130,12 +127,14 @@ int _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, pxmitbuf->pallocated_buf = kmalloc(MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ, GFP_ATOMIC); if (!pxmitbuf->pallocated_buf) - return -ENOMEM; + goto free_xmitbuf; pxmitbuf->pbuf = pxmitbuf->pallocated_buf + XMITBUF_ALIGN_SZ - ((addr_t) (pxmitbuf->pallocated_buf) & (XMITBUF_ALIGN_SZ - 1)); - if (r8712_xmit_resource_alloc(padapter, pxmitbuf)) - return -ENOMEM; + if (r8712_xmit_resource_alloc(padapter, pxmitbuf)) { + kfree(pxmitbuf->pallocated_buf); + goto free_xmitbuf; + } list_add_tail(&pxmitbuf->list, &(pxmitpriv->free_xmitbuf_queue.queue)); pxmitbuf++; @@ -146,6 +145,18 @@ int _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, init_hwxmits(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry); tasklet_setup(&pxmitpriv->xmit_tasklet, r8712_xmit_bh); return 0; + +free_xmitbuf: + pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf; + while (i-- > 0) { + r8712_xmit_resource_free(padapter, pxmitbuf); + kfree(pxmitbuf->pallocated_buf); + pxmitbuf++; + } + kfree(pxmitpriv->pallocated_xmitbuf); +free_frame_buf: + kfree(pxmitpriv->pallocated_frame_buf); + return -ENOMEM; } void _free_xmit_priv(struct xmit_priv *pxmitpriv) --