]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blob - arch/tile/kernel/compat_signal.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
[mirror_ubuntu-zesty-kernel.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 struct pt_regs *regs)
202 {
203 stack_t uss, uoss;
204 int ret;
205 mm_segment_t seg;
206
207 if (uss_ptr) {
208 u32 ptr;
209
210 memset(&uss, 0, sizeof(stack_t));
211 if (!access_ok(VERIFY_READ, uss_ptr, sizeof(*uss_ptr)) ||
212 __get_user(ptr, &uss_ptr->ss_sp) ||
213 __get_user(uss.ss_flags, &uss_ptr->ss_flags) ||
214 __get_user(uss.ss_size, &uss_ptr->ss_size))
215 return -EFAULT;
216 uss.ss_sp = compat_ptr(ptr);
217 }
218 seg = get_fs();
219 set_fs(KERNEL_DS);
220 ret = do_sigaltstack(uss_ptr ? (stack_t __user __force *)&uss : NULL,
221 (stack_t __user __force *)&uoss,
222 (unsigned long)compat_ptr(regs->sp));
223 set_fs(seg);
224 if (ret >= 0 && uoss_ptr) {
225 if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(*uoss_ptr)) ||
226 __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) ||
227 __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) ||
228 __put_user(uoss.ss_size, &uoss_ptr->ss_size))
229 ret = -EFAULT;
230 }
231 return ret;
232 }
233
234 /* The assembly shim for this function arranges to ignore the return value. */
235 long compat_sys_rt_sigreturn(struct pt_regs *regs)
236 {
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, regs) != 0)
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 }