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:
parent
f88083005a
commit
2ca9bb456a
|
@ -1717,21 +1717,18 @@ static int _proc_do_string(char *data, int maxlen, int write,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (write) {
|
if (write) {
|
||||||
|
/* Start writing from beginning of buffer. */
|
||||||
len = 0;
|
len = 0;
|
||||||
|
*ppos += *lenp;
|
||||||
p = buffer;
|
p = buffer;
|
||||||
while (len < *lenp) {
|
while ((p - buffer) < *lenp && len < maxlen - 1) {
|
||||||
if (get_user(c, p++))
|
if (get_user(c, p++))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (c == 0 || c == '\n')
|
if (c == 0 || c == '\n')
|
||||||
break;
|
break;
|
||||||
len++;
|
data[len++] = c;
|
||||||
}
|
}
|
||||||
if (len >= maxlen)
|
|
||||||
len = maxlen-1;
|
|
||||||
if(copy_from_user(data, buffer, len))
|
|
||||||
return -EFAULT;
|
|
||||||
data[len] = 0;
|
data[len] = 0;
|
||||||
*ppos += *lenp;
|
|
||||||
} else {
|
} else {
|
||||||
len = strlen(data);
|
len = strlen(data);
|
||||||
if (len > maxlen)
|
if (len > maxlen)
|
||||||
|
|
Loading…
Reference in a new issue