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>
This commit is contained in:
Kees Cook 2014-06-06 14:37:18 -07:00 committed by Linus Torvalds
parent f88083005a
commit 2ca9bb456a

View File

@ -1717,21 +1717,18 @@ static int _proc_do_string(char *data, int maxlen, int write,
}
if (write) {
/* Start writing from beginning of buffer. */
len = 0;
*ppos += *lenp;
p = buffer;
while (len < *lenp) {
while ((p - buffer) < *lenp && len < maxlen - 1) {
if (get_user(c, p++))
return -EFAULT;
if (c == 0 || c == '\n')
break;
len++;
data[len++] = c;
}
if (len >= maxlen)
len = maxlen-1;
if(copy_from_user(data, buffer, len))
return -EFAULT;
data[len] = 0;
*ppos += *lenp;
} else {
len = strlen(data);
if (len > maxlen)