Example #1
0
int restore_i387_xstate(void __user *buf)
{
	struct task_struct *tsk = current;
	int err = 0;

	if (!buf) {
		if (used_math())
			goto clear;
		return 0;
	} else
		if (!access_ok(VERIFY_READ, buf, sig_xstate_size))
			return -EACCES;

	if (!used_math()) {
		err = init_fpu(tsk);
		if (err)
			return err;
	}

	user_fpu_begin();
	if (use_xsave())
		err = restore_user_xstate(buf);
	else
		err = fxrstor_checking((__force struct i387_fxsave_struct *)
				       buf);
	if (unlikely(err)) {
		/*
                                                          
                                      
   */
clear:
		clear_fpu(tsk);
		clear_used_math();
	}
	return err;
}
Example #2
0
static int
restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax)
{
	unsigned int err = 0;

	/* Always make any pending restarted system calls return -EINTR */
	current_thread_info()->restart_block.fn = do_no_restart_syscall;

#define COPY(x)		err |= __get_user(regs->x, &sc->x)

#define COPY_SEG(seg)							\
	{ unsigned short tmp;						\
	  err |= __get_user(tmp, &sc->seg);				\
	  regs->x##seg = tmp; }

#define COPY_SEG_STRICT(seg)						\
	{ unsigned short tmp;						\
	  err |= __get_user(tmp, &sc->seg);				\
	  regs->x##seg = tmp|3; }

#define GET_SEG(seg)							\
	{ unsigned short tmp;						\
	  err |= __get_user(tmp, &sc->seg);				\
	  loadsegment(seg,tmp); }

#define	FIX_EFLAGS	(X86_EFLAGS_AC | X86_EFLAGS_RF |		 \
			 X86_EFLAGS_OF | X86_EFLAGS_DF |		 \
			 X86_EFLAGS_TF | X86_EFLAGS_SF | X86_EFLAGS_ZF | \
			 X86_EFLAGS_AF | X86_EFLAGS_PF | X86_EFLAGS_CF)

	GET_SEG(gs);
	COPY_SEG(fs);
	COPY_SEG(es);
	COPY_SEG(ds);
	COPY(edi);
	COPY(esi);
	COPY(ebp);
	COPY(esp);
	COPY(ebx);
	COPY(edx);
	COPY(ecx);
	COPY(eip);
	COPY_SEG_STRICT(cs);
	COPY_SEG_STRICT(ss);
	
	{
		unsigned int tmpflags;
		err |= __get_user(tmpflags, &sc->eflags);
		regs->eflags = (regs->eflags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
		regs->orig_eax = -1;		/* disable syscall checks */
	}

	{
		struct _fpstate __user * buf;
		err |= __get_user(buf, &sc->fpstate);
		if (buf) {
			if (!access_ok(VERIFY_READ, buf, sizeof(*buf)))
				goto badframe;
			err |= restore_i387(buf);
		} else {
			struct task_struct *me = current;
			if (used_math()) {
				clear_fpu(me);
				clear_used_math();
			}
		}
	}

	err |= __get_user(*peax, &sc->eax);
	return err;

badframe:
	return 1;
}
Example #3
0
/*
 * Do a signal return; undo the signal stack.
 */
static int
restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
           unsigned long *pax)
{
    unsigned int err = 0;

    /* Always make any pending restarted system calls return -EINTR */
    current_thread_info()->restart_block.fn = do_no_restart_syscall;

#define COPY(x)        err |= __get_user(regs->x, &sc->x)

    COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
    COPY(dx); COPY(cx); COPY(ip);
    COPY(r8);
    COPY(r9);
    COPY(r10);
    COPY(r11);
    COPY(r12);
    COPY(r13);
    COPY(r14);
    COPY(r15);

    /* 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. */
    {
        unsigned cs;
        err |= __get_user(cs, &sc->cs);
        regs->cs = cs | 3;    /* Force into user mode */
    }

    {
        unsigned int tmpflags;
        err |= __get_user(tmpflags, &sc->flags);
        regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
        regs->orig_ax = -1;        /* disable syscall checks */
    }

    {
        struct _fpstate __user * buf;
        err |= __get_user(buf, &sc->fpstate);

        if (buf) {
            if (!access_ok(VERIFY_READ, buf, sizeof(*buf)))
                goto badframe;
            err |= restore_i387(buf);
        } else {
            struct task_struct *me = current;
            if (used_math()) {
                clear_fpu(me);
                clear_used_math();
            }
        }
    }

    err |= __get_user(*pax, &sc->ax);
    return err;

badframe:
    return 1;
}