[patch 4/6] sys_indirect RFC - compat code for sys_indirect and compat_call_syscall for x86-64

From: Davide Libenzi
Date: Fri Jun 29 2007 - 17:51:12 EST


This is the compat code necessary for sys_indirect(). Since the data
structure passed down to sys_indirect() is compat-free, this is the
only processing needed.
A required compat_call_syscall() has been added to the x86-64 arch.



Signed-off-by: Davide Libenzi <davidel@xxxxxxxxxxxxxxx>


- Davide



---
arch/x86_64/ia32/ia32entry.S | 18 +++++++++++++++++
include/asm-x86_64/unistd.h | 1
kernel/compat.c | 44 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 63 insertions(+)

Index: linux-2.6.mod/kernel/compat.c
===================================================================
--- linux-2.6.mod.orig/kernel/compat.c 2007-06-29 12:12:41.000000000 -0700
+++ linux-2.6.mod/kernel/compat.c 2007-06-29 12:13:46.000000000 -0700
@@ -23,6 +23,8 @@
#include <linux/timex.h>
#include <linux/migrate.h>
#include <linux/posix-timers.h>
+#include <linux/fsalloc.h>
+#include <linux/indirect.h>

#include <asm/uaccess.h>

@@ -1082,3 +1084,45 @@
return 0;
}

+asmlinkage long compat_sys_indirect(unsigned int nr,
+ const __u32 __user *ctxs, unsigned int nctxs,
+ const __u32 __user *params)
+{
+ unsigned int i;
+ long res;
+ u32 tmp;
+ struct indirect_op *iops;
+ const struct indirect_ctx __user * __user *uctxs;
+ unsigned long kparams[6];
+ struct fsa_context ator;
+ char ator_cache[128];
+
+ if (!indirect_call_ok(nr) || nctxs >= INT_MAX / sizeof(__u32))
+ return -EINVAL;
+ if (!access_ok(VERIFY_READ, params, 6 * sizeof(u32)) ||
+ !access_ok(VERIFY_READ, ctxs, nctxs * sizeof(u32)))
+ return -EFAULT;
+ uctxs = compat_alloc_user_space(nctxs * sizeof(void *));
+ for (i = 0, res = 0; !res && i < nctxs; i++) {
+ res |= __get_user(tmp, &ctxs[i]);
+ res |= __put_user((unsigned long) tmp, &uctxs[i]);
+ }
+ if (res)
+ return -EFAULT;
+ for (i = 0, res = 0; i < 6; i++) {
+ res |= __get_user(tmp, &params[i]);
+ kparams[i] = tmp;
+ }
+ if (res)
+ return -EFAULT;
+ fsa_init(&ator, ator_cache, sizeof(ator_cache));
+ res = indirect_set_context(&ator, uctxs, nctxs, &iops);
+ if (likely(res == 0)) {
+ res = compat_call_syscall(nr, kparams);
+ indirect_unset_context(iops);
+ }
+ fsa_cleanup(&ator);
+
+ return res;
+}
+
Index: linux-2.6.mod/include/asm-x86_64/unistd.h
===================================================================
--- linux-2.6.mod.orig/include/asm-x86_64/unistd.h 2007-06-29 12:12:48.000000000 -0700
+++ linux-2.6.mod/include/asm-x86_64/unistd.h 2007-06-29 12:57:58.000000000 -0700
@@ -670,6 +670,7 @@
struct sigaction __user *oact,
size_t sigsetsize);
extern long call_syscall(unsigned int nr, const unsigned long *params);
+extern long compat_call_syscall(unsigned int nr, const unsigned long *params);

static inline int indirect_call_ok(unsigned int nr)
{
Index: linux-2.6.mod/arch/x86_64/ia32/ia32entry.S
===================================================================
--- linux-2.6.mod.orig/arch/x86_64/ia32/ia32entry.S 2007-06-29 12:12:41.000000000 -0700
+++ linux-2.6.mod/arch/x86_64/ia32/ia32entry.S 2007-06-29 12:57:58.000000000 -0700
@@ -392,6 +392,24 @@
CFI_ENDPROC
END(ia32_ptregs_common)

+ENTRY(compat_call_syscall)
+ movq $-ENOSYS, %rax
+ cmpl $(IA32_NR_syscalls-1), %edi
+ ja bad_sysc
+ mov %edi, %eax
+ movq %rsi, %r11
+ movq (%r11), %rdi
+ movq 8(%r11), %rsi
+ movq 16(%r11), %rdx
+ movq 24(%r11), %rcx
+ movq 32(%r11), %r8
+ movq 40(%r11), %r9
+ call *ia32_sys_call_table(,%rax,8)
+bad_sysc:
+ ret
+ENDPROC(compat_call_syscall)
+
+
.section .rodata,"a"
.align 8
ia32_sys_call_table:

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/