initial commit with v2.6.9
[linux-2.6.9-moxart.git] / arch / um / kernel / signal_kern.c
blob23aefcbea7a24a50919f991497bad6754c2d2b27
1 /*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
6 #include "linux/config.h"
7 #include "linux/stddef.h"
8 #include "linux/sys.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"
25 #include "signal_user.h"
26 #include "kern.h"
27 #include "frame_kern.h"
28 #include "sigcontext.h"
29 #include "mode.h"
31 EXPORT_SYMBOL(block_signals);
32 EXPORT_SYMBOL(unblock_signals);
34 #define _S(nr) (1<<((nr)-1))
36 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
39 * OK, we're invoking a handler
40 */
41 static int handle_signal(struct pt_regs *regs, unsigned long signr,
42 struct k_sigaction *ka, siginfo_t *info,
43 sigset_t *oldset, int error)
45 __sighandler_t handler;
46 void (*restorer)(void);
47 unsigned long sp;
48 sigset_t save;
49 int err, ret;
51 ret = 0;
52 /* Always make any pending restarted system calls return -EINTR */
53 current_thread_info()->restart_block.fn = do_no_restart_syscall;
54 switch(error){
55 case -ERESTART_RESTARTBLOCK:
56 case -ERESTARTNOHAND:
57 ret = -EINTR;
58 break;
60 case -ERESTARTSYS:
61 if (!(ka->sa.sa_flags & SA_RESTART)) {
62 ret = -EINTR;
63 break;
65 /* fallthrough */
66 case -ERESTARTNOINTR:
67 PT_REGS_RESTART_SYSCALL(regs);
68 PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
70 /* This is because of the UM_SET_SYSCALL_RETURN and the fact
71 * that on i386 the system call number and return value are
72 * in the same register. When the system call restarts, %eax
73 * had better have the system call number in it. Since the
74 * return value doesn't matter (except that it shouldn't be
75 * -ERESTART*), we'll stick the system call number there.
77 ret = PT_REGS_SYSCALL_NR(regs);
78 break;
81 handler = ka->sa.sa_handler;
82 save = *oldset;
84 if (ka->sa.sa_flags & SA_ONESHOT)
85 ka->sa.sa_handler = SIG_DFL;
87 if (!(ka->sa.sa_flags & SA_NODEFER)) {
88 spin_lock_irq(&current->sighand->siglock);
89 sigorsets(&current->blocked, &current->blocked,
90 &ka->sa.sa_mask);
91 sigaddset(&current->blocked, signr);
92 recalc_sigpending();
93 spin_unlock_irq(&current->sighand->siglock);
96 sp = PT_REGS_SP(regs);
98 if((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
99 sp = current->sas_ss_sp + current->sas_ss_size;
101 if(error != 0) PT_REGS_SET_SYSCALL_RETURN(regs, ret);
103 if (ka->sa.sa_flags & SA_RESTORER) restorer = ka->sa.sa_restorer;
104 else restorer = NULL;
106 if(ka->sa.sa_flags & SA_SIGINFO)
107 err = setup_signal_stack_si(sp, signr, (unsigned long) handler,
108 restorer, regs, info, &save);
109 else
110 err = setup_signal_stack_sc(sp, signr, (unsigned long) handler,
111 restorer, regs, &save);
112 if(err) goto segv;
114 return(0);
115 segv:
116 force_sigsegv(signr, current);
117 return(1);
120 static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset, int error)
122 struct k_sigaction ka_copy;
123 siginfo_t info;
124 int err, sig;
126 if (!oldset)
127 oldset = &current->blocked;
129 sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL);
130 if(sig == 0)
131 return(0);
133 /* Whee! Actually deliver the signal. */
134 err = handle_signal(regs, sig, &ka_copy, &info, oldset, error);
135 if(!err)
136 return(1);
138 /* Did we come from a system call? */
139 if(PT_REGS_SYSCALL_NR(regs) >= 0){
140 /* Restart the system call - no handlers present */
141 if(PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOHAND ||
142 PT_REGS_SYSCALL_RET(regs) == -ERESTARTSYS ||
143 PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOINTR){
144 PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
145 PT_REGS_RESTART_SYSCALL(regs);
147 else if(PT_REGS_SYSCALL_RET(regs) == -ERESTART_RESTARTBLOCK){
148 PT_REGS_SYSCALL_RET(regs) = __NR_restart_syscall;
149 PT_REGS_RESTART_SYSCALL(regs);
153 /* This closes a way to execute a system call on the host. If
154 * you set a breakpoint on a system call instruction and singlestep
155 * from it, the tracing thread used to PTRACE_SINGLESTEP the process
156 * rather than PTRACE_SYSCALL it, allowing the system call to execute
157 * on the host. The tracing thread will check this flag and
158 * PTRACE_SYSCALL if necessary.
160 if((current->ptrace & PT_DTRACE) &&
161 is_syscall(PT_REGS_IP(&current->thread.regs)))
162 (void) CHOOSE_MODE(current->thread.mode.tt.singlestep_syscall = 1, 0);
163 return(0);
166 int do_signal(int error)
168 return(kern_do_signal(&current->thread.regs, NULL, error));
172 * Atomically swap in the new signal mask, and wait for a signal.
174 int sys_sigsuspend(int history0, int history1, old_sigset_t mask)
176 sigset_t saveset;
178 mask &= _BLOCKABLE;
179 spin_lock_irq(&current->sighand->siglock);
180 saveset = current->blocked;
181 siginitset(&current->blocked, mask);
182 recalc_sigpending();
183 spin_unlock_irq(&current->sighand->siglock);
185 while (1) {
186 current->state = TASK_INTERRUPTIBLE;
187 schedule();
188 if(kern_do_signal(&current->thread.regs, &saveset, -EINTR))
189 return(-EINTR);
193 int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
195 sigset_t saveset, newset;
197 /* XXX: Don't preclude handling different sized sigset_t's. */
198 if (sigsetsize != sizeof(sigset_t))
199 return -EINVAL;
201 if (copy_from_user(&newset, unewset, sizeof(newset)))
202 return -EFAULT;
203 sigdelsetmask(&newset, ~_BLOCKABLE);
205 spin_lock_irq(&current->sighand->siglock);
206 saveset = current->blocked;
207 current->blocked = newset;
208 recalc_sigpending();
209 spin_unlock_irq(&current->sighand->siglock);
211 while (1) {
212 current->state = TASK_INTERRUPTIBLE;
213 schedule();
214 if (kern_do_signal(&current->thread.regs, &saveset, -EINTR))
215 return(-EINTR);
219 int sys_sigaction(int sig, const struct old_sigaction __user *act,
220 struct old_sigaction __user *oact)
222 struct k_sigaction new_ka, old_ka;
223 int ret;
225 if (act) {
226 old_sigset_t mask;
227 if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
228 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
229 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
230 return -EFAULT;
231 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
232 __get_user(mask, &act->sa_mask);
233 siginitset(&new_ka.sa.sa_mask, mask);
236 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
238 if (!ret && oact) {
239 if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
240 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
241 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
242 return -EFAULT;
243 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
244 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
247 return ret;
250 int sys_sigaltstack(const stack_t *uss, stack_t *uoss)
252 return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs)));
255 extern int userspace_pid[];
257 static int copy_sc_from_user(struct pt_regs *to, void *from,
258 struct arch_frame_data *arch)
260 int ret;
262 ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, arch),
263 copy_sc_from_user_skas(userspace_pid[0],
264 &to->regs, from));
265 return(ret);
268 int sys_sigreturn(struct pt_regs regs)
270 void __user *sc = sp_to_sc(PT_REGS_SP(&current->thread.regs));
271 void __user *mask = sp_to_mask(PT_REGS_SP(&current->thread.regs));
272 int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
274 spin_lock_irq(&current->sighand->siglock);
275 copy_from_user(&current->blocked.sig[0], sc_sigmask(sc),
276 sizeof(current->blocked.sig[0]));
277 copy_from_user(&current->blocked.sig[1], mask, sig_size);
278 sigdelsetmask(&current->blocked, ~_BLOCKABLE);
279 recalc_sigpending();
280 spin_unlock_irq(&current->sighand->siglock);
281 copy_sc_from_user(&current->thread.regs, sc,
282 &signal_frame_sc.common.arch);
283 return(PT_REGS_SYSCALL_RET(&current->thread.regs));
286 int sys_rt_sigreturn(struct pt_regs regs)
288 unsigned long sp = PT_REGS_SP(&current->thread.regs);
289 struct ucontext __user *uc = sp_to_uc(sp);
290 int sig_size = _NSIG_WORDS * sizeof(unsigned long);
292 spin_lock_irq(&current->sighand->siglock);
293 copy_from_user(&current->blocked, &uc->uc_sigmask, sig_size);
294 sigdelsetmask(&current->blocked, ~_BLOCKABLE);
295 recalc_sigpending();
296 spin_unlock_irq(&current->sighand->siglock);
297 copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext,
298 &signal_frame_si.common.arch);
299 return(PT_REGS_SYSCALL_RET(&current->thread.regs));
303 * Overrides for Emacs so that we follow Linus's tabbing style.
304 * Emacs will notice this stuff at the end of the file and automatically
305 * adjust the settings for this buffer only. This must remain at the end
306 * of the file.
307 * ---------------------------------------------------------------------------
308 * Local variables:
309 * c-file-style: "linux"
310 * End: