Commit 98e3d45e authored by Hiroshi Shimamoto's avatar Hiroshi Shimamoto Committed by H. Peter Anvin
Browse files

x86: signal: use {get|put}_user_try and catch



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: default avatarHiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>
Signed-off-by: default avatarH. Peter Anvin <hpa@linux.intel.com>
parent fe40c0af
Loading
Loading
Loading
Loading
+154 −137
Original line number Diff line number Diff line
@@ -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_try {

#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_catch(err);

	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;

			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_catch(err);

	return err;
}
@@ -336,34 +343,31 @@ 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);
	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);
	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));
	if (err)
		return -EFAULT;

		/* 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);
		put_user_ex(restorer, &frame->pretcode);

		/*
		 * This is movl $__NR_rt_sigreturn, %ax ; int $0x80
@@ -372,7 +376,8 @@ 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);
		put_user_ex(*((u64 *)&rt_retcode), (u64 *)frame->retcode);
	} put_user_catch(err);

	if (err)
		return -EFAULT;
@@ -436,16 +441,17 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
			return -EFAULT;
	}

	put_user_try {
		/* 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,11 +459,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;
			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;