2 * Based on arch/arm/kernel/signal.c
4 * Copyright (C) 1995-2009 Russell King
5 * Copyright (C) 2012 ARM Ltd.
6 * Modified by Will Deacon <will.deacon@arm.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #define __SYSCALL_COMPAT
23 #include <linux/compat.h>
24 #include <linux/signal.h>
25 #include <linux/syscalls.h>
26 #include <linux/ratelimit.h>
28 #include <asm/fpsimd.h>
29 #include <asm/signal32.h>
30 #include <asm/uaccess.h>
31 #include <asm/unistd.h>
33 struct compat_sigaction
{
34 compat_uptr_t sa_handler
;
35 compat_ulong_t sa_flags
;
36 compat_uptr_t sa_restorer
;
37 compat_sigset_t sa_mask
;
40 struct compat_old_sigaction
{
41 compat_uptr_t sa_handler
;
42 compat_old_sigset_t sa_mask
;
43 compat_ulong_t sa_flags
;
44 compat_uptr_t sa_restorer
;
47 typedef struct compat_sigaltstack
{
50 compat_size_t ss_size
;
53 struct compat_sigcontext
{
54 /* We always set these two fields to 0 */
55 compat_ulong_t trap_no
;
56 compat_ulong_t error_code
;
58 compat_ulong_t oldmask
;
59 compat_ulong_t arm_r0
;
60 compat_ulong_t arm_r1
;
61 compat_ulong_t arm_r2
;
62 compat_ulong_t arm_r3
;
63 compat_ulong_t arm_r4
;
64 compat_ulong_t arm_r5
;
65 compat_ulong_t arm_r6
;
66 compat_ulong_t arm_r7
;
67 compat_ulong_t arm_r8
;
68 compat_ulong_t arm_r9
;
69 compat_ulong_t arm_r10
;
70 compat_ulong_t arm_fp
;
71 compat_ulong_t arm_ip
;
72 compat_ulong_t arm_sp
;
73 compat_ulong_t arm_lr
;
74 compat_ulong_t arm_pc
;
75 compat_ulong_t arm_cpsr
;
76 compat_ulong_t fault_address
;
79 struct compat_ucontext
{
80 compat_ulong_t uc_flags
;
81 struct compat_ucontext
*uc_link
;
82 compat_stack_t uc_stack
;
83 struct compat_sigcontext uc_mcontext
;
84 compat_sigset_t uc_sigmask
;
85 int __unused
[32 - (sizeof (compat_sigset_t
) / sizeof (int))];
86 compat_ulong_t uc_regspace
[128] __attribute__((__aligned__(8)));
89 struct compat_vfp_sigframe
{
92 struct compat_user_vfp
{
93 compat_u64 fpregs
[32];
96 struct compat_user_vfp_exc
{
98 compat_ulong_t fpinst
;
99 compat_ulong_t fpinst2
;
101 } __attribute__((__aligned__(8)));
103 #define VFP_MAGIC 0x56465001
104 #define VFP_STORAGE_SIZE sizeof(struct compat_vfp_sigframe)
106 struct compat_aux_sigframe
{
107 struct compat_vfp_sigframe vfp
;
109 /* Something that isn't a valid magic number for any coprocessor. */
110 unsigned long end_magic
;
111 } __attribute__((__aligned__(8)));
113 struct compat_sigframe
{
114 struct compat_ucontext uc
;
115 compat_ulong_t retcode
[2];
118 struct compat_rt_sigframe
{
119 struct compat_siginfo info
;
120 struct compat_sigframe sig
;
123 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
126 * For ARM syscalls, the syscall number has to be loaded into r7.
127 * We do not support an OABI userspace.
129 #define MOV_R7_NR_SIGRETURN (0xe3a07000 | __NR_compat_sigreturn)
130 #define SVC_SYS_SIGRETURN (0xef000000 | __NR_compat_sigreturn)
131 #define MOV_R7_NR_RT_SIGRETURN (0xe3a07000 | __NR_compat_rt_sigreturn)
132 #define SVC_SYS_RT_SIGRETURN (0xef000000 | __NR_compat_rt_sigreturn)
135 * For Thumb syscalls, we also pass the syscall number via r7. We therefore
136 * need two 16-bit instructions.
138 #define SVC_THUMB_SIGRETURN (((0xdf00 | __NR_compat_sigreturn) << 16) | \
139 0x2700 | __NR_compat_sigreturn)
140 #define SVC_THUMB_RT_SIGRETURN (((0xdf00 | __NR_compat_rt_sigreturn) << 16) | \
141 0x2700 | __NR_compat_rt_sigreturn)
143 const compat_ulong_t aarch32_sigret_code
[6] = {
145 * AArch32 sigreturn code.
146 * We don't construct an OABI SWI - instead we just set the imm24 field
147 * to the EABI syscall number so that we create a sane disassembly.
149 MOV_R7_NR_SIGRETURN
, SVC_SYS_SIGRETURN
, SVC_THUMB_SIGRETURN
,
150 MOV_R7_NR_RT_SIGRETURN
, SVC_SYS_RT_SIGRETURN
, SVC_THUMB_RT_SIGRETURN
,
153 static inline int put_sigset_t(compat_sigset_t __user
*uset
, sigset_t
*set
)
155 compat_sigset_t cset
;
157 cset
.sig
[0] = set
->sig
[0] & 0xffffffffull
;
158 cset
.sig
[1] = set
->sig
[0] >> 32;
160 return copy_to_user(uset
, &cset
, sizeof(*uset
));
163 static inline int get_sigset_t(sigset_t
*set
,
164 const compat_sigset_t __user
*uset
)
168 if (copy_from_user(&s32
, uset
, sizeof(*uset
)))
171 set
->sig
[0] = s32
.sig
[0] | (((long)s32
.sig
[1]) << 32);
175 int copy_siginfo_to_user32(compat_siginfo_t __user
*to
, siginfo_t
*from
)
179 if (!access_ok(VERIFY_WRITE
, to
, sizeof(*to
)))
182 /* If you change siginfo_t structure, please be sure
183 * this code is fixed accordingly.
184 * It should never copy any pad contained in the structure
185 * to avoid security leaks, but must copy the generic
186 * 3 ints plus the relevant union member.
187 * This routine must convert siginfo from 64bit to 32bit as well
190 err
= __put_user(from
->si_signo
, &to
->si_signo
);
191 err
|= __put_user(from
->si_errno
, &to
->si_errno
);
192 err
|= __put_user((short)from
->si_code
, &to
->si_code
);
193 if (from
->si_code
< 0)
194 err
|= __copy_to_user(&to
->_sifields
._pad
, &from
->_sifields
._pad
,
196 else switch (from
->si_code
& __SI_MASK
) {
198 err
|= __put_user(from
->si_pid
, &to
->si_pid
);
199 err
|= __put_user(from
->si_uid
, &to
->si_uid
);
202 err
|= __put_user(from
->si_tid
, &to
->si_tid
);
203 err
|= __put_user(from
->si_overrun
, &to
->si_overrun
);
204 err
|= __put_user((compat_uptr_t
)(unsigned long)from
->si_ptr
,
208 err
|= __put_user(from
->si_band
, &to
->si_band
);
209 err
|= __put_user(from
->si_fd
, &to
->si_fd
);
212 err
|= __put_user((compat_uptr_t
)(unsigned long)from
->si_addr
,
216 * Other callers might not initialize the si_lsb field,
217 * so check explicitely for the right codes here.
219 if (from
->si_code
== BUS_MCEERR_AR
|| from
->si_code
== BUS_MCEERR_AO
)
220 err
|= __put_user(from
->si_addr_lsb
, &to
->si_addr_lsb
);
224 err
|= __put_user(from
->si_pid
, &to
->si_pid
);
225 err
|= __put_user(from
->si_uid
, &to
->si_uid
);
226 err
|= __put_user(from
->si_status
, &to
->si_status
);
227 err
|= __put_user(from
->si_utime
, &to
->si_utime
);
228 err
|= __put_user(from
->si_stime
, &to
->si_stime
);
230 case __SI_RT
: /* This is not generated by the kernel as of now. */
231 case __SI_MESGQ
: /* But this is */
232 err
|= __put_user(from
->si_pid
, &to
->si_pid
);
233 err
|= __put_user(from
->si_uid
, &to
->si_uid
);
234 err
|= __put_user((compat_uptr_t
)(unsigned long)from
->si_ptr
, &to
->si_ptr
);
236 default: /* this is just in case for now ... */
237 err
|= __put_user(from
->si_pid
, &to
->si_pid
);
238 err
|= __put_user(from
->si_uid
, &to
->si_uid
);
244 int copy_siginfo_from_user32(siginfo_t
*to
, compat_siginfo_t __user
*from
)
246 memset(to
, 0, sizeof *to
);
248 if (copy_from_user(to
, from
, __ARCH_SI_PREAMBLE_SIZE
) ||
249 copy_from_user(to
->_sifields
._pad
,
250 from
->_sifields
._pad
, SI_PAD_SIZE
))
257 * VFP save/restore code.
259 static int compat_preserve_vfp_context(struct compat_vfp_sigframe __user
*frame
)
261 struct fpsimd_state
*fpsimd
= ¤t
->thread
.fpsimd_state
;
262 compat_ulong_t magic
= VFP_MAGIC
;
263 compat_ulong_t size
= VFP_STORAGE_SIZE
;
264 compat_ulong_t fpscr
, fpexc
;
268 * Save the hardware registers to the fpsimd_state structure.
269 * Note that this also saves V16-31, which aren't visible
272 fpsimd_save_state(fpsimd
);
274 /* Place structure header on the stack */
275 __put_user_error(magic
, &frame
->magic
, err
);
276 __put_user_error(size
, &frame
->size
, err
);
279 * Now copy the FP registers. Since the registers are packed,
280 * we can copy the prefix we want (V0-V15) as it is.
281 * FIXME: Won't work if big endian.
283 err
|= __copy_to_user(&frame
->ufp
.fpregs
, fpsimd
->vregs
,
284 sizeof(frame
->ufp
.fpregs
));
286 /* Create an AArch32 fpscr from the fpsr and the fpcr. */
287 fpscr
= (fpsimd
->fpsr
& VFP_FPSCR_STAT_MASK
) |
288 (fpsimd
->fpcr
& VFP_FPSCR_CTRL_MASK
);
289 __put_user_error(fpscr
, &frame
->ufp
.fpscr
, err
);
292 * The exception register aren't available so we fake up a
293 * basic FPEXC and zero everything else.
296 __put_user_error(fpexc
, &frame
->ufp_exc
.fpexc
, err
);
297 __put_user_error(0, &frame
->ufp_exc
.fpinst
, err
);
298 __put_user_error(0, &frame
->ufp_exc
.fpinst2
, err
);
300 return err
? -EFAULT
: 0;
303 static int compat_restore_vfp_context(struct compat_vfp_sigframe __user
*frame
)
305 struct fpsimd_state fpsimd
;
306 compat_ulong_t magic
= VFP_MAGIC
;
307 compat_ulong_t size
= VFP_STORAGE_SIZE
;
308 compat_ulong_t fpscr
;
311 __get_user_error(magic
, &frame
->magic
, err
);
312 __get_user_error(size
, &frame
->size
, err
);
316 if (magic
!= VFP_MAGIC
|| size
!= VFP_STORAGE_SIZE
)
320 * Copy the FP registers into the start of the fpsimd_state.
321 * FIXME: Won't work if big endian.
323 err
|= __copy_from_user(fpsimd
.vregs
, frame
->ufp
.fpregs
,
324 sizeof(frame
->ufp
.fpregs
));
326 /* Extract the fpsr and the fpcr from the fpscr */
327 __get_user_error(fpscr
, &frame
->ufp
.fpscr
, err
);
328 fpsimd
.fpsr
= fpscr
& VFP_FPSCR_STAT_MASK
;
329 fpsimd
.fpcr
= fpscr
& VFP_FPSCR_CTRL_MASK
;
332 * We don't need to touch the exception register, so
333 * reload the hardware state.
337 fpsimd_load_state(&fpsimd
);
341 return err
? -EFAULT
: 0;
345 * atomically swap in the new signal mask, and wait for a signal.
347 asmlinkage
int compat_sys_sigsuspend(int restart
, compat_ulong_t oldmask
,
348 compat_old_sigset_t mask
)
352 siginitset(¤t
->blocked
, mask
);
353 return sigsuspend(&blocked
);
356 asmlinkage
int compat_sys_sigaction(int sig
,
357 const struct compat_old_sigaction __user
*act
,
358 struct compat_old_sigaction __user
*oact
)
360 struct k_sigaction new_ka
, old_ka
;
362 compat_old_sigset_t mask
;
363 compat_uptr_t handler
, restorer
;
366 if (!access_ok(VERIFY_READ
, act
, sizeof(*act
)) ||
367 __get_user(handler
, &act
->sa_handler
) ||
368 __get_user(restorer
, &act
->sa_restorer
) ||
369 __get_user(new_ka
.sa
.sa_flags
, &act
->sa_flags
) ||
370 __get_user(mask
, &act
->sa_mask
))
373 new_ka
.sa
.sa_handler
= compat_ptr(handler
);
374 new_ka
.sa
.sa_restorer
= compat_ptr(restorer
);
375 siginitset(&new_ka
.sa
.sa_mask
, mask
);
378 ret
= do_sigaction(sig
, act
? &new_ka
: NULL
, oact
? &old_ka
: NULL
);
381 if (!access_ok(VERIFY_WRITE
, oact
, sizeof(*oact
)) ||
382 __put_user(ptr_to_compat(old_ka
.sa
.sa_handler
),
383 &oact
->sa_handler
) ||
384 __put_user(ptr_to_compat(old_ka
.sa
.sa_restorer
),
385 &oact
->sa_restorer
) ||
386 __put_user(old_ka
.sa
.sa_flags
, &oact
->sa_flags
) ||
387 __put_user(old_ka
.sa
.sa_mask
.sig
[0], &oact
->sa_mask
))
394 asmlinkage
int compat_sys_rt_sigaction(int sig
,
395 const struct compat_sigaction __user
*act
,
396 struct compat_sigaction __user
*oact
,
397 compat_size_t sigsetsize
)
399 struct k_sigaction new_ka
, old_ka
;
402 /* XXX: Don't preclude handling different sized sigset_t's. */
403 if (sigsetsize
!= sizeof(compat_sigset_t
))
407 compat_uptr_t handler
, restorer
;
409 ret
= get_user(handler
, &act
->sa_handler
);
410 new_ka
.sa
.sa_handler
= compat_ptr(handler
);
411 ret
|= get_user(restorer
, &act
->sa_restorer
);
412 new_ka
.sa
.sa_restorer
= compat_ptr(restorer
);
413 ret
|= get_sigset_t(&new_ka
.sa
.sa_mask
, &act
->sa_mask
);
414 ret
|= __get_user(new_ka
.sa
.sa_flags
, &act
->sa_flags
);
419 ret
= do_sigaction(sig
, act
? &new_ka
: NULL
, oact
? &old_ka
: NULL
);
421 ret
= put_user(ptr_to_compat(old_ka
.sa
.sa_handler
), &oact
->sa_handler
);
422 ret
|= put_sigset_t(&oact
->sa_mask
, &old_ka
.sa
.sa_mask
);
423 ret
|= __put_user(old_ka
.sa
.sa_flags
, &oact
->sa_flags
);
428 int compat_do_sigaltstack(compat_uptr_t compat_uss
, compat_uptr_t compat_uoss
,
431 compat_stack_t __user
*newstack
= compat_ptr(compat_uss
);
432 compat_stack_t __user
*oldstack
= compat_ptr(compat_uoss
);
438 /* Marshall the compat new stack into a stack_t */
440 if (get_user(ss_sp
, &newstack
->ss_sp
) ||
441 __get_user(uss
.ss_flags
, &newstack
->ss_flags
) ||
442 __get_user(uss
.ss_size
, &newstack
->ss_size
))
444 uss
.ss_sp
= compat_ptr(ss_sp
);
449 /* The __user pointer casts are valid because of the set_fs() */
450 ret
= do_sigaltstack(
451 newstack
? (stack_t __user
*) &uss
: NULL
,
452 oldstack
? (stack_t __user
*) &uoss
: NULL
,
456 /* Convert the old stack_t into a compat stack. */
457 if (!ret
&& oldstack
&&
458 (put_user(ptr_to_compat(uoss
.ss_sp
), &oldstack
->ss_sp
) ||
459 __put_user(uoss
.ss_flags
, &oldstack
->ss_flags
) ||
460 __put_user(uoss
.ss_size
, &oldstack
->ss_size
)))
465 static int compat_restore_sigframe(struct pt_regs
*regs
,
466 struct compat_sigframe __user
*sf
)
470 struct compat_aux_sigframe __user
*aux
;
472 err
= get_sigset_t(&set
, &sf
->uc
.uc_sigmask
);
474 sigdelsetmask(&set
, ~_BLOCKABLE
);
475 set_current_blocked(&set
);
478 __get_user_error(regs
->regs
[0], &sf
->uc
.uc_mcontext
.arm_r0
, err
);
479 __get_user_error(regs
->regs
[1], &sf
->uc
.uc_mcontext
.arm_r1
, err
);
480 __get_user_error(regs
->regs
[2], &sf
->uc
.uc_mcontext
.arm_r2
, err
);
481 __get_user_error(regs
->regs
[3], &sf
->uc
.uc_mcontext
.arm_r3
, err
);
482 __get_user_error(regs
->regs
[4], &sf
->uc
.uc_mcontext
.arm_r4
, err
);
483 __get_user_error(regs
->regs
[5], &sf
->uc
.uc_mcontext
.arm_r5
, err
);
484 __get_user_error(regs
->regs
[6], &sf
->uc
.uc_mcontext
.arm_r6
, err
);
485 __get_user_error(regs
->regs
[7], &sf
->uc
.uc_mcontext
.arm_r7
, err
);
486 __get_user_error(regs
->regs
[8], &sf
->uc
.uc_mcontext
.arm_r8
, err
);
487 __get_user_error(regs
->regs
[9], &sf
->uc
.uc_mcontext
.arm_r9
, err
);
488 __get_user_error(regs
->regs
[10], &sf
->uc
.uc_mcontext
.arm_r10
, err
);
489 __get_user_error(regs
->regs
[11], &sf
->uc
.uc_mcontext
.arm_fp
, err
);
490 __get_user_error(regs
->regs
[12], &sf
->uc
.uc_mcontext
.arm_ip
, err
);
491 __get_user_error(regs
->compat_sp
, &sf
->uc
.uc_mcontext
.arm_sp
, err
);
492 __get_user_error(regs
->compat_lr
, &sf
->uc
.uc_mcontext
.arm_lr
, err
);
493 __get_user_error(regs
->pc
, &sf
->uc
.uc_mcontext
.arm_pc
, err
);
494 __get_user_error(regs
->pstate
, &sf
->uc
.uc_mcontext
.arm_cpsr
, err
);
497 * Avoid compat_sys_sigreturn() restarting.
499 regs
->syscallno
= ~0UL;
501 err
|= !valid_user_regs(®s
->user_regs
);
503 aux
= (struct compat_aux_sigframe __user
*) sf
->uc
.uc_regspace
;
505 err
|= compat_restore_vfp_context(&aux
->vfp
);
510 asmlinkage
int compat_sys_sigreturn(struct pt_regs
*regs
)
512 struct compat_sigframe __user
*frame
;
514 /* Always make any pending restarted system calls return -EINTR */
515 current_thread_info()->restart_block
.fn
= do_no_restart_syscall
;
518 * Since we stacked the signal on a 64-bit boundary,
519 * then 'sp' should be word aligned here. If it's
520 * not, then the user is trying to mess with us.
522 if (regs
->compat_sp
& 7)
525 frame
= (struct compat_sigframe __user
*)regs
->compat_sp
;
527 if (!access_ok(VERIFY_READ
, frame
, sizeof (*frame
)))
530 if (compat_restore_sigframe(regs
, frame
))
533 return regs
->regs
[0];
536 if (show_unhandled_signals
)
537 pr_info_ratelimited("%s[%d]: bad frame in %s: pc=%08llx sp=%08llx\n",
538 current
->comm
, task_pid_nr(current
), __func__
,
540 force_sig(SIGSEGV
, current
);
544 asmlinkage
int compat_sys_rt_sigreturn(struct pt_regs
*regs
)
546 struct compat_rt_sigframe __user
*frame
;
548 /* Always make any pending restarted system calls return -EINTR */
549 current_thread_info()->restart_block
.fn
= do_no_restart_syscall
;
552 * Since we stacked the signal on a 64-bit boundary,
553 * then 'sp' should be word aligned here. If it's
554 * not, then the user is trying to mess with us.
556 if (regs
->compat_sp
& 7)
559 frame
= (struct compat_rt_sigframe __user
*)regs
->compat_sp
;
561 if (!access_ok(VERIFY_READ
, frame
, sizeof (*frame
)))
564 if (compat_restore_sigframe(regs
, &frame
->sig
))
567 if (compat_do_sigaltstack(ptr_to_compat(&frame
->sig
.uc
.uc_stack
),
568 ptr_to_compat((void __user
*)NULL
),
569 regs
->compat_sp
) == -EFAULT
)
572 return regs
->regs
[0];
575 if (show_unhandled_signals
)
576 pr_info_ratelimited("%s[%d]: bad frame in %s: pc=%08llx sp=%08llx\n",
577 current
->comm
, task_pid_nr(current
), __func__
,
579 force_sig(SIGSEGV
, current
);
583 static inline void __user
*compat_get_sigframe(struct k_sigaction
*ka
,
584 struct pt_regs
*regs
,
587 compat_ulong_t sp
= regs
->compat_sp
;
591 * This is the X/Open sanctioned signal stack switching.
593 if ((ka
->sa
.sa_flags
& SA_ONSTACK
) && !sas_ss_flags(sp
))
594 sp
= current
->sas_ss_sp
+ current
->sas_ss_size
;
597 * ATPCS B01 mandates 8-byte alignment
599 frame
= compat_ptr((compat_uptr_t
)((sp
- framesize
) & ~7));
602 * Check that we can actually write to the signal frame.
604 if (!access_ok(VERIFY_WRITE
, frame
, framesize
))
610 static int compat_setup_return(struct pt_regs
*regs
, struct k_sigaction
*ka
,
611 compat_ulong_t __user
*rc
, void __user
*frame
,
614 compat_ulong_t handler
= ptr_to_compat(ka
->sa
.sa_handler
);
615 compat_ulong_t retcode
;
616 compat_ulong_t spsr
= regs
->pstate
& ~PSR_f
;
619 /* Check if the handler is written for ARM or Thumb */
623 spsr
|= COMPAT_PSR_T_BIT
;
624 spsr
&= ~COMPAT_PSR_IT_MASK
;
626 spsr
&= ~COMPAT_PSR_T_BIT
;
629 if (ka
->sa
.sa_flags
& SA_RESTORER
) {
630 retcode
= ptr_to_compat(ka
->sa
.sa_restorer
);
632 /* Set up sigreturn pointer */
633 unsigned int idx
= thumb
<< 1;
635 if (ka
->sa
.sa_flags
& SA_SIGINFO
)
638 retcode
= AARCH32_VECTORS_BASE
+
639 AARCH32_KERN_SIGRET_CODE_OFFSET
+
643 regs
->regs
[0] = usig
;
644 regs
->compat_sp
= ptr_to_compat(frame
);
645 regs
->compat_lr
= retcode
;
652 static int compat_setup_sigframe(struct compat_sigframe __user
*sf
,
653 struct pt_regs
*regs
, sigset_t
*set
)
655 struct compat_aux_sigframe __user
*aux
;
658 __put_user_error(regs
->regs
[0], &sf
->uc
.uc_mcontext
.arm_r0
, err
);
659 __put_user_error(regs
->regs
[1], &sf
->uc
.uc_mcontext
.arm_r1
, err
);
660 __put_user_error(regs
->regs
[2], &sf
->uc
.uc_mcontext
.arm_r2
, err
);
661 __put_user_error(regs
->regs
[3], &sf
->uc
.uc_mcontext
.arm_r3
, err
);
662 __put_user_error(regs
->regs
[4], &sf
->uc
.uc_mcontext
.arm_r4
, err
);
663 __put_user_error(regs
->regs
[5], &sf
->uc
.uc_mcontext
.arm_r5
, err
);
664 __put_user_error(regs
->regs
[6], &sf
->uc
.uc_mcontext
.arm_r6
, err
);
665 __put_user_error(regs
->regs
[7], &sf
->uc
.uc_mcontext
.arm_r7
, err
);
666 __put_user_error(regs
->regs
[8], &sf
->uc
.uc_mcontext
.arm_r8
, err
);
667 __put_user_error(regs
->regs
[9], &sf
->uc
.uc_mcontext
.arm_r9
, err
);
668 __put_user_error(regs
->regs
[10], &sf
->uc
.uc_mcontext
.arm_r10
, err
);
669 __put_user_error(regs
->regs
[11], &sf
->uc
.uc_mcontext
.arm_fp
, err
);
670 __put_user_error(regs
->regs
[12], &sf
->uc
.uc_mcontext
.arm_ip
, err
);
671 __put_user_error(regs
->compat_sp
, &sf
->uc
.uc_mcontext
.arm_sp
, err
);
672 __put_user_error(regs
->compat_lr
, &sf
->uc
.uc_mcontext
.arm_lr
, err
);
673 __put_user_error(regs
->pc
, &sf
->uc
.uc_mcontext
.arm_pc
, err
);
674 __put_user_error(regs
->pstate
, &sf
->uc
.uc_mcontext
.arm_cpsr
, err
);
676 __put_user_error((compat_ulong_t
)0, &sf
->uc
.uc_mcontext
.trap_no
, err
);
677 __put_user_error((compat_ulong_t
)0, &sf
->uc
.uc_mcontext
.error_code
, err
);
678 __put_user_error(current
->thread
.fault_address
, &sf
->uc
.uc_mcontext
.fault_address
, err
);
679 __put_user_error(set
->sig
[0], &sf
->uc
.uc_mcontext
.oldmask
, err
);
681 err
|= put_sigset_t(&sf
->uc
.uc_sigmask
, set
);
683 aux
= (struct compat_aux_sigframe __user
*) sf
->uc
.uc_regspace
;
686 err
|= compat_preserve_vfp_context(&aux
->vfp
);
687 __put_user_error(0, &aux
->end_magic
, err
);
693 * 32-bit signal handling routines called from signal.c
695 int compat_setup_rt_frame(int usig
, struct k_sigaction
*ka
, siginfo_t
*info
,
696 sigset_t
*set
, struct pt_regs
*regs
)
698 struct compat_rt_sigframe __user
*frame
;
699 compat_stack_t stack
;
702 frame
= compat_get_sigframe(ka
, regs
, sizeof(*frame
));
707 err
|= copy_siginfo_to_user32(&frame
->info
, info
);
709 __put_user_error(0, &frame
->sig
.uc
.uc_flags
, err
);
710 __put_user_error(NULL
, &frame
->sig
.uc
.uc_link
, err
);
712 memset(&stack
, 0, sizeof(stack
));
713 stack
.ss_sp
= (compat_uptr_t
)current
->sas_ss_sp
;
714 stack
.ss_flags
= sas_ss_flags(regs
->compat_sp
);
715 stack
.ss_size
= current
->sas_ss_size
;
716 err
|= __copy_to_user(&frame
->sig
.uc
.uc_stack
, &stack
, sizeof(stack
));
718 err
|= compat_setup_sigframe(&frame
->sig
, regs
, set
);
720 err
= compat_setup_return(regs
, ka
, frame
->sig
.retcode
, frame
,
724 regs
->regs
[1] = (compat_ulong_t
)(unsigned long)&frame
->info
;
725 regs
->regs
[2] = (compat_ulong_t
)(unsigned long)&frame
->sig
.uc
;
731 int compat_setup_frame(int usig
, struct k_sigaction
*ka
, sigset_t
*set
,
732 struct pt_regs
*regs
)
734 struct compat_sigframe __user
*frame
;
737 frame
= compat_get_sigframe(ka
, regs
, sizeof(*frame
));
742 __put_user_error(0x5ac3c35a, &frame
->uc
.uc_flags
, err
);
744 err
|= compat_setup_sigframe(frame
, regs
, set
);
746 err
= compat_setup_return(regs
, ka
, frame
->retcode
, frame
, usig
);
752 * RT signals don't have generic compat wrappers.
753 * See arch/powerpc/kernel/signal_32.c
755 asmlinkage
int compat_sys_rt_sigprocmask(int how
, compat_sigset_t __user
*set
,
756 compat_sigset_t __user
*oset
,
757 compat_size_t sigsetsize
)
762 mm_segment_t old_fs
= get_fs();
765 if (get_sigset_t(&s
, set
))
770 /* This is valid because of the set_fs() */
771 up
= (sigset_t __user
*) &s
;
772 ret
= sys_rt_sigprocmask(how
, set
? up
: NULL
, oset
? up
: NULL
,
778 if (put_sigset_t(oset
, &s
))
784 asmlinkage
int compat_sys_rt_sigpending(compat_sigset_t __user
*set
,
785 compat_size_t sigsetsize
)
789 mm_segment_t old_fs
= get_fs();
792 /* The __user pointer cast is valid because of the set_fs() */
793 ret
= sys_rt_sigpending((sigset_t __user
*) &s
, sigsetsize
);
796 if (put_sigset_t(set
, &s
))
802 asmlinkage
int compat_sys_rt_sigqueueinfo(int pid
, int sig
,
803 compat_siginfo_t __user
*uinfo
)
807 mm_segment_t old_fs
= get_fs();
809 ret
= copy_siginfo_from_user32(&info
, uinfo
);
814 /* The __user pointer cast is valid because of the set_fs() */
815 ret
= sys_rt_sigqueueinfo(pid
, sig
, (siginfo_t __user
*) &info
);
820 void compat_setup_restart_syscall(struct pt_regs
*regs
)
822 regs
->regs
[7] = __NR_compat_restart_syscall
;