1 // SPDX-License-Identifier: GPL-2.0-only
3 * Based on arch/arm/kernel/signal.c
5 * Copyright (C) 1995-2009 Russell King
6 * Copyright (C) 2012 ARM Ltd.
7 * Modified by Will Deacon <will.deacon@arm.com>
10 #include <linux/compat.h>
11 #include <linux/signal.h>
12 #include <linux/syscalls.h>
13 #include <linux/ratelimit.h>
16 #include <asm/fpsimd.h>
17 #include <asm/signal32.h>
18 #include <asm/traps.h>
19 #include <linux/uaccess.h>
20 #include <asm/unistd.h>
23 struct compat_vfp_sigframe
{
26 struct compat_user_vfp
{
27 compat_u64 fpregs
[32];
30 struct compat_user_vfp_exc
{
32 compat_ulong_t fpinst
;
33 compat_ulong_t fpinst2
;
35 } __attribute__((__aligned__(8)));
37 #define VFP_MAGIC 0x56465001
38 #define VFP_STORAGE_SIZE sizeof(struct compat_vfp_sigframe)
40 #define FSR_WRITE_SHIFT (11)
42 struct compat_aux_sigframe
{
43 struct compat_vfp_sigframe vfp
;
45 /* Something that isn't a valid magic number for any coprocessor. */
46 unsigned long end_magic
;
47 } __attribute__((__aligned__(8)));
49 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
51 static inline int put_sigset_t(compat_sigset_t __user
*uset
, sigset_t
*set
)
55 cset
.sig
[0] = set
->sig
[0] & 0xffffffffull
;
56 cset
.sig
[1] = set
->sig
[0] >> 32;
58 return copy_to_user(uset
, &cset
, sizeof(*uset
));
61 static inline int get_sigset_t(sigset_t
*set
,
62 const compat_sigset_t __user
*uset
)
66 if (copy_from_user(&s32
, uset
, sizeof(*uset
)))
69 set
->sig
[0] = s32
.sig
[0] | (((long)s32
.sig
[1]) << 32);
74 * VFP save/restore code.
76 * We have to be careful with endianness, since the fpsimd context-switch
77 * code operates on 128-bit (Q) register values whereas the compat ABI
78 * uses an array of 64-bit (D) registers. Consequently, we need to swap
79 * the two halves of each Q register when running on a big-endian CPU.
94 static int compat_preserve_vfp_context(struct compat_vfp_sigframe __user
*frame
)
96 struct user_fpsimd_state
const *fpsimd
=
97 ¤t
->thread
.uw
.fpsimd_state
;
98 compat_ulong_t magic
= VFP_MAGIC
;
99 compat_ulong_t size
= VFP_STORAGE_SIZE
;
100 compat_ulong_t fpscr
, fpexc
;
104 * Save the hardware registers to the fpsimd_state structure.
105 * Note that this also saves V16-31, which aren't visible
108 fpsimd_signal_preserve_current_state();
110 /* Place structure header on the stack */
111 __put_user_error(magic
, &frame
->magic
, err
);
112 __put_user_error(size
, &frame
->size
, err
);
115 * Now copy the FP registers. Since the registers are packed,
116 * we can copy the prefix we want (V0-V15) as it is.
118 for (i
= 0; i
< ARRAY_SIZE(frame
->ufp
.fpregs
); i
+= 2) {
119 union __fpsimd_vreg vreg
= {
120 .raw
= fpsimd
->vregs
[i
>> 1],
123 __put_user_error(vreg
.lo
, &frame
->ufp
.fpregs
[i
], err
);
124 __put_user_error(vreg
.hi
, &frame
->ufp
.fpregs
[i
+ 1], err
);
127 /* Create an AArch32 fpscr from the fpsr and the fpcr. */
128 fpscr
= (fpsimd
->fpsr
& VFP_FPSCR_STAT_MASK
) |
129 (fpsimd
->fpcr
& VFP_FPSCR_CTRL_MASK
);
130 __put_user_error(fpscr
, &frame
->ufp
.fpscr
, err
);
133 * The exception register aren't available so we fake up a
134 * basic FPEXC and zero everything else.
137 __put_user_error(fpexc
, &frame
->ufp_exc
.fpexc
, err
);
138 __put_user_error(0, &frame
->ufp_exc
.fpinst
, err
);
139 __put_user_error(0, &frame
->ufp_exc
.fpinst2
, err
);
141 return err
? -EFAULT
: 0;
144 static int compat_restore_vfp_context(struct compat_vfp_sigframe __user
*frame
)
146 struct user_fpsimd_state fpsimd
;
147 compat_ulong_t magic
= VFP_MAGIC
;
148 compat_ulong_t size
= VFP_STORAGE_SIZE
;
149 compat_ulong_t fpscr
;
152 __get_user_error(magic
, &frame
->magic
, err
);
153 __get_user_error(size
, &frame
->size
, err
);
157 if (magic
!= VFP_MAGIC
|| size
!= VFP_STORAGE_SIZE
)
160 /* Copy the FP registers into the start of the fpsimd_state. */
161 for (i
= 0; i
< ARRAY_SIZE(frame
->ufp
.fpregs
); i
+= 2) {
162 union __fpsimd_vreg vreg
;
164 __get_user_error(vreg
.lo
, &frame
->ufp
.fpregs
[i
], err
);
165 __get_user_error(vreg
.hi
, &frame
->ufp
.fpregs
[i
+ 1], err
);
166 fpsimd
.vregs
[i
>> 1] = vreg
.raw
;
169 /* Extract the fpsr and the fpcr from the fpscr */
170 __get_user_error(fpscr
, &frame
->ufp
.fpscr
, err
);
171 fpsimd
.fpsr
= fpscr
& VFP_FPSCR_STAT_MASK
;
172 fpsimd
.fpcr
= fpscr
& VFP_FPSCR_CTRL_MASK
;
175 * We don't need to touch the exception register, so
176 * reload the hardware state.
179 fpsimd_update_current_state(&fpsimd
);
181 return err
? -EFAULT
: 0;
184 static int compat_restore_sigframe(struct pt_regs
*regs
,
185 struct compat_sigframe __user
*sf
)
189 struct compat_aux_sigframe __user
*aux
;
192 err
= get_sigset_t(&set
, &sf
->uc
.uc_sigmask
);
194 sigdelsetmask(&set
, ~_BLOCKABLE
);
195 set_current_blocked(&set
);
198 __get_user_error(regs
->regs
[0], &sf
->uc
.uc_mcontext
.arm_r0
, err
);
199 __get_user_error(regs
->regs
[1], &sf
->uc
.uc_mcontext
.arm_r1
, err
);
200 __get_user_error(regs
->regs
[2], &sf
->uc
.uc_mcontext
.arm_r2
, err
);
201 __get_user_error(regs
->regs
[3], &sf
->uc
.uc_mcontext
.arm_r3
, err
);
202 __get_user_error(regs
->regs
[4], &sf
->uc
.uc_mcontext
.arm_r4
, err
);
203 __get_user_error(regs
->regs
[5], &sf
->uc
.uc_mcontext
.arm_r5
, err
);
204 __get_user_error(regs
->regs
[6], &sf
->uc
.uc_mcontext
.arm_r6
, err
);
205 __get_user_error(regs
->regs
[7], &sf
->uc
.uc_mcontext
.arm_r7
, err
);
206 __get_user_error(regs
->regs
[8], &sf
->uc
.uc_mcontext
.arm_r8
, err
);
207 __get_user_error(regs
->regs
[9], &sf
->uc
.uc_mcontext
.arm_r9
, err
);
208 __get_user_error(regs
->regs
[10], &sf
->uc
.uc_mcontext
.arm_r10
, err
);
209 __get_user_error(regs
->regs
[11], &sf
->uc
.uc_mcontext
.arm_fp
, err
);
210 __get_user_error(regs
->regs
[12], &sf
->uc
.uc_mcontext
.arm_ip
, err
);
211 __get_user_error(regs
->compat_sp
, &sf
->uc
.uc_mcontext
.arm_sp
, err
);
212 __get_user_error(regs
->compat_lr
, &sf
->uc
.uc_mcontext
.arm_lr
, err
);
213 __get_user_error(regs
->pc
, &sf
->uc
.uc_mcontext
.arm_pc
, err
);
214 __get_user_error(psr
, &sf
->uc
.uc_mcontext
.arm_cpsr
, err
);
216 regs
->pstate
= compat_psr_to_pstate(psr
);
219 * Avoid compat_sys_sigreturn() restarting.
221 forget_syscall(regs
);
223 err
|= !valid_user_regs(®s
->user_regs
, current
);
225 aux
= (struct compat_aux_sigframe __user
*) sf
->uc
.uc_regspace
;
227 err
|= compat_restore_vfp_context(&aux
->vfp
);
232 COMPAT_SYSCALL_DEFINE0(sigreturn
)
234 struct pt_regs
*regs
= current_pt_regs();
235 struct compat_sigframe __user
*frame
;
237 /* Always make any pending restarted system calls return -EINTR */
238 current
->restart_block
.fn
= do_no_restart_syscall
;
241 * Since we stacked the signal on a 64-bit boundary,
242 * then 'sp' should be word aligned here. If it's
243 * not, then the user is trying to mess with us.
245 if (regs
->compat_sp
& 7)
248 frame
= (struct compat_sigframe __user
*)regs
->compat_sp
;
250 if (!access_ok(frame
, sizeof (*frame
)))
253 if (compat_restore_sigframe(regs
, frame
))
256 return regs
->regs
[0];
259 arm64_notify_segfault(regs
->compat_sp
);
263 COMPAT_SYSCALL_DEFINE0(rt_sigreturn
)
265 struct pt_regs
*regs
= current_pt_regs();
266 struct compat_rt_sigframe __user
*frame
;
268 /* Always make any pending restarted system calls return -EINTR */
269 current
->restart_block
.fn
= do_no_restart_syscall
;
272 * Since we stacked the signal on a 64-bit boundary,
273 * then 'sp' should be word aligned here. If it's
274 * not, then the user is trying to mess with us.
276 if (regs
->compat_sp
& 7)
279 frame
= (struct compat_rt_sigframe __user
*)regs
->compat_sp
;
281 if (!access_ok(frame
, sizeof (*frame
)))
284 if (compat_restore_sigframe(regs
, &frame
->sig
))
287 if (compat_restore_altstack(&frame
->sig
.uc
.uc_stack
))
290 return regs
->regs
[0];
293 arm64_notify_segfault(regs
->compat_sp
);
297 static void __user
*compat_get_sigframe(struct ksignal
*ksig
,
298 struct pt_regs
*regs
,
301 compat_ulong_t sp
= sigsp(regs
->compat_sp
, ksig
);
305 * ATPCS B01 mandates 8-byte alignment
307 frame
= compat_ptr((compat_uptr_t
)((sp
- framesize
) & ~7));
310 * Check that we can actually write to the signal frame.
312 if (!access_ok(frame
, framesize
))
318 static void compat_setup_return(struct pt_regs
*regs
, struct k_sigaction
*ka
,
319 compat_ulong_t __user
*rc
, void __user
*frame
,
322 compat_ulong_t handler
= ptr_to_compat(ka
->sa
.sa_handler
);
323 compat_ulong_t retcode
;
324 compat_ulong_t spsr
= regs
->pstate
& ~(PSR_f
| PSR_AA32_E_BIT
);
327 /* Check if the handler is written for ARM or Thumb */
331 spsr
|= PSR_AA32_T_BIT
;
333 spsr
&= ~PSR_AA32_T_BIT
;
335 /* The IT state must be cleared for both ARM and Thumb-2 */
336 spsr
&= ~PSR_AA32_IT_MASK
;
338 /* Restore the original endianness */
339 spsr
|= PSR_AA32_ENDSTATE
;
341 if (ka
->sa
.sa_flags
& SA_RESTORER
) {
342 retcode
= ptr_to_compat(ka
->sa
.sa_restorer
);
344 /* Set up sigreturn pointer */
345 #ifdef CONFIG_COMPAT_VDSO
346 void *vdso_base
= current
->mm
->context
.vdso
;
347 void *vdso_trampoline
;
349 if (ka
->sa
.sa_flags
& SA_SIGINFO
) {
351 vdso_trampoline
= VDSO_SYMBOL(vdso_base
,
352 compat_rt_sigreturn_thumb
);
354 vdso_trampoline
= VDSO_SYMBOL(vdso_base
,
355 compat_rt_sigreturn_arm
);
359 vdso_trampoline
= VDSO_SYMBOL(vdso_base
,
360 compat_sigreturn_thumb
);
362 vdso_trampoline
= VDSO_SYMBOL(vdso_base
,
363 compat_sigreturn_arm
);
367 retcode
= ptr_to_compat(vdso_trampoline
) + thumb
;
369 unsigned int idx
= thumb
<< 1;
371 if (ka
->sa
.sa_flags
& SA_SIGINFO
)
374 retcode
= (unsigned long)current
->mm
->context
.vdso
+
379 regs
->regs
[0] = usig
;
380 regs
->compat_sp
= ptr_to_compat(frame
);
381 regs
->compat_lr
= retcode
;
386 static int compat_setup_sigframe(struct compat_sigframe __user
*sf
,
387 struct pt_regs
*regs
, sigset_t
*set
)
389 struct compat_aux_sigframe __user
*aux
;
390 unsigned long psr
= pstate_to_compat_psr(regs
->pstate
);
393 __put_user_error(regs
->regs
[0], &sf
->uc
.uc_mcontext
.arm_r0
, err
);
394 __put_user_error(regs
->regs
[1], &sf
->uc
.uc_mcontext
.arm_r1
, err
);
395 __put_user_error(regs
->regs
[2], &sf
->uc
.uc_mcontext
.arm_r2
, err
);
396 __put_user_error(regs
->regs
[3], &sf
->uc
.uc_mcontext
.arm_r3
, err
);
397 __put_user_error(regs
->regs
[4], &sf
->uc
.uc_mcontext
.arm_r4
, err
);
398 __put_user_error(regs
->regs
[5], &sf
->uc
.uc_mcontext
.arm_r5
, err
);
399 __put_user_error(regs
->regs
[6], &sf
->uc
.uc_mcontext
.arm_r6
, err
);
400 __put_user_error(regs
->regs
[7], &sf
->uc
.uc_mcontext
.arm_r7
, err
);
401 __put_user_error(regs
->regs
[8], &sf
->uc
.uc_mcontext
.arm_r8
, err
);
402 __put_user_error(regs
->regs
[9], &sf
->uc
.uc_mcontext
.arm_r9
, err
);
403 __put_user_error(regs
->regs
[10], &sf
->uc
.uc_mcontext
.arm_r10
, err
);
404 __put_user_error(regs
->regs
[11], &sf
->uc
.uc_mcontext
.arm_fp
, err
);
405 __put_user_error(regs
->regs
[12], &sf
->uc
.uc_mcontext
.arm_ip
, err
);
406 __put_user_error(regs
->compat_sp
, &sf
->uc
.uc_mcontext
.arm_sp
, err
);
407 __put_user_error(regs
->compat_lr
, &sf
->uc
.uc_mcontext
.arm_lr
, err
);
408 __put_user_error(regs
->pc
, &sf
->uc
.uc_mcontext
.arm_pc
, err
);
409 __put_user_error(psr
, &sf
->uc
.uc_mcontext
.arm_cpsr
, err
);
411 __put_user_error((compat_ulong_t
)0, &sf
->uc
.uc_mcontext
.trap_no
, err
);
412 /* set the compat FSR WnR */
413 __put_user_error(!!(current
->thread
.fault_code
& ESR_ELx_WNR
) <<
414 FSR_WRITE_SHIFT
, &sf
->uc
.uc_mcontext
.error_code
, err
);
415 __put_user_error(current
->thread
.fault_address
, &sf
->uc
.uc_mcontext
.fault_address
, err
);
416 __put_user_error(set
->sig
[0], &sf
->uc
.uc_mcontext
.oldmask
, err
);
418 err
|= put_sigset_t(&sf
->uc
.uc_sigmask
, set
);
420 aux
= (struct compat_aux_sigframe __user
*) sf
->uc
.uc_regspace
;
423 err
|= compat_preserve_vfp_context(&aux
->vfp
);
424 __put_user_error(0, &aux
->end_magic
, err
);
430 * 32-bit signal handling routines called from signal.c
432 int compat_setup_rt_frame(int usig
, struct ksignal
*ksig
,
433 sigset_t
*set
, struct pt_regs
*regs
)
435 struct compat_rt_sigframe __user
*frame
;
438 frame
= compat_get_sigframe(ksig
, regs
, sizeof(*frame
));
443 err
|= copy_siginfo_to_user32(&frame
->info
, &ksig
->info
);
445 __put_user_error(0, &frame
->sig
.uc
.uc_flags
, err
);
446 __put_user_error(0, &frame
->sig
.uc
.uc_link
, err
);
448 err
|= __compat_save_altstack(&frame
->sig
.uc
.uc_stack
, regs
->compat_sp
);
450 err
|= compat_setup_sigframe(&frame
->sig
, regs
, set
);
453 compat_setup_return(regs
, &ksig
->ka
, frame
->sig
.retcode
, frame
, usig
);
454 regs
->regs
[1] = (compat_ulong_t
)(unsigned long)&frame
->info
;
455 regs
->regs
[2] = (compat_ulong_t
)(unsigned long)&frame
->sig
.uc
;
461 int compat_setup_frame(int usig
, struct ksignal
*ksig
, sigset_t
*set
,
462 struct pt_regs
*regs
)
464 struct compat_sigframe __user
*frame
;
467 frame
= compat_get_sigframe(ksig
, regs
, sizeof(*frame
));
472 __put_user_error(0x5ac3c35a, &frame
->uc
.uc_flags
, err
);
474 err
|= compat_setup_sigframe(frame
, regs
, set
);
476 compat_setup_return(regs
, &ksig
->ka
, frame
->retcode
, frame
, usig
);
481 void compat_setup_restart_syscall(struct pt_regs
*regs
)
483 regs
->regs
[7] = __NR_compat_restart_syscall
;