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 #include <linux/compat.h>
22 #include <linux/signal.h>
23 #include <linux/syscalls.h>
24 #include <linux/ratelimit.h>
27 #include <asm/fpsimd.h>
28 #include <asm/signal32.h>
29 #include <linux/uaccess.h>
30 #include <asm/unistd.h>
32 struct compat_sigcontext
{
33 /* We always set these two fields to 0 */
34 compat_ulong_t trap_no
;
35 compat_ulong_t error_code
;
37 compat_ulong_t oldmask
;
38 compat_ulong_t arm_r0
;
39 compat_ulong_t arm_r1
;
40 compat_ulong_t arm_r2
;
41 compat_ulong_t arm_r3
;
42 compat_ulong_t arm_r4
;
43 compat_ulong_t arm_r5
;
44 compat_ulong_t arm_r6
;
45 compat_ulong_t arm_r7
;
46 compat_ulong_t arm_r8
;
47 compat_ulong_t arm_r9
;
48 compat_ulong_t arm_r10
;
49 compat_ulong_t arm_fp
;
50 compat_ulong_t arm_ip
;
51 compat_ulong_t arm_sp
;
52 compat_ulong_t arm_lr
;
53 compat_ulong_t arm_pc
;
54 compat_ulong_t arm_cpsr
;
55 compat_ulong_t fault_address
;
58 struct compat_ucontext
{
59 compat_ulong_t uc_flags
;
60 compat_uptr_t uc_link
;
61 compat_stack_t uc_stack
;
62 struct compat_sigcontext uc_mcontext
;
63 compat_sigset_t uc_sigmask
;
64 int __unused
[32 - (sizeof (compat_sigset_t
) / sizeof (int))];
65 compat_ulong_t uc_regspace
[128] __attribute__((__aligned__(8)));
68 struct compat_vfp_sigframe
{
71 struct compat_user_vfp
{
72 compat_u64 fpregs
[32];
75 struct compat_user_vfp_exc
{
77 compat_ulong_t fpinst
;
78 compat_ulong_t fpinst2
;
80 } __attribute__((__aligned__(8)));
82 #define VFP_MAGIC 0x56465001
83 #define VFP_STORAGE_SIZE sizeof(struct compat_vfp_sigframe)
85 #define FSR_WRITE_SHIFT (11)
87 struct compat_aux_sigframe
{
88 struct compat_vfp_sigframe vfp
;
90 /* Something that isn't a valid magic number for any coprocessor. */
91 unsigned long end_magic
;
92 } __attribute__((__aligned__(8)));
94 struct compat_sigframe
{
95 struct compat_ucontext uc
;
96 compat_ulong_t retcode
[2];
99 struct compat_rt_sigframe
{
100 struct compat_siginfo info
;
101 struct compat_sigframe sig
;
104 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
106 static inline int put_sigset_t(compat_sigset_t __user
*uset
, sigset_t
*set
)
108 compat_sigset_t cset
;
110 cset
.sig
[0] = set
->sig
[0] & 0xffffffffull
;
111 cset
.sig
[1] = set
->sig
[0] >> 32;
113 return copy_to_user(uset
, &cset
, sizeof(*uset
));
116 static inline int get_sigset_t(sigset_t
*set
,
117 const compat_sigset_t __user
*uset
)
121 if (copy_from_user(&s32
, uset
, sizeof(*uset
)))
124 set
->sig
[0] = s32
.sig
[0] | (((long)s32
.sig
[1]) << 32);
129 * VFP save/restore code.
131 * We have to be careful with endianness, since the fpsimd context-switch
132 * code operates on 128-bit (Q) register values whereas the compat ABI
133 * uses an array of 64-bit (D) registers. Consequently, we need to swap
134 * the two halves of each Q register when running on a big-endian CPU.
136 union __fpsimd_vreg
{
149 static int compat_preserve_vfp_context(struct compat_vfp_sigframe __user
*frame
)
151 struct user_fpsimd_state
const *fpsimd
=
152 ¤t
->thread
.fpsimd_state
.user_fpsimd
;
153 compat_ulong_t magic
= VFP_MAGIC
;
154 compat_ulong_t size
= VFP_STORAGE_SIZE
;
155 compat_ulong_t fpscr
, fpexc
;
159 * Save the hardware registers to the fpsimd_state structure.
160 * Note that this also saves V16-31, which aren't visible
163 fpsimd_signal_preserve_current_state();
165 /* Place structure header on the stack */
166 __put_user_error(magic
, &frame
->magic
, err
);
167 __put_user_error(size
, &frame
->size
, err
);
170 * Now copy the FP registers. Since the registers are packed,
171 * we can copy the prefix we want (V0-V15) as it is.
173 for (i
= 0; i
< ARRAY_SIZE(frame
->ufp
.fpregs
); i
+= 2) {
174 union __fpsimd_vreg vreg
= {
175 .raw
= fpsimd
->vregs
[i
>> 1],
178 __put_user_error(vreg
.lo
, &frame
->ufp
.fpregs
[i
], err
);
179 __put_user_error(vreg
.hi
, &frame
->ufp
.fpregs
[i
+ 1], err
);
182 /* Create an AArch32 fpscr from the fpsr and the fpcr. */
183 fpscr
= (fpsimd
->fpsr
& VFP_FPSCR_STAT_MASK
) |
184 (fpsimd
->fpcr
& VFP_FPSCR_CTRL_MASK
);
185 __put_user_error(fpscr
, &frame
->ufp
.fpscr
, err
);
188 * The exception register aren't available so we fake up a
189 * basic FPEXC and zero everything else.
192 __put_user_error(fpexc
, &frame
->ufp_exc
.fpexc
, err
);
193 __put_user_error(0, &frame
->ufp_exc
.fpinst
, err
);
194 __put_user_error(0, &frame
->ufp_exc
.fpinst2
, err
);
196 return err
? -EFAULT
: 0;
199 static int compat_restore_vfp_context(struct compat_vfp_sigframe __user
*frame
)
201 struct user_fpsimd_state fpsimd
;
202 compat_ulong_t magic
= VFP_MAGIC
;
203 compat_ulong_t size
= VFP_STORAGE_SIZE
;
204 compat_ulong_t fpscr
;
207 __get_user_error(magic
, &frame
->magic
, err
);
208 __get_user_error(size
, &frame
->size
, err
);
212 if (magic
!= VFP_MAGIC
|| size
!= VFP_STORAGE_SIZE
)
215 /* Copy the FP registers into the start of the fpsimd_state. */
216 for (i
= 0; i
< ARRAY_SIZE(frame
->ufp
.fpregs
); i
+= 2) {
217 union __fpsimd_vreg vreg
;
219 __get_user_error(vreg
.lo
, &frame
->ufp
.fpregs
[i
], err
);
220 __get_user_error(vreg
.hi
, &frame
->ufp
.fpregs
[i
+ 1], err
);
221 fpsimd
.vregs
[i
>> 1] = vreg
.raw
;
224 /* Extract the fpsr and the fpcr from the fpscr */
225 __get_user_error(fpscr
, &frame
->ufp
.fpscr
, err
);
226 fpsimd
.fpsr
= fpscr
& VFP_FPSCR_STAT_MASK
;
227 fpsimd
.fpcr
= fpscr
& VFP_FPSCR_CTRL_MASK
;
230 * We don't need to touch the exception register, so
231 * reload the hardware state.
234 fpsimd_update_current_state(&fpsimd
);
236 return err
? -EFAULT
: 0;
239 static int compat_restore_sigframe(struct pt_regs
*regs
,
240 struct compat_sigframe __user
*sf
)
244 struct compat_aux_sigframe __user
*aux
;
246 err
= get_sigset_t(&set
, &sf
->uc
.uc_sigmask
);
248 sigdelsetmask(&set
, ~_BLOCKABLE
);
249 set_current_blocked(&set
);
252 __get_user_error(regs
->regs
[0], &sf
->uc
.uc_mcontext
.arm_r0
, err
);
253 __get_user_error(regs
->regs
[1], &sf
->uc
.uc_mcontext
.arm_r1
, err
);
254 __get_user_error(regs
->regs
[2], &sf
->uc
.uc_mcontext
.arm_r2
, err
);
255 __get_user_error(regs
->regs
[3], &sf
->uc
.uc_mcontext
.arm_r3
, err
);
256 __get_user_error(regs
->regs
[4], &sf
->uc
.uc_mcontext
.arm_r4
, err
);
257 __get_user_error(regs
->regs
[5], &sf
->uc
.uc_mcontext
.arm_r5
, err
);
258 __get_user_error(regs
->regs
[6], &sf
->uc
.uc_mcontext
.arm_r6
, err
);
259 __get_user_error(regs
->regs
[7], &sf
->uc
.uc_mcontext
.arm_r7
, err
);
260 __get_user_error(regs
->regs
[8], &sf
->uc
.uc_mcontext
.arm_r8
, err
);
261 __get_user_error(regs
->regs
[9], &sf
->uc
.uc_mcontext
.arm_r9
, err
);
262 __get_user_error(regs
->regs
[10], &sf
->uc
.uc_mcontext
.arm_r10
, err
);
263 __get_user_error(regs
->regs
[11], &sf
->uc
.uc_mcontext
.arm_fp
, err
);
264 __get_user_error(regs
->regs
[12], &sf
->uc
.uc_mcontext
.arm_ip
, err
);
265 __get_user_error(regs
->compat_sp
, &sf
->uc
.uc_mcontext
.arm_sp
, err
);
266 __get_user_error(regs
->compat_lr
, &sf
->uc
.uc_mcontext
.arm_lr
, err
);
267 __get_user_error(regs
->pc
, &sf
->uc
.uc_mcontext
.arm_pc
, err
);
268 __get_user_error(regs
->pstate
, &sf
->uc
.uc_mcontext
.arm_cpsr
, err
);
271 * Avoid compat_sys_sigreturn() restarting.
273 forget_syscall(regs
);
275 err
|= !valid_user_regs(®s
->user_regs
, current
);
277 aux
= (struct compat_aux_sigframe __user
*) sf
->uc
.uc_regspace
;
279 err
|= compat_restore_vfp_context(&aux
->vfp
);
284 asmlinkage
int compat_sys_sigreturn(struct pt_regs
*regs
)
286 struct compat_sigframe __user
*frame
;
288 /* Always make any pending restarted system calls return -EINTR */
289 current
->restart_block
.fn
= do_no_restart_syscall
;
292 * Since we stacked the signal on a 64-bit boundary,
293 * then 'sp' should be word aligned here. If it's
294 * not, then the user is trying to mess with us.
296 if (regs
->compat_sp
& 7)
299 frame
= (struct compat_sigframe __user
*)regs
->compat_sp
;
301 if (!access_ok(VERIFY_READ
, frame
, sizeof (*frame
)))
304 if (compat_restore_sigframe(regs
, frame
))
307 return regs
->regs
[0];
310 if (show_unhandled_signals
)
311 pr_info_ratelimited("%s[%d]: bad frame in %s: pc=%08llx sp=%08llx\n",
312 current
->comm
, task_pid_nr(current
), __func__
,
313 regs
->pc
, regs
->compat_sp
);
314 force_sig(SIGSEGV
, current
);
318 asmlinkage
int compat_sys_rt_sigreturn(struct pt_regs
*regs
)
320 struct compat_rt_sigframe __user
*frame
;
322 /* Always make any pending restarted system calls return -EINTR */
323 current
->restart_block
.fn
= do_no_restart_syscall
;
326 * Since we stacked the signal on a 64-bit boundary,
327 * then 'sp' should be word aligned here. If it's
328 * not, then the user is trying to mess with us.
330 if (regs
->compat_sp
& 7)
333 frame
= (struct compat_rt_sigframe __user
*)regs
->compat_sp
;
335 if (!access_ok(VERIFY_READ
, frame
, sizeof (*frame
)))
338 if (compat_restore_sigframe(regs
, &frame
->sig
))
341 if (compat_restore_altstack(&frame
->sig
.uc
.uc_stack
))
344 return regs
->regs
[0];
347 if (show_unhandled_signals
)
348 pr_info_ratelimited("%s[%d]: bad frame in %s: pc=%08llx sp=%08llx\n",
349 current
->comm
, task_pid_nr(current
), __func__
,
350 regs
->pc
, regs
->compat_sp
);
351 force_sig(SIGSEGV
, current
);
355 static void __user
*compat_get_sigframe(struct ksignal
*ksig
,
356 struct pt_regs
*regs
,
359 compat_ulong_t sp
= sigsp(regs
->compat_sp
, ksig
);
363 * ATPCS B01 mandates 8-byte alignment
365 frame
= compat_ptr((compat_uptr_t
)((sp
- framesize
) & ~7));
368 * Check that we can actually write to the signal frame.
370 if (!access_ok(VERIFY_WRITE
, frame
, framesize
))
376 static void compat_setup_return(struct pt_regs
*regs
, struct k_sigaction
*ka
,
377 compat_ulong_t __user
*rc
, void __user
*frame
,
380 compat_ulong_t handler
= ptr_to_compat(ka
->sa
.sa_handler
);
381 compat_ulong_t retcode
;
382 compat_ulong_t spsr
= regs
->pstate
& ~(PSR_f
| COMPAT_PSR_E_BIT
);
385 /* Check if the handler is written for ARM or Thumb */
389 spsr
|= COMPAT_PSR_T_BIT
;
391 spsr
&= ~COMPAT_PSR_T_BIT
;
393 /* The IT state must be cleared for both ARM and Thumb-2 */
394 spsr
&= ~COMPAT_PSR_IT_MASK
;
396 /* Restore the original endianness */
397 spsr
|= COMPAT_PSR_ENDSTATE
;
399 if (ka
->sa
.sa_flags
& SA_RESTORER
) {
400 retcode
= ptr_to_compat(ka
->sa
.sa_restorer
);
402 /* Set up sigreturn pointer */
403 unsigned int idx
= thumb
<< 1;
405 if (ka
->sa
.sa_flags
& SA_SIGINFO
)
408 retcode
= AARCH32_VECTORS_BASE
+
409 AARCH32_KERN_SIGRET_CODE_OFFSET
+
413 regs
->regs
[0] = usig
;
414 regs
->compat_sp
= ptr_to_compat(frame
);
415 regs
->compat_lr
= retcode
;
420 static int compat_setup_sigframe(struct compat_sigframe __user
*sf
,
421 struct pt_regs
*regs
, sigset_t
*set
)
423 struct compat_aux_sigframe __user
*aux
;
426 __put_user_error(regs
->regs
[0], &sf
->uc
.uc_mcontext
.arm_r0
, err
);
427 __put_user_error(regs
->regs
[1], &sf
->uc
.uc_mcontext
.arm_r1
, err
);
428 __put_user_error(regs
->regs
[2], &sf
->uc
.uc_mcontext
.arm_r2
, err
);
429 __put_user_error(regs
->regs
[3], &sf
->uc
.uc_mcontext
.arm_r3
, err
);
430 __put_user_error(regs
->regs
[4], &sf
->uc
.uc_mcontext
.arm_r4
, err
);
431 __put_user_error(regs
->regs
[5], &sf
->uc
.uc_mcontext
.arm_r5
, err
);
432 __put_user_error(regs
->regs
[6], &sf
->uc
.uc_mcontext
.arm_r6
, err
);
433 __put_user_error(regs
->regs
[7], &sf
->uc
.uc_mcontext
.arm_r7
, err
);
434 __put_user_error(regs
->regs
[8], &sf
->uc
.uc_mcontext
.arm_r8
, err
);
435 __put_user_error(regs
->regs
[9], &sf
->uc
.uc_mcontext
.arm_r9
, err
);
436 __put_user_error(regs
->regs
[10], &sf
->uc
.uc_mcontext
.arm_r10
, err
);
437 __put_user_error(regs
->regs
[11], &sf
->uc
.uc_mcontext
.arm_fp
, err
);
438 __put_user_error(regs
->regs
[12], &sf
->uc
.uc_mcontext
.arm_ip
, err
);
439 __put_user_error(regs
->compat_sp
, &sf
->uc
.uc_mcontext
.arm_sp
, err
);
440 __put_user_error(regs
->compat_lr
, &sf
->uc
.uc_mcontext
.arm_lr
, err
);
441 __put_user_error(regs
->pc
, &sf
->uc
.uc_mcontext
.arm_pc
, err
);
442 __put_user_error(regs
->pstate
, &sf
->uc
.uc_mcontext
.arm_cpsr
, err
);
444 __put_user_error((compat_ulong_t
)0, &sf
->uc
.uc_mcontext
.trap_no
, err
);
445 /* set the compat FSR WnR */
446 __put_user_error(!!(current
->thread
.fault_code
& ESR_ELx_WNR
) <<
447 FSR_WRITE_SHIFT
, &sf
->uc
.uc_mcontext
.error_code
, err
);
448 __put_user_error(current
->thread
.fault_address
, &sf
->uc
.uc_mcontext
.fault_address
, err
);
449 __put_user_error(set
->sig
[0], &sf
->uc
.uc_mcontext
.oldmask
, err
);
451 err
|= put_sigset_t(&sf
->uc
.uc_sigmask
, set
);
453 aux
= (struct compat_aux_sigframe __user
*) sf
->uc
.uc_regspace
;
456 err
|= compat_preserve_vfp_context(&aux
->vfp
);
457 __put_user_error(0, &aux
->end_magic
, err
);
463 * 32-bit signal handling routines called from signal.c
465 int compat_setup_rt_frame(int usig
, struct ksignal
*ksig
,
466 sigset_t
*set
, struct pt_regs
*regs
)
468 struct compat_rt_sigframe __user
*frame
;
471 frame
= compat_get_sigframe(ksig
, regs
, sizeof(*frame
));
476 err
|= copy_siginfo_to_user32(&frame
->info
, &ksig
->info
);
478 __put_user_error(0, &frame
->sig
.uc
.uc_flags
, err
);
479 __put_user_error(0, &frame
->sig
.uc
.uc_link
, err
);
481 err
|= __compat_save_altstack(&frame
->sig
.uc
.uc_stack
, regs
->compat_sp
);
483 err
|= compat_setup_sigframe(&frame
->sig
, regs
, set
);
486 compat_setup_return(regs
, &ksig
->ka
, frame
->sig
.retcode
, frame
, usig
);
487 regs
->regs
[1] = (compat_ulong_t
)(unsigned long)&frame
->info
;
488 regs
->regs
[2] = (compat_ulong_t
)(unsigned long)&frame
->sig
.uc
;
494 int compat_setup_frame(int usig
, struct ksignal
*ksig
, sigset_t
*set
,
495 struct pt_regs
*regs
)
497 struct compat_sigframe __user
*frame
;
500 frame
= compat_get_sigframe(ksig
, regs
, sizeof(*frame
));
505 __put_user_error(0x5ac3c35a, &frame
->uc
.uc_flags
, err
);
507 err
|= compat_setup_sigframe(frame
, regs
, set
);
509 compat_setup_return(regs
, &ksig
->ka
, frame
->retcode
, frame
, usig
);
514 void compat_setup_restart_syscall(struct pt_regs
*regs
)
516 regs
->regs
[7] = __NR_compat_restart_syscall
;