1 /* $NetBSD: compat_16_machdep.c,v 1.34 2022/08/20 23:49:31 riastradh Exp $ */ 2 3 /*- 4 * Copyright (c) 1996, 1997, 1998, 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Charles M. Hannum. 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 __KERNEL_RCSID(0, "$NetBSD: compat_16_machdep.c,v 1.34 2022/08/20 23:49:31 riastradh Exp $"); 34 35 #ifdef _KERNEL_OPT 36 #include "opt_compat_netbsd.h" 37 #endif 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/signal.h> 42 #include <sys/signalvar.h> 43 #include <sys/kernel.h> 44 #include <sys/proc.h> 45 #include <sys/mount.h> 46 #include <sys/syscallargs.h> 47 48 #include <uvm/uvm_extern.h> 49 50 #include <machine/pmap.h> 51 #include <machine/pmap_private.h> 52 #include <machine/vmparam.h> 53 #include <x86/fpu.h> 54 55 #if defined(COMPAT_16) 56 57 #include <compat/sys/signal.h> 58 #include <compat/sys/signalvar.h> 59 /* 60 * System call to cleanup state after a signal 61 * has been taken. Reset signal mask and 62 * stack state from context left by sendsig (above). 63 * Return to previous pc and psl as specified by 64 * context left by sendsig. Check carefully to 65 * make sure that the user has not modified the 66 * psl to gain improper privileges or to cause 67 * a machine fault. 68 */ 69 int compat_16_sys___sigreturn14(struct lwp *, const struct compat_16_sys___sigreturn14_args *, register_t *); 70 71 int 72 compat_16_sys___sigreturn14(struct lwp *l, const struct compat_16_sys___sigreturn14_args *uap, register_t *retval) 73 { 74 /* { 75 syscallarg(struct sigcontext *) sigcntxp; 76 } */ 77 struct proc *p = l->l_proc; 78 struct sigcontext *scp, context; 79 struct trapframe *tf; 80 81 /* 82 * The trampoline code hands us the context. 83 * It is unsafe to keep track of it ourselves, in the event that a 84 * program jumps out of a signal handler. 85 */ 86 scp = SCARG(uap, sigcntxp); 87 if (copyin((void *)scp, &context, sizeof(*scp)) != 0) 88 return (EFAULT); 89 90 /* Restore register context. */ 91 tf = l->l_md.md_regs; 92 93 /* 94 * Check for security violations. If we're returning to 95 * protected mode, the CPU will validate the segment registers 96 * automatically and generate a trap on violations. We handle 97 * the trap, rather than doing all of the checking here. 98 */ 99 if (((context.sc_eflags ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 || 100 !USERMODE(context.sc_cs)) 101 return (EINVAL); 102 103 tf->tf_gs = context.sc_gs; 104 tf->tf_fs = context.sc_fs; 105 tf->tf_es = context.sc_es; 106 tf->tf_ds = context.sc_ds; 107 tf->tf_eflags &= ~PSL_USER; 108 tf->tf_eflags |= context.sc_eflags & PSL_USER; 109 110 tf->tf_edi = context.sc_edi; 111 tf->tf_esi = context.sc_esi; 112 tf->tf_ebp = context.sc_ebp; 113 tf->tf_ebx = context.sc_ebx; 114 tf->tf_edx = context.sc_edx; 115 tf->tf_ecx = context.sc_ecx; 116 tf->tf_eax = context.sc_eax; 117 tf->tf_eip = context.sc_eip; 118 tf->tf_cs = context.sc_cs; 119 tf->tf_esp = context.sc_esp; 120 tf->tf_ss = context.sc_ss; 121 122 /* Restore signal stack. */ 123 mutex_enter(p->p_lock); 124 if (context.sc_onstack & SS_ONSTACK) 125 l->l_sigstk.ss_flags |= SS_ONSTACK; 126 else 127 l->l_sigstk.ss_flags &= ~SS_ONSTACK; 128 /* Restore signal mask. */ 129 (void) sigprocmask1(l, SIG_SETMASK, &context.sc_mask, 0); 130 mutex_exit(p->p_lock); 131 132 return (EJUSTRETURN); 133 } 134 #endif 135 136 #ifdef COMPAT_16 137 /* 138 * Send an interrupt to process. 139 * 140 * Stack is set up to allow sigcode stored 141 * in u. to call routine, followed by kcall 142 * to sigreturn routine below. After sigreturn 143 * resets the signal mask, the stack, and the 144 * frame pointer, it returns to the user 145 * specified pc, psl. 146 */ 147 void 148 sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask) 149 { 150 struct lwp *l = curlwp; 151 struct proc *p = l->l_proc; 152 struct pmap *pmap = vm_map_pmap(&p->p_vmspace->vm_map); 153 int sel = pmap->pm_hiexec > I386_MAX_EXE_ADDR ? 154 GUCODEBIG_SEL : GUCODE_SEL; 155 struct sigacts *ps = p->p_sigacts; 156 struct trapframe *tf = l->l_md.md_regs; 157 int onstack, error; 158 int sig = ksi->ksi_signo; 159 u_long code = KSI_TRAPCODE(ksi); 160 struct sigframe_sigcontext *fp = getframe(l, sig, &onstack), frame; 161 sig_t catcher = SIGACTION(p, sig).sa_handler; 162 163 fp--; 164 165 /* Build stack frame for signal trampoline. */ 166 switch (ps->sa_sigdesc[sig].sd_vers) { 167 case __SIGTRAMP_SIGCODE_VERSION: /* legacy on-stack sigtramp */ 168 frame.sf_ra = (int)p->p_sigctx.ps_sigcode; 169 break; 170 171 case __SIGTRAMP_SIGCONTEXT_VERSION: 172 frame.sf_ra = (int)ps->sa_sigdesc[sig].sd_tramp; 173 break; 174 175 default: 176 /* Don't know what trampoline version; kill it. */ 177 sigexit(l, SIGILL); 178 } 179 180 frame.sf_signum = sig; 181 frame.sf_code = code; 182 frame.sf_scp = &fp->sf_sc; 183 184 /* Save register context. */ 185 frame.sf_sc.sc_gs = tf->tf_gs; 186 frame.sf_sc.sc_fs = tf->tf_fs; 187 frame.sf_sc.sc_es = tf->tf_es; 188 frame.sf_sc.sc_ds = tf->tf_ds; 189 frame.sf_sc.sc_eflags = tf->tf_eflags; 190 191 frame.sf_sc.sc_edi = tf->tf_edi; 192 frame.sf_sc.sc_esi = tf->tf_esi; 193 frame.sf_sc.sc_ebp = tf->tf_ebp; 194 frame.sf_sc.sc_ebx = tf->tf_ebx; 195 frame.sf_sc.sc_edx = tf->tf_edx; 196 frame.sf_sc.sc_ecx = tf->tf_ecx; 197 frame.sf_sc.sc_eax = tf->tf_eax; 198 frame.sf_sc.sc_eip = tf->tf_eip; 199 frame.sf_sc.sc_cs = tf->tf_cs; 200 frame.sf_sc.sc_esp = tf->tf_esp; 201 frame.sf_sc.sc_ss = tf->tf_ss; 202 frame.sf_sc.sc_trapno = tf->tf_trapno; 203 frame.sf_sc.sc_err = tf->tf_err; 204 205 /* Save signal stack. */ 206 frame.sf_sc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK; 207 208 /* Save signal mask. */ 209 frame.sf_sc.sc_mask = *mask; 210 211 #ifdef COMPAT_13 212 /* 213 * XXX We always have to save an old style signal mask because 214 * XXX we might be delivering a signal to a process which will 215 * XXX escape from the signal in a non-standard way and invoke 216 * XXX sigreturn() directly. 217 */ 218 native_sigset_to_sigset13(mask, &frame.sf_sc.__sc_mask13); 219 #endif 220 221 sendsig_reset(l, sig); 222 223 mutex_exit(p->p_lock); 224 error = copyout(&frame, fp, sizeof(frame)); 225 mutex_enter(p->p_lock); 226 227 if (error != 0) { 228 /* 229 * Process has trashed its stack; give it an illegal 230 * instruction to halt it in its tracks. 231 */ 232 sigexit(l, SIGILL); 233 /* NOTREACHED */ 234 } 235 236 buildcontext(l, sel, catcher, fp); 237 238 /* Remember that we're now on the signal stack. */ 239 if (onstack) 240 l->l_sigstk.ss_flags |= SS_ONSTACK; 241 } 242 #endif 243