diff options
author | Oleg Nesterov <oleg@tv-sign.ru> | 2007-02-10 04:46:38 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-11 14:18:07 -0500 |
commit | 8d06087714b78e8921bd30b5c64202fe80c47339 (patch) | |
tree | fc55cbbf9fcdd2f9bed838b073f7828a1e78f636 /kernel/sysctl.c | |
parent | c75fb88dbcc470e6041a20b1457b4835b9a0a48a (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>
Diffstat (limited to 'kernel/sysctl.c')
-rw-r--r-- | kernel/sysctl.c | 16 |
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) |