Esempio n. 1
0
File: signal.c Progetto: aldld/linux
int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
{
	unsigned long buf_val;
	void __user *buf;
	unsigned int tmpflags;
	unsigned int err = 0;

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

	get_user_try {

#ifdef CONFIG_X86_32
		set_user_gs(regs, 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(ax);

#ifdef CONFIG_X86_64
		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);
#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);
#endif /* CONFIG_X86_32 */

		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_val, &sc->fpstate);
		buf = (void __user *)buf_val;
	} get_user_catch(err);

	err |= fpu__restore_sig(buf, config_enabled(CONFIG_X86_32));

	force_iret();

	return err;
}
Esempio n. 2
0
int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
		       unsigned long *pax)
{
	void __user *buf;
	unsigned int tmpflags;
	unsigned int err = 0;

	/*                                                              */
	current_thread_info()->restart_block.fn = do_no_restart_syscall;

	get_user_try {

#ifdef CONFIG_X86_32
		set_user_gs(regs, GET_SEG(gs));
		COPY_SEG(fs);
		COPY_SEG(es);
		COPY_SEG(ds);
#endif /*               */

		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);
#endif /*               */

#ifdef CONFIG_X86_32
		COPY_SEG_CPL3(cs);
		COPY_SEG_CPL3(ss);
#else /*                */
		/*                                                                   
                                                                    
                                                                     */
		COPY_SEG_CPL3(cs);
#endif /*               */

		get_user_ex(tmpflags, &sc->flags);
		regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
		regs->orig_ax = -1;		/*                        */

		get_user_ex(buf, &sc->fpstate);
		err |= restore_i387_xstate(buf);

		get_user_ex(*pax, &sc->ax);
	} get_user_catch(err);

	return err;
}
Esempio n. 3
0
static int ia32_restore_sigcontext(struct pt_regs *regs,
                                   struct sigcontext_ia32 __user *sc,
                                   unsigned int *pax)
{
    unsigned int tmpflags, err = 0;
    void __user *buf;
    u32 tmp;

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

    get_user_try {
        /*
         * Reload fs and gs if they have changed in the signal
         * handler.  This does not handle long fs/gs base changes in
         * the handler, but does not clobber them at least in the
         * normal case.
         */
        RELOAD_SEG(gs);
        RELOAD_SEG(fs);
        RELOAD_SEG(ds);
        RELOAD_SEG(es);

        COPY(di);
        COPY(si);
        COPY(bp);
        COPY(sp);
        COPY(bx);
        COPY(dx);
        COPY(cx);
        COPY(ip);
        /* Don't touch extended registers */

        COPY_SEG_CPL3(cs);
        COPY_SEG_CPL3(ss);

        get_user_ex(tmpflags, &sc->flags);
        regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
        /* disable syscall checks */
        regs->orig_ax = -1;

        get_user_ex(tmp, &sc->fpstate);
        buf = compat_ptr(tmp);
        err |= restore_i387_xstate_ia32(buf);

        get_user_ex(*pax, &sc->ax);
    } get_user_catch(err);

    return err;
}
asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
				  stack_ia32_t __user *uoss_ptr,
				  struct pt_regs *regs)
{
	stack_t uss, uoss;
	int ret, err = 0;
	mm_segment_t seg;

	if (uss_ptr) {
		u32 ptr;

		memset(&uss, 0, sizeof(stack_t));
		if (!access_ok(VERIFY_READ, uss_ptr, sizeof(stack_ia32_t)))
			return -EFAULT;

		get_user_try {
			get_user_ex(ptr, &uss_ptr->ss_sp);
			get_user_ex(uss.ss_flags, &uss_ptr->ss_flags);
			get_user_ex(uss.ss_size, &uss_ptr->ss_size);
		} get_user_catch(err);

		if (err)
			return -EFAULT;
		uss.ss_sp = compat_ptr(ptr);
	}
	seg = get_fs();
	set_fs(KERNEL_DS);
	ret = do_sigaltstack(uss_ptr ? (const stack_t __force_user *)&uss : NULL, (stack_t __force_user *)&uoss, regs->sp);
	set_fs(seg);
	if (ret >= 0 && uoss_ptr)  {
		if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t)))
			return -EFAULT;

		put_user_try {
			put_user_ex(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp);
			put_user_ex(uoss.ss_flags, &uoss_ptr->ss_flags);
			put_user_ex(uoss.ss_size, &uoss_ptr->ss_size);
		} put_user_catch(err);

		if (err)
			ret = -EFAULT;
	}
	return ret;
}
static int ia32_restore_sigcontext(struct pt_regs *regs,
				   struct sigcontext_ia32 __user *sc,
				   unsigned int *pax)
{
	unsigned int tmpflags, err = 0;
	void __user *buf;
	u32 tmp;

	
	current_thread_info()->restart_block.fn = do_no_restart_syscall;

	get_user_try {
		RELOAD_SEG(gs);
		RELOAD_SEG(fs);
		RELOAD_SEG(ds);
		RELOAD_SEG(es);

		COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
		COPY(dx); COPY(cx); COPY(ip);
		

		COPY_SEG_CPL3(cs);
		COPY_SEG_CPL3(ss);

		get_user_ex(tmpflags, &sc->flags);
		regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
		
		regs->orig_ax = -1;

		get_user_ex(tmp, &sc->fpstate);
		buf = compat_ptr(tmp);
		err |= restore_i387_xstate_ia32(buf);

		get_user_ex(*pax, &sc->ax);
	} get_user_catch(err);

	return err;
}
int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
{
	int err = 0;
	u32 ptr32;

	if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
		return -EFAULT;

	get_user_try {
		get_user_ex(to->si_signo, &from->si_signo);
		get_user_ex(to->si_errno, &from->si_errno);
		get_user_ex(to->si_code, &from->si_code);

		get_user_ex(to->si_pid, &from->si_pid);
		get_user_ex(to->si_uid, &from->si_uid);
		get_user_ex(ptr32, &from->si_ptr);
		to->si_ptr = compat_ptr(ptr32);
	} get_user_catch(err);

	return err;
}