Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
[powerpc.git] / kernel / sysctl.c
index 0278f52..067554b 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/slab.h>
 #include <linux/sysctl.h>
 #include <linux/proc_fs.h>
-#include <linux/capability.h>
+#include <linux/security.h>
 #include <linux/ctype.h>
 #include <linux/utsname.h>
 #include <linux/smp_lock.h>
@@ -55,6 +55,8 @@
 #include <asm/stacktrace.h>
 #endif
 
+static int deprecated_sysctl_warning(struct __sysctl_args *args);
+
 #if defined(CONFIG_SYSCTL)
 
 /* External variables not in a header file. */
@@ -369,6 +371,7 @@ static struct ctl_table kern_table[] = {
                .proc_handler   = &proc_dointvec_taint,
        },
 #endif
+#ifdef CONFIG_SECURITY_CAPABILITIES
        {
                .procname       = "cap-bound",
                .data           = &cap_bset,
@@ -376,6 +379,7 @@ static struct ctl_table kern_table[] = {
                .mode           = 0600,
                .proc_handler   = &proc_dointvec_bset,
        },
+#endif /* def CONFIG_SECURITY_CAPABILITIES */
 #ifdef CONFIG_BLK_DEV_INITRD
        {
                .ctl_name       = KERN_REALROOTDEV,
@@ -509,7 +513,6 @@ static struct ctl_table kern_table[] = {
 #endif
 #ifdef CONFIG_PROC_SYSCTL
        {
-               .ctl_name       = KERN_CADPID,
                .procname       = "cad_pid",
                .data           = NULL,
                .maxlen         = sizeof (int),
@@ -1348,10 +1351,15 @@ asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
        if (copy_from_user(&tmp, args, sizeof(tmp)))
                return -EFAULT;
 
+       error = deprecated_sysctl_warning(&tmp);
+       if (error)
+               goto out;
+
        lock_kernel();
        error = do_sysctl(tmp.name, tmp.nlen, tmp.oldval, tmp.oldlenp,
                          tmp.newval, tmp.newlen);
        unlock_kernel();
+out:
        return error;
 }
 #endif /* CONFIG_SYSCTL_SYSCALL */
@@ -1462,7 +1470,9 @@ static void sysctl_set_parent(struct ctl_table *parent, struct ctl_table *table)
 
 static __init int sysctl_init(void)
 {
+       int err;
        sysctl_set_parent(NULL, root_table);
+       err = sysctl_check_table(root_table);
        return 0;
 }
 
@@ -1547,6 +1557,10 @@ struct ctl_table_header *register_sysctl_table(struct ctl_table * table)
        tmp->used = 0;
        tmp->unregistering = NULL;
        sysctl_set_parent(NULL, table);
+       if (sysctl_check_table(tmp->ctl_table)) {
+               kfree(tmp);
+               return NULL;
+       }
        spin_lock(&sysctl_lock);
        list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry);
        spin_unlock(&sysctl_lock);
@@ -1860,10 +1874,11 @@ static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
        return 0;
 }
 
+#ifdef CONFIG_SECURITY_CAPABILITIES
 /*
  *     init may raise the set.
  */
+
 int proc_dointvec_bset(struct ctl_table *table, int write, struct file *filp,
                        void __user *buffer, size_t *lenp, loff_t *ppos)
 {
@@ -1877,6 +1892,7 @@ int proc_dointvec_bset(struct ctl_table *table, int write, struct file *filp,
        return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
                                do_proc_dointvec_bset_conv,&op);
 }
+#endif /* def CONFIG_SECURITY_CAPABILITIES */
 
 /*
  *     Taint values can only be increased
@@ -2535,35 +2551,19 @@ int sysctl_ms_jiffies(struct ctl_table *table, int __user *name, int nlen,
 
 asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
 {
-       static int msg_count;
        struct __sysctl_args tmp;
-       int name[CTL_MAXNAME];
-       int i;
+       int error;
 
-       /* Read in the sysctl name for better debug message logging */
        if (copy_from_user(&tmp, args, sizeof(tmp)))
                return -EFAULT;
-       if (tmp.nlen <= 0 || tmp.nlen >= CTL_MAXNAME)
-               return -ENOTDIR;
-       for (i = 0; i < tmp.nlen; i++)
-               if (get_user(name[i], tmp.name + i))
-                       return -EFAULT;
 
-       /* Ignore accesses to kernel.version */
-       if ((tmp.nlen == 2) && (name[0] == CTL_KERN) && (name[1] == KERN_VERSION))
-               goto out;
+       error = deprecated_sysctl_warning(&tmp);
 
-       if (msg_count < 5) {
-               msg_count++;
-               printk(KERN_INFO
-                       "warning: process `%s' used the removed sysctl "
-                       "system call with ", current->comm);
-               for (i = 0; i < tmp.nlen; i++)
-                       printk("%d.", name[i]);
-               printk("\n");
-       }
-out:
-       return -ENOSYS;
+       /* If no error reading the parameters then just -ENOSYS ... */
+       if (!error)
+               error = -ENOSYS;
+
+       return error;
 }
 
 int sysctl_data(struct ctl_table *table, int __user *name, int nlen,
@@ -2603,6 +2603,33 @@ int sysctl_ms_jiffies(struct ctl_table *table, int __user *name, int nlen,
 
 #endif /* CONFIG_SYSCTL_SYSCALL */
 
+static int deprecated_sysctl_warning(struct __sysctl_args *args)
+{
+       static int msg_count;
+       int name[CTL_MAXNAME];
+       int i;
+
+       /* Read in the sysctl name for better debug message logging */
+       for (i = 0; i < args->nlen; i++)
+               if (get_user(name[i], args->name + i))
+                       return -EFAULT;
+
+       /* Ignore accesses to kernel.version */
+       if ((args->nlen == 2) && (name[0] == CTL_KERN) && (name[1] == KERN_VERSION))
+               return 0;
+
+       if (msg_count < 5) {
+               msg_count++;
+               printk(KERN_INFO
+                       "warning: process `%s' used the deprecated sysctl "
+                       "system call with ", current->comm);
+               for (i = 0; i < args->nlen; i++)
+                       printk("%d.", name[i]);
+               printk("\n");
+       }
+       return 0;
+}
+
 /*
  * No sense putting this after each symbol definition, twice,
  * exception granted :-)