2009-11-06 00:40:36

by Eric W. Biederman

[permalink] [raw]
Subject: [PATCH 0/11] generic compat_sys_sysctl


I am in the process of cleaning up, and converting the binary sysctl
sysctl call into a wrapper on top of the text based proc/sys.

A first step in that process is to introduce a generic
compat_sys_sysctl to reduce the number of places I have to touch.
The following patcheset is the start of my series for handling that.

The only architecture specific changes should be replace the
current architecture name for it's 32bit compat syscall with
compat_sys_sysctl, and deleting the architectures private
32bit compat syscall. The only requirement is that CONFIG_COMPAT
be set when you need compat_sys_sysctl.

These patches should just work, but an eyeball from someone who is
familiar with the architecture specific details would be appreciated.
I have only tested the 32bit compat code on x86_64.

Eric


2009-11-06 00:42:04

by Eric W. Biederman

[permalink] [raw]
Subject: [PATCH 01/11] sysctl: Separate the binary sysctl logic into it's own file.

From: Eric W. Biederman <[email protected]>

In preparation for more invasive cleanups separate the core
binary sysctl logic into it's own file.

Signed-off-by: Eric W. Biederman <[email protected]>
---
kernel/Makefile | 2 +-
kernel/sysctl.c | 164 ------------------------------------------
kernel/sysctl_binary.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 185 insertions(+), 165 deletions(-)
create mode 100644 kernel/sysctl_binary.c

diff --git a/kernel/Makefile b/kernel/Makefile
index b8d4cd8..986a5c1 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -4,7 +4,7 @@

obj-y = sched.o fork.o exec_domain.o panic.o printk.o \
cpu.o exit.o itimer.o time.o softirq.o resource.o \
- sysctl.o capability.o ptrace.o timer.o user.o \
+ sysctl.o sysctl_binary.o capability.o ptrace.o timer.o user.o \
signal.o sys.o kmod.o workqueue.o pid.o \
rcupdate.o extable.o params.o posix-timers.o \
kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 0d949c5..34c8dbc 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -60,7 +60,6 @@
#include <asm/io.h>
#endif

-static int deprecated_sysctl_warning(struct __sysctl_args *args);

#if defined(CONFIG_SYSCTL)

@@ -1766,122 +1765,6 @@ void register_sysctl_root(struct ctl_table_root *root)
spin_unlock(&sysctl_lock);
}

