Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755981AbYLWFXo (ORCPT ); Tue, 23 Dec 2008 00:23:44 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751039AbYLWFXf (ORCPT ); Tue, 23 Dec 2008 00:23:35 -0500 Received: from gateway-1237.mvista.com ([63.81.120.158]:52176 "EHLO gateway-1237.mvista.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751242AbYLWFXd (ORCPT ); Tue, 23 Dec 2008 00:23:33 -0500 Message-ID: <495075D4.3070405@ct.jp.nec.com> Date: Mon, 22 Dec 2008 21:23:32 -0800 From: Hiroshi Shimamoto User-Agent: Thunderbird 2.0.0.18 (Windows/20081105) MIME-Version: 1.0 To: Ingo Molnar , Thomas Gleixner , "H. Peter Anvin" Cc: linux-kernel@vger.kernel.org Subject: [RFC -tip 3/4] x86: signal: use __{get|put}_user exception handling framework References: <49507534.5080401@ct.jp.nec.com> In-Reply-To: <49507534.5080401@ct.jp.nec.com> Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 13582 Lines: 402 From: Hiroshi Shimamoto Impact: cleanup Use __{get|put}_user exception handling framework. Signed-off-by: Hiroshi Shimamoto --- arch/x86/kernel/signal.c | 186 ++++++++++++++++++++++++--------------------- 1 files changed, 99 insertions(+), 87 deletions(-) diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 4fa5243..fcaa318 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -51,24 +51,24 @@ #endif #define COPY(x) { \ - err |= __get_user(regs->x, &sc->x); \ + __get_user_ex(regs->x, &sc->x); \ } #define COPY_SEG(seg) { \ unsigned short tmp; \ - err |= __get_user(tmp, &sc->seg); \ + __get_user_ex(tmp, &sc->seg); \ regs->seg = tmp; \ } #define COPY_SEG_CPL3(seg) { \ unsigned short tmp; \ - err |= __get_user(tmp, &sc->seg); \ + __get_user_ex(tmp, &sc->seg); \ regs->seg = tmp | 3; \ } #define GET_SEG(seg) { \ unsigned short tmp; \ - err |= __get_user(tmp, &sc->seg); \ + __get_user_ex(tmp, &sc->seg); \ loadsegment(seg, tmp); \ } @@ -83,6 +83,8 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, /* Always make any pending restarted system calls return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; + __get_user_ex_try(&err, -EFAULT); + #ifdef CONFIG_X86_32 GET_SEG(gs); COPY_SEG(fs); @@ -114,14 +116,16 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, COPY_SEG_CPL3(cs); #endif /* CONFIG_X86_32 */ - err |= __get_user(tmpflags, &sc->flags); + __get_user_ex(tmpflags, &sc->flags); regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); regs->orig_ax = -1; /* disable syscall checks */ - err |= __get_user(buf, &sc->fpstate); + __get_user_ex(buf, &sc->fpstate); err |= restore_i387_xstate(buf); - err |= __get_user(*pax, &sc->ax); + __get_user_ex(*pax, &sc->ax); + + __get_user_ex_catch(); return err; } @@ -131,57 +135,61 @@ setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate, { int err = 0; + __put_user_ex_try(&err, -EFAULT); + #ifdef CONFIG_X86_32 { unsigned int tmp; savesegment(gs, tmp); - err |= __put_user(tmp, (unsigned int __user *)&sc->gs); + __put_user_ex(tmp, (unsigned int __user *)&sc->gs); } - err |= __put_user(regs->fs, (unsigned int __user *)&sc->fs); - err |= __put_user(regs->es, (unsigned int __user *)&sc->es); - err |= __put_user(regs->ds, (unsigned int __user *)&sc->ds); + __put_user_ex(regs->fs, (unsigned int __user *)&sc->fs); + __put_user_ex(regs->es, (unsigned int __user *)&sc->es); + __put_user_ex(regs->ds, (unsigned int __user *)&sc->ds); #endif /* CONFIG_X86_32 */ - err |= __put_user(regs->di, &sc->di); - err |= __put_user(regs->si, &sc->si); - err |= __put_user(regs->bp, &sc->bp); - err |= __put_user(regs->sp, &sc->sp); - err |= __put_user(regs->bx, &sc->bx); - err |= __put_user(regs->dx, &sc->dx); - err |= __put_user(regs->cx, &sc->cx); - err |= __put_user(regs->ax, &sc->ax); + __put_user_ex(regs->di, &sc->di); + __put_user_ex(regs->si, &sc->si); + __put_user_ex(regs->bp, &sc->bp); + __put_user_ex(regs->sp, &sc->sp); + __put_user_ex(regs->bx, &sc->bx); + __put_user_ex(regs->dx, &sc->dx); + __put_user_ex(regs->cx, &sc->cx); + __put_user_ex(regs->ax, &sc->ax); #ifdef CONFIG_X86_64 - err |= __put_user(regs->r8, &sc->r8); - err |= __put_user(regs->r9, &sc->r9); - err |= __put_user(regs->r10, &sc->r10); - err |= __put_user(regs->r11, &sc->r11); - err |= __put_user(regs->r12, &sc->r12); - err |= __put_user(regs->r13, &sc->r13); - err |= __put_user(regs->r14, &sc->r14); - err |= __put_user(regs->r15, &sc->r15); + __put_user_ex(regs->r8, &sc->r8); + __put_user_ex(regs->r9, &sc->r9); + __put_user_ex(regs->r10, &sc->r10); + __put_user_ex(regs->r11, &sc->r11); + __put_user_ex(regs->r12, &sc->r12); + __put_user_ex(regs->r13, &sc->r13); + __put_user_ex(regs->r14, &sc->r14); + __put_user_ex(regs->r15, &sc->r15); #endif /* CONFIG_X86_64 */ - err |= __put_user(current->thread.trap_no, &sc->trapno); - err |= __put_user(current->thread.error_code, &sc->err); - err |= __put_user(regs->ip, &sc->ip); + __put_user_ex(current->thread.trap_no, &sc->trapno); + __put_user_ex(current->thread.error_code, &sc->err); + __put_user_ex(regs->ip, &sc->ip); #ifdef CONFIG_X86_32 - err |= __put_user(regs->cs, (unsigned int __user *)&sc->cs); - err |= __put_user(regs->flags, &sc->flags); - err |= __put_user(regs->sp, &sc->sp_at_signal); - err |= __put_user(regs->ss, (unsigned int __user *)&sc->ss); + __put_user_ex(regs->cs, (unsigned int __user *)&sc->cs); + __put_user_ex(regs->flags, &sc->flags); + __put_user_ex(regs->sp, &sc->sp_at_signal); + __put_user_ex(regs->ss, (unsigned int __user *)&sc->ss); #else /* !CONFIG_X86_32 */ - err |= __put_user(regs->flags, &sc->flags); - err |= __put_user(regs->cs, &sc->cs); - err |= __put_user(0, &sc->gs); - err |= __put_user(0, &sc->fs); + __put_user_ex(regs->flags, &sc->flags); + __put_user_ex(regs->cs, &sc->cs); + __put_user_ex(0, &sc->gs); + __put_user_ex(0, &sc->fs); #endif /* CONFIG_X86_32 */ - err |= __put_user(fpstate, &sc->fpstate); + __put_user_ex(fpstate, &sc->fpstate); /* non-iBCS2 extensions.. */ - err |= __put_user(mask, &sc->oldmask); - err |= __put_user(current->thread.cr2, &sc->cr2); + __put_user_ex(mask, &sc->oldmask); + __put_user_ex(current->thread.cr2, &sc->cr2); + + __put_user_ex_catch(); return err; } @@ -269,13 +277,14 @@ __setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, int err = 0; void __user *fpstate = NULL; + __put_user_ex_try(&err, -EFAULT); + frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) return -EFAULT; - if (__put_user(sig, &frame->sig)) - return -EFAULT; + __put_user_ex(sig, &frame->sig); if (setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0])) return -EFAULT; @@ -294,7 +303,7 @@ __setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, restorer = ka->sa.sa_restorer; /* Set up to return from userspace. */ - err |= __put_user(restorer, &frame->pretcode); + __put_user_ex(restorer, &frame->pretcode); /* * This is popl %eax ; movl $__NR_sigreturn, %eax ; int $0x80 @@ -303,10 +312,7 @@ __setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, * reasons and because gdb uses it as a signature to notice * signal handler stack frames. */ - err |= __put_user(*((u64 *)&retcode), (u64 *)frame->retcode); - - if (err) - return -EFAULT; + __put_user_ex(*((u64 *)&retcode), (u64 *)frame->retcode); /* Set up registers for signal handler */ regs->sp = (unsigned long)frame; @@ -320,7 +326,9 @@ __setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, regs->ss = __USER_DS; regs->cs = __USER_CS; - return 0; + __put_user_ex_catch(); + + return err; } static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, @@ -331,28 +339,30 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, int err = 0; void __user *fpstate = NULL; + __put_user_ex_try(&err, -EFAULT); + frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) return -EFAULT; - err |= __put_user(sig, &frame->sig); - err |= __put_user(&frame->info, &frame->pinfo); - err |= __put_user(&frame->uc, &frame->puc); + __put_user_ex(sig, &frame->sig); + __put_user_ex(&frame->info, &frame->pinfo); + __put_user_ex(&frame->uc, &frame->puc); err |= copy_siginfo_to_user(&frame->info, info); if (err) return -EFAULT; /* Create the ucontext. */ if (cpu_has_xsave) - err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags); + __put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags); else - err |= __put_user(0, &frame->uc.uc_flags); - err |= __put_user(0, &frame->uc.uc_link); - err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); - err |= __put_user(sas_ss_flags(regs->sp), + __put_user_ex(0, &frame->uc.uc_flags); + __put_user_ex(0, &frame->uc.uc_link); + __put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); + __put_user_ex(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags); - err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); + __put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size); err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate, regs, set->sig[0]); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); @@ -363,7 +373,7 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn); if (ka->sa.sa_flags & SA_RESTORER) restorer = ka->sa.sa_restorer; - err |= __put_user(restorer, &frame->pretcode); + __put_user_ex(restorer, &frame->pretcode); /* * This is movl $__NR_rt_sigreturn, %ax ; int $0x80 @@ -372,10 +382,7 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, * reasons and because gdb uses it as a signature to notice * signal handler stack frames. */ - err |= __put_user(*((u64 *)&rt_retcode), (u64 *)frame->retcode); - - if (err) - return -EFAULT; + __put_user_ex(*((u64 *)&rt_retcode), (u64 *)frame->retcode); /* Set up registers for signal handler */ regs->sp = (unsigned long)frame; @@ -389,7 +396,9 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, regs->ss = __USER_DS; regs->cs = __USER_CS; - return 0; + __put_user_ex_catch(); + + return err; } #else /* !CONFIG_X86_32 */ /* @@ -418,6 +427,8 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, int err = 0; struct task_struct *me = current; + __put_user_ex_try(&err, -EFAULT); + if (used_math()) { fp = get_stack(ka, regs->sp, sig_xstate_size); frame = (void __user *)round_down( @@ -438,14 +449,14 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* Create the ucontext. */ if (cpu_has_xsave) - err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags); + __put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags); else - err |= __put_user(0, &frame->uc.uc_flags); - err |= __put_user(0, &frame->uc.uc_link); - err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp); - err |= __put_user(sas_ss_flags(regs->sp), + __put_user_ex(0, &frame->uc.uc_flags); + __put_user_ex(0, &frame->uc.uc_link); + __put_user_ex(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp); + __put_user_ex(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags); - err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); + __put_user_ex(me->sas_ss_size, &frame->uc.uc_stack.ss_size); err |= setup_sigcontext(&frame->uc.uc_mcontext, fp, regs, set->sig[0]); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); @@ -453,15 +464,12 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, already in userspace. */ /* x86-64 should always use SA_RESTORER. */ if (ka->sa.sa_flags & SA_RESTORER) { - err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); + __put_user_ex(ka->sa.sa_restorer, &frame->pretcode); } else { /* could use a vstub here */ return -EFAULT; } - if (err) - return -EFAULT; - /* Set up registers for signal handler */ regs->di = sig; /* In case the signal handler was declared without prototypes */ @@ -479,7 +487,8 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, even if the handler happens to be interrupting 32-bit code. */ regs->cs = __USER_CS; - return 0; + __put_user_ex_catch(); + return err; } #endif /* CONFIG_X86_32 */ @@ -511,31 +520,34 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, struct k_sigaction new_ka, old_ka; int ret; + __put_user_ex_try(&ret, -EFAULT); + __get_user_ex_try(&ret, -EFAULT); + if (act) { old_sigset_t mask; - if (!access_ok(VERIFY_READ, act, sizeof(*act)) || - __get_user(new_ka.sa.sa_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) + if (!access_ok(VERIFY_READ, act, sizeof(*act))) return -EFAULT; - - __get_user(new_ka.sa.sa_flags, &act->sa_flags); - __get_user(mask, &act->sa_mask); + __get_user_ex(new_ka.sa.sa_handler, &act->sa_handler); + __get_user_ex(new_ka.sa.sa_flags, &act->sa_flags); + __get_user_ex(mask, &act->sa_mask); + __get_user_ex(new_ka.sa.sa_restorer, &act->sa_restorer); siginitset(&new_ka.sa.sa_mask, mask); } ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); if (!ret && oact) { - if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || - __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) + if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact))) return -EFAULT; - - __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); + __put_user_ex(old_ka.sa.sa_handler, &oact->sa_handler); + __put_user_ex(old_ka.sa.sa_flags, &oact->sa_flags); + __put_user_ex(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); + __put_user_ex(old_ka.sa.sa_restorer, &oact->sa_restorer); } + __get_user_ex_catch(); + __put_user_ex_catch(); return ret; } #endif /* CONFIG_X86_32 */ -- 1.6.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/