[PATCH] sysctl: fix sys_sysctl interface of ipc sysctls
authorEric W. Biederman <ebiederm@xmission.com>
Fri, 8 Dec 2006 10:39:57 +0000 (02:39 -0800)
committerLinus Torvalds <torvalds@woody.osdl.org>
Fri, 8 Dec 2006 16:29:03 +0000 (08:29 -0800)
Currently there is a regression and the ipc sysctls don't show up in the
binary sysctl namespace.

This patch adds sysctl_ipc_data to read data/write from the appropriate
namespace and deliver it in the expected manner.

[akpm@osdl.org: warning fix]
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
kernel/sysctl.c

index 10474a63a111ca17c630cd729ee4134fe0ebd968..025fcb3c66f87ce7b81c6dc6b3271dc28cbd5085 100644 (file)
@@ -143,6 +143,12 @@ 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);
 
+#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, void **context);
+#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);
@@ -476,6 +482,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 +491,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 +500,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 +509,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 +518,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 +527,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,6 +536,7 @@ 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
@@ -2611,6 +2624,47 @@ static int sysctl_uts_string(ctl_table *table, int __user *name, int nlen,
        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, void **context)
+{
+       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 */
 
 
@@ -2681,6 +2735,12 @@ static int sysctl_uts_string(ctl_table *table, int __user *name, int nlen,
 {
        return -ENOSYS;
 }
+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, void **context)
+{
+       return -ENOSYS;
+}
 #endif /* CONFIG_SYSCTL_SYSCALL */
 
 /*