static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { int usig = signr_convert(sig); int ret; /* Set up the stack frame */ if (is_ia32) { if (ka->sa.sa_flags & SA_SIGINFO) ret = ia32_setup_rt_frame(usig, ka, info, set, regs); else ret = ia32_setup_frame(usig, ka, set, regs); } else ret = __setup_rt_frame(sig, ka, info, set, regs); if (ret) { force_sigsegv(sig, current); return -EFAULT; } return ret; }
static int handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) { int ret; #ifdef DEBUG_SIG printk("handle_signal pid:%d sig:%lu rip:%lx rsp:%lx regs=%p\n", current->pid, sig, regs->rip, regs->rsp, regs); #endif /* Are we from a system call? */ if ((long)regs->orig_rax >= 0) { /* If so, check system call restarting.. */ switch (regs->rax) { case -ERESTART_RESTARTBLOCK: case -ERESTARTNOHAND: regs->rax = -EINTR; break; case -ERESTARTSYS: if (!(ka->sa.sa_flags & SA_RESTART)) { regs->rax = -EINTR; break; } /* fallthrough */ case -ERESTARTNOINTR: regs->rax = regs->orig_rax; regs->rip -= 2; break; } } /* * If TF is set due to a debugger (PT_DTRACE), clear the TF * flag so that register information in the sigcontext is * correct. */ if (unlikely(regs->eflags & TF_MASK)) { if (likely(current->ptrace & PT_DTRACE)) { current->ptrace &= ~PT_DTRACE; regs->eflags &= ~TF_MASK; } } #ifdef CONFIG_IA32_EMULATION if (test_thread_flag(TIF_IA32)) { if (ka->sa.sa_flags & SA_SIGINFO) ret = ia32_setup_rt_frame(sig, ka, info, oldset, regs); else ret = ia32_setup_frame(sig, ka, oldset, regs); } else #endif ret = setup_rt_frame(sig, ka, info, oldset, regs); if (ret == 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); } return ret; }
static int handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) { int ret; #ifdef DEBUG_SIG printk("handle_signal pid:%d sig:%lu rip:%lx rsp:%lx regs=%p\n", current->pid, sig, regs->rip, regs->rsp, regs); #endif /* Are we from a system call? */ if (current_syscall(regs) >= 0) { /* If so, check system call restarting.. */ switch (current_syscall_ret(regs)) { case -ERESTART_RESTARTBLOCK: case -ERESTARTNOHAND: regs->rax = -EINTR; break; case -ERESTARTSYS: if (!(ka->sa.sa_flags & SA_RESTART)) { regs->rax = -EINTR; break; } /* fallthrough */ case -ERESTARTNOINTR: regs->rax = regs->orig_rax; regs->rip -= 2; break; } } /* * If TF is set due to a debugger (TIF_FORCED_TF), clear the TF flag so * that register information in the sigcontext is correct. */ if (unlikely(regs->eflags & TF_MASK) && likely(test_and_clear_thread_flag(TIF_FORCED_TF))) regs->eflags &= ~TF_MASK; #ifdef CONFIG_IA32_EMULATION if (test_thread_flag(TIF_IA32)) { if (ka->sa.sa_flags & SA_SIGINFO) ret = ia32_setup_rt_frame(sig, ka, info, oldset, regs); else ret = ia32_setup_frame(sig, ka, oldset, regs); } else #endif ret = setup_rt_frame(sig, ka, info, oldset, regs); if (ret == 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); /* * Clear TF when entering the signal handler, but * notify any tracer that was single-stepping it. * The tracer may want to single-step inside the * handler too. */ regs->eflags &= ~(TF_MASK | X86_EFLAGS_DF); tracehook_report_handle_signal(sig, ka, oldset, regs); } return ret; }
static int handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) { int ret; /* Are we from a system call? */ if (current_syscall(regs) >= 0) { /* If so, check system call restarting.. */ switch (current_syscall_ret(regs)) { case -ERESTART_RESTARTBLOCK: case -ERESTARTNOHAND: regs->ax = -EINTR; break; case -ERESTARTSYS: if (!(ka->sa.sa_flags & SA_RESTART)) { regs->ax = -EINTR; break; } /* fallthrough */ case -ERESTARTNOINTR: regs->ax = regs->orig_ax; regs->ip -= 2; break; } } /* * If TF is set due to a debugger (TIF_FORCED_TF), clear the TF * flag so that register information in the sigcontext is correct. */ if (unlikely(regs->flags & X86_EFLAGS_TF) && likely(test_and_clear_thread_flag(TIF_FORCED_TF))) regs->flags &= ~X86_EFLAGS_TF; #ifdef CONFIG_IA32_EMULATION if (test_thread_flag(TIF_IA32)) { if (ka->sa.sa_flags & SA_SIGINFO) ret = ia32_setup_rt_frame(sig, ka, info, oldset, regs); else ret = ia32_setup_frame(sig, ka, oldset, regs); } else #endif ret = setup_rt_frame(sig, ka, info, oldset, regs); if (ret == 0) { /* * This has nothing to do with segment registers, * despite the name. This magic affects uaccess.h * macros' behavior. Reset it to the normal setting. */ set_fs(USER_DS); /* * Clear the direction flag as per the ABI for function entry. */ regs->flags &= ~X86_EFLAGS_DF; /* * Clear TF when entering the signal handler, but * notify any tracer that was single-stepping it. * The tracer may want to single-step inside the * handler too. */ regs->flags &= ~X86_EFLAGS_TF; if (test_thread_flag(TIF_SINGLESTEP)) ptrace_notify(SIGTRAP); 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); } return ret; }