-#ifdef CONFIG_SYSCTL_SYSCALL
-/* Perform the actual read/write of a sysctl table entry. */
-static int do_sysctl_strategy(struct ctl_table_root *root,
- struct ctl_table *table,
- void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen)
-{
- int op = 0, rc;
-
- if (oldval)
- op |= MAY_READ;
- if (newval)
- op |= MAY_WRITE;
- if (sysctl_perm(root, table, op))
- return -EPERM;
-
- if (table->strategy) {
- rc = table->strategy(table, oldval, oldlenp, newval, newlen);
- if (rc < 0)
- return rc;
- if (rc > 0)
- return 0;
- }
-
- /* If there is no strategy routine, or if the strategy returns
- * zero, proceed with automatic r/w */
- if (table->data && table->maxlen) {
- rc = sysctl_data(table, oldval, oldlenp, newval, newlen);
- if (rc < 0)
- return rc;
- }
- return 0;
-}
-
-static int parse_table(int __user *name, int nlen,
- void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen,
- struct ctl_table_root *root,
- struct ctl_table *table)
-{
- int n;
-repeat:
- if (!nlen)
- return -ENOTDIR;
- if (get_user(n, name))
- return -EFAULT;
- for ( ; table->ctl_name || table->procname; table++) {
- if (!table->ctl_name)
- continue;
- if (n == table->ctl_name) {
- int error;
- if (table->child) {
- if (sysctl_perm(root, table, MAY_EXEC))
- return -EPERM;
- name++;
- nlen--;
- table = table->child;
- goto repeat;
- }
- error = do_sysctl_strategy(root, table,
- oldval, oldlenp,
- newval, newlen);
- return error;
- }
- }
- return -ENOTDIR;
-}
-
-int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen)
-{
- struct ctl_table_header *head;
- int error = -ENOTDIR;
-
- if (nlen <= 0 || nlen >= CTL_MAXNAME)
- return -ENOTDIR;
- if (oldval) {
- int old_len;
- if (!oldlenp || get_user(old_len, oldlenp))
- return -EFAULT;
- }
-
- for (head = sysctl_head_next(NULL); head;
- head = sysctl_head_next(head)) {
- error = parse_table(name, nlen, oldval, oldlenp,
- newval, newlen,
- head->root, head->ctl_table);
- if (error != -ENOTDIR) {
- sysctl_head_finish(head);
- break;
- }
- }
- return error;
-}
-
-SYSCALL_DEFINE1(sysctl, struct __sysctl_args __user *, args)
-{
- struct __sysctl_args tmp;
- int error;
-
- 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 */
-
/*
* sysctl_perm does NOT grant the superuser all rights automatically, because
* some sysctl variables are readonly even to root.
@@ -3148,23 +3031,6 @@ int sysctl_ms_jiffies(struct ctl_table *table,
#else /* CONFIG_SYSCTL_SYSCALL */


-SYSCALL_DEFINE1(sysctl, struct __sysctl_args __user *, args)
-{
- struct __sysctl_args tmp;
- int error;
-
- if (copy_from_user(&tmp, args, sizeof(tmp)))
- return -EFAULT;
-
- error = deprecated_sysctl_warning(&tmp);
-
- /* If no error reading the parameters then just -ENOSYS ... */
- if (!error)
- error = -ENOSYS;
-
- return error;
-}
-
int sysctl_data(struct ctl_table *table,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen)
@@ -3202,36 +3068,6 @@ int sysctl_ms_jiffies(struct ctl_table *table,

#endif /* CONFIG_SYSCTL_SYSCALL */

-static int deprecated_sysctl_warning(struct __sysctl_args *args)
-{
- static int msg_count;
- int name[CTL_MAXNAME];
- int i;
-
- /* Check args->nlen. */
- if (args->nlen < 0 || args->nlen > CTL_MAXNAME)
- return -ENOTDIR;
-
- /* 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,
diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c
new file mode 100644
index 0000000..2431653
--- /dev/null
+++ b/kernel/sysctl_binary.c
@@ -0,0 +1,184 @@
+#include <linux/stat.h>
+#include <linux/sysctl.h>
+#include "../fs/xfs/linux-2.6/xfs_sysctl.h"
+#include <linux/sunrpc/debug.h>
+#include <linux/string.h>
+#include <net/ip_vs.h>
+#include <linux/syscalls.h>
+#include <linux/namei.h>
+#include <linux/mount.h>
+#include <linux/fs.h>
+#include <linux/nsproxy.h>
+#include <linux/pid_namespace.h>
+#include <linux/file.h>
+#include <linux/ctype.h>
+
+static int deprecated_sysctl_warning(struct __sysctl_args *args);
+
+#ifdef CONFIG_SYSCTL_SYSCALL
+
+/* Perform the actual read/write of a sysctl table entry. */
+static int do_sysctl_strategy(struct ctl_table_root *root,
+ struct ctl_table *table,
+ void __user *oldval, size_t __user *oldlenp,
+ void __user *newval, size_t newlen)
+{
+ int op = 0, rc;
+
+ if (oldval)
+ op |= MAY_READ;
+ if (newval)
+ op |= MAY_WRITE;
+ if (sysctl_perm(root, table, op))
+ return -EPERM;
+
+ if (table->strategy) {
+ rc = table->strategy(table, oldval, oldlenp, newval, newlen);
+ if (rc < 0)
+ return rc;
+ if (rc > 0)
+ return 0;
+ }
+
+ /* If there is no strategy routine, or if the strategy returns
+ * zero, proceed with automatic r/w */
+ if (table->data && table->maxlen) {
+ rc = sysctl_data(table, oldval, oldlenp, newval, newlen);
+ if (rc < 0)
+ return rc;
+ }
+ return 0;
+}
+
+static int parse_table(int __user *name, int nlen,
+ void __user *oldval, size_t __user *oldlenp,
+ void __user *newval, size_t newlen,
+ struct ctl_table_root *root,
+ struct ctl_table *table)
+{
+ int n;
+repeat:
+ if (!nlen)
+ return -ENOTDIR;
+ if (get_user(n, name))
+ return -EFAULT;
+ for ( ; table->ctl_name || table->procname; table++) {
+ if (!table->ctl_name)
+ continue;
+ if (n == table->ctl_name) {
+ int error;
+ if (table->child) {
+ if (sysctl_perm(root, table, MAY_EXEC))
+ return -EPERM;
+ name++;
+ nlen--;
+ table = table->child;
+ goto repeat;
+ }
+ error = do_sysctl_strategy(root, table,
+ oldval, oldlenp,
+ newval, newlen);
+ return error;
+ }
+ }
+ return -ENOTDIR;
+}
+
+int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp,
+ void __user *newval, size_t newlen)
+{
+ struct ctl_table_header *head;
+ int error = -ENOTDIR;
+
+ if (nlen <= 0 || nlen >= CTL_MAXNAME)
+ return -ENOTDIR;
+ if (oldval) {
+ int old_len;
+ if (!oldlenp || get_user(old_len, oldlenp))
+ return -EFAULT;
+ }
+
+ for (head = sysctl_head_next(NULL); head;
+ head = sysctl_head_next(head)) {
+ error = parse_table(name, nlen, oldval, oldlenp,
+ newval, newlen,
+ head->root, head->ctl_table);
+ if (error != -ENOTDIR) {
+ sysctl_head_finish(head);
+ break;
+ }
+ }
+ return error;
+}
+
+SYSCALL_DEFINE1(sysctl, struct __sysctl_args __user *, args)
+{
+ struct __sysctl_args tmp;
+ int error;
+
+ 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;
+}
+
+#else /* CONFIG_SYSCTL_SYSCALL */
+
+SYSCALL_DEFINE1(sysctl, struct __sysctl_args __user *, args)
+{
+ struct __sysctl_args tmp;
+ int error;
+
+ if (copy_from_user(&tmp, args, sizeof(tmp)))
+ return -EFAULT;
+
+ error = deprecated_sysctl_warning(&tmp);
+
+ /* If no error reading the parameters then just -ENOSYS ... */
+ if (!error)
+ error = -ENOSYS;
+
+ return error;
+}
+
+#endif /* CONFIG_SYSCTL_SYSCALL */
+
+static int deprecated_sysctl_warning(struct __sysctl_args *args)
+{
+ static int msg_count;
+ int name[CTL_MAXNAME];
+ int i;
+
+ /* Check args->nlen. */
+ if (args->nlen < 0 || args->nlen > CTL_MAXNAME)
+ return -ENOTDIR;
+
+ /* 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;
+}
--
1.6.5.2.143.g8cc62

2009-11-06 00:42:14

by Eric W. Biederman

[permalink] [raw]
Subject: [PATCH 02/11] sysctl: Refactor the binary sysctl handling to remove duplicate code

From: Eric W. Biederman <[email protected]>

Read in the binary sysctl path once, instead of reread it
from user space each time the code needs to access a path
element.

The deprecated sysctl warning is moved to do_sysctl so
that the compat_sysctl entries syscalls will also warn.

The return of -ENOSYS when !CONFIG_SYSCTL_SYSCALL is moved
to binary_sysctl. Always leaving a do_sysctl available
that handles !CONFIG_SYSCTL_SYSCALL and printing the
deprecated sysctl warning allows for a single defitition
of the sysctl syscall.

Signed-off-by: Eric W. Biederman <[email protected]>
---
kernel/sysctl_binary.c | 123 ++++++++++++++++++++++-------------------------
1 files changed, 58 insertions(+), 65 deletions(-)

diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c
index 2431653..c5cc393 100644
--- a/kernel/sysctl_binary.c
+++ b/kernel/sysctl_binary.c
@@ -13,8 +13,6 @@
#include <linux/file.h>
#include <linux/ctype.h>

-static int deprecated_sysctl_warning(struct __sysctl_args *args);
-
#ifdef CONFIG_SYSCTL_SYSCALL

/* Perform the actual read/write of a sysctl table entry. */
@@ -50,7 +48,7 @@ static int do_sysctl_strategy(struct ctl_table_root *root,
return 0;
}

-static int parse_table(int __user *name, int nlen,
+static int parse_table(const int *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen,
struct ctl_table_root *root,
@@ -60,8 +58,7 @@ static int parse_table(int __user *name, int nlen,
repeat:
if (!nlen)
return -ENOTDIR;
- if (get_user(n, name))
- return -EFAULT;
+ n = *name;
for ( ; table->ctl_name || table->procname; table++) {
if (!table->ctl_name)
continue;
@@ -84,19 +81,13 @@ repeat:
return -ENOTDIR;
}

-int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen)
+static ssize_t binary_sysctl(const int *name, int nlen,
+ void __user *oldval, size_t __user *oldlenp,
+ void __user *newval, size_t newlen)
+
{
struct ctl_table_header *head;
- int error = -ENOTDIR;
-
- if (nlen <= 0 || nlen >= CTL_MAXNAME)
- return -ENOTDIR;
- if (oldval) {
- int old_len;
- if (!oldlenp || get_user(old_len, oldlenp))
- return -EFAULT;
- }
+ ssize_t error = -ENOTDIR;

for (head = sysctl_head_next(NULL); head;
head = sysctl_head_next(head)) {
@@ -111,74 +102,76 @@ int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *ol
return error;
}

-SYSCALL_DEFINE1(sysctl, struct __sysctl_args __user *, args)
-{
- struct __sysctl_args tmp;
- int error;
-
- 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;
-}
-
#else /* CONFIG_SYSCTL_SYSCALL */

-SYSCALL_DEFINE1(sysctl, struct __sysctl_args __user *, args)
+static ssize_t binary_sysctl(const int *ctl_name, int nlen,
+ void __user *oldval, size_t __user *oldlenp,
+ void __user *newval, size_t newlen)
{
- struct __sysctl_args tmp;
- int error;
-
- if (copy_from_user(&tmp, args, sizeof(tmp)))
- return -EFAULT;
-
- error = deprecated_sysctl_warning(&tmp);
-
- /* If no error reading the parameters then just -ENOSYS ... */
- if (!error)
- error = -ENOSYS;
-
- return error;
+ return -ENOSYS;
}

#endif /* CONFIG_SYSCTL_SYSCALL */

-static int deprecated_sysctl_warning(struct __sysctl_args *args)
+static void deprecated_sysctl_warning(const int *name, int nlen)
{
static int msg_count;
- int name[CTL_MAXNAME];
int i;

- /* Check args->nlen. */
- if (args->nlen < 0 || args->nlen > CTL_MAXNAME)
- return -ENOTDIR;
-
- /* 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 ((nlen == 2) && (name[0] == CTL_KERN) && (name[1] == KERN_VERSION))
+ return;

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++)
+ for (i = 0; i < nlen; i++)
printk("%d.", name[i]);
printk("\n");
}
- return 0;
+ return;
+}
+
+int do_sysctl(int __user *args_name, int nlen,
+ void __user *oldval, size_t __user *oldlenp,
+ void __user *newval, size_t newlen)
+{
+ int name[CTL_MAXNAME];
+ size_t oldlen = 0;
+ int i;
+
+ if (nlen <= 0 || nlen >= CTL_MAXNAME)
+ return -ENOTDIR;
+ if (oldval && !oldlenp)
+ return -EFAULT;
+ if (oldlenp && get_user(oldlen, oldlenp))
+ return -EFAULT;
+
+ /* Read in the sysctl name for simplicity */
+ for (i = 0; i < nlen; i++)
+ if (get_user(name[i], args_name + i))
+ return -EFAULT;
+
+ deprecated_sysctl_warning(name, nlen);
+
+ return binary_sysctl(name, nlen, oldval, oldlenp, newval, newlen);
+}
+
+
+SYSCALL_DEFINE1(sysctl, struct __sysctl_args __user *, args)
+{
+ struct __sysctl_args tmp;
+ int error;
+
+ if (copy_from_user(&tmp, args, sizeof(tmp)))
+ return -EFAULT;
+
+ lock_kernel();
+ error = do_sysctl(tmp.name, tmp.nlen, tmp.oldval, tmp.oldlenp,
+ tmp.newval, tmp.newlen);
+ unlock_kernel();
+
+ return error;
}
--
1.6.5.2.143.g8cc62

2009-11-06 00:43:17

by Eric W. Biederman

[permalink] [raw]
Subject: [PATCH 03/11] sysctl: Introduce a generic compat sysctl sysctl

From: Eric W. Biederman <[email protected]>

This uses compat_alloc_userspace to remove the various
hacks to allow do_sysctl to write to throuh oldlenp.

The rest of our mature compat syscall helper facitilies
are used as well to ensure we have a nice clean maintainable
compat syscall that can be used on all architectures.

The motiviation for a generic compat sysctl (besides the
obvious hack removal) is to reduce the number of compat
sysctl defintions out there so I can refactor the
binary sysctl implementation.

ppc already used the name compat_sys_sysctl so I remove the
ppcs version here.

Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Paul Mackerras <[email protected]>
Signed-off-by: Eric W. Biederman <[email protected]>
---
arch/powerpc/kernel/sys_ppc32.c | 52 ---------------------------------------
kernel/sysctl_binary.c | 50 +++++++++++++++++++++++++++++++++++++
2 files changed, 50 insertions(+), 52 deletions(-)

diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c
index b97c2d6..c5a4732 100644
--- a/arch/powerpc/kernel/sys_ppc32.c
+++ b/arch/powerpc/kernel/sys_ppc32.c
@@ -520,58 +520,6 @@ asmlinkage long compat_sys_umask(u32 mask)
return sys_umask((int)mask);
}

-#ifdef CONFIG_SYSCTL_SYSCALL
-struct __sysctl_args32 {
- u32 name;
- int nlen;
- u32 oldval;
- u32 oldlenp;
- u32 newval;
- u32 newlen;
- u32 __unused[4];
-};
-
-asmlinkage long compat_sys_sysctl(struct __sysctl_args32 __user *args)
-{
- struct __sysctl_args32 tmp;
- int error;
- size_t oldlen;
- size_t __user *oldlenp = NULL;
- unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7;
-
- if (copy_from_user(&tmp, args, sizeof(tmp)))
- return -EFAULT;
-
- if (tmp.oldval && tmp.oldlenp) {
- /* Duh, this is ugly and might not work if sysctl_args
- is in read-only memory, but do_sysctl does indirectly
- a lot of uaccess in both directions and we'd have to
- basically copy the whole sysctl.c here, and
- glibc's __sysctl uses rw memory for the structure
- anyway. */
- oldlenp = (size_t __user *)addr;
- if (get_user(oldlen, (compat_size_t __user *)compat_ptr(tmp.oldlenp)) ||
- put_user(oldlen, oldlenp))
- return -EFAULT;
- }
-
- lock_kernel();
- error = do_sysctl(compat_ptr(tmp.name), tmp.nlen,
- compat_ptr(tmp.oldval), oldlenp,
- compat_ptr(tmp.newval), tmp.newlen);
- unlock_kernel();
- if (oldlenp) {
- if (!error) {
- if (get_user(oldlen, oldlenp) ||
- put_user(oldlen, (compat_size_t __user *)compat_ptr(tmp.oldlenp)))
- error = -EFAULT;
- }
- copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
- }
- return error;
-}
-#endif
-
unsigned long compat_sys_mmap2(unsigned long addr, size_t len,
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff)
diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c
index c5cc393..a2fed5b 100644
--- a/kernel/sysctl_binary.c
+++ b/kernel/sysctl_binary.c
@@ -175,3 +175,53 @@ SYSCALL_DEFINE1(sysctl, struct __sysctl_args __user *, args)

return error;
}
+
+#ifdef CONFIG_COMPAT
+#include <asm/compat.h>
+
+struct compat_sysctl_args {
+ compat_uptr_t name;
+ int nlen;
+ compat_uptr_t oldval;
+ compat_uptr_t oldlenp;
+ compat_uptr_t newval;
+ compat_size_t newlen;
+ compat_ulong_t __unused[4];
+};
+
+asmlinkage long compat_sys_sysctl(struct compat_sysctl_args __user *args)
+{
+ struct compat_sysctl_args tmp;
+ compat_size_t __user *compat_oldlenp;
+ size_t __user *oldlenp = NULL;
+ size_t oldlen = 0;
+ ssize_t result;
+
+ if (copy_from_user(&tmp, args, sizeof(tmp)))
+ return -EFAULT;
+
+ compat_oldlenp = compat_ptr(tmp.oldlenp);
+ if (compat_oldlenp) {
+ oldlenp = compat_alloc_user_space(sizeof(*compat_oldlenp));
+
+ if (get_user(oldlen, compat_oldlenp) ||
+ put_user(oldlen, oldlenp))
+ return -EFAULT;
+ }
+
+ lock_kernel();
+ result = do_sysctl(compat_ptr(tmp.name), tmp.nlen,
+ compat_ptr(tmp.oldval), oldlenp,
+ compat_ptr(tmp.newval), tmp.newlen);
+ unlock_kernel();
+
+ if (oldlenp && !result) {
+ if (get_user(oldlen, oldlenp) ||
+ put_user(oldlen, compat_oldlenp))
+ return -EFAULT;
+ }
+
+ return result;
+}
+
+#endif /* CONFIG_COMPAT */
--
1.6.5.2.143.g8cc62

2009-11-06 00:44:10

by Eric W. Biederman

[permalink] [raw]
Subject: [PATCH 04/11] sysctl: ia64 Use the compat_sys_sysctl

From: Eric W. Biederman <[email protected]>

Now that we have a generic 32bit compatibility implementation
there is no need for ia64 to implement it's own.

Cc: Tony Luck <[email protected]>
Cc: Fenghua Yu <[email protected]>
Signed-off-by: Eric W. Biederman <[email protected]>
---
arch/ia64/ia32/ia32_entry.S | 2 +-
arch/ia64/ia32/sys_ia32.c | 55 -------------------------------------------
2 files changed, 1 insertions(+), 56 deletions(-)

diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
index af9405c..10c3751 100644
--- a/arch/ia64/ia32/ia32_entry.S
+++ b/arch/ia64/ia32/ia32_entry.S
@@ -327,7 +327,7 @@ ia32_syscall_table:
data8 compat_sys_writev
data8 sys_getsid
data8 sys_fdatasync
- data8 sys32_sysctl
+ data8 compat_sys_sysctl
data8 sys_mlock /* 150 */
data8 sys_munlock
data8 sys_mlockall
diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
index 625ed8f..429ec96 100644
--- a/arch/ia64/ia32/sys_ia32.c
+++ b/arch/ia64/ia32/sys_ia32.c
@@ -1628,61 +1628,6 @@ sys32_msync (unsigned int start, unsigned int len, int flags)
return sys_msync(addr, len + (start - addr), flags);
}

-struct sysctl32 {
- unsigned int name;
- int nlen;
- unsigned int oldval;
- unsigned int oldlenp;
- unsigned int newval;
- unsigned int newlen;
- unsigned int __unused[4];
-};
-
-#ifdef CONFIG_SYSCTL_SYSCALL
-asmlinkage long
-sys32_sysctl (struct sysctl32 __user *args)
-{
- struct sysctl32 a32;
- mm_segment_t old_fs = get_fs ();
- void __user *oldvalp, *newvalp;
- size_t oldlen;
- int __user *namep;
- long ret;
-
- if (copy_from_user(&a32, args, sizeof(a32)))
- return -EFAULT;
-
- /*
- * We need to pre-validate these because we have to disable address checking
- * before calling do_sysctl() because of OLDLEN but we can't run the risk of the
- * user specifying bad addresses here. Well, since we're dealing with 32 bit
- * addresses, we KNOW that access_ok() will always succeed, so this is an
- * expensive NOP, but so what...
- */
- namep = (int __user *) compat_ptr(a32.name);
- oldvalp = compat_ptr(a32.oldval);
- newvalp = compat_ptr(a32.newval);
-
- if ((oldvalp && get_user(oldlen, (int __user *) compat_ptr(a32.oldlenp)))
- || !access_ok(VERIFY_WRITE, namep, 0)
- || !access_ok(VERIFY_WRITE, oldvalp, 0)
- || !access_ok(VERIFY_WRITE, newvalp, 0))
- return -EFAULT;
-
- set_fs(KERNEL_DS);
- lock_kernel();
- ret = do_sysctl(namep, a32.nlen, oldvalp, (size_t __user *) &oldlen,
- newvalp, (size_t) a32.newlen);
- unlock_kernel();
- set_fs(old_fs);
-
- if (oldvalp && put_user (oldlen, (int __user *) compat_ptr(a32.oldlenp)))
- return -EFAULT;
-
- return ret;
-}
-#endif
-
asmlinkage long
sys32_newuname (struct new_utsname __user *name)
{
--
1.6.5.2.143.g8cc62

2009-11-06 00:43:37

by Eric W. Biederman

[permalink] [raw]
Subject: [PATCH 05/11] sysctl: mips Use the compat_sys_sysctl

From: Eric W. Biederman <[email protected]>

Now that we have a generic 32bit compatibility implementation
there is no need for mips to implement it's own.

Cc: Ralf Baechle <[email protected]>
Signed-off-by: Eric W. Biederman <[email protected]>
---
arch/mips/kernel/linux32.c | 61 ----------------------------------------
arch/mips/kernel/scall64-n32.S | 2 +-
arch/mips/kernel/scall64-o32.S | 2 +-
3 files changed, 2 insertions(+), 63 deletions(-)

diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index b77fefa..1a2793e 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -265,67 +265,6 @@ SYSCALL_DEFINE5(n32_msgrcv, int, msqid, u32, msgp, size_t, msgsz,
}
#endif

-struct sysctl_args32
-{
- compat_caddr_t name;
- int nlen;
- compat_caddr_t oldval;
- compat_caddr_t oldlenp;
- compat_caddr_t newval;
- compat_size_t newlen;
- unsigned int __unused[4];
-};
-
-#ifdef CONFIG_SYSCTL_SYSCALL
-
-SYSCALL_DEFINE1(32_sysctl, struct sysctl_args32 __user *, args)
-{
- struct sysctl_args32 tmp;
- int error;
- size_t oldlen;
- size_t __user *oldlenp = NULL;
- unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7;
-
- if (copy_from_user(&tmp, args, sizeof(tmp)))
- return -EFAULT;
-
- if (tmp.oldval && tmp.oldlenp) {
- /* Duh, this is ugly and might not work if sysctl_args
- is in read-only memory, but do_sysctl does indirectly
- a lot of uaccess in both directions and we'd have to
- basically copy the whole sysctl.c here, and
- glibc's __sysctl uses rw memory for the structure
- anyway. */
- if (get_user(oldlen, (u32 __user *)A(tmp.oldlenp)) ||
- put_user(oldlen, (size_t __user *)addr))
- return -EFAULT;
- oldlenp = (size_t __user *)addr;
- }
-
- lock_kernel();
- error = do_sysctl((int __user *)A(tmp.name), tmp.nlen, (void __user *)A(tmp.oldval),
- oldlenp, (void __user *)A(tmp.newval), tmp.newlen);
- unlock_kernel();
- if (oldlenp) {
- if (!error) {
- if (get_user(oldlen, (size_t __user *)addr) ||
- put_user(oldlen, (u32 __user *)A(tmp.oldlenp)))
- error = -EFAULT;
- }
- copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
- }
- return error;
-}
-
-#else
-
-SYSCALL_DEFINE1(32_sysctl, struct sysctl_args32 __user *, args)
-{
- return -ENOSYS;
-}
-
-#endif /* CONFIG_SYSCTL_SYSCALL */
-
SYSCALL_DEFINE1(32_newuname, struct new_utsname __user *, name)
{
int ret = 0;
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 6ebc079..8a0be0b 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -272,7 +272,7 @@ EXPORT(sysn32_call_table)
PTR sys_munlockall
PTR sys_vhangup /* 6150 */
PTR sys_pivot_root
- PTR sys_32_sysctl
+ PTR compat_sys_sysctl
PTR sys_prctl
PTR compat_sys_adjtimex
PTR compat_sys_setrlimit /* 6155 */
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 14dde4c..41dbdb7 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -356,7 +356,7 @@ sys_call_table:
PTR sys_ni_syscall /* 4150 */
PTR sys_getsid
PTR sys_fdatasync
- PTR sys_32_sysctl
+ PTR compat_sys_sysctl
PTR sys_mlock
PTR sys_munlock /* 4155 */
PTR sys_mlockall
--
1.6.5.2.143.g8cc62

2009-11-06 00:42:21

by Eric W. Biederman

[permalink] [raw]
Subject: [PATCH 06/11] sysctl: parisc Use the compat_sys_sysctl

From: Eric W. Biederman <[email protected]>

Now that we have a generic 32bit compatibility implementation
there is no need for parisc to implement it's own.

Cc: Kyle McMartin <[email protected]>
Cc: Thibaut Varene <[email protected]>
Signed-off-by: Eric W. Biederman <[email protected]>
---
arch/parisc/kernel/sys_parisc32.c | 71 ------------------------------------
arch/parisc/kernel/syscall_table.S | 2 +-
2 files changed, 1 insertions(+), 72 deletions(-)

diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c
index 561388b..76d23ec 100644
--- a/arch/parisc/kernel/sys_parisc32.c
+++ b/arch/parisc/kernel/sys_parisc32.c
@@ -90,77 +90,6 @@ asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23,
return -ENOSYS;
}

-#ifdef CONFIG_SYSCTL
-
-struct __sysctl_args32 {
- u32 name;
- int nlen;
- u32 oldval;
- u32 oldlenp;
- u32 newval;
- u32 newlen;
- u32 __unused[4];
-};
-
-asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
-{
-#ifndef CONFIG_SYSCTL_SYSCALL
- return -ENOSYS;
-#else
- struct __sysctl_args32 tmp;
- int error;
- unsigned int oldlen32;
- size_t oldlen, __user *oldlenp = NULL;
- unsigned long addr = (((long __force)&args->__unused[0]) + 7) & ~7;
-
- DBG(("sysctl32(%p)\n", args));
-
- if (copy_from_user(&tmp, args, sizeof(tmp)))
- return -EFAULT;
-
- if (tmp.oldval && tmp.oldlenp) {
- /* Duh, this is ugly and might not work if sysctl_args
- is in read-only memory, but do_sysctl does indirectly
- a lot of uaccess in both directions and we'd have to
- basically copy the whole sysctl.c here, and
- glibc's __sysctl uses rw memory for the structure
- anyway. */
- /* a possibly better hack than this, which will avoid the
- * problem if the struct is read only, is to push the
- * 'oldlen' value out to the user's stack instead. -PB
- */
- if (get_user(oldlen32, (u32 *)(u64)tmp.oldlenp))
- return -EFAULT;
- oldlen = oldlen32;
- if (put_user(oldlen, (size_t *)addr))
- return -EFAULT;
- oldlenp = (size_t *)addr;
- }
-
- lock_kernel();
- error = do_sysctl((int __user *)(u64)tmp.name, tmp.nlen,
- (void __user *)(u64)tmp.oldval, oldlenp,
- (void __user *)(u64)tmp.newval, tmp.newlen);
- unlock_kernel();
- if (oldlenp) {
- if (!error) {
- if (get_user(oldlen, (size_t *)addr)) {
- error = -EFAULT;
- } else {
- oldlen32 = oldlen;
- if (put_user(oldlen32, (u32 *)(u64)tmp.oldlenp))
- error = -EFAULT;
- }
- }
- if (copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused)))
- error = -EFAULT;
- }
- return error;
-#endif
-}
-
-#endif /* CONFIG_SYSCTL */
-
asmlinkage long sys32_sched_rr_get_interval(pid_t pid,
struct compat_timespec __user *interval)
{
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index 843f423..01c4fcf 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -234,7 +234,7 @@
ENTRY_SAME(getsid)
ENTRY_SAME(fdatasync)
/* struct __sysctl_args is a mess */
- ENTRY_DIFF(sysctl)
+ ENTRY_COMP(sysctl)
ENTRY_SAME(mlock) /* 150 */
ENTRY_SAME(munlock)
ENTRY_SAME(mlockall)
--
1.6.5.2.143.g8cc62

2009-11-06 00:43:21

by Eric W. Biederman

[permalink] [raw]
Subject: [PATCH 07/11] sysctl: s390 Use the compat_sys_sysctl

From: Eric W. Biederman <[email protected]>

Now that we have a generic 32bit compatibility implementation
there is no need for s390 to implement it's own.

Cc: Carsten Otte <[email protected]>
Cc: Christian Borntraeger <[email protected]>
Signed-off-by: Eric W. Biederman <[email protected]>
---
arch/s390/kernel/compat_linux.c | 53 -------------------------------------
arch/s390/kernel/compat_linux.h | 2 -
arch/s390/kernel/compat_wrapper.S | 6 +---
3 files changed, 2 insertions(+), 59 deletions(-)

diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 0debcec..fda1a81 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -527,59 +527,6 @@ asmlinkage long sys32_sendfile64(int out_fd, int in_fd,
return ret;
}

-#ifdef CONFIG_SYSCTL_SYSCALL
-struct __sysctl_args32 {
- u32 name;
- int nlen;
- u32 oldval;
- u32 oldlenp;
- u32 newval;
- u32 newlen;
- u32 __unused[4];
-};
-
-asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
-{
- struct __sysctl_args32 tmp;
- int error;
- size_t oldlen;
- size_t __user *oldlenp = NULL;
- unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7;
-
- if (copy_from_user(&tmp, args, sizeof(tmp)))
- return -EFAULT;
-
- if (tmp.oldval && tmp.oldlenp) {
- /* Duh, this is ugly and might not work if sysctl_args
- is in read-only memory, but do_sysctl does indirectly
- a lot of uaccess in both directions and we'd have to
- basically copy the whole sysctl.c here, and
- glibc's __sysctl uses rw memory for the structure
- anyway. */
- if (get_user(oldlen, (u32 __user *)compat_ptr(tmp.oldlenp)) ||
- put_user(oldlen, (size_t __user *)addr))
- return -EFAULT;
- oldlenp = (size_t __user *)addr;
- }
-
- lock_kernel();
- error = do_sysctl(compat_ptr(tmp.name), tmp.nlen, compat_ptr(tmp.oldval),
- oldlenp, compat_ptr(tmp.newval), tmp.newlen);
- unlock_kernel();
- if (oldlenp) {
- if (!error) {
- if (get_user(oldlen, (size_t __user *)addr) ||
- put_user(oldlen, (u32 __user *)compat_ptr(tmp.oldlenp)))
- error = -EFAULT;
- }
- if (copy_to_user(args->__unused, tmp.__unused,
- sizeof(tmp.__unused)))
- error = -EFAULT;
- }
- return error;
-}
-#endif
-
struct stat64_emu31 {
unsigned long long st_dev;
unsigned int __pad1;
diff --git a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h
index c07f9ca..45e9092 100644
--- a/arch/s390/kernel/compat_linux.h
+++ b/arch/s390/kernel/compat_linux.h
@@ -162,7 +162,6 @@ struct ucontext32 {
compat_sigset_t uc_sigmask; /* mask last for extensibility */
};

-struct __sysctl_args32;
struct stat64_emu31;
struct mmap_arg_struct_emu31;
struct fadvise64_64_args;
@@ -212,7 +211,6 @@ long sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset,
size_t count);
long sys32_sendfile64(int out_fd, int in_fd, compat_loff_t __user *offset,
s32 count);
-long sys32_sysctl(struct __sysctl_args32 __user *args);
long sys32_stat64(char __user * filename, struct stat64_emu31 __user * statbuf);
long sys32_lstat64(char __user * filename,
struct stat64_emu31 __user * statbuf);
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index cbd9901..30de2d0 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -689,8 +689,6 @@ sys32_fdatasync_wrapper:
llgfr %r2,%r2 # unsigned int
jg sys_fdatasync # branch to system call

-#sys32_sysctl_wrapper # tbd
-
.globl sys32_mlock_wrapper
sys32_mlock_wrapper:
llgfr %r2,%r2 # unsigned long
@@ -1087,8 +1085,8 @@ sys32_stime_wrapper:

.globl sys32_sysctl_wrapper
sys32_sysctl_wrapper:
- llgtr %r2,%r2 # struct __sysctl_args32 *
- jg sys32_sysctl
+ llgtr %r2,%r2 # struct compat_sysctl_args *
+ jg compat_sys_sysctl

.globl sys32_fstat64_wrapper
sys32_fstat64_wrapper:
--
1.6.5.2.143.g8cc62

2009-11-06 00:43:52

by Eric W. Biederman

[permalink] [raw]
Subject: [PATCH 08/11] sysctl: sparc Use the compat_sys_sysctl

From: Eric W. Biederman <[email protected]>

Now that we have a generic 32bit compatibility implementation
there is no need for sparc to implement it's own.

Cc: "David S. Miller" <[email protected]>
Signed-off-by: Eric W. Biederman <[email protected]>
---
arch/sparc/kernel/sys_sparc32.c | 57 ---------------------------------------
arch/sparc/kernel/systbls_64.S | 2 +-
2 files changed, 1 insertions(+), 58 deletions(-)

diff --git a/arch/sparc/kernel/sys_sparc32.c b/arch/sparc/kernel/sys_sparc32.c
index 04e28b2..f862372 100644
--- a/arch/sparc/kernel/sys_sparc32.c
+++ b/arch/sparc/kernel/sys_sparc32.c
@@ -591,63 +591,6 @@ out:
return ret;
}

-struct __sysctl_args32 {
- u32 name;
- int nlen;
- u32 oldval;
- u32 oldlenp;
- u32 newval;
- u32 newlen;
- u32 __unused[4];
-};
-
-asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
-{
-#ifndef CONFIG_SYSCTL_SYSCALL
- return -ENOSYS;
-#else
- struct __sysctl_args32 tmp;
- int error;
- size_t oldlen, __user *oldlenp = NULL;
- unsigned long addr = (((unsigned long)&args->__unused[0]) + 7UL) & ~7UL;
-
- if (copy_from_user(&tmp, args, sizeof(tmp)))
- return -EFAULT;
-
- if (tmp.oldval && tmp.oldlenp) {
- /* Duh, this is ugly and might not work if sysctl_args
- is in read-only memory, but do_sysctl does indirectly
- a lot of uaccess in both directions and we'd have to
- basically copy the whole sysctl.c here, and
- glibc's __sysctl uses rw memory for the structure
- anyway. */
- if (get_user(oldlen, (u32 __user *)(unsigned long)tmp.oldlenp) ||
- put_user(oldlen, (size_t __user *)addr))
- return -EFAULT;
- oldlenp = (size_t __user *)addr;
- }
-
- lock_kernel();
- error = do_sysctl((int __user *)(unsigned long) tmp.name,
- tmp.nlen,
- (void __user *)(unsigned long) tmp.oldval,
- oldlenp,
- (void __user *)(unsigned long) tmp.newval,
- tmp.newlen);
- unlock_kernel();
- if (oldlenp) {
- if (!error) {
- if (get_user(oldlen, (size_t __user *)addr) ||
- put_user(oldlen, (u32 __user *)(unsigned long) tmp.oldlenp))
- error = -EFAULT;
- }
- if (copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused)))
- error = -EFAULT;
- }
- return error;
-#endif
-}
-
long sys32_lookup_dcookie(unsigned long cookie_high,
unsigned long cookie_low,
char __user *buf, size_t len)
diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S
index 009825f..034b10e 100644
--- a/arch/sparc/kernel/systbls_64.S
+++ b/arch/sparc/kernel/systbls_64.S
@@ -68,7 +68,7 @@ sys_call_table32:
.word compat_sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys32_mlockall
/*240*/ .word sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys32_sched_setscheduler, sys32_sched_getscheduler
.word sys_sched_yield, sys32_sched_get_priority_max, sys32_sched_get_priority_min, sys32_sched_rr_get_interval, compat_sys_nanosleep
-/*250*/ .word sys32_mremap, sys32_sysctl, sys32_getsid, sys_fdatasync, sys32_nfsservctl
+/*250*/ .word sys32_mremap, compat_sys_sysctl, sys32_getsid, sys_fdatasync, sys32_nfsservctl
.word sys32_sync_file_range, compat_sys_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep
/*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun
.word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
--
1.6.5.2.143.g8cc62

2009-11-06 00:42:52

by Eric W. Biederman

[permalink] [raw]
Subject: [PATCH 09/11] sysctl: x86 Use the compat_sys_sysctl

From: Eric W. Biederman <[email protected]>

Now that we have a generic 32bit compatibility implementation
there is no need for x86 to implement it's own.

Cc: Thomas Gleixner <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: "H. Peter Anvin" <[email protected]>
Signed-off-by: Eric W. Biederman <[email protected]>
---
arch/x86/ia32/ia32entry.S | 2 +-
arch/x86/ia32/sys_ia32.c | 56 ---------------------------------------
arch/x86/include/asm/sys_ia32.h | 5 ---
3 files changed, 1 insertions(+), 62 deletions(-)

diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 581b056..5d25848 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -653,7 +653,7 @@ ia32_sys_call_table:
.quad compat_sys_writev
.quad sys_getsid
.quad sys_fdatasync
- .quad sys32_sysctl /* sysctl */
+ .quad compat_sys_sysctl /* sysctl */
.quad sys_mlock /* 150 */
.quad sys_munlock
.quad sys_mlockall
diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c
index 9f55271..df82c0e 100644
--- a/arch/x86/ia32/sys_ia32.c
+++ b/arch/x86/ia32/sys_ia32.c
@@ -434,62 +434,6 @@ asmlinkage long sys32_rt_sigqueueinfo(int pid, int sig,
return ret;
}

