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 * 28ecbb00a2SDoug Rabson * $Id: linux_sysvec.c,v 1.29 1998/05/07 00:42:25 eivind Exp $ 29d66a5066SPeter Wemm */ 30d66a5066SPeter Wemm 31d66a5066SPeter Wemm /* XXX we use functions that might not exist. */ 325591b823SEivind Eklund #include "opt_compat.h" 335591b823SEivind Eklund 345591b823SEivind Eklund #ifndef COMPAT_43 355591b823SEivind Eklund #error "Unable to compile Linux-emulator due to missing COMPAT_43 option!" 365591b823SEivind Eklund #endif 37d66a5066SPeter Wemm 38d66a5066SPeter Wemm #include <sys/param.h> 395e26fb6fSJordan K. Hubbard #include <sys/buf.h> 40aad9af2bSBruce Evans #include <sys/proc.h> 41d66a5066SPeter Wemm #include <sys/systm.h> 42d66a5066SPeter Wemm #include <sys/sysent.h> 43d66a5066SPeter Wemm #include <sys/imgact.h> 44e1743d02SSøren Schmidt #include <sys/imgact_elf.h> 45d66a5066SPeter Wemm #include <sys/signalvar.h> 46e1743d02SSøren Schmidt #include <sys/malloc.h> 47d66a5066SPeter Wemm #include <vm/vm.h> 48d66a5066SPeter Wemm #include <vm/vm_param.h> 49d66a5066SPeter Wemm #include <vm/vm_prot.h> 50d66a5066SPeter Wemm #include <vm/vm_page.h> 51d66a5066SPeter Wemm #include <vm/vm_extern.h> 52d66a5066SPeter Wemm #include <sys/exec.h> 535cf588ebSPeter Wemm #include <sys/kernel.h> 54d66a5066SPeter Wemm #include <machine/cpu.h> 55d66a5066SPeter Wemm 56d66a5066SPeter Wemm #include <i386/linux/linux.h> 57d66a5066SPeter Wemm #include <i386/linux/linux_proto.h> 58e1743d02SSøren Schmidt 59ecbb00a2SDoug Rabson static int linux_fixup __P((long **stack_base, 60303b270bSEivind Eklund struct image_params *iparams)); 61ecbb00a2SDoug Rabson static int elf_linux_fixup __P((long **stack_base, 62303b270bSEivind Eklund struct image_params *iparams)); 63303b270bSEivind Eklund static void linux_prepsyscall __P((struct trapframe *tf, int *args, 64303b270bSEivind Eklund u_int *code, caddr_t *params)); 65303b270bSEivind Eklund static void linux_sendsig __P((sig_t catcher, int sig, int mask, 66303b270bSEivind Eklund u_long code)); 67d66a5066SPeter Wemm 68d66a5066SPeter Wemm /* 69d66a5066SPeter Wemm * Linux syscalls return negative errno's, we do positive and map them 70d66a5066SPeter Wemm */ 719d767d02SBruce Evans static int bsd_to_linux_errno[ELAST] = { 72d66a5066SPeter Wemm -0, -1, -2, -3, -4, -5, -6, -7, -8, -9, 73d66a5066SPeter Wemm -10, -35, -12, -13, -14, -15, -16, -17, -18, -19, 74d66a5066SPeter Wemm -20, -21, -22, -23, -24, -25, -26, -27, -28, -29, 75d66a5066SPeter Wemm -30, -31, -32, -33, -34, -11,-115,-114, -88, -89, 76d66a5066SPeter Wemm -90, -91, -92, -93, -94, -95, -96, -97, -98, -99, 77d66a5066SPeter Wemm -100,-101,-102,-103,-104,-105,-106,-107,-108,-109, 78d66a5066SPeter Wemm -110,-111, -40, -36,-112,-113, -39, -11, -87,-122, 79d66a5066SPeter Wemm -116, -66, -6, -6, -6, -6, -6, -37, -38, -9, 80958a0829SSøren Schmidt -6, -43, -42 81d66a5066SPeter Wemm }; 82d66a5066SPeter Wemm 83d66a5066SPeter Wemm int bsd_to_linux_signal[NSIG] = { 84d66a5066SPeter Wemm 0, LINUX_SIGHUP, LINUX_SIGINT, LINUX_SIGQUIT, 85d66a5066SPeter Wemm LINUX_SIGILL, LINUX_SIGTRAP, LINUX_SIGABRT, 0, 86d66a5066SPeter Wemm LINUX_SIGFPE, LINUX_SIGKILL, LINUX_SIGBUS, LINUX_SIGSEGV, 87d66a5066SPeter Wemm 0, LINUX_SIGPIPE, LINUX_SIGALRM, LINUX_SIGTERM, 88d66a5066SPeter Wemm LINUX_SIGURG, LINUX_SIGSTOP, LINUX_SIGTSTP, LINUX_SIGCONT, 89d66a5066SPeter Wemm LINUX_SIGCHLD, LINUX_SIGTTIN, LINUX_SIGTTOU, LINUX_SIGIO, 90d66a5066SPeter Wemm LINUX_SIGXCPU, LINUX_SIGXFSZ, LINUX_SIGVTALRM, LINUX_SIGPROF, 91d66a5066SPeter Wemm LINUX_SIGWINCH, 0, LINUX_SIGUSR1, LINUX_SIGUSR2 92d66a5066SPeter Wemm }; 93d66a5066SPeter Wemm 94d66a5066SPeter Wemm int linux_to_bsd_signal[LINUX_NSIG] = { 95d66a5066SPeter Wemm 0, SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGEMT, 96d66a5066SPeter Wemm SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, 97d66a5066SPeter Wemm SIGBUS, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGIO, 98d66a5066SPeter Wemm SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH, SIGURG, SIGURG, 0 99d66a5066SPeter Wemm }; 100d66a5066SPeter Wemm 101288078beSEivind Eklund /* 102288078beSEivind Eklund * If FreeBSD & Linux have a difference of opinion about what a trap 103288078beSEivind Eklund * means, deal with it here. 104288078beSEivind Eklund */ 105288078beSEivind Eklund static int 106288078beSEivind Eklund translate_traps(int signal, int trap_code) 107288078beSEivind Eklund { 108d563a53aSEivind Eklund if (signal != SIGBUS) 109d563a53aSEivind Eklund return signal; 110288078beSEivind Eklund switch (trap_code) { 111288078beSEivind Eklund case T_PROTFLT: 112288078beSEivind Eklund case T_TSSFLT: 113288078beSEivind Eklund case T_DOUBLEFLT: 114288078beSEivind Eklund case T_PAGEFLT: 115288078beSEivind Eklund return SIGSEGV; 116288078beSEivind Eklund default: 117288078beSEivind Eklund return signal; 118288078beSEivind Eklund } 119288078beSEivind Eklund } 120288078beSEivind Eklund 121303b270bSEivind Eklund static int 122ecbb00a2SDoug Rabson linux_fixup(long **stack_base, struct image_params *imgp) 123d66a5066SPeter Wemm { 124ecbb00a2SDoug Rabson long *argv, *envp; 125d66a5066SPeter Wemm 126d66a5066SPeter Wemm argv = *stack_base; 127d66a5066SPeter Wemm envp = *stack_base + (imgp->argc + 1); 128d66a5066SPeter Wemm (*stack_base)--; 129ecbb00a2SDoug Rabson **stack_base = (long)envp; 130d66a5066SPeter Wemm (*stack_base)--; 131ecbb00a2SDoug Rabson **stack_base = (long)argv; 132d66a5066SPeter Wemm (*stack_base)--; 133ecbb00a2SDoug Rabson **stack_base = (long)imgp->argc; 134e1743d02SSøren Schmidt return 0; 135d66a5066SPeter Wemm } 136d66a5066SPeter Wemm 137303b270bSEivind Eklund static int 138ecbb00a2SDoug Rabson elf_linux_fixup(long **stack_base, struct image_params *imgp) 139e1743d02SSøren Schmidt { 140e1743d02SSøren Schmidt Elf32_Auxargs *args = (Elf32_Auxargs *)imgp->auxargs; 141ecbb00a2SDoug Rabson long *pos; 142d66a5066SPeter Wemm 143e1743d02SSøren Schmidt pos = *stack_base + (imgp->argc + imgp->envc + 2); 144e1743d02SSøren Schmidt 145e1743d02SSøren Schmidt if (args->trace) { 146e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_DEBUG, 1); 147e1743d02SSøren Schmidt } 148e1743d02SSøren Schmidt if (args->execfd != -1) { 149e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); 150e1743d02SSøren Schmidt } 151e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); 152e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_PHENT, args->phent); 153e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum); 154e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz); 155e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); 156e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); 157e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_BASE, args->base); 158e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_cred->p_ruid); 159e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_cred->p_svuid); 160e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_cred->p_rgid); 161e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_cred->p_svgid); 162e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_NULL, 0); 163e1743d02SSøren Schmidt 164e1743d02SSøren Schmidt free(imgp->auxargs, M_TEMP); 165e1743d02SSøren Schmidt imgp->auxargs = NULL; 166e1743d02SSøren Schmidt 167e1743d02SSøren Schmidt (*stack_base)--; 168ecbb00a2SDoug Rabson **stack_base = (long)imgp->argc; 169e1743d02SSøren Schmidt return 0; 170e1743d02SSøren Schmidt } 171d66a5066SPeter Wemm 172d66a5066SPeter Wemm extern int _ucodesel, _udatasel; 173d66a5066SPeter Wemm 174d66a5066SPeter Wemm /* 175d66a5066SPeter Wemm * Send an interrupt to process. 176d66a5066SPeter Wemm * 177d66a5066SPeter Wemm * Stack is set up to allow sigcode stored 178d66a5066SPeter Wemm * in u. to call routine, followed by kcall 179d66a5066SPeter Wemm * to sigreturn routine below. After sigreturn 180d66a5066SPeter Wemm * resets the signal mask, the stack, and the 181d66a5066SPeter Wemm * frame pointer, it returns to the user 182d66a5066SPeter Wemm * specified pc, psl. 183d66a5066SPeter Wemm */ 184d66a5066SPeter Wemm 185303b270bSEivind Eklund static void 186b36546f6SPeter Wemm linux_sendsig(sig_t catcher, int sig, int mask, u_long code) 187d66a5066SPeter Wemm { 188d66a5066SPeter Wemm register struct proc *p = curproc; 189213fdd80SPeter Wemm register struct trapframe *regs; 190d66a5066SPeter Wemm struct linux_sigframe *fp, frame; 191d66a5066SPeter Wemm struct sigacts *psp = p->p_sigacts; 192d66a5066SPeter Wemm int oonstack; 193d66a5066SPeter Wemm 194d66a5066SPeter Wemm regs = p->p_md.md_regs; 195d66a5066SPeter Wemm oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK; 196d66a5066SPeter Wemm 197d66a5066SPeter Wemm #ifdef DEBUG 198b36546f6SPeter Wemm printf("Linux-emul(%d): linux_sendsig(%8x, %d, %d, %ld)\n", 199d66a5066SPeter Wemm p->p_pid, catcher, sig, mask, code); 200d66a5066SPeter Wemm #endif 201d66a5066SPeter Wemm /* 202d66a5066SPeter Wemm * Allocate space for the signal handler context. 203d66a5066SPeter Wemm */ 204d66a5066SPeter Wemm if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack && 205d66a5066SPeter Wemm (psp->ps_sigonstack & sigmask(sig))) { 206d66a5066SPeter Wemm fp = (struct linux_sigframe *)(psp->ps_sigstk.ss_sp + 207d66a5066SPeter Wemm psp->ps_sigstk.ss_size - sizeof(struct linux_sigframe)); 208d66a5066SPeter Wemm psp->ps_sigstk.ss_flags |= SS_ONSTACK; 209d66a5066SPeter Wemm } else { 210213fdd80SPeter Wemm fp = (struct linux_sigframe *)regs->tf_esp - 1; 211d66a5066SPeter Wemm } 212d66a5066SPeter Wemm 213d66a5066SPeter Wemm /* 214d66a5066SPeter Wemm * grow() will return FALSE if the fp will not fit inside the stack 215d66a5066SPeter Wemm * and the stack can not be grown. useracc will return FALSE 216d66a5066SPeter Wemm * if access is denied. 217d66a5066SPeter Wemm */ 218d66a5066SPeter Wemm if ((grow(p, (int)fp) == FALSE) || 219d66a5066SPeter Wemm (useracc((caddr_t)fp, sizeof (struct linux_sigframe), B_WRITE) == FALSE)) { 220d66a5066SPeter Wemm /* 221d66a5066SPeter Wemm * Process has trashed its stack; give it an illegal 222d66a5066SPeter Wemm * instruction to halt it in its tracks. 223d66a5066SPeter Wemm */ 224d66a5066SPeter Wemm SIGACTION(p, SIGILL) = SIG_DFL; 225d66a5066SPeter Wemm sig = sigmask(SIGILL); 226d66a5066SPeter Wemm p->p_sigignore &= ~sig; 227d66a5066SPeter Wemm p->p_sigcatch &= ~sig; 228d66a5066SPeter Wemm p->p_sigmask &= ~sig; 229d66a5066SPeter Wemm psignal(p, SIGILL); 230d66a5066SPeter Wemm return; 231d66a5066SPeter Wemm } 232d66a5066SPeter Wemm 233d66a5066SPeter Wemm /* 234d66a5066SPeter Wemm * Build the argument list for the signal handler. 235d66a5066SPeter Wemm */ 236d66a5066SPeter Wemm if (p->p_sysent->sv_sigtbl) { 237d66a5066SPeter Wemm if (sig < p->p_sysent->sv_sigsize) 238d66a5066SPeter Wemm sig = p->p_sysent->sv_sigtbl[sig]; 239d66a5066SPeter Wemm else 240d66a5066SPeter Wemm sig = p->p_sysent->sv_sigsize + 1; 241d66a5066SPeter Wemm } 242d66a5066SPeter Wemm 243d66a5066SPeter Wemm frame.sf_handler = catcher; 244d66a5066SPeter Wemm frame.sf_sig = sig; 245d66a5066SPeter Wemm 246d66a5066SPeter Wemm /* 247d66a5066SPeter Wemm * Build the signal context to be used by sigreturn. 248d66a5066SPeter Wemm */ 249d66a5066SPeter Wemm frame.sf_sc.sc_mask = mask; 250d66a5066SPeter Wemm __asm("movl %%gs,%w0" : "=r" (frame.sf_sc.sc_gs)); 251d66a5066SPeter Wemm __asm("movl %%fs,%w0" : "=r" (frame.sf_sc.sc_fs)); 252213fdd80SPeter Wemm frame.sf_sc.sc_es = regs->tf_es; 253213fdd80SPeter Wemm frame.sf_sc.sc_ds = regs->tf_ds; 254213fdd80SPeter Wemm frame.sf_sc.sc_edi = regs->tf_edi; 255213fdd80SPeter Wemm frame.sf_sc.sc_esi = regs->tf_esi; 256213fdd80SPeter Wemm frame.sf_sc.sc_ebp = regs->tf_ebp; 257213fdd80SPeter Wemm frame.sf_sc.sc_ebx = regs->tf_ebx; 258213fdd80SPeter Wemm frame.sf_sc.sc_edx = regs->tf_edx; 259213fdd80SPeter Wemm frame.sf_sc.sc_ecx = regs->tf_ecx; 260213fdd80SPeter Wemm frame.sf_sc.sc_eax = regs->tf_eax; 261213fdd80SPeter Wemm frame.sf_sc.sc_eip = regs->tf_eip; 262213fdd80SPeter Wemm frame.sf_sc.sc_cs = regs->tf_cs; 263213fdd80SPeter Wemm frame.sf_sc.sc_eflags = regs->tf_eflags; 264213fdd80SPeter Wemm frame.sf_sc.sc_esp_at_signal = regs->tf_esp; 265213fdd80SPeter Wemm frame.sf_sc.sc_ss = regs->tf_ss; 266213fdd80SPeter Wemm frame.sf_sc.sc_err = regs->tf_err; 267d66a5066SPeter Wemm frame.sf_sc.sc_trapno = code; /* XXX ???? */ 268d66a5066SPeter Wemm 269d66a5066SPeter Wemm if (copyout(&frame, fp, sizeof(frame)) != 0) { 270d66a5066SPeter Wemm /* 271d66a5066SPeter Wemm * Process has trashed its stack; give it an illegal 272d66a5066SPeter Wemm * instruction to halt it in its tracks. 273d66a5066SPeter Wemm */ 274d66a5066SPeter Wemm sigexit(p, SIGILL); 275d66a5066SPeter Wemm /* NOTREACHED */ 276d66a5066SPeter Wemm } 277d66a5066SPeter Wemm 278d66a5066SPeter Wemm /* 279d66a5066SPeter Wemm * Build context to run handler in. 280d66a5066SPeter Wemm */ 281213fdd80SPeter Wemm regs->tf_esp = (int)fp; 282213fdd80SPeter Wemm regs->tf_eip = (int)(((char *)PS_STRINGS) - *(p->p_sysent->sv_szsigcode)); 283213fdd80SPeter Wemm regs->tf_eflags &= ~PSL_VM; 284213fdd80SPeter Wemm regs->tf_cs = _ucodesel; 285213fdd80SPeter Wemm regs->tf_ds = _udatasel; 286213fdd80SPeter Wemm regs->tf_es = _udatasel; 287213fdd80SPeter Wemm regs->tf_ss = _udatasel; 288d66a5066SPeter Wemm } 289d66a5066SPeter Wemm 290d66a5066SPeter Wemm /* 291d66a5066SPeter Wemm * System call to cleanup state after a signal 292d66a5066SPeter Wemm * has been taken. Reset signal mask and 293d66a5066SPeter Wemm * stack state from context left by sendsig (above). 294d66a5066SPeter Wemm * Return to previous pc and psl as specified by 295d66a5066SPeter Wemm * context left by sendsig. Check carefully to 296d66a5066SPeter Wemm * make sure that the user has not modified the 297d66a5066SPeter Wemm * psl to gain improper privileges or to cause 298d66a5066SPeter Wemm * a machine fault. 299d66a5066SPeter Wemm */ 300d66a5066SPeter Wemm int 301cb226aaaSPoul-Henning Kamp linux_sigreturn(p, args) 302d66a5066SPeter Wemm struct proc *p; 303d66a5066SPeter Wemm struct linux_sigreturn_args *args; 304d66a5066SPeter Wemm { 305d66a5066SPeter Wemm struct linux_sigcontext *scp, context; 306213fdd80SPeter Wemm register struct trapframe *regs; 307d66a5066SPeter Wemm int eflags; 308d66a5066SPeter Wemm 309d66a5066SPeter Wemm regs = p->p_md.md_regs; 310d66a5066SPeter Wemm 311d66a5066SPeter Wemm #ifdef DEBUG 312d66a5066SPeter Wemm printf("Linux-emul(%d): linux_sigreturn(%8x)\n", p->p_pid, args->scp); 313d66a5066SPeter Wemm #endif 314d66a5066SPeter Wemm /* 315d66a5066SPeter Wemm * The trampoline code hands us the context. 316d66a5066SPeter Wemm * It is unsafe to keep track of it ourselves, in the event that a 317d66a5066SPeter Wemm * program jumps out of a signal handler. 318d66a5066SPeter Wemm */ 319ecbb00a2SDoug Rabson scp = SCARG(args,scp); 320d66a5066SPeter Wemm if (copyin((caddr_t)scp, &context, sizeof(*scp)) != 0) 321d66a5066SPeter Wemm return (EFAULT); 322d66a5066SPeter Wemm 323d66a5066SPeter Wemm /* 324d66a5066SPeter Wemm * Check for security violations. 325d66a5066SPeter Wemm */ 326d66a5066SPeter Wemm #define EFLAGS_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) 327d66a5066SPeter Wemm eflags = context.sc_eflags; 328d66a5066SPeter Wemm /* 329d66a5066SPeter Wemm * XXX do allow users to change the privileged flag PSL_RF. The 330d66a5066SPeter Wemm * cpu sets PSL_RF in tf_eflags for faults. Debuggers should 331d66a5066SPeter Wemm * sometimes set it there too. tf_eflags is kept in the signal 332d66a5066SPeter Wemm * context during signal handling and there is no other place 333d66a5066SPeter Wemm * to remember it, so the PSL_RF bit may be corrupted by the 334d66a5066SPeter Wemm * signal handler without us knowing. Corruption of the PSL_RF 335d66a5066SPeter Wemm * bit at worst causes one more or one less debugger trap, so 336d66a5066SPeter Wemm * allowing it is fairly harmless. 337d66a5066SPeter Wemm */ 338213fdd80SPeter Wemm if (!EFLAGS_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) { 339d66a5066SPeter Wemm return(EINVAL); 340d66a5066SPeter Wemm } 341d66a5066SPeter Wemm 342d66a5066SPeter Wemm /* 343d66a5066SPeter Wemm * Don't allow users to load a valid privileged %cs. Let the 344d66a5066SPeter Wemm * hardware check for invalid selectors, excess privilege in 345d66a5066SPeter Wemm * other selectors, invalid %eip's and invalid %esp's. 346d66a5066SPeter Wemm */ 34740d50994SPhilippe Charnier #define CS_SECURE(cs) (ISPL(cs) == SEL_UPL) 348d66a5066SPeter Wemm if (!CS_SECURE(context.sc_cs)) { 349d66a5066SPeter Wemm trapsignal(p, SIGBUS, T_PROTFLT); 350d66a5066SPeter Wemm return(EINVAL); 351d66a5066SPeter Wemm } 352d66a5066SPeter Wemm 353d66a5066SPeter Wemm p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK; 354d66a5066SPeter Wemm p->p_sigmask = context.sc_mask &~ 355d66a5066SPeter Wemm (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP)); 356d66a5066SPeter Wemm /* 357d66a5066SPeter Wemm * Restore signal context. 358d66a5066SPeter Wemm */ 359d66a5066SPeter Wemm /* %fs and %gs were restored by the trampoline. */ 360213fdd80SPeter Wemm regs->tf_es = context.sc_es; 361213fdd80SPeter Wemm regs->tf_ds = context.sc_ds; 362213fdd80SPeter Wemm regs->tf_edi = context.sc_edi; 363213fdd80SPeter Wemm regs->tf_esi = context.sc_esi; 364213fdd80SPeter Wemm regs->tf_ebp = context.sc_ebp; 365213fdd80SPeter Wemm regs->tf_ebx = context.sc_ebx; 366213fdd80SPeter Wemm regs->tf_edx = context.sc_edx; 367213fdd80SPeter Wemm regs->tf_ecx = context.sc_ecx; 368213fdd80SPeter Wemm regs->tf_eax = context.sc_eax; 369213fdd80SPeter Wemm regs->tf_eip = context.sc_eip; 370213fdd80SPeter Wemm regs->tf_cs = context.sc_cs; 371213fdd80SPeter Wemm regs->tf_eflags = eflags; 372213fdd80SPeter Wemm regs->tf_esp = context.sc_esp_at_signal; 373213fdd80SPeter Wemm regs->tf_ss = context.sc_ss; 374d66a5066SPeter Wemm 375d66a5066SPeter Wemm return (EJUSTRETURN); 376d66a5066SPeter Wemm } 377d66a5066SPeter Wemm 378303b270bSEivind Eklund static void 379d66a5066SPeter Wemm linux_prepsyscall(struct trapframe *tf, int *args, u_int *code, caddr_t *params) 380d66a5066SPeter Wemm { 381d66a5066SPeter Wemm args[0] = tf->tf_ebx; 382d66a5066SPeter Wemm args[1] = tf->tf_ecx; 383d66a5066SPeter Wemm args[2] = tf->tf_edx; 384d66a5066SPeter Wemm args[3] = tf->tf_esi; 385d66a5066SPeter Wemm args[4] = tf->tf_edi; 386d66a5066SPeter Wemm *params = NULL; /* no copyin */ 387d66a5066SPeter Wemm } 388d66a5066SPeter Wemm 389d66a5066SPeter Wemm struct sysentvec linux_sysvec = { 390e1743d02SSøren Schmidt LINUX_SYS_MAXSYSCALL, 391d66a5066SPeter Wemm linux_sysent, 392d66a5066SPeter Wemm 0xff, 393d66a5066SPeter Wemm NSIG, 394d66a5066SPeter Wemm bsd_to_linux_signal, 395d66a5066SPeter Wemm ELAST, 396d66a5066SPeter Wemm bsd_to_linux_errno, 397288078beSEivind Eklund translate_traps, 398d66a5066SPeter Wemm linux_fixup, 399d66a5066SPeter Wemm linux_sendsig, 400d66a5066SPeter Wemm linux_sigcode, 401d66a5066SPeter Wemm &linux_szsigcode, 402d66a5066SPeter Wemm linux_prepsyscall, 4036ead3eddSJohn Dyson "Linux a.out" 404d66a5066SPeter Wemm }; 405e1743d02SSøren Schmidt 406e1743d02SSøren Schmidt struct sysentvec elf_linux_sysvec = { 407e1743d02SSøren Schmidt LINUX_SYS_MAXSYSCALL, 408e1743d02SSøren Schmidt linux_sysent, 409e1743d02SSøren Schmidt 0xff, 410e1743d02SSøren Schmidt NSIG, 411e1743d02SSøren Schmidt bsd_to_linux_signal, 412e1743d02SSøren Schmidt ELAST, 413e1743d02SSøren Schmidt bsd_to_linux_errno, 414288078beSEivind Eklund translate_traps, 415e1743d02SSøren Schmidt elf_linux_fixup, 416e1743d02SSøren Schmidt linux_sendsig, 417e1743d02SSøren Schmidt linux_sigcode, 418e1743d02SSøren Schmidt &linux_szsigcode, 419e1743d02SSøren Schmidt linux_prepsyscall, 4206ead3eddSJohn Dyson "Linux ELF" 421e1743d02SSøren Schmidt }; 422e1743d02SSøren Schmidt 4235cf588ebSPeter Wemm /* 4245cf588ebSPeter Wemm * Installed either via SYSINIT() or via LKM stubs. 4255cf588ebSPeter Wemm */ 426d131a704SEivind Eklund Elf32_Brandinfo linux_brand = { 427ea5a2b2eSSøren Schmidt "Linux", 428ea5a2b2eSSøren Schmidt "/compat/linux", 4295cf588ebSPeter Wemm "/lib/ld-linux.so.1", 430ea5a2b2eSSøren Schmidt &elf_linux_sysvec 4315cf588ebSPeter Wemm }; 4325cf588ebSPeter Wemm 4335cf588ebSPeter Wemm #ifndef LKM 4345cf588ebSPeter Wemm /* 4355cf588ebSPeter Wemm * XXX: this is WRONG, it needs to be SI_SUB_EXEC, but this is just at the 4365cf588ebSPeter Wemm * "proof of concept" stage and will be fixed shortly 4375cf588ebSPeter Wemm */ 43817bd614dSBruce Evans static void linux_elf_init __P((void *dummy)); 43917bd614dSBruce Evans 440d30ea4f5SPeter Wemm static void 441d30ea4f5SPeter Wemm linux_elf_init(dummy) 442d30ea4f5SPeter Wemm void *dummy; 443d30ea4f5SPeter Wemm { 444d30ea4f5SPeter Wemm if (elf_insert_brand_entry(&linux_brand) < 0) 445d30ea4f5SPeter Wemm printf("cannot insert Linux elf brand handler\n"); 446d30ea4f5SPeter Wemm else if (bootverbose) 447d30ea4f5SPeter Wemm printf("Linux-ELF exec handler installed\n"); 448d30ea4f5SPeter Wemm } 449d30ea4f5SPeter Wemm 450d30ea4f5SPeter Wemm SYSINIT(linuxelf, SI_SUB_VFS, SI_ORDER_ANY, linux_elf_init, NULL); 4515cf588ebSPeter Wemm #endif 452