/* 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; siginfo_t info; int signr; if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C)) restart_syscall = 1; else restart_syscall = 0; if (test_thread_flag(TIF_RESTORE_SIGMASK)) oldset = ¤t->saved_sigmask; else oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, NULL); /* If the debugger messes with the program counter, it clears * the software "in syscall" bit, directing us to not perform * a syscall restart. */ if (restart_syscall && !pt_regs_is_syscall(regs)) restart_syscall = 0; if (signr > 0) { if (restart_syscall) syscall_restart(orig_i0, regs, &ka.sa); if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { /* a signal was successfully delivered; the saved * sigmask will have been stored in the signal frame, * and will be restored by sigreturn, so we can simply * clear the TIF_RESTORE_SIGMASK flag. */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) clear_thread_flag(TIF_RESTORE_SIGMASK); } 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->pc -= 4; regs->npc -= 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->pc -= 4; regs->npc -= 4; pt_regs_clear_syscall(regs); } /* if there's no signal to deliver, we just put the saved sigmask * back */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) { clear_thread_flag(TIF_RESTORE_SIGMASK); sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } }
/* 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(); }
/* 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; 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->psr & PSR_C)) regs->u_regs[UREG_G6] = orig_i0; if (test_thread_flag(TIF_RESTORE_SIGMASK)) oldset = ¤t->saved_sigmask; else oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, NULL); /* If the debugger messes with the program counter, it clears * the software "in syscall" bit, directing us to not perform * a syscall restart. */ restart_syscall = 0; if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C)) { restart_syscall = 1; orig_i0 = regs->u_regs[UREG_G6]; } if (signr > 0) { if (restart_syscall) syscall_restart(orig_i0, regs, &ka.sa); if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { /* a signal was successfully delivered; the saved * sigmask will have been stored in the signal frame, * and will be restored by sigreturn, so we can simply * clear the TIF_RESTORE_SIGMASK flag. */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) clear_thread_flag(TIF_RESTORE_SIGMASK); } 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->pc -= 4; regs->npc -= 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->pc -= 4; regs->npc -= 4; pt_regs_clear_syscall(regs); } /* if there's no signal to deliver, we just put the saved sigmask * back */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) { clear_thread_flag(TIF_RESTORE_SIGMASK); sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } }
/* 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; siginfo_t info; int signr; if (pt_regs_is_syscall(regs) && (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) { restart_syscall = 1; } else restart_syscall = 0; if (current_thread_info()->status & TS_RESTORE_SIGMASK) oldset = ¤t->saved_sigmask; else oldset = ¤t->blocked; #ifdef CONFIG_COMPAT if (test_thread_flag(TIF_32BIT)) { extern void do_signal32(sigset_t *, struct pt_regs *, int restart_syscall, unsigned long orig_i0); do_signal32(oldset, regs, restart_syscall, orig_i0); return; } #endif signr = get_signal_to_deliver(&info, &ka, regs, NULL); /* If the debugger messes with the program counter, it clears * the software "in syscall" bit, directing us to not perform * a syscall restart. */ if (restart_syscall && !pt_regs_is_syscall(regs)) restart_syscall = 0; if (signr > 0) { if (restart_syscall) syscall_restart(orig_i0, regs, &ka.sa); handle_signal(signr, &ka, &info, oldset, regs); /* A signal was successfully delivered; the saved * sigmask will have been stored in the signal frame, * and will be restored by sigreturn, so we can simply * clear the TS_RESTORE_SIGMASK flag. */ current_thread_info()->status &= ~TS_RESTORE_SIGMASK; tracehook_signal_handler(signr, &info, &ka, regs, 0); 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; } if (restart_syscall && regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { regs->u_regs[UREG_G1] = __NR_restart_syscall; regs->tpc -= 4; regs->tnpc -= 4; } /* If there's no signal to deliver, we just put the saved sigmask * back */ if (current_thread_info()->status & TS_RESTORE_SIGMASK) { current_thread_info()->status &= ~TS_RESTORE_SIGMASK; sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } }
/* 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 ksignal ksig; int restart_syscall; bool has_handler; /* 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(struct pt_regs *); do_signal32(regs); return; } #endif has_handler = get_signal(&ksig); 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 (has_handler) { if (restart_syscall) syscall_restart(orig_i0, regs, &ksig.ka.sa); signal_setup_done(setup_rt_frame(&ksig, regs), &ksig, 0); } else { if (restart_syscall) { switch (regs->u_regs[UREG_I0]) { case ERESTARTNOHAND: case ERESTARTSYS: case 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); case ERESTART_RESTARTBLOCK: regs->u_regs[UREG_G1] = __NR_restart_syscall; regs->tpc -= 4; regs->tnpc -= 4; pt_regs_clear_syscall(regs); } } restore_saved_sigmask(); } }
/* 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 ksignal ksig; int restart_syscall; bool has_handler; /* 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->psr & PSR_C)) regs->u_regs[UREG_G6] = orig_i0; has_handler = get_signal(&ksig); /* If the debugger messes with the program counter, it clears * the software "in syscall" bit, directing us to not perform * a syscall restart. */ restart_syscall = 0; if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C)) { restart_syscall = 1; orig_i0 = regs->u_regs[UREG_G6]; } if (has_handler) { if (restart_syscall) syscall_restart(orig_i0, regs, &ksig.ka.sa); handle_signal(&ksig, regs); } else { if (restart_syscall) { switch (regs->u_regs[UREG_I0]) { case ERESTARTNOHAND: case ERESTARTSYS: case ERESTARTNOINTR: /* replay the system call when we are done */ regs->u_regs[UREG_I0] = orig_i0; regs->pc -= 4; regs->npc -= 4; pt_regs_clear_syscall(regs); case ERESTART_RESTARTBLOCK: regs->u_regs[UREG_G1] = __NR_restart_syscall; regs->pc -= 4; regs->npc -= 4; pt_regs_clear_syscall(regs); } } restore_saved_sigmask(); } }
static void do_signal(struct pt_regs *regs, unsigned long orig_i0) { struct k_sigaction ka; int restart_syscall; sigset_t *oldset; siginfo_t info; int signr; if (pt_regs_is_syscall(regs) && (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) regs->u_regs[UREG_G6] = orig_i0; if (current_thread_info()->status & TS_RESTORE_SIGMASK) oldset = ¤t->saved_sigmask; else oldset = ¤t->blocked; #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); if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { current_thread_info()->status &= ~TS_RESTORE_SIGMASK; } return; } if (restart_syscall && (regs->u_regs[UREG_I0] == ERESTARTNOHAND || regs->u_regs[UREG_I0] == ERESTARTSYS || regs->u_regs[UREG_I0] == ERESTARTNOINTR)) { 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 (current_thread_info()->status & TS_RESTORE_SIGMASK) { current_thread_info()->status &= ~TS_RESTORE_SIGMASK; set_current_blocked(¤t->saved_sigmask); } }