treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 234
[linux-2.6-block.git] / arch / arm64 / kernel / signal32.c
CommitLineData
caab277b 1// SPDX-License-Identifier: GPL-2.0-only
3dd681d9
WD
2/*
3 * Based on arch/arm/kernel/signal.c
4 *
5 * Copyright (C) 1995-2009 Russell King
6 * Copyright (C) 2012 ARM Ltd.
7 * Modified by Will Deacon <will.deacon@arm.com>
3dd681d9
WD
8 */
9
3dd681d9
WD
10#include <linux/compat.h>
11#include <linux/signal.h>
12#include <linux/syscalls.h>
13#include <linux/ratelimit.h>
14
9141300a 15#include <asm/esr.h>
3dd681d9
WD
16#include <asm/fpsimd.h>
17#include <asm/signal32.h>
f71016a8 18#include <asm/traps.h>
7c0f6ba6 19#include <linux/uaccess.h>
f3e5c847 20#include <asm/unistd.h>
3dd681d9 21
3dd681d9
WD
22struct compat_sigcontext {
23 /* We always set these two fields to 0 */
24 compat_ulong_t trap_no;
25 compat_ulong_t error_code;
26
27 compat_ulong_t oldmask;
28 compat_ulong_t arm_r0;
29 compat_ulong_t arm_r1;
30 compat_ulong_t arm_r2;
31 compat_ulong_t arm_r3;
32 compat_ulong_t arm_r4;
33 compat_ulong_t arm_r5;
34 compat_ulong_t arm_r6;
35 compat_ulong_t arm_r7;
36 compat_ulong_t arm_r8;
37 compat_ulong_t arm_r9;
38 compat_ulong_t arm_r10;
39 compat_ulong_t arm_fp;
40 compat_ulong_t arm_ip;
41 compat_ulong_t arm_sp;
42 compat_ulong_t arm_lr;
43 compat_ulong_t arm_pc;
44 compat_ulong_t arm_cpsr;
45 compat_ulong_t fault_address;
46};
47
48struct compat_ucontext {
49 compat_ulong_t uc_flags;
c0e01d5d 50 compat_uptr_t uc_link;
3dd681d9
WD
51 compat_stack_t uc_stack;
52 struct compat_sigcontext uc_mcontext;
53 compat_sigset_t uc_sigmask;
54 int __unused[32 - (sizeof (compat_sigset_t) / sizeof (int))];
55 compat_ulong_t uc_regspace[128] __attribute__((__aligned__(8)));
56};
57
58struct compat_vfp_sigframe {
59 compat_ulong_t magic;
60 compat_ulong_t size;
61 struct compat_user_vfp {
62 compat_u64 fpregs[32];
63 compat_ulong_t fpscr;
64 } ufp;
65 struct compat_user_vfp_exc {
66 compat_ulong_t fpexc;
67 compat_ulong_t fpinst;
68 compat_ulong_t fpinst2;
69 } ufp_exc;
70} __attribute__((__aligned__(8)));
71
72#define VFP_MAGIC 0x56465001
73#define VFP_STORAGE_SIZE sizeof(struct compat_vfp_sigframe)
74
9141300a
CM
75#define FSR_WRITE_SHIFT (11)
76
3dd681d9
WD
77struct compat_aux_sigframe {
78 struct compat_vfp_sigframe vfp;
79
80 /* Something that isn't a valid magic number for any coprocessor. */
81 unsigned long end_magic;
82} __attribute__((__aligned__(8)));
83
84struct compat_sigframe {
85 struct compat_ucontext uc;
86 compat_ulong_t retcode[2];
87};
88
89struct compat_rt_sigframe {
90 struct compat_siginfo info;
91 struct compat_sigframe sig;
92};
93
94#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
95
3dd681d9
WD
96static inline int put_sigset_t(compat_sigset_t __user *uset, sigset_t *set)
97{
98 compat_sigset_t cset;
99
100 cset.sig[0] = set->sig[0] & 0xffffffffull;
101 cset.sig[1] = set->sig[0] >> 32;
102
103 return copy_to_user(uset, &cset, sizeof(*uset));
104}
105
106static inline int get_sigset_t(sigset_t *set,
107 const compat_sigset_t __user *uset)
108{
109 compat_sigset_t s32;
110
111 if (copy_from_user(&s32, uset, sizeof(*uset)))
112 return -EFAULT;
113
114 set->sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
115 return 0;
116}
117
3dd681d9
WD
118/*
119 * VFP save/restore code.
bdec97a8
WD
120 *
121 * We have to be careful with endianness, since the fpsimd context-switch
122 * code operates on 128-bit (Q) register values whereas the compat ABI
123 * uses an array of 64-bit (D) registers. Consequently, we need to swap
124 * the two halves of each Q register when running on a big-endian CPU.
3dd681d9 125 */
bdec97a8
WD
126union __fpsimd_vreg {
127 __uint128_t raw;
128 struct {
129#ifdef __AARCH64EB__
130 u64 hi;
131 u64 lo;
132#else
133 u64 lo;
134 u64 hi;
135#endif
136 };
137};
138
3dd681d9
WD
139static int compat_preserve_vfp_context(struct compat_vfp_sigframe __user *frame)
140{
65896545
DM
141 struct user_fpsimd_state const *fpsimd =
142 &current->thread.uw.fpsimd_state;
3dd681d9
WD
143 compat_ulong_t magic = VFP_MAGIC;
144 compat_ulong_t size = VFP_STORAGE_SIZE;
145 compat_ulong_t fpscr, fpexc;
bdec97a8 146 int i, err = 0;
3dd681d9
WD
147
148 /*
149 * Save the hardware registers to the fpsimd_state structure.
150 * Note that this also saves V16-31, which aren't visible
151 * in AArch32.
152 */
8cd969d2 153 fpsimd_signal_preserve_current_state();
3dd681d9
WD
154
155 /* Place structure header on the stack */
156 __put_user_error(magic, &frame->magic, err);
157 __put_user_error(size, &frame->size, err);
158
159 /*
160 * Now copy the FP registers. Since the registers are packed,
161 * we can copy the prefix we want (V0-V15) as it is.
3dd681d9 162 */
bdec97a8
WD
163 for (i = 0; i < ARRAY_SIZE(frame->ufp.fpregs); i += 2) {
164 union __fpsimd_vreg vreg = {
165 .raw = fpsimd->vregs[i >> 1],
166 };
167
168 __put_user_error(vreg.lo, &frame->ufp.fpregs[i], err);
169 __put_user_error(vreg.hi, &frame->ufp.fpregs[i + 1], err);
170 }
3dd681d9
WD
171
172 /* Create an AArch32 fpscr from the fpsr and the fpcr. */
173 fpscr = (fpsimd->fpsr & VFP_FPSCR_STAT_MASK) |
174 (fpsimd->fpcr & VFP_FPSCR_CTRL_MASK);
175 __put_user_error(fpscr, &frame->ufp.fpscr, err);
176
177 /*
178 * The exception register aren't available so we fake up a
179 * basic FPEXC and zero everything else.
180 */
181 fpexc = (1 << 30);
182 __put_user_error(fpexc, &frame->ufp_exc.fpexc, err);
183 __put_user_error(0, &frame->ufp_exc.fpinst, err);
184 __put_user_error(0, &frame->ufp_exc.fpinst2, err);
185
186 return err ? -EFAULT : 0;
187}
188
189static int compat_restore_vfp_context(struct compat_vfp_sigframe __user *frame)
190{
0abdeff5 191 struct user_fpsimd_state fpsimd;
3dd681d9
WD
192 compat_ulong_t magic = VFP_MAGIC;
193 compat_ulong_t size = VFP_STORAGE_SIZE;
194 compat_ulong_t fpscr;
bdec97a8 195 int i, err = 0;
3dd681d9
WD
196
197 __get_user_error(magic, &frame->magic, err);
198 __get_user_error(size, &frame->size, err);
199
200 if (err)
201 return -EFAULT;
202 if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE)
203 return -EINVAL;
204
bdec97a8
WD
205 /* Copy the FP registers into the start of the fpsimd_state. */
206 for (i = 0; i < ARRAY_SIZE(frame->ufp.fpregs); i += 2) {
207 union __fpsimd_vreg vreg;
208
209 __get_user_error(vreg.lo, &frame->ufp.fpregs[i], err);
210 __get_user_error(vreg.hi, &frame->ufp.fpregs[i + 1], err);
211 fpsimd.vregs[i >> 1] = vreg.raw;
212 }
3dd681d9
WD
213
214 /* Extract the fpsr and the fpcr from the fpscr */
215 __get_user_error(fpscr, &frame->ufp.fpscr, err);
216 fpsimd.fpsr = fpscr & VFP_FPSCR_STAT_MASK;
217 fpsimd.fpcr = fpscr & VFP_FPSCR_CTRL_MASK;
218
219 /*
220 * We don't need to touch the exception register, so
221 * reload the hardware state.
222 */
c51f9269
AB
223 if (!err)
224 fpsimd_update_current_state(&fpsimd);
3dd681d9
WD
225
226 return err ? -EFAULT : 0;
227}
228
3dd681d9
WD
229static int compat_restore_sigframe(struct pt_regs *regs,
230 struct compat_sigframe __user *sf)
231{
232 int err;
233 sigset_t set;
234 struct compat_aux_sigframe __user *aux;
25dc2c80 235 unsigned long psr;
3dd681d9
WD
236
237 err = get_sigset_t(&set, &sf->uc.uc_sigmask);
238 if (err == 0) {
239 sigdelsetmask(&set, ~_BLOCKABLE);
240 set_current_blocked(&set);
241 }
242
243 __get_user_error(regs->regs[0], &sf->uc.uc_mcontext.arm_r0, err);
244 __get_user_error(regs->regs[1], &sf->uc.uc_mcontext.arm_r1, err);
245 __get_user_error(regs->regs[2], &sf->uc.uc_mcontext.arm_r2, err);
246 __get_user_error(regs->regs[3], &sf->uc.uc_mcontext.arm_r3, err);
247 __get_user_error(regs->regs[4], &sf->uc.uc_mcontext.arm_r4, err);
248 __get_user_error(regs->regs[5], &sf->uc.uc_mcontext.arm_r5, err);
249 __get_user_error(regs->regs[6], &sf->uc.uc_mcontext.arm_r6, err);
250 __get_user_error(regs->regs[7], &sf->uc.uc_mcontext.arm_r7, err);
251 __get_user_error(regs->regs[8], &sf->uc.uc_mcontext.arm_r8, err);
252 __get_user_error(regs->regs[9], &sf->uc.uc_mcontext.arm_r9, err);
253 __get_user_error(regs->regs[10], &sf->uc.uc_mcontext.arm_r10, err);
254 __get_user_error(regs->regs[11], &sf->uc.uc_mcontext.arm_fp, err);
255 __get_user_error(regs->regs[12], &sf->uc.uc_mcontext.arm_ip, err);
256 __get_user_error(regs->compat_sp, &sf->uc.uc_mcontext.arm_sp, err);
257 __get_user_error(regs->compat_lr, &sf->uc.uc_mcontext.arm_lr, err);
258 __get_user_error(regs->pc, &sf->uc.uc_mcontext.arm_pc, err);
25dc2c80
MR
259 __get_user_error(psr, &sf->uc.uc_mcontext.arm_cpsr, err);
260
261 regs->pstate = compat_psr_to_pstate(psr);
3dd681d9
WD
262
263 /*
264 * Avoid compat_sys_sigreturn() restarting.
265 */
17c28958 266 forget_syscall(regs);
3dd681d9 267
dbd4d7ca 268 err |= !valid_user_regs(&regs->user_regs, current);
3dd681d9
WD
269
270 aux = (struct compat_aux_sigframe __user *) sf->uc.uc_regspace;
271 if (err == 0)
272 err |= compat_restore_vfp_context(&aux->vfp);
273
274 return err;
275}
276
bf4ce5cc 277COMPAT_SYSCALL_DEFINE0(sigreturn)
3dd681d9 278{
3085e164 279 struct pt_regs *regs = current_pt_regs();
3dd681d9
WD
280 struct compat_sigframe __user *frame;
281
282 /* Always make any pending restarted system calls return -EINTR */
f56141e3 283 current->restart_block.fn = do_no_restart_syscall;
3dd681d9
WD
284
285 /*
286 * Since we stacked the signal on a 64-bit boundary,
287 * then 'sp' should be word aligned here. If it's
288 * not, then the user is trying to mess with us.
289 */
290 if (regs->compat_sp & 7)
291 goto badframe;
292
293 frame = (struct compat_sigframe __user *)regs->compat_sp;
294
96d4f267 295 if (!access_ok(frame, sizeof (*frame)))
3dd681d9
WD
296 goto badframe;
297
298 if (compat_restore_sigframe(regs, frame))
299 goto badframe;
300
301 return regs->regs[0];
302
303badframe:
f71016a8 304 arm64_notify_segfault(regs->compat_sp);
3dd681d9
WD
305 return 0;
306}
307
bf4ce5cc 308COMPAT_SYSCALL_DEFINE0(rt_sigreturn)
3dd681d9 309{
3085e164 310 struct pt_regs *regs = current_pt_regs();
3dd681d9
WD
311 struct compat_rt_sigframe __user *frame;
312
313 /* Always make any pending restarted system calls return -EINTR */
f56141e3 314 current->restart_block.fn = do_no_restart_syscall;
3dd681d9
WD
315
316 /*
317 * Since we stacked the signal on a 64-bit boundary,
318 * then 'sp' should be word aligned here. If it's
319 * not, then the user is trying to mess with us.
320 */
321 if (regs->compat_sp & 7)
322 goto badframe;
323
324 frame = (struct compat_rt_sigframe __user *)regs->compat_sp;
325
96d4f267 326 if (!access_ok(frame, sizeof (*frame)))
3dd681d9
WD
327 goto badframe;
328
329 if (compat_restore_sigframe(regs, &frame->sig))
330 goto badframe;
331
207bdae4 332 if (compat_restore_altstack(&frame->sig.uc.uc_stack))
3dd681d9
WD
333 goto badframe;
334
335 return regs->regs[0];
336
337badframe:
f71016a8 338 arm64_notify_segfault(regs->compat_sp);
3dd681d9
WD
339 return 0;
340}
341
38a7be3c 342static void __user *compat_get_sigframe(struct ksignal *ksig,
88a24cff
WD
343 struct pt_regs *regs,
344 int framesize)
3dd681d9 345{
38a7be3c 346 compat_ulong_t sp = sigsp(regs->compat_sp, ksig);
3dd681d9
WD
347 void __user *frame;
348
3dd681d9
WD
349 /*
350 * ATPCS B01 mandates 8-byte alignment
351 */
352 frame = compat_ptr((compat_uptr_t)((sp - framesize) & ~7));
353
354 /*
355 * Check that we can actually write to the signal frame.
356 */
96d4f267 357 if (!access_ok(frame, framesize))
3dd681d9
WD
358 frame = NULL;
359
360 return frame;
361}
362
060a18c7
WD
363static void compat_setup_return(struct pt_regs *regs, struct k_sigaction *ka,
364 compat_ulong_t __user *rc, void __user *frame,
365 int usig)
3dd681d9
WD
366{
367 compat_ulong_t handler = ptr_to_compat(ka->sa.sa_handler);
368 compat_ulong_t retcode;
d64567f6 369 compat_ulong_t spsr = regs->pstate & ~(PSR_f | PSR_AA32_E_BIT);
3dd681d9
WD
370 int thumb;
371
372 /* Check if the handler is written for ARM or Thumb */
373 thumb = handler & 1;
374
aa62c209 375 if (thumb)
d64567f6 376 spsr |= PSR_AA32_T_BIT;
aa62c209 377 else
d64567f6 378 spsr &= ~PSR_AA32_T_BIT;
aa62c209
P
379
380 /* The IT state must be cleared for both ARM and Thumb-2 */
d64567f6 381 spsr &= ~PSR_AA32_IT_MASK;
3dd681d9 382
2d888f48 383 /* Restore the original endianness */
d64567f6 384 spsr |= PSR_AA32_ENDSTATE;
2d888f48 385
3dd681d9
WD
386 if (ka->sa.sa_flags & SA_RESTORER) {
387 retcode = ptr_to_compat(ka->sa.sa_restorer);
388 } else {
389 /* Set up sigreturn pointer */
390 unsigned int idx = thumb << 1;
391
392 if (ka->sa.sa_flags & SA_SIGINFO)
393 idx += 3;
394
0d747f65 395 retcode = (unsigned long)current->mm->context.vdso +
3dd681d9
WD
396 (idx << 2) + thumb;
397 }
398
399 regs->regs[0] = usig;
400 regs->compat_sp = ptr_to_compat(frame);
401 regs->compat_lr = retcode;
402 regs->pc = handler;
403 regs->pstate = spsr;
3dd681d9
WD
404}
405
406static int compat_setup_sigframe(struct compat_sigframe __user *sf,
407 struct pt_regs *regs, sigset_t *set)
408{
409 struct compat_aux_sigframe __user *aux;
25dc2c80 410 unsigned long psr = pstate_to_compat_psr(regs->pstate);
3dd681d9
WD
411 int err = 0;
412
413 __put_user_error(regs->regs[0], &sf->uc.uc_mcontext.arm_r0, err);
414 __put_user_error(regs->regs[1], &sf->uc.uc_mcontext.arm_r1, err);
415 __put_user_error(regs->regs[2], &sf->uc.uc_mcontext.arm_r2, err);
416 __put_user_error(regs->regs[3], &sf->uc.uc_mcontext.arm_r3, err);
417 __put_user_error(regs->regs[4], &sf->uc.uc_mcontext.arm_r4, err);
418 __put_user_error(regs->regs[5], &sf->uc.uc_mcontext.arm_r5, err);
419 __put_user_error(regs->regs[6], &sf->uc.uc_mcontext.arm_r6, err);
420 __put_user_error(regs->regs[7], &sf->uc.uc_mcontext.arm_r7, err);
421 __put_user_error(regs->regs[8], &sf->uc.uc_mcontext.arm_r8, err);
422 __put_user_error(regs->regs[9], &sf->uc.uc_mcontext.arm_r9, err);
423 __put_user_error(regs->regs[10], &sf->uc.uc_mcontext.arm_r10, err);
424 __put_user_error(regs->regs[11], &sf->uc.uc_mcontext.arm_fp, err);
425 __put_user_error(regs->regs[12], &sf->uc.uc_mcontext.arm_ip, err);
426 __put_user_error(regs->compat_sp, &sf->uc.uc_mcontext.arm_sp, err);
427 __put_user_error(regs->compat_lr, &sf->uc.uc_mcontext.arm_lr, err);
428 __put_user_error(regs->pc, &sf->uc.uc_mcontext.arm_pc, err);
25dc2c80 429 __put_user_error(psr, &sf->uc.uc_mcontext.arm_cpsr, err);
3dd681d9
WD
430
431 __put_user_error((compat_ulong_t)0, &sf->uc.uc_mcontext.trap_no, err);
9141300a 432 /* set the compat FSR WnR */
aed40e01 433 __put_user_error(!!(current->thread.fault_code & ESR_ELx_WNR) <<
9141300a 434 FSR_WRITE_SHIFT, &sf->uc.uc_mcontext.error_code, err);
3dd681d9
WD
435 __put_user_error(current->thread.fault_address, &sf->uc.uc_mcontext.fault_address, err);
436 __put_user_error(set->sig[0], &sf->uc.uc_mcontext.oldmask, err);
437
438 err |= put_sigset_t(&sf->uc.uc_sigmask, set);
439
440 aux = (struct compat_aux_sigframe __user *) sf->uc.uc_regspace;
441
442 if (err == 0)
443 err |= compat_preserve_vfp_context(&aux->vfp);
444 __put_user_error(0, &aux->end_magic, err);
445
446 return err;
447}
448
449/*
450 * 32-bit signal handling routines called from signal.c
451 */
00554fa4 452int compat_setup_rt_frame(int usig, struct ksignal *ksig,
3dd681d9
WD
453 sigset_t *set, struct pt_regs *regs)
454{
455 struct compat_rt_sigframe __user *frame;
3dd681d9
WD
456 int err = 0;
457
38a7be3c 458 frame = compat_get_sigframe(ksig, regs, sizeof(*frame));
3dd681d9
WD
459
460 if (!frame)
461 return 1;
462
00554fa4 463 err |= copy_siginfo_to_user32(&frame->info, &ksig->info);
3dd681d9
WD
464
465 __put_user_error(0, &frame->sig.uc.uc_flags, err);
c0e01d5d 466 __put_user_error(0, &frame->sig.uc.uc_link, err);
3dd681d9 467
207bdae4 468 err |= __compat_save_altstack(&frame->sig.uc.uc_stack, regs->compat_sp);
3dd681d9
WD
469
470 err |= compat_setup_sigframe(&frame->sig, regs, set);
3dd681d9
WD
471
472 if (err == 0) {
00554fa4 473 compat_setup_return(regs, &ksig->ka, frame->sig.retcode, frame, usig);
3dd681d9
WD
474 regs->regs[1] = (compat_ulong_t)(unsigned long)&frame->info;
475 regs->regs[2] = (compat_ulong_t)(unsigned long)&frame->sig.uc;
476 }
477
478 return err;
479}
480
00554fa4 481int compat_setup_frame(int usig, struct ksignal *ksig, sigset_t *set,
3dd681d9
WD
482 struct pt_regs *regs)
483{
484 struct compat_sigframe __user *frame;
485 int err = 0;
486
38a7be3c 487 frame = compat_get_sigframe(ksig, regs, sizeof(*frame));
3dd681d9
WD
488
489 if (!frame)
490 return 1;
491
492 __put_user_error(0x5ac3c35a, &frame->uc.uc_flags, err);
493
494 err |= compat_setup_sigframe(frame, regs, set);
495 if (err == 0)
00554fa4 496 compat_setup_return(regs, &ksig->ka, frame->retcode, frame, usig);
3dd681d9
WD
497
498 return err;
499}
500
3dd681d9
WD
501void compat_setup_restart_syscall(struct pt_regs *regs)
502{
4ed27ecf 503 regs->regs[7] = __NR_compat_restart_syscall;
3dd681d9 504}