vserver 1.9.3
[linux-2.6.git] / arch / um / kernel / signal_kern.c
1 /* 
2  * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3  * Licensed under the GPL
4  */
5
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"
30
31 EXPORT_SYMBOL(block_signals);
32 EXPORT_SYMBOL(unblock_signals);
33
34 #define _S(nr) (1<<((nr)-1))
35
36 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
37
38 /*
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)
44 {
45         __sighandler_t handler;
46         void (*restorer)(void);
47         unsigned long sp;
48         sigset_t save;
49         int err, ret;
50
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;
59
60         case -ERESTARTSYS:
61                 if (!(ka->sa.sa_flags & SA_RESTART)) {
62                         ret = -EINTR;
63                         break;
64                 }
65                 /* fallthrough */
66         case -ERESTARTNOINTR:
67                 PT_REGS_RESTART_SYSCALL(regs);
68                 PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
69
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.
76                  */
77                 ret = PT_REGS_SYSCALL_NR(regs);
78                 break;
79         }
80
81         handler = ka->sa.sa_handler;
82         save = *oldset;
83
84         if (ka->sa.sa_flags & SA_ONESHOT)
85                 ka->sa.sa_handler = SIG_DFL;
86
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);
94         }
95
96         sp = PT_REGS_SP(regs);
97
98         if((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
99                 sp = current->sas_ss_sp + current->sas_ss_size;
100         
101         if(error != 0) PT_REGS_SET_SYSCALL_RETURN(regs, ret);
102
103         if (ka->sa.sa_flags & SA_RESTORER) restorer = ka->sa.sa_restorer;
104         else restorer = NULL;
105
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;
113
114         return(0);
115  segv:
116         force_sigsegv(signr, current);
117         return(1);
118 }
119
120 static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset, int error)
121 {
122         struct k_sigaction ka_copy;
123         siginfo_t info;
124         int err, sig;
125
126         if (!oldset)
127                 oldset = &current->blocked;
128
129         sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL);
130         if(sig == 0)
131                 return(0);
132
133         /* Whee!  Actually deliver the signal.  */
134         err = handle_signal(regs, sig, &ka_copy, &info, oldset, error);
135         if(!err)
136                 return(1);
137
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);
146                 }
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);
150                 }
151         }
152
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.
159          */
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);
164 }
165
166 int do_signal(int error)
167 {
168         return(kern_do_signal(&current->thread.regs, NULL, error));
169 }
170
171 /*
172  * Atomically swap in the new signal mask, and wait for a signal.
173  */
174 int sys_sigsuspend(int history0, int history1, old_sigset_t mask)
175 {
176         sigset_t saveset;
177
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);
184
185         while (1) {
186                 current->state = TASK_INTERRUPTIBLE;
187                 schedule();
188                 if(kern_do_signal(&current->thread.regs, &saveset, -EINTR))
189                         return(-EINTR);
190         }
191 }
192
193 int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
194 {
195         sigset_t saveset, newset;
196
197         /* XXX: Don't preclude handling different sized sigset_t's.  */
198         if (sigsetsize != sizeof(sigset_t))
199                 return -EINVAL;
200
201         if (copy_from_user(&newset, unewset, sizeof(newset)))
202                 return -EFAULT;
203         sigdelsetmask(&newset, ~_BLOCKABLE);
204
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);
210
211         while (1) {
212                 current->state = TASK_INTERRUPTIBLE;
213                 schedule();
214                 if (kern_do_signal(&current->thread.regs, &saveset, -EINTR))
215                         return(-EINTR);
216         }
217 }
218
219 int sys_sigaction(int sig, const struct old_sigaction __user *act,
220                          struct old_sigaction __user *oact)
221 {
222         struct k_sigaction new_ka, old_ka;
223         int ret;
224
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);
234         }
235
236         ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
237
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);
245         }
246
247         return ret;
248 }
249
250 int sys_sigaltstack(const stack_t *uss, stack_t *uoss)
251 {
252         return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs)));
253 }
254
255 extern int userspace_pid[];
256
257 static int copy_sc_from_user(struct pt_regs *to, void *from, 
258                              struct arch_frame_data *arch)
259 {
260         int ret;
261
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);
266 }
267
268 int sys_sigreturn(struct pt_regs regs)
269 {
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);
273
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));
284 }
285
286 int sys_rt_sigreturn(struct pt_regs regs)
287 {
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);
291
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));
300 }
301
302 /*
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:
311  */