aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sysctl.c
diff options
context:
space:
mode:
authorEric Sandeen <sandeen@redhat.com>2019-05-14 18:45:13 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-05-14 22:52:51 -0400
commit3116ad38f51c98c81175151bd7358858a92a6031 (patch)
tree050a030511caba8c6a56c783087bd9900b1c885f /kernel/sysctl.c
parent2ea622b887e74497ce5aac5bfe247502b5786f56 (diff)
kernel/sysctl.c: fix proc_do_large_bitmap for large input buffers
Today, proc_do_large_bitmap() truncates a large write input buffer to PAGE_SIZE - 1, which may result in misparsed numbers at the (truncated) end of the buffer. Further, it fails to notify the caller that the buffer was truncated, so it doesn't get called iteratively to finish the entire input buffer. Tell the caller if there's more work to do by adding the skipped amount back to left/*lenp before returning. To fix the misparsing, reset the position if we have completely consumed a truncated buffer (or if just one char is left, which may be a "-" in a range), and ask the caller to come back for more. Link: http://lkml.kernel.org/r/20190320222831.8243-7-mcgrof@kernel.org Signed-off-by: Eric Sandeen <sandeen@redhat.com> Signed-off-by: Luis Chamberlain <mcgrof@kernel.org> Acked-by: Kees Cook <keescook@chromium.org> Cc: Eric Sandeen <sandeen@sandeen.net> 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.c29
1 files changed, 28 insertions, 1 deletions
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index f7bd1aead3bf..943c89178e3d 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -3172,9 +3172,13 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
3172 3172
3173 if (write) { 3173 if (write) {
3174 char *kbuf, *p; 3174 char *kbuf, *p;
3175 size_t skipped = 0;
3175 3176
3176 if (left > PAGE_SIZE - 1) 3177 if (left > PAGE_SIZE - 1) {
3177 left = PAGE_SIZE - 1; 3178 left = PAGE_SIZE - 1;
3179 /* How much of the buffer we'll skip this pass */
3180 skipped = *lenp - left;
3181 }
3178 3182
3179 p = kbuf = memdup_user_nul(buffer, left); 3183 p = kbuf = memdup_user_nul(buffer, left);
3180 if (IS_ERR(kbuf)) 3184 if (IS_ERR(kbuf))
@@ -3189,9 +3193,22 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
3189 while (!err && left) { 3193 while (!err && left) {
3190 unsigned long val_a, val_b; 3194 unsigned long val_a, val_b;
3191 bool neg; 3195 bool neg;
3196 size_t saved_left;
3192 3197
3198 /* In case we stop parsing mid-number, we can reset */
3199 saved_left = left;
3193 err = proc_get_long(&p, &left, &val_a, &neg, tr_a, 3200 err = proc_get_long(&p, &left, &val_a, &neg, tr_a,
3194 sizeof(tr_a), &c); 3201 sizeof(tr_a), &c);
3202 /*
3203 * If we consumed the entirety of a truncated buffer or
3204 * only one char is left (may be a "-"), then stop here,
3205 * reset, & come back for more.
3206 */
3207 if ((left <= 1) && skipped) {
3208 left = saved_left;
3209 break;
3210 }
3211
3195 if (err) 3212 if (err)
3196 break; 3213 break;
3197 if (val_a >= bitmap_len || neg) { 3214 if (val_a >= bitmap_len || neg) {
@@ -3209,6 +3226,15 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
3209 err = proc_get_long(&p, &left, &val_b, 3226 err = proc_get_long(&p, &left, &val_b,
3210 &neg, tr_b, sizeof(tr_b), 3227 &neg, tr_b, sizeof(tr_b),
3211 &c); 3228 &c);
3229 /*
3230 * If we consumed all of a truncated buffer or
3231 * then stop here, reset, & come back for more.
3232 */
3233 if (!left && skipped) {
3234 left = saved_left;
3235 break;
3236 }
3237
3212 if (err) 3238 if (err)
3213 break; 3239 break;
3214 if (val_b >= bitmap_len || neg || 3240 if (val_b >= bitmap_len || neg ||
@@ -3227,6 +3253,7 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
3227 proc_skip_char(&p, &left, '\n'); 3253 proc_skip_char(&p, &left, '\n');
3228 } 3254 }
3229 kfree(kbuf); 3255 kfree(kbuf);
3256 left += skipped;
3230 } else { 3257 } else {
3231 unsigned long bit_a, bit_b = 0; 3258 unsigned long bit_a, bit_b = 0;
3232 3259