The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH] sunrpc - fixup userspace buffer possible overrun v2
@ 2008-08-31 10:08 Cyrill Gorcunov
  2008-08-31 10:35 ` Vegard Nossum
  2008-08-31 14:09 ` Ingo Oeser
  0 siblings, 2 replies; 5+ messages in thread
From: Cyrill Gorcunov @ 2008-08-31 10:08 UTC (permalink / raw)
  To: LKML; +Cc: Vegard Nossum, bfields, neilb

Vegard Nossum reported
----------------------
> I noticed that something weird is going on with /proc/sys/sunrpc/transports.
> This file is generated in net/sunrpc/sysctl.c, function proc_do_xprt(). When
> I "cat" this file, I get the expected output:
>    $ cat /proc/sys/sunrpc/transports
>    tcp 1048576
>    udp 32768

> But I think that it does not check the length of the buffer supplied by
> userspace to read(). With my original program, I found that the stack was
> being overwritten by the characters above, even when the length given to
> read() was just 1.

David Wagner added (among other things) that copy_to_user could be
probably used here.

The conclusion is that proc_do_xprt doesn't check for userside buffer
size indeed so fix. Also set lenp to number of bytes were really written.

Reported-by: Vegard Nossum <vegard.nossum@gmail.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
CC: David Wagner <daw@cs.berkeley.edu>
---

Please review.

Index: linux-2.6.git/net/sunrpc/sysctl.c
===================================================================
--- linux-2.6.git.orig/net/sunrpc/sysctl.c	2008-08-31 13:43:46.000000000 +0400
+++ linux-2.6.git/net/sunrpc/sysctl.c	2008-08-31 13:58:14.000000000 +0400
@@ -60,23 +60,26 @@ static int proc_do_xprt(ctl_table *table
 			void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	char tmpbuf[256];
-	int len;
+	size_t len;
+
 	if ((*ppos && !write) || !*lenp) {
 		*lenp = 0;
 		return 0;
 	}
+
 	if (write)
 		return -EINVAL;
 	else {
 		len = svc_print_xprts(tmpbuf, sizeof(tmpbuf));
-		if (!access_ok(VERIFY_WRITE, buffer, len))
-			return -EFAULT;
-
-		if (__copy_to_user(buffer, tmpbuf, len))
+		if (len > *lenp)
+			len = *lenp;
+		if (copy_to_user(buffer, tmpbuf, len))
 			return -EFAULT;
 	}
-	*lenp -= len;
+
+	*lenp = len;
 	*ppos += len;
+
 	return 0;
 }
 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] sunrpc - fixup userspace buffer possible overrun v2
  2008-08-31 10:08 [PATCH] sunrpc - fixup userspace buffer possible overrun v2 Cyrill Gorcunov
@ 2008-08-31 10:35 ` Vegard Nossum
  2008-08-31 14:09 ` Ingo Oeser
  1 sibling, 0 replies; 5+ messages in thread
From: Vegard Nossum @ 2008-08-31 10:35 UTC (permalink / raw)
  To: Cyrill Gorcunov; +Cc: LKML, bfields, neilb

On Sun, Aug 31, 2008 at 12:08 PM, Cyrill Gorcunov <gorcunov@gmail.com> wrote:
> Vegard Nossum reported
> ----------------------
>> I noticed that something weird is going on with /proc/sys/sunrpc/transports.
>> This file is generated in net/sunrpc/sysctl.c, function proc_do_xprt(). When
>> I "cat" this file, I get the expected output:
>>    $ cat /proc/sys/sunrpc/transports
>>    tcp 1048576
>>    udp 32768
>
>> But I think that it does not check the length of the buffer supplied by
>> userspace to read(). With my original program, I found that the stack was
>> being overwritten by the characters above, even when the length given to
>> read() was just 1.
>
> David Wagner added (among other things) that copy_to_user could be
> probably used here.
>
> The conclusion is that proc_do_xprt doesn't check for userside buffer
> size indeed so fix. Also set lenp to number of bytes were really written.
>
> Reported-by: Vegard Nossum <vegard.nossum@gmail.com>
> Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
> CC: David Wagner <daw@cs.berkeley.edu>
> ---
>
> Please review.

read() returns the correct number of bytes written in to the buffer.
read() does not overwrite the buffer past the length that the user supplied.
Too small buffer results in a partial data.

But trying to call read() twice results in first a partial buffer, then EOF:

open("/proc/sys/sunrpc/transports", O_RDONLY) = 3
read(3, "tc", 2)                        = 2
read(3, "", 2)                          = 0

Maybe this can be fixed later.

Tested-by: Vegard Nossum <vegard.nossum@gmail.com>


Vegard

-- 
"The animistic metaphor of the bug that maliciously sneaked in while
the programmer was not looking is intellectually dishonest as it
disguises that the error is the programmer's own creation."
	-- E. W. Dijkstra, EWD1036

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] sunrpc - fixup userspace buffer possible overrun v2
  2008-08-31 10:08 [PATCH] sunrpc - fixup userspace buffer possible overrun v2 Cyrill Gorcunov
  2008-08-31 10:35 ` Vegard Nossum
@ 2008-08-31 14:09 ` Ingo Oeser
  2008-08-31 14:41   ` Cyrill Gorcunov
  1 sibling, 1 reply; 5+ messages in thread
From: Ingo Oeser @ 2008-08-31 14:09 UTC (permalink / raw)
  To: Cyrill Gorcunov; +Cc: LKML, Vegard Nossum, bfields, neilb

Hi Cyrill,

On Sunday 31 August 2008, Cyrill Gorcunov wrote:
> The conclusion is that proc_do_xprt doesn't check for userside buffer
> size indeed so fix. Also set lenp to number of bytes were really written.

Why not use  simple_read_from_buffer() for the read case and
keep the -EINVAL for the write case.

> Reported-by: Vegard Nossum <vegard.nossum@gmail.com>
> Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
> CC: David Wagner <daw@cs.berkeley.edu>
> ---
> 
> Please review.
> 
> Index: linux-2.6.git/net/sunrpc/sysctl.c
> ===================================================================
> --- linux-2.6.git.orig/net/sunrpc/sysctl.c	2008-08-31 13:43:46.000000000 +0400
> +++ linux-2.6.git/net/sunrpc/sysctl.c	2008-08-31 13:58:14.000000000 +0400
> @@ -60,23 +60,26 @@ static int proc_do_xprt(ctl_table *table
>  			void __user *buffer, size_t *lenp, loff_t *ppos)
>  {
>  	char tmpbuf[256];
> -	int len;
> +	size_t len;
> +
+ ssize_t ret;
>  	if ((*ppos && !write) || !*lenp) {
>  		*lenp = 0;
>  		return 0;
>  	}
> +
>  	if (write)
>  		return -EINVAL;

        len = svc_print_xprts(tmpbuf, sizeof(tmpbuf));
	ret = simple_read_from_buffer(buffer, ppos, tmpbuf, len);
	if (ret >= 0) {
		*lenp = ret;
		ret = 0;
	}

	return ret;
   }


Best Regards

Ingo Oeser

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] sunrpc - fixup userspace buffer possible overrun v2
  2008-08-31 14:09 ` Ingo Oeser
@ 2008-08-31 14:41   ` Cyrill Gorcunov
  2008-08-31 14:44     ` Cyrill Gorcunov
  0 siblings, 1 reply; 5+ messages in thread
From: Cyrill Gorcunov @ 2008-08-31 14:41 UTC (permalink / raw)
  To: Ingo Oeser; +Cc: LKML, Vegard Nossum, bfields, neilb

[Ingo Oeser - Sun, Aug 31, 2008 at 04:09:10PM +0200]
| Hi Cyrill,
| 
| On Sunday 31 August 2008, Cyrill Gorcunov wrote:
| > The conclusion is that proc_do_xprt doesn't check for userside buffer
| > size indeed so fix. Also set lenp to number of bytes were really written.
| 
| Why not use  simple_read_from_buffer() for the read case and
| keep the -EINVAL for the write case.

Ah, thanks Ingo - good idea. Btw does libfs.c depends
on anything?

| 
| > Reported-by: Vegard Nossum <vegard.nossum@gmail.com>
| > Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
| > CC: David Wagner <daw@cs.berkeley.edu>
| > ---
| > 
| > Please review.
| > 
| > Index: linux-2.6.git/net/sunrpc/sysctl.c
| > ===================================================================
| > --- linux-2.6.git.orig/net/sunrpc/sysctl.c	2008-08-31 13:43:46.000000000 +0400
| > +++ linux-2.6.git/net/sunrpc/sysctl.c	2008-08-31 13:58:14.000000000 +0400
| > @@ -60,23 +60,26 @@ static int proc_do_xprt(ctl_table *table
| >  			void __user *buffer, size_t *lenp, loff_t *ppos)
| >  {
| >  	char tmpbuf[256];
| > -	int len;
| > +	size_t len;
| > +
| + ssize_t ret;
| >  	if ((*ppos && !write) || !*lenp) {
| >  		*lenp = 0;
| >  		return 0;
| >  	}
| > +
| >  	if (write)
| >  		return -EINVAL;
| 
|         len = svc_print_xprts(tmpbuf, sizeof(tmpbuf));
| 	ret = simple_read_from_buffer(buffer, ppos, tmpbuf, len);
| 	if (ret >= 0) {
| 		*lenp = ret;
| 		ret = 0;
| 	}
| 
| 	return ret;
|    }
| 
| 
| Best Regards
| 
| Ingo Oeser
| 
		- Cyrill -

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] sunrpc - fixup userspace buffer possible overrun v2
  2008-08-31 14:41   ` Cyrill Gorcunov
@ 2008-08-31 14:44     ` Cyrill Gorcunov
  0 siblings, 0 replies; 5+ messages in thread
From: Cyrill Gorcunov @ 2008-08-31 14:44 UTC (permalink / raw)
  To: Ingo Oeser, LKML, Vegard Nossum, bfields, neilb

[Cyrill Gorcunov - Sun, Aug 31, 2008 at 06:41:29PM +0400]
| [Ingo Oeser - Sun, Aug 31, 2008 at 04:09:10PM +0200]
| | Hi Cyrill,
| | 
| | On Sunday 31 August 2008, Cyrill Gorcunov wrote:
| | > The conclusion is that proc_do_xprt doesn't check for userside buffer
| | > size indeed so fix. Also set lenp to number of bytes were really written.
| | 
| | Why not use  simple_read_from_buffer() for the read case and
| | keep the -EINVAL for the write case.
| 
| Ah, thanks Ingo - good idea. Btw does libfs.c depends
| on anything?
|
...

yes, it's always compiled in.
 
		- Cyrill -

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2008-08-31 14:44 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-08-31 10:08 [PATCH] sunrpc - fixup userspace buffer possible overrun v2 Cyrill Gorcunov
2008-08-31 10:35 ` Vegard Nossum
2008-08-31 14:09 ` Ingo Oeser
2008-08-31 14:41   ` Cyrill Gorcunov
2008-08-31 14:44     ` Cyrill Gorcunov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox