]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
x86: signal: use {get|put}_user_try and catch
authorHiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>
Fri, 23 Jan 2009 23:50:10 +0000 (15:50 -0800)
committerH. Peter Anvin <hpa@linux.intel.com>
Sat, 24 Jan 2009 01:17:38 +0000 (17:17 -0800)
Impact: use new framework

Use {get|put}_user_try, catch, and _ex in arch/x86/kernel/signal.c.

Note: this patch contains "WARNING: line over 80 characters", because when
introducing new block I insert an indent to avoid mistakes by edit.

Signed-off-by: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
arch/x86/kernel/signal.c

index 89bb7668041d63067c1a2b3fd1210ab9ccfcb49d..cf34eb37fbeed58d4309bf7f5557358213f7e8fb 100644 (file)
 #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,45 +83,49 @@ 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_try {
+
 #ifdef CONFIG_X86_32
-       GET_SEG(gs);
-       COPY_SEG(fs);
-       COPY_SEG(es);
-       COPY_SEG(ds);
+               GET_SEG(gs);
+               COPY_SEG(fs);
+               COPY_SEG(es);
+               COPY_SEG(ds);
 #endif /* CONFIG_X86_32 */
 
-       COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
-       COPY(dx); COPY(cx); COPY(ip);
+               COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
+               COPY(dx); COPY(cx); COPY(ip);
 
 #ifdef CONFIG_X86_64
-       COPY(r8);
-       COPY(r9);
-       COPY(r10);
-       COPY(r11);
-       COPY(r12);
-       COPY(r13);
-       COPY(r14);
-       COPY(r15);
+               COPY(r8);
+               COPY(r9);
+               COPY(r10);
+               COPY(r11);
+               COPY(r12);
+               COPY(r13);
+               COPY(r14);
+               COPY(r15);
 #endif /* CONFIG_X86_64 */
 
 #ifdef CONFIG_X86_32
-       COPY_SEG_CPL3(cs);
-       COPY_SEG_CPL3(ss);
+               COPY_SEG_CPL3(cs);
+               COPY_SEG_CPL3(ss);
 #else /* !CONFIG_X86_32 */
-       /* Kernel saves and restores only the CS segment register on signals,
-        * which is the bare minimum needed to allow mixed 32/64-bit code.
-        * App's signal handler can save/restore other segments if needed. */
-       COPY_SEG_CPL3(cs);
+               /* Kernel saves and restores only the CS segment register on signals,
+                * which is the bare minimum needed to allow mixed 32/64-bit code.
+                * App's signal handler can save/restore other segments if needed. */
+               COPY_SEG_CPL3(cs);
 #endif /* CONFIG_X86_32 */
 
-       err |= __get_user(tmpflags, &sc->flags);
-       regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
-       regs->orig_ax = -1;             /* disable syscall checks */
+               get_user_ex(tmpflags, &sc->flags);
+               regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
+               regs->orig_ax = -1;             /* disable syscall checks */
+
+               get_user_ex(buf, &sc->fpstate);
+               err |= restore_i387_xstate(buf);
 
-       err |= __get_user(buf, &sc->fpstate);
-       err |= restore_i387_xstate(buf);
+               get_user_ex(*pax, &sc->ax);
+       } get_user_catch(err);
 
-       err |= __get_user(*pax, &sc->ax);
        return err;
 }
 
@@ -131,57 +135,60 @@ setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,
 {
        int err = 0;
 
+       put_user_try {
+
 #ifdef CONFIG_X86_32
-       {
-               unsigned int tmp;
+               {
+                       unsigned int tmp;
 
-               savesegment(gs, tmp);
-               err |= __put_user(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);
+                       savesegment(gs, tmp);
+                       put_user_ex(tmp, (unsigned int __user *)&sc->gs);
+               }
+               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);
+               /* non-iBCS2 extensions.. */
+               put_user_ex(mask, &sc->oldmask);
+               put_user_ex(current->thread.cr2, &sc->cr2);
+       } put_user_catch(err);
 
        return err;
 }
@@ -336,43 +343,41 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        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);
-       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);
-       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),
-                         &frame->uc.uc_stack.ss_flags);
-       err |= __put_user(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));
-       if (err)
-               return -EFAULT;
+       put_user_try {
+               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);
 
-       /* Set up to return from userspace.  */
-       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);
+               /* Create the ucontext.  */
+               if (cpu_has_xsave)
+                       put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
+               else
+                       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);
+               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));
+
+               /* Set up to return from userspace.  */
+               restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn);
+               if (ka->sa.sa_flags & SA_RESTORER)
+                       restorer = ka->sa.sa_restorer;
+               put_user_ex(restorer, &frame->pretcode);
 
-       /*
-        * This is movl $__NR_rt_sigreturn, %ax ; int $0x80
-        *
-        * WE DO NOT USE IT ANY MORE! It's only left here for historical
-        * reasons and because gdb uses it as a signature to notice
-        * signal handler stack frames.
-        */
-       err |= __put_user(*((u64 *)&rt_retcode), (u64 *)frame->retcode);
+               /*
+                * This is movl $__NR_rt_sigreturn, %ax ; int $0x80
+                *
+                * WE DO NOT USE IT ANY MORE! It's only left here for historical
+                * reasons and because gdb uses it as a signature to notice
+                * signal handler stack frames.
+                */
+               put_user_ex(*((u64 *)&rt_retcode), (u64 *)frame->retcode);
+       } put_user_catch(err);
 
        if (err)
                return -EFAULT;
@@ -436,28 +441,30 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                        return -EFAULT;
        }
 
-       /* Create the ucontext.  */
-       if (cpu_has_xsave)
-               err |= __put_user(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),
-                         &frame->uc.uc_stack.ss_flags);
-       err |= __put_user(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));
-
-       /* Set up to return from userspace.  If provided, use a stub
-          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);
-       } else {
-               /* could use a vstub here */
-               return -EFAULT;
-       }
+       put_user_try {
+               /* Create the ucontext.  */
+               if (cpu_has_xsave)
+                       put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
+               else
+                       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);
+               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));
+
+               /* Set up to return from userspace.  If provided, use a stub
+                  already in userspace.  */
+               /* x86-64 should always use SA_RESTORER. */
+               if (ka->sa.sa_flags & SA_RESTORER) {
+                       put_user_ex(ka->sa.sa_restorer, &frame->pretcode);
+               } else {
+                       /* could use a vstub here */
+                       err |= -EFAULT;
+               }
+       } put_user_catch(err);
 
        if (err)
                return -EFAULT;
@@ -509,31 +516,41 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
              struct old_sigaction __user *oact)
 {
        struct k_sigaction new_ka, old_ka;
-       int ret;
+       int ret = 0;
 
        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_try {
+                       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);
+               } get_user_catch(ret);
+
+               if (ret)
+                       return -EFAULT;
                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_try {
+                       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);
+               } put_user_catch(ret);
+
+               if (ret)
+                       return -EFAULT;
        }
 
        return ret;