From: Jeff Dike This fixes a couple of copy-user problems spotted by Al Viro. copy_sc_from_user_tt was doing a copy_from_user to do an in-kernel assignment. I commented this, at the request of Chris Wedgewood. sys_ipc had a void *__user ptr which should have been void __user *ptr. Finally, there were a couple of bogus __user annotations on unsigned longs, which were never going to be passed into copy_user. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton --- 25-akpm/arch/um/sys-i386/signal.c | 20 +++++++++++++------- 25-akpm/arch/um/sys-i386/syscalls.c | 2 +- 25-akpm/arch/um/sys-x86_64/signal.c | 2 +- 3 files changed, 15 insertions(+), 9 deletions(-) diff -puN arch/um/sys-i386/signal.c~uml-fix-some-usercopy-confusion arch/um/sys-i386/signal.c --- 25/arch/um/sys-i386/signal.c~uml-fix-some-usercopy-confusion 2005-03-07 22:16:11.000000000 -0800 +++ 25-akpm/arch/um/sys-i386/signal.c 2005-03-07 22:16:11.000000000 -0800 @@ -108,6 +108,15 @@ int copy_sc_to_user_skas(struct sigconte #endif #ifdef CONFIG_MODE_TT + +/* These copy a sigcontext to/from userspace. They copy the fpstate pointer, + * blowing away the old, good one. So, that value is saved, and then restored + * after the sigcontext copy. In copy_from, the variable holding the saved + * fpstate pointer, and the sigcontext that it should be restored to are both + * in the kernel, so we can just restore using an assignment. In copy_to, the + * saved pointer is in the kernel, but the sigcontext is in userspace, so we + * copy_to_user it. + */ int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from, int fpsize) { @@ -120,11 +129,9 @@ int copy_sc_from_user_tt(struct sigconte sigs = to->oldmask; err = copy_from_user(to, from, sizeof(*to)); to->oldmask = sigs; - if(to_fp != NULL){ - err |= copy_from_user(&to->fpstate, &to_fp, - sizeof(to->fpstate)); + to->fpstate = to_fp; + if(to_fp != NULL) err |= copy_from_user(to_fp, from_fp, fpsize); - } return(err); } @@ -138,8 +145,7 @@ int copy_sc_to_user_tt(struct sigcontext from_fp = from->fpstate; err = copy_to_user(to, from, sizeof(*to)); if(from_fp != NULL){ - err |= copy_to_user(&to->fpstate, &to_fp, - sizeof(to->fpstate)); + err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate)); err |= copy_to_user(to_fp, from_fp, fpsize); } return(err); @@ -303,7 +309,7 @@ int setup_signal_stack_si(unsigned long long sys_sigreturn(struct pt_regs regs) { - unsigned long __user sp = PT_REGS_SP(¤t->thread.regs); + unsigned long sp = PT_REGS_SP(¤t->thread.regs); struct sigframe __user *frame = (struct sigframe *)(sp - 8); sigset_t set; struct sigcontext __user *sc = &frame->sc; diff -puN arch/um/sys-i386/syscalls.c~uml-fix-some-usercopy-confusion arch/um/sys-i386/syscalls.c --- 25/arch/um/sys-i386/syscalls.c~uml-fix-some-usercopy-confusion 2005-03-07 22:16:11.000000000 -0800 +++ 25-akpm/arch/um/sys-i386/syscalls.c 2005-03-07 22:16:11.000000000 -0800 @@ -88,7 +88,7 @@ long sys_clone(unsigned long clone_flags * This is really horribly ugly. */ long sys_ipc (uint call, int first, int second, - int third, void *__user ptr, long fifth) + int third, void __user *ptr, long fifth) { int version, ret; diff -puN arch/um/sys-x86_64/signal.c~uml-fix-some-usercopy-confusion arch/um/sys-x86_64/signal.c --- 25/arch/um/sys-x86_64/signal.c~uml-fix-some-usercopy-confusion 2005-03-07 22:16:11.000000000 -0800 +++ 25-akpm/arch/um/sys-x86_64/signal.c 2005-03-07 22:16:11.000000000 -0800 @@ -237,7 +237,7 @@ int setup_signal_stack_si(unsigned long long sys_rt_sigreturn(struct pt_regs *regs) { - unsigned long __user sp = PT_REGS_SP(¤t->thread.regs); + unsigned long sp = PT_REGS_SP(¤t->thread.regs); struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(sp - 8); struct ucontext __user *uc = &frame->uc; _