2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
6 #include "linux/config.h"
7 #include "linux/stddef.h"
9 #include "linux/sched.h"
10 #include "linux/wait.h"
11 #include "linux/kernel.h"
12 #include "linux/smp_lock.h"
13 #include "linux/module.h"
14 #include "linux/slab.h"
15 #include "linux/tty.h"
16 #include "linux/binfmts.h"
17 #include "linux/ptrace.h"
18 #include "asm/signal.h"
19 #include "asm/uaccess.h"
20 #include "asm/unistd.h"
21 #include "user_util.h"
22 #include "asm/ucontext.h"
23 #include "kern_util.h"
24 #include "signal_kern.h"
26 #include "frame_kern.h"
27 #include "sigcontext.h"
30 EXPORT_SYMBOL(block_signals);
31 EXPORT_SYMBOL(unblock_signals);
33 #define _S(nr) (1<<((nr)-1))
35 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
38 * OK, we're invoking a handler
40 static int handle_signal(struct pt_regs *regs, unsigned long signr,
41 struct k_sigaction *ka, siginfo_t *info,
47 /* Always make any pending restarted system calls return -EINTR */
48 current_thread_info()->restart_block.fn = do_no_restart_syscall;
50 /* Did we come from a system call? */
51 if(PT_REGS_SYSCALL_NR(regs) >= 0){
52 /* If so, check system call restarting.. */
53 switch(PT_REGS_SYSCALL_RET(regs)){
54 case -ERESTART_RESTARTBLOCK:
56 PT_REGS_SYSCALL_RET(regs) = -EINTR;
60 if (!(ka->sa.sa_flags & SA_RESTART)) {
61 PT_REGS_SYSCALL_RET(regs) = -EINTR;
66 PT_REGS_RESTART_SYSCALL(regs);
67 PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
72 sp = PT_REGS_SP(regs);
73 if((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
74 sp = current->sas_ss_sp + current->sas_ss_size;
76 #ifdef CONFIG_ARCH_HAS_SC_SIGNALS
77 if(!(ka->sa.sa_flags & SA_SIGINFO))
78 err = setup_signal_stack_sc(sp, signr, ka, regs, oldset);
81 err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset);
84 spin_lock_irq(¤t->sighand->siglock);
85 current->blocked = *oldset;
87 spin_unlock_irq(¤t->sighand->siglock);
88 force_sigsegv(signr, current);
90 spin_lock_irq(¤t->sighand->siglock);
91 sigorsets(¤t->blocked, ¤t->blocked,
93 if(!(ka->sa.sa_flags & SA_NODEFER))
94 sigaddset(¤t->blocked, signr);
96 spin_unlock_irq(¤t->sighand->siglock);
102 static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset)
104 struct k_sigaction ka_copy;
106 int sig, handled_sig = 0;
108 while((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0){
110 /* Whee! Actually deliver the signal. */
111 if(!handle_signal(regs, sig, &ka_copy, &info, oldset))
115 /* Did we come from a system call? */
116 if(!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)){
117 /* Restart the system call - no handlers present */
118 if(PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOHAND ||
119 PT_REGS_SYSCALL_RET(regs) == -ERESTARTSYS ||
120 PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOINTR){
121 PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
122 PT_REGS_RESTART_SYSCALL(regs);
124 else if(PT_REGS_SYSCALL_RET(regs) == -ERESTART_RESTARTBLOCK){
125 PT_REGS_SYSCALL_RET(regs) = __NR_restart_syscall;
126 PT_REGS_RESTART_SYSCALL(regs);
130 /* This closes a way to execute a system call on the host. If
131 * you set a breakpoint on a system call instruction and singlestep
132 * from it, the tracing thread used to PTRACE_SINGLESTEP the process
133 * rather than PTRACE_SYSCALL it, allowing the system call to execute
134 * on the host. The tracing thread will check this flag and
135 * PTRACE_SYSCALL if necessary.
137 if(current->ptrace & PT_DTRACE)
138 current->thread.singlestep_syscall =
139 is_syscall(PT_REGS_IP(¤t->thread.regs));
145 return(kern_do_signal(¤t->thread.regs, ¤t->blocked));
149 * Atomically swap in the new signal mask, and wait for a signal.
151 long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
156 spin_lock_irq(¤t->sighand->siglock);
157 saveset = current->blocked;
158 siginitset(¤t->blocked, mask);
160 spin_unlock_irq(¤t->sighand->siglock);
162 PT_REGS_SYSCALL_RET(¤t->thread.regs) = -EINTR;
164 current->state = TASK_INTERRUPTIBLE;
166 if(kern_do_signal(¤t->thread.regs, &saveset))
171 long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
173 sigset_t saveset, newset;
175 /* XXX: Don't preclude handling different sized sigset_t's. */
176 if (sigsetsize != sizeof(sigset_t))
179 if (copy_from_user(&newset, unewset, sizeof(newset)))
181 sigdelsetmask(&newset, ~_BLOCKABLE);
183 spin_lock_irq(¤t->sighand->siglock);
184 saveset = current->blocked;
185 current->blocked = newset;
187 spin_unlock_irq(¤t->sighand->siglock);
189 PT_REGS_SYSCALL_RET(¤t->thread.regs) = -EINTR;
191 current->state = TASK_INTERRUPTIBLE;
193 if (kern_do_signal(¤t->thread.regs, &saveset))
198 long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
200 return(do_sigaltstack(uss, uoss, PT_REGS_SP(¤t->thread.regs)));
204 * Overrides for Emacs so that we follow Linus's tabbing style.
205 * Emacs will notice this stuff at the end of the file and automatically
206 * adjust the settings for this buffer only. This must remain at the end
208 * ---------------------------------------------------------------------------
210 * c-file-style: "linux"