aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@tv-sign.ru>2007-02-10 04:46:38 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-11 14:18:07 -0500
commit8d06087714b78e8921bd30b5c64202fe80c47339 (patch)
treefc55cbbf9fcdd2f9bed838b073f7828a1e78f636
parentc75fb88dbcc470e6041a20b1457b4835b9a0a48a (diff)
[PATCH] _proc_do_string(): fix short reads
If you try to read things like /proc/sys/kernel/osrelease with single-byte reads, you get just one byte and then EOF. This is because _proc_do_string() assumes that the caller is read()ing into a buffer which is large enough to fit the whole string in a single hit. Fix. Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Michael Tokarev <mjt@tls.msk.ru> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--kernel/sysctl.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 84cab0ce44d9..e0ac6cd79fcf 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1686,13 +1686,12 @@ static int _proc_do_string(void* data, int maxlen, int write,
1686 size_t len; 1686 size_t len;
1687 char __user *p; 1687 char __user *p;
1688 char c; 1688 char c;
1689 1689
1690 if (!data || !maxlen || !*lenp || 1690 if (!data || !maxlen || !*lenp) {
1691 (*ppos && !write)) {
1692 *lenp = 0; 1691 *lenp = 0;
1693 return 0; 1692 return 0;
1694 } 1693 }
1695 1694
1696 if (write) { 1695 if (write) {
1697 len = 0; 1696 len = 0;
1698 p = buffer; 1697 p = buffer;
@@ -1713,6 +1712,15 @@ static int _proc_do_string(void* data, int maxlen, int write,
1713 len = strlen(data); 1712 len = strlen(data);
1714 if (len > maxlen) 1713 if (len > maxlen)
1715 len = maxlen; 1714 len = maxlen;
1715
1716 if (*ppos > len) {
1717 *lenp = 0;
1718 return 0;
1719 }
1720
1721 data += *ppos;
1722 len -= *ppos;
1723
1716 if (len > *lenp) 1724 if (len > *lenp)
1717 len = *lenp; 1725 len = *lenp;
1718 if (len) 1726 if (len)