-#ifdef CONFIG_SYSCTL_SYSCALL
-struct sysctl_ia32 {
- unsigned int name;
- int nlen;
- unsigned int oldval;
- unsigned int oldlenp;
- unsigned int newval;
- unsigned int newlen;
- unsigned int __unused[4];
-};
-
-
-asmlinkage long sys32_sysctl(struct sysctl_ia32 __user *args32)
-{
- struct sysctl_ia32 a32;
- mm_segment_t old_fs = get_fs();
- void __user *oldvalp, *newvalp;
- size_t oldlen;
- int __user *namep;
- long ret;
-
- if (copy_from_user(&a32, args32, sizeof(a32)))
- return -EFAULT;
-
- /*
- * We need to pre-validate these because we have to disable
- * address checking before calling do_sysctl() because of
- * OLDLEN but we can't run the risk of the user specifying bad
- * addresses here. Well, since we're dealing with 32 bit
- * addresses, we KNOW that access_ok() will always succeed, so
- * this is an expensive NOP, but so what...
- */
- namep = compat_ptr(a32.name);
- oldvalp = compat_ptr(a32.oldval);
- newvalp = compat_ptr(a32.newval);
-
- if ((oldvalp && get_user(oldlen, (int __user *)compat_ptr(a32.oldlenp)))
- || !access_ok(VERIFY_WRITE, namep, 0)
- || !access_ok(VERIFY_WRITE, oldvalp, 0)
- || !access_ok(VERIFY_WRITE, newvalp, 0))
- return -EFAULT;
-
- set_fs(KERNEL_DS);
- lock_kernel();
- ret = do_sysctl(namep, a32.nlen, oldvalp, (size_t __user *)&oldlen,
- newvalp, (size_t) a32.newlen);
- unlock_kernel();
- set_fs(old_fs);
-
- if (oldvalp && put_user(oldlen, (int __user *)compat_ptr(a32.oldlenp)))
- return -EFAULT;
-
- return ret;
-}
-#endif
-
/* warning: next two assume little endian */
asmlinkage long sys32_pread(unsigned int fd, char __user *ubuf, u32 count,
u32 poslo, u32 poshi)
diff --git a/arch/x86/include/asm/sys_ia32.h b/arch/x86/include/asm/sys_ia32.h
index 72a6dcd..9af9dec 100644
--- a/arch/x86/include/asm/sys_ia32.h
+++ b/arch/x86/include/asm/sys_ia32.h
@@ -51,11 +51,6 @@ asmlinkage long sys32_sched_rr_get_interval(compat_pid_t,
asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *, compat_size_t);
asmlinkage long sys32_rt_sigqueueinfo(int, int, compat_siginfo_t __user *);

-#ifdef CONFIG_SYSCTL_SYSCALL
-struct sysctl_ia32;
-asmlinkage long sys32_sysctl(struct sysctl_ia32 __user *);
-#endif
-
asmlinkage long sys32_pread(unsigned int, char __user *, u32, u32, u32);
asmlinkage long sys32_pwrite(unsigned int, char __user *, u32, u32, u32);

--
1.6.5.2.143.g8cc62

2009-11-06 00:42:50

by Eric W. Biederman

[permalink] [raw]
Subject: [PATCH 10/11] sysctl: Remove the cond_syscall entry for sys32_sysctl

From: Eric W. Biederman <[email protected]>

Now that all architechtures are use compat_sys_sysctl and sys32_sysctl
does not exist there is not point in retaining a cond_syscall
entry for it.

Signed-off-by: Eric W. Biederman <[email protected]>
---
kernel/sys_ni.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index e06d0b8..de5bf14 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -139,7 +139,6 @@ cond_syscall(sys_pciconfig_read);
cond_syscall(sys_pciconfig_write);
cond_syscall(sys_pciconfig_iobase);
cond_syscall(sys32_ipc);
-cond_syscall(sys32_sysctl);
cond_syscall(ppc_rtas);
cond_syscall(sys_spu_run);
cond_syscall(sys_spu_create);
--
1.6.5.2.143.g8cc62

2009-11-06 00:42:38

by Eric W. Biederman

[permalink] [raw]
Subject: [PATCH 11/11] sysctl: Make do_sysctl static

From: Eric W. Biederman <[email protected]>

Now that all of the architectures use compat_sys_sysctl do_sysctl
can become static.

Signed-off-by: Eric W. Biederman <[email protected]>
---
include/linux/sysctl.h | 4 ----
kernel/sysctl_binary.c | 2 +-
2 files changed, 1 insertions(+), 5 deletions(-)

diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 1e4743e..82c32b8 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -996,10 +996,6 @@ extern int proc_doulongvec_minmax(struct ctl_table *, int,
extern int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int,
void __user *, size_t *, loff_t *);

-extern int do_sysctl (int __user *name, int nlen,
- void __user *oldval, size_t __user *oldlenp,
- void __user *newval, size_t newlen);
-
extern ctl_handler sysctl_data;
extern ctl_handler sysctl_string;
extern ctl_handler sysctl_intvec;
diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c
index a2fed5b..b9b841e 100644
--- a/kernel/sysctl_binary.c
+++ b/kernel/sysctl_binary.c
@@ -134,7 +134,7 @@ static void deprecated_sysctl_warning(const int *name, int nlen)
return;
}

-int do_sysctl(int __user *args_name, int nlen,
+static int do_sysctl(int __user *args_name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen)
{
--
1.6.5.2.143.g8cc62

2009-11-06 00:48:49

by Eric W. Biederman

[permalink] [raw]
Subject: Re: [PATCH 0/11] generic compat_sys_sysctl


> I am in the process of cleaning up, and converting the binary sysctl
> sysctl call into a wrapper on top of the text based proc/sys.
>
> A first step in that process is to introduce a generic
> compat_sys_sysctl to reduce the number of places I have to touch.
> The following patcheset is the start of my series for handling that.
>
> The only architecture specific changes should be replace the
> current architecture name for it's 32bit compat syscall with
> compat_sys_sysctl, and deleting the architectures private
> 32bit compat syscall. The only requirement is that CONFIG_COMPAT
> be set when you need compat_sys_sysctl.
>
> These patches should just work, but an eyeball from someone who is
> familiar with the architecture specific details would be appreciated.
> I have only tested the 32bit compat code on x86_64.

I forgot to mention, my plan is to carry these patches in my tree
until the next merge window opens. That way I will be able to build
on top of them, without having to worry what happens if someone is
slow to merge the patches.

Eric

2009-11-06 00:56:15

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [PATCH 09/11] sysctl: x86 Use the compat_sys_sysctl

On 11/05/2009 04:41 PM, Eric W. Biederman wrote:
> From: Eric W. Biederman <[email protected]>
>
> Now that we have a generic 32bit compatibility implementation
> there is no need for x86 to implement it's own.
>
> Cc: Thomas Gleixner <[email protected]>
> Cc: Ingo Molnar <[email protected]>
> Cc: "H. Peter Anvin" <[email protected]>
> Signed-off-by: Eric W. Biederman <[email protected]>

Acked-by: H. Peter Anvin <[email protected]>

I'm assuming based on your previous email that you'll hang on to this
patch and carry it yourself.

-hpa

2009-11-06 01:15:18

by Eric W. Biederman

[permalink] [raw]
Subject: Re: [PATCH 09/11] sysctl: x86 Use the compat_sys_sysctl

"H. Peter Anvin" <[email protected]> writes:

> On 11/05/2009 04:41 PM, Eric W. Biederman wrote:
>> From: Eric W. Biederman <[email protected]>
>>
>> Now that we have a generic 32bit compatibility implementation
>> there is no need for x86 to implement it's own.
>>
>> Cc: Thomas Gleixner <[email protected]>
>> Cc: Ingo Molnar <[email protected]>
>> Cc: "H. Peter Anvin" <[email protected]>
>> Signed-off-by: Eric W. Biederman <[email protected]>
>
> Acked-by: H. Peter Anvin <[email protected]>
>
> I'm assuming based on your previous email that you'll hang on to this
> patch and carry it yourself.

That's the plan.

Eric

2009-11-06 01:42:31

by David Miller

[permalink] [raw]
Subject: Re: [PATCH 08/11] sysctl: sparc Use the compat_sys_sysctl

From: "Eric W. Biederman" <[email protected]>
Date: Thu, 5 Nov 2009 16:41:51 -0800

> From: Eric W. Biederman <[email protected]>
>
> Now that we have a generic 32bit compatibility implementation
> there is no need for sparc to implement it's own.
>
> Cc: "David S. Miller" <[email protected]>
> Signed-off-by: Eric W. Biederman <[email protected]>

Acked-by: David S. Miller <[email protected]>

2009-11-06 06:01:51

by Kyle McMartin

[permalink] [raw]
Subject: Re: [PATCH 06/11] sysctl: parisc Use the compat_sys_sysctl

On Thu, Nov 05, 2009 at 04:41:49PM -0800, Eric W. Biederman wrote:
> From: Eric W. Biederman <[email protected]>
>
> Now that we have a generic 32bit compatibility implementation
> there is no need for parisc to implement it's own.
>
> Cc: Kyle McMartin <[email protected]>
> Cc: Thibaut Varene <[email protected]>
> Signed-off-by: Eric W. Biederman <[email protected]>

Acked-by: Kyle McMartin <[email protected]>

2009-11-06 09:04:27

by Christian Borntraeger

[permalink] [raw]
Subject: Re: [PATCH 01/11] sysctl: Separate the binary sysctl logic into it's own file.

Am Freitag 06 November 2009 01:41:44 schrieb Eric W. Biederman:
> From: Eric W. Biederman <[email protected]>
>
> In preparation for more invasive cleanups separate the core
> binary sysctl logic into it's own file.
>
> Signed-off-by: Eric W. Biederman <[email protected]>

Hmm, with your patches on Linus git I get the following on s390:

kernel/sysctl_binary.c: In function 'SYSC_sysctl':
kernel/sysctl_binary.c:126: error: implicit declaration of function
'lock_kernel'
kernel/sysctl_binary.c:129: error: implicit declaration of function
'unlock_kernel'

Christian

2009-11-06 09:12:18

by Christian Borntraeger

[permalink] [raw]
Subject: Re: [PATCH 07/11] sysctl: s390 Use the compat_sys_sysctl

Am Freitag 06 November 2009 01:41:50 schrieb Eric W. Biederman:
> From: Eric W. Biederman <[email protected]>
>
> Now that we have a generic 32bit compatibility implementation
> there is no need for s390 to implement it's own.
>
> Cc: Carsten Otte <[email protected]>
> Cc: Christian Borntraeger <[email protected]>

You should have CCed Martin & Heiko, since this is cleary not KVM.
I took a look anyway ;-)

> Signed-off-by: Eric W. Biederman <[email protected]>
Patch looks good.

Acked-by: Christian Borntraeger <[email protected]>

2009-11-06 09:23:40

by Martin Schwidefsky

[permalink] [raw]
Subject: Re: [PATCH 07/11] sysctl: s390 Use the compat_sys_sysctl

On Thu, 5 Nov 2009 16:41:50 -0800
"Eric W. Biederman" <[email protected]> wrote:

> From: Eric W. Biederman <[email protected]>
>
> Now that we have a generic 32bit compatibility implementation
> there is no need for s390 to implement it's own.
>
> Cc: Carsten Otte <[email protected]>
> Cc: Christian Borntraeger <[email protected]>
> Signed-off-by: Eric W. Biederman <[email protected]>
> ---
> arch/s390/kernel/compat_linux.c | 53 -------------------------------------
> arch/s390/kernel/compat_linux.h | 2 -
> arch/s390/kernel/compat_wrapper.S | 6 +---
> 3 files changed, 2 insertions(+), 59 deletions(-)

That looks nice, definitely an improvement over the old code.

Acked-by: Martin Schwidefsky <[email protected]>

--
blue skies,
Martin.

"Reality continues to ruin my life." - Calvin.

2009-11-06 10:19:54

by Eric W. Biederman

[permalink] [raw]
Subject: Re: [PATCH 07/11] sysctl: s390 Use the compat_sys_sysctl

Christian Borntraeger <[email protected]> writes:

> Am Freitag 06 November 2009 01:41:50 schrieb Eric W. Biederman:
>> From: Eric W. Biederman <[email protected]>
>>
>> Now that we have a generic 32bit compatibility implementation
>> there is no need for s390 to implement it's own.
>>
>> Cc: Carsten Otte <[email protected]>
>> Cc: Christian Borntraeger <[email protected]>
>
> You should have CCed Martin & Heiko, since this is cleary not KVM.
> I took a look anyway ;-)

Groan. I got the wrong s390 line in MAINTAINERS.

>> Signed-off-by: Eric W. Biederman <[email protected]>
> Patch looks good.
>
> Acked-by: Christian Borntraeger <[email protected]>

2009-11-06 10:29:19

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 0/11] generic compat_sys_sysctl

On Friday 06 November 2009, Eric W. Biederman wrote:
> current architecture name for it's 32bit compat syscall with
> compat_sys_sysctl, and deleting the architectures private
> 32bit compat syscall. The only requirement is that CONFIG_COMPAT
> be set when you need compat_sys_sysctl.
>
> These patches should just work, but an eyeball from someone who is
> familiar with the architecture specific details would be appreciated.
> I have only tested the 32bit compat code on x86_64.

I have done similar conversions for other syscalls and am familiar
with s390 and powerpc specific details. Your compat code looks good
for all of the pitfalls I'm aware of and possibly fixes bugs in the
existing arch specific implementations.

Very nice series!

Acked-by: Arnd Bergmann <[email protected]>

2009-11-06 11:33:34

by Eric W. Biederman

[permalink] [raw]
Subject: Re: [PATCH 01/11] sysctl: Separate the binary sysctl logic into it's own file.

Christian Borntraeger <[email protected]> writes:

> Am Freitag 06 November 2009 01:41:44 schrieb Eric W. Biederman:
>> From: Eric W. Biederman <[email protected]>
>>
>> In preparation for more invasive cleanups separate the core
>> binary sysctl logic into it's own file.
>>
>> Signed-off-by: Eric W. Biederman <[email protected]>
>
> Hmm, with your patches on Linus git I get the following on s390:
>
> kernel/sysctl_binary.c: In function 'SYSC_sysctl':
> kernel/sysctl_binary.c:126: error: implicit declaration of function
> 'lock_kernel'
> kernel/sysctl_binary.c:129: error: implicit declaration of function
> 'unlock_kernel'

Bah. A missing smp_lock.h.


Thanks.
Eric

2009-11-06 12:10:15

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 01/11] sysctl: Separate the binary sysctl logic into it's own file.

On Friday 06 November 2009, Eric W. Biederman wrote:
> Christian Borntraeger <[email protected]> writes:
>
> > Am Freitag 06 November 2009 01:41:44 schrieb Eric W. Biederman:
> >> From: Eric W. Biederman <[email protected]>
> >>
> >> In preparation for more invasive cleanups separate the core
> >> binary sysctl logic into it's own file.
> >>
> >> Signed-off-by: Eric W. Biederman <[email protected]>
> >
> > Hmm, with your patches on Linus git I get the following on s390:
> >
> > kernel/sysctl_binary.c: In function 'SYSC_sysctl':
> > kernel/sysctl_binary.c:126: error: implicit declaration of function
> > 'lock_kernel'
> > kernel/sysctl_binary.c:129: error: implicit declaration of function
> > 'unlock_kernel'
>
> Bah. A missing smp_lock.h.

BTW, there is a patch in the kill-the-BKL tree to push down the BKL
further into the sysctl handlers. It may be a good idea to put that
into your tree, or to redo the same thing there differently, since
you already have a patch series touching this area.

Arnd <><

2009-11-06 12:55:27

by Eric W. Biederman

[permalink] [raw]
Subject: Re: [PATCH 01/11] sysctl: Separate the binary sysctl logic into it's own file.

Arnd Bergmann <[email protected]> writes:

> On Friday 06 November 2009, Eric W. Biederman wrote:
>> Christian Borntraeger <[email protected]> writes:
>>
>> > Am Freitag 06 November 2009 01:41:44 schrieb Eric W. Biederman:
>> >> From: Eric W. Biederman <[email protected]>
>> >>
>> >> In preparation for more invasive cleanups separate the core
>> >> binary sysctl logic into it's own file.
>> >>
>> >> Signed-off-by: Eric W. Biederman <[email protected]>
>> >
>> > Hmm, with your patches on Linus git I get the following on s390:
>> >
>> > kernel/sysctl_binary.c: In function 'SYSC_sysctl':
>> > kernel/sysctl_binary.c:126: error: implicit declaration of function
>> > 'lock_kernel'
>> > kernel/sysctl_binary.c:129: error: implicit declaration of function
>> > 'unlock_kernel'
>>
>> Bah. A missing smp_lock.h.
>
> BTW, there is a patch in the kill-the-BKL tree to push down the BKL
> further into the sysctl handlers. It may be a good idea to put that
> into your tree, or to redo the same thing there differently, since
> you already have a patch series touching this area.

Thanks for the info.

The primary proc path already doesn't need the lock_kernel(). My next
patch winds up killing the entire binary path and rebuilding on top of
/proc/sys. Which removes that lock_kernel().

Which I think elegantly solves all of the sysctl BKL lock issues.

Which is probably why I missed the compilation failure.

Eric

2009-11-06 13:11:29

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 01/11] sysctl: Separate the binary sysctl logic into it's own file.

On Friday 06 November 2009, Eric W. Biederman wrote:
> The primary proc path already doesn't need the lock_kernel(). My next
> patch winds up killing the entire binary path and rebuilding on top of
> /proc/sys. Which removes that lock_kernel().
>
> Which I think elegantly solves all of the sysctl BKL lock issues.

Yes, that sounds like an excellent plan, but I'm not completely sure
if the lack of the BKL in the procfs case is intentional. As a
particular case that I stumbled over, 'core_pattern' is read
with the BKL held to protect against sysctl changing it, but
it is changed with proc_dostring without the BKL.

Most uses of intvec or string seem to be racy and probably need
a proper serialization method anyway.

Arnd <><

2009-11-06 13:58:45

by Eric W. Biederman

[permalink] [raw]
Subject: Re: [PATCH 01/11] sysctl: Separate the binary sysctl logic into it's own file.

Arnd Bergmann <[email protected]> writes:

> On Friday 06 November 2009, Eric W. Biederman wrote:
>> The primary proc path already doesn't need the lock_kernel(). My next
>> patch winds up killing the entire binary path and rebuilding on top of
>> /proc/sys. Which removes that lock_kernel().
>>
>> Which I think elegantly solves all of the sysctl BKL lock issues.
>
> Yes, that sounds like an excellent plan, but I'm not completely sure
> if the lack of the BKL in the procfs case is intentional. As a
> particular case that I stumbled over, 'core_pattern' is read
> with the BKL held to protect against sysctl changing it, but
> it is changed with proc_dostring without the BKL.

Then that is a bug. The bottom line is sys_sysctl never gets used
in practice, making the proc interface normative.

> Most uses of intvec or string seem to be racy and probably need
> a proper serialization method anyway.

That sounds familiar. Of course in practice the changes are rare
enough and are of static variables that don't get reallocated
that I would be surprised if the lack of lacking ever causes
more more than temporary strange behavior.

Eric