signal.c (3383B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 4 */ 5 6#include <linux/module.h> 7#include <linux/ptrace.h> 8#include <linux/sched.h> 9#include <linux/ftrace.h> 10#include <asm/siginfo.h> 11#include <asm/signal.h> 12#include <asm/unistd.h> 13#include <frame_kern.h> 14#include <kern_util.h> 15#include <os.h> 16 17EXPORT_SYMBOL(block_signals); 18EXPORT_SYMBOL(unblock_signals); 19 20void block_signals_trace(void) 21{ 22 block_signals(); 23 if (current_thread_info()) 24 trace_hardirqs_off(); 25} 26 27void unblock_signals_trace(void) 28{ 29 if (current_thread_info()) 30 trace_hardirqs_on(); 31 unblock_signals(); 32} 33 34void um_trace_signals_on(void) 35{ 36 if (current_thread_info()) 37 trace_hardirqs_on(); 38} 39 40void um_trace_signals_off(void) 41{ 42 if (current_thread_info()) 43 trace_hardirqs_off(); 44} 45 46/* 47 * OK, we're invoking a handler 48 */ 49static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) 50{ 51 sigset_t *oldset = sigmask_to_save(); 52 int singlestep = 0; 53 unsigned long sp; 54 int err; 55 56 if (test_thread_flag(TIF_SINGLESTEP) && (current->ptrace & PT_PTRACED)) 57 singlestep = 1; 58 59 /* Did we come from a system call? */ 60 if (PT_REGS_SYSCALL_NR(regs) >= 0) { 61 /* If so, check system call restarting.. */ 62 switch (PT_REGS_SYSCALL_RET(regs)) { 63 case -ERESTART_RESTARTBLOCK: 64 case -ERESTARTNOHAND: 65 PT_REGS_SYSCALL_RET(regs) = -EINTR; 66 break; 67 68 case -ERESTARTSYS: 69 if (!(ksig->ka.sa.sa_flags & SA_RESTART)) { 70 PT_REGS_SYSCALL_RET(regs) = -EINTR; 71 break; 72 } 73 fallthrough; 74 case -ERESTARTNOINTR: 75 PT_REGS_RESTART_SYSCALL(regs); 76 PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs); 77 break; 78 } 79 } 80 81 sp = PT_REGS_SP(regs); 82 if ((ksig->ka.sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0)) 83 sp = current->sas_ss_sp + current->sas_ss_size; 84 85#ifdef CONFIG_ARCH_HAS_SC_SIGNALS 86 if (!(ksig->ka.sa.sa_flags & SA_SIGINFO)) 87 err = setup_signal_stack_sc(sp, ksig, regs, oldset); 88 else 89#endif 90 err = setup_signal_stack_si(sp, ksig, regs, oldset); 91 92 signal_setup_done(err, ksig, singlestep); 93} 94 95void do_signal(struct pt_regs *regs) 96{ 97 struct ksignal ksig; 98 int handled_sig = 0; 99 100 while (get_signal(&ksig)) { 101 handled_sig = 1; 102 /* Whee! Actually deliver the signal. */ 103 handle_signal(&ksig, regs); 104 } 105 106 /* Did we come from a system call? */ 107 if (!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)) { 108 /* Restart the system call - no handlers present */ 109 switch (PT_REGS_SYSCALL_RET(regs)) { 110 case -ERESTARTNOHAND: 111 case -ERESTARTSYS: 112 case -ERESTARTNOINTR: 113 PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs); 114 PT_REGS_RESTART_SYSCALL(regs); 115 break; 116 case -ERESTART_RESTARTBLOCK: 117 PT_REGS_ORIG_SYSCALL(regs) = __NR_restart_syscall; 118 PT_REGS_RESTART_SYSCALL(regs); 119 break; 120 } 121 } 122 123 /* 124 * This closes a way to execute a system call on the host. If 125 * you set a breakpoint on a system call instruction and singlestep 126 * from it, the tracing thread used to PTRACE_SINGLESTEP the process 127 * rather than PTRACE_SYSCALL it, allowing the system call to execute 128 * on the host. The tracing thread will check this flag and 129 * PTRACE_SYSCALL if necessary. 130 */ 131 if (test_thread_flag(TIF_SINGLESTEP)) 132 current->thread.singlestep_syscall = 133 is_syscall(PT_REGS_IP(¤t->thread.regs)); 134 135 /* 136 * if there's no signal to deliver, we just put the saved sigmask 137 * back 138 */ 139 if (!handled_sig) 140 restore_saved_sigmask(); 141}