diff options
author | Kees Cook <keescook@chromium.org> | 2014-06-06 17:37:18 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-06 19:08:13 -0400 |
commit | 2ca9bb456ada8bcbdc8f77f8fc78207653bbaa92 (patch) | |
tree | 05f8bd09ad6e9b24b735d7cf90c3167bade83050 /kernel/sysctl.c | |
parent | f88083005ab319abba5d0b2e4e997558245493c8 (diff) |
sysctl: refactor sysctl string writing logic
Consolidate buffer length checking with new-line/end-of-line checking.
Additionally, instead of reading user memory twice, just do the
assignment during the loop.
This change doesn't affect the potential races here. It was already
possible to read a sysctl that was in the middle of a write. In both
cases, the string will always be NULL terminated. The pre-existing race
remains a problem to be solved.
Signed-off-by: Kees Cook <keescook@chromium.org>
Cc: Randy Dunlap <rdunlap@infradead.org>
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 | 11 |
1 files changed, 4 insertions, 7 deletions
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 3e214beabbe9..ac6847feaa83 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -1717,21 +1717,18 @@ static int _proc_do_string(char *data, int maxlen, int write, | |||
1717 | } | 1717 | } |
1718 | 1718 | ||
1719 | if (write) { | 1719 | if (write) { |
1720 | /* Start writing from beginning of buffer. */ | ||
1720 | len = 0; | 1721 | len = 0; |
1722 | *ppos += *lenp; | ||
1721 | p = buffer; | 1723 | p = buffer; |
1722 | while (len < *lenp) { | 1724 | while ((p - buffer) < *lenp && len < maxlen - 1) { |
1723 | if (get_user(c, p++)) | 1725 | if (get_user(c, p++)) |
1724 | return -EFAULT; | 1726 | return -EFAULT; |
1725 | if (c == 0 || c == '\n') | 1727 | if (c == 0 || c == '\n') |
1726 | break; | 1728 | break; |
1727 | len++; | 1729 | data[len++] = c; |
1728 | } | 1730 | } |
1729 | if (len >= maxlen) | ||
1730 | len = maxlen-1; | ||
1731 | if(copy_from_user(data, buffer, len)) | ||
1732 | return -EFAULT; | ||
1733 | data[len] = 0; | 1731 | data[len] = 0; |
1734 | *ppos += *lenp; | ||
1735 | } else { | 1732 | } else { |
1736 | len = strlen(data); | 1733 | len = strlen(data); |
1737 | if (len > maxlen) | 1734 | if (len > maxlen) |