1 /* $NetBSD: netbsd32_machdep_16.c,v 1.6 2021/11/06 20:42:56 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1998, 2001 Matthew R. Green 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep_16.c,v 1.6 2021/11/06 20:42:56 thorpej Exp $"); 31 32 #ifdef _KERNEL_OPT 33 #include "opt_compat_netbsd.h" 34 #include "opt_modular.h" 35 #include "opt_execfmt.h" 36 #include "firm_events.h" 37 #endif 38 39 #include <sys/param.h> 40 #include <sys/exec.h> 41 #include <sys/exec_aout.h> 42 #include <sys/filedesc.h> 43 #include <sys/file.h> 44 #include <sys/proc.h> 45 #include <sys/signalvar.h> 46 #include <sys/systm.h> 47 #include <sys/core.h> 48 #include <sys/mount.h> 49 #include <sys/buf.h> 50 #include <sys/vnode.h> 51 #include <sys/select.h> 52 #include <sys/socketvar.h> 53 #include <sys/ucontext.h> 54 #include <sys/ioctl.h> 55 #include <sys/kmem.h> 56 57 #include <dev/sun/event_var.h> 58 59 #include <net/if.h> 60 #include <net/route.h> 61 62 #include <netinet/in.h> 63 #include <netinet/in_var.h> 64 #include <netinet/igmp.h> 65 #include <netinet/igmp_var.h> 66 #include <netinet/ip_mroute.h> 67 68 #include <compat/netbsd32/netbsd32.h> 69 #include <compat/netbsd32/netbsd32_ioctl.h> 70 #include <compat/netbsd32/netbsd32_syscallargs.h> 71 #include <compat/netbsd32/netbsd32_exec.h> 72 73 #include <compat/sys/signal.h> 74 #include <compat/sys/signalvar.h> 75 #include <compat/sys/siginfo.h> 76 #include <compat/sys/ucontext.h> 77 78 #include <machine/frame.h> 79 #include <machine/pcb.h> 80 #include <machine/reg.h> 81 #include <machine/vmparam.h> 82 #include <machine/vuid_event.h> 83 #include <machine/netbsd32_machdep.h> 84 #include <machine/userret.h> 85 86 /* 87 * NB: since this is a 32-bit address world, sf_scp and sf_sc 88 * can't be a pointer since those are 64-bits wide. 89 */ 90 struct sparc32_sigframe { 91 int sf_signo; /* signal number */ 92 int sf_code; /* code */ 93 u_int sf_scp; /* SunOS user addr of sigcontext */ 94 int sf_addr; /* SunOS compat, always 0 for now */ 95 struct netbsd32_sigcontext sf_sc; /* actual sigcontext */ 96 }; 97 98 #undef DEBUG 99 #ifdef DEBUG 100 extern int sigdebug; 101 #endif 102 103 static void 104 netbsd32_sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask) 105 { 106 int sig = ksi->ksi_signo; 107 struct lwp *l = curlwp; 108 struct proc *p = l->l_proc; 109 struct sparc32_sigframe *fp; 110 struct trapframe64 *tf; 111 int addr, onstack, error; 112 struct rwindow32 *oldsp, *newsp; 113 register32_t sp; 114 sig_t catcher = SIGACTION(p, sig).sa_handler; 115 struct sparc32_sigframe sf; 116 extern char netbsd32_sigcode[], netbsd32_esigcode[]; 117 #define szsigcode (netbsd32_esigcode - netbsd32_sigcode) 118 119 tf = l->l_md.md_tf; 120 /* Need to attempt to zero extend this 32-bit pointer */ 121 oldsp = (struct rwindow32 *)(u_long)(u_int)tf->tf_out[6]; 122 /* Do we need to jump onto the signal stack? */ 123 onstack = 124 (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && 125 (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; 126 if (onstack) { 127 fp = (struct sparc32_sigframe *)((char *)l->l_sigstk.ss_sp + 128 l->l_sigstk.ss_size); 129 l->l_sigstk.ss_flags |= SS_ONSTACK; 130 } else 131 fp = (struct sparc32_sigframe *)oldsp; 132 fp = (struct sparc32_sigframe *)((u_long)(fp - 1) & ~7); 133 134 #ifdef DEBUG 135 sigpid = p->p_pid; 136 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) { 137 printf("sendsig: %s[%d] sig %d newusp %p scp %p oldsp %p\n", 138 p->p_comm, p->p_pid, sig, fp, &fp->sf_sc, oldsp); 139 if (sigdebug & SDB_DDB) Debugger(); 140 } 141 #endif 142 /* 143 * Now set up the signal frame. We build it in kernel space 144 * and then copy it out. We probably ought to just build it 145 * directly in user space.... 146 */ 147 memset(&sf, 0, sizeof(sf)); 148 sf.sf_signo = sig; 149 sf.sf_code = (u_int)ksi->ksi_trap; 150 sf.sf_scp = (u_long)&fp->sf_sc; 151 sf.sf_addr = 0; /* XXX */ 152 153 /* 154 * Build the signal context to be used by sigreturn. 155 */ 156 sf.sf_sc.sc_onstack = onstack; 157 sf.sf_sc.sc_mask = *mask; 158 sf.sf_sc.sc_sp = (u_long)oldsp; 159 sf.sf_sc.sc_pc = tf->tf_pc; 160 sf.sf_sc.sc_npc = tf->tf_npc; 161 sf.sf_sc.sc_psr = TSTATECCR_TO_PSR(tf->tf_tstate); /* XXX */ 162 sf.sf_sc.sc_g1 = tf->tf_global[1]; 163 sf.sf_sc.sc_o0 = tf->tf_out[0]; 164 165 /* 166 * Put the stack in a consistent state before we whack away 167 * at it. Note that write_user_windows may just dump the 168 * registers into the pcb; we need them in the process's memory. 169 * We also need to make sure that when we start the signal handler, 170 * its %i6 (%fp), which is loaded from the newly allocated stack area, 171 * joins seamlessly with the frame it was in when the signal occurred, 172 * so that the debugger and _longjmp code can back up through it. 173 */ 174 sendsig_reset(l, sig); 175 mutex_exit(p->p_lock); 176 newsp = (struct rwindow32 *)((long)fp - sizeof(struct rwindow32)); 177 write_user_windows(); 178 #ifdef DEBUG 179 if ((sigdebug & SDB_KSTACK)) 180 printf("sendsig: saving sf to %p, setting stack pointer %p to %p\n", 181 fp, &(((struct rwindow32 *)newsp)->rw_in[6]), oldsp); 182 #endif 183 sp = NETBSD32PTR32I(oldsp); 184 error = (rwindow_save(l) || 185 copyout(&sf, fp, sizeof sf) || 186 copyout(&sp, &(((struct rwindow32 *)newsp)->rw_in[6]), 187 sizeof(sp))); 188 mutex_enter(p->p_lock); 189 if (error) { 190 /* 191 * Process has trashed its stack; give it an illegal 192 * instruction to halt it in its tracks. 193 */ 194 #ifdef DEBUG 195 mutex_exit(p->p_lock); 196 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 197 printf("sendsig: window save or copyout error\n"); 198 printf("sendsig: stack was trashed trying to send sig %d, sending SIGILL\n", sig); 199 if (sigdebug & SDB_DDB) Debugger(); 200 mutex_enter(p->p_lock); 201 #endif 202 sigexit(l, SIGILL); 203 /* NOTREACHED */ 204 } 205 206 #ifdef DEBUG 207 if (sigdebug & SDB_FOLLOW) { 208 printf("sendsig: %s[%d] sig %d scp %p\n", 209 p->p_comm, p->p_pid, sig, &fp->sf_sc); 210 } 211 #endif 212 /* 213 * Arrange to continue execution at the code copied out in exec(). 214 * It needs the function to call in %g1, and a new stack pointer. 215 */ 216 addr = p->p_psstrp - szsigcode; 217 tf->tf_global[1] = (long)catcher; 218 tf->tf_pc = addr; 219 tf->tf_npc = addr + 4; 220 tf->tf_out[6] = (uint64_t)(u_int)(u_long)newsp; 221 222 /* Remember that we're now on the signal stack. */ 223 if (onstack) 224 l->l_sigstk.ss_flags |= SS_ONSTACK; 225 226 #ifdef DEBUG 227 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) { 228 mutex_exit(p->p_lock); 229 printf("sendsig: about to return to catcher %p thru %p\n", 230 catcher, addr); 231 if (sigdebug & SDB_DDB) Debugger(); 232 mutex_enter(p->p_lock); 233 } 234 #endif 235 } 236 237 struct sparc32_sigframe_siginfo { 238 siginfo32_t sf_si; 239 ucontext32_t sf_uc; 240 }; 241 242 #undef DEBUG 243 244 /* 245 * System call to cleanup state after a signal 246 * has been taken. Reset signal mask and 247 * stack state from context left by sendsig (above), 248 * and return to the given trap frame (if there is one). 249 * Check carefully to make sure that the user has not 250 * modified the state to gain improper privileges or to cause 251 * a machine fault. 252 */ 253 /* ARGSUSED */ 254 int 255 compat_16_netbsd32___sigreturn14(struct lwp *l, const struct compat_16_netbsd32___sigreturn14_args *uap, register_t *retval) 256 { 257 /* { 258 syscallarg(struct sigcontext *) sigcntxp; 259 } */ 260 struct netbsd32_sigcontext sc, *scp; 261 struct trapframe64 *tf; 262 struct proc *p = l->l_proc; 263 264 /* First ensure consistent stack state (see sendsig). */ 265 write_user_windows(); 266 if (rwindow_save(l)) { 267 #ifdef DEBUG 268 printf("netbsd32_sigreturn14: rwindow_save(%p) failed, sending SIGILL\n", p); 269 Debugger(); 270 #endif 271 mutex_enter(p->p_lock); 272 sigexit(l, SIGILL); 273 } 274 #ifdef DEBUG 275 if (sigdebug & SDB_FOLLOW) { 276 printf("netbsd32_sigreturn14: %s[%d], sigcntxp %p\n", 277 p->p_comm, p->p_pid, SCARG(uap, sigcntxp)); 278 if (sigdebug & SDB_DDB) Debugger(); 279 } 280 #endif 281 scp = (struct netbsd32_sigcontext *)(u_long)SCARG(uap, sigcntxp); 282 if ((vaddr_t)scp & 3 || (copyin((void *)scp, &sc, sizeof sc) != 0)) 283 { 284 #ifdef DEBUG 285 printf("netbsd32_sigreturn14: copyin failed: scp=%p\n", scp); 286 Debugger(); 287 #endif 288 return (EINVAL); 289 } 290 scp = ≻ 291 292 tf = l->l_md.md_tf; 293 /* 294 * Only the icc bits in the psr are used, so it need not be 295 * verified. pc and npc must be multiples of 4. This is all 296 * that is required; if it holds, just do it. 297 */ 298 if (((sc.sc_pc | sc.sc_npc) & 3) != 0 || (sc.sc_pc == 0) || (sc.sc_npc == 0)) 299 #ifdef DEBUG 300 { 301 printf("netbsd32_sigreturn14: pc %p or npc %p invalid\n", sc.sc_pc, sc.sc_npc); 302 Debugger(); 303 return (EINVAL); 304 } 305 #else 306 return (EINVAL); 307 #endif 308 /* take only psr ICC field */ 309 tf->tf_tstate = (int64_t)(tf->tf_tstate & ~TSTATE_CCR) | PSRCC_TO_TSTATE(sc.sc_psr); 310 tf->tf_pc = (int64_t)sc.sc_pc; 311 tf->tf_npc = (int64_t)sc.sc_npc; 312 tf->tf_global[1] = (int64_t)sc.sc_g1; 313 tf->tf_out[0] = (int64_t)sc.sc_o0; 314 tf->tf_out[6] = (int64_t)sc.sc_sp; 315 #ifdef DEBUG 316 if (sigdebug & SDB_FOLLOW) { 317 printf("netbsd32_sigreturn14: return trapframe pc=%p sp=%p tstate=%llx\n", 318 (vaddr_t)tf->tf_pc, (vaddr_t)tf->tf_out[6], tf->tf_tstate); 319 if (sigdebug & SDB_DDB) Debugger(); 320 } 321 #endif 322 323 /* Restore signal stack. */ 324 mutex_enter(p->p_lock); 325 if (sc.sc_onstack & SS_ONSTACK) 326 l->l_sigstk.ss_flags |= SS_ONSTACK; 327 else 328 l->l_sigstk.ss_flags &= ~SS_ONSTACK; 329 /* Restore signal mask. */ 330 (void) sigprocmask1(l, SIG_SETMASK, &sc.sc_mask, 0); 331 mutex_exit(p->p_lock); 332 333 return (EJUSTRETURN); 334 } 335 336 void 337 netbsd32_machdep_md_16_init(void) 338 { 339 340 MODULE_HOOK_SET(netbsd32_sendsig_sigcontext_16_hook, 341 netbsd32_sendsig_sigcontext); 342 } 343 344 void 345 netbsd32_machdep_md_16_fini(void) 346 { 347 348 MODULE_HOOK_UNSET(netbsd32_sendsig_sigcontext_16_hook); 349 } 350