]> err.no Git - linux-2.6/blobdiff - kernel/sysctl.c
ACPI: delete extra #defines in /drivers/acpi/ drivers
[linux-2.6] / kernel / sysctl.c
index 10474a63a111ca17c630cd729ee4134fe0ebd968..e0ac6cd79fcf6955c6105815b4c8ab4d9d53e97f 100644 (file)
@@ -65,7 +65,6 @@ extern int sysctl_overcommit_memory;
 extern int sysctl_overcommit_ratio;
 extern int sysctl_panic_on_oom;
 extern int max_threads;
-extern int sysrq_enabled;
 extern int core_uses_pid;
 extern int suid_dumpable;
 extern char core_pattern[];
@@ -133,7 +132,7 @@ extern int max_lock_depth;
 
 #ifdef CONFIG_SYSCTL_SYSCALL
 static int parse_table(int __user *, int, void __user *, size_t __user *,
-               void __user *, size_t, ctl_table *, void **);
+               void __user *, size_t, ctl_table *);
 #endif
 
 static int proc_do_uts_string(ctl_table *table, int write, struct file *filp,
@@ -141,11 +140,19 @@ static int proc_do_uts_string(ctl_table *table, int write, struct file *filp,
 
 static int sysctl_uts_string(ctl_table *table, int __user *name, int nlen,
                  void __user *oldval, size_t __user *oldlenp,
-                 void __user *newval, size_t newlen, void **context);
+                 void __user *newval, size_t newlen);
+
+#ifdef CONFIG_SYSVIPC
+static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
+                 void __user *oldval, size_t __user *oldlenp,
+                 void __user *newval, size_t newlen);
+#endif
 
 #ifdef CONFIG_PROC_SYSCTL
 static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp,
                  void __user *buffer, size_t *lenp, loff_t *ppos);
+static int proc_dointvec_taint(ctl_table *table, int write, struct file *filp,
+                              void __user *buffer, size_t *lenp, loff_t *ppos);
 #endif
 
 static ctl_table root_table[];
@@ -169,6 +176,7 @@ extern ctl_table inotify_table[];
 int sysctl_legacy_va_layout;
 #endif
 
+
 static void *get_uts(ctl_table *table, int write)
 {
        char *which = table->data;
@@ -339,14 +347,16 @@ static ctl_table kern_table[] = {
                .proc_handler   = &proc_dostring,
                .strategy       = &sysctl_string,
        },
+#ifdef CONFIG_PROC_SYSCTL
        {
                .ctl_name       = KERN_TAINTED,
                .procname       = "tainted",
                .data           = &tainted,
                .maxlen         = sizeof(int),
-               .mode           = 0444,
-               .proc_handler   = &proc_dointvec,
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_taint,
        },
+#endif
        {
                .ctl_name       = KERN_CAP_BSET,
                .procname       = "cap-bound",
@@ -476,6 +486,7 @@ static ctl_table kern_table[] = {
                .maxlen         = sizeof (init_ipc_ns.shm_ctlmax),
                .mode           = 0644,
                .proc_handler   = &proc_ipc_doulongvec_minmax,
+               .strategy       = sysctl_ipc_data,
        },
        {
                .ctl_name       = KERN_SHMALL,
@@ -484,6 +495,7 @@ static ctl_table kern_table[] = {
                .maxlen         = sizeof (init_ipc_ns.shm_ctlall),
                .mode           = 0644,
                .proc_handler   = &proc_ipc_doulongvec_minmax,
+               .strategy       = sysctl_ipc_data,
        },
        {
                .ctl_name       = KERN_SHMMNI,
@@ -492,6 +504,7 @@ static ctl_table kern_table[] = {
                .maxlen         = sizeof (init_ipc_ns.shm_ctlmni),
                .mode           = 0644,
                .proc_handler   = &proc_ipc_dointvec,
+               .strategy       = sysctl_ipc_data,
        },
        {
                .ctl_name       = KERN_MSGMAX,
@@ -500,6 +513,7 @@ static ctl_table kern_table[] = {
                .maxlen         = sizeof (init_ipc_ns.msg_ctlmax),
                .mode           = 0644,
                .proc_handler   = &proc_ipc_dointvec,
+               .strategy       = sysctl_ipc_data,
        },
        {
                .ctl_name       = KERN_MSGMNI,
@@ -508,6 +522,7 @@ static ctl_table kern_table[] = {
                .maxlen         = sizeof (init_ipc_ns.msg_ctlmni),
                .mode           = 0644,
                .proc_handler   = &proc_ipc_dointvec,
+               .strategy       = sysctl_ipc_data,
        },
        {
                .ctl_name       = KERN_MSGMNB,
@@ -516,6 +531,7 @@ static ctl_table kern_table[] = {
                .maxlen         = sizeof (init_ipc_ns.msg_ctlmnb),
                .mode           = 0644,
                .proc_handler   = &proc_ipc_dointvec,
+               .strategy       = sysctl_ipc_data,
        },
        {
                .ctl_name       = KERN_SEM,
@@ -524,13 +540,14 @@ static ctl_table kern_table[] = {
                .maxlen         = 4*sizeof (int),
                .mode           = 0644,
                .proc_handler   = &proc_ipc_dointvec,
+               .strategy       = sysctl_ipc_data,
        },
 #endif
 #ifdef CONFIG_MAGIC_SYSRQ
        {
                .ctl_name       = KERN_SYSRQ,
                .procname       = "sysrq",
-               .data           = &sysrq_enabled,
+               .data           = &__sysrq_enabled,
                .maxlen         = sizeof (int),
                .mode           = 0644,
                .proc_handler   = &proc_dointvec,
@@ -1230,7 +1247,6 @@ int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *ol
        do {
                struct ctl_table_header *head =
                        list_entry(tmp, struct ctl_table_header, ctl_entry);
-               void *context = NULL;
 
                if (!use_table(head))
                        continue;
@@ -1238,9 +1254,7 @@ int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *ol
                spin_unlock(&sysctl_lock);
 
                error = parse_table(name, nlen, oldval, oldlenp, 
-                                       newval, newlen, head->ctl_table,
-                                       &context);
-               kfree(context);
+                                       newval, newlen, head->ctl_table);
 
                spin_lock(&sysctl_lock);
                unuse_table(head);
@@ -1296,7 +1310,7 @@ static inline int ctl_perm(ctl_table *table, int op)
 static int parse_table(int __user *name, int nlen,
                       void __user *oldval, size_t __user *oldlenp,
                       void __user *newval, size_t newlen,
-                      ctl_table *table, void **context)
+                      ctl_table *table)
 {
        int n;
 repeat:
@@ -1316,7 +1330,7 @@ repeat:
                                        error = table->strategy(
                                                table, name, nlen,
                                                oldval, oldlenp,
-                                               newval, newlen, context);
+                                               newval, newlen);
                                        if (error)
                                                return error;
                                }
@@ -1327,7 +1341,7 @@ repeat:
                        }
                        error = do_sysctl_strategy(table, name, nlen,
                                                   oldval, oldlenp,
-                                                  newval, newlen, context);
+                                                  newval, newlen);
                        return error;
                }
        }
@@ -1338,7 +1352,7 @@ repeat:
 int do_sysctl_strategy (ctl_table *table, 
                        int __user *name, int nlen,
                        void __user *oldval, size_t __user *oldlenp,
-                       void __user *newval, size_t newlen, void **context)
+                       void __user *newval, size_t newlen)
 {
        int op = 0, rc;
        size_t len;
@@ -1352,7 +1366,7 @@ int do_sysctl_strategy (ctl_table *table,
 
        if (table->strategy) {
                rc = table->strategy(table, name, nlen, oldval, oldlenp,
-                                    newval, newlen, context);
+                                    newval, newlen);
                if (rc < 0)
                        return rc;
                if (rc > 0)
@@ -1672,13 +1686,12 @@ static int _proc_do_string(void* data, int maxlen, int write,
        size_t len;
        char __user *p;
        char c;
-       
-       if (!data || !maxlen || !*lenp ||
-           (*ppos && !write)) {
+
+       if (!data || !maxlen || !*lenp) {
                *lenp = 0;
                return 0;
        }
-       
+
        if (write) {
                len = 0;
                p = buffer;
@@ -1699,6 +1712,15 @@ static int _proc_do_string(void* data, int maxlen, int write,
                len = strlen(data);
                if (len > maxlen)
                        len = maxlen;
+
+               if (*ppos > len) {
+                       *lenp = 0;
+                       return 0;
+               }
+
+               data += *ppos;
+               len  -= *ppos;
+
                if (len > *lenp)
                        len = *lenp;
                if (len)
@@ -1919,8 +1941,6 @@ int proc_dointvec(ctl_table *table, int write, struct file *filp,
 #define OP_SET 0
 #define OP_AND 1
 #define OP_OR  2
-#define OP_MAX 3
-#define OP_MIN 4
 
 static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
                                      int *valp,
@@ -1933,12 +1953,6 @@ static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
                case OP_SET:    *valp = val; break;
                case OP_AND:    *valp &= val; break;
                case OP_OR:     *valp |= val; break;
-               case OP_MAX:    if(*valp < val)
-                                       *valp = val;
-                               break;
-               case OP_MIN:    if(*valp > val)
-                               *valp = val;
-                               break;
                }
        } else {
                int val = *valp;
@@ -1962,7 +1976,7 @@ int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
 {
        int op;
 
-       if (!capable(CAP_SYS_MODULE)) {
+       if (write && !capable(CAP_SYS_MODULE)) {
                return -EPERM;
        }
 
@@ -1971,6 +1985,22 @@ int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
                                do_proc_dointvec_bset_conv,&op);
 }
 
+/*
+ *     Taint values can only be increased
+ */
+static int proc_dointvec_taint(ctl_table *table, int write, struct file *filp,
+                              void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       int op;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       op = OP_OR;
+       return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
+                               do_proc_dointvec_bset_conv,&op);
+}
+
 struct do_proc_dointvec_minmax_conv_param {
        int *min;
        int *max;
@@ -2395,6 +2425,17 @@ static int proc_do_ipc_string(ctl_table *table, int write, struct file *filp,
 {
        return -ENOSYS;
 }
+static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp,
+               void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       return -ENOSYS;
+}
+static int proc_ipc_doulongvec_minmax(ctl_table *table, int write,
+               struct file *filp, void __user *buffer,
+               size_t *lenp, loff_t *ppos)
+{
+       return -ENOSYS;
+}
 #endif
 
 int proc_dointvec(ctl_table *table, int write, struct file *filp,
@@ -2459,7 +2500,7 @@ int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
 /* The generic string strategy routine: */
 int sysctl_string(ctl_table *table, int __user *name, int nlen,
                  void __user *oldval, size_t __user *oldlenp,
-                 void __user *newval, size_t newlen, void **context)
+                 void __user *newval, size_t newlen)
 {
        if (!table->data || !table->maxlen) 
                return -ENOTDIR;
@@ -2505,7 +2546,7 @@ int sysctl_string(ctl_table *table, int __user *name, int nlen,
  */
 int sysctl_intvec(ctl_table *table, int __user *name, int nlen,
                void __user *oldval, size_t __user *oldlenp,
-               void __user *newval, size_t newlen, void **context)
+               void __user *newval, size_t newlen)
 {
 
        if (newval && newlen) {
@@ -2541,19 +2582,25 @@ int sysctl_intvec(ctl_table *table, int __user *name, int nlen,
 /* Strategy function to convert jiffies to seconds */ 
 int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
                void __user *oldval, size_t __user *oldlenp,
-               void __user *newval, size_t newlen, void **context)
+               void __user *newval, size_t newlen)
 {
-       if (oldval) {
+       if (oldval && oldlenp) {
                size_t olen;
-               if (oldlenp) { 
-                       if (get_user(olen, oldlenp))
+
+               if (get_user(olen, oldlenp))
+                       return -EFAULT;
+               if (olen) {
+                       int val;
+
+                       if (olen < sizeof(int))
+                               return -EINVAL;
+
+                       val = *(int *)(table->data) / HZ;
+                       if (put_user(val, (int __user *)oldval))
+                               return -EFAULT;
+                       if (put_user(sizeof(int), oldlenp))
                                return -EFAULT;
-                       if (olen!=sizeof(int))
-                               return -EINVAL; 
                }
-               if (put_user(*(int *)(table->data)/HZ, (int __user *)oldval) ||
-                   (oldlenp && put_user(sizeof(int),oldlenp)))
-                       return -EFAULT;
        }
        if (newval && newlen) { 
                int new;
@@ -2569,19 +2616,25 @@ int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
 /* Strategy function to convert jiffies to seconds */ 
 int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
                void __user *oldval, size_t __user *oldlenp,
-               void __user *newval, size_t newlen, void **context)
+               void __user *newval, size_t newlen)
 {
-       if (oldval) {
+       if (oldval && oldlenp) {
                size_t olen;
-               if (oldlenp) { 
-                       if (get_user(olen, oldlenp))
+
+               if (get_user(olen, oldlenp))
+                       return -EFAULT;
+               if (olen) {
+                       int val;
+
+                       if (olen < sizeof(int))
+                               return -EINVAL;
+
+                       val = jiffies_to_msecs(*(int *)(table->data));
+                       if (put_user(val, (int __user *)oldval))
+                               return -EFAULT;
+                       if (put_user(sizeof(int), oldlenp))
                                return -EFAULT;
-                       if (olen!=sizeof(int))
-                               return -EINVAL; 
                }
-               if (put_user(jiffies_to_msecs(*(int *)(table->data)), (int __user *)oldval) ||
-                   (oldlenp && put_user(sizeof(int),oldlenp)))
-                       return -EFAULT;
        }
        if (newval && newlen) { 
                int new;
@@ -2598,7 +2651,7 @@ int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
 /* The generic string strategy routine: */
 static int sysctl_uts_string(ctl_table *table, int __user *name, int nlen,
                  void __user *oldval, size_t __user *oldlenp,
-                 void __user *newval, size_t newlen, void **context)
+                 void __user *newval, size_t newlen)
 {
        struct ctl_table uts_table;
        int r, write;
@@ -2606,11 +2659,52 @@ static int sysctl_uts_string(ctl_table *table, int __user *name, int nlen,
        memcpy(&uts_table, table, sizeof(uts_table));
        uts_table.data = get_uts(table, write);
        r = sysctl_string(&uts_table, name, nlen,
-               oldval, oldlenp, newval, newlen, context);
+               oldval, oldlenp, newval, newlen);
        put_uts(table, write, uts_table.data);
        return r;
 }
 
+#ifdef CONFIG_SYSVIPC
+/* The generic sysctl ipc data routine. */
+static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
+               void __user *oldval, size_t __user *oldlenp,
+               void __user *newval, size_t newlen)
+{
+       size_t len;
+       void *data;
+
+       /* Get out of I don't have a variable */
+       if (!table->data || !table->maxlen)
+               return -ENOTDIR;
+
+       data = get_ipc(table, 1);
+       if (!data)
+               return -ENOTDIR;
+
+       if (oldval && oldlenp) {
+               if (get_user(len, oldlenp))
+                       return -EFAULT;
+               if (len) {
+                       if (len > table->maxlen)
+                               len = table->maxlen;
+                       if (copy_to_user(oldval, data, len))
+                               return -EFAULT;
+                       if (put_user(len, oldlenp))
+                               return -EFAULT;
+               }
+       }
+
+       if (newval && newlen) {
+               if (newlen > table->maxlen)
+                       newlen = table->maxlen;
+
+               if (copy_from_user(data, newval, newlen))
+                       return -EFAULT;
+       }
+       return 1;
+}
+#endif
+
 #else /* CONFIG_SYSCTL_SYSCALL */
 
 
@@ -2649,38 +2743,46 @@ out:
 
 int sysctl_string(ctl_table *table, int __user *name, int nlen,
                  void __user *oldval, size_t __user *oldlenp,
-                 void __user *newval, size_t newlen, void **context)
+                 void __user *newval, size_t newlen)
 {
        return -ENOSYS;
 }
 
 int sysctl_intvec(ctl_table *table, int __user *name, int nlen,
                void __user *oldval, size_t __user *oldlenp,
-               void __user *newval, size_t newlen, void **context)
+               void __user *newval, size_t newlen)
 {
        return -ENOSYS;
 }
 
 int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
                void __user *oldval, size_t __user *oldlenp,
-               void __user *newval, size_t newlen, void **context)
+               void __user *newval, size_t newlen)
 {
        return -ENOSYS;
 }
 
 int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
                void __user *oldval, size_t __user *oldlenp,
-               void __user *newval, size_t newlen, void **context)
+               void __user *newval, size_t newlen)
 {
        return -ENOSYS;
 }
 
 static int sysctl_uts_string(ctl_table *table, int __user *name, int nlen,
                  void __user *oldval, size_t __user *oldlenp,
-                 void __user *newval, size_t newlen, void **context)
+                 void __user *newval, size_t newlen)
 {
        return -ENOSYS;
 }
+#ifdef CONFIG_SYSVIPC
+static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
+               void __user *oldval, size_t __user *oldlenp,
+               void __user *newval, size_t newlen)
+{
+       return -ENOSYS;
+}
+#endif
 #endif /* CONFIG_SYSCTL_SYSCALL */
 
 /*