tile: compat rt_sigreturn gets too enthusiastic about sigaltstack errors
[sfrench/cifs-2.6.git] / arch / tile / kernel / compat_signal.c
1 /*
2  * Copyright 2010 Tilera Corporation. All Rights Reserved.
3  *
4  *   This program is free software; you can redistribute it and/or
5  *   modify it under the terms of the GNU General Public License
6  *   as published by the Free Software Foundation, version 2.
7  *
8  *   This program is distributed in the hope that it will be useful, but
9  *   WITHOUT ANY WARRANTY; without even the implied warranty of
10  *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11  *   NON INFRINGEMENT.  See the GNU General Public License for
12  *   more details.
13  */
14
15 #include <linux/sched.h>
16 #include <linux/mm.h>
17 #include <linux/smp.h>
18 #include <linux/kernel.h>
19 #include <linux/signal.h>
20 #include <linux/errno.h>
21 #include <linux/wait.h>
22 #include <linux/unistd.h>
23 #include <linux/stddef.h>
24 #include <linux/personality.h>
25 #include <linux/suspend.h>
26 #include <linux/ptrace.h>
27 #include <linux/elf.h>
28 #include <linux/compat.h>
29 #include <linux/syscalls.h>
30 #include <linux/uaccess.h>
31 #include <asm/processor.h>
32 #include <asm/ucontext.h>
33 #include <asm/sigframe.h>
34 #include <asm/syscalls.h>
35 #include <arch/interrupts.h>
36
37 struct compat_sigaction {
38         compat_uptr_t sa_handler;
39         compat_ulong_t sa_flags;
40         compat_uptr_t sa_restorer;
41         sigset_t sa_mask __packed;
42 };
43
44 struct compat_sigaltstack {
45         compat_uptr_t ss_sp;
46         int ss_flags;
47         compat_size_t ss_size;
48 };
49
50 struct compat_ucontext {
51         compat_ulong_t    uc_flags;
52         compat_uptr_t     uc_link;
53         struct compat_sigaltstack         uc_stack;
54         struct sigcontext uc_mcontext;
55         sigset_t          uc_sigmask;   /* mask last for extensibility */
56 };
57
58 struct compat_rt_sigframe {
59         unsigned char save_area[C_ABI_SAVE_AREA_SIZE]; /* caller save area */
60         struct compat_siginfo info;
61         struct compat_ucontext uc;
62 };
63
64 long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act,
65                              struct compat_sigaction __user *oact,
66                              size_t sigsetsize)
67 {
68         struct k_sigaction new_sa, old_sa;
69         int ret = -EINVAL;
70
71         /* XXX: Don't preclude handling different sized sigset_t's.  */
72         if (sigsetsize != sizeof(sigset_t))
73                 goto out;
74
75         if (act) {
76                 compat_uptr_t handler, restorer;
77
78                 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
79                     __get_user(handler, &act->sa_handler) ||
80                     __get_user(new_sa.sa.sa_flags, &act->sa_flags) ||
81                     __get_user(restorer, &act->sa_restorer) ||
82                     __copy_from_user(&new_sa.sa.sa_mask, &act->sa_mask,
83                                      sizeof(sigset_t)))
84                         return -EFAULT;
85                 new_sa.sa.sa_handler = compat_ptr(handler);
86                 new_sa.sa.sa_restorer = compat_ptr(restorer);
87         }
88
89         ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
90
91         if (!ret && oact) {
92                 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
93                     __put_user(ptr_to_compat(old_sa.sa.sa_handler),
94                                &oact->sa_handler) ||
95                     __put_user(ptr_to_compat(old_sa.sa.sa_restorer),
96                                &oact->sa_restorer) ||
97                     __put_user(old_sa.sa.sa_flags, &oact->sa_flags) ||
98                     __copy_to_user(&oact->sa_mask, &old_sa.sa.sa_mask,
99                                    sizeof(sigset_t)))
100                         return -EFAULT;
101         }
102 out:
103         return ret;
104 }
105
106 long compat_sys_rt_sigqueueinfo(int pid, int sig,
107                                 struct compat_siginfo __user *uinfo)
108 {
109         siginfo_t info;
110         int ret;
111         mm_segment_t old_fs = get_fs();
112
113         if (copy_siginfo_from_user32(&info, uinfo))
114                 return -EFAULT;
115         set_fs(KERNEL_DS);
116         ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __force __user *)&info);
117         set_fs(old_fs);
118         return ret;
119 }
120
121 int copy_siginfo_to_user32(struct compat_siginfo __user *to, siginfo_t *from)
122 {
123         int err;
124
125         if (!access_ok(VERIFY_WRITE, to, sizeof(struct compat_siginfo)))
126                 return -EFAULT;
127
128         /* If you change siginfo_t structure, please make sure that
129            this code is fixed accordingly.
130            It should never copy any pad contained in the structure
131            to avoid security leaks, but must copy the generic
132            3 ints plus the relevant union member.  */
133         err = __put_user(from->si_signo, &to->si_signo);
134         err |= __put_user(from->si_errno, &to->si_errno);
135         err |= __put_user((short)from->si_code, &to->si_code);
136
137         if (from->si_code < 0) {
138                 err |= __put_user(from->si_pid, &to->si_pid);
139                 err |= __put_user(from->si_uid, &to->si_uid);
140                 err |= __put_user(ptr_to_compat(from->si_ptr), &to->si_ptr);
141         } else {
142                 /*
143                  * First 32bits of unions are always present:
144                  * si_pid === si_band === si_tid === si_addr(LS half)
145                  */
146                 err |= __put_user(from->_sifields._pad[0],
147                                   &to->_sifields._pad[0]);
148                 switch (from->si_code >> 16) {
149                 case __SI_FAULT >> 16:
150                         break;
151                 case __SI_CHLD >> 16:
152                         err |= __put_user(from->si_utime, &to->si_utime);
153                         err |= __put_user(from->si_stime, &to->si_stime);
154                         err |= __put_user(from->si_status, &to->si_status);
155                         /* FALL THROUGH */
156                 default:
157                 case __SI_KILL >> 16:
158                         err |= __put_user(from->si_uid, &to->si_uid);
159                         break;
160                 case __SI_POLL >> 16:
161                         err |= __put_user(from->si_fd, &to->si_fd);
162                         break;
163                 case __SI_TIMER >> 16:
164                         err |= __put_user(from->si_overrun, &to->si_overrun);
165                         err |= __put_user(ptr_to_compat(from->si_ptr),
166                                           &to->si_ptr);
167                         break;
168                          /* This is not generated by the kernel as of now.  */
169                 case __SI_RT >> 16:
170                 case __SI_MESGQ >> 16:
171                         err |= __put_user(from->si_uid, &to->si_uid);
172                         err |= __put_user(from->si_int, &to->si_int);
173                         break;
174                 }
175         }
176         return err;
177 }
178
179 int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
180 {
181         int err;
182         u32 ptr32;
183
184         if (!access_ok(VERIFY_READ, from, sizeof(struct compat_siginfo)))
185                 return -EFAULT;
186
187         err = __get_user(to->si_signo, &from->si_signo);
188         err |= __get_user(to->si_errno, &from->si_errno);
189         err |= __get_user(to->si_code, &from->si_code);
190
191         err |= __get_user(to->si_pid, &from->si_pid);
192         err |= __get_user(to->si_uid, &from->si_uid);
193         err |= __get_user(ptr32, &from->si_ptr);
194         to->si_ptr = compat_ptr(ptr32);
195
196         return err;
197 }
198
199 long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
200                             struct compat_sigaltstack __user *uoss_ptr)
201 {
202         stack_t uss, uoss;
203         int ret;
204         mm_segment_t seg;
205
206         if (uss_ptr) {
207                 u32 ptr;
208
209                 memset(&uss, 0, sizeof(stack_t));
210                 if (!access_ok(VERIFY_READ, uss_ptr, sizeof(*uss_ptr)) ||
211                             __get_user(ptr, &uss_ptr->ss_sp) ||
212                             __get_user(uss.ss_flags, &uss_ptr->ss_flags) ||
213                             __get_user(uss.ss_size, &uss_ptr->ss_size))
214                         return -EFAULT;
215                 uss.ss_sp = compat_ptr(ptr);
216         }
217         seg = get_fs();
218         set_fs(KERNEL_DS);
219         ret = do_sigaltstack(uss_ptr ? (stack_t __user __force *)&uss : NULL,
220                              (stack_t __user __force *)&uoss,
221                              (unsigned long)compat_ptr(current_pt_regs()->sp));
222         set_fs(seg);
223         if (ret >= 0 && uoss_ptr)  {
224                 if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(*uoss_ptr)) ||
225                     __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) ||
226                     __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) ||
227                     __put_user(uoss.ss_size, &uoss_ptr->ss_size))
228                         ret = -EFAULT;
229         }
230         return ret;
231 }
232
233 /* The assembly shim for this function arranges to ignore the return value. */
234 long compat_sys_rt_sigreturn(void)
235 {
236         struct pt_regs *regs = current_pt_regs();
237         struct compat_rt_sigframe __user *frame =
238                 (struct compat_rt_sigframe __user *) compat_ptr(regs->sp);
239         sigset_t set;
240
241         if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
242                 goto badframe;
243         if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
244                 goto badframe;
245
246         set_current_blocked(&set);
247
248         if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
249                 goto badframe;
250
251         if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL) == -EFAULT)
252                 goto badframe;
253
254         return 0;
255
256 badframe:
257         signal_fault("bad sigreturn frame", regs, frame, 0);
258         return 0;
259 }
260
261 /*
262  * Determine which stack to use..
263  */
264 static inline void __user *compat_get_sigframe(struct k_sigaction *ka,
265                                                struct pt_regs *regs,
266                                                size_t frame_size)
267 {
268         unsigned long sp;
269
270         /* Default to using normal stack */
271         sp = (unsigned long)compat_ptr(regs->sp);
272
273         /*
274          * If we are on the alternate signal stack and would overflow
275          * it, don't.  Return an always-bogus address instead so we
276          * will die with SIGSEGV.
277          */
278         if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size)))
279                 return (void __user __force *)-1UL;
280
281         /* This is the X/Open sanctioned signal stack switching.  */
282         if (ka->sa.sa_flags & SA_ONSTACK) {
283                 if (sas_ss_flags(sp) == 0)
284                         sp = current->sas_ss_sp + current->sas_ss_size;
285         }
286
287         sp -= frame_size;
288         /*
289          * Align the stack pointer according to the TILE ABI,
290          * i.e. so that on function entry (sp & 15) == 0.
291          */
292         sp &= -16UL;
293         return (void __user *) sp;
294 }
295
296 int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
297                           sigset_t *set, struct pt_regs *regs)
298 {
299         unsigned long restorer;
300         struct compat_rt_sigframe __user *frame;
301         int err = 0;
302         int usig;
303
304         frame = compat_get_sigframe(ka, regs, sizeof(*frame));
305
306         if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
307                 goto give_sigsegv;
308
309         usig = current_thread_info()->exec_domain
310                 && current_thread_info()->exec_domain->signal_invmap
311                 && sig < 32
312                 ? current_thread_info()->exec_domain->signal_invmap[sig]
313                 : sig;
314
315         /* Always write at least the signal number for the stack backtracer. */
316         if (ka->sa.sa_flags & SA_SIGINFO) {
317                 /* At sigreturn time, restore the callee-save registers too. */
318                 err |= copy_siginfo_to_user32(&frame->info, info);
319                 regs->flags |= PT_FLAGS_RESTORE_REGS;
320         } else {
321                 err |= __put_user(info->si_signo, &frame->info.si_signo);
322         }
323
324         /* Create the ucontext.  */
325         err |= __clear_user(&frame->save_area, sizeof(frame->save_area));
326         err |= __put_user(0, &frame->uc.uc_flags);
327         err |= __put_user(0, &frame->uc.uc_link);
328         err |= __put_user(ptr_to_compat((void *)(current->sas_ss_sp)),
329                           &frame->uc.uc_stack.ss_sp);
330         err |= __put_user(sas_ss_flags(regs->sp),
331                           &frame->uc.uc_stack.ss_flags);
332         err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
333         err |= setup_sigcontext(&frame->uc.uc_mcontext, regs);
334         err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
335         if (err)
336                 goto give_sigsegv;
337
338         restorer = VDSO_BASE;
339         if (ka->sa.sa_flags & SA_RESTORER)
340                 restorer = ptr_to_compat_reg(ka->sa.sa_restorer);
341
342         /*
343          * Set up registers for signal handler.
344          * Registers that we don't modify keep the value they had from
345          * user-space at the time we took the signal.
346          * We always pass siginfo and mcontext, regardless of SA_SIGINFO,
347          * since some things rely on this (e.g. glibc's debug/segfault.c).
348          */
349         regs->pc = ptr_to_compat_reg(ka->sa.sa_handler);
350         regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */
351         regs->sp = ptr_to_compat_reg(frame);
352         regs->lr = restorer;
353         regs->regs[0] = (unsigned long) usig;
354         regs->regs[1] = ptr_to_compat_reg(&frame->info);
355         regs->regs[2] = ptr_to_compat_reg(&frame->uc);
356         regs->flags |= PT_FLAGS_CALLER_SAVES;
357         return 0;
358
359 give_sigsegv:
360         signal_fault("bad setup frame", regs, frame, sig);
361         return -EFAULT;
362 }