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 pt_regs *regs, unsigned long signr, 22 struct k_sigaction *ka, siginfo_t *info) 23 { 24 sigset_t *oldset = sigmask_to_save(); 25 unsigned long sp; 26 int err; 27 28 /* Did we come from a system call? */ 29 if (PT_REGS_SYSCALL_NR(regs) >= 0) { 30 /* If so, check system call restarting.. */ 31 switch (PT_REGS_SYSCALL_RET(regs)) { 32 case -ERESTART_RESTARTBLOCK: 33 case -ERESTARTNOHAND: 34 PT_REGS_SYSCALL_RET(regs) = -EINTR; 35 break; 36 37 case -ERESTARTSYS: 38 if (!(ka->sa.sa_flags & SA_RESTART)) { 39 PT_REGS_SYSCALL_RET(regs) = -EINTR; 40 break; 41 } 42 /* fallthrough */ 43 case -ERESTARTNOINTR: 44 PT_REGS_RESTART_SYSCALL(regs); 45 PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs); 46 break; 47 } 48 } 49 50 sp = PT_REGS_SP(regs); 51 if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0)) 52 sp = current->sas_ss_sp + current->sas_ss_size; 53 54 #ifdef CONFIG_ARCH_HAS_SC_SIGNALS 55 if (!(ka->sa.sa_flags & SA_SIGINFO)) 56 err = setup_signal_stack_sc(sp, signr, ka, regs, oldset); 57 else 58 #endif 59 err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset); 60 61 if (err) 62 force_sigsegv(signr, current); 63 else 64 signal_delivered(signr, info, ka, regs, 0); 65 } 66 67 static int kern_do_signal(struct pt_regs *regs) 68 { 69 struct k_sigaction ka_copy; 70 siginfo_t info; 71 int sig, handled_sig = 0; 72 73 while ((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0) { 74 handled_sig = 1; 75 /* Whee! Actually deliver the signal. */ 76 handle_signal(regs, sig, &ka_copy, &info); 77 } 78 79 /* Did we come from a system call? */ 80 if (!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)) { 81 /* Restart the system call - no handlers present */ 82 switch (PT_REGS_SYSCALL_RET(regs)) { 83 case -ERESTARTNOHAND: 84 case -ERESTARTSYS: 85 case -ERESTARTNOINTR: 86 PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs); 87 PT_REGS_RESTART_SYSCALL(regs); 88 break; 89 case -ERESTART_RESTARTBLOCK: 90 PT_REGS_ORIG_SYSCALL(regs) = __NR_restart_syscall; 91 PT_REGS_RESTART_SYSCALL(regs); 92 break; 93 } 94 } 95 96 /* 97 * This closes a way to execute a system call on the host. If 98 * you set a breakpoint on a system call instruction and singlestep 99 * from it, the tracing thread used to PTRACE_SINGLESTEP the process 100 * rather than PTRACE_SYSCALL it, allowing the system call to execute 101 * on the host. The tracing thread will check this flag and 102 * PTRACE_SYSCALL if necessary. 103 */ 104 if (current->ptrace & PT_DTRACE) 105 current->thread.singlestep_syscall = 106 is_syscall(PT_REGS_IP(¤t->thread.regs)); 107 108 /* 109 * if there's no signal to deliver, we just put the saved sigmask 110 * back 111 */ 112 if (!handled_sig) 113 restore_saved_sigmask(); 114 return handled_sig; 115 } 116 117 int do_signal(void) 118 { 119 return kern_do_signal(¤t->thread.regs); 120 } 121 122 /* 123 * Atomically swap in the new signal mask, and wait for a signal. 124 */ 125 long sys_sigsuspend(int history0, int history1, old_sigset_t mask) 126 { 127 sigset_t blocked; 128 siginitset(&blocked, mask); 129 return sigsuspend(&blocked); 130 } 131 132 long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) 133 { 134 return do_sigaltstack(uss, uoss, PT_REGS_SP(¤t->thread.regs)); 135 } 136