/* * OK, we're invoking a handler */ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) { sigset_t *oldset = sigmask_to_save(); int ret; /* * Set up the stack frame */ if (ksig->ka.sa.sa_flags & SA_SIGINFO) ret = setup_rt_frame(ksig, oldset, regs); else ret = setup_frame(ksig, oldset, regs); /* * Check that the resulting registers are actually sane. */ ret |= !valid_user_regs(regs); signal_setup_done(ret, ksig, 0); }
/* * handle the actual delivery of a signal to userspace */ static int handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, struct pt_regs *regs) { sigset_t *oldset = sigmask_to_save(); int ret; /* Are we from a system call? */ if (regs->orig_d0 >= 0) { /* If so, check system call restarting.. */ switch (regs->d0) { case -ERESTART_RESTARTBLOCK: case -ERESTARTNOHAND: regs->d0 = -EINTR; break; case -ERESTARTSYS: if (!(ka->sa.sa_flags & SA_RESTART)) { regs->d0 = -EINTR; break; } /* fallthrough */ case -ERESTARTNOINTR: regs->d0 = regs->orig_d0; stepback(regs); } } /* Set up the stack frame */ if (ka->sa.sa_flags & SA_SIGINFO) ret = setup_rt_frame(sig, ka, info, oldset, regs); else ret = setup_frame(sig, ka, oldset, regs); if (ret) return ret; signal_delivered(sig, info, ka, regs, test_thread_flag(TIF_SINGLESTEP)); return 0; }
static void handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, struct pt_regs *regs) { sigset_t *oldset = sigmask_to_save(); int ret; struct mips_abi *abi = current->thread.abi; void *vdso = current->mm->context.vdso; if (regs->regs[0]) { switch(regs->regs[2]) { case ERESTART_RESTARTBLOCK: case ERESTARTNOHAND: regs->regs[2] = EINTR; break; case ERESTARTSYS: if (!(ka->sa.sa_flags & SA_RESTART)) { regs->regs[2] = EINTR; break; } /* fallthrough */ case ERESTARTNOINTR: regs->regs[7] = regs->regs[26]; regs->regs[2] = regs->regs[0]; regs->cp0_epc -= 4; } regs->regs[0] = 0; /* Don't deal with this again. */ } if (sig_uses_siginfo(ka)) ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset, ka, regs, sig, oldset, info); else ret = abi->setup_frame(vdso + abi->signal_return_offset, ka, regs, sig, oldset); if (ret) return; signal_delivered(sig, info, ka, regs, 0); }
/* * OK, we're invoking a handler */ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) { struct thread_info *thread = current_thread_info(); struct task_struct *tsk = current; sigset_t *oldset = sigmask_to_save(); int usig = ksig->sig; int ret; /* * translate the signal */ if (usig < 32 && thread->exec_domain && thread->exec_domain->signal_invmap) usig = thread->exec_domain->signal_invmap[usig]; /* * Set up the stack frame */ if (is_compat_task()) { if (ksig->ka.sa.sa_flags & SA_SIGINFO) ret = compat_setup_rt_frame(usig, ksig, oldset, regs); else ret = compat_setup_frame(usig, ksig, oldset, regs); } else { ret = setup_rt_frame(usig, ksig, oldset, regs); } /* * Check that the resulting registers are actually sane. */ ret |= !valid_user_regs(®s->user_regs); /* * Fast forward the stepping logic so we step into the signal * handler. */ if (!ret) user_fastforward_single_step(tsk); signal_setup_done(ret, ksig, 0); }
static long handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, struct sigscratch *scr) { if (!setup_frame(sig, ka, info, sigmask_to_save(), scr)) return 0; spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); if (!(ka->sa.sa_flags & SA_NODEFER)) sigaddset(¤t->blocked, sig); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); /* * Let tracing know that we've done the handler setup. */ tracehook_signal_handler(sig, info, ka, &scr->pt, test_thread_flag(TIF_SINGLESTEP)); return 1; }
/* * OK, we're invoking a handler */ static void handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, struct pt_regs *regs) { struct task_struct *tsk = current; sigset_t *oldset = sigmask_to_save(); int usig = sig; int ret; /* * Set up the stack frame */ if (is_compat_task()) { if (ka->sa.sa_flags & SA_SIGINFO) ret = compat_setup_rt_frame(usig, ka, info, oldset, regs); else ret = compat_setup_frame(usig, ka, oldset, regs); } else { ret = setup_rt_frame(usig, ka, info, oldset, regs); } /* * Check that the resulting registers are actually sane. */ ret |= !valid_user_regs(®s->user_regs); if (ret != 0) { force_sigsegv(sig, tsk); return; } /* * Fast forward the stepping logic so we step into the signal * handler. */ user_fastforward_single_step(tsk); signal_delivered(sig, info, ka, regs, 0); }
static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) { sigset_t *oldset = sigmask_to_save(); int ret; /* Are we from a system call? */ if (regs->faultnum == INT_SWINT_1) { /* If so, check system call restarting.. */ switch (regs->regs[0]) { case -ERESTART_RESTARTBLOCK: case -ERESTARTNOHAND: regs->regs[0] = -EINTR; break; case -ERESTARTSYS: if (!(ksig->ka.sa.sa_flags & SA_RESTART)) { regs->regs[0] = -EINTR; break; } /* fallthrough */ case -ERESTARTNOINTR: /* Reload caller-saves to restore r0..r5 and r10. */ regs->flags |= PT_FLAGS_CALLER_SAVES; regs->regs[0] = regs->orig_r0; regs->pc -= 8; } } /* Set up the stack frame */ #ifdef CONFIG_COMPAT if (is_compat_task()) ret = compat_setup_rt_frame(ksig, oldset, regs); else #endif ret = setup_rt_frame(ksig, oldset, regs); signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP)); }
/* * handle the actual delivery of a signal to userspace */ static int handle_signal(struct ksignal *ksig, struct pt_regs *regs) { sigset_t *oldset = sigmask_to_save(); int ret; /* Are we from a system call? */ if (regs->orig_d0 >= 0) { /* If so, check system call restarting.. */ switch (regs->d0) { case -ERESTART_RESTARTBLOCK: case -ERESTARTNOHAND: regs->d0 = -EINTR; break; case -ERESTARTSYS: if (!(ksig->ka.sa.sa_flags & SA_RESTART)) { regs->d0 = -EINTR; break; } /* fallthrough */ case -ERESTARTNOINTR: regs->d0 = regs->orig_d0; stepback(regs); } } /* Set up the stack frame */ if (ksig->ka.sa.sa_flags & SA_SIGINFO) ret = setup_rt_frame(ksig, oldset, regs); else ret = setup_frame(ksig, oldset, regs); signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP)); return 0; }
/* * OK, we're invoking a handler */ static void handle_signal(struct ksignal *ksig) { sigset_t *oldset = sigmask_to_save(); int ret; /* Are we from a system call? */ if (__frame->syscallno != -1) { /* If so, check system call restarting.. */ switch (__frame->gr8) { case -ERESTART_RESTARTBLOCK: case -ERESTARTNOHAND: __frame->gr8 = -EINTR; break; case -ERESTARTSYS: if (!(ksig->ka.sa.sa_flags & SA_RESTART)) { __frame->gr8 = -EINTR; break; } /* fallthrough */ case -ERESTARTNOINTR: __frame->gr8 = __frame->orig_gr8; __frame->pc -= 4; } __frame->syscallno = -1; } /* Set up the stack frame */ if (ksig->ka.sa.sa_flags & SA_SIGINFO) ret = setup_rt_frame(ksig, oldset); else ret = setup_frame(ksig, oldset); signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP)); } /* end handle_signal() */
static inline void handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, struct pt_regs *regs, int syscall) { int ret; /* * Set up the stack frame */ ret = setup_rt_frame(sig, ka, info, sigmask_to_save(), regs); /* * Check that the resulting registers are sane */ ret |= !valid_user_regs(regs); /* * Block the signal if we were successful. */ if (ret != 0) force_sigsegv(sig, current); else signal_delivered(sig, info, ka, regs, 0); }
/* Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) { struct k_sigaction ka; int restart_syscall; sigset_t *oldset = sigmask_to_save(); siginfo_t info; int signr; /* It's a lot of work and synchronization to add a new ptrace * register for GDB to save and restore in order to get * orig_i0 correct for syscall restarts when debugging. * * Although it should be the case that most of the global * registers are volatile across a system call, glibc already * depends upon that fact that we preserve them. So we can't * just use any global register to save away the orig_i0 value. * * In particular %g2, %g3, %g4, and %g5 are all assumed to be * preserved across a system call trap by various pieces of * code in glibc. * * %g7 is used as the "thread register". %g6 is not used in * any fixed manner. %g6 is used as a scratch register and * a compiler temporary, but it's value is never used across * a system call. Therefore %g6 is usable for orig_i0 storage. */ if (pt_regs_is_syscall(regs) && (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) regs->u_regs[UREG_G6] = orig_i0; #ifdef CONFIG_COMPAT if (test_thread_flag(TIF_32BIT)) { extern void do_signal32(sigset_t *, struct pt_regs *); do_signal32(oldset, regs); return; } #endif signr = get_signal_to_deliver(&info, &ka, regs, NULL); restart_syscall = 0; if (pt_regs_is_syscall(regs) && (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) { restart_syscall = 1; orig_i0 = regs->u_regs[UREG_G6]; } if (signr > 0) { if (restart_syscall) syscall_restart(orig_i0, regs, &ka.sa); handle_signal(signr, &ka, &info, oldset, regs); return; } if (restart_syscall && (regs->u_regs[UREG_I0] == ERESTARTNOHAND || regs->u_regs[UREG_I0] == ERESTARTSYS || regs->u_regs[UREG_I0] == ERESTARTNOINTR)) { /* replay the system call when we are done */ regs->u_regs[UREG_I0] = orig_i0; regs->tpc -= 4; regs->tnpc -= 4; pt_regs_clear_syscall(regs); } if (restart_syscall && regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { regs->u_regs[UREG_G1] = __NR_restart_syscall; regs->tpc -= 4; regs->tnpc -= 4; pt_regs_clear_syscall(regs); } /* If there's no signal to deliver, we just put the saved sigmask * back */ restore_saved_sigmask(); }
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; }