1 /* $NetBSD: compat_16_machdep.c,v 1.3 2008/11/28 09:01:00 he 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.3 2008/11/28 09:01:00 he 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/user.h> 81 #include <sys/systm.h> 82 #include <sys/kernel.h> 83 #include <sys/syscallargs.h> 84 85 #ifdef COMPAT_13 86 #include <compat/sys/signal.h> 87 #include <compat/sys/signalvar.h> 88 #endif 89 #include <machine/frame.h> 90 91 #ifdef COMPAT_13 92 #include <compat/sys/signal.h> 93 #include <compat/sys/signalvar.h> 94 #endif /* COMPAT_13 */ 95 96 struct sigframe_sigcontext { 97 int sf_signo; /* signal number */ 98 int sf_code; /* code */ 99 struct sigcontext *sf_scp; /* SunOS user addr of sigcontext */ 100 int sf_addr; /* SunOS compat, always 0 for now */ 101 struct sigcontext sf_sc; /* actual sigcontext */ 102 }; 103 104 #ifdef DEBUG 105 extern int sigdebug; 106 extern int sigpid; 107 #define SDB_FOLLOW 0x01 108 #define SDB_KSTACK 0x02 109 #define SDB_FPSTATE 0x04 110 #endif 111 112 void 113 sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask) 114 { 115 struct lwp *l = curlwp; 116 struct proc *p = l->l_proc; 117 struct sigacts *ps = p->p_sigacts; 118 struct sigframe_sigcontext *fp; 119 struct trapframe *tf; 120 int addr, onstack, oldsp, newsp, error; 121 struct sigframe_sigcontext sf; 122 int sig = ksi->ksi_signo; 123 u_long code = KSI_TRAPCODE(ksi); 124 sig_t catcher = SIGACTION(p, sig).sa_handler; 125 126 tf = l->l_md.md_tf; 127 oldsp = tf->tf_out[6]; 128 129 /* 130 * Compute new user stack addresses, subtract off 131 * one signal frame, and align. 132 */ 133 onstack = 134 (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && 135 (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; 136 137 if (onstack) 138 fp = (struct sigframe_sigcontext *) 139 ((char *)l->l_sigstk.ss_sp + 140 l->l_sigstk.ss_size); 141 else 142 fp = (struct sigframe_sigcontext *)oldsp; 143 144 fp = (struct sigframe_sigcontext *)((int)(fp - 1) & ~7); 145 146 #ifdef DEBUG 147 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 148 printf("sendsig_sigcontext: %s[%d] sig %d newusp %p scp %p\n", 149 p->p_comm, p->p_pid, sig, fp, &fp->sf_sc); 150 #endif 151 /* 152 * Now set up the signal frame. We build it in kernel space 153 * and then copy it out. We probably ought to just build it 154 * directly in user space.... 155 */ 156 sf.sf_signo = sig; 157 sf.sf_code = code; 158 sf.sf_scp = 0; 159 sf.sf_addr = 0; /* XXX */ 160 161 /* 162 * Build the signal context to be used by sigreturn. 163 */ 164 sf.sf_sc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK; 165 sf.sf_sc.sc_mask = *mask; 166 #ifdef COMPAT_13 167 /* 168 * XXX We always have to save an old style signal mask because 169 * XXX we might be delivering a signal to a process which will 170 * XXX escape from the signal in a non-standard way and invoke 171 * XXX sigreturn() directly. 172 */ 173 native_sigset_to_sigset13(mask, &sf.sf_sc.__sc_mask13); 174 #endif 175 sf.sf_sc.sc_sp = oldsp; 176 sf.sf_sc.sc_pc = tf->tf_pc; 177 sf.sf_sc.sc_npc = tf->tf_npc; 178 sf.sf_sc.sc_psr = tf->tf_psr; 179 sf.sf_sc.sc_g1 = tf->tf_global[1]; 180 sf.sf_sc.sc_o0 = tf->tf_out[0]; 181 182 /* 183 * Put the stack in a consistent state before we whack away 184 * at it. Note that write_user_windows may just dump the 185 * registers into the pcb; we need them in the process's memory. 186 * We also need to make sure that when we start the signal handler, 187 * its %i6 (%fp), which is loaded from the newly allocated stack area, 188 * joins seamlessly with the frame it was in when the signal occurred, 189 * so that the debugger and _longjmp code can back up through it. 190 */ 191 sendsig_reset(l, sig); 192 mutex_exit(p->p_lock); 193 newsp = (int)fp - sizeof(struct rwindow); 194 write_user_windows(); 195 error = (rwindow_save(l) || copyout((void *)&sf, (void *)fp, sizeof sf) || 196 suword(&((struct rwindow *)newsp)->rw_in[6], oldsp)); 197 mutex_enter(p->p_lock); 198 199 if (error) { 200 /* 201 * Process has trashed its stack; give it an illegal 202 * instruction to halt it in its tracks. 203 */ 204 #ifdef DEBUG 205 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 206 printf("sendsig_sigcontext: window save or copyout error\n"); 207 #endif 208 sigexit(l, SIGILL); 209 /* NOTREACHED */ 210 } 211 #ifdef DEBUG 212 if (sigdebug & SDB_FOLLOW) 213 printf("sendsig_siginfo: %s[%d] sig %d scp %p\n", 214 p->p_comm, p->p_pid, sig, &fp->sf_sc); 215 #endif 216 /* 217 * Arrange to continue execution at the code copied out in exec(). 218 * It needs the function to call in %g1, and a new stack pointer. 219 */ 220 switch (ps->sa_sigdesc[sig].sd_vers) { 221 case 0: /* legacy on-stack sigtramp */ 222 addr = (int)p->p_sigctx.ps_sigcode; 223 break; 224 225 case 1: 226 addr = (int)ps->sa_sigdesc[sig].sd_tramp; 227 break; 228 229 default: 230 /* Don't know what trampoline version; kill it. */ 231 addr = 0; 232 sigexit(l, SIGILL); 233 } 234 235 tf->tf_global[1] = (int)catcher; 236 tf->tf_pc = addr; 237 tf->tf_npc = addr + 4; 238 tf->tf_out[6] = newsp; 239 240 /* Remember that we're now on the signal stack. */ 241 if (onstack) 242 l->l_sigstk.ss_flags |= SS_ONSTACK; 243 244 #ifdef DEBUG 245 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 246 printf("sendsig: about to return to catcher\n"); 247 #endif 248 } 249 250 /* 251 * System call to cleanup state after a signal 252 * has been taken. Reset signal mask and 253 * stack state from context left by sendsig (above), 254 * and return to the given trap frame (if there is one). 255 * Check carefully to make sure that the user has not 256 * modified the state to gain improper privileges or to cause 257 * a machine fault. 258 */ 259 /* ARGSUSED */ 260 int 261 compat_16_sys___sigreturn14(struct lwp *l, const struct compat_16_sys___sigreturn14_args *uap, register_t *retval) 262 { 263 /* { 264 syscallarg(struct sigcontext *) sigcntxp; 265 } */ 266 struct sigcontext sc, *scp; 267 struct trapframe *tf; 268 struct proc *p; 269 int error; 270 271 p = l->l_proc; 272 273 /* First ensure consistent stack state (see sendsig). */ 274 write_user_windows(); 275 if (rwindow_save(l)) { 276 mutex_enter(p->p_lock); 277 sigexit(l, SIGILL); 278 } 279 #ifdef DEBUG 280 if (sigdebug & SDB_FOLLOW) 281 printf("sigreturn: %s[%d], sigcntxp %p\n", 282 p->p_comm, p->p_pid, SCARG(uap, sigcntxp)); 283 #endif 284 if ((error = copyin(SCARG(uap, sigcntxp), &sc, sizeof sc)) != 0) 285 return (error); 286 scp = ≻ 287 288 tf = l->l_md.md_tf; 289 /* 290 * Only the icc bits in the psr are used, so it need not be 291 * verified. pc and npc must be multiples of 4. This is all 292 * that is required; if it holds, just do it. 293 */ 294 if (((scp->sc_pc | scp->sc_npc) & 3) != 0) 295 return (EINVAL); 296 297 /* take only psr ICC field */ 298 tf->tf_psr = (tf->tf_psr & ~PSR_ICC) | (scp->sc_psr & PSR_ICC); 299 tf->tf_pc = scp->sc_pc; 300 tf->tf_npc = scp->sc_npc; 301 tf->tf_global[1] = scp->sc_g1; 302 tf->tf_out[0] = scp->sc_o0; 303 tf->tf_out[6] = scp->sc_sp; 304 305 mutex_enter(p->p_lock); 306 if (scp->sc_onstack & SS_ONSTACK) 307 l->l_sigstk.ss_flags |= SS_ONSTACK; 308 else 309 l->l_sigstk.ss_flags &= ~SS_ONSTACK; 310 /* Restore signal mask */ 311 (void) sigprocmask1(l, SIG_SETMASK, &scp->sc_mask, 0); 312 mutex_exit(p->p_lock); 313 314 return (EJUSTRETURN); 315 } 316