1d66a5066SPeter Wemm /*- 2e1743d02SSøren Schmidt * Copyright (c) 1994-1996 S�ren Schmidt 3d66a5066SPeter Wemm * All rights reserved. 4d66a5066SPeter Wemm * 5d66a5066SPeter Wemm * Redistribution and use in source and binary forms, with or without 6d66a5066SPeter Wemm * modification, are permitted provided that the following conditions 7d66a5066SPeter Wemm * are met: 8d66a5066SPeter Wemm * 1. Redistributions of source code must retain the above copyright 9d66a5066SPeter Wemm * notice, this list of conditions and the following disclaimer 10d66a5066SPeter Wemm * in this position and unchanged. 11d66a5066SPeter Wemm * 2. Redistributions in binary form must reproduce the above copyright 12d66a5066SPeter Wemm * notice, this list of conditions and the following disclaimer in the 13d66a5066SPeter Wemm * documentation and/or other materials provided with the distribution. 14d66a5066SPeter Wemm * 3. The name of the author may not be used to endorse or promote products 15d66a5066SPeter Wemm * derived from this software withough specific prior written permission 16d66a5066SPeter Wemm * 17d66a5066SPeter Wemm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18d66a5066SPeter Wemm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19d66a5066SPeter Wemm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20d66a5066SPeter Wemm * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21d66a5066SPeter Wemm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22d66a5066SPeter Wemm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23d66a5066SPeter Wemm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24d66a5066SPeter Wemm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25d66a5066SPeter Wemm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26d66a5066SPeter Wemm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27d66a5066SPeter Wemm * 28aad9af2bSBruce Evans * $Id: linux_sysvec.c,v 1.7 1996/06/18 05:15:53 dyson Exp $ 29d66a5066SPeter Wemm */ 30d66a5066SPeter Wemm 31d66a5066SPeter Wemm /* XXX we use functions that might not exist. */ 32d66a5066SPeter Wemm #define COMPAT_43 1 33d66a5066SPeter Wemm 34d66a5066SPeter Wemm #include <sys/param.h> 355e26fb6fSJordan K. Hubbard #include <sys/buf.h> 36aad9af2bSBruce Evans #include <sys/proc.h> 37d66a5066SPeter Wemm #include <sys/systm.h> 38d66a5066SPeter Wemm #include <sys/sysproto.h> 39d66a5066SPeter Wemm #include <sys/sysent.h> 40d66a5066SPeter Wemm #include <sys/imgact.h> 41e1743d02SSøren Schmidt #include <sys/imgact_elf.h> 42d66a5066SPeter Wemm #include <sys/signalvar.h> 43e1743d02SSøren Schmidt #include <sys/malloc.h> 44d66a5066SPeter Wemm #include <vm/vm.h> 45d66a5066SPeter Wemm #include <vm/vm_param.h> 46d66a5066SPeter Wemm #include <vm/vm_prot.h> 47d66a5066SPeter Wemm #include <vm/lock.h> 48d66a5066SPeter Wemm #include <vm/vm_kern.h> 49d66a5066SPeter Wemm #include <vm/vm_object.h> 50d66a5066SPeter Wemm #include <vm/vm_page.h> 51d66a5066SPeter Wemm #include <vm/vm_map.h> 52d66a5066SPeter Wemm #include <vm/vm_pager.h> 53d66a5066SPeter Wemm #include <vm/vm_extern.h> 54d66a5066SPeter Wemm #include <sys/user.h> 55d66a5066SPeter Wemm #include <sys/exec.h> 565cf588ebSPeter Wemm #include <sys/kernel.h> 57d66a5066SPeter Wemm #include <machine/cpu.h> 58d66a5066SPeter Wemm #include <machine/frame.h> 59d66a5066SPeter Wemm #include <machine/reg.h> 60d66a5066SPeter Wemm #include <machine/specialreg.h> 61d66a5066SPeter Wemm #include <machine/psl.h> 62d66a5066SPeter Wemm #include <machine/sysarch.h> 63d66a5066SPeter Wemm #include <machine/md_var.h> 64d66a5066SPeter Wemm 65d66a5066SPeter Wemm #include <i386/linux/linux.h> 66d66a5066SPeter Wemm #include <i386/linux/linux_proto.h> 67e1743d02SSøren Schmidt 68e1743d02SSøren Schmidt int linux_fixup __P((int **stack_base, struct image_params *iparams)); 69e1743d02SSøren Schmidt int elf_linux_fixup __P((int **stack_base, struct image_params *iparams)); 70e1743d02SSøren Schmidt void linux_prepsyscall __P((struct trapframe *tf, int *args, u_int *code, caddr_t *params)); 71b36546f6SPeter Wemm void linux_sendsig __P((sig_t catcher, int sig, int mask, u_long code)); 72d66a5066SPeter Wemm 73d66a5066SPeter Wemm /* 74d66a5066SPeter Wemm * Linux syscalls return negative errno's, we do positive and map them 75d66a5066SPeter Wemm */ 76d66a5066SPeter Wemm int bsd_to_linux_errno[ELAST] = { 77d66a5066SPeter Wemm -0, -1, -2, -3, -4, -5, -6, -7, -8, -9, 78d66a5066SPeter Wemm -10, -35, -12, -13, -14, -15, -16, -17, -18, -19, 79d66a5066SPeter Wemm -20, -21, -22, -23, -24, -25, -26, -27, -28, -29, 80d66a5066SPeter Wemm -30, -31, -32, -33, -34, -11,-115,-114, -88, -89, 81d66a5066SPeter Wemm -90, -91, -92, -93, -94, -95, -96, -97, -98, -99, 82d66a5066SPeter Wemm -100,-101,-102,-103,-104,-105,-106,-107,-108,-109, 83d66a5066SPeter Wemm -110,-111, -40, -36,-112,-113, -39, -11, -87,-122, 84d66a5066SPeter Wemm -116, -66, -6, -6, -6, -6, -6, -37, -38, -9, 85d66a5066SPeter Wemm -6, 86d66a5066SPeter Wemm }; 87d66a5066SPeter Wemm 88d66a5066SPeter Wemm int bsd_to_linux_signal[NSIG] = { 89d66a5066SPeter Wemm 0, LINUX_SIGHUP, LINUX_SIGINT, LINUX_SIGQUIT, 90d66a5066SPeter Wemm LINUX_SIGILL, LINUX_SIGTRAP, LINUX_SIGABRT, 0, 91d66a5066SPeter Wemm LINUX_SIGFPE, LINUX_SIGKILL, LINUX_SIGBUS, LINUX_SIGSEGV, 92d66a5066SPeter Wemm 0, LINUX_SIGPIPE, LINUX_SIGALRM, LINUX_SIGTERM, 93d66a5066SPeter Wemm LINUX_SIGURG, LINUX_SIGSTOP, LINUX_SIGTSTP, LINUX_SIGCONT, 94d66a5066SPeter Wemm LINUX_SIGCHLD, LINUX_SIGTTIN, LINUX_SIGTTOU, LINUX_SIGIO, 95d66a5066SPeter Wemm LINUX_SIGXCPU, LINUX_SIGXFSZ, LINUX_SIGVTALRM, LINUX_SIGPROF, 96d66a5066SPeter Wemm LINUX_SIGWINCH, 0, LINUX_SIGUSR1, LINUX_SIGUSR2 97d66a5066SPeter Wemm }; 98d66a5066SPeter Wemm 99d66a5066SPeter Wemm int linux_to_bsd_signal[LINUX_NSIG] = { 100d66a5066SPeter Wemm 0, SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGEMT, 101d66a5066SPeter Wemm SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, 102d66a5066SPeter Wemm SIGBUS, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGIO, 103d66a5066SPeter Wemm SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH, SIGURG, SIGURG, 0 104d66a5066SPeter Wemm }; 105d66a5066SPeter Wemm 106d66a5066SPeter Wemm int linux_fixup(int **stack_base, struct image_params *imgp) 107d66a5066SPeter Wemm { 108d66a5066SPeter Wemm int *argv, *envp; 109d66a5066SPeter Wemm 110d66a5066SPeter Wemm argv = *stack_base; 111d66a5066SPeter Wemm envp = *stack_base + (imgp->argc + 1); 112d66a5066SPeter Wemm (*stack_base)--; 113d66a5066SPeter Wemm **stack_base = (int)envp; 114d66a5066SPeter Wemm (*stack_base)--; 115d66a5066SPeter Wemm **stack_base = (int)argv; 116d66a5066SPeter Wemm (*stack_base)--; 117d66a5066SPeter Wemm **stack_base = (int)imgp->argc; 118e1743d02SSøren Schmidt return 0; 119d66a5066SPeter Wemm } 120d66a5066SPeter Wemm 121e1743d02SSøren Schmidt int elf_linux_fixup(int **stack_base, struct image_params *imgp) 122e1743d02SSøren Schmidt { 123e1743d02SSøren Schmidt Elf32_Auxargs *args = (Elf32_Auxargs *)imgp->auxargs; 124e1743d02SSøren Schmidt int *pos; 125d66a5066SPeter Wemm 126e1743d02SSøren Schmidt pos = *stack_base + (imgp->argc + imgp->envc + 2); 127e1743d02SSøren Schmidt 128e1743d02SSøren Schmidt if (args->trace) { 129e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_DEBUG, 1); 130e1743d02SSøren Schmidt } 131e1743d02SSøren Schmidt if (args->execfd != -1) { 132e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); 133e1743d02SSøren Schmidt } 134e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); 135e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_PHENT, args->phent); 136e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum); 137e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz); 138e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); 139e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); 140e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_BASE, args->base); 141e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_cred->p_ruid); 142e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_cred->p_svuid); 143e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_cred->p_rgid); 144e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_cred->p_svgid); 145e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_NULL, 0); 146e1743d02SSøren Schmidt 147e1743d02SSøren Schmidt free(imgp->auxargs, M_TEMP); 148e1743d02SSøren Schmidt imgp->auxargs = NULL; 149e1743d02SSøren Schmidt 150e1743d02SSøren Schmidt (*stack_base)--; 151e1743d02SSøren Schmidt **stack_base = (int)imgp->argc; 152e1743d02SSøren Schmidt return 0; 153e1743d02SSøren Schmidt } 154d66a5066SPeter Wemm 155d66a5066SPeter Wemm extern int _ucodesel, _udatasel; 156d66a5066SPeter Wemm 157d66a5066SPeter Wemm /* 158d66a5066SPeter Wemm * Send an interrupt to process. 159d66a5066SPeter Wemm * 160d66a5066SPeter Wemm * Stack is set up to allow sigcode stored 161d66a5066SPeter Wemm * in u. to call routine, followed by kcall 162d66a5066SPeter Wemm * to sigreturn routine below. After sigreturn 163d66a5066SPeter Wemm * resets the signal mask, the stack, and the 164d66a5066SPeter Wemm * frame pointer, it returns to the user 165d66a5066SPeter Wemm * specified pc, psl. 166d66a5066SPeter Wemm */ 167d66a5066SPeter Wemm 168e1743d02SSøren Schmidt void 169b36546f6SPeter Wemm linux_sendsig(sig_t catcher, int sig, int mask, u_long code) 170d66a5066SPeter Wemm { 171d66a5066SPeter Wemm register struct proc *p = curproc; 172d66a5066SPeter Wemm register int *regs; 173d66a5066SPeter Wemm struct linux_sigframe *fp, frame; 174d66a5066SPeter Wemm struct sigacts *psp = p->p_sigacts; 175d66a5066SPeter Wemm int oonstack; 176d66a5066SPeter Wemm 177d66a5066SPeter Wemm regs = p->p_md.md_regs; 178d66a5066SPeter Wemm oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK; 179d66a5066SPeter Wemm 180d66a5066SPeter Wemm #ifdef DEBUG 181b36546f6SPeter Wemm printf("Linux-emul(%d): linux_sendsig(%8x, %d, %d, %ld)\n", 182d66a5066SPeter Wemm p->p_pid, catcher, sig, mask, code); 183d66a5066SPeter Wemm #endif 184d66a5066SPeter Wemm /* 185d66a5066SPeter Wemm * Allocate space for the signal handler context. 186d66a5066SPeter Wemm */ 187d66a5066SPeter Wemm if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack && 188d66a5066SPeter Wemm (psp->ps_sigonstack & sigmask(sig))) { 189d66a5066SPeter Wemm fp = (struct linux_sigframe *)(psp->ps_sigstk.ss_sp + 190d66a5066SPeter Wemm psp->ps_sigstk.ss_size - sizeof(struct linux_sigframe)); 191d66a5066SPeter Wemm psp->ps_sigstk.ss_flags |= SS_ONSTACK; 192d66a5066SPeter Wemm } else { 193d66a5066SPeter Wemm fp = (struct linux_sigframe *)regs[tESP] - 1; 194d66a5066SPeter Wemm } 195d66a5066SPeter Wemm 196d66a5066SPeter Wemm /* 197d66a5066SPeter Wemm * grow() will return FALSE if the fp will not fit inside the stack 198d66a5066SPeter Wemm * and the stack can not be grown. useracc will return FALSE 199d66a5066SPeter Wemm * if access is denied. 200d66a5066SPeter Wemm */ 201d66a5066SPeter Wemm if ((grow(p, (int)fp) == FALSE) || 202d66a5066SPeter Wemm (useracc((caddr_t)fp, sizeof (struct linux_sigframe), B_WRITE) == FALSE)) { 203d66a5066SPeter Wemm /* 204d66a5066SPeter Wemm * Process has trashed its stack; give it an illegal 205d66a5066SPeter Wemm * instruction to halt it in its tracks. 206d66a5066SPeter Wemm */ 207d66a5066SPeter Wemm SIGACTION(p, SIGILL) = SIG_DFL; 208d66a5066SPeter Wemm sig = sigmask(SIGILL); 209d66a5066SPeter Wemm p->p_sigignore &= ~sig; 210d66a5066SPeter Wemm p->p_sigcatch &= ~sig; 211d66a5066SPeter Wemm p->p_sigmask &= ~sig; 212d66a5066SPeter Wemm psignal(p, SIGILL); 213d66a5066SPeter Wemm return; 214d66a5066SPeter Wemm } 215d66a5066SPeter Wemm 216d66a5066SPeter Wemm /* 217d66a5066SPeter Wemm * Build the argument list for the signal handler. 218d66a5066SPeter Wemm */ 219d66a5066SPeter Wemm if (p->p_sysent->sv_sigtbl) { 220d66a5066SPeter Wemm if (sig < p->p_sysent->sv_sigsize) 221d66a5066SPeter Wemm sig = p->p_sysent->sv_sigtbl[sig]; 222d66a5066SPeter Wemm else 223d66a5066SPeter Wemm sig = p->p_sysent->sv_sigsize + 1; 224d66a5066SPeter Wemm } 225d66a5066SPeter Wemm 226d66a5066SPeter Wemm frame.sf_handler = catcher; 227d66a5066SPeter Wemm frame.sf_sig = sig; 228d66a5066SPeter Wemm 229d66a5066SPeter Wemm /* 230d66a5066SPeter Wemm * Build the signal context to be used by sigreturn. 231d66a5066SPeter Wemm */ 232d66a5066SPeter Wemm frame.sf_sc.sc_mask = mask; 233d66a5066SPeter Wemm __asm("movl %%gs,%w0" : "=r" (frame.sf_sc.sc_gs)); 234d66a5066SPeter Wemm __asm("movl %%fs,%w0" : "=r" (frame.sf_sc.sc_fs)); 235d66a5066SPeter Wemm frame.sf_sc.sc_es = regs[tES]; 236d66a5066SPeter Wemm frame.sf_sc.sc_ds = regs[tDS]; 237d66a5066SPeter Wemm frame.sf_sc.sc_edi = regs[tEDI]; 238d66a5066SPeter Wemm frame.sf_sc.sc_esi = regs[tESI]; 239d66a5066SPeter Wemm frame.sf_sc.sc_ebp = regs[tEBP]; 240d66a5066SPeter Wemm frame.sf_sc.sc_ebx = regs[tEBX]; 241d66a5066SPeter Wemm frame.sf_sc.sc_edx = regs[tEDX]; 242d66a5066SPeter Wemm frame.sf_sc.sc_ecx = regs[tECX]; 243d66a5066SPeter Wemm frame.sf_sc.sc_eax = regs[tEAX]; 244d66a5066SPeter Wemm frame.sf_sc.sc_eip = regs[tEIP]; 245d66a5066SPeter Wemm frame.sf_sc.sc_cs = regs[tCS]; 246d66a5066SPeter Wemm frame.sf_sc.sc_eflags = regs[tEFLAGS]; 247d66a5066SPeter Wemm frame.sf_sc.sc_esp_at_signal = regs[tESP]; 248d66a5066SPeter Wemm frame.sf_sc.sc_ss = regs[tSS]; 249d66a5066SPeter Wemm frame.sf_sc.sc_err = regs[tERR]; 250d66a5066SPeter Wemm frame.sf_sc.sc_trapno = code; /* XXX ???? */ 251d66a5066SPeter Wemm 252d66a5066SPeter Wemm if (copyout(&frame, fp, sizeof(frame)) != 0) { 253d66a5066SPeter Wemm /* 254d66a5066SPeter Wemm * Process has trashed its stack; give it an illegal 255d66a5066SPeter Wemm * instruction to halt it in its tracks. 256d66a5066SPeter Wemm */ 257d66a5066SPeter Wemm sigexit(p, SIGILL); 258d66a5066SPeter Wemm /* NOTREACHED */ 259d66a5066SPeter Wemm } 260d66a5066SPeter Wemm 261d66a5066SPeter Wemm /* 262d66a5066SPeter Wemm * Build context to run handler in. 263d66a5066SPeter Wemm */ 264d66a5066SPeter Wemm regs[tESP] = (int)fp; 265d66a5066SPeter Wemm regs[tEIP] = (int)(((char *)PS_STRINGS) - *(p->p_sysent->sv_szsigcode)); 266d66a5066SPeter Wemm regs[tEFLAGS] &= ~PSL_VM; 267d66a5066SPeter Wemm regs[tCS] = _ucodesel; 268d66a5066SPeter Wemm regs[tDS] = _udatasel; 269d66a5066SPeter Wemm regs[tES] = _udatasel; 270d66a5066SPeter Wemm regs[tSS] = _udatasel; 271d66a5066SPeter Wemm } 272d66a5066SPeter Wemm 273d66a5066SPeter Wemm /* 274d66a5066SPeter Wemm * System call to cleanup state after a signal 275d66a5066SPeter Wemm * has been taken. Reset signal mask and 276d66a5066SPeter Wemm * stack state from context left by sendsig (above). 277d66a5066SPeter Wemm * Return to previous pc and psl as specified by 278d66a5066SPeter Wemm * context left by sendsig. Check carefully to 279d66a5066SPeter Wemm * make sure that the user has not modified the 280d66a5066SPeter Wemm * psl to gain improper privileges or to cause 281d66a5066SPeter Wemm * a machine fault. 282d66a5066SPeter Wemm */ 283d66a5066SPeter Wemm int 284d66a5066SPeter Wemm linux_sigreturn(p, args, retval) 285d66a5066SPeter Wemm struct proc *p; 286d66a5066SPeter Wemm struct linux_sigreturn_args *args; 287d66a5066SPeter Wemm int *retval; 288d66a5066SPeter Wemm { 289d66a5066SPeter Wemm struct linux_sigcontext *scp, context; 290d66a5066SPeter Wemm register int *regs; 291d66a5066SPeter Wemm int eflags; 292d66a5066SPeter Wemm 293d66a5066SPeter Wemm regs = p->p_md.md_regs; 294d66a5066SPeter Wemm 295d66a5066SPeter Wemm #ifdef DEBUG 296d66a5066SPeter Wemm printf("Linux-emul(%d): linux_sigreturn(%8x)\n", p->p_pid, args->scp); 297d66a5066SPeter Wemm #endif 298d66a5066SPeter Wemm /* 299d66a5066SPeter Wemm * The trampoline code hands us the context. 300d66a5066SPeter Wemm * It is unsafe to keep track of it ourselves, in the event that a 301d66a5066SPeter Wemm * program jumps out of a signal handler. 302d66a5066SPeter Wemm */ 303d66a5066SPeter Wemm scp = args->scp; 304d66a5066SPeter Wemm if (copyin((caddr_t)scp, &context, sizeof(*scp)) != 0) 305d66a5066SPeter Wemm return (EFAULT); 306d66a5066SPeter Wemm 307d66a5066SPeter Wemm /* 308d66a5066SPeter Wemm * Check for security violations. 309d66a5066SPeter Wemm */ 310d66a5066SPeter Wemm #define EFLAGS_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) 311d66a5066SPeter Wemm eflags = context.sc_eflags; 312d66a5066SPeter Wemm /* 313d66a5066SPeter Wemm * XXX do allow users to change the privileged flag PSL_RF. The 314d66a5066SPeter Wemm * cpu sets PSL_RF in tf_eflags for faults. Debuggers should 315d66a5066SPeter Wemm * sometimes set it there too. tf_eflags is kept in the signal 316d66a5066SPeter Wemm * context during signal handling and there is no other place 317d66a5066SPeter Wemm * to remember it, so the PSL_RF bit may be corrupted by the 318d66a5066SPeter Wemm * signal handler without us knowing. Corruption of the PSL_RF 319d66a5066SPeter Wemm * bit at worst causes one more or one less debugger trap, so 320d66a5066SPeter Wemm * allowing it is fairly harmless. 321d66a5066SPeter Wemm */ 322d66a5066SPeter Wemm if (!EFLAGS_SECURE(eflags & ~PSL_RF, regs[tEFLAGS] & ~PSL_RF)) { 323d66a5066SPeter Wemm return(EINVAL); 324d66a5066SPeter Wemm } 325d66a5066SPeter Wemm 326d66a5066SPeter Wemm /* 327d66a5066SPeter Wemm * Don't allow users to load a valid privileged %cs. Let the 328d66a5066SPeter Wemm * hardware check for invalid selectors, excess privilege in 329d66a5066SPeter Wemm * other selectors, invalid %eip's and invalid %esp's. 330d66a5066SPeter Wemm */ 331d66a5066SPeter Wemm #define CS_SECURE(cs) (ISPL(cs) == SEL_UPL) 332d66a5066SPeter Wemm if (!CS_SECURE(context.sc_cs)) { 333d66a5066SPeter Wemm trapsignal(p, SIGBUS, T_PROTFLT); 334d66a5066SPeter Wemm return(EINVAL); 335d66a5066SPeter Wemm } 336d66a5066SPeter Wemm 337d66a5066SPeter Wemm p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK; 338d66a5066SPeter Wemm p->p_sigmask = context.sc_mask &~ 339d66a5066SPeter Wemm (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP)); 340d66a5066SPeter Wemm /* 341d66a5066SPeter Wemm * Restore signal context. 342d66a5066SPeter Wemm */ 343d66a5066SPeter Wemm /* %fs and %gs were restored by the trampoline. */ 344d66a5066SPeter Wemm regs[tES] = context.sc_es; 345d66a5066SPeter Wemm regs[tDS] = context.sc_ds; 346d66a5066SPeter Wemm regs[tEDI] = context.sc_edi; 347d66a5066SPeter Wemm regs[tESI] = context.sc_esi; 348d66a5066SPeter Wemm regs[tEBP] = context.sc_ebp; 349d66a5066SPeter Wemm regs[tEBX] = context.sc_ebx; 350d66a5066SPeter Wemm regs[tEDX] = context.sc_edx; 351d66a5066SPeter Wemm regs[tECX] = context.sc_ecx; 352d66a5066SPeter Wemm regs[tEAX] = context.sc_eax; 353d66a5066SPeter Wemm regs[tEIP] = context.sc_eip; 354d66a5066SPeter Wemm regs[tCS] = context.sc_cs; 355d66a5066SPeter Wemm regs[tEFLAGS] = eflags; 356d66a5066SPeter Wemm regs[tESP] = context.sc_esp_at_signal; 357d66a5066SPeter Wemm regs[tSS] = context.sc_ss; 358d66a5066SPeter Wemm 359d66a5066SPeter Wemm return (EJUSTRETURN); 360d66a5066SPeter Wemm } 361d66a5066SPeter Wemm 362e1743d02SSøren Schmidt void 363d66a5066SPeter Wemm linux_prepsyscall(struct trapframe *tf, int *args, u_int *code, caddr_t *params) 364d66a5066SPeter Wemm { 365d66a5066SPeter Wemm args[0] = tf->tf_ebx; 366d66a5066SPeter Wemm args[1] = tf->tf_ecx; 367d66a5066SPeter Wemm args[2] = tf->tf_edx; 368d66a5066SPeter Wemm args[3] = tf->tf_esi; 369d66a5066SPeter Wemm args[4] = tf->tf_edi; 370d66a5066SPeter Wemm *params = NULL; /* no copyin */ 371d66a5066SPeter Wemm } 372d66a5066SPeter Wemm 373d66a5066SPeter Wemm struct sysentvec linux_sysvec = { 374e1743d02SSøren Schmidt LINUX_SYS_MAXSYSCALL, 375d66a5066SPeter Wemm linux_sysent, 376d66a5066SPeter Wemm 0xff, 377d66a5066SPeter Wemm NSIG, 378d66a5066SPeter Wemm bsd_to_linux_signal, 379d66a5066SPeter Wemm ELAST, 380d66a5066SPeter Wemm bsd_to_linux_errno, 381d66a5066SPeter Wemm linux_fixup, 382d66a5066SPeter Wemm linux_sendsig, 383d66a5066SPeter Wemm linux_sigcode, 384d66a5066SPeter Wemm &linux_szsigcode, 385d66a5066SPeter Wemm linux_prepsyscall, 3866ead3eddSJohn Dyson "Linux a.out" 387d66a5066SPeter Wemm }; 388e1743d02SSøren Schmidt 389e1743d02SSøren Schmidt struct sysentvec elf_linux_sysvec = { 390e1743d02SSøren Schmidt LINUX_SYS_MAXSYSCALL, 391e1743d02SSøren Schmidt linux_sysent, 392e1743d02SSøren Schmidt 0xff, 393e1743d02SSøren Schmidt NSIG, 394e1743d02SSøren Schmidt bsd_to_linux_signal, 395e1743d02SSøren Schmidt ELAST, 396e1743d02SSøren Schmidt bsd_to_linux_errno, 397e1743d02SSøren Schmidt elf_linux_fixup, 398e1743d02SSøren Schmidt linux_sendsig, 399e1743d02SSøren Schmidt linux_sigcode, 400e1743d02SSøren Schmidt &linux_szsigcode, 401e1743d02SSøren Schmidt linux_prepsyscall, 4026ead3eddSJohn Dyson "Linux ELF" 403e1743d02SSøren Schmidt }; 404e1743d02SSøren Schmidt 4055cf588ebSPeter Wemm /* 4065cf588ebSPeter Wemm * Installed either via SYSINIT() or via LKM stubs. 4075cf588ebSPeter Wemm */ 4085cf588ebSPeter Wemm Elf32_Interp_info linux_interp = { 4095cf588ebSPeter Wemm &elf_linux_sysvec, 4105cf588ebSPeter Wemm "/lib/ld-linux.so.1", 4115cf588ebSPeter Wemm "/compat/linux" 4125cf588ebSPeter Wemm }; 4135cf588ebSPeter Wemm 4145cf588ebSPeter Wemm #ifndef LKM 4155cf588ebSPeter Wemm /* 4165cf588ebSPeter Wemm * XXX: this is WRONG, it needs to be SI_SUB_EXEC, but this is just at the 4175cf588ebSPeter Wemm * "proof of concept" stage and will be fixed shortly 4185cf588ebSPeter Wemm */ 4195cf588ebSPeter Wemm SYSINIT(linuxelf, SI_SUB_VFS, SI_ORDER_ANY, elf_insert_interp, &linux_interp); 4205cf588ebSPeter Wemm #endif 421