static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; int err = 0; frame = get_sigframe(ka, regs, sizeof(*frame)); err = -EFAULT; if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) goto out; /* * Set up the return code: * * mov r8, __NR_rt_sigreturn * scall * * Note: This will blow up since we're using a non-executable * stack. Better use SA_RESTORER. */ #if __NR_rt_sigreturn > 127 # error __NR_rt_sigreturn must be < 127 to fit in a short mov #endif err = __put_user(0x3008d733 | (__NR_rt_sigreturn << 20), &frame->retcode); err |= copy_siginfo_to_user(&frame->info, info); /* Set up the ucontext */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(NULL, &frame->uc.uc_link); err |= __save_altstack(&frame->uc.uc_stack, regs->sp); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) goto out; regs->r12 = sig; regs->r11 = (unsigned long) &frame->info; regs->r10 = (unsigned long) &frame->uc; regs->sp = (unsigned long) frame; if (ka->sa.sa_flags & SA_RESTORER) regs->lr = (unsigned long)ka->sa.sa_restorer; else { printk(KERN_NOTICE "[%s:%d] did not set SA_RESTORER\n", current->comm, current->pid); regs->lr = (unsigned long) &frame->retcode; } pr_debug("SIG deliver [%s:%d]: sig=%d sp=0x%lx pc=0x%lx->0x%p lr=0x%lx\n", current->comm, current->pid, sig, regs->sp, regs->pc, ka->sa.sa_handler, regs->lr); regs->pc = (unsigned long) ka->sa.sa_handler; out: return err; }
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; int err = 0; int signal; frame = get_sigframe(ka, regs->spu, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; signal = current_thread_info()->exec_domain && current_thread_info()->exec_domain->signal_invmap && sig < 32 ? current_thread_info()->exec_domain->signal_invmap[sig] : sig; err |= __put_user(signal, &frame->sig); if (err) goto give_sigsegv; err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->uc, &frame->puc); err |= copy_siginfo_to_user(&frame->info, info); if (err) goto give_sigsegv; /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_link); err |= __save_altstack(&frame->uc.uc_stack, regs->spu); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) goto give_sigsegv; /* Set up to return from userspace. */ regs->lr = (unsigned long)ka->sa.sa_restorer; /* Set up registers for signal handler */ regs->spu = (unsigned long)frame; regs->r0 = signal; /* Arg for signal handler */ regs->r1 = (unsigned long)&frame->info; regs->r2 = (unsigned long)&frame->uc; regs->bpc = (unsigned long)ka->sa.sa_handler; set_fs(USER_DS); #if DEBUG_SIG printk("SIG deliver (%s:%d): sp=%p pc=%p\n", current->comm, current->pid, frame, regs->pc); #endif return 0; give_sigsegv: force_sigsegv(sig, current); return -EFAULT; }
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame = get_sigframe(ksig, regs, sizeof(*frame)); int err = 0; if (!frame) return 1; err |= copy_siginfo_to_user(&frame->info, &ksig->info); __put_user_error(0, &frame->sig.uc.uc_flags, err); __put_user_error(NULL, &frame->sig.uc.uc_link, err); err |= __save_altstack(&frame->sig.uc.uc_stack, regs->ARM_sp); err |= setup_sigframe(&frame->sig, regs, set); if (err == 0) err = setup_return(regs, ksig, frame->sig.retcode, frame); if (err == 0) { /* * For realtime signals we must also set the second and third * arguments for the signal handler. * -- Peter Maydell <*****@*****.**> 2000-12-06 */ regs->ARM_r1 = (unsigned long)&frame->info; regs->ARM_r2 = (unsigned long)&frame->sig.uc; } return err; }
static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; int err = 0; frame = get_sigframe(ka, regs); if (!frame) return 1; __put_user_error(0, &frame->uc.uc_flags, err); __put_user_error(0, &frame->uc.uc_link, err); err |= __save_altstack(&frame->uc.uc_stack, regs->sp); err |= setup_sigframe(frame, regs, set); if (err == 0) { setup_return(regs, ka, frame, usig); if (ka->sa.sa_flags & SA_SIGINFO) { err |= copy_siginfo_to_user(&frame->info, info); regs->regs[1] = (unsigned long)&frame->info; regs->regs[2] = (unsigned long)&frame->uc; } } return err; }
static int setup_rt_frame(struct ksignal *ksig, sigset_t * set, struct pt_regs *regs) { struct rt_sigframe __user *frame = get_sigframe(ksig, regs, sizeof(*frame)); int err = 0; if (!access_ok(frame, sizeof(*frame))) return -EFAULT; __put_user_error(0, &frame->uc.uc_flags, err); __put_user_error(NULL, &frame->uc.uc_link, err); err |= __save_altstack(&frame->uc.uc_stack, regs->sp); err |= setup_sigframe(frame, regs, set); if (err == 0) { setup_return(regs, ksig, frame); if (ksig->ka.sa.sa_flags & SA_SIGINFO) { err |= copy_siginfo_to_user(&frame->info, &ksig->info); regs->uregs[1] = (unsigned long)&frame->info; regs->uregs[2] = (unsigned long)&frame->uc; } } return err; }
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs * regs) { int err = 0; rt_sigframe __user *frame; frame = get_sigframe(ka, regs, sizeof(rt_sigframe)); if (frame == (void __user *) -1UL) goto give_sigsegv; if (copy_siginfo_to_user(&frame->info, info)) goto give_sigsegv; /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(NULL, &frame->uc.uc_link); err |= __save_altstack(&frame->uc.uc_stack, regs->gprs[15]); err |= save_sigregs(regs, &frame->uc.uc_mcontext); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) goto give_sigsegv; /* Set up to return from userspace. If provided, use a stub already in userspace. */ if (ka->sa.sa_flags & SA_RESTORER) { regs->gprs[14] = (unsigned long) ka->sa.sa_restorer | PSW_ADDR_AMODE; } else { regs->gprs[14] = (unsigned long) frame->retcode | PSW_ADDR_AMODE; if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn, (u16 __user *)(frame->retcode))) goto give_sigsegv; } /* Set up backchain. */ if (__put_user(regs->gprs[15], (addr_t __user *) frame)) goto give_sigsegv; /* Set up registers for signal handler */ regs->gprs[15] = (unsigned long) frame; /* Force default amode and default user address space control. */ regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA | (PSW_USER_BITS & PSW_MASK_ASC) | (regs->psw.mask & ~PSW_MASK_ASC); regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE; regs->gprs[2] = map_signal(sig); regs->gprs[3] = (unsigned long) &frame->info; regs->gprs[4] = (unsigned long) &frame->uc; regs->gprs[5] = task_thread_info(current)->last_break; return 0; give_sigsegv: force_sigsegv(sig, current); return -EFAULT; }
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) { unsigned long restorer; struct rt_sigframe __user *frame; int err = 0, sig = ksig->sig; frame = get_sigframe(&ksig->ka, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto err; /* Always write at least the signal number for the stack backtracer. */ if (ksig->ka.sa.sa_flags & SA_SIGINFO) { /* At sigreturn time, restore the callee-save registers too. */ err |= copy_siginfo_to_user(&frame->info, &ksig->info); regs->flags |= PT_FLAGS_RESTORE_REGS; } else { err |= __put_user(ksig->info.si_signo, &frame->info.si_signo); } /* Create the ucontext. */ err |= __clear_user(&frame->save_area, sizeof(frame->save_area)); err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(NULL, &frame->uc.uc_link); err |= __save_altstack(&frame->uc.uc_stack, regs->sp); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) goto err; restorer = VDSO_SYM(&__vdso_rt_sigreturn); if (ksig->ka.sa.sa_flags & SA_RESTORER) restorer = (unsigned long) ksig->ka.sa.sa_restorer; /* * Set up registers for signal handler. * Registers that we don't modify keep the value they had from * user-space at the time we took the signal. * We always pass siginfo and mcontext, regardless of SA_SIGINFO, * since some things rely on this (e.g. glibc's debug/segfault.c). */ regs->pc = (unsigned long) ksig->ka.sa.sa_handler; regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */ regs->sp = (unsigned long) frame; regs->lr = restorer; regs->regs[0] = (unsigned long) sig; regs->regs[1] = (unsigned long) &frame->info; regs->regs[2] = (unsigned long) &frame->uc; regs->flags |= PT_FLAGS_CALLER_SAVES; return 0; err: trace_unhandled_signal("bad sigreturn frame", regs, (unsigned long)frame, SIGSEGV); return -EFAULT; }
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { unsigned long oldsp, r26, err = 0; struct rt_sigframe __user *frame; oldsp = rdusp(); frame = get_sigframe(ka, oldsp, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) return -EFAULT; err |= copy_siginfo_to_user(&frame->info, info); /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_link); err |= __put_user(set->sig[0], &frame->uc.uc_osf_sigmask); err |= __save_altstack(&frame->uc.uc_stack, oldsp); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0], oldsp); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) return -EFAULT; /* Set up to return from userspace. If provided, use a stub already in userspace. */ if (ka->ka_restorer) { r26 = (unsigned long) ka->ka_restorer; } else { err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0); err |= __put_user(INSN_LDI_R0+__NR_rt_sigreturn, frame->retcode+1); err |= __put_user(INSN_CALLSYS, frame->retcode+2); imb(); r26 = (unsigned long) frame->retcode; } if (err) return -EFAULT; /* "Return" to the handler */ regs->r26 = r26; regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler; regs->r16 = sig; /* a0: signal number */ regs->r17 = (unsigned long) &frame->info; /* a1: siginfo pointer */ regs->r18 = (unsigned long) &frame->uc; /* a2: ucontext pointer */ wrusp((unsigned long) frame); #if DEBUG_SIG printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", current->comm, current->pid, frame, regs->pc, regs->r26); #endif return 0; }
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; int err; unsigned long code; frame = get_sigframe(&ksig->ka, regs->REG_SP, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) return -EFAULT; err = copy_siginfo_to_user(&frame->info, &ksig->info); /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, (unsigned long __user *)&frame->uc.uc_link); err |= __save_altstack(&frame->uc.uc_stack, regs->REG_SP); err |= setup_sigcontext(&frame->uc.uc_mcontext, 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. */ /* MOV D1Re0 (D1.0), #__NR_rt_sigreturn */ code = 0x03000004 | (__NR_rt_sigreturn << 3); err |= __put_user(code, (unsigned long __user *)(&frame->retcode[0])); /* SWITCH #__METAG_SW_SYS */ code = __METAG_SW_ENCODING(SYS); err |= __put_user(code, (unsigned long __user *)(&frame->retcode[1])); if (err) return -EFAULT; /* Set up registers for signal handler */ regs->REG_RTP = (unsigned long) frame->retcode; regs->REG_SP = (unsigned long) frame + sizeof(*frame); regs->REG_ARG1 = ksig->sig; regs->REG_ARG2 = (unsigned long) &frame->info; regs->REG_ARG3 = (unsigned long) &frame->uc; regs->REG_PC = (unsigned long) ksig->ka.sa.sa_handler; pr_debug("SIG deliver (%s:%d): sp=%p pc=%08x pr=%08x\n", current->comm, current->pid, frame, regs->REG_PC, regs->REG_RTP); /* Now pass size of 'new code' into sigtramp so we can do a more * effective cache flush - directed rather than 'full flush'. */ flush_cache_sigtramp(regs->REG_RTP, sizeof(frame->retcode)); return 0; }
/* grab and setup a signal frame. * * basically we stack a lot of state info, and arrange for the * user-mode program to return to the kernel using either a * trampoline which performs the syscall sigreturn, or a provided * user-mode trampoline. */ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe *frame; unsigned long return_ip; int err = 0; frame = get_sigframe(ksig, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) return -EFAULT; /* Create siginfo. */ if (ksig->ka.sa.sa_flags & SA_SIGINFO) err |= copy_siginfo_to_user(&frame->info, &ksig->info); /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(NULL, &frame->uc.uc_link); err |= __save_altstack(&frame->uc.uc_stack, regs->sp); err |= setup_sigcontext(regs, &frame->uc.uc_mcontext); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) return -EFAULT; /* trampoline - the desired return ip is the retcode itself */ return_ip = (unsigned long)&frame->retcode; /* This is: l.ori r11,r0,__NR_sigreturn l.sys 1 */ err |= __put_user(0xa960, (short *)(frame->retcode + 0)); err |= __put_user(__NR_rt_sigreturn, (short *)(frame->retcode + 2)); err |= __put_user(0x20000001, (unsigned long *)(frame->retcode + 4)); err |= __put_user(0x15000000, (unsigned long *)(frame->retcode + 8)); if (err) return -EFAULT; /* TODO what is the current->exec_domain stuff and invmap ? */ /* Set up registers for signal handler */ regs->pc = (unsigned long)ksig->ka.sa.sa_handler; /* what we enter NOW */ regs->gpr[9] = (unsigned long)return_ip; /* what we enter LATER */ regs->gpr[3] = (unsigned long)ksig->sig; /* arg 1: signo */ regs->gpr[4] = (unsigned long)&frame->info; /* arg 2: (siginfo_t*) */ regs->gpr[5] = (unsigned long)&frame->uc; /* arg 3: ucontext */ /* actually move the usp to reflect the stacked frame */ regs->sp = (unsigned long)frame; return 0; }
static int setup_rt_frame(void *sig_return, struct k_sigaction *ka, struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info) { struct rt_sigframe __user *frame; int err = 0; frame = get_sigframe(ka, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) goto give_sigsegv; /* Create siginfo. */ err |= copy_siginfo_to_user(&frame->rs_info, info); /* Create the ucontext. */ err |= __put_user(0, &frame->rs_uc.uc_flags); err |= __put_user(NULL, &frame->rs_uc.uc_link); err |= __save_altstack(&frame->rs_uc.uc_stack, regs->regs[29]); err |= setup_sigcontext(regs, &frame->rs_uc.uc_mcontext); err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set)); if (err) goto give_sigsegv; /* * Arguments to signal handler: * * a0 = signal number * a1 = 0 (should be cause) * a2 = pointer to ucontext * * $25 and c0_epc point to the signal handler, $29 points to * the struct rt_sigframe. */ regs->regs[ 4] = signr; regs->regs[ 5] = (unsigned long) &frame->rs_info; regs->regs[ 6] = (unsigned long) &frame->rs_uc; regs->regs[29] = (unsigned long) frame; regs->regs[31] = (unsigned long) sig_return; regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", current->comm, current->pid, frame, regs->cp0_epc, regs->regs[31]); return 0; give_sigsegv: force_sigsegv(signr, current); return -EFAULT; }
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe *frame; int err = 0; unsigned char *ret; frame = get_sigframe(ksig, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) return -EFAULT; if (ksig->ka.sa.sa_flags & SA_SIGINFO) err |= copy_siginfo_to_user(&frame->info, &ksig->info); /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_link); err |= __save_altstack(&frame->uc.uc_stack, rdusp()); err |= setup_sigcontext(&frame->uc.uc_mcontext, 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. */ ret = frame->retcode; if (ksig->ka.sa.sa_flags & SA_RESTORER) ret = (unsigned char *)(ksig->ka.sa.sa_restorer); else { /* sub.l er0,er0; mov.b #__NR_rt_sigreturn,r0l; trapa #0 */ err |= __put_user(0x1a80f800 + (__NR_rt_sigreturn & 0xff), (unsigned long *)(frame->retcode + 0)); err |= __put_user(0x5700, (unsigned short *)(frame->retcode + 4)); } err |= __put_user(ret, &frame->pretcode); if (err) return -EFAULT; /* Set up registers for signal handler */ wrusp((unsigned long) frame); regs->pc = (unsigned long) ksig->ka.sa.sa_handler; regs->er0 = ksig->sig; regs->er1 = (unsigned long)&(frame->info); regs->er2 = (unsigned long)&frame->uc; regs->er5 = current->mm->start_data; /* GOT base */ return 0; }
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; int err = 0; int sig = ksig->sig; frame = get_sigframe(ksig, regs->spu, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) return -EFAULT; err |= __put_user(sig, &frame->sig); if (err) return -EFAULT; err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->uc, &frame->puc); err |= copy_siginfo_to_user(&frame->info, &ksig->info); if (err) return -EFAULT; /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_link); err |= __save_altstack(&frame->uc.uc_stack, regs->spu); err |= setup_sigcontext(&frame->uc.uc_mcontext, 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. */ regs->lr = (unsigned long)ksig->ka.sa.sa_restorer; /* Set up registers for signal handler */ regs->spu = (unsigned long)frame; regs->r0 = sig; /* Arg for signal handler */ regs->r1 = (unsigned long)&frame->info; regs->r2 = (unsigned long)&frame->uc; regs->bpc = (unsigned long)ksig->ka.sa.sa_handler; #if DEBUG_SIG printk("SIG deliver (%s:%d): sp=%p pc=%p\n", current->comm, current->pid, frame, regs->pc); #endif return 0; }
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; long err = 0; frame = get_sigframe(ksig, regs, sizeof(*frame)); if (!access_ok(frame, sizeof(*frame))) return -EFAULT; err |= copy_siginfo_to_user(&frame->info, &ksig->info); /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(NULL, &frame->uc.uc_link); err |= __save_altstack(&frame->uc.uc_stack, regs->sp); err |= setup_sigcontext(frame, regs); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) return -EFAULT; /* Set up to return from userspace. */ regs->ra = (unsigned long)VDSO_SYMBOL( current->mm->context.vdso, rt_sigreturn); /* * Set up registers for signal handler. * Registers that we don't modify keep the value they had from * user-space at the time we took the signal. * We always pass siginfo and mcontext, regardless of SA_SIGINFO, * since some things rely on this (e.g. glibc's debug/segfault.c). */ regs->sepc = (unsigned long)ksig->ka.sa.sa_handler; regs->sp = (unsigned long)frame; regs->a0 = ksig->sig; /* a0: signal number */ regs->a1 = (unsigned long)(&frame->info); /* a1: siginfo pointer */ regs->a2 = (unsigned long)(&frame->uc); /* a2: ucontext pointer */ #if DEBUG_SIG pr_info("SIG deliver (%s:%d): sig=%d pc=%p ra=%p sp=%p\n", current->comm, task_pid_nr(current), ksig->sig, (void *)regs->sepc, (void *)regs->ra, frame); #endif return 0; }
/* * Setup signal stack frame with siginfo structure */ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { int err = 0; struct rt_sigframe __user *frame; struct hexagon_vdso *vdso = current->mm->context.vdso; frame = get_sigframe(ka, regs, sizeof(struct rt_sigframe)); if (!access_ok(VERIFY_WRITE, frame, sizeof(struct rt_sigframe))) goto sigsegv; if (copy_siginfo_to_user(&frame->info, info)) goto sigsegv; /* The on-stack signal trampoline is no longer executed; * however, the libgcc signal frame unwinding code checks for * the presence of these two numeric magic values. */ err |= __put_user(0x7800d166, &frame->tramp[0]); err |= __put_user(0x5400c004, &frame->tramp[1]); err |= setup_sigcontext(regs, &frame->uc.uc_mcontext); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); err |= __save_altstack(&frame->uc.uc_stack, user_stack_pointer(regs)); if (err) goto sigsegv; /* Load r0/r1 pair with signumber/siginfo pointer... */ regs->r0100 = ((unsigned long long)((unsigned long)&frame->info) << 32) | (unsigned long long)signr; regs->r02 = (unsigned long) &frame->uc; regs->r31 = (unsigned long) vdso->rt_signal_trampoline; pt_psp(regs) = (unsigned long) frame; pt_set_elr(regs, (unsigned long)ka->sa.sa_handler); return 0; sigsegv: force_sigsegv(signr, current); return -EFAULT; }
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe *frame; int err = 0; struct csky_vdso *vdso = current->mm->context.vdso; frame = get_sigframe(ksig, regs, sizeof(*frame)); if (!access_ok(frame, sizeof(*frame))) return -EFAULT; err |= copy_siginfo_to_user(&frame->info, &ksig->info); /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(NULL, &frame->uc.uc_link); err |= __save_altstack(&frame->uc.uc_stack, regs->usp); err |= setup_sigcontext(frame, regs); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) return -EFAULT; /* Set up to return from userspace. */ regs->lr = (unsigned long)(vdso->rt_signal_retcode); /* * Set up registers for signal handler. * Registers that we don't modify keep the value they had from * user-space at the time we took the signal. * We always pass siginfo and mcontext, regardless of SA_SIGINFO, * since some things rely on this (e.g. glibc's debug/segfault.c). */ regs->pc = (unsigned long)ksig->ka.sa.sa_handler; regs->usp = (unsigned long)frame; regs->a0 = ksig->sig; /* a0: signal number */ regs->a1 = (unsigned long)(&(frame->info)); /* a1: siginfo pointer */ regs->a2 = (unsigned long)(&(frame->uc)); /* a2: ucontext pointer */ return 0; }
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; int err = 0; frame = get_sigframe(ksig, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) return 1; err |= __clear_user(&frame->uc, sizeof(frame->uc)); err |= __save_altstack(&frame->uc.uc_stack, regs->sp); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); /* set return address for signal handler to trampoline */ regs->ra = sigreturn_tramp; /* Set up registers for returning to signal handler */ /* entry point */ regs->ea = (unsigned long)ksig->ka.sa.sa_handler - 4; /* stack pointer */ regs->sp = (unsigned long)frame - 4; /* Signal handler arguments */ regs->r1 = ksig->sig; /* first argument = signum */ regs->r2 = (unsigned long)&frame->info; regs->r3 = (unsigned long)&frame->uc; #if DEBUG_SIG printk("SIG deliver (%s:%d): frame=%p, sp=%p ra=%08lx ea=%08lx, signal(r1)=%d\n", current->comm, current->pid, frame, regs->sp, regs->ra, regs->ea, sig); #endif return 0; }
static int setup_rt_frame(int signo, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *sf; unsigned int magic = 0; int err = 0; sf = get_sigframe(ka, regs, sizeof(struct rt_sigframe)); if (!sf) return 1; /* * w/o SA_SIGINFO, struct ucontext is partially populated (only * uc_mcontext/uc_sigmask) for kernel's normal user state preservation * during signal handler execution. This works for SA_SIGINFO as well * although the semantics are now overloaded (the same reg state can be * inspected by userland: but are they allowed to fiddle with it ? */ err |= stash_usr_regs(sf, regs, set); /* * SA_SIGINFO requires 3 args to signal handler: * #1: sig-no (common to any handler) * #2: struct siginfo * #3: struct ucontext (completely populated) */ if (unlikely(ka->sa.sa_flags & SA_SIGINFO)) { err |= copy_siginfo_to_user(&sf->info, info); err |= __put_user(0, &sf->uc.uc_flags); err |= __put_user(NULL, &sf->uc.uc_link); err |= __save_altstack(&sf->uc.uc_stack, regs->sp); /* setup args 2 and 3 for user mode handler */ regs->r1 = (unsigned long)&sf->info; regs->r2 = (unsigned long)&sf->uc; /* * small optim to avoid unconditonally calling do_sigaltstack * in sigreturn path, now that we only have rt_sigreturn */ magic = MAGIC_SIGALTSTK; } err |= __put_user(magic, &sf->sigret_magic); if (err) return err; /* #1 arg to the user Signal handler */ regs->r0 = map_sig(signo); /* setup PC of user space signal handler */ regs->ret = (unsigned long)ka->sa.sa_handler; /* * handler returns using sigreturn stub provided already by userpsace */ BUG_ON(!(ka->sa.sa_flags & SA_RESTORER)); regs->blink = (unsigned long)ka->sa.sa_restorer; /* User Stack for signal handler will be above the frame just carved */ regs->sp = (unsigned long)sf; /* * Bug 94183, Clear the DE bit, so that when signal handler * starts to run, it doesn't use BTA */ regs->status32 &= ~STATUS_DE_MASK; regs->status32 |= STATUS_L_MASK; return err; }
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; int err = 0, sig = ksig->sig; unsigned long address = 0; #ifdef CONFIG_MMU pmd_t *pmdp; pte_t *ptep; #endif frame = get_sigframe(ksig, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) return -EFAULT; if (ksig->ka.sa.sa_flags & SA_SIGINFO) err |= copy_siginfo_to_user(&frame->info, &ksig->info); /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(NULL, &frame->uc.uc_link); err |= __save_altstack(&frame->uc.uc_stack, regs->r1); err |= setup_sigcontext(&frame->uc.uc_mcontext, 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. */ /* minus 8 is offset to cater for "rtsd r15,8" */ /* addi r12, r0, __NR_sigreturn */ err |= __put_user(0x31800000 | __NR_rt_sigreturn , frame->tramp + 0); /* brki r14, 0x8 */ err |= __put_user(0xb9cc0008, frame->tramp + 1); /* Return from sighandler will jump to the tramp. Negative 8 offset because return is rtsd r15, 8 */ regs->r15 = ((unsigned long)frame->tramp)-8; address = ((unsigned long)frame->tramp); #ifdef CONFIG_MMU pmdp = pmd_offset(pud_offset( pgd_offset(current->mm, address), address), address); preempt_disable(); ptep = pte_offset_map(pmdp, address); if (pte_present(*ptep)) { address = (unsigned long) page_address(pte_page(*ptep)); /* MS: I need add offset in page */ address += ((unsigned long)frame->tramp) & ~PAGE_MASK; /* MS address is virtual */ address = __virt_to_phys(address); invalidate_icache_range(address, address + 8); flush_dcache_range(address, address + 8); } pte_unmap(ptep); preempt_enable(); #else flush_icache_range(address, address + 8); flush_dcache_range(address, address + 8); #endif if (err) return -EFAULT; /* Set up registers for signal handler */ regs->r1 = (unsigned long) frame; /* Signal handler args: */ regs->r5 = sig; /* arg 0: signum */ regs->r6 = (unsigned long) &frame->info; /* arg 1: siginfo */ regs->r7 = (unsigned long) &frame->uc; /* arg2: ucontext */ /* Offset to handle microblaze rtid r14, 0 */ regs->pc = (unsigned long)ksig->ka.sa.sa_handler; #ifdef DEBUG_SIG pr_info("SIG deliver (%s:%d): sp=%p pc=%08lx\n", current->comm, current->pid, frame, regs->pc); #endif return 0; }
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; int err = 0; frame = get_sigframe(ka, regs->regs[15], sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; err |= copy_siginfo_to_user(&frame->info, info); /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(NULL, &frame->uc.uc_link); err |= __save_altstack(&frame->uc.uc_stack, regs->regs[15]); err |= setup_sigcontext(&frame->uc.uc_mcontext, 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. */ if (ka->sa.sa_flags & SA_RESTORER) { regs->pr = (unsigned long) ka->sa.sa_restorer; #ifdef CONFIG_VSYSCALL } else if (likely(current->mm->context.vdso)) { regs->pr = VDSO_SYM(&__kernel_rt_sigreturn); #endif } else { /* Generate return code (system call to rt_sigreturn) */ err |= __put_user(MOVW(7), &frame->retcode[0]); err |= __put_user(TRAP_NOARG, &frame->retcode[1]); err |= __put_user(OR_R0_R0, &frame->retcode[2]); err |= __put_user(OR_R0_R0, &frame->retcode[3]); err |= __put_user(OR_R0_R0, &frame->retcode[4]); err |= __put_user(OR_R0_R0, &frame->retcode[5]); err |= __put_user(OR_R0_R0, &frame->retcode[6]); err |= __put_user((__NR_rt_sigreturn), &frame->retcode[7]); regs->pr = (unsigned long) frame->retcode; flush_icache_range(regs->pr, regs->pr + sizeof(frame->retcode)); } if (err) goto give_sigsegv; /* Set up registers for signal handler */ regs->regs[15] = (unsigned long) frame; regs->regs[4] = sig; /* Arg for signal handler */ regs->regs[5] = (unsigned long) &frame->info; regs->regs[6] = (unsigned long) &frame->uc; if (current->personality & FDPIC_FUNCPTRS) { struct fdpic_func_descriptor __user *funcptr = (struct fdpic_func_descriptor __user *)ka->sa.sa_handler; err |= __get_user(regs->pc, &funcptr->text); err |= __get_user(regs->regs[12], &funcptr->GOT); } else regs->pc = (unsigned long)ka->sa.sa_handler; if (err) goto give_sigsegv; set_fs(USER_DS); pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n", current->comm, task_pid_nr(current), frame, regs->pc, regs->pr); return 0; give_sigsegv: force_sigsegv(sig, current); return -EFAULT; }
/* * set up a realtime signal frame */ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; int rsig, sig = ksig->sig; frame = get_sigframe(ksig, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) return -EFAULT; rsig = sig; if (sig < 32 && current_thread_info()->exec_domain && current_thread_info()->exec_domain->signal_invmap) rsig = current_thread_info()->exec_domain->signal_invmap[sig]; if (__put_user(rsig, &frame->sig) || __put_user(&frame->info, &frame->pinfo) || __put_user(&frame->uc, &frame->puc) || copy_siginfo_to_user(&frame->info, &ksig->info)) return -EFAULT; /* create the ucontext. */ if (__put_user(0, &frame->uc.uc_flags) || __put_user(0, &frame->uc.uc_link) || __save_altstack(&frame->uc.uc_stack, regs->sp) || setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpuctx, regs, set->sig[0]) || __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set))) return -EFAULT; /* set up to return from userspace. If provided, use a stub already in * userspace */ if (ksig->ka.sa.sa_flags & SA_RESTORER) { if (__put_user(ksig->ka.sa.sa_restorer, &frame->pretcode)) return -EFAULT; } else { if (__put_user((void(*)(void))frame->retcode, &frame->pretcode) || /* This is mov $,d0; syscall 0 */ __put_user(0x2c, (char *)(frame->retcode + 0)) || __put_user(__NR_rt_sigreturn, (char *)(frame->retcode + 1)) || __put_user(0x00, (char *)(frame->retcode + 2)) || __put_user(0xf0, (char *)(frame->retcode + 3)) || __put_user(0xe0, (char *)(frame->retcode + 4))) return -EFAULT; flush_icache_range((u_long) frame->retcode, (u_long) frame->retcode + 5); } /* Set up registers for signal handler */ regs->sp = (unsigned long) frame; regs->pc = (unsigned long) ksig->ka.sa.sa_handler; regs->d0 = sig; regs->d1 = (long) &frame->info; #if DEBUG_SIG printk(KERN_DEBUG "SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", sig, current->comm, current->pid, frame, regs->pc, frame->pretcode); #endif return 0; }
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; unsigned long return_ip; int err = 0; frame = get_sigframe(ksig, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) return -EFAULT; err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->uc, &frame->puc); err |= copy_siginfo_to_user(&frame->info, &ksig->info); if (err) return -EFAULT; /* Clear all the bits of the ucontext we don't use. */ err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext)); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); err |= __save_altstack(&frame->uc.uc_stack, rdusp()); if (err) return -EFAULT; /* Set up to return from userspace. If provided, use a stub already in userspace. */ if (ksig->ka.sa.sa_flags & SA_RESTORER) { return_ip = (unsigned long)ksig->ka.sa.sa_restorer; } else { /* trampoline - the desired return ip is the retcode itself */ return_ip = (unsigned long)&frame->retcode; /* This is movu.w __NR_rt_sigreturn, r9; break 13; */ err |= __put_user(0x9c5f, (short __user *)(frame->retcode+0)); err |= __put_user(__NR_rt_sigreturn, (short __user *)(frame->retcode+2)); err |= __put_user(0xe93d, (short __user *)(frame->retcode+4)); } if (err) return -EFAULT; /* Set up registers for signal handler */ /* What we enter NOW */ regs->irp = (unsigned long) ksig->ka.sa.sa_handler; /* What we enter LATER */ regs->srp = return_ip; /* First argument is signo */ regs->r10 = ksig->sig; /* Second argument is (siginfo_t *) */ regs->r11 = (unsigned long)&frame->info; /* Third argument is unused */ regs->r12 = 0; /* Actually move the usp to reflect the stacked frame */ wrusp((unsigned long)frame); return 0; }
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; unsigned long uc_flags, restorer; size_t frame_size; frame_size = sizeof(struct rt_sigframe) - sizeof(_sigregs_ext); /* * gprs_high are only present for a 31-bit task running on * a 64-bit kernel (see compat_signal.c) but the space for * gprs_high need to be allocated if vector registers are * included in the signal frame on a 31-bit system. */ uc_flags = 0; #ifdef CONFIG_64BIT if (MACHINE_HAS_VX) { frame_size += sizeof(_sigregs_ext); if (current->thread.vxrs) uc_flags |= UC_VXRS; } #endif frame = get_sigframe(&ksig->ka, regs, frame_size); if (frame == (void __user *) -1UL) return -EFAULT; /* Set up backchain. */ if (__put_user(regs->gprs[15], (addr_t __user *) frame)) return -EFAULT; /* Set up to return from userspace. If provided, use a stub already in userspace. */ if (ksig->ka.sa.sa_flags & SA_RESTORER) { restorer = (unsigned long) ksig->ka.sa.sa_restorer | PSW_ADDR_AMODE; } else { __u16 __user *svc = &frame->svc_insn; if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn, svc)) return -EFAULT; restorer = (unsigned long) svc | PSW_ADDR_AMODE; } /* Create siginfo on the signal stack */ if (copy_siginfo_to_user(&frame->info, &ksig->info)) return -EFAULT; /* Store registers needed to create the signal frame */ store_sigregs(); /* Create ucontext on the signal stack. */ if (__put_user(uc_flags, &frame->uc.uc_flags) || __put_user(NULL, &frame->uc.uc_link) || __save_altstack(&frame->uc.uc_stack, regs->gprs[15]) || save_sigregs(regs, &frame->uc.uc_mcontext) || __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)) || save_sigregs_ext(regs, &frame->uc.uc_mcontext_ext)) return -EFAULT; /* Set up registers for signal handler */ regs->gprs[14] = restorer; regs->gprs[15] = (unsigned long) frame; /* Force default amode and default user address space control. */ regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA | (PSW_USER_BITS & PSW_MASK_ASC) | (regs->psw.mask & ~PSW_MASK_ASC); regs->psw.addr = (unsigned long) ksig->ka.sa.sa_handler | PSW_ADDR_AMODE; regs->gprs[2] = map_signal(ksig->sig); regs->gprs[3] = (unsigned long) &frame->info; regs->gprs[4] = (unsigned long) &frame->uc; regs->gprs[5] = task_thread_info(current)->last_break; return 0; }
int handle_rt_signal64(struct ksignal *ksig, sigset_t *set, struct task_struct *tsk) { struct rt_sigframe __user *frame; unsigned long newsp = 0; long err = 0; struct pt_regs *regs = tsk->thread.regs; BUG_ON(tsk != current); frame = get_sigframe(ksig, get_tm_stackpointer(tsk), sizeof(*frame), 0); if (unlikely(frame == NULL)) goto badframe; err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->uc, &frame->puc); err |= copy_siginfo_to_user(&frame->info, &ksig->info); if (err) goto badframe; /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __save_altstack(&frame->uc.uc_stack, regs->gpr[1]); #ifdef CONFIG_PPC_TRANSACTIONAL_MEM if (MSR_TM_ACTIVE(regs->msr)) { /* The ucontext_t passed to userland points to the second * ucontext_t (for transactional state) with its uc_link ptr. */ err |= __put_user(&frame->uc_transact, &frame->uc.uc_link); err |= setup_tm_sigcontexts(&frame->uc.uc_mcontext, &frame->uc_transact.uc_mcontext, tsk, ksig->sig, NULL, (unsigned long)ksig->ka.sa.sa_handler); } else #endif { err |= __put_user(0, &frame->uc.uc_link); err |= setup_sigcontext(&frame->uc.uc_mcontext, tsk, ksig->sig, NULL, (unsigned long)ksig->ka.sa.sa_handler, 1); } err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) goto badframe; /* Make sure signal handler doesn't get spurious FP exceptions */ tsk->thread.fp_state.fpscr = 0; /* Set up to return from userspace. */ if (vdso64_rt_sigtramp && tsk->mm->context.vdso_base) { regs->link = tsk->mm->context.vdso_base + vdso64_rt_sigtramp; } else { err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]); if (err) goto badframe; regs->link = (unsigned long) &frame->tramp[0]; } /* Allocate a dummy caller frame for the signal handler. */ newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE; err |= put_user(regs->gpr[1], (unsigned long __user *)newsp); /* Set up "regs" so we "return" to the signal handler. */ if (is_elf2_task()) { regs->nip = (unsigned long) ksig->ka.sa.sa_handler; regs->gpr[12] = regs->nip; } else { /* Handler is *really* a pointer to the function descriptor for * the signal routine. The first entry in the function * descriptor is the entry address of signal and the second * entry is the TOC value we need to use. */ func_descr_t __user *funct_desc_ptr = (func_descr_t __user *) ksig->ka.sa.sa_handler; err |= get_user(regs->nip, &funct_desc_ptr->entry); err |= get_user(regs->gpr[2], &funct_desc_ptr->toc); } /* enter the signal handler in native-endian mode */ regs->msr &= ~MSR_LE; regs->msr |= (MSR_KERNEL & MSR_LE); regs->gpr[1] = newsp; regs->gpr[3] = ksig->sig; regs->result = 0; if (ksig->ka.sa.sa_flags & SA_SIGINFO) { err |= get_user(regs->gpr[4], (unsigned long __user *)&frame->pinfo); err |= get_user(regs->gpr[5], (unsigned long __user *)&frame->puc); regs->gpr[6] = (unsigned long) frame; } else { regs->gpr[4] = (unsigned long)&frame->uc.uc_mcontext; } if (err) goto badframe; return 0; badframe: if (show_unhandled_signals) printk_ratelimited(regs->msr & MSR_64BIT ? fmt64 : fmt32, tsk->comm, tsk->pid, "setup_rt_frame", (long)frame, regs->nip, regs->link); return 1; }
static int setup_rt_frame(struct ksignal *kig, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; int err = 0, sig = ksig->sig; frame = get_sigframe(&ksig->ka, regs->regs[REG_SP], sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) return -EFAULT; err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->uc, &frame->puc); err |= copy_siginfo_to_user(&frame->info, &ksig->info); /* Give up earlier as i386, in case */ if (err) return -EFAULT; /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_link); err |= __save_altstack(&frame->uc.uc_stack, regs->regs[REG_SP]); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); /* Give up earlier as i386, in case */ if (err) return -EFAULT; /* Set up to return from userspace. If provided, use a stub already in userspace. */ if (ksig->ka.sa.sa_flags & SA_RESTORER) { /* * On SH5 all edited pointers are subject to NEFF */ DEREF_REG_PR = neff_sign_extend((unsigned long) ksig->ka.sa.sa_restorer | 0x1); } else { /* * Different approach on SH5. * . Endianness independent asm code gets placed in entry.S . * This is limited to four ASM instructions corresponding * to two long longs in size. * . err checking is done on the else branch only * . flush_icache_range() is called upon __put_user() only * . all edited pointers are subject to NEFF * . being code, linker turns ShMedia bit on, always * dereference index -1. */ DEREF_REG_PR = neff_sign_extend((unsigned long) frame->retcode | 0x01); if (__copy_to_user(frame->retcode, (void *)((unsigned long)sa_default_rt_restorer & (~1)), 16) != 0) return -EFAULT; /* Cohere the trampoline with the I-cache. */ flush_icache_range(DEREF_REG_PR-1, DEREF_REG_PR-1+15); } /* * Set up registers for signal handler. * All edited pointers are subject to NEFF. */ regs->regs[REG_SP] = neff_sign_extend((unsigned long)frame); regs->regs[REG_ARG1] = sig; /* Arg for signal handler */ regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->info; regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->uc.uc_mcontext; regs->pc = neff_sign_extend((unsigned long)ksig->ka.sa.sa_handler); pr_debug("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n", sig, current->comm, current->pid, frame, regs->pc >> 32, regs->pc & 0xffffffff, DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff); return 0; }
int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { /* Handler is *really* a pointer to the function descriptor for * the signal routine. The first entry in the function * descriptor is the entry address of signal and the second * entry is the TOC value we need to use. */ func_descr_t __user *funct_desc_ptr; struct rt_sigframe __user *frame; unsigned long newsp = 0; long err = 0; frame = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*frame), 0); if (unlikely(frame == NULL)) goto badframe; err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->uc, &frame->puc); err |= copy_siginfo_to_user(&frame->info, info); if (err) goto badframe; /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __save_altstack(&frame->uc.uc_stack, regs->gpr[1]); #ifdef CONFIG_PPC_TRANSACTIONAL_MEM if (MSR_TM_ACTIVE(regs->msr)) { /* The ucontext_t passed to userland points to the second * ucontext_t (for transactional state) with its uc_link ptr. */ err |= __put_user(&frame->uc_transact, &frame->uc.uc_link); err |= setup_tm_sigcontexts(&frame->uc.uc_mcontext, &frame->uc_transact.uc_mcontext, regs, signr, NULL, (unsigned long)ka->sa.sa_handler); } else #endif { err |= __put_user(0, &frame->uc.uc_link); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, signr, NULL, (unsigned long)ka->sa.sa_handler, 1); } err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) goto badframe; /* Make sure signal handler doesn't get spurious FP exceptions */ current->thread.fp_state.fpscr = 0; #ifdef CONFIG_PPC_TRANSACTIONAL_MEM /* Remove TM bits from thread's MSR. The MSR in the sigcontext * just indicates to userland that we were doing a transaction, but we * don't want to return in transactional state: */ regs->msr &= ~MSR_TS_MASK; #endif /* Set up to return from userspace. */ if (vdso64_rt_sigtramp && current->mm->context.vdso_base) { regs->link = current->mm->context.vdso_base + vdso64_rt_sigtramp; } else { err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]); if (err) goto badframe; regs->link = (unsigned long) &frame->tramp[0]; } funct_desc_ptr = (func_descr_t __user *) ka->sa.sa_handler; /* Allocate a dummy caller frame for the signal handler. */ newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE; err |= put_user(regs->gpr[1], (unsigned long __user *)newsp); /* Set up "regs" so we "return" to the signal handler. */ err |= get_user(regs->nip, &funct_desc_ptr->entry); /* enter the signal handler in big-endian mode */ regs->msr &= ~MSR_LE; regs->gpr[1] = newsp; err |= get_user(regs->gpr[2], &funct_desc_ptr->toc); regs->gpr[3] = signr; regs->result = 0; if (ka->sa.sa_flags & SA_SIGINFO) { err |= get_user(regs->gpr[4], (unsigned long __user *)&frame->pinfo); err |= get_user(regs->gpr[5], (unsigned long __user *)&frame->puc); regs->gpr[6] = (unsigned long) frame; } else { regs->gpr[4] = (unsigned long)&frame->uc.uc_mcontext; } if (err) goto badframe; return 1; badframe: #if DEBUG_SIG printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); #endif if (show_unhandled_signals) printk_ratelimited(regs->msr & MSR_64BIT ? fmt64 : fmt32, current->comm, current->pid, "setup_rt_frame", (long)frame, regs->nip, regs->link); force_sigsegv(signr, current); return 0; }
static long setup_frame(struct ksignal *ksig, sigset_t *set, struct sigscratch *scr) { extern char __kernel_sigtramp[]; unsigned long tramp_addr, new_rbs = 0, new_sp; struct sigframe __user *frame; long err; new_sp = scr->pt.r12; tramp_addr = (unsigned long) __kernel_sigtramp; if (ksig->ka.sa.sa_flags & SA_ONSTACK) { int onstack = sas_ss_flags(new_sp); if (onstack == 0) { new_sp = current->sas_ss_sp + current->sas_ss_size; /* * We need to check for the register stack being on the * signal stack separately, because it's switched * separately (memory stack is switched in the kernel, * register stack is switched in the signal trampoline). */ if (!rbs_on_sig_stack(scr->pt.ar_bspstore)) new_rbs = ALIGN(current->sas_ss_sp, sizeof(long)); } else if (onstack == SS_ONSTACK) { unsigned long check_sp; /* * If we are on the alternate signal stack and would * overflow it, don't. Return an always-bogus address * instead so we will die with SIGSEGV. */ check_sp = (new_sp - sizeof(*frame)) & -STACK_ALIGN; if (!likely(on_sig_stack(check_sp))) return force_sigsegv_info(ksig->sig, (void __user *) check_sp); } } frame = (void __user *) ((new_sp - sizeof(*frame)) & -STACK_ALIGN); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) return force_sigsegv_info(ksig->sig, frame); err = __put_user(ksig->sig, &frame->arg0); err |= __put_user(&frame->info, &frame->arg1); err |= __put_user(&frame->sc, &frame->arg2); err |= __put_user(new_rbs, &frame->sc.sc_rbs_base); err |= __put_user(0, &frame->sc.sc_loadrs); /* initialize to zero */ err |= __put_user(ksig->ka.sa.sa_handler, &frame->handler); err |= copy_siginfo_to_user(&frame->info, &ksig->info); err |= __save_altstack(&frame->sc.sc_stack, scr->pt.r12); err |= setup_sigcontext(&frame->sc, set, scr); if (unlikely(err)) return force_sigsegv_info(ksig->sig, frame); scr->pt.r12 = (unsigned long) frame - 16; /* new stack pointer */ scr->pt.ar_fpsr = FPSR_DEFAULT; /* reset fpsr for signal handler */ scr->pt.cr_iip = tramp_addr; ia64_psr(&scr->pt)->ri = 0; /* start executing in first slot */ ia64_psr(&scr->pt)->be = 0; /* force little-endian byte-order */ /* * Force the interruption function mask to zero. This has no effect when a * system-call got interrupted by a signal (since, in that case, scr->pt_cr_ifs is * ignored), but it has the desirable effect of making it possible to deliver a * signal with an incomplete register frame (which happens when a mandatory RSE * load faults). Furthermore, it has no negative effect on the getting the user's * dirty partition preserved, because that's governed by scr->pt.loadrs. */ scr->pt.cr_ifs = (1UL << 63); /* * Note: this affects only the NaT bits of the scratch regs (the ones saved in * pt_regs), which is exactly what we want. */ scr->scratch_unat = 0; /* ensure NaT bits of r12 is clear */ #if DEBUG_SIG printk("SIG deliver (%s:%d): sig=%d sp=%lx ip=%lx handler=%p\n", current->comm, current->pid, ksig->sig, scr->pt.r12, frame->sc.sc_ip, frame->handler); #endif return 0; }
static int setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs, sigset_t *oldset) { struct rt_signal_frame __user *sf; int sigframe_size, wsaved; void __user *tail; unsigned int psr; int err; synchronize_user_stack(); wsaved = current_thread_info()->w_saved; sigframe_size = sizeof(*sf); if (used_math()) sigframe_size += sizeof(__siginfo_fpu_t); if (wsaved) sigframe_size += sizeof(__siginfo_rwin_t); sf = (struct rt_signal_frame __user *) get_sigframe(ksig, regs, sigframe_size); if (invalid_frame_pointer(sf, sigframe_size)) { do_exit(SIGILL); return -EINVAL; } tail = sf + 1; err = __put_user(regs->pc, &sf->regs.pc); err |= __put_user(regs->npc, &sf->regs.npc); err |= __put_user(regs->y, &sf->regs.y); psr = regs->psr; if (used_math()) psr |= PSR_EF; err |= __put_user(psr, &sf->regs.psr); err |= __copy_to_user(&sf->regs.u_regs, regs->u_regs, sizeof(regs->u_regs)); err |= __put_user(0, &sf->extra_size); if (psr & PSR_EF) { __siginfo_fpu_t __user *fp = tail; tail += sizeof(*fp); err |= save_fpu_state(regs, fp); err |= __put_user(fp, &sf->fpu_save); } else { err |= __put_user(0, &sf->fpu_save); } if (wsaved) { __siginfo_rwin_t __user *rwp = tail; tail += sizeof(*rwp); err |= save_rwin_state(wsaved, rwp); err |= __put_user(rwp, &sf->rwin_save); } else { err |= __put_user(0, &sf->rwin_save); } err |= __copy_to_user(&sf->mask, &oldset->sig[0], sizeof(sigset_t)); /* Setup sigaltstack */ err |= __save_altstack(&sf->stack, regs->u_regs[UREG_FP]); if (!wsaved) { err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP], sizeof(struct reg_window32)); } else { struct reg_window32 *rp; rp = ¤t_thread_info()->reg_window[wsaved - 1]; err |= __copy_to_user(sf, rp, sizeof(struct reg_window32)); } err |= copy_siginfo_to_user(&sf->info, &ksig->info); if (err) return err; regs->u_regs[UREG_FP] = (unsigned long) sf; regs->u_regs[UREG_I0] = ksig->sig; regs->u_regs[UREG_I1] = (unsigned long) &sf->info; regs->u_regs[UREG_I2] = (unsigned long) &sf->regs; regs->pc = (unsigned long) ksig->ka.sa.sa_handler; regs->npc = (regs->pc + 4); if (ksig->ka.ka_restorer) regs->u_regs[UREG_I7] = (unsigned long)ksig->ka.ka_restorer; else { regs->u_regs[UREG_I7] = (unsigned long)(&(sf->insns[0]) - 2); /* mov __NR_sigreturn, %g1 */ err |= __put_user(0x821020d8, &sf->insns[0]); /* t 0x10 */ err |= __put_user(0x91d02010, &sf->insns[1]); if (err) return err; /* Flush instruction space. */ flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0])); } return 0; }
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set) { struct rt_sigframe __user *frame; int sig = ksig->sig; frame = get_sigframe(ksig, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) return -EFAULT; if (__put_user(sig, &frame->sig) || __put_user(&frame->info, &frame->pinfo) || __put_user(&frame->uc, &frame->puc)) return -EFAULT; if (copy_siginfo_to_user(&frame->info, &ksig->info)) return -EFAULT; /* Create the ucontext. */ if (__put_user(0, &frame->uc.uc_flags) || __put_user(NULL, &frame->uc.uc_link) || __save_altstack(&frame->uc.uc_stack, __frame->sp)) return -EFAULT; if (setup_sigcontext(&frame->uc.uc_mcontext, set->sig[0])) return -EFAULT; if (__copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set))) return -EFAULT; /* Set up to return from userspace. If provided, use a stub * already in userspace. */ if (ksig->ka.sa.sa_flags & SA_RESTORER) { if (__put_user(ksig->ka.sa.sa_restorer, &frame->pretcode)) return -EFAULT; } else { /* Set up the following code on the stack: * setlos #__NR_sigreturn,gr7 * tira gr0,0 */ if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) || __put_user(0x8efc0000|__NR_rt_sigreturn, &frame->retcode[0]) || __put_user(0xc0700000, &frame->retcode[1])) return -EFAULT; flush_icache_range((unsigned long) frame->retcode, (unsigned long) (frame->retcode + 2)); } /* Set up registers for signal handler */ if (current->personality & FDPIC_FUNCPTRS) { struct fdpic_func_descriptor __user *funcptr = (struct fdpic_func_descriptor __user *) ksig->ka.sa.sa_handler; struct fdpic_func_descriptor desc; if (copy_from_user(&desc, funcptr, sizeof(desc))) return -EFAULT; __frame->pc = desc.text; __frame->gr15 = desc.GOT; } else { __frame->pc = (unsigned long) ksig->ka.sa.sa_handler; __frame->gr15 = 0; } __frame->sp = (unsigned long) frame; __frame->lr = (unsigned long) &frame->retcode; __frame->gr8 = sig; __frame->gr9 = (unsigned long) &frame->info; #if DEBUG_SIG printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", sig, current->comm, current->pid, frame, __frame->pc, frame->pretcode); #endif return 0; } /* end setup_rt_frame() */
static inline int setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs) { struct rt_signal_frame __user *sf; int wsaved, err, sf_size; void __user *tail; /* 1. Make sure everything is clean */ synchronize_user_stack(); save_and_clear_fpu(); wsaved = get_thread_wsaved(); sf_size = sizeof(struct rt_signal_frame); if (current_thread_info()->fpsaved[0] & FPRS_FEF) sf_size += sizeof(__siginfo_fpu_t); if (wsaved) sf_size += sizeof(__siginfo_rwin_t); sf = (struct rt_signal_frame __user *) get_sigframe(ksig, regs, sf_size); if (invalid_frame_pointer (sf)) { do_exit(SIGILL); /* won't return, actually */ return -EINVAL; } tail = (sf + 1); /* 2. Save the current process state */ err = copy_to_user(&sf->regs, regs, sizeof (*regs)); if (current_thread_info()->fpsaved[0] & FPRS_FEF) { __siginfo_fpu_t __user *fpu_save = tail; tail += sizeof(__siginfo_fpu_t); err |= save_fpu_state(regs, fpu_save); err |= __put_user((u64)fpu_save, &sf->fpu_save); } else { err |= __put_user(0, &sf->fpu_save); } if (wsaved) { __siginfo_rwin_t __user *rwin_save = tail; tail += sizeof(__siginfo_rwin_t); err |= save_rwin_state(wsaved, rwin_save); err |= __put_user((u64)rwin_save, &sf->rwin_save); set_thread_wsaved(0); } else { err |= __put_user(0, &sf->rwin_save); } /* Setup sigaltstack */ err |= __save_altstack(&sf->stack, regs->u_regs[UREG_FP]); err |= copy_to_user(&sf->mask, sigmask_to_save(), sizeof(sigset_t)); if (!wsaved) { err |= copy_in_user((u64 __user *)sf, (u64 __user *)(regs->u_regs[UREG_FP] + STACK_BIAS), sizeof(struct reg_window)); } else { struct reg_window *rp; rp = ¤t_thread_info()->reg_window[wsaved - 1]; err |= copy_to_user(sf, rp, sizeof(struct reg_window)); } if (ksig->ka.sa.sa_flags & SA_SIGINFO) err |= copy_siginfo_to_user(&sf->info, &ksig->info); else { err |= __put_user(ksig->sig, &sf->info.si_signo); err |= __put_user(SI_NOINFO, &sf->info.si_code); } if (err) return err; /* 3. signal handler back-trampoline and parameters */ regs->u_regs[UREG_FP] = ((unsigned long) sf) - STACK_BIAS; regs->u_regs[UREG_I0] = ksig->sig; regs->u_regs[UREG_I1] = (unsigned long) &sf->info; /* The sigcontext is passed in this way because of how it * is defined in GLIBC's /usr/include/bits/sigcontext.h * for sparc64. It includes the 128 bytes of siginfo_t. */ regs->u_regs[UREG_I2] = (unsigned long) &sf->info; /* 5. signal handler */ regs->tpc = (unsigned long) ksig->ka.sa.sa_handler; regs->tnpc = (regs->tpc + 4); if (test_thread_flag(TIF_32BIT)) { regs->tpc &= 0xffffffff; regs->tnpc &= 0xffffffff; } /* 4. return to kernel instructions */ regs->u_regs[UREG_I7] = (unsigned long)ksig->ka.ka_restorer; return 0; }