sysctl: returns -EINVAL when a negative value is passed to proc_doulongvec_minmax
authorBaokun Li <libaokun1@huawei.com>
Sat, 22 Jan 2022 06:13:48 +0000 (22:13 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 22 Jan 2022 06:33:37 +0000 (08:33 +0200)
When we pass a negative value to the proc_doulongvec_minmax() function,
the function returns 0, but the corresponding interface value does not
change.

we can easily reproduce this problem with the following commands:

    cd /proc/sys/fs/epoll
    echo -1 > max_user_watches; echo $?; cat max_user_watches

This function requires a non-negative number to be passed in, so when a
negative number is passed in, -EINVAL is returned.

Link: https://lkml.kernel.org/r/20211220092627.3744624-1-libaokun1@huawei.com
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reported-by: Hulk Robot <hulkci@huawei.com>
Acked-by: Luis Chamberlain <mcgrof@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
kernel/sysctl.c

index e92e8d21d6bf493fa4a663c5c41bcf07a863cbe7..5ae443b2882e2f4698a4a71a44be462613967308 100644 (file)
@@ -1145,10 +1145,11 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table,
                        err = proc_get_long(&p, &left, &val, &neg,
                                             proc_wspace_sep,
                                             sizeof(proc_wspace_sep), NULL);
-                       if (err)
+                       if (err || neg) {
+                               err = -EINVAL;
                                break;
-                       if (neg)
-                               continue;
+                       }
+
                        val = convmul * val / convdiv;
                        if ((min && val < *min) || (max && val > *max)) {
                                err = -EINVAL;