kernel/sysctl.c: detect overflows when converting to int
[cascardo/linux.git] / kernel / sysctl.c
index ce410bb..2082b1a 100644 (file)
@@ -19,6 +19,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/aio.h>
 #include <linux/mm.h>
 #include <linux/swap.h>
 #include <linux/slab.h>
 #include <linux/nmi.h>
 #endif
 
-
 #if defined(CONFIG_SYSCTL)
 
 /* External variables not in a header file. */
-extern int max_threads;
 extern int suid_dumpable;
 #ifdef CONFIG_COREDUMP
 extern int core_uses_pid;
@@ -709,10 +708,10 @@ static struct ctl_table kern_table[] = {
 #endif
        {
                .procname       = "threads-max",
-               .data           = &max_threads,
+               .data           = NULL,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec,
+               .proc_handler   = sysctl_max_threads,
        },
        {
                .procname       = "random",
@@ -846,7 +845,7 @@ static struct ctl_table kern_table[] = {
                .data           = &watchdog_user_enabled,
                .maxlen         = sizeof (int),
                .mode           = 0644,
-               .proc_handler   = proc_dowatchdog,
+               .proc_handler   = proc_watchdog,
                .extra1         = &zero,
                .extra2         = &one,
        },
@@ -855,10 +854,32 @@ static struct ctl_table kern_table[] = {
                .data           = &watchdog_thresh,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = proc_dowatchdog,
+               .proc_handler   = proc_watchdog_thresh,
                .extra1         = &zero,
                .extra2         = &sixty,
        },
+       {
+               .procname       = "nmi_watchdog",
+               .data           = &nmi_watchdog_enabled,
+               .maxlen         = sizeof (int),
+               .mode           = 0644,
+               .proc_handler   = proc_nmi_watchdog,
+               .extra1         = &zero,
+#if defined(CONFIG_HAVE_NMI_WATCHDOG) || defined(CONFIG_HARDLOCKUP_DETECTOR)
+               .extra2         = &one,
+#else
+               .extra2         = &zero,
+#endif
+       },
+       {
+               .procname       = "soft_watchdog",
+               .data           = &soft_watchdog_enabled,
+               .maxlen         = sizeof (int),
+               .mode           = 0644,
+               .proc_handler   = proc_soft_watchdog,
+               .extra1         = &zero,
+               .extra2         = &one,
+       },
        {
                .procname       = "softlockup_panic",
                .data           = &softlockup_panic,
@@ -879,15 +900,6 @@ static struct ctl_table kern_table[] = {
                .extra2         = &one,
        },
 #endif /* CONFIG_SMP */
-       {
-               .procname       = "nmi_watchdog",
-               .data           = &watchdog_user_enabled,
-               .maxlen         = sizeof (int),
-               .mode           = 0644,
-               .proc_handler   = proc_dowatchdog,
-               .extra1         = &zero,
-               .extra2         = &one,
-       },
 #endif
 #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86)
        {
@@ -1321,6 +1333,15 @@ static struct ctl_table vm_table[] = {
                .extra1         = &min_extfrag_threshold,
                .extra2         = &max_extfrag_threshold,
        },
+       {
+               .procname       = "compact_unevictable_allowed",
+               .data           = &sysctl_compact_unevictable_allowed,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec,
+               .extra1         = &zero,
+               .extra2         = &one,
+       },
 
 #endif /* CONFIG_COMPACTION */
        {
@@ -1960,7 +1981,15 @@ static int do_proc_dointvec_conv(bool *negp, unsigned long *lvalp,
                                 int write, void *data)
 {
        if (write) {
-               *valp = *negp ? -*lvalp : *lvalp;
+               if (*negp) {
+                       if (*lvalp > (unsigned long) INT_MAX + 1)
+                               return -EINVAL;
+                       *valp = -*lvalp;
+               } else {
+                       if (*lvalp > (unsigned long) INT_MAX)
+                               return -EINVAL;
+                       *valp = *lvalp;
+               }
        } else {
                int val = *valp;
                if (val < 0) {