staging: rtl8712: clean up dynamic memory management
cover staging: rtl8712: clean up dynamic memory management
This driver is fine if memory allocation never fails. However it does not handle allocation failure well. This can either lead to memory leak, or unallocated buffers being used.
Nam Cao (4):
Revert "staging: r8712u: Tracking kmemleak false positives."
staging: rtl8712: check for alloc fail in _r8712_init_recv_priv()
staging: rtl8712: check for return value of _r8712_init_xmit_priv()
staging: rtl8712: fix potential memory leak
drivers/staging/rtl8712/os_intfs.c | 27 +++++++++++++++++++++----- drivers/staging/rtl8712/recv_osdep.h | 8 ++++---- drivers/staging/rtl8712/rtl8712_recv.c | 7 ++++--- drivers/staging/rtl8712/rtl871x_recv.c | 16 ++++++++------- 4 files changed, 39 insertions(+), 19 deletions(-)
Signature · 1 line
2.25.1
PATCH 1/4 Revert "staging: r8712u: Tracking kmemleak false positives."
This reverts commit 5d3da4a20a271e3cf5496a50cbb8118aa019374f.
This commit annotated false positive for kmemleak. The reasoning is that the buffers are freed when the driver is unloaded. However, there is actually potential memory leak when probe fails.
--- drivers/staging/rtl8712/rtl871x_recv.c | 3 --- 1 file changed, 3 deletions(-)
drivers/staging/rtl8712/rtl871x_recv.c +0 -3
@@ -17,9 +17,7 @@#define _RTL871X_RECV_C_#include <linux/ip.h> -#include <linux/slab.h> #include <linux/if_ether.h> -#include <linux/kmemleak.h> #include <linux/etherdevice.h> #include <linux/ieee80211.h> #include <net/cfg80211.h>
@@ -61,7 +59,6 @@ void _r8712_init_recv_priv(struct recv_priv *precvpriv, GFP_ATOMIC);if (!precvpriv->pallocated_frame_buf)return ; -kmemleak_not_leak (precvpriv->pallocated_frame_buf); precvpriv->precv_frame_buf = precvpriv->pallocated_frame_buf + RXFRAME_ALIGN_SZ - ((addr_t)(precvpriv->pallocated_frame_buf) &
Signature · 1 line
2.25.1
PATCH 2/4 staging: rtl8712: check for alloc fail in _r8712_init_recv_priv()
In reply to Nam CaoThe function _r8712_init_recv_priv() and also r8712_init_recv_priv() just returns silently if they fail to allocate memory. Change their return type to int and add necessary checks and handling if they return -ENOMEM
--- drivers/staging/rtl8712/os_intfs.c | 3 ++- drivers/staging/rtl8712/recv_osdep.h | 8 ++++---- drivers/staging/rtl8712/rtl8712_recv.c | 7 ++++--- drivers/staging/rtl8712/rtl871x_recv.c | 13 +++++++++---- 4 files changed, 19 insertions(+), 12 deletions(-)
drivers/staging/rtl8712/os_intfs.c +2 -1
@@ -309,7 +309,8 @@ int r8712_init_drv_sw(struct _adapter *padapter)if (ret)return ret;_r8712_init_xmit_priv (&padapter->xmitpriv, padapter); -_r8712_init_recv_priv (&padapter->recvpriv, padapter); + ret =_r8712_init_recv_priv (&padapter->recvpriv, padapter); +return ret;memset ((unsigned char *)&padapter->securitypriv,0 ,sizeof (struct security_priv )); timer_setup(&padapter->securitypriv.tkip_timer,
drivers/staging/rtl8712/recv_osdep.h +4 -4
@@ -18,15 +18,15 @@#include "drv_types.h" #include <linux/skbuff.h> -void _r8712_init_recv_priv (struct recv_priv *precvpriv, -struct _adapter *padapter); +int _r8712_init_recv_priv (struct recv_priv *precvpriv, +struct _adapter *padapter);void _r8712_free_recv_priv (struct recv_priv *precvpriv);void r8712_recv_entry (union recv_frame *precv_frame);void r8712_recv_indicatepkt (struct _adapter *adapter,union recv_frame *precv_frame);void r8712_handle_tkip_mic_err (struct _adapter *padapter,u8 bgroup); -void r8712_init_recv_priv (struct recv_priv *precvpriv, -struct _adapter *padapter); +int r8712_init_recv_priv (struct recv_priv *precvpriv, +struct _adapter *padapter);void r8712_free_recv_priv (struct recv_priv *precvpriv);void r8712_os_recv_resource_alloc (struct _adapter *padapter,union recv_frame *precvframe);
drivers/staging/rtl8712/rtl8712_recv.c +4 -3
@@ -30,8 +30,8 @@static void recv_tasklet (struct tasklet_struct *t); -void r8712_init_recv_priv (struct recv_priv *precvpriv, -struct _adapter *padapter) +int r8712_init_recv_priv (struct recv_priv *precvpriv, +struct _adapter *padapter) {int i;struct recv_buf *precvbuf;
@@ -44,7 +44,7 @@ void r8712_init_recv_priv(struct recv_priv *precvpriv, precvpriv->pallocated_recv_buf =kzalloc (NR_RECVBUFF *sizeof (struct recv_buf ) +4 ,GFP_ATOMIC );if (!precvpriv->pallocated_recv_buf) -return ; +return -ENOMEM ; precvpriv->precv_buf = precvpriv->pallocated_recv_buf +4 - ((addr_t)(precvpriv->pallocated_recv_buf) &3 ); precvbuf = (struct recv_buf *)precvpriv->precv_buf;
@@ -75,6 +75,7 @@ void r8712_init_recv_priv(struct recv_priv *precvpriv, } pskb =NULL ; } +return 0 ; }void r8712_free_recv_priv (struct recv_priv *precvpriv)
drivers/staging/rtl8712/rtl871x_recv.c +9 -4
@@ -42,9 +42,10 @@ void _r8712_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv)_init_queue (&psta_recvpriv->defrag_q); } -void _r8712_init_recv_priv (struct recv_priv *precvpriv, -struct _adapter *padapter) +int _r8712_init_recv_priv (struct recv_priv *precvpriv, +struct _adapter *padapter) { +int ret;sint i;union recv_frame *precvframe;
@@ -58,7 +59,7 @@ void _r8712_init_recv_priv(struct recv_priv *precvpriv,sizeof (union recv_frame ) +RXFRAME_ALIGN_SZ , GFP_ATOMIC);if (!precvpriv->pallocated_frame_buf) -return ; +return -ENOMEM ; precvpriv->precv_frame_buf = precvpriv->pallocated_frame_buf + RXFRAME_ALIGN_SZ - ((addr_t)(precvpriv->pallocated_frame_buf) &
@@ -73,7 +74,11 @@ void _r8712_init_recv_priv(struct recv_priv *precvpriv, precvframe++; } precvpriv->rx_pending_cnt =1 ; -r8712_init_recv_priv (precvpriv, padapter); + ret =r8712_init_recv_priv (precvpriv, padapter); +if (ret) +kfree (precvpriv->pallocated_frame_buf); + +return ret; }void _r8712_free_recv_priv (struct recv_priv *precvpriv)
Signature · 1 line
2.25.1
Re: [PATCH 2/4] staging: rtl8712: check for alloc fail in _r8712_init_recv_priv()
Quoted 18 lines · Nam Cao
The function
_r8712_init_recv_priv()and alsor8712_init_recv_priv()just returns silently if they fail to allocate memory. Change their return type to int and add necessary checks and handling if they return-ENOMEMSigned-off-by Nam Cao <[email protected]>--- drivers/staging/rtl8712/os_intfs.c | 3 ++- drivers/staging/rtl8712/recv_osdep.h | 8 ++++---- drivers/staging/rtl8712/rtl8712_recv.c | 7 ++++--- drivers/staging/rtl8712/rtl871x_recv.c | 13 +++++++++---- 4 files changed, 19 insertions(+), 12 deletions(-)drivers/staging/rtl8712/os_intfs.c +0
-0
drivers/staging/rtl8712/os_intfs.c int r8712_init_drv_sw(struct _adapter *padapter) · line 313
Quoted 6 lines
drivers/staging/rtl8712/os_intfs.c +2
-1@@ -309,7 +309,8 @@ int r8712_init_drv_sw(struct _adapter *padapter)if (ret)return ret;_r8712_init_xmit_priv (&padapter->xmitpriv, padapter); -_r8712_init_recv_priv (&padapter->recvpriv, padapter); + ret =_r8712_init_recv_priv (&padapter->recvpriv, padapter); +return ret;
If statement missing.
drivers/staging/rtl8712/os_intfs.c int r8712_init_drv_sw(struct _adapter *padapter) · line 316
Quoted 3 lines
drivers/staging/rtl8712/os_intfs.c +0
-0memset ((unsigned char *)&padapter->securitypriv,0 ,sizeof (struct security_priv )); timer_setup(&padapter->securitypriv.tkip_timer,
regards,
dan carpenter
Re: [PATCH 2/4] staging: rtl8712: check for alloc fail in _r8712_init_recv_priv()
Quoted 14 lines · Dan Carpenter
Quoted 13 lines · Nam Cao
The function
_r8712_init_recv_priv()and alsor8712_init_recv_priv()just returns silently if they fail to allocate memory. Change their return type to int and add necessary checks and handling if they return-ENOMEMSigned-off-by Nam Cao <[email protected]>--- drivers/staging/rtl8712/os_intfs.c | 3 ++- drivers/staging/rtl8712/recv_osdep.h | 8 ++++---- drivers/staging/rtl8712/rtl8712_recv.c | 7 ++++--- drivers/staging/rtl8712/rtl871x_recv.c | 13 +++++++++---- 4 files changed, 19 insertions(+), 12 deletions(-)
Quoted 13 lines
drivers/staging/rtl8712/os_intfs.c int r8712_init_drv_sw(struct _adapter *padapter) · line 313
Quoted 11 lines
drivers/staging/rtl8712/os_intfs.c +2
-1@@ -309,7 +309,8 @@ int r8712_init_drv_sw(struct _adapter *padapter)if (ret)return ret;_r8712_init_xmit_priv (&padapter->xmitpriv, padapter); -_r8712_init_recv_priv (&padapter->recvpriv, padapter); + ret =_r8712_init_recv_priv (&padapter->recvpriv, padapter); +return ret;If statement missing.
Probably a rebase mistake, the if statement is there in the last patch. Will send a v2 nonetheless, thank you for noticing this.
Best regards,
Nam
PATCH 3/4 staging: rtl8712: check for return value of _r8712_init_xmit_priv()
In reply to Nam CaoThe return value of _r8712_init_xmit_priv() is never checked and the driver always continue execution as if all is well. This will cause problems if, for example, buffers cannot be allocated and the driver continue and use those buffers.
Check for return value of _r8712_init_xmit_priv() and return error (if any) during probing.
--- drivers/staging/rtl8712/os_intfs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/staging/rtl8712/os_intfs.c +3 -1
@@ -308,7 +308,9 @@ int r8712_init_drv_sw(struct _adapter *padapter) ret =r8712_init_mlme_priv (padapter);if (ret)return ret; -_r8712_init_xmit_priv (&padapter->xmitpriv, padapter); + ret =_r8712_init_xmit_priv (&padapter->xmitpriv, padapter); +if (ret) +return ret; ret =_r8712_init_recv_priv (&padapter->recvpriv, padapter);return ret; memset((unsigned char *)&padapter->securitypriv, 0,
Signature · 1 line
2.25.1
PATCH 4/4 staging: rtl8712: fix potential memory leak
In reply to Nam CaoIn r8712_init_drv_sw(), whenever any function call returns error, it is returned immediately without properly cleaning up the other successfully executed functions. This can cause memory leak.
Instead of return immediately, free all the allocated buffers first.
--- drivers/staging/rtl8712/os_intfs.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-)
drivers/staging/rtl8712/os_intfs.c +19 -5
@@ -304,28 +304,42 @@ int r8712_init_drv_sw(struct _adapter *padapter) padapter->cmdpriv.padapter = padapter; ret =r8712_init_evt_priv (&padapter->evtpriv);if (ret) -return ret; + goto free_cmd; ret =r8712_init_mlme_priv (padapter);if (ret) -return ret; + goto free_evt; ret =_r8712_init_xmit_priv (&padapter->xmitpriv, padapter);if (ret) -return ret; + goto free_mlme; ret =_r8712_init_recv_priv (&padapter->recvpriv, padapter); -return ret; +if (ret) + goto free_xmit;memset ((unsigned char *)&padapter->securitypriv,0 ,sizeof (struct security_priv ));timer_setup (&padapter->securitypriv.tkip_timer, r8712_use_tkipkey_handler,0 ); ret =_r8712_init_sta_priv (&padapter->stapriv);if (ret) -return ret; + goto free_recv; padapter->stapriv.padapter = padapter;r8712_init_bcmc_stainfo (padapter);r8712_init_pwrctrl_priv (padapter);mp871xinit (padapter);init_default_value (padapter);r8712_InitSwLeds (padapter); + +return 0 ; + +free_recv: +_r8712_free_recv_priv (&padapter->recvpriv); +free_xmit: +_free_xmit_priv (&padapter->xmitpriv); +free_mlme: +r8712_free_mlme_priv (&padapter->mlmepriv); +free_evt: +r8712_free_evt_priv (&padapter->evtpriv); +free_cmd: +r8712_free_cmd_priv (&padapter->cmdpriv);return ret; }
Signature · 1 line
2.25.1