1 /* $NetBSD: compat_16_machdep.c,v 1.4 2009/11/21 04:16:51 rmind Exp $ */ 2 3 /*- 4 * Copyright (c) 1996, 1997, 1998, 2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Copyright (c) 1992, 1993 35 * The Regents of the University of California. All rights reserved. 36 * 37 * This software was developed by the Computer Systems Engineering group 38 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 39 * contributed to Berkeley. 40 * 41 * All advertising materials mentioning features or use of this software 42 * must display the following acknowledgement: 43 * This product includes software developed by the University of 44 * California, Lawrence Berkeley Laboratory. 45 * 46 * Redistribution and use in source and binary forms, with or without 47 * modification, are permitted provided that the following conditions 48 * are met: 49 * 1. Redistributions of source code must retain the above copyright 50 * notice, this list of conditions and the following disclaimer. 51 * 2. Redistributions in binary form must reproduce the above copyright 52 * notice, this list of conditions and the following disclaimer in the 53 * documentation and/or other materials provided with the distribution. 54 * 3. Neither the name of the University nor the names of its contributors 55 * may be used to endorse or promote products derived from this software 56 * without specific prior written permission. 57 * 58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 68 * SUCH DAMAGE. 69 * 70 * @(#)machdep.c 8.6 (Berkeley) 1/14/94 71 */ 72 73 #include <sys/cdefs.h> 74 __KERNEL_RCSID(0, "$NetBSD: compat_16_machdep.c,v 1.4 2009/11/21 04:16:51 rmind Exp $"); 75 76 #include <sys/param.h> 77 #include <sys/signal.h> 78 #include <sys/signalvar.h> 79 #include <sys/proc.h> 80 #include <sys/systm.h> 81 #include <sys/kernel.h> 82 #include <sys/syscallargs.h> 83 84 #ifdef COMPAT_13 85 #include <compat/sys/signal.h> 86 #include <compat/sys/signalvar.h> 87 #endif 88 #include <machine/frame.h> 89 90 #ifdef COMPAT_13 91 #include <compat/sys/signal.h> 92 #include <compat/sys/signalvar.h> 93 #endif /* COMPAT_13 */ 94 95 struct sigframe_sigcontext { 96 int sf_signo; /* signal number */ 97 int sf_code; /* code */ 98 struct sigcontext *sf_scp; /* SunOS user addr of sigcontext */ 99 int sf_addr; /* SunOS compat, always 0 for now */ 100 struct sigcontext sf_sc; /* actual sigcontext */ 101 }; 102 103 #ifdef DEBUG 104 extern int sigdebug; 105 extern int sigpid; 106 #define SDB_FOLLOW 0x01 107 #define SDB_KSTACK 0x02 108 #define SDB_FPSTATE 0x04 109 #endif 110 111 void 112 sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask) 113 { 114 struct lwp *l = curlwp; 115 struct proc *p = l->l_proc; 116 struct sigacts *ps = p->p_sigacts; 117 struct sigframe_sigcontext *fp; 118 struct trapframe *tf; 119 int addr, onstack, oldsp, newsp, error; 120 struct sigframe_sigcontext sf; 121 int sig = ksi->ksi_signo; 122 u_long code = KSI_TRAPCODE(ksi); 123 sig_t catcher = SIGACTION(p, sig).sa_handler; 124 125 tf = l->l_md.md_tf; 126 oldsp = tf->tf_out[6]; 127 128 /* 129 * Compute new user stack addresses, subtract off 130 * one signal frame, and align. 131 */ 132 onstack = 133 (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && 134 (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; 135 136 if (onstack) 137 fp = (struct sigframe_sigcontext *) 138 ((char *)l->l_sigstk.ss_sp + 139 l->l_sigstk.ss_size); 140 else 141 fp = (struct sigframe_sigcontext *)oldsp; 142 143 fp = (struct sigframe_sigcontext *)((int)(fp - 1) & ~7); 144 145 #ifdef DEBUG 146 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 147 printf("sendsig_sigcontext: %s[%d] sig %d newusp %p scp %p\n", 148 p->p_comm, p->p_pid, sig, fp, &fp->sf_sc); 149 #endif 150 /* 151 * Now set up the signal frame. We build it in kernel space 152 * and then copy it out. We probably ought to just build it 153 * directly in user space.... 154 */ 155 sf.sf_signo = sig; 156 sf.sf_code = code; 157 sf.sf_scp = 0; 158 sf.sf_addr = 0; /* XXX */ 159 160 /* 161 * Build the signal context to be used by sigreturn. 162 */ 163 sf.sf_sc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK; 164 sf.sf_sc.sc_mask = *mask; 165 #ifdef COMPAT_13 166 /* 167 * XXX We always have to save an old style signal mask because 168 * XXX we might be delivering a signal to a process which will 169 * XXX escape from the signal in a non-standard way and invoke 170 * XXX sigreturn() directly. 171 */ 172 native_sigset_to_sigset13(mask, &sf.sf_sc.__sc_mask13); 173 #endif 174 sf.sf_sc.sc_sp = oldsp; 175 sf.sf_sc.sc_pc = tf->tf_pc; 176 sf.sf_sc.sc_npc = tf->tf_npc; 177 sf.sf_sc.sc_psr = tf->tf_psr; 178 sf.sf_sc.sc_g1 = tf->tf_global[1]; 179 sf.sf_sc.sc_o0 = tf->tf_out[0]; 180 181 /* 182 * Put the stack in a consistent state before we whack away 183 * at it. Note that write_user_windows may just dump the 184 * registers into the pcb; we need them in the process's memory. 185 * We also need to make sure that when we start the signal handler, 186 * its %i6 (%fp), which is loaded from the newly allocated stack area, 187 * joins seamlessly with the frame it was in when the signal occurred, 188 * so that the debugger and _longjmp code can back up through it. 189 */ 190 sendsig_reset(l, sig); 191 mutex_exit(p->p_lock); 192 newsp = (int)fp - sizeof(struct rwindow); 193 write_user_windows(); 194 error = (rwindow_save(l) || copyout((void *)&sf, (void *)fp, sizeof sf) || 195 suword(&((struct rwindow *)newsp)->rw_in[6], oldsp)); 196 mutex_enter(p->p_lock); 197 198 if (error) { 199 /* 200 * Process has trashed its stack; give it an illegal 201 * instruction to halt it in its tracks. 202 */ 203 #ifdef DEBUG 204 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 205 printf("sendsig_sigcontext: window save or copyout error\n"); 206 #endif 207 sigexit(l, SIGILL); 208 /* NOTREACHED */ 209 } 210 #ifdef DEBUG 211 if (sigdebug & SDB_FOLLOW) 212 printf("sendsig_siginfo: %s[%d] sig %d scp %p\n", 213 p->p_comm, p->p_pid, sig, &fp->sf_sc); 214 #endif 215 /* 216 * Arrange to continue execution at the code copied out in exec(). 217 * It needs the function to call in %g1, and a new stack pointer. 218 */ 219 switch (ps->sa_sigdesc[sig].sd_vers) { 220 case 0: /* legacy on-stack sigtramp */ 221 addr = (int)p->p_sigctx.ps_sigcode; 222 break; 223 224 case 1: 225 addr = (int)ps->sa_sigdesc[sig].sd_tramp; 226 break; 227 228 default: 229 /* Don't know what trampoline version; kill it. */ 230 addr = 0; 231 sigexit(l, SIGILL); 232 } 233 234 tf->tf_global[1] = (int)catcher; 235 tf->tf_pc = addr; 236 tf->tf_npc = addr + 4; 237 tf->tf_out[6] = newsp; 238 239 /* Remember that we're now on the signal stack. */ 240 if (onstack) 241 l->l_sigstk.ss_flags |= SS_ONSTACK; 242 243 #ifdef DEBUG 244 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 245 printf("sendsig: about to return to catcher\n"); 246 #endif 247 } 248 249 /* 250 * System call to cleanup state after a signal 251 * has been taken. Reset signal mask and 252 * stack state from context left by sendsig (above), 253 * and return to the given trap frame (if there is one). 254 * Check carefully to make sure that the user has not 255 * modified the state to gain improper privileges or to cause 256 * a machine fault. 257 */ 258 /* ARGSUSED */ 259 int 260 compat_16_sys___sigreturn14(struct lwp *l, const struct compat_16_sys___sigreturn14_args *uap, register_t *retval) 261 { 262 /* { 263 syscallarg(struct sigcontext *) sigcntxp; 264 } */ 265 struct sigcontext sc, *scp; 266 struct trapframe *tf; 267 struct proc *p; 268 int error; 269 270 p = l->l_proc; 271 272 /* First ensure consistent stack state (see sendsig). */ 273 write_user_windows(); 274 if (rwindow_save(l)) { 275 mutex_enter(p->p_lock); 276 sigexit(l, SIGILL); 277 } 278 #ifdef DEBUG 279 if (sigdebug & SDB_FOLLOW) 280 printf("sigreturn: %s[%d], sigcntxp %p\n", 281 p->p_comm, p->p_pid, SCARG(uap, sigcntxp)); 282 #endif 283 if ((error = copyin(SCARG(uap, sigcntxp), &sc, sizeof sc)) != 0) 284 return (error); 285 scp = ≻ 286 287 tf = l->l_md.md_tf; 288 /* 289 * Only the icc bits in the psr are used, so it need not be 290 * verified. pc and npc must be multiples of 4. This is all 291 * that is required; if it holds, just do it. 292 */ 293 if (((scp->sc_pc | scp->sc_npc) & 3) != 0) 294 return (EINVAL); 295 296 /* take only psr ICC field */ 297 tf->tf_psr = (tf->tf_psr & ~PSR_ICC) | (scp->sc_psr & PSR_ICC); 298 tf->tf_pc = scp->sc_pc; 299 tf->tf_npc = scp->sc_npc; 300 tf->tf_global[1] = scp->sc_g1; 301 tf->tf_out[0] = scp->sc_o0; 302 tf->tf_out[6] = scp->sc_sp; 303 304 mutex_enter(p->p_lock); 305 if (scp->sc_onstack & SS_ONSTACK) 306 l->l_sigstk.ss_flags |= SS_ONSTACK; 307 else 308 l->l_sigstk.ss_flags &= ~SS_ONSTACK; 309 /* Restore signal mask */ 310 (void) sigprocmask1(l, SIG_SETMASK, &scp->sc_mask, 0); 311 mutex_exit(p->p_lock); 312 313 return (EJUSTRETURN); 314 } 315