This commit was manufactured by cvs2svn to create tag
[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 static void force_segv(int sig)
35 {
36         if(sig == SIGSEGV){
37                 struct k_sigaction *ka;
38
39                 ka = &current->sighand->action[SIGSEGV - 1];
40                 ka->sa.sa_handler = SIG_DFL;
41         }
42         force_sig(SIGSEGV, current);
43 }
44
45 #define _S(nr) (1<<((nr)-1))
46
47 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
48
49 /*
50  * OK, we're invoking a handler
51  */     
52 static int handle_signal(struct pt_regs *regs, unsigned long signr, 
53                          struct k_sigaction *ka, siginfo_t *info, 
54                          sigset_t *oldset, int error)
55 {
56         __sighandler_t handler;
57         void (*restorer)(void);
58         unsigned long sp;
59         sigset_t save;
60         int err, ret;
61
62         ret = 0;
63         /* Always make any pending restarted system calls return -EINTR */
64         current_thread_info()->restart_block.fn = do_no_restart_syscall;
65         switch(error){
66         case -ERESTART_RESTARTBLOCK:
67         case -ERESTARTNOHAND:
68                 ret = -EINTR;
69                 break;
70
71         case -ERESTARTSYS:
72                 if (!(ka->sa.sa_flags & SA_RESTART)) {
73                         ret = -EINTR;
74                         break;
75                 }
76                 /* fallthrough */
77         case -ERESTARTNOINTR:
78                 PT_REGS_RESTART_SYSCALL(regs);
79                 PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
80
81                 /* This is because of the UM_SET_SYSCALL_RETURN and the fact
82                  * that on i386 the system call number and return value are
83                  * in the same register.  When the system call restarts, %eax
84                  * had better have the system call number in it.  Since the
85                  * return value doesn't matter (except that it shouldn't be
86                  * -ERESTART*), we'll stick the system call number there.
87                  */
88                 ret = PT_REGS_SYSCALL_NR(regs);
89                 break;
90         }
91
92         handler = ka->sa.sa_handler;
93         save = *oldset;
94
95         if (ka->sa.sa_flags & SA_ONESHOT)
96                 ka->sa.sa_handler = SIG_DFL;
97
98         if (!(ka->sa.sa_flags & SA_NODEFER)) {
99                 spin_lock_irq(&current->sighand->siglock);
100                 sigorsets(&current->blocked, &current->blocked, 
101                           &ka->sa.sa_mask);
102                 sigaddset(&current->blocked, signr);
103                 recalc_sigpending();
104                 spin_unlock_irq(&current->sighand->siglock);
105         }
106
107         sp = PT_REGS_SP(regs);
108
109         if((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
110                 sp = current->sas_ss_sp + current->sas_ss_size;
111         
112         if(error != 0) PT_REGS_SET_SYSCALL_RETURN(regs, ret);
113
114         if (ka->sa.sa_flags & SA_RESTORER) restorer = ka->sa.sa_restorer;
115         else restorer = NULL;
116
117         if(ka->sa.sa_flags & SA_SIGINFO)
118                 err = setup_signal_stack_si(sp, signr, (unsigned long) handler,
119                                             restorer, regs, info, &save);
120         else
121                 err = setup_signal_stack_sc(sp, signr, (unsigned long) handler,
122                                             restorer, regs, &save);
123         if(err) goto segv;
124
125         return(0);
126  segv:
127         force_segv(signr);
128         return(1);
129 }
130
131 static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset, int error)
132 {
133         siginfo_t info;
134         struct k_sigaction *ka;
135         int err, sig;
136
137         if (!oldset)
138                 oldset = &current->blocked;
139
140         sig = get_signal_to_deliver(&info, regs, NULL);
141         if(sig == 0)
142                 return(0);
143
144         /* Whee!  Actually deliver the signal.  */
145         ka = &current->sighand->action[sig -1 ];
146         err = handle_signal(regs, sig, ka, &info, oldset, error);
147         if(!err) return(1);
148
149         /* Did we come from a system call? */
150         if(PT_REGS_SYSCALL_NR(regs) >= 0){
151                 /* Restart the system call - no handlers present */
152                 if(PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOHAND ||
153                    PT_REGS_SYSCALL_RET(regs) == -ERESTARTSYS ||
154                    PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOINTR){
155                         PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
156                         PT_REGS_RESTART_SYSCALL(regs);
157                 }
158                 else if(PT_REGS_SYSCALL_RET(regs) == -ERESTART_RESTARTBLOCK){
159                         PT_REGS_SYSCALL_RET(regs) = __NR_restart_syscall;
160                         PT_REGS_RESTART_SYSCALL(regs);
161                 }
162         }
163
164         /* This closes a way to execute a system call on the host.  If
165          * you set a breakpoint on a system call instruction and singlestep
166          * from it, the tracing thread used to PTRACE_SINGLESTEP the process
167          * rather than PTRACE_SYSCALL it, allowing the system call to execute
168          * on the host.  The tracing thread will check this flag and 
169          * PTRACE_SYSCALL if necessary.
170          */
171         if((current->ptrace & PT_DTRACE) && 
172            is_syscall(PT_REGS_IP(&current->thread.regs)))
173                 (void) CHOOSE_MODE(current->thread.mode.tt.singlestep_syscall = 1, 0);
174         return(0);
175 }
176
177 int do_signal(int error)
178 {
179         return(kern_do_signal(&current->thread.regs, NULL, error));
180 }
181
182 /*
183  * Atomically swap in the new signal mask, and wait for a signal.
184  */
185 int sys_sigsuspend(int history0, int history1, old_sigset_t mask)
186 {
187         sigset_t saveset;
188
189         mask &= _BLOCKABLE;
190         spin_lock_irq(&current->sighand->siglock);
191         saveset = current->blocked;
192         siginitset(&current->blocked, mask);
193         recalc_sigpending();
194         spin_unlock_irq(&current->sighand->siglock);
195
196         while (1) {
197                 current->state = TASK_INTERRUPTIBLE;
198                 schedule();
199                 if(kern_do_signal(&current->thread.regs, &saveset, -EINTR))
200                         return(-EINTR);
201         }
202 }
203
204 int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
205 {
206         sigset_t saveset, newset;
207
208         /* XXX: Don't preclude handling different sized sigset_t's.  */
209         if (sigsetsize != sizeof(sigset_t))
210                 return -EINVAL;
211
212         if (copy_from_user(&newset, unewset, sizeof(newset)))
213                 return -EFAULT;
214         sigdelsetmask(&newset, ~_BLOCKABLE);
215
216         spin_lock_irq(&current->sighand->siglock);
217         saveset = current->blocked;
218         current->blocked = newset;
219         recalc_sigpending();
220         spin_unlock_irq(&current->sighand->siglock);
221
222         while (1) {
223                 current->state = TASK_INTERRUPTIBLE;
224                 schedule();
225                 if (kern_do_signal(&current->thread.regs, &saveset, -EINTR))
226                         return(-EINTR);
227         }
228 }
229
230 int sys_sigaction(int sig, const struct old_sigaction __user *act,
231                          struct old_sigaction __user *oact)
232 {
233         struct k_sigaction new_ka, old_ka;
234         int ret;
235
236         if (act) {
237                 old_sigset_t mask;
238                 if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
239                     __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
240                     __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
241                         return -EFAULT;
242                 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
243                 __get_user(mask, &act->sa_mask);
244                 siginitset(&new_ka.sa.sa_mask, mask);
245         }
246
247         ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
248
249         if (!ret && oact) {
250                 if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
251                     __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
252                     __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
253                         return -EFAULT;
254                 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
255                 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
256         }
257
258         return ret;
259 }
260
261 int sys_sigaltstack(const stack_t *uss, stack_t *uoss)
262 {
263         return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs)));
264 }
265
266 extern int userspace_pid[];
267
268 static int copy_sc_from_user(struct pt_regs *to, void *from, 
269                              struct arch_frame_data *arch)
270 {
271         int ret;
272
273         ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, arch),
274                           copy_sc_from_user_skas(userspace_pid[0], 
275                                                  &to->regs, from));
276         return(ret);
277 }
278
279 int sys_sigreturn(struct pt_regs regs)
280 {
281         void __user *sc = sp_to_sc(PT_REGS_SP(&current->thread.regs));
282         void __user *mask = sp_to_mask(PT_REGS_SP(&current->thread.regs));
283         int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
284
285         spin_lock_irq(&current->sighand->siglock);
286         copy_from_user(&current->blocked.sig[0], sc_sigmask(sc), 
287                        sizeof(current->blocked.sig[0]));
288         copy_from_user(&current->blocked.sig[1], mask, sig_size);
289         sigdelsetmask(&current->blocked, ~_BLOCKABLE);
290         recalc_sigpending();
291         spin_unlock_irq(&current->sighand->siglock);
292         copy_sc_from_user(&current->thread.regs, sc, 
293                           &signal_frame_sc.common.arch);
294         return(PT_REGS_SYSCALL_RET(&current->thread.regs));
295 }
296
297 int sys_rt_sigreturn(struct pt_regs regs)
298 {
299         unsigned long sp = PT_REGS_SP(&current->thread.regs);
300         struct ucontext __user *uc = sp_to_uc(sp);
301         int sig_size = _NSIG_WORDS * sizeof(unsigned long);
302
303         spin_lock_irq(&current->sighand->siglock);
304         copy_from_user(&current->blocked, &uc->uc_sigmask, sig_size);
305         sigdelsetmask(&current->blocked, ~_BLOCKABLE);
306         recalc_sigpending();
307         spin_unlock_irq(&current->sighand->siglock);
308         copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext,
309                           &signal_frame_si.common.arch);
310         return(PT_REGS_SYSCALL_RET(&current->thread.regs));
311 }
312
313 /*
314  * Overrides for Emacs so that we follow Linus's tabbing style.
315  * Emacs will notice this stuff at the end of the file and automatically
316  * adjust the settings for this buffer only.  This must remain at the end
317  * of the file.
318  * ---------------------------------------------------------------------------
319  * Local variables:
320  * c-file-style: "linux"
321  * End:
322  */