1 /* $NetBSD: sig_machdep.c,v 1.9 2024/04/14 12:51:16 skrll Exp $ */ 2 3 /*- 4 * Copyright (c) 2014 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Matt Thomas of 3am Software Foundry. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 34 __KERNEL_RCSID(1, "$NetBSD: sig_machdep.c,v 1.9 2024/04/14 12:51:16 skrll Exp $"); 35 36 #include <sys/param.h> 37 #include <sys/types.h> 38 #include <sys/cpu.h> 39 #include <sys/proc.h> 40 #include <sys/signalvar.h> 41 #include <sys/siginfo.h> 42 43 #include <aarch64/frame.h> 44 45 void 46 sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask) 47 { 48 struct lwp * const l = curlwp; 49 struct proc * const p = l->l_proc; 50 struct trapframe * const tf = lwp_trapframe(l); 51 stack_t * const ss = &l->l_sigstk; 52 const struct sigact_sigdesc * const sd = 53 &p->p_sigacts->sa_sigdesc[ksi->ksi_signo]; 54 55 const uintptr_t handler = (uintptr_t) sd->sd_sigact.sa_handler; 56 const bool onstack_p = (ss->ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 57 && (sd->sd_sigact.sa_flags & SA_ONSTACK) != 0; 58 59 vaddr_t sp; 60 61 /* 62 * The user stack isn't guaranteed to be aligned to 16 bytes. Align 63 * it before pushing anything onto it. 64 */ 65 sp = onstack_p ? ((vaddr_t)ss->ss_sp + ss->ss_size) : tf->tf_sp; 66 sp &= -16; 67 68 __CTASSERT(sizeof(ucontext_t) % 16 == 0); 69 sp -= sizeof(ucontext_t); 70 const vaddr_t ucp = sp; 71 72 sp -= roundup(sizeof(siginfo_t), 16); 73 const vaddr_t sip = sp; 74 75 ucontext_t uc; 76 memset(&uc, 0, sizeof(uc)); 77 uc.uc_flags = _UC_SIGMASK; 78 uc.uc_sigmask = *mask; 79 uc.uc_link = l->l_ctxlink; 80 uc.uc_flags |= (l->l_sigstk.ss_flags & SS_ONSTACK) 81 ? _UC_SETSTACK : _UC_CLRSTACK; 82 sendsig_reset(l, ksi->ksi_signo); 83 mutex_exit(p->p_lock); 84 cpu_getmcontext(l, &uc.uc_mcontext, &uc.uc_flags); 85 86 /* 87 * Copy the siginfo and ucontext onto the user's stack. 88 */ 89 int error = copyout(&ksi->ksi_info, (void *)sip, sizeof(ksi->ksi_info)); 90 if (error == 0) { 91 error = copyout(&uc, (void *)ucp, sizeof(uc)); 92 } 93 94 mutex_enter(p->p_lock); 95 96 if (error || sd->sd_vers != __SIGTRAMP_SIGINFO_VERSION) { 97 /* 98 * Thread has trashed its stack. Blow it away. 99 */ 100 if (error == 0) { 101 printf("pid %d.%d(%s): %p(sig %d): bad version %d\n", 102 p->p_pid, l->l_lid, p->p_comm, __func__, 103 ksi->ksi_signo, sd->sd_vers); 104 } 105 sigexit(l, SIGILL); 106 /* NOTREACHED */ 107 } 108 109 tf->tf_reg[0] = ksi->ksi_signo; 110 tf->tf_reg[1] = sip; 111 tf->tf_reg[2] = ucp; 112 tf->tf_reg[28] = ucp; /* put in a callee saved register */ 113 114 tf->tf_sp = sp; 115 tf->tf_lr = (uint64_t)sd->sd_tramp; 116 tf->tf_pc = handler; 117 118 /* 119 * Remember if we're now on the signal stack. 120 */ 121 if (onstack_p) 122 ss->ss_flags |= SS_ONSTACK; 123 } 124