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; }
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; }
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; }