From 1feb8d2d7396748fb3bd6795d09bbfbdd4c03dff Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Thu, 14 Jul 2005 00:33:36 -0700 Subject: [PATCH] uml: workaround host bug in "TT mode vs. NPTL link fix" A big bug has been diagnosed on hosts running the SKAS patch and built with CONFIG_REGPARM, due to some missing prevent_tail_call(). On these hosts, this workaround is needed to avoid triggering that bug, because "to" is kept by GCC only in EBX, which is corrupted at the return of mmap2(). Since to trigger this bug int 0x80 must be used when doing the call, it rarely manifests itself, so I'd prefer to get this merged to workaround that host bug, since it should cause no functional change. Still, you might prefer to drop it, I'll leave this to you. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/sys-i386/unmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/um/sys-i386') diff --git a/arch/um/sys-i386/unmap.c b/arch/um/sys-i386/unmap.c index 136875263d27..1b0ad0e4adcd 100644 --- a/arch/um/sys-i386/unmap.c +++ b/arch/um/sys-i386/unmap.c @@ -15,7 +15,7 @@ int switcheroo(int fd, int prot, void *from, void *to, int size) if(munmap(to, size) < 0){ return(-1); } - if(mmap2(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) != to){ + if(mmap2(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) == (void*) -1 ){ return(-1); } if(munmap(from, size) < 0){ -- cgit v1.2.2 From 2e5e55923e315e8198f46f24f7ca37e1fd9aa102 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Thu, 14 Jul 2005 00:33:37 -0700 Subject: [PATCH] uml: consolidate modify_ldt *) Reorganize the two cases of sys_modify_ldt to share all the reasonably common code. *) Avoid memory allocation when unneeded (i.e. when we are writing and the passed buffer size is known), thus not returning ENOMEM (which isn't allowed for this syscall, even if there is no strict "specification"). *) Add copy_{from,to}_user to modify_ldt for TT mode. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/sys-i386/ldt.c | 114 +++++++++++++++++++++++++++---------------------- 1 file changed, 62 insertions(+), 52 deletions(-) (limited to 'arch/um/sys-i386') diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c index dc755b0b9db8..bd3c34aa52e5 100644 --- a/arch/um/sys-i386/ldt.c +++ b/arch/um/sys-i386/ldt.c @@ -4,96 +4,106 @@ */ #include "linux/config.h" +#include "linux/sched.h" #include "linux/slab.h" +#include "linux/types.h" #include "asm/uaccess.h" #include "asm/ptrace.h" +#include "asm/smp.h" +#include "asm/ldt.h" #include "choose-mode.h" #include "kern.h" +#include "mode_kern.h" #ifdef CONFIG_MODE_TT -extern int modify_ldt(int func, void *ptr, unsigned long bytecount); -/* XXX this needs copy_to_user and copy_from_user */ +extern int modify_ldt(int func, void *ptr, unsigned long bytecount); -int sys_modify_ldt_tt(int func, void __user *ptr, unsigned long bytecount) +static int do_modify_ldt_tt(int func, void *ptr, unsigned long bytecount) { - if (!access_ok(VERIFY_READ, ptr, bytecount)) - return -EFAULT; - return modify_ldt(func, ptr, bytecount); } + #endif #ifdef CONFIG_MODE_SKAS -extern int userspace_pid[]; +#include "skas.h" #include "skas_ptrace.h" -int sys_modify_ldt_skas(int func, void __user *ptr, unsigned long bytecount) +static int do_modify_ldt_skas(int func, void *ptr, unsigned long bytecount) { struct ptrace_ldt ldt; - void *buf; - int res, n; + u32 cpu; + int res; - buf = kmalloc(bytecount, GFP_KERNEL); - if(buf == NULL) - return(-ENOMEM); + ldt = ((struct ptrace_ldt) { .func = func, + .ptr = ptr, + .bytecount = bytecount }); - res = 0; + cpu = get_cpu(); + res = ptrace(PTRACE_LDT, userspace_pid[cpu], 0, (unsigned long) &ldt); + put_cpu(); + + return res; +} +#endif + +int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) +{ + struct user_desc info; + int res = 0; + void *buf = NULL; + void *p = NULL; /* What we pass to host. */ switch(func){ case 1: - case 0x11: - res = copy_from_user(buf, ptr, bytecount); - break; - } + case 0x11: /* write_ldt */ + /* Do this check now to avoid overflows. */ + if (bytecount != sizeof(struct user_desc)) { + res = -EINVAL; + goto out; + } + + if(copy_from_user(&info, ptr, sizeof(info))) { + res = -EFAULT; + goto out; + } - if(res != 0){ - res = -EFAULT; + p = &info; + break; + case 0: + case 2: /* read_ldt */ + + /* The use of info avoids kmalloc on the write case, not on the + * read one. */ + buf = kmalloc(bytecount, GFP_KERNEL); + if (!buf) { + res = -ENOMEM; + goto out; + } + p = buf; + default: + res = -ENOSYS; goto out; } - ldt = ((struct ptrace_ldt) { .func = func, - .ptr = buf, - .bytecount = bytecount }); -#warning Need to look up userspace_pid by cpu - res = ptrace(PTRACE_LDT, userspace_pid[0], 0, (unsigned long) &ldt); + res = CHOOSE_MODE_PROC(do_modify_ldt_tt, do_modify_ldt_skas, func, + p, bytecount); if(res < 0) goto out; switch(func){ case 0: case 2: - n = res; - res = copy_to_user(ptr, buf, n); - if(res != 0) + /* Modify_ldt was for reading and returned the number of read + * bytes.*/ + if(copy_to_user(ptr, p, res)) res = -EFAULT; - else - res = n; break; } - out: +out: kfree(buf); - return(res); -} -#endif - -int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) -{ - return(CHOOSE_MODE_PROC(sys_modify_ldt_tt, sys_modify_ldt_skas, func, - ptr, bytecount)); + return res; } - - - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ -- cgit v1.2.2 From 9057e9deee648cb2824d83b9eb7058edb5442a21 Mon Sep 17 00:00:00 2001 From: Bodo Stroesser Date: Thu, 28 Jul 2005 21:16:06 -0700 Subject: [PATCH] uml: Fix skas0 stub return It's wrong to pop a fixed number of words from stack before calling sigreturn, as the number depends on what code is generated by the compiler for the start of stub_segv_handler(). What we need is esp containing the address of sigcontext. So we explicitly load that pointer into esp. Signed-off-by: Bodo Stroesser Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/sys-i386/stub_segv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/um/sys-i386') diff --git a/arch/um/sys-i386/stub_segv.c b/arch/um/sys-i386/stub_segv.c index b251442ad0b1..68aeabe3a654 100644 --- a/arch/um/sys-i386/stub_segv.c +++ b/arch/um/sys-i386/stub_segv.c @@ -21,10 +21,10 @@ stub_segv_handler(int sig) __asm__("movl %0, %%eax ; int $0x80": : "g" (__NR_getpid)); __asm__("movl %%eax, %%ebx ; movl %0, %%eax ; movl %1, %%ecx ;" "int $0x80": : "g" (__NR_kill), "g" (SIGUSR1)); - /* Pop the frame pointer and return address since we need to leave + /* Load pointer to sigcontext into esp, since we need to leave * the stack in its original form when we do the sigreturn here, by * hand. */ - __asm__("popl %%eax ; popl %%eax ; popl %%eax ; movl %0, %%eax ; " - "int $0x80" : : "g" (__NR_sigreturn)); + __asm__("mov %0,%%esp ; movl %1, %%eax ; " + "int $0x80" : : "a" (sc), "g" (__NR_sigreturn)); } -- cgit v1.2.2