1caab277bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 22c020ed8SCatalin Marinas /* 32c020ed8SCatalin Marinas * Based on arch/arm/kernel/signal.c 42c020ed8SCatalin Marinas * 52c020ed8SCatalin Marinas * Copyright (C) 1995-2009 Russell King 62c020ed8SCatalin Marinas * Copyright (C) 2012 ARM Ltd. 72c020ed8SCatalin Marinas */ 82c020ed8SCatalin Marinas 994b07c1fSDave Martin #include <linux/cache.h> 10fd92d4a5SAKASHI Takahiro #include <linux/compat.h> 112c020ed8SCatalin Marinas #include <linux/errno.h> 1220987de3SDave Martin #include <linux/kernel.h> 132c020ed8SCatalin Marinas #include <linux/signal.h> 142c020ed8SCatalin Marinas #include <linux/freezer.h> 1547ccb028SDave Martin #include <linux/stddef.h> 162c020ed8SCatalin Marinas #include <linux/uaccess.h> 1733f08261SDave Martin #include <linux/sizes.h> 18bb4891a6SDave Martin #include <linux/string.h> 1903248addSEric W. Biederman #include <linux/resume_user_mode.h> 202c020ed8SCatalin Marinas #include <linux/ratelimit.h> 21cf7de27aSThomas Garnier #include <linux/syscalls.h> 222c020ed8SCatalin Marinas 238d66772eSJames Morse #include <asm/daifflags.h> 242c020ed8SCatalin Marinas #include <asm/debug-monitors.h> 252c020ed8SCatalin Marinas #include <asm/elf.h> 262c020ed8SCatalin Marinas #include <asm/cacheflush.h> 272c020ed8SCatalin Marinas #include <asm/ucontext.h> 282c020ed8SCatalin Marinas #include <asm/unistd.h> 292c020ed8SCatalin Marinas #include <asm/fpsimd.h> 3017c28958SDave Martin #include <asm/ptrace.h> 31e30e8d46SMark Rutland #include <asm/syscall.h> 322c020ed8SCatalin Marinas #include <asm/signal32.h> 33f71016a8SWill Deacon #include <asm/traps.h> 342c020ed8SCatalin Marinas #include <asm/vdso.h> 352c020ed8SCatalin Marinas 362c020ed8SCatalin Marinas /* 372c020ed8SCatalin Marinas * Do a signal return; undo the signal stack. These are aligned to 128-bit. 382c020ed8SCatalin Marinas */ 392c020ed8SCatalin Marinas struct rt_sigframe { 402c020ed8SCatalin Marinas struct siginfo info; 412c020ed8SCatalin Marinas struct ucontext uc; 4220987de3SDave Martin }; 4320987de3SDave Martin 4420987de3SDave Martin struct frame_record { 45304ef4e8SWill Deacon u64 fp; 46304ef4e8SWill Deacon u64 lr; 472c020ed8SCatalin Marinas }; 482c020ed8SCatalin Marinas 4920987de3SDave Martin struct rt_sigframe_user_layout { 5020987de3SDave Martin struct rt_sigframe __user *sigframe; 5120987de3SDave Martin struct frame_record __user *next_frame; 52bb4891a6SDave Martin 53bb4891a6SDave Martin unsigned long size; /* size of allocated sigframe data */ 54bb4891a6SDave Martin unsigned long limit; /* largest allowed size */ 55bb4891a6SDave Martin 56bb4891a6SDave Martin unsigned long fpsimd_offset; 57bb4891a6SDave Martin unsigned long esr_offset; 588cd969d2SDave Martin unsigned long sve_offset; 59*39e54499SMark Brown unsigned long tpidr2_offset; 6039782210SMark Brown unsigned long za_offset; 6133f08261SDave Martin unsigned long extra_offset; 62bb4891a6SDave Martin unsigned long end_offset; 6320987de3SDave Martin }; 6420987de3SDave Martin 6533f08261SDave Martin #define BASE_SIGFRAME_SIZE round_up(sizeof(struct rt_sigframe), 16) 6633f08261SDave Martin #define TERMINATOR_SIZE round_up(sizeof(struct _aarch64_ctx), 16) 6733f08261SDave Martin #define EXTRA_CONTEXT_SIZE round_up(sizeof(struct extra_context), 16) 6833f08261SDave Martin 69bb4891a6SDave Martin static void init_user_layout(struct rt_sigframe_user_layout *user) 70bb4891a6SDave Martin { 7133f08261SDave Martin const size_t reserved_size = 7233f08261SDave Martin sizeof(user->sigframe->uc.uc_mcontext.__reserved); 7333f08261SDave Martin 74bb4891a6SDave Martin memset(user, 0, sizeof(*user)); 75bb4891a6SDave Martin user->size = offsetof(struct rt_sigframe, uc.uc_mcontext.__reserved); 76bb4891a6SDave Martin 7733f08261SDave Martin user->limit = user->size + reserved_size; 7833f08261SDave Martin 7933f08261SDave Martin user->limit -= TERMINATOR_SIZE; 8033f08261SDave Martin user->limit -= EXTRA_CONTEXT_SIZE; 8133f08261SDave Martin /* Reserve space for extension and terminator ^ */ 82bb4891a6SDave Martin } 83bb4891a6SDave Martin 84bb4891a6SDave Martin static size_t sigframe_size(struct rt_sigframe_user_layout const *user) 85bb4891a6SDave Martin { 86bb4891a6SDave Martin return round_up(max(user->size, sizeof(struct rt_sigframe)), 16); 87bb4891a6SDave Martin } 88bb4891a6SDave Martin 89bb4322f7SDave Martin /* 9033f08261SDave Martin * Sanity limit on the approximate maximum size of signal frame we'll 9133f08261SDave Martin * try to generate. Stack alignment padding and the frame record are 9233f08261SDave Martin * not taken into account. This limit is not a guarantee and is 9333f08261SDave Martin * NOT ABI. 9433f08261SDave Martin */ 957ddcaf78SMark Brown #define SIGFRAME_MAXSZ SZ_256K 9633f08261SDave Martin 9733f08261SDave Martin static int __sigframe_alloc(struct rt_sigframe_user_layout *user, 9833f08261SDave Martin unsigned long *offset, size_t size, bool extend) 9933f08261SDave Martin { 10033f08261SDave Martin size_t padded_size = round_up(size, 16); 10133f08261SDave Martin 10233f08261SDave Martin if (padded_size > user->limit - user->size && 10333f08261SDave Martin !user->extra_offset && 10433f08261SDave Martin extend) { 10533f08261SDave Martin int ret; 10633f08261SDave Martin 10733f08261SDave Martin user->limit += EXTRA_CONTEXT_SIZE; 10833f08261SDave Martin ret = __sigframe_alloc(user, &user->extra_offset, 10933f08261SDave Martin sizeof(struct extra_context), false); 11033f08261SDave Martin if (ret) { 11133f08261SDave Martin user->limit -= EXTRA_CONTEXT_SIZE; 11233f08261SDave Martin return ret; 11333f08261SDave Martin } 11433f08261SDave Martin 11533f08261SDave Martin /* Reserve space for the __reserved[] terminator */ 11633f08261SDave Martin user->size += TERMINATOR_SIZE; 11733f08261SDave Martin 11833f08261SDave Martin /* 11933f08261SDave Martin * Allow expansion up to SIGFRAME_MAXSZ, ensuring space for 12033f08261SDave Martin * the terminator: 12133f08261SDave Martin */ 12233f08261SDave Martin user->limit = SIGFRAME_MAXSZ - TERMINATOR_SIZE; 12333f08261SDave Martin } 12433f08261SDave Martin 12533f08261SDave Martin /* Still not enough space? Bad luck! */ 12633f08261SDave Martin if (padded_size > user->limit - user->size) 12733f08261SDave Martin return -ENOMEM; 12833f08261SDave Martin 12933f08261SDave Martin *offset = user->size; 13033f08261SDave Martin user->size += padded_size; 13133f08261SDave Martin 13233f08261SDave Martin return 0; 13333f08261SDave Martin } 13433f08261SDave Martin 13533f08261SDave Martin /* 136bb4322f7SDave Martin * Allocate space for an optional record of <size> bytes in the user 137bb4322f7SDave Martin * signal frame. The offset from the signal frame base address to the 138bb4322f7SDave Martin * allocated block is assigned to *offset. 139bb4322f7SDave Martin */ 140bb4322f7SDave Martin static int sigframe_alloc(struct rt_sigframe_user_layout *user, 141bb4322f7SDave Martin unsigned long *offset, size_t size) 142bb4322f7SDave Martin { 14333f08261SDave Martin return __sigframe_alloc(user, offset, size, true); 14433f08261SDave Martin } 145bb4322f7SDave Martin 14633f08261SDave Martin /* Allocate the null terminator record and prevent further allocations */ 14733f08261SDave Martin static int sigframe_alloc_end(struct rt_sigframe_user_layout *user) 14833f08261SDave Martin { 14933f08261SDave Martin int ret; 150bb4322f7SDave Martin 15133f08261SDave Martin /* Un-reserve the space reserved for the terminator: */ 15233f08261SDave Martin user->limit += TERMINATOR_SIZE; 15333f08261SDave Martin 15433f08261SDave Martin ret = sigframe_alloc(user, &user->end_offset, 15533f08261SDave Martin sizeof(struct _aarch64_ctx)); 15633f08261SDave Martin if (ret) 15733f08261SDave Martin return ret; 15833f08261SDave Martin 15933f08261SDave Martin /* Prevent further allocation: */ 16033f08261SDave Martin user->limit = user->size; 161bb4322f7SDave Martin return 0; 162bb4322f7SDave Martin } 163bb4322f7SDave Martin 164bb4891a6SDave Martin static void __user *apply_user_offset( 165bb4891a6SDave Martin struct rt_sigframe_user_layout const *user, unsigned long offset) 166bb4891a6SDave Martin { 167bb4891a6SDave Martin char __user *base = (char __user *)user->sigframe; 168bb4891a6SDave Martin 169bb4891a6SDave Martin return base + offset; 170bb4891a6SDave Martin } 171bb4891a6SDave Martin 1722c020ed8SCatalin Marinas static int preserve_fpsimd_context(struct fpsimd_context __user *ctx) 1732c020ed8SCatalin Marinas { 17465896545SDave Martin struct user_fpsimd_state const *fpsimd = 17565896545SDave Martin ¤t->thread.uw.fpsimd_state; 1762c020ed8SCatalin Marinas int err; 1772c020ed8SCatalin Marinas 1782c020ed8SCatalin Marinas /* copy the FP and status/control registers */ 1792c020ed8SCatalin Marinas err = __copy_to_user(ctx->vregs, fpsimd->vregs, sizeof(fpsimd->vregs)); 1802c020ed8SCatalin Marinas __put_user_error(fpsimd->fpsr, &ctx->fpsr, err); 1812c020ed8SCatalin Marinas __put_user_error(fpsimd->fpcr, &ctx->fpcr, err); 1822c020ed8SCatalin Marinas 1832c020ed8SCatalin Marinas /* copy the magic/size information */ 1842c020ed8SCatalin Marinas __put_user_error(FPSIMD_MAGIC, &ctx->head.magic, err); 1852c020ed8SCatalin Marinas __put_user_error(sizeof(struct fpsimd_context), &ctx->head.size, err); 1862c020ed8SCatalin Marinas 1872c020ed8SCatalin Marinas return err ? -EFAULT : 0; 1882c020ed8SCatalin Marinas } 1892c020ed8SCatalin Marinas 1902c020ed8SCatalin Marinas static int restore_fpsimd_context(struct fpsimd_context __user *ctx) 1912c020ed8SCatalin Marinas { 1920abdeff5SDave Martin struct user_fpsimd_state fpsimd; 1932c020ed8SCatalin Marinas __u32 magic, size; 1942c020ed8SCatalin Marinas int err = 0; 1952c020ed8SCatalin Marinas 1962c020ed8SCatalin Marinas /* check the magic/size information */ 1972c020ed8SCatalin Marinas __get_user_error(magic, &ctx->head.magic, err); 1982c020ed8SCatalin Marinas __get_user_error(size, &ctx->head.size, err); 1992c020ed8SCatalin Marinas if (err) 2002c020ed8SCatalin Marinas return -EFAULT; 2012c020ed8SCatalin Marinas if (magic != FPSIMD_MAGIC || size != sizeof(struct fpsimd_context)) 2022c020ed8SCatalin Marinas return -EINVAL; 2032c020ed8SCatalin Marinas 2042c020ed8SCatalin Marinas /* copy the FP and status/control registers */ 2052c020ed8SCatalin Marinas err = __copy_from_user(fpsimd.vregs, ctx->vregs, 2062c020ed8SCatalin Marinas sizeof(fpsimd.vregs)); 2072c020ed8SCatalin Marinas __get_user_error(fpsimd.fpsr, &ctx->fpsr, err); 2082c020ed8SCatalin Marinas __get_user_error(fpsimd.fpcr, &ctx->fpcr, err); 2092c020ed8SCatalin Marinas 2108cd969d2SDave Martin clear_thread_flag(TIF_SVE); 211baa85152SMark Brown current->thread.fp_type = FP_STATE_FPSIMD; 2128cd969d2SDave Martin 2132c020ed8SCatalin Marinas /* load the hardware registers from the fpsimd_state structure */ 214c51f9269SArd Biesheuvel if (!err) 215c51f9269SArd Biesheuvel fpsimd_update_current_state(&fpsimd); 2162c020ed8SCatalin Marinas 2172c020ed8SCatalin Marinas return err ? -EFAULT : 0; 2182c020ed8SCatalin Marinas } 2192c020ed8SCatalin Marinas 2208cd969d2SDave Martin 22147ccb028SDave Martin struct user_ctxs { 22247ccb028SDave Martin struct fpsimd_context __user *fpsimd; 2238cd969d2SDave Martin struct sve_context __user *sve; 224*39e54499SMark Brown struct tpidr2_context __user *tpidr2; 22539782210SMark Brown struct za_context __user *za; 22647ccb028SDave Martin }; 22747ccb028SDave Martin 2288cd969d2SDave Martin #ifdef CONFIG_ARM64_SVE 2298cd969d2SDave Martin 2308cd969d2SDave Martin static int preserve_sve_context(struct sve_context __user *ctx) 2318cd969d2SDave Martin { 2328cd969d2SDave Martin int err = 0; 2338cd969d2SDave Martin u16 reserved[ARRAY_SIZE(ctx->__reserved)]; 23485ed24daSMark Brown u16 flags = 0; 2350423eedcSMark Brown unsigned int vl = task_get_sve_vl(current); 2368cd969d2SDave Martin unsigned int vq = 0; 2378cd969d2SDave Martin 23885ed24daSMark Brown if (thread_sm_enabled(¤t->thread)) { 23985ed24daSMark Brown vl = task_get_sme_vl(current); 2408cd969d2SDave Martin vq = sve_vq_from_vl(vl); 24185ed24daSMark Brown flags |= SVE_SIG_FLAG_SM; 24285ed24daSMark Brown } else if (test_thread_flag(TIF_SVE)) { 24385ed24daSMark Brown vq = sve_vq_from_vl(vl); 24485ed24daSMark Brown } 2458cd969d2SDave Martin 2468cd969d2SDave Martin memset(reserved, 0, sizeof(reserved)); 2478cd969d2SDave Martin 2488cd969d2SDave Martin __put_user_error(SVE_MAGIC, &ctx->head.magic, err); 2498cd969d2SDave Martin __put_user_error(round_up(SVE_SIG_CONTEXT_SIZE(vq), 16), 2508cd969d2SDave Martin &ctx->head.size, err); 2518cd969d2SDave Martin __put_user_error(vl, &ctx->vl, err); 25285ed24daSMark Brown __put_user_error(flags, &ctx->flags, err); 2538cd969d2SDave Martin BUILD_BUG_ON(sizeof(ctx->__reserved) != sizeof(reserved)); 2548cd969d2SDave Martin err |= __copy_to_user(&ctx->__reserved, reserved, sizeof(reserved)); 2558cd969d2SDave Martin 2568cd969d2SDave Martin if (vq) { 2578cd969d2SDave Martin /* 2588cd969d2SDave Martin * This assumes that the SVE state has already been saved to 25968a4c52eSJulien Grall * the task struct by calling the function 26068a4c52eSJulien Grall * fpsimd_signal_preserve_current_state(). 2618cd969d2SDave Martin */ 2628cd969d2SDave Martin err |= __copy_to_user((char __user *)ctx + SVE_SIG_REGS_OFFSET, 2638cd969d2SDave Martin current->thread.sve_state, 2648cd969d2SDave Martin SVE_SIG_REGS_SIZE(vq)); 2658cd969d2SDave Martin } 2668cd969d2SDave Martin 2678cd969d2SDave Martin return err ? -EFAULT : 0; 2688cd969d2SDave Martin } 2698cd969d2SDave Martin 2708cd969d2SDave Martin static int restore_sve_fpsimd_context(struct user_ctxs *user) 2718cd969d2SDave Martin { 2728cd969d2SDave Martin int err; 27385ed24daSMark Brown unsigned int vl, vq; 2740abdeff5SDave Martin struct user_fpsimd_state fpsimd; 2758cd969d2SDave Martin struct sve_context sve; 2768cd969d2SDave Martin 2778cd969d2SDave Martin if (__copy_from_user(&sve, user->sve, sizeof(sve))) 2788cd969d2SDave Martin return -EFAULT; 2798cd969d2SDave Martin 28085ed24daSMark Brown if (sve.flags & SVE_SIG_FLAG_SM) { 28185ed24daSMark Brown if (!system_supports_sme()) 28285ed24daSMark Brown return -EINVAL; 28385ed24daSMark Brown 28485ed24daSMark Brown vl = task_get_sme_vl(current); 28585ed24daSMark Brown } else { 286df07443fSMark Brown if (!system_supports_sve()) 287df07443fSMark Brown return -EINVAL; 288df07443fSMark Brown 28985ed24daSMark Brown vl = task_get_sve_vl(current); 29085ed24daSMark Brown } 29185ed24daSMark Brown 29285ed24daSMark Brown if (sve.vl != vl) 2938cd969d2SDave Martin return -EINVAL; 2948cd969d2SDave Martin 2958cd969d2SDave Martin if (sve.head.size <= sizeof(*user->sve)) { 2968cd969d2SDave Martin clear_thread_flag(TIF_SVE); 297ec0067a6SMark Brown current->thread.svcr &= ~SVCR_SM_MASK; 298baa85152SMark Brown current->thread.fp_type = FP_STATE_FPSIMD; 2998cd969d2SDave Martin goto fpsimd_only; 3008cd969d2SDave Martin } 3018cd969d2SDave Martin 3028cd969d2SDave Martin vq = sve_vq_from_vl(sve.vl); 3038cd969d2SDave Martin 3048cd969d2SDave Martin if (sve.head.size < SVE_SIG_CONTEXT_SIZE(vq)) 3058cd969d2SDave Martin return -EINVAL; 3068cd969d2SDave Martin 3078cd969d2SDave Martin /* 3088cd969d2SDave Martin * Careful: we are about __copy_from_user() directly into 3098cd969d2SDave Martin * thread.sve_state with preemption enabled, so protection is 3108cd969d2SDave Martin * needed to prevent a racing context switch from writing stale 3118cd969d2SDave Martin * registers back over the new data. 3128cd969d2SDave Martin */ 3138cd969d2SDave Martin 3148cd969d2SDave Martin fpsimd_flush_task_state(current); 3158cd969d2SDave Martin /* From now, fpsimd_thread_switch() won't touch thread.sve_state */ 3168cd969d2SDave Martin 317826a4fddSMark Brown sve_alloc(current, true); 3187559b7d7SMark Brown if (!current->thread.sve_state) { 3197559b7d7SMark Brown clear_thread_flag(TIF_SVE); 3207559b7d7SMark Brown return -ENOMEM; 3217559b7d7SMark Brown } 3227559b7d7SMark Brown 3238cd969d2SDave Martin err = __copy_from_user(current->thread.sve_state, 3248cd969d2SDave Martin (char __user const *)user->sve + 3258cd969d2SDave Martin SVE_SIG_REGS_OFFSET, 3268cd969d2SDave Martin SVE_SIG_REGS_SIZE(vq)); 3278cd969d2SDave Martin if (err) 3288cd969d2SDave Martin return -EFAULT; 3298cd969d2SDave Martin 33085ed24daSMark Brown if (sve.flags & SVE_SIG_FLAG_SM) 331ec0067a6SMark Brown current->thread.svcr |= SVCR_SM_MASK; 33285ed24daSMark Brown else 3338cd969d2SDave Martin set_thread_flag(TIF_SVE); 334baa85152SMark Brown current->thread.fp_type = FP_STATE_SVE; 3358cd969d2SDave Martin 3368cd969d2SDave Martin fpsimd_only: 3378cd969d2SDave Martin /* copy the FP and status/control registers */ 3388cd969d2SDave Martin /* restore_sigframe() already checked that user->fpsimd != NULL. */ 3398cd969d2SDave Martin err = __copy_from_user(fpsimd.vregs, user->fpsimd->vregs, 3408cd969d2SDave Martin sizeof(fpsimd.vregs)); 3418cd969d2SDave Martin __get_user_error(fpsimd.fpsr, &user->fpsimd->fpsr, err); 3428cd969d2SDave Martin __get_user_error(fpsimd.fpcr, &user->fpsimd->fpcr, err); 3438cd969d2SDave Martin 3448cd969d2SDave Martin /* load the hardware registers from the fpsimd_state structure */ 3458cd969d2SDave Martin if (!err) 3468cd969d2SDave Martin fpsimd_update_current_state(&fpsimd); 3478cd969d2SDave Martin 3488cd969d2SDave Martin return err ? -EFAULT : 0; 3498cd969d2SDave Martin } 3508cd969d2SDave Martin 3518cd969d2SDave Martin #else /* ! CONFIG_ARM64_SVE */ 3528cd969d2SDave Martin 353df07443fSMark Brown static int restore_sve_fpsimd_context(struct user_ctxs *user) 354df07443fSMark Brown { 355df07443fSMark Brown WARN_ON_ONCE(1); 356df07443fSMark Brown return -EINVAL; 357df07443fSMark Brown } 358df07443fSMark Brown 359df07443fSMark Brown /* Turn any non-optimised out attempts to use this into a link error: */ 3608cd969d2SDave Martin extern int preserve_sve_context(void __user *ctx); 3618cd969d2SDave Martin 3628cd969d2SDave Martin #endif /* ! CONFIG_ARM64_SVE */ 3638cd969d2SDave Martin 36439782210SMark Brown #ifdef CONFIG_ARM64_SME 36539782210SMark Brown 366*39e54499SMark Brown static int preserve_tpidr2_context(struct tpidr2_context __user *ctx) 367*39e54499SMark Brown { 368*39e54499SMark Brown int err = 0; 369*39e54499SMark Brown 370*39e54499SMark Brown current->thread.tpidr2_el0 = read_sysreg_s(SYS_TPIDR2_EL0); 371*39e54499SMark Brown 372*39e54499SMark Brown __put_user_error(TPIDR2_MAGIC, &ctx->head.magic, err); 373*39e54499SMark Brown __put_user_error(sizeof(*ctx), &ctx->head.size, err); 374*39e54499SMark Brown __put_user_error(current->thread.tpidr2_el0, &ctx->tpidr2, err); 375*39e54499SMark Brown 376*39e54499SMark Brown return err; 377*39e54499SMark Brown } 378*39e54499SMark Brown 379*39e54499SMark Brown static int restore_tpidr2_context(struct user_ctxs *user) 380*39e54499SMark Brown { 381*39e54499SMark Brown u64 tpidr2_el0; 382*39e54499SMark Brown int err = 0; 383*39e54499SMark Brown 384*39e54499SMark Brown /* Magic and size were validated deciding to call this function */ 385*39e54499SMark Brown __get_user_error(tpidr2_el0, &user->tpidr2->tpidr2, err); 386*39e54499SMark Brown if (!err) 387*39e54499SMark Brown current->thread.tpidr2_el0 = tpidr2_el0; 388*39e54499SMark Brown 389*39e54499SMark Brown return err; 390*39e54499SMark Brown } 391*39e54499SMark Brown 39239782210SMark Brown static int preserve_za_context(struct za_context __user *ctx) 39339782210SMark Brown { 39439782210SMark Brown int err = 0; 39539782210SMark Brown u16 reserved[ARRAY_SIZE(ctx->__reserved)]; 39639782210SMark Brown unsigned int vl = task_get_sme_vl(current); 39739782210SMark Brown unsigned int vq; 39839782210SMark Brown 39939782210SMark Brown if (thread_za_enabled(¤t->thread)) 40039782210SMark Brown vq = sve_vq_from_vl(vl); 40139782210SMark Brown else 40239782210SMark Brown vq = 0; 40339782210SMark Brown 40439782210SMark Brown memset(reserved, 0, sizeof(reserved)); 40539782210SMark Brown 40639782210SMark Brown __put_user_error(ZA_MAGIC, &ctx->head.magic, err); 40739782210SMark Brown __put_user_error(round_up(ZA_SIG_CONTEXT_SIZE(vq), 16), 40839782210SMark Brown &ctx->head.size, err); 40939782210SMark Brown __put_user_error(vl, &ctx->vl, err); 41039782210SMark Brown BUILD_BUG_ON(sizeof(ctx->__reserved) != sizeof(reserved)); 41139782210SMark Brown err |= __copy_to_user(&ctx->__reserved, reserved, sizeof(reserved)); 41239782210SMark Brown 41339782210SMark Brown if (vq) { 41439782210SMark Brown /* 41539782210SMark Brown * This assumes that the ZA state has already been saved to 41639782210SMark Brown * the task struct by calling the function 41739782210SMark Brown * fpsimd_signal_preserve_current_state(). 41839782210SMark Brown */ 41939782210SMark Brown err |= __copy_to_user((char __user *)ctx + ZA_SIG_REGS_OFFSET, 42039782210SMark Brown current->thread.za_state, 42139782210SMark Brown ZA_SIG_REGS_SIZE(vq)); 42239782210SMark Brown } 42339782210SMark Brown 42439782210SMark Brown return err ? -EFAULT : 0; 42539782210SMark Brown } 42639782210SMark Brown 4271bec877bSCatalin Marinas static int restore_za_context(struct user_ctxs *user) 42839782210SMark Brown { 42939782210SMark Brown int err; 43039782210SMark Brown unsigned int vq; 43139782210SMark Brown struct za_context za; 43239782210SMark Brown 43339782210SMark Brown if (__copy_from_user(&za, user->za, sizeof(za))) 43439782210SMark Brown return -EFAULT; 43539782210SMark Brown 43639782210SMark Brown if (za.vl != task_get_sme_vl(current)) 43739782210SMark Brown return -EINVAL; 43839782210SMark Brown 43939782210SMark Brown if (za.head.size <= sizeof(*user->za)) { 440ec0067a6SMark Brown current->thread.svcr &= ~SVCR_ZA_MASK; 44139782210SMark Brown return 0; 44239782210SMark Brown } 44339782210SMark Brown 44439782210SMark Brown vq = sve_vq_from_vl(za.vl); 44539782210SMark Brown 44639782210SMark Brown if (za.head.size < ZA_SIG_CONTEXT_SIZE(vq)) 44739782210SMark Brown return -EINVAL; 44839782210SMark Brown 44939782210SMark Brown /* 45039782210SMark Brown * Careful: we are about __copy_from_user() directly into 45139782210SMark Brown * thread.za_state with preemption enabled, so protection is 45239782210SMark Brown * needed to prevent a racing context switch from writing stale 45339782210SMark Brown * registers back over the new data. 45439782210SMark Brown */ 45539782210SMark Brown 45639782210SMark Brown fpsimd_flush_task_state(current); 45739782210SMark Brown /* From now, fpsimd_thread_switch() won't touch thread.sve_state */ 45839782210SMark Brown 45939782210SMark Brown sme_alloc(current); 46039782210SMark Brown if (!current->thread.za_state) { 461ec0067a6SMark Brown current->thread.svcr &= ~SVCR_ZA_MASK; 46239782210SMark Brown clear_thread_flag(TIF_SME); 46339782210SMark Brown return -ENOMEM; 46439782210SMark Brown } 46539782210SMark Brown 46639782210SMark Brown err = __copy_from_user(current->thread.za_state, 46739782210SMark Brown (char __user const *)user->za + 46839782210SMark Brown ZA_SIG_REGS_OFFSET, 46939782210SMark Brown ZA_SIG_REGS_SIZE(vq)); 47039782210SMark Brown if (err) 47139782210SMark Brown return -EFAULT; 47239782210SMark Brown 47339782210SMark Brown set_thread_flag(TIF_SME); 474ec0067a6SMark Brown current->thread.svcr |= SVCR_ZA_MASK; 47539782210SMark Brown 47639782210SMark Brown return 0; 47739782210SMark Brown } 47839782210SMark Brown #else /* ! CONFIG_ARM64_SME */ 47939782210SMark Brown 48039782210SMark Brown /* Turn any non-optimised out attempts to use these into a link error: */ 481*39e54499SMark Brown extern int preserve_tpidr2_context(void __user *ctx); 482*39e54499SMark Brown extern int restore_tpidr2_context(struct user_ctxs *user); 48339782210SMark Brown extern int preserve_za_context(void __user *ctx); 48439782210SMark Brown extern int restore_za_context(struct user_ctxs *user); 48539782210SMark Brown 48639782210SMark Brown #endif /* ! CONFIG_ARM64_SME */ 4878cd969d2SDave Martin 48847ccb028SDave Martin static int parse_user_sigframe(struct user_ctxs *user, 48947ccb028SDave Martin struct rt_sigframe __user *sf) 49047ccb028SDave Martin { 49147ccb028SDave Martin struct sigcontext __user *const sc = &sf->uc.uc_mcontext; 492bb4891a6SDave Martin struct _aarch64_ctx __user *head; 493bb4891a6SDave Martin char __user *base = (char __user *)&sc->__reserved; 49447ccb028SDave Martin size_t offset = 0; 495bb4891a6SDave Martin size_t limit = sizeof(sc->__reserved); 49633f08261SDave Martin bool have_extra_context = false; 49733f08261SDave Martin char const __user *const sfp = (char const __user *)sf; 49847ccb028SDave Martin 49947ccb028SDave Martin user->fpsimd = NULL; 5008cd969d2SDave Martin user->sve = NULL; 501*39e54499SMark Brown user->tpidr2 = NULL; 50239782210SMark Brown user->za = NULL; 50347ccb028SDave Martin 504bb4891a6SDave Martin if (!IS_ALIGNED((unsigned long)base, 16)) 50547ccb028SDave Martin goto invalid; 50647ccb028SDave Martin 507bb4891a6SDave Martin while (1) { 508bb4891a6SDave Martin int err = 0; 509bb4891a6SDave Martin u32 magic, size; 51033f08261SDave Martin char const __user *userp; 51133f08261SDave Martin struct extra_context const __user *extra; 51233f08261SDave Martin u64 extra_datap; 51333f08261SDave Martin u32 extra_size; 51433f08261SDave Martin struct _aarch64_ctx const __user *end; 51533f08261SDave Martin u32 end_magic, end_size; 516bb4891a6SDave Martin 517bb4891a6SDave Martin if (limit - offset < sizeof(*head)) 518bb4891a6SDave Martin goto invalid; 519bb4891a6SDave Martin 520bb4891a6SDave Martin if (!IS_ALIGNED(offset, 16)) 521bb4891a6SDave Martin goto invalid; 522bb4891a6SDave Martin 523bb4891a6SDave Martin head = (struct _aarch64_ctx __user *)(base + offset); 52447ccb028SDave Martin __get_user_error(magic, &head->magic, err); 52547ccb028SDave Martin __get_user_error(size, &head->size, err); 52647ccb028SDave Martin if (err) 52747ccb028SDave Martin return err; 52847ccb028SDave Martin 529bb4891a6SDave Martin if (limit - offset < size) 530bb4891a6SDave Martin goto invalid; 531bb4891a6SDave Martin 53247ccb028SDave Martin switch (magic) { 53347ccb028SDave Martin case 0: 53447ccb028SDave Martin if (size) 53547ccb028SDave Martin goto invalid; 53647ccb028SDave Martin 53747ccb028SDave Martin goto done; 53847ccb028SDave Martin 53947ccb028SDave Martin case FPSIMD_MAGIC: 5406d502b6bSSuzuki K Poulose if (!system_supports_fpsimd()) 5416d502b6bSSuzuki K Poulose goto invalid; 54247ccb028SDave Martin if (user->fpsimd) 54347ccb028SDave Martin goto invalid; 54447ccb028SDave Martin 545bb4891a6SDave Martin if (size < sizeof(*user->fpsimd)) 54647ccb028SDave Martin goto invalid; 54747ccb028SDave Martin 54847ccb028SDave Martin user->fpsimd = (struct fpsimd_context __user *)head; 54947ccb028SDave Martin break; 55047ccb028SDave Martin 55147ccb028SDave Martin case ESR_MAGIC: 55247ccb028SDave Martin /* ignore */ 55347ccb028SDave Martin break; 55447ccb028SDave Martin 5558cd969d2SDave Martin case SVE_MAGIC: 55685ed24daSMark Brown if (!system_supports_sve() && !system_supports_sme()) 5578cd969d2SDave Martin goto invalid; 5588cd969d2SDave Martin 5598cd969d2SDave Martin if (user->sve) 5608cd969d2SDave Martin goto invalid; 5618cd969d2SDave Martin 5628cd969d2SDave Martin if (size < sizeof(*user->sve)) 5638cd969d2SDave Martin goto invalid; 5648cd969d2SDave Martin 5658cd969d2SDave Martin user->sve = (struct sve_context __user *)head; 5668cd969d2SDave Martin break; 5678cd969d2SDave Martin 568*39e54499SMark Brown case TPIDR2_MAGIC: 569*39e54499SMark Brown if (!system_supports_sme()) 570*39e54499SMark Brown goto invalid; 571*39e54499SMark Brown 572*39e54499SMark Brown if (user->tpidr2) 573*39e54499SMark Brown goto invalid; 574*39e54499SMark Brown 575*39e54499SMark Brown if (size != sizeof(*user->tpidr2)) 576*39e54499SMark Brown goto invalid; 577*39e54499SMark Brown 578*39e54499SMark Brown user->tpidr2 = (struct tpidr2_context __user *)head; 579*39e54499SMark Brown break; 580*39e54499SMark Brown 58139782210SMark Brown case ZA_MAGIC: 58239782210SMark Brown if (!system_supports_sme()) 58339782210SMark Brown goto invalid; 58439782210SMark Brown 58539782210SMark Brown if (user->za) 58639782210SMark Brown goto invalid; 58739782210SMark Brown 58839782210SMark Brown if (size < sizeof(*user->za)) 58939782210SMark Brown goto invalid; 59039782210SMark Brown 59139782210SMark Brown user->za = (struct za_context __user *)head; 59239782210SMark Brown break; 59339782210SMark Brown 59433f08261SDave Martin case EXTRA_MAGIC: 59533f08261SDave Martin if (have_extra_context) 59633f08261SDave Martin goto invalid; 59733f08261SDave Martin 59833f08261SDave Martin if (size < sizeof(*extra)) 59933f08261SDave Martin goto invalid; 60033f08261SDave Martin 60133f08261SDave Martin userp = (char const __user *)head; 60233f08261SDave Martin 60333f08261SDave Martin extra = (struct extra_context const __user *)userp; 60433f08261SDave Martin userp += size; 60533f08261SDave Martin 60633f08261SDave Martin __get_user_error(extra_datap, &extra->datap, err); 60733f08261SDave Martin __get_user_error(extra_size, &extra->size, err); 60833f08261SDave Martin if (err) 60933f08261SDave Martin return err; 61033f08261SDave Martin 61133f08261SDave Martin /* Check for the dummy terminator in __reserved[]: */ 61233f08261SDave Martin 61333f08261SDave Martin if (limit - offset - size < TERMINATOR_SIZE) 61433f08261SDave Martin goto invalid; 61533f08261SDave Martin 61633f08261SDave Martin end = (struct _aarch64_ctx const __user *)userp; 61733f08261SDave Martin userp += TERMINATOR_SIZE; 61833f08261SDave Martin 61933f08261SDave Martin __get_user_error(end_magic, &end->magic, err); 62033f08261SDave Martin __get_user_error(end_size, &end->size, err); 62133f08261SDave Martin if (err) 62233f08261SDave Martin return err; 62333f08261SDave Martin 62433f08261SDave Martin if (end_magic || end_size) 62533f08261SDave Martin goto invalid; 62633f08261SDave Martin 62733f08261SDave Martin /* Prevent looping/repeated parsing of extra_context */ 62833f08261SDave Martin have_extra_context = true; 62933f08261SDave Martin 63033f08261SDave Martin base = (__force void __user *)extra_datap; 63133f08261SDave Martin if (!IS_ALIGNED((unsigned long)base, 16)) 63233f08261SDave Martin goto invalid; 63333f08261SDave Martin 63433f08261SDave Martin if (!IS_ALIGNED(extra_size, 16)) 63533f08261SDave Martin goto invalid; 63633f08261SDave Martin 63733f08261SDave Martin if (base != userp) 63833f08261SDave Martin goto invalid; 63933f08261SDave Martin 64033f08261SDave Martin /* Reject "unreasonably large" frames: */ 64133f08261SDave Martin if (extra_size > sfp + SIGFRAME_MAXSZ - userp) 64233f08261SDave Martin goto invalid; 64333f08261SDave Martin 64433f08261SDave Martin /* 64533f08261SDave Martin * Ignore trailing terminator in __reserved[] 64633f08261SDave Martin * and start parsing extra data: 64733f08261SDave Martin */ 64833f08261SDave Martin offset = 0; 64933f08261SDave Martin limit = extra_size; 650abf73988SDave Martin 65196d4f267SLinus Torvalds if (!access_ok(base, limit)) 652abf73988SDave Martin goto invalid; 653abf73988SDave Martin 65433f08261SDave Martin continue; 65533f08261SDave Martin 65647ccb028SDave Martin default: 65747ccb028SDave Martin goto invalid; 65847ccb028SDave Martin } 65947ccb028SDave Martin 66047ccb028SDave Martin if (size < sizeof(*head)) 66147ccb028SDave Martin goto invalid; 66247ccb028SDave Martin 663bb4891a6SDave Martin if (limit - offset < size) 66447ccb028SDave Martin goto invalid; 66547ccb028SDave Martin 66647ccb028SDave Martin offset += size; 66747ccb028SDave Martin } 66847ccb028SDave Martin 66947ccb028SDave Martin done: 67047ccb028SDave Martin return 0; 67147ccb028SDave Martin 67247ccb028SDave Martin invalid: 67347ccb028SDave Martin return -EINVAL; 67447ccb028SDave Martin } 67547ccb028SDave Martin 6762c020ed8SCatalin Marinas static int restore_sigframe(struct pt_regs *regs, 6772c020ed8SCatalin Marinas struct rt_sigframe __user *sf) 6782c020ed8SCatalin Marinas { 6792c020ed8SCatalin Marinas sigset_t set; 6802c020ed8SCatalin Marinas int i, err; 68147ccb028SDave Martin struct user_ctxs user; 6822c020ed8SCatalin Marinas 6832c020ed8SCatalin Marinas err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set)); 6842c020ed8SCatalin Marinas if (err == 0) 6852c020ed8SCatalin Marinas set_current_blocked(&set); 6862c020ed8SCatalin Marinas 6872c020ed8SCatalin Marinas for (i = 0; i < 31; i++) 6882c020ed8SCatalin Marinas __get_user_error(regs->regs[i], &sf->uc.uc_mcontext.regs[i], 6892c020ed8SCatalin Marinas err); 6902c020ed8SCatalin Marinas __get_user_error(regs->sp, &sf->uc.uc_mcontext.sp, err); 6912c020ed8SCatalin Marinas __get_user_error(regs->pc, &sf->uc.uc_mcontext.pc, err); 6922c020ed8SCatalin Marinas __get_user_error(regs->pstate, &sf->uc.uc_mcontext.pstate, err); 6932c020ed8SCatalin Marinas 6942c020ed8SCatalin Marinas /* 6952c020ed8SCatalin Marinas * Avoid sys_rt_sigreturn() restarting. 6962c020ed8SCatalin Marinas */ 69717c28958SDave Martin forget_syscall(regs); 6982c020ed8SCatalin Marinas 699dbd4d7caSMark Rutland err |= !valid_user_regs(®s->user_regs, current); 70047ccb028SDave Martin if (err == 0) 70147ccb028SDave Martin err = parse_user_sigframe(&user, sf); 7022c020ed8SCatalin Marinas 7036d502b6bSSuzuki K Poulose if (err == 0 && system_supports_fpsimd()) { 7048cd969d2SDave Martin if (!user.fpsimd) 7058cd969d2SDave Martin return -EINVAL; 7068cd969d2SDave Martin 707df07443fSMark Brown if (user.sve) 7088cd969d2SDave Martin err = restore_sve_fpsimd_context(&user); 709df07443fSMark Brown else 71047ccb028SDave Martin err = restore_fpsimd_context(user.fpsimd); 7118cd969d2SDave Martin } 7122c020ed8SCatalin Marinas 713*39e54499SMark Brown if (err == 0 && system_supports_sme() && user.tpidr2) 714*39e54499SMark Brown err = restore_tpidr2_context(&user); 715*39e54499SMark Brown 71639782210SMark Brown if (err == 0 && system_supports_sme() && user.za) 71739782210SMark Brown err = restore_za_context(&user); 71839782210SMark Brown 7192c020ed8SCatalin Marinas return err; 7202c020ed8SCatalin Marinas } 7212c020ed8SCatalin Marinas 722bf4ce5ccSMark Rutland SYSCALL_DEFINE0(rt_sigreturn) 7232c020ed8SCatalin Marinas { 7243085e164SMark Rutland struct pt_regs *regs = current_pt_regs(); 7252c020ed8SCatalin Marinas struct rt_sigframe __user *frame; 7262c020ed8SCatalin Marinas 7272c020ed8SCatalin Marinas /* Always make any pending restarted system calls return -EINTR */ 728f56141e3SAndy Lutomirski current->restart_block.fn = do_no_restart_syscall; 7292c020ed8SCatalin Marinas 7302c020ed8SCatalin Marinas /* 7312c020ed8SCatalin Marinas * Since we stacked the signal on a 128-bit boundary, then 'sp' should 7322c020ed8SCatalin Marinas * be word aligned here. 7332c020ed8SCatalin Marinas */ 7342c020ed8SCatalin Marinas if (regs->sp & 15) 7352c020ed8SCatalin Marinas goto badframe; 7362c020ed8SCatalin Marinas 7372c020ed8SCatalin Marinas frame = (struct rt_sigframe __user *)regs->sp; 7382c020ed8SCatalin Marinas 73996d4f267SLinus Torvalds if (!access_ok(frame, sizeof (*frame))) 7402c020ed8SCatalin Marinas goto badframe; 7412c020ed8SCatalin Marinas 7422c020ed8SCatalin Marinas if (restore_sigframe(regs, frame)) 7432c020ed8SCatalin Marinas goto badframe; 7442c020ed8SCatalin Marinas 745207bdae4SAl Viro if (restore_altstack(&frame->uc.uc_stack)) 7462c020ed8SCatalin Marinas goto badframe; 7472c020ed8SCatalin Marinas 7482c020ed8SCatalin Marinas return regs->regs[0]; 7492c020ed8SCatalin Marinas 7502c020ed8SCatalin Marinas badframe: 751f71016a8SWill Deacon arm64_notify_segfault(regs->sp); 7522c020ed8SCatalin Marinas return 0; 7532c020ed8SCatalin Marinas } 7542c020ed8SCatalin Marinas 75594b07c1fSDave Martin /* 75694b07c1fSDave Martin * Determine the layout of optional records in the signal frame 75794b07c1fSDave Martin * 75894b07c1fSDave Martin * add_all: if true, lays out the biggest possible signal frame for 75994b07c1fSDave Martin * this task; otherwise, generates a layout for the current state 76094b07c1fSDave Martin * of the task. 76194b07c1fSDave Martin */ 76294b07c1fSDave Martin static int setup_sigframe_layout(struct rt_sigframe_user_layout *user, 76394b07c1fSDave Martin bool add_all) 764bb4891a6SDave Martin { 765bb4322f7SDave Martin int err; 766bb4322f7SDave Martin 7670a32c88dSDavid Engraf if (system_supports_fpsimd()) { 768bb4322f7SDave Martin err = sigframe_alloc(user, &user->fpsimd_offset, 769bb4322f7SDave Martin sizeof(struct fpsimd_context)); 770bb4322f7SDave Martin if (err) 771bb4322f7SDave Martin return err; 7720a32c88dSDavid Engraf } 773bb4891a6SDave Martin 774bb4891a6SDave Martin /* fault information, if valid */ 77594b07c1fSDave Martin if (add_all || current->thread.fault_code) { 776bb4322f7SDave Martin err = sigframe_alloc(user, &user->esr_offset, 777bb4322f7SDave Martin sizeof(struct esr_context)); 778bb4322f7SDave Martin if (err) 779bb4322f7SDave Martin return err; 780bb4891a6SDave Martin } 781bb4891a6SDave Martin 7828cd969d2SDave Martin if (system_supports_sve()) { 7838cd969d2SDave Martin unsigned int vq = 0; 7848cd969d2SDave Martin 78585ed24daSMark Brown if (add_all || test_thread_flag(TIF_SVE) || 78685ed24daSMark Brown thread_sm_enabled(¤t->thread)) { 78785ed24daSMark Brown int vl = max(sve_max_vl(), sme_max_vl()); 78894b07c1fSDave Martin 78994b07c1fSDave Martin if (!add_all) 79085ed24daSMark Brown vl = thread_get_cur_vl(¤t->thread); 79194b07c1fSDave Martin 79294b07c1fSDave Martin vq = sve_vq_from_vl(vl); 79394b07c1fSDave Martin } 7948cd969d2SDave Martin 7958cd969d2SDave Martin err = sigframe_alloc(user, &user->sve_offset, 7968cd969d2SDave Martin SVE_SIG_CONTEXT_SIZE(vq)); 7978cd969d2SDave Martin if (err) 7988cd969d2SDave Martin return err; 7998cd969d2SDave Martin } 8008cd969d2SDave Martin 80139782210SMark Brown if (system_supports_sme()) { 80239782210SMark Brown unsigned int vl; 80339782210SMark Brown unsigned int vq = 0; 80439782210SMark Brown 80539782210SMark Brown if (add_all) 80639782210SMark Brown vl = sme_max_vl(); 80739782210SMark Brown else 80839782210SMark Brown vl = task_get_sme_vl(current); 80939782210SMark Brown 810*39e54499SMark Brown err = sigframe_alloc(user, &user->tpidr2_offset, 811*39e54499SMark Brown sizeof(struct tpidr2_context)); 812*39e54499SMark Brown if (err) 813*39e54499SMark Brown return err; 814*39e54499SMark Brown 81539782210SMark Brown if (thread_za_enabled(¤t->thread)) 81639782210SMark Brown vq = sve_vq_from_vl(vl); 81739782210SMark Brown 81839782210SMark Brown err = sigframe_alloc(user, &user->za_offset, 81939782210SMark Brown ZA_SIG_CONTEXT_SIZE(vq)); 82039782210SMark Brown if (err) 82139782210SMark Brown return err; 82239782210SMark Brown } 82339782210SMark Brown 82433f08261SDave Martin return sigframe_alloc_end(user); 825bb4891a6SDave Martin } 826bb4891a6SDave Martin 82720987de3SDave Martin static int setup_sigframe(struct rt_sigframe_user_layout *user, 8282c020ed8SCatalin Marinas struct pt_regs *regs, sigset_t *set) 8292c020ed8SCatalin Marinas { 8302c020ed8SCatalin Marinas int i, err = 0; 83120987de3SDave Martin struct rt_sigframe __user *sf = user->sigframe; 8322c020ed8SCatalin Marinas 833304ef4e8SWill Deacon /* set up the stack frame for unwinding */ 83420987de3SDave Martin __put_user_error(regs->regs[29], &user->next_frame->fp, err); 83520987de3SDave Martin __put_user_error(regs->regs[30], &user->next_frame->lr, err); 836304ef4e8SWill Deacon 8372c020ed8SCatalin Marinas for (i = 0; i < 31; i++) 8382c020ed8SCatalin Marinas __put_user_error(regs->regs[i], &sf->uc.uc_mcontext.regs[i], 8392c020ed8SCatalin Marinas err); 8402c020ed8SCatalin Marinas __put_user_error(regs->sp, &sf->uc.uc_mcontext.sp, err); 8412c020ed8SCatalin Marinas __put_user_error(regs->pc, &sf->uc.uc_mcontext.pc, err); 8422c020ed8SCatalin Marinas __put_user_error(regs->pstate, &sf->uc.uc_mcontext.pstate, err); 8432c020ed8SCatalin Marinas 8442c020ed8SCatalin Marinas __put_user_error(current->thread.fault_address, &sf->uc.uc_mcontext.fault_address, err); 8452c020ed8SCatalin Marinas 8462c020ed8SCatalin Marinas err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set)); 8472c020ed8SCatalin Marinas 8486d502b6bSSuzuki K Poulose if (err == 0 && system_supports_fpsimd()) { 849bb4891a6SDave Martin struct fpsimd_context __user *fpsimd_ctx = 850bb4891a6SDave Martin apply_user_offset(user, user->fpsimd_offset); 8510e0276d1SCatalin Marinas err |= preserve_fpsimd_context(fpsimd_ctx); 8520e0276d1SCatalin Marinas } 8532c020ed8SCatalin Marinas 85415af1942SCatalin Marinas /* fault information, if valid */ 855bb4891a6SDave Martin if (err == 0 && user->esr_offset) { 856bb4891a6SDave Martin struct esr_context __user *esr_ctx = 857bb4891a6SDave Martin apply_user_offset(user, user->esr_offset); 858bb4891a6SDave Martin 85915af1942SCatalin Marinas __put_user_error(ESR_MAGIC, &esr_ctx->head.magic, err); 86015af1942SCatalin Marinas __put_user_error(sizeof(*esr_ctx), &esr_ctx->head.size, err); 86115af1942SCatalin Marinas __put_user_error(current->thread.fault_code, &esr_ctx->esr, err); 86215af1942SCatalin Marinas } 86315af1942SCatalin Marinas 86485ed24daSMark Brown /* Scalable Vector Extension state (including streaming), if present */ 86585ed24daSMark Brown if ((system_supports_sve() || system_supports_sme()) && 86685ed24daSMark Brown err == 0 && user->sve_offset) { 8678cd969d2SDave Martin struct sve_context __user *sve_ctx = 8688cd969d2SDave Martin apply_user_offset(user, user->sve_offset); 8698cd969d2SDave Martin err |= preserve_sve_context(sve_ctx); 8708cd969d2SDave Martin } 8718cd969d2SDave Martin 872*39e54499SMark Brown /* TPIDR2 if supported */ 873*39e54499SMark Brown if (system_supports_sme() && err == 0) { 874*39e54499SMark Brown struct tpidr2_context __user *tpidr2_ctx = 875*39e54499SMark Brown apply_user_offset(user, user->tpidr2_offset); 876*39e54499SMark Brown err |= preserve_tpidr2_context(tpidr2_ctx); 877*39e54499SMark Brown } 878*39e54499SMark Brown 87939782210SMark Brown /* ZA state if present */ 88039782210SMark Brown if (system_supports_sme() && err == 0 && user->za_offset) { 88139782210SMark Brown struct za_context __user *za_ctx = 88239782210SMark Brown apply_user_offset(user, user->za_offset); 88339782210SMark Brown err |= preserve_za_context(za_ctx); 88439782210SMark Brown } 88539782210SMark Brown 88633f08261SDave Martin if (err == 0 && user->extra_offset) { 88733f08261SDave Martin char __user *sfp = (char __user *)user->sigframe; 88833f08261SDave Martin char __user *userp = 88933f08261SDave Martin apply_user_offset(user, user->extra_offset); 89033f08261SDave Martin 89133f08261SDave Martin struct extra_context __user *extra; 89233f08261SDave Martin struct _aarch64_ctx __user *end; 89333f08261SDave Martin u64 extra_datap; 89433f08261SDave Martin u32 extra_size; 89533f08261SDave Martin 89633f08261SDave Martin extra = (struct extra_context __user *)userp; 89733f08261SDave Martin userp += EXTRA_CONTEXT_SIZE; 89833f08261SDave Martin 89933f08261SDave Martin end = (struct _aarch64_ctx __user *)userp; 90033f08261SDave Martin userp += TERMINATOR_SIZE; 90133f08261SDave Martin 90233f08261SDave Martin /* 90333f08261SDave Martin * extra_datap is just written to the signal frame. 90433f08261SDave Martin * The value gets cast back to a void __user * 90533f08261SDave Martin * during sigreturn. 90633f08261SDave Martin */ 90733f08261SDave Martin extra_datap = (__force u64)userp; 90833f08261SDave Martin extra_size = sfp + round_up(user->size, 16) - userp; 90933f08261SDave Martin 91033f08261SDave Martin __put_user_error(EXTRA_MAGIC, &extra->head.magic, err); 91133f08261SDave Martin __put_user_error(EXTRA_CONTEXT_SIZE, &extra->head.size, err); 91233f08261SDave Martin __put_user_error(extra_datap, &extra->datap, err); 91333f08261SDave Martin __put_user_error(extra_size, &extra->size, err); 91433f08261SDave Martin 91533f08261SDave Martin /* Add the terminator */ 91633f08261SDave Martin __put_user_error(0, &end->magic, err); 91733f08261SDave Martin __put_user_error(0, &end->size, err); 91833f08261SDave Martin } 91933f08261SDave Martin 9202c020ed8SCatalin Marinas /* set the "end" magic */ 921bb4891a6SDave Martin if (err == 0) { 922bb4891a6SDave Martin struct _aarch64_ctx __user *end = 923bb4891a6SDave Martin apply_user_offset(user, user->end_offset); 924bb4891a6SDave Martin 9250e0276d1SCatalin Marinas __put_user_error(0, &end->magic, err); 9260e0276d1SCatalin Marinas __put_user_error(0, &end->size, err); 927bb4891a6SDave Martin } 9282c020ed8SCatalin Marinas 9292c020ed8SCatalin Marinas return err; 9302c020ed8SCatalin Marinas } 9312c020ed8SCatalin Marinas 93220987de3SDave Martin static int get_sigframe(struct rt_sigframe_user_layout *user, 93320987de3SDave Martin struct ksignal *ksig, struct pt_regs *regs) 9342c020ed8SCatalin Marinas { 9352c020ed8SCatalin Marinas unsigned long sp, sp_top; 936bb4891a6SDave Martin int err; 937bb4891a6SDave Martin 938bb4891a6SDave Martin init_user_layout(user); 93994b07c1fSDave Martin err = setup_sigframe_layout(user, false); 940bb4891a6SDave Martin if (err) 941bb4891a6SDave Martin return err; 9422c020ed8SCatalin Marinas 94338a7be3cSRichard Weinberger sp = sp_top = sigsp(regs->sp, ksig); 9442c020ed8SCatalin Marinas 94520987de3SDave Martin sp = round_down(sp - sizeof(struct frame_record), 16); 94620987de3SDave Martin user->next_frame = (struct frame_record __user *)sp; 94720987de3SDave Martin 948bb4891a6SDave Martin sp = round_down(sp, 16) - sigframe_size(user); 94920987de3SDave Martin user->sigframe = (struct rt_sigframe __user *)sp; 9502c020ed8SCatalin Marinas 9512c020ed8SCatalin Marinas /* 9522c020ed8SCatalin Marinas * Check that we can actually write to the signal frame. 9532c020ed8SCatalin Marinas */ 95496d4f267SLinus Torvalds if (!access_ok(user->sigframe, sp_top - sp)) 95520987de3SDave Martin return -EFAULT; 9562c020ed8SCatalin Marinas 95720987de3SDave Martin return 0; 9582c020ed8SCatalin Marinas } 9592c020ed8SCatalin Marinas 960304ef4e8SWill Deacon static void setup_return(struct pt_regs *regs, struct k_sigaction *ka, 96120987de3SDave Martin struct rt_sigframe_user_layout *user, int usig) 9622c020ed8SCatalin Marinas { 9632c020ed8SCatalin Marinas __sigrestore_t sigtramp; 9642c020ed8SCatalin Marinas 9652c020ed8SCatalin Marinas regs->regs[0] = usig; 96620987de3SDave Martin regs->sp = (unsigned long)user->sigframe; 96720987de3SDave Martin regs->regs[29] = (unsigned long)&user->next_frame->fp; 9682c020ed8SCatalin Marinas regs->pc = (unsigned long)ka->sa.sa_handler; 9692c020ed8SCatalin Marinas 9708ef8f360SDave Martin /* 9718ef8f360SDave Martin * Signal delivery is a (wacky) indirect function call in 9728ef8f360SDave Martin * userspace, so simulate the same setting of BTYPE as a BLR 9738ef8f360SDave Martin * <register containing the signal handler entry point>. 9748ef8f360SDave Martin * Signal delivery to a location in a PROT_BTI guarded page 9758ef8f360SDave Martin * that is not a function entry point will now trigger a 9768ef8f360SDave Martin * SIGILL in userspace. 9778ef8f360SDave Martin * 9788ef8f360SDave Martin * If the signal handler entry point is not in a PROT_BTI 9798ef8f360SDave Martin * guarded page, this is harmless. 9808ef8f360SDave Martin */ 9818ef8f360SDave Martin if (system_supports_bti()) { 9828ef8f360SDave Martin regs->pstate &= ~PSR_BTYPE_MASK; 9838ef8f360SDave Martin regs->pstate |= PSR_BTYPE_C; 9848ef8f360SDave Martin } 9858ef8f360SDave Martin 986637ec831SVincenzo Frascino /* TCO (Tag Check Override) always cleared for signal handlers */ 987637ec831SVincenzo Frascino regs->pstate &= ~PSR_TCO_BIT; 988637ec831SVincenzo Frascino 98940a8e87bSMark Brown /* Signal handlers are invoked with ZA and streaming mode disabled */ 99040a8e87bSMark Brown if (system_supports_sme()) { 991ea64baacSMark Brown /* 992ea64baacSMark Brown * If we were in streaming mode the saved register 993ea64baacSMark Brown * state was SVE but we will exit SM and use the 994ea64baacSMark Brown * FPSIMD register state - flush the saved FPSIMD 995ea64baacSMark Brown * register state in case it gets loaded. 996ea64baacSMark Brown */ 997baa85152SMark Brown if (current->thread.svcr & SVCR_SM_MASK) { 998ea64baacSMark Brown memset(¤t->thread.uw.fpsimd_state, 0, 999ea64baacSMark Brown sizeof(current->thread.uw.fpsimd_state)); 1000baa85152SMark Brown current->thread.fp_type = FP_STATE_FPSIMD; 1001baa85152SMark Brown } 1002ea64baacSMark Brown 1003ec0067a6SMark Brown current->thread.svcr &= ~(SVCR_ZA_MASK | 1004ec0067a6SMark Brown SVCR_SM_MASK); 100540a8e87bSMark Brown sme_smstop(); 100640a8e87bSMark Brown } 100740a8e87bSMark Brown 10082c020ed8SCatalin Marinas if (ka->sa.sa_flags & SA_RESTORER) 10092c020ed8SCatalin Marinas sigtramp = ka->sa.sa_restorer; 10102c020ed8SCatalin Marinas else 10112c020ed8SCatalin Marinas sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp); 10122c020ed8SCatalin Marinas 10132c020ed8SCatalin Marinas regs->regs[30] = (unsigned long)sigtramp; 10142c020ed8SCatalin Marinas } 10152c020ed8SCatalin Marinas 101600554fa4SRichard Weinberger static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set, 101700554fa4SRichard Weinberger struct pt_regs *regs) 10182c020ed8SCatalin Marinas { 101920987de3SDave Martin struct rt_sigframe_user_layout user; 10202c020ed8SCatalin Marinas struct rt_sigframe __user *frame; 10212c020ed8SCatalin Marinas int err = 0; 10222c020ed8SCatalin Marinas 10238cd969d2SDave Martin fpsimd_signal_preserve_current_state(); 10248cd969d2SDave Martin 102520987de3SDave Martin if (get_sigframe(&user, ksig, regs)) 10262c020ed8SCatalin Marinas return 1; 10272c020ed8SCatalin Marinas 102820987de3SDave Martin frame = user.sigframe; 102920987de3SDave Martin 10302c020ed8SCatalin Marinas __put_user_error(0, &frame->uc.uc_flags, err); 10312c020ed8SCatalin Marinas __put_user_error(NULL, &frame->uc.uc_link, err); 10322c020ed8SCatalin Marinas 1033207bdae4SAl Viro err |= __save_altstack(&frame->uc.uc_stack, regs->sp); 103420987de3SDave Martin err |= setup_sigframe(&user, regs, set); 1035304ef4e8SWill Deacon if (err == 0) { 103620987de3SDave Martin setup_return(regs, &ksig->ka, &user, usig); 103700554fa4SRichard Weinberger if (ksig->ka.sa.sa_flags & SA_SIGINFO) { 103800554fa4SRichard Weinberger err |= copy_siginfo_to_user(&frame->info, &ksig->info); 10392c020ed8SCatalin Marinas regs->regs[1] = (unsigned long)&frame->info; 10402c020ed8SCatalin Marinas regs->regs[2] = (unsigned long)&frame->uc; 10412c020ed8SCatalin Marinas } 1042304ef4e8SWill Deacon } 10432c020ed8SCatalin Marinas 10442c020ed8SCatalin Marinas return err; 10452c020ed8SCatalin Marinas } 10462c020ed8SCatalin Marinas 10472c020ed8SCatalin Marinas static void setup_restart_syscall(struct pt_regs *regs) 10482c020ed8SCatalin Marinas { 10492c020ed8SCatalin Marinas if (is_compat_task()) 10502c020ed8SCatalin Marinas compat_setup_restart_syscall(regs); 10512c020ed8SCatalin Marinas else 10522c020ed8SCatalin Marinas regs->regs[8] = __NR_restart_syscall; 10532c020ed8SCatalin Marinas } 10542c020ed8SCatalin Marinas 10552c020ed8SCatalin Marinas /* 10562c020ed8SCatalin Marinas * OK, we're invoking a handler 10572c020ed8SCatalin Marinas */ 105800554fa4SRichard Weinberger static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) 10592c020ed8SCatalin Marinas { 10602c020ed8SCatalin Marinas sigset_t *oldset = sigmask_to_save(); 106100554fa4SRichard Weinberger int usig = ksig->sig; 10622c020ed8SCatalin Marinas int ret; 10632c020ed8SCatalin Marinas 1064409d5db4SWill Deacon rseq_signal_deliver(ksig, regs); 1065409d5db4SWill Deacon 10662c020ed8SCatalin Marinas /* 10672c020ed8SCatalin Marinas * Set up the stack frame 10682c020ed8SCatalin Marinas */ 10692c020ed8SCatalin Marinas if (is_compat_task()) { 107000554fa4SRichard Weinberger if (ksig->ka.sa.sa_flags & SA_SIGINFO) 107100554fa4SRichard Weinberger ret = compat_setup_rt_frame(usig, ksig, oldset, regs); 10722c020ed8SCatalin Marinas else 107300554fa4SRichard Weinberger ret = compat_setup_frame(usig, ksig, oldset, regs); 10742c020ed8SCatalin Marinas } else { 107500554fa4SRichard Weinberger ret = setup_rt_frame(usig, ksig, oldset, regs); 10762c020ed8SCatalin Marinas } 10772c020ed8SCatalin Marinas 10782c020ed8SCatalin Marinas /* 10792c020ed8SCatalin Marinas * Check that the resulting registers are actually sane. 10802c020ed8SCatalin Marinas */ 1081dbd4d7caSMark Rutland ret |= !valid_user_regs(®s->user_regs, current); 10822c020ed8SCatalin Marinas 1083ac2081cdSWill Deacon /* Step into the signal handler if we are stepping */ 1084ac2081cdSWill Deacon signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP)); 10852c020ed8SCatalin Marinas } 10862c020ed8SCatalin Marinas 10872c020ed8SCatalin Marinas /* 10882c020ed8SCatalin Marinas * Note that 'init' is a special process: it doesn't get signals it doesn't 10892c020ed8SCatalin Marinas * want to handle. Thus you cannot kill init even with a SIGKILL even by 10902c020ed8SCatalin Marinas * mistake. 10912c020ed8SCatalin Marinas * 10922c020ed8SCatalin Marinas * Note that we go through the signals twice: once to check the signals that 10932c020ed8SCatalin Marinas * the kernel can handle, and then we build all the user-level signal handling 10942c020ed8SCatalin Marinas * stack-frames in one go after that. 10952c020ed8SCatalin Marinas */ 10962c020ed8SCatalin Marinas static void do_signal(struct pt_regs *regs) 10972c020ed8SCatalin Marinas { 10982c020ed8SCatalin Marinas unsigned long continue_addr = 0, restart_addr = 0; 109900554fa4SRichard Weinberger int retval = 0; 110000554fa4SRichard Weinberger struct ksignal ksig; 11010fe42512SDave Martin bool syscall = in_syscall(regs); 11022c020ed8SCatalin Marinas 11032c020ed8SCatalin Marinas /* 11042c020ed8SCatalin Marinas * If we were from a system call, check for system call restarting... 11052c020ed8SCatalin Marinas */ 11060fe42512SDave Martin if (syscall) { 11072c020ed8SCatalin Marinas continue_addr = regs->pc; 11082c020ed8SCatalin Marinas restart_addr = continue_addr - (compat_thumb_mode(regs) ? 2 : 4); 11092c020ed8SCatalin Marinas retval = regs->regs[0]; 11102c020ed8SCatalin Marinas 11112c020ed8SCatalin Marinas /* 11122c020ed8SCatalin Marinas * Avoid additional syscall restarting via ret_to_user. 11132c020ed8SCatalin Marinas */ 111417c28958SDave Martin forget_syscall(regs); 11152c020ed8SCatalin Marinas 11162c020ed8SCatalin Marinas /* 11172c020ed8SCatalin Marinas * Prepare for system call restart. We do this here so that a 11182c020ed8SCatalin Marinas * debugger will see the already changed PC. 11192c020ed8SCatalin Marinas */ 11202c020ed8SCatalin Marinas switch (retval) { 11212c020ed8SCatalin Marinas case -ERESTARTNOHAND: 11222c020ed8SCatalin Marinas case -ERESTARTSYS: 11232c020ed8SCatalin Marinas case -ERESTARTNOINTR: 11242c020ed8SCatalin Marinas case -ERESTART_RESTARTBLOCK: 11252c020ed8SCatalin Marinas regs->regs[0] = regs->orig_x0; 11262c020ed8SCatalin Marinas regs->pc = restart_addr; 11272c020ed8SCatalin Marinas break; 11282c020ed8SCatalin Marinas } 11292c020ed8SCatalin Marinas } 11302c020ed8SCatalin Marinas 11312c020ed8SCatalin Marinas /* 11322c020ed8SCatalin Marinas * Get the signal to deliver. When running under ptrace, at this point 11332c020ed8SCatalin Marinas * the debugger may change all of our registers. 11342c020ed8SCatalin Marinas */ 113500554fa4SRichard Weinberger if (get_signal(&ksig)) { 11362c020ed8SCatalin Marinas /* 11372c020ed8SCatalin Marinas * Depending on the signal settings, we may need to revert the 11382c020ed8SCatalin Marinas * decision to restart the system call, but skip this if a 11392c020ed8SCatalin Marinas * debugger has chosen to restart at a different PC. 11402c020ed8SCatalin Marinas */ 11412c020ed8SCatalin Marinas if (regs->pc == restart_addr && 11422c020ed8SCatalin Marinas (retval == -ERESTARTNOHAND || 11432c020ed8SCatalin Marinas retval == -ERESTART_RESTARTBLOCK || 11442c020ed8SCatalin Marinas (retval == -ERESTARTSYS && 114500554fa4SRichard Weinberger !(ksig.ka.sa.sa_flags & SA_RESTART)))) { 1146e30e8d46SMark Rutland syscall_set_return_value(current, regs, -EINTR, 0); 11472c020ed8SCatalin Marinas regs->pc = continue_addr; 11482c020ed8SCatalin Marinas } 11492c020ed8SCatalin Marinas 115000554fa4SRichard Weinberger handle_signal(&ksig, regs); 11512c020ed8SCatalin Marinas return; 11522c020ed8SCatalin Marinas } 11532c020ed8SCatalin Marinas 11542c020ed8SCatalin Marinas /* 11552c020ed8SCatalin Marinas * Handle restarting a different system call. As above, if a debugger 11562c020ed8SCatalin Marinas * has chosen to restart at a different PC, ignore the restart. 11572c020ed8SCatalin Marinas */ 11580fe42512SDave Martin if (syscall && regs->pc == restart_addr) { 11592c020ed8SCatalin Marinas if (retval == -ERESTART_RESTARTBLOCK) 11602c020ed8SCatalin Marinas setup_restart_syscall(regs); 11612c020ed8SCatalin Marinas user_rewind_single_step(current); 11622c020ed8SCatalin Marinas } 11632c020ed8SCatalin Marinas 11642c020ed8SCatalin Marinas restore_saved_sigmask(); 11652c020ed8SCatalin Marinas } 11662c020ed8SCatalin Marinas 11674d1c2ee2SMark Rutland void do_notify_resume(struct pt_regs *regs, unsigned long thread_flags) 11682c020ed8SCatalin Marinas { 1169a2048e34SThomas Garnier do { 1170421dd6faSChris Metcalf if (thread_flags & _TIF_NEED_RESCHED) { 11718d66772eSJames Morse /* Unmask Debug and SError for the next task */ 11728d66772eSJames Morse local_daif_restore(DAIF_PROCCTX_NOIRQ); 11738d66772eSJames Morse 1174421dd6faSChris Metcalf schedule(); 1175421dd6faSChris Metcalf } else { 11768d66772eSJames Morse local_daif_restore(DAIF_PROCCTX); 1177421dd6faSChris Metcalf 11789842ceaeSPratyush Anand if (thread_flags & _TIF_UPROBE) 11799842ceaeSPratyush Anand uprobe_notify_resume(regs); 11809842ceaeSPratyush Anand 1181637ec831SVincenzo Frascino if (thread_flags & _TIF_MTE_ASYNC_FAULT) { 1182637ec831SVincenzo Frascino clear_thread_flag(TIF_MTE_ASYNC_FAULT); 1183637ec831SVincenzo Frascino send_sig_fault(SIGSEGV, SEGV_MTEAERR, 1184637ec831SVincenzo Frascino (void __user *)NULL, current); 1185637ec831SVincenzo Frascino } 1186637ec831SVincenzo Frascino 1187192caabdSJens Axboe if (thread_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL)) 11882c020ed8SCatalin Marinas do_signal(regs); 11892c020ed8SCatalin Marinas 1190a68de80fSSean Christopherson if (thread_flags & _TIF_NOTIFY_RESUME) 119103248addSEric W. Biederman resume_user_mode_work(regs); 1192005f78cdSArd Biesheuvel 1193005f78cdSArd Biesheuvel if (thread_flags & _TIF_FOREIGN_FPSTATE) 1194005f78cdSArd Biesheuvel fpsimd_restore_current_state(); 1195421dd6faSChris Metcalf } 1196005f78cdSArd Biesheuvel 11978d66772eSJames Morse local_daif_mask(); 1198342b3808SMark Rutland thread_flags = read_thread_flags(); 1199421dd6faSChris Metcalf } while (thread_flags & _TIF_WORK_MASK); 12002c020ed8SCatalin Marinas } 120194b07c1fSDave Martin 120294b07c1fSDave Martin unsigned long __ro_after_init signal_minsigstksz; 120394b07c1fSDave Martin 120494b07c1fSDave Martin /* 120594b07c1fSDave Martin * Determine the stack space required for guaranteed signal devliery. 120694b07c1fSDave Martin * This function is used to populate AT_MINSIGSTKSZ at process startup. 120794b07c1fSDave Martin * cpufeatures setup is assumed to be complete. 120894b07c1fSDave Martin */ 120994b07c1fSDave Martin void __init minsigstksz_setup(void) 121094b07c1fSDave Martin { 121194b07c1fSDave Martin struct rt_sigframe_user_layout user; 121294b07c1fSDave Martin 121394b07c1fSDave Martin init_user_layout(&user); 121494b07c1fSDave Martin 121594b07c1fSDave Martin /* 121694b07c1fSDave Martin * If this fails, SIGFRAME_MAXSZ needs to be enlarged. It won't 121794b07c1fSDave Martin * be big enough, but it's our best guess: 121894b07c1fSDave Martin */ 121994b07c1fSDave Martin if (WARN_ON(setup_sigframe_layout(&user, true))) 122094b07c1fSDave Martin return; 122194b07c1fSDave Martin 122294b07c1fSDave Martin signal_minsigstksz = sigframe_size(&user) + 122394b07c1fSDave Martin round_up(sizeof(struct frame_record), 16) + 122494b07c1fSDave Martin 16; /* max alignment padding */ 122594b07c1fSDave Martin } 1226726e337bSMarco Elver 1227726e337bSMarco Elver /* 1228726e337bSMarco Elver * Compile-time assertions for siginfo_t offsets. Check NSIG* as well, as 1229726e337bSMarco Elver * changes likely come with new fields that should be added below. 1230726e337bSMarco Elver */ 1231726e337bSMarco Elver static_assert(NSIGILL == 11); 1232726e337bSMarco Elver static_assert(NSIGFPE == 15); 1233726e337bSMarco Elver static_assert(NSIGSEGV == 9); 1234726e337bSMarco Elver static_assert(NSIGBUS == 5); 1235726e337bSMarco Elver static_assert(NSIGTRAP == 6); 1236726e337bSMarco Elver static_assert(NSIGCHLD == 6); 1237726e337bSMarco Elver static_assert(NSIGSYS == 2); 123850ae8130SEric W. Biederman static_assert(sizeof(siginfo_t) == 128); 123950ae8130SEric W. Biederman static_assert(__alignof__(siginfo_t) == 8); 1240726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_signo) == 0x00); 1241726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_errno) == 0x04); 1242726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_code) == 0x08); 1243726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_pid) == 0x10); 1244726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_uid) == 0x14); 1245726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_tid) == 0x10); 1246726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_overrun) == 0x14); 1247726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_status) == 0x18); 1248726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_utime) == 0x20); 1249726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_stime) == 0x28); 1250726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_value) == 0x18); 1251726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_int) == 0x18); 1252726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_ptr) == 0x18); 1253726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_addr) == 0x10); 1254726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_addr_lsb) == 0x18); 1255726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_lower) == 0x20); 1256726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_upper) == 0x28); 1257726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_pkey) == 0x20); 1258726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_perf_data) == 0x18); 1259726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_perf_type) == 0x20); 126078ed93d7SMarco Elver static_assert(offsetof(siginfo_t, si_perf_flags) == 0x24); 1261726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_band) == 0x10); 1262726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_fd) == 0x18); 1263726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_call_addr) == 0x10); 1264726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_syscall) == 0x18); 1265726e337bSMarco Elver static_assert(offsetof(siginfo_t, si_arch) == 0x1c); 1266