1
2
3
4
5
6
7
8
9
10
11
12
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
37struct 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
44struct compat_sigaltstack {
45 compat_uptr_t ss_sp;
46 int ss_flags;
47 compat_size_t ss_size;
48};
49
50struct 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;
56};
57
58#define COMPAT_SI_PAD_SIZE ((SI_MAX_SIZE - 3 * sizeof(int)) / sizeof(int))
59
60struct compat_siginfo {
61 int si_signo;
62 int si_errno;
63 int si_code;
64
65 union {
66 int _pad[COMPAT_SI_PAD_SIZE];
67
68
69 struct {
70 unsigned int _pid;
71 unsigned int _uid;
72 } _kill;
73
74
75 struct {
76 compat_timer_t _tid;
77 int _overrun;
78 compat_sigval_t _sigval;
79 int _sys_private;
80 int _overrun_incr;
81 } _timer;
82
83
84 struct {
85 unsigned int _pid;
86 unsigned int _uid;
87 compat_sigval_t _sigval;
88 } _rt;
89
90
91 struct {
92 unsigned int _pid;
93 unsigned int _uid;
94 int _status;
95 compat_clock_t _utime;
96 compat_clock_t _stime;
97 } _sigchld;
98
99
100 struct {
101 unsigned int _addr;
102#ifdef __ARCH_SI_TRAPNO
103 int _trapno;
104#endif
105 } _sigfault;
106
107
108 struct {
109 int _band;
110 int _fd;
111 } _sigpoll;
112 } _sifields;
113};
114
115struct compat_rt_sigframe {
116 unsigned char save_area[C_ABI_SAVE_AREA_SIZE];
117 struct compat_siginfo info;
118 struct compat_ucontext uc;
119};
120
121#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
122
123long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act,
124 struct compat_sigaction __user *oact,
125 size_t sigsetsize)
126{
127 struct k_sigaction new_sa, old_sa;
128 int ret = -EINVAL;
129
130
131 if (sigsetsize != sizeof(sigset_t))
132 goto out;
133
134 if (act) {
135 compat_uptr_t handler, restorer;
136
137 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
138 __get_user(handler, &act->sa_handler) ||
139 __get_user(new_sa.sa.sa_flags, &act->sa_flags) ||
140 __get_user(restorer, &act->sa_restorer) ||
141 __copy_from_user(&new_sa.sa.sa_mask, &act->sa_mask,
142 sizeof(sigset_t)))
143 return -EFAULT;
144 new_sa.sa.sa_handler = compat_ptr(handler);
145 new_sa.sa.sa_restorer = compat_ptr(restorer);
146 }
147
148 ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
149
150 if (!ret && oact) {
151 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
152 __put_user(ptr_to_compat(old_sa.sa.sa_handler),
153 &oact->sa_handler) ||
154 __put_user(ptr_to_compat(old_sa.sa.sa_restorer),
155 &oact->sa_restorer) ||
156 __put_user(old_sa.sa.sa_flags, &oact->sa_flags) ||
157 __copy_to_user(&oact->sa_mask, &old_sa.sa.sa_mask,
158 sizeof(sigset_t)))
159 return -EFAULT;
160 }
161out:
162 return ret;
163}
164
165long compat_sys_rt_sigqueueinfo(int pid, int sig,
166 struct compat_siginfo __user *uinfo)
167{
168 siginfo_t info;
169 int ret;
170 mm_segment_t old_fs = get_fs();
171
172 if (copy_siginfo_from_user32(&info, uinfo))
173 return -EFAULT;
174 set_fs(KERNEL_DS);
175 ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __force __user *)&info);
176 set_fs(old_fs);
177 return ret;
178}
179
180int copy_siginfo_to_user32(struct compat_siginfo __user *to, siginfo_t *from)
181{
182 int err;
183
184 if (!access_ok(VERIFY_WRITE, to, sizeof(struct compat_siginfo)))
185 return -EFAULT;
186
187
188
189
190
191
192 err = __put_user(from->si_signo, &to->si_signo);
193 err |= __put_user(from->si_errno, &to->si_errno);
194 err |= __put_user((short)from->si_code, &to->si_code);
195
196 if (from->si_code < 0) {
197 err |= __put_user(from->si_pid, &to->si_pid);
198 err |= __put_user(from->si_uid, &to->si_uid);
199 err |= __put_user(ptr_to_compat(from->si_ptr), &to->si_ptr);
200 } else {
201
202
203
204
205 err |= __put_user(from->_sifields._pad[0],
206 &to->_sifields._pad[0]);
207 switch (from->si_code >> 16) {
208 case __SI_FAULT >> 16:
209 break;
210 case __SI_CHLD >> 16:
211 err |= __put_user(from->si_utime, &to->si_utime);
212 err |= __put_user(from->si_stime, &to->si_stime);
213 err |= __put_user(from->si_status, &to->si_status);
214
215 default:
216 case __SI_KILL >> 16:
217 err |= __put_user(from->si_uid, &to->si_uid);
218 break;
219 case __SI_POLL >> 16:
220 err |= __put_user(from->si_fd, &to->si_fd);
221 break;
222 case __SI_TIMER >> 16:
223 err |= __put_user(from->si_overrun, &to->si_overrun);
224 err |= __put_user(ptr_to_compat(from->si_ptr),
225 &to->si_ptr);
226 break;
227
228 case __SI_RT >> 16:
229 case __SI_MESGQ >> 16:
230 err |= __put_user(from->si_uid, &to->si_uid);
231 err |= __put_user(from->si_int, &to->si_int);
232 break;
233 }
234 }
235 return err;
236}
237
238int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
239{
240 int err;
241 u32 ptr32;
242
243 if (!access_ok(VERIFY_READ, from, sizeof(struct compat_siginfo)))
244 return -EFAULT;
245
246 err = __get_user(to->si_signo, &from->si_signo);
247 err |= __get_user(to->si_errno, &from->si_errno);
248 err |= __get_user(to->si_code, &from->si_code);
249
250 err |= __get_user(to->si_pid, &from->si_pid);
251 err |= __get_user(to->si_uid, &from->si_uid);
252 err |= __get_user(ptr32, &from->si_ptr);
253 to->si_ptr = compat_ptr(ptr32);
254
255 return err;
256}
257
258long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
259 struct compat_sigaltstack __user *uoss_ptr,
260 struct pt_regs *regs)
261{
262 stack_t uss, uoss;
263 int ret;
264 mm_segment_t seg;
265
266 if (uss_ptr) {
267 u32 ptr;
268
269 memset(&uss, 0, sizeof(stack_t));
270 if (!access_ok(VERIFY_READ, uss_ptr, sizeof(*uss_ptr)) ||
271 __get_user(ptr, &uss_ptr->ss_sp) ||
272 __get_user(uss.ss_flags, &uss_ptr->ss_flags) ||
273 __get_user(uss.ss_size, &uss_ptr->ss_size))
274 return -EFAULT;
275 uss.ss_sp = compat_ptr(ptr);
276 }
277 seg = get_fs();
278 set_fs(KERNEL_DS);
279 ret = do_sigaltstack(uss_ptr ? (stack_t __user __force *)&uss : NULL,
280 (stack_t __user __force *)&uoss,
281 (unsigned long)compat_ptr(regs->sp));
282 set_fs(seg);
283 if (ret >= 0 && uoss_ptr) {
284 if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(*uoss_ptr)) ||
285 __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) ||
286 __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) ||
287 __put_user(uoss.ss_size, &uoss_ptr->ss_size))
288 ret = -EFAULT;
289 }
290 return ret;
291}
292
293
294long compat_sys_rt_sigreturn(struct pt_regs *regs)
295{
296 struct compat_rt_sigframe __user *frame =
297 (struct compat_rt_sigframe __user *) compat_ptr(regs->sp);
298 sigset_t set;
299
300 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
301 goto badframe;
302 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
303 goto badframe;
304
305 sigdelsetmask(&set, ~_BLOCKABLE);
306 spin_lock_irq(¤t->sighand->siglock);
307 current->blocked = set;
308 recalc_sigpending();
309 spin_unlock_irq(¤t->sighand->siglock);
310
311 if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
312 goto badframe;
313
314 if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0)
315 goto badframe;
316
317 return 0;
318
319badframe:
320 signal_fault("bad sigreturn frame", regs, frame, 0);
321 return 0;
322}
323
324
325
326
327static inline void __user *compat_get_sigframe(struct k_sigaction *ka,
328 struct pt_regs *regs,
329 size_t frame_size)
330{
331 unsigned long sp;
332
333
334 sp = (unsigned long)compat_ptr(regs->sp);
335
336
337
338
339
340
341 if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size)))
342 return (void __user __force *)-1UL;
343
344
345 if (ka->sa.sa_flags & SA_ONSTACK) {
346 if (sas_ss_flags(sp) == 0)
347 sp = current->sas_ss_sp + current->sas_ss_size;
348 }
349
350 sp -= frame_size;
351
352
353
354
355 sp &= -16UL;
356 return (void __user *) sp;
357}
358
359int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
360 sigset_t *set, struct pt_regs *regs)
361{
362 unsigned long restorer;
363 struct compat_rt_sigframe __user *frame;
364 int err = 0;
365 int usig;
366
367 frame = compat_get_sigframe(ka, regs, sizeof(*frame));
368
369 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
370 goto give_sigsegv;
371
372 usig = current_thread_info()->exec_domain
373 && current_thread_info()->exec_domain->signal_invmap
374 && sig < 32
375 ? current_thread_info()->exec_domain->signal_invmap[sig]
376 : sig;
377
378
379 if (ka->sa.sa_flags & SA_SIGINFO) {
380
381 err |= copy_siginfo_to_user32(&frame->info, info);
382 regs->flags |= PT_FLAGS_RESTORE_REGS;
383 } else {
384 err |= __put_user(info->si_signo, &frame->info.si_signo);
385 }
386
387
388 err |= __clear_user(&frame->save_area, sizeof(frame->save_area));
389 err |= __put_user(0, &frame->uc.uc_flags);
390 err |= __put_user(0, &frame->uc.uc_link);
391 err |= __put_user(ptr_to_compat((void *)(current->sas_ss_sp)),
392 &frame->uc.uc_stack.ss_sp);
393 err |= __put_user(sas_ss_flags(regs->sp),
394 &frame->uc.uc_stack.ss_flags);
395 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
396 err |= setup_sigcontext(&frame->uc.uc_mcontext, regs);
397 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
398 if (err)
399 goto give_sigsegv;
400
401 restorer = VDSO_BASE;
402 if (ka->sa.sa_flags & SA_RESTORER)
403 restorer = ptr_to_compat_reg(ka->sa.sa_restorer);
404
405
406
407
408
409
410 regs->pc = ptr_to_compat_reg(ka->sa.sa_handler);
411 regs->ex1 = PL_ICS_EX1(USER_PL, 1);
412 regs->sp = ptr_to_compat_reg(frame);
413 regs->lr = restorer;
414 regs->regs[0] = (unsigned long) usig;
415
416 if (ka->sa.sa_flags & SA_SIGINFO) {
417
418 regs->regs[1] = ptr_to_compat_reg(&frame->info);
419 regs->regs[2] = ptr_to_compat_reg(&frame->uc);
420 regs->flags |= PT_FLAGS_CALLER_SAVES;
421 }
422
423
424
425
426
427
428 if (test_thread_flag(TIF_SINGLESTEP))
429 ptrace_notify(SIGTRAP);
430
431 return 0;
432
433give_sigsegv:
434 signal_fault("bad setup frame", regs, frame, sig);
435 return -EFAULT;
436}
437