History

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.

Kees Cook committed 12 years ago

Commit 2ca9bb41 parent f8808301 file · +4 −7Browse files

Unified · Split

kernel/sysctl.c+4−7
@@ -1717,21 +1717,18 @@ static int _proc_do_string(char *data, int maxlen, int write, · 1716 unmodified lines
17171717 }
17181718
17191719 if (write) {
1720+ /* Start writing from beginning of buffer. */
17201721 len = 0;
1722+ *ppos += *lenp;
17211723 p = buffer;
1722− while (len < *lenp) {
1724+ while ((p - buffer) < *lenp && len < maxlen - 1) {
17231725 if (get_user(c, p++))
17241726 return -EFAULT;
17251727 if (c == 0 || c == '\n')
17261728 break;
1727− len++;
1729+ data[len++] = c;
17281730 }
1729− if (len >= maxlen)
1730− len = maxlen-1;
1731− if(copy_from_user(data, buffer, len))
1732− return -EFAULT;
17331731 data[len] = 0;
1734− *ppos += *lenp;
17351732 } else {
17361733 len = strlen(data);
17371734 if (len > maxlen)