Re: Brainy: Kernel Memory Leak in sdmmc

2015-02-15 Thread Doug Hogan
On Sun, Feb 15, 2015 at 08:53:08PM +, Miod Vallat wrote:
 This ought to fix this problem:

This looks reasonable but needs a tweak if you want to keep the existing
behavior.  In the existing code, it has this section above the copyout():

rw_enter_write(sc-sc_lock);
if (request == SDIOCEXECMMC)
error = sdmmc_mmc_command(sc, cmd);
else
error = sdmmc_app_command(sc, cmd);
rw_exit(sc-sc_lock);
if (error  !cmd.c_error)
cmd.c_error = error;

and returns 0 even if error is non-zero.  With this diff, it will either
return the result of those functions or the result of copyout depending
on whether ucmd-c_data is non-zero.  Using the result of copyout is
intentional, but not the result from sdmmc_{mmc,app}_command().

Could you set error=0 after the above chunk or use a new variable?
Also, one of the new lines has space indents rather than a tab.

 Index: sdmmc.c
 ===
 RCS file: /cvs/src/sys/dev/sdmmc/sdmmc.c,v
 retrieving revision 1.36
 diff -u -p -r1.36 sdmmc.c
 --- sdmmc.c   1 Nov 2014 16:32:06 -   1.36
 +++ sdmmc.c   15 Feb 2015 20:52:08 -
 @@ -749,7 +749,7 @@ sdmmc_ioctl(struct device *self, u_long 
   struct sdmmc_command *ucmd;
   struct sdmmc_command cmd;
   void *data;
 - int error;
 + int error = 0;
  
   switch (request) {
  #ifdef SDMMC_DEBUG
 @@ -784,8 +784,9 @@ sdmmc_ioctl(struct device *self, u_long 
   M_WAITOK | M_CANFAIL);
   if (data == NULL)
   return ENOMEM;
 - if (copyin(ucmd-c_data, data, ucmd-c_datalen))
 - return EFAULT;
 + error = copyin(ucmd-c_data, data, ucmd-c_datalen);
 + if (error != 0)
 + goto exec_done;
  
   cmd.c_data = data;
   cmd.c_datalen = ucmd-c_datalen;
 @@ -804,10 +805,10 @@ sdmmc_ioctl(struct device *self, u_long 
   ucmd-c_flags = cmd.c_flags;
   ucmd-c_error = cmd.c_error;
  
 - if (ucmd-c_data  copyout(data, ucmd-c_data,
 - ucmd-c_datalen))
 - return EFAULT;
 + if (ucmd-c_data)
 +error = copyout(data, ucmd-c_data, ucmd-c_datalen);
  
 +exec_done:
   if (ucmd-c_data)
   free(data, M_TEMP, 0);
   break;
 @@ -815,7 +816,7 @@ sdmmc_ioctl(struct device *self, u_long 
   default:
   return ENOTTY;
   }
 - return 0;
 + return error;
  }
  #endif
  
 



Brainy: Kernel Memory Leak in sdmmc

2015-02-15 Thread Maxime Villard
Hi,
I put here a bug among others:

-- dev/sdmmc/sdmmc.c --

783 data = malloc(ucmd-c_datalen, M_TEMP,
M_WAITOK | M_CANFAIL);
if (data == NULL)
return ENOMEM;
if (copyin(ucmd-c_data, data, ucmd-c_datalen))
return EFAULT;

---

'data' is leaked.

Found by The Brainy Code Scanner.

Maxime



Re: Brainy: Kernel Memory Leak in sdmmc

2015-02-15 Thread Miod Vallat
 Hi,
 I put here a bug among others:
 
 -- dev/sdmmc/sdmmc.c --
 
 783   data = malloc(ucmd-c_datalen, M_TEMP,
   M_WAITOK | M_CANFAIL);
   if (data == NULL)
   return ENOMEM;
   if (copyin(ucmd-c_data, data, ucmd-c_datalen))
   return EFAULT;
 
 ---
 
 'data' is leaked.

This ought to fix this problem:

Index: sdmmc.c
===
RCS file: /cvs/src/sys/dev/sdmmc/sdmmc.c,v
retrieving revision 1.36
diff -u -p -r1.36 sdmmc.c
--- sdmmc.c 1 Nov 2014 16:32:06 -   1.36
+++ sdmmc.c 15 Feb 2015 20:52:08 -
@@ -749,7 +749,7 @@ sdmmc_ioctl(struct device *self, u_long 
struct sdmmc_command *ucmd;
struct sdmmc_command cmd;
void *data;
-   int error;
+   int error = 0;
 
switch (request) {
 #ifdef SDMMC_DEBUG
@@ -784,8 +784,9 @@ sdmmc_ioctl(struct device *self, u_long 
M_WAITOK | M_CANFAIL);
if (data == NULL)
return ENOMEM;
-   if (copyin(ucmd-c_data, data, ucmd-c_datalen))
-   return EFAULT;
+   error = copyin(ucmd-c_data, data, ucmd-c_datalen);
+   if (error != 0)
+   goto exec_done;
 
cmd.c_data = data;
cmd.c_datalen = ucmd-c_datalen;
@@ -804,10 +805,10 @@ sdmmc_ioctl(struct device *self, u_long 
ucmd-c_flags = cmd.c_flags;
ucmd-c_error = cmd.c_error;
 
-   if (ucmd-c_data  copyout(data, ucmd-c_data,
-   ucmd-c_datalen))
-   return EFAULT;
+   if (ucmd-c_data)
+  error = copyout(data, ucmd-c_data, ucmd-c_datalen);
 
+exec_done:
if (ucmd-c_data)
free(data, M_TEMP, 0);
break;
@@ -815,7 +816,7 @@ sdmmc_ioctl(struct device *self, u_long 
default:
return ENOTTY;
}
-   return 0;
+   return error;
 }
 #endif
 



Re: Brainy: Kernel Memory Leak in sdmmc

2015-02-15 Thread Miod Vallat
 On Sun, Feb 15, 2015 at 08:53:08PM +, Miod Vallat wrote:
  This ought to fix this problem:
 
 This looks reasonable but needs a tweak if you want to keep the existing
 behavior.  In the existing code, it has this section above the copyout():
 
   rw_enter_write(sc-sc_lock);
   if (request == SDIOCEXECMMC)
   error = sdmmc_mmc_command(sc, cmd);
   else
   error = sdmmc_app_command(sc, cmd);
   rw_exit(sc-sc_lock);
   if (error  !cmd.c_error)
   cmd.c_error = error;
 
 and returns 0 even if error is non-zero.  With this diff, it will either
 return the result of those functions or the result of copyout depending
 on whether ucmd-c_data is non-zero.  Using the result of copyout is
 intentional, but not the result from sdmmc_{mmc,app}_command().
 
 Could you set error=0 after the above chunk or use a new variable?
 Also, one of the new lines has space indents rather than a tab.

Indeed.

Index: sdmmc.c
===
RCS file: /cvs/src/sys/dev/sdmmc/sdmmc.c,v
retrieving revision 1.36
diff -u -p -r1.36 sdmmc.c
--- sdmmc.c 1 Nov 2014 16:32:06 -   1.36
+++ sdmmc.c 16 Feb 2015 05:14:27 -
@@ -749,7 +749,7 @@ sdmmc_ioctl(struct device *self, u_long 
struct sdmmc_command *ucmd;
struct sdmmc_command cmd;
void *data;
-   int error;
+   int error = 0;
 
switch (request) {
 #ifdef SDMMC_DEBUG
@@ -784,8 +784,9 @@ sdmmc_ioctl(struct device *self, u_long 
M_WAITOK | M_CANFAIL);
if (data == NULL)
return ENOMEM;
-   if (copyin(ucmd-c_data, data, ucmd-c_datalen))
-   return EFAULT;
+   error = copyin(ucmd-c_data, data, ucmd-c_datalen);
+   if (error != 0)
+   goto exec_done;
 
cmd.c_data = data;
cmd.c_datalen = ucmd-c_datalen;
@@ -804,10 +805,12 @@ sdmmc_ioctl(struct device *self, u_long 
ucmd-c_flags = cmd.c_flags;
ucmd-c_error = cmd.c_error;
 
-   if (ucmd-c_data  copyout(data, ucmd-c_data,
-   ucmd-c_datalen))
-   return EFAULT;
+   if (ucmd-c_data)
+   error = copyout(data, ucmd-c_data, ucmd-c_datalen);
+   else
+   error = 0;
 
+exec_done:
if (ucmd-c_data)
free(data, M_TEMP, 0);
break;
@@ -815,7 +818,7 @@ sdmmc_ioctl(struct device *self, u_long 
default:
return ENOTTY;
}
-   return 0;
+   return error;
 }
 #endif