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 17 EXPORT_SYMBOL(block_signals); 18 EXPORT_SYMBOL(unblock_signals); 19 20 void block_signals_trace(void) 21 { 22 block_signals(); 23 if (current_thread_info()) 24 trace_hardirqs_off(); 25 } 26 27 void unblock_signals_trace(void) 28 { 29 if (current_thread_info()) 30 trace_hardirqs_on(); 31 unblock_signals(); 32 } 33 34 void um_trace_signals_on(void) 35 { 36 if (current_thread_info()) 37 trace_hardirqs_on(); 38 } 39 40 void 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 */ 49 static 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 95 void 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 * if there's no signal to deliver, we just put the saved sigmask 125 * back 126 */ 127 if (!handled_sig) 128 restore_saved_sigmask(); 129 } 130
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.