1/* $OpenBSD: sig_machdep.c,v 1.10 2022/03/22 06:49:25 miod Exp $ */ 2 3/* 4 * Copyright (c) 1990 The Regents of the University of California. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * William Jolitz and Don Ahn. 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 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 */ 39/* 40 * Copyright (c) 2001 Opsycon AB (www.opsycon.se) 41 * 42 * Redistribution and use in source and binary forms, with or without 43 * modification, are permitted provided that the following conditions 44 * are met: 45 * 1. Redistributions of source code must retain the above copyright 46 * notice, this list of conditions and the following disclaimer. 47 * 2. Redistributions in binary form must reproduce the above copyright 48 * notice, this list of conditions and the following disclaimer in the 49 * documentation and/or other materials provided with the distribution. 50 * 51 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 52 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 53 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 54 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 55 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 61 * SUCH DAMAGE. 62 * 63 */ 64 65#include <sys/param.h> 66 67#include <sys/mount.h> /* XXX only needed by syscallargs.h */ 68#include <sys/proc.h> 69#include <sys/signal.h> 70#include <sys/signalvar.h> 71#include <sys/syscallargs.h> 72#include <sys/systm.h> 73#include <sys/user.h> 74 75#include <machine/cpu.h> 76#include <machine/frame.h> 77#include <machine/pcb.h> 78 79#include <uvm/uvm_extern.h> 80 81static __inline struct trapframe * 82process_frame(struct proc *p) 83{ 84 return p->p_addr->u_pcb.pcb_tf; 85} 86 87/* 88 * Send an interrupt to process. 89 * 90 * Stack is set up to allow sigcode to call routine, followed by 91 * syscall to sigreturn routine below. After sigreturn resets the 92 * signal mask, the stack, and the frame pointer, it returns to the 93 * user specified pc. 94 */ 95int 96sendsig(sig_t catcher, int sig, sigset_t mask, const siginfo_t *ksip, 97 int info, int onstack) 98{ 99 struct proc *p = curproc; 100 struct trapframe *tf; 101 struct sigframe *fp, frame; 102 struct fpreg *fpreg; 103 siginfo_t *sip = NULL; 104 int i; 105 106 tf = process_frame(p); 107 108 /* Allocate space for the signal handler context. */ 109 if ((p->p_sigstk.ss_flags & SS_DISABLE) == 0 && 110 !sigonstack(tf->tf_sp) && onstack) 111 fp = (struct sigframe *) 112 trunc_page((vaddr_t)p->p_sigstk.ss_sp + p->p_sigstk.ss_size); 113 else 114 fp = (struct sigframe *)tf->tf_sp; 115 116 /* make room on the stack */ 117 fp--; 118 119 /* make the stack aligned */ 120 fp = (struct sigframe *)STACKALIGN(fp); 121 122 /* Save FPU state to PCB if necessary. */ 123 if (p->p_addr->u_pcb.pcb_flags & PCB_FPU) 124 fpu_save(p, tf); 125 126 /* Build stack frame for signal trampoline. */ 127 bzero(&frame, sizeof(frame)); 128 frame.sf_signum = sig; 129 130 /* Save register context. */ 131 for (i=0; i < 7; i++) 132 frame.sf_sc.sc_t[i] = tf->tf_t[i]; 133 for (i=0; i < 12; i++) 134 frame.sf_sc.sc_s[i] = tf->tf_s[i]; 135 for (i=0; i < 8; i++) 136 frame.sf_sc.sc_a[i] = tf->tf_a[i]; 137 frame.sf_sc.sc_ra = tf->tf_ra; 138 frame.sf_sc.sc_sp = tf->tf_sp; 139 frame.sf_sc.sc_tp = tf->tf_tp; 140 frame.sf_sc.sc_sepc = tf->tf_sepc; 141 142 /* Save signal mask. */ 143 frame.sf_sc.sc_mask = mask; 144 145 /* Copy the saved FPU state into the frame if necessary. */ 146 if (p->p_addr->u_pcb.pcb_flags & PCB_FPU) { 147 fpreg = &p->p_addr->u_pcb.pcb_fpstate; 148 for (i = 0; i < 32; i++) 149 frame.sf_sc.sc_f[i] = fpreg->fp_f[i]; 150 frame.sf_sc.sc_fcsr = fpreg->fp_fcsr; 151 } 152 153 if (info) { 154 sip = &fp->sf_si; 155 frame.sf_si = *ksip; 156 } 157 158 frame.sf_sc.sc_cookie = (long)&fp->sf_sc ^ p->p_p->ps_sigcookie; 159 if (copyout(&frame, fp, sizeof(frame)) != 0) { 160 /* 161 * Process has trashed its stack; alert caller which 162 * will give it an illegal instruction to halt it in 163 * its tracks. 164 */ 165 return 1; 166 } 167 168 169 /* 170 * Build context to run handler in. We invoke the handler 171 * directly, only returning via the trampoline. 172 */ 173 tf->tf_a[0] = sig; 174 tf->tf_a[1] = (register_t)sip; 175 tf->tf_a[2] = (register_t)&fp->sf_sc; 176 tf->tf_ra = p->p_p->ps_sigcode; 177 tf->tf_sp = (register_t)fp; 178 179 tf->tf_sepc = (register_t)catcher; 180 181 return 0; 182} 183 184/* 185 * System call to cleanup state after a signal 186 * has been taken. Reset signal mask and 187 * stack state from context left by sendsig (above). 188 * Return to previous pc and psl as specified by 189 * context left by sendsig. Check carefully to 190 * make sure that the user has not modified the 191 * psr to gain improper privileges or to cause 192 * a machine fault. 193 */ 194 195int 196sys_sigreturn(struct proc *p, void *v, register_t *retval) 197{ 198 199 struct sys_sigreturn_args /* { 200 syscallarg(struct sigcontext *) sigcntxp; 201 } */ *uap = v; 202 struct sigcontext ksc, *scp = SCARG(uap, sigcntxp); 203 struct trapframe *tf; 204 struct fpreg *fpreg; 205 int i; 206 207 if (PROC_PC(p) != p->p_p->ps_sigcoderet) { 208 sigexit(p, SIGILL); 209 return (EPERM); 210 } 211 212 if (copyin(scp, &ksc, sizeof(*scp)) != 0) 213 return (EFAULT); 214 215 if (ksc.sc_cookie != ((long)scp ^ p->p_p->ps_sigcookie)) { 216 sigexit(p, SIGILL); 217 return (EFAULT); 218 } 219 220 /* Prevent reuse of the sigcontext cookie */ 221 ksc.sc_cookie = 0; 222 (void)copyout(&ksc.sc_cookie, (caddr_t)scp + 223 offsetof(struct sigcontext, sc_cookie), sizeof (ksc.sc_cookie)); 224 225 /* Restore register context. */ 226 tf = process_frame(p); 227 for (i=0; i < 7; i++) 228 tf->tf_t[i] = ksc.sc_t[i]; 229 for (i=0; i < 12; i++) 230 tf->tf_s[i] = ksc.sc_s[i]; 231 for (i=0; i < 8; i++) 232 tf->tf_a[i] = ksc.sc_a[i]; 233 tf->tf_ra = ksc.sc_ra; 234 tf->tf_sp = ksc.sc_sp; 235 tf->tf_tp = ksc.sc_tp; 236 tf->tf_sepc = ksc.sc_sepc; 237 238 /* Write saved FPU state back to PCB if necessary. */ 239 if (p->p_addr->u_pcb.pcb_flags & PCB_FPU) { 240 fpreg = &p->p_addr->u_pcb.pcb_fpstate; 241 for (i = 0; i < 32; i++) 242 fpreg->fp_f[i] = ksc.sc_f[i]; 243 fpreg->fp_fcsr = ksc.sc_fcsr; 244 245 /* drop FPU state */ 246 tf->tf_sstatus &= ~SSTATUS_FS_MASK; 247 tf->tf_sstatus |= SSTATUS_FS_OFF; 248 } 249 250 /* Restore signal mask. */ 251 p->p_sigmask = ksc.sc_mask & ~sigcantmask; 252 253 return (EJUSTRETURN); 254} 255