]> git.baikalelectronics.ru Git - kernel.git/commitdiff
proc: proc_skip_spaces() shouldn't think it is working on C strings
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 5 Dec 2022 20:09:06 +0000 (12:09 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 8 Dec 2022 10:23:06 +0000 (11:23 +0100)
commit bce9332220bd677d83b19d21502776ad555a0e73 upstream.

proc_skip_spaces() seems to think it is working on C strings, and ends
up being just a wrapper around skip_spaces() with a really odd calling
convention.

Instead of basing it on skip_spaces(), it should have looked more like
proc_skip_char(), which really is the exact same function (except it
skips a particular character, rather than whitespace).  So use that as
inspiration, odd coding and all.

Now the calling convention actually makes sense and works for the
intended purpose.

Reported-and-tested-by: Kyle Zeng <zengyhkyle@gmail.com>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
kernel/sysctl.c

index 3d74e0ab2aaeb77fd6a1baa1b5925ff56e075643..decabf5714c0f2c8baa8b8118d834143f3815384 100644 (file)
@@ -2156,13 +2156,14 @@ int proc_dostring(struct ctl_table *table, int write,
                               (char __user *)buffer, lenp, ppos);
 }
 
-static size_t proc_skip_spaces(char **buf)
+static void proc_skip_spaces(char **buf, size_t *size)
 {
-       size_t ret;
-       char *tmp = skip_spaces(*buf);
-       ret = tmp - *buf;
-       *buf = tmp;
-       return ret;
+       while (*size) {
+               if (!isspace(**buf))
+                       break;
+               (*size)--;
+               (*buf)++;
+       }
 }
 
 static void proc_skip_char(char **buf, size_t *size, const char v)
@@ -2399,7 +2400,7 @@ static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
                bool neg;
 
                if (write) {
-                       left -= proc_skip_spaces(&p);
+                       proc_skip_spaces(&p, &left);
 
                        if (!left)
                                break;
@@ -2430,7 +2431,7 @@ static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
        if (!write && !first && left && !err)
                err = proc_put_char(&buffer, &left, '\n');
        if (write && !err && left)
-               left -= proc_skip_spaces(&p);
+               proc_skip_spaces(&p, &left);
        if (write) {
                kfree(kbuf);
                if (first)
@@ -2479,7 +2480,7 @@ static int do_proc_douintvec_w(unsigned int *tbl_data,
        if (IS_ERR(kbuf))
                return -EINVAL;
 
-       left -= proc_skip_spaces(&p);
+       proc_skip_spaces(&p, &left);
        if (!left) {
                err = -EINVAL;
                goto out_free;
@@ -2499,7 +2500,7 @@ static int do_proc_douintvec_w(unsigned int *tbl_data,
        }
 
        if (!err && left)
-               left -= proc_skip_spaces(&p);
+               proc_skip_spaces(&p, &left);
 
 out_free:
        kfree(kbuf);
@@ -2913,7 +2914,7 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int
                if (write) {
                        bool neg;
 
-                       left -= proc_skip_spaces(&p);
+                       proc_skip_spaces(&p, &left);
                        if (!left)
                                break;
 
@@ -2946,7 +2947,7 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int
        if (!write && !first && left && !err)
                err = proc_put_char(&buffer, &left, '\n');
        if (write && !err)
-               left -= proc_skip_spaces(&p);
+               proc_skip_spaces(&p, &left);
        if (write) {
                kfree(kbuf);
                if (first)