linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Sergey Vlasov <vsu@altlinux.ru>
To: sensors@stimpy.netroedge.com, linux-kernel@vger.kernel.org
Subject: Re: PATCH: 2.4.22-pre7 drivers/i2c/i2c-dev.c user/kernel bug and   mem leak
Date: Mon, 4 Aug 2003 19:32:12 +0400	[thread overview]
Message-ID: <20030804193212.11786d06.vsu@altlinux.ru> (raw)
In-Reply-To: <20030803192312.68762d3c.khali@linux-fr.org>

On Sun, 3 Aug 2003 19:23:12 +0200
Jean Delvare <khali@linux-fr.org> wrote:

> Ten days ago, Robert T. Johnson repported two bugs in 2.4's
> drivers/i2c/i2c-dev.c. It also applies to i2c CVS (out of kernel), which
> is intended to become 2.4's soon. Being a member of the LM Sensors dev
> team, I took a look at the repport. My knowledge is somewhat limited but
> I'll do my best to help (unless Greg wants to handle it alone? ;-)).
> 
> For the user/kernel bug, I'm not sure I understand how copy_from_user is
> supposed to work. If I understand what the proposed patch does, it
> simply allocates a second buffer, copy_from_user to that buffer instead
> of to the original one, and then copies from that second buffer to the
> original one (kernel to kernel). I just don't see how different it is
> from what the current code does, as far as user/kernel issues are
> concerned. I must be missing something obvious, can someone please bring
> me some light?

The current code takes rdwr_arg.msgs (which is a userspace pointer)
and then reads rdwr_arg.msgs[i].buf directly, which must not be done.
This is done in two places - when copying the user data before
i2c_transfer(), and when copying the result back to the userspace
after it.

Because both the userspace pointer and the kernel buffer pointer are
needed, a second copy must be made. If you want to conserve memory,
you may just allocate an array of pointers to keep the userspace
buffer pointers during the transfer.

BTW, an optimization is possible here: the whole rdwr_arg.msgs array
can be copied into the kernel memory with one copy_from_user() instead
of copying its items one by one.

> For the mem leak bug, it's clearly there. I admit the proposed patch
> fixes it, but I think there is a better way to fix it. Compare what the
> proposed patch does:
> 
> --- i2c-dev.c	Sun Aug  3 18:24:33 2003
> +++ i2c-dev.c.proposed	Sun Aug  3 19:13:58 2003
> @@ -226,6 +226,7 @@
>  		res = 0;
>  		for( i=0; i<rdwr_arg.nmsgs; i++ )
>  		{
> +			rdwr_pa[i].buf = NULL;
>  		    	if(copy_from_user(&(rdwr_pa[i]),
>  					&(rdwr_arg.msgs[i]),
>  					sizeof(rdwr_pa[i])))
> @@ -254,8 +255,9 @@
>  		}
>  		if (res < 0) {
>  			int j;
> -			for (j = 0; j < i; ++j)
> -				kfree(rdwr_pa[j].buf);
> +			for (j = 0; j <= i; ++j)
> +				if (rdwr_pa[j].buf)
> +					kfree(rdwr_pa[j].buf);
>  			kfree(rdwr_pa);
>  			return res;
>  		}
> 
> with what I suggest:
> 
> --- i2c-dev.c	Sun Aug  3 18:24:33 2003
> +++ i2c-dev.c.khali	Sun Aug  3 19:15:04 2003
> @@ -247,8 +247,9 @@
>  			if(copy_from_user(rdwr_pa[i].buf,
>  				rdwr_arg.msgs[i].buf,
>  				rdwr_pa[i].len))
>  			{
> +				kfree(rdwr_pa[i].buf);
>  			    	res = -EFAULT;
>  				break;
>  			}
>  		}
> 
> Contrary to the proposed fix, my fix does not slow down the non-faulty
> cases. I also believe it will increase the code size by fewer bytes than
> the proposed fix (not verified though).

This fix should work too. Yet another way is to do ++i there, but that
would be too obscure.

> So, what about it?

Here is my version (with the mentioned optimization - warning: not
even compiled):

--- i2c-dev.c.old	2003-07-28 16:14:34 +0400
+++ i2c-dev.c	2003-08-04 19:28:25 +0400
@@ -171,6 +171,7 @@
 	struct i2c_smbus_ioctl_data data_arg;
 	union i2c_smbus_data temp;
 	struct i2c_msg *rdwr_pa;
+	u8 **data_ptrs;
 	int i,datasize,res;
 	unsigned long funcs;
 
@@ -223,21 +224,28 @@
 
 		if (rdwr_pa == NULL) return -ENOMEM;
 
+		if (copy_from_user(rdwr_pa, rdwr_arg.msgs,
+				   rdwr_arg.nmsgs * sizeof(struct i2c_msg))) {
+			kfree(rdwr_pa);
+			return -EFAULT;
+		}
+
+		data_ptrs = (u8 **) kmalloc(rdwr_arg.nmsgs * sizeof(u8 *),
+					    GFP_KERNEL);
+		if (data_ptrs == NULL) {
+			kfree(rdwr_pa);
+			return -ENOMEM;
+		}
+
 		res = 0;
 		for( i=0; i<rdwr_arg.nmsgs; i++ )
 		{
-		    	if(copy_from_user(&(rdwr_pa[i]),
-					&(rdwr_arg.msgs[i]),
-					sizeof(rdwr_pa[i])))
-			{
-			        res = -EFAULT;
-				break;
-			}
 			/* Limit the size of the message to a sane amount */
 			if (rdwr_pa[i].len > 8192) {
 				res = -EINVAL;
 				break;
 			}
+			data_ptrs[i] = rdwr_pa[i].buf;
 			rdwr_pa[i].buf = kmalloc(rdwr_pa[i].len, GFP_KERNEL);
 			if(rdwr_pa[i].buf == NULL)
 			{
@@ -245,9 +253,10 @@
 				break;
 			}
 			if(copy_from_user(rdwr_pa[i].buf,
-				rdwr_arg.msgs[i].buf,
+				data_ptrs[i],
 				rdwr_pa[i].len))
 			{
+				kfree(rdwr_pa[i].buf);
 			    	res = -EFAULT;
 				break;
 			}
@@ -256,6 +265,7 @@
 			int j;
 			for (j = 0; j < i; ++j)
 				kfree(rdwr_pa[j].buf);
+			kfree(data_ptrs);
 			kfree(rdwr_pa);
 			return res;
 		}
@@ -270,7 +280,7 @@
 			if( res>=0 && (rdwr_pa[i].flags & I2C_M_RD))
 			{
 				if(copy_to_user(
-					rdwr_arg.msgs[i].buf,
+					data_ptrs[i],
 					rdwr_pa[i].buf,
 					rdwr_pa[i].len))
 				{
@@ -279,6 +289,7 @@
 			}
 			kfree(rdwr_pa[i].buf);
 		}
+		kfree(data_ptrs);
 		kfree(rdwr_pa);
 		return res;
 

  reply	other threads:[~2003-08-04 15:32 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-08-03 17:23 PATCH: 2.4.22-pre7 drivers/i2c/i2c-dev.c user/kernel bug and mem leak Jean Delvare
2003-08-04 15:32 ` Sergey Vlasov [this message]
2003-08-05  8:32   ` Jean Delvare
2003-08-05 14:10     ` Sergey Vlasov
2003-08-05 21:07     ` Greg KH
2003-08-06  8:07       ` [PATCH 2.4] i2c-dev " Jean Delvare
     [not found]         ` <1060886657.1006.7121.camel@dooby.cs.berkeley.edu>
     [not found]           ` <20030814190954.GA2492@kroah.com>
2003-08-15  2:01             ` Robert T. Johnson
2003-08-15 21:13               ` Greg KH
2003-08-15 22:17                 ` Robert T. Johnson
2003-08-15 23:51                   ` Greg KH
2003-08-18  0:54                     ` Robert T. Johnson
2003-08-18 21:05                       ` Greg KH
2003-09-10 23:02                         ` CQual 0.99 Released: user/kernel pointer bug finding tool Robert T. Johnson
2003-08-28  1:17                 ` [PATCH 2.4] i2c-dev user/kernel bug and mem leak Robert T. Johnson
2003-08-29 16:21                   ` Jean Delvare
2003-08-29 17:30                     ` Robert T. Johnson
  -- strict thread matches above, loose matches on Subject: below --
2003-07-23 20:58 PATCH: 2.4.22-pre7 drivers/i2c/i2c-dev.c " Robert T. Johnson
2003-07-24 14:05 ` Greg KH

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20030804193212.11786d06.vsu@altlinux.ru \
    --to=vsu@altlinux.ru \
    --cc=linux-kernel@vger.kernel.org \
    --cc=sensors@stimpy.netroedge.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).