Vegard Nossum reported
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;
}
--
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 --
Hi Cyrill,
Why not use simple_read_from_buffer() for the read case and
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
--
[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 -
--
[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 - --
| Jesse Barnes | Re: [stable] [BUG][PATCH] cpqphp: fix kernel NULL pointer dereference |
| Greg KH | [003/136] p54usb: add Zcomax XG-705A usbid |
| Magnus Damm | [PATCH 03/07] ARM: Use shared GIC entry macros on Realview |
| Oliver Neukum | Re: [Bug #13682] The webcam stopped working when upgrading from 2.6.29 to 2.6.30 |
| Martin Schwidefsky | Re: [PATCH] optimized ktime_get[_ts] for GENERIC_TIME=y |
git: | |
| Junio C Hamano | Re: Some advanced index playing |
| Jeff King | Re: confusion over the new branch and merge config |
| Robin Rosenberg | Re: cvs2svn conversion directly to git ready for experimentation |
| Linus Torvalds | git binary size... |
| Ævar Arnfjörð Bjarmason | Re: Challenge with Git-Bash |
| Linux Kernel Mailing List | md: move allocation of ->queue from mddev_find to md_probe |
| Linux Kernel Mailing List | md: raid0: Represent zone->zone_offset in sectors. |
| Linux Kernel Mailing List | [ARM] S3C24XX: Add gpio_to_irq() facility |
| Linux Kernel Mailing List |
