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