diff options
author | Tony Luck <tony.luck@intel.com> | 2005-07-15 16:59:00 -0700 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2005-07-15 16:59:00 -0700 |
commit | 08848e446bcd2130c26945be966446389d25bcc2 (patch) | |
tree | e31e6ec7a1d9e8f6bbf8cdee2692eb42f4869f47 /arch/um/sys-i386/ldt.c | |
parent | 46906c4415f88cebfad530917bada0835d651824 (diff) | |
parent | 38d84c3bd6dd22bdb1f797c87006931133d71aea (diff) | |
download | linux-stable-08848e446bcd2130c26945be966446389d25bcc2.tar.gz linux-stable-08848e446bcd2130c26945be966446389d25bcc2.tar.bz2 linux-stable-08848e446bcd2130c26945be966446389d25bcc2.zip |
Auto merge with /home/aegl/GIT/linus
Diffstat (limited to 'arch/um/sys-i386/ldt.c')
-rw-r--r-- | arch/um/sys-i386/ldt.c | 114 |
1 files changed, 62 insertions, 52 deletions
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: - */ |