userns: Convert audit to work with user namespaces enabled
[firefly-linux-kernel-4.4.55.git] / kernel / sysctl.c
index d48ff4fd44c328eb3458390b79facac08734b7b9..87174ef59161eb32ce298f5ef9c2b0e9feb1b3f1 100644 (file)
 #include <linux/swap.h>
 #include <linux/slab.h>
 #include <linux/sysctl.h>
+#include <linux/bitmap.h>
 #include <linux/signal.h>
 #include <linux/printk.h>
 #include <linux/proc_fs.h>
 #include <linux/security.h>
 #include <linux/ctype.h>
 #include <linux/kmemcheck.h>
+#include <linux/kmemleak.h>
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -68,6 +70,9 @@
 #include <asm/stacktrace.h>
 #include <asm/io.h>
 #endif
+#ifdef CONFIG_SPARC
+#include <asm/setup.h>
+#endif
 #ifdef CONFIG_BSD_PROCESS_ACCT
 #include <linux/acct.h>
 #endif
@@ -142,7 +147,6 @@ static const int cap_last_cap = CAP_LAST_CAP;
 #include <linux/inotify.h>
 #endif
 #ifdef CONFIG_SPARC
-#include <asm/system.h>
 #endif
 
 #ifdef CONFIG_SPARC64
@@ -167,10 +171,15 @@ static int proc_taint(struct ctl_table *table, int write,
 #endif
 
 #ifdef CONFIG_PRINTK
-static int proc_dmesg_restrict(struct ctl_table *table, int write,
+static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
                                void __user *buffer, size_t *lenp, loff_t *ppos);
 #endif
 
+static int proc_dointvec_minmax_coredump(struct ctl_table *table, int write,
+               void __user *buffer, size_t *lenp, loff_t *ppos);
+static int proc_dostring_coredump(struct ctl_table *table, int write,
+               void __user *buffer, size_t *lenp, loff_t *ppos);
+
 #ifdef CONFIG_MAGIC_SYSRQ
 /* Note: sysrq code uses it's own private copy */
 static int __sysrq_enabled = SYSRQ_DEFAULT_ENABLE;
@@ -407,7 +416,7 @@ static struct ctl_table kern_table[] = {
                .data           = core_pattern,
                .maxlen         = CORENAME_MAX_SIZE,
                .mode           = 0644,
-               .proc_handler   = proc_dostring,
+               .proc_handler   = proc_dostring_coredump,
        },
        {
                .procname       = "core_pipe_limit",
@@ -700,7 +709,7 @@ static struct ctl_table kern_table[] = {
                .data           = &dmesg_restrict,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec_minmax,
+               .proc_handler   = proc_dointvec_minmax_sysadmin,
                .extra1         = &zero,
                .extra2         = &one,
        },
@@ -709,7 +718,7 @@ static struct ctl_table kern_table[] = {
                .data           = &kptr_restrict,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = proc_dmesg_restrict,
+               .proc_handler   = proc_dointvec_minmax_sysadmin,
                .extra1         = &zero,
                .extra2         = &two,
        },
@@ -1092,11 +1101,9 @@ static struct ctl_table vm_table[] = {
                .extra1         = &zero,
        },
        {
-               .procname       = "nr_pdflush_threads",
-               .data           = &nr_pdflush_threads,
-               .maxlen         = sizeof nr_pdflush_threads,
-               .mode           = 0444 /* read-only*/,
-               .proc_handler   = proc_dointvec,
+               .procname       = "nr_pdflush_threads",
+               .mode           = 0444 /* read-only */,
+               .proc_handler   = pdflush_proc_obsolete,
        },
        {
                .procname       = "swappiness",
@@ -1490,12 +1497,30 @@ static struct ctl_table fs_table[] = {
        },
 #endif
 #endif
+       {
+               .procname       = "protected_symlinks",
+               .data           = &sysctl_protected_symlinks,
+               .maxlen         = sizeof(int),
+               .mode           = 0600,
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &zero,
+               .extra2         = &one,
+       },
+       {
+               .procname       = "protected_hardlinks",
+               .data           = &sysctl_protected_hardlinks,
+               .maxlen         = sizeof(int),
+               .mode           = 0600,
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &zero,
+               .extra2         = &one,
+       },
        {
                .procname       = "suid_dumpable",
                .data           = &suid_dumpable,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec_minmax,
+               .proc_handler   = proc_dointvec_minmax_coredump,
                .extra1         = &zero,
                .extra2         = &two,
        },
@@ -1548,7 +1573,10 @@ static struct ctl_table dev_table[] = {
 
 int __init sysctl_init(void)
 {
-       register_sysctl_table(sysctl_base_table);
+       struct ctl_table_header *hdr;
+
+       hdr = register_sysctl_table(sysctl_base_table);
+       kmemleak_not_leak(hdr);
        return 0;
 }
 
@@ -1940,7 +1968,7 @@ static int proc_taint(struct ctl_table *table, int write,
 }
 
 #ifdef CONFIG_PRINTK
-static int proc_dmesg_restrict(struct ctl_table *table, int write,
+static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
                                void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        if (write && !capable(CAP_SYS_ADMIN))
@@ -2006,6 +2034,34 @@ int proc_dointvec_minmax(struct ctl_table *table, int write,
                                do_proc_dointvec_minmax_conv, &param);
 }
 
+static void validate_coredump_safety(void)
+{
+       if (suid_dumpable == SUID_DUMPABLE_SAFE &&
+           core_pattern[0] != '/' && core_pattern[0] != '|') {
+               printk(KERN_WARNING "Unsafe core_pattern used with "\
+                       "suid_dumpable=2. Pipe handler or fully qualified "\
+                       "core dump path required.\n");
+       }
+}
+
+static int proc_dointvec_minmax_coredump(struct ctl_table *table, int write,
+               void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       int error = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+       if (!error)
+               validate_coredump_safety();
+       return error;
+}
+
+static int proc_dostring_coredump(struct ctl_table *table, int write,
+                 void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       int error = proc_dostring(table, write, buffer, lenp, ppos);
+       if (!error)
+               validate_coredump_safety();
+       return error;
+}
+
 static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int write,
                                     void __user *buffer,
                                     size_t *lenp, loff_t *ppos,
@@ -2393,9 +2449,7 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
                                }
                        }
 
-                       while (val_a <= val_b)
-                               set_bit(val_a++, tmp_bitmap);
-
+                       bitmap_set(tmp_bitmap, val_a, val_b - val_a + 1);
                        first = 0;
                        proc_skip_char(&kbuf, &left, '\n');
                }
@@ -2438,8 +2492,7 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
                        if (*ppos)
                                bitmap_or(bitmap, bitmap, tmp_bitmap, bitmap_len);
                        else
-                               memcpy(bitmap, tmp_bitmap,
-                                       BITS_TO_LONGS(bitmap_len) * sizeof(unsigned long));
+                               bitmap_copy(bitmap, tmp_bitmap, bitmap_len);
                }
                kfree(tmp_bitmap);
                *lenp -= left;