scsi: megaraid_sas: Print FW fault information
[linux-2.6-microblaze.git] / kernel / sysctl.c
index 599510a..943c891 100644 (file)
@@ -66,6 +66,7 @@
 #include <linux/kexec.h>
 #include <linux/bpf.h>
 #include <linux/mount.h>
+#include <linux/userfaultfd_k.h>
 
 #include "../lib/kstrtox.h"
 
@@ -1719,6 +1720,17 @@ static struct ctl_table vm_table[] = {
                .extra1         = (void *)&mmap_rnd_compat_bits_min,
                .extra2         = (void *)&mmap_rnd_compat_bits_max,
        },
+#endif
+#ifdef CONFIG_USERFAULTFD
+       {
+               .procname       = "unprivileged_userfaultfd",
+               .data           = &sysctl_unprivileged_userfaultfd,
+               .maxlen         = sizeof(sysctl_unprivileged_userfaultfd),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &zero,
+               .extra2         = &one,
+       },
 #endif
        { }
 };
@@ -2874,8 +2886,10 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int
                        if (neg)
                                continue;
                        val = convmul * val / convdiv;
-                       if ((min && val < *min) || (max && val > *max))
-                               continue;
+                       if ((min && val < *min) || (max && val > *max)) {
+                               err = -EINVAL;
+                               break;
+                       }
                        *i = val;
                } else {
                        val = convdiv * (*i) / convmul;
@@ -3158,17 +3172,19 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
 
        if (write) {
                char *kbuf, *p;
+               size_t skipped = 0;
 
-               if (left > PAGE_SIZE - 1)
+               if (left > PAGE_SIZE - 1) {
                        left = PAGE_SIZE - 1;
+                       /* How much of the buffer we'll skip this pass */
+                       skipped = *lenp - left;
+               }
 
                p = kbuf = memdup_user_nul(buffer, left);
                if (IS_ERR(kbuf))
                        return PTR_ERR(kbuf);
 
-               tmp_bitmap = kcalloc(BITS_TO_LONGS(bitmap_len),
-                                    sizeof(unsigned long),
-                                    GFP_KERNEL);
+               tmp_bitmap = bitmap_zalloc(bitmap_len, GFP_KERNEL);
                if (!tmp_bitmap) {
                        kfree(kbuf);
                        return -ENOMEM;
@@ -3177,9 +3193,22 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
                while (!err && left) {
                        unsigned long val_a, val_b;
                        bool neg;
+                       size_t saved_left;
 
+                       /* In case we stop parsing mid-number, we can reset */
+                       saved_left = left;
                        err = proc_get_long(&p, &left, &val_a, &neg, tr_a,
                                             sizeof(tr_a), &c);
+                       /*
+                        * If we consumed the entirety of a truncated buffer or
+                        * only one char is left (may be a "-"), then stop here,
+                        * reset, & come back for more.
+                        */
+                       if ((left <= 1) && skipped) {
+                               left = saved_left;
+                               break;
+                       }
+
                        if (err)
                                break;
                        if (val_a >= bitmap_len || neg) {
@@ -3197,6 +3226,15 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
                                err = proc_get_long(&p, &left, &val_b,
                                                     &neg, tr_b, sizeof(tr_b),
                                                     &c);
+                               /*
+                                * If we consumed all of a truncated buffer or
+                                * then stop here, reset, & come back for more.
+                                */
+                               if (!left && skipped) {
+                                       left = saved_left;
+                                       break;
+                               }
+
                                if (err)
                                        break;
                                if (val_b >= bitmap_len || neg ||
@@ -3215,6 +3253,7 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
                        proc_skip_char(&p, &left, '\n');
                }
                kfree(kbuf);
+               left += skipped;
        } else {
                unsigned long bit_a, bit_b = 0;
 
@@ -3259,7 +3298,7 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
                *ppos += *lenp;
        }
 
-       kfree(tmp_bitmap);
+       bitmap_free(tmp_bitmap);
        return err;
 }