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 * 28c3aac50fSPeter Wemm * $FreeBSD$ 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> 3975f83872SPeter Wemm #include <sys/systm.h> 405e26fb6fSJordan K. Hubbard #include <sys/buf.h> 41aad9af2bSBruce Evans #include <sys/proc.h> 42d66a5066SPeter Wemm #include <sys/sysent.h> 43d66a5066SPeter Wemm #include <sys/imgact.h> 4422d4b0fbSJohn Polstra #include <sys/imgact_aout.h> 45e1743d02SSøren Schmidt #include <sys/imgact_elf.h> 46d66a5066SPeter Wemm #include <sys/signalvar.h> 47e1743d02SSøren Schmidt #include <sys/malloc.h> 48d66a5066SPeter Wemm #include <vm/vm.h> 49d66a5066SPeter Wemm #include <vm/vm_param.h> 50d66a5066SPeter Wemm #include <vm/vm_prot.h> 51d66a5066SPeter Wemm #include <vm/vm_page.h> 52d66a5066SPeter Wemm #include <vm/vm_extern.h> 53d66a5066SPeter Wemm #include <sys/exec.h> 545cf588ebSPeter Wemm #include <sys/kernel.h> 55aa855a59SPeter Wemm #include <sys/module.h> 56d66a5066SPeter Wemm #include <machine/cpu.h> 57d66a5066SPeter Wemm 58d66a5066SPeter Wemm #include <i386/linux/linux.h> 59d66a5066SPeter Wemm #include <i386/linux/linux_proto.h> 60e1743d02SSøren Schmidt 61ecbb00a2SDoug Rabson static int linux_fixup __P((long **stack_base, 62303b270bSEivind Eklund struct image_params *iparams)); 63ecbb00a2SDoug Rabson static int elf_linux_fixup __P((long **stack_base, 64303b270bSEivind Eklund struct image_params *iparams)); 65303b270bSEivind Eklund static void linux_prepsyscall __P((struct trapframe *tf, int *args, 66303b270bSEivind Eklund u_int *code, caddr_t *params)); 67956d3333SMarcel Moolenaar static void linux_sendsig __P((sig_t catcher, int sig, sigset_t *mask, 68303b270bSEivind Eklund u_long code)); 69d66a5066SPeter Wemm 70d66a5066SPeter Wemm /* 71d66a5066SPeter Wemm * Linux syscalls return negative errno's, we do positive and map them 72d66a5066SPeter Wemm */ 7385f118c8SDmitrij Tejblum static int bsd_to_linux_errno[ELAST + 1] = { 74d66a5066SPeter Wemm -0, -1, -2, -3, -4, -5, -6, -7, -8, -9, 75d66a5066SPeter Wemm -10, -35, -12, -13, -14, -15, -16, -17, -18, -19, 76d66a5066SPeter Wemm -20, -21, -22, -23, -24, -25, -26, -27, -28, -29, 77d66a5066SPeter Wemm -30, -31, -32, -33, -34, -11,-115,-114, -88, -89, 78d66a5066SPeter Wemm -90, -91, -92, -93, -94, -95, -96, -97, -98, -99, 79d66a5066SPeter Wemm -100,-101,-102,-103,-104,-105,-106,-107,-108,-109, 80d66a5066SPeter Wemm -110,-111, -40, -36,-112,-113, -39, -11, -87,-122, 81d66a5066SPeter Wemm -116, -66, -6, -6, -6, -6, -6, -37, -38, -9, 8285f118c8SDmitrij Tejblum -6, -6, -43, -42, -75, -6, -84 83d66a5066SPeter Wemm }; 84d66a5066SPeter Wemm 85956d3333SMarcel Moolenaar int bsd_to_linux_signal[LINUX_SIGTBLSZ] = { 86956d3333SMarcel Moolenaar LINUX_SIGHUP, LINUX_SIGINT, LINUX_SIGQUIT, LINUX_SIGILL, 87956d3333SMarcel Moolenaar LINUX_SIGTRAP, LINUX_SIGABRT, 0, LINUX_SIGFPE, 88956d3333SMarcel Moolenaar LINUX_SIGKILL, LINUX_SIGBUS, LINUX_SIGSEGV, 0, 89956d3333SMarcel Moolenaar LINUX_SIGPIPE, LINUX_SIGALRM, LINUX_SIGTERM, LINUX_SIGURG, 90956d3333SMarcel Moolenaar LINUX_SIGSTOP, LINUX_SIGTSTP, LINUX_SIGCONT, LINUX_SIGCHLD, 91956d3333SMarcel Moolenaar LINUX_SIGTTIN, LINUX_SIGTTOU, LINUX_SIGIO, LINUX_SIGXCPU, 92956d3333SMarcel Moolenaar LINUX_SIGXFSZ, LINUX_SIGVTALRM, LINUX_SIGPROF, LINUX_SIGWINCH, 93956d3333SMarcel Moolenaar 0, LINUX_SIGUSR1, LINUX_SIGUSR2 94d66a5066SPeter Wemm }; 95d66a5066SPeter Wemm 96956d3333SMarcel Moolenaar int linux_to_bsd_signal[LINUX_SIGTBLSZ] = { 97956d3333SMarcel Moolenaar SIGHUP, SIGINT, SIGQUIT, SIGILL, 98956d3333SMarcel Moolenaar SIGTRAP, SIGABRT, SIGBUS, SIGFPE, 99956d3333SMarcel Moolenaar SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, 100956d3333SMarcel Moolenaar SIGPIPE, SIGALRM, SIGTERM, SIGBUS, 101956d3333SMarcel Moolenaar SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, 102956d3333SMarcel Moolenaar SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, 103956d3333SMarcel Moolenaar SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH, 104956d3333SMarcel Moolenaar SIGIO, SIGURG, 0 105d66a5066SPeter Wemm }; 106d66a5066SPeter Wemm 107288078beSEivind Eklund /* 108288078beSEivind Eklund * If FreeBSD & Linux have a difference of opinion about what a trap 109288078beSEivind Eklund * means, deal with it here. 110288078beSEivind Eklund */ 111288078beSEivind Eklund static int 112288078beSEivind Eklund translate_traps(int signal, int trap_code) 113288078beSEivind Eklund { 114d563a53aSEivind Eklund if (signal != SIGBUS) 115d563a53aSEivind Eklund return signal; 116288078beSEivind Eklund switch (trap_code) { 117288078beSEivind Eklund case T_PROTFLT: 118288078beSEivind Eklund case T_TSSFLT: 119288078beSEivind Eklund case T_DOUBLEFLT: 120288078beSEivind Eklund case T_PAGEFLT: 121288078beSEivind Eklund return SIGSEGV; 122288078beSEivind Eklund default: 123288078beSEivind Eklund return signal; 124288078beSEivind Eklund } 125288078beSEivind Eklund } 126288078beSEivind Eklund 127303b270bSEivind Eklund static int 128ecbb00a2SDoug Rabson linux_fixup(long **stack_base, struct image_params *imgp) 129d66a5066SPeter Wemm { 130ecbb00a2SDoug Rabson long *argv, *envp; 131d66a5066SPeter Wemm 132d66a5066SPeter Wemm argv = *stack_base; 133d66a5066SPeter Wemm envp = *stack_base + (imgp->argc + 1); 134d66a5066SPeter Wemm (*stack_base)--; 13586a14a7aSBruce Evans **stack_base = (intptr_t)(void *)envp; 136d66a5066SPeter Wemm (*stack_base)--; 13786a14a7aSBruce Evans **stack_base = (intptr_t)(void *)argv; 138d66a5066SPeter Wemm (*stack_base)--; 13986a14a7aSBruce Evans **stack_base = imgp->argc; 140e1743d02SSøren Schmidt return 0; 141d66a5066SPeter Wemm } 142d66a5066SPeter Wemm 143303b270bSEivind Eklund static int 144ecbb00a2SDoug Rabson elf_linux_fixup(long **stack_base, struct image_params *imgp) 145e1743d02SSøren Schmidt { 146e1743d02SSøren Schmidt Elf32_Auxargs *args = (Elf32_Auxargs *)imgp->auxargs; 147ecbb00a2SDoug Rabson long *pos; 148d66a5066SPeter Wemm 149e1743d02SSøren Schmidt pos = *stack_base + (imgp->argc + imgp->envc + 2); 150e1743d02SSøren Schmidt 151e1743d02SSøren Schmidt if (args->trace) { 152e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_DEBUG, 1); 153e1743d02SSøren Schmidt } 154e1743d02SSøren Schmidt if (args->execfd != -1) { 155e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); 156e1743d02SSøren Schmidt } 157e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); 158e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_PHENT, args->phent); 159e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum); 160e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz); 161e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); 162e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); 163e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_BASE, args->base); 164e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_cred->p_ruid); 165e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_cred->p_svuid); 166e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_cred->p_rgid); 167e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_cred->p_svgid); 168e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_NULL, 0); 169e1743d02SSøren Schmidt 170e1743d02SSøren Schmidt free(imgp->auxargs, M_TEMP); 171e1743d02SSøren Schmidt imgp->auxargs = NULL; 172e1743d02SSøren Schmidt 173e1743d02SSøren Schmidt (*stack_base)--; 174ecbb00a2SDoug Rabson **stack_base = (long)imgp->argc; 175e1743d02SSøren Schmidt return 0; 176e1743d02SSøren Schmidt } 177d66a5066SPeter Wemm 178d66a5066SPeter Wemm extern int _ucodesel, _udatasel; 179d66a5066SPeter Wemm 180d66a5066SPeter Wemm /* 181d66a5066SPeter Wemm * Send an interrupt to process. 182d66a5066SPeter Wemm * 183d66a5066SPeter Wemm * Stack is set up to allow sigcode stored 184d66a5066SPeter Wemm * in u. to call routine, followed by kcall 185d66a5066SPeter Wemm * to sigreturn routine below. After sigreturn 186d66a5066SPeter Wemm * resets the signal mask, the stack, and the 187d66a5066SPeter Wemm * frame pointer, it returns to the user 188d66a5066SPeter Wemm * specified pc, psl. 189d66a5066SPeter Wemm */ 190d66a5066SPeter Wemm 191303b270bSEivind Eklund static void 192956d3333SMarcel Moolenaar linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) 193d66a5066SPeter Wemm { 194d66a5066SPeter Wemm register struct proc *p = curproc; 195213fdd80SPeter Wemm register struct trapframe *regs; 196d66a5066SPeter Wemm struct linux_sigframe *fp, frame; 197d66a5066SPeter Wemm struct sigacts *psp = p->p_sigacts; 198d66a5066SPeter Wemm int oonstack; 199d66a5066SPeter Wemm 200d66a5066SPeter Wemm regs = p->p_md.md_regs; 201645682fdSLuoqi Chen oonstack = p->p_sigstk.ss_flags & SS_ONSTACK; 202d66a5066SPeter Wemm 203d66a5066SPeter Wemm #ifdef DEBUG 204956d3333SMarcel Moolenaar printf("Linux-emul(%ld): linux_sendsig(%p, %d, %p, %lu)\n", 205956d3333SMarcel Moolenaar (long)p->p_pid, catcher, sig, (void*)mask, code); 206d66a5066SPeter Wemm #endif 207d66a5066SPeter Wemm /* 208d66a5066SPeter Wemm * Allocate space for the signal handler context. 209d66a5066SPeter Wemm */ 210645682fdSLuoqi Chen if ((p->p_flag & P_ALTSTACK) && !oonstack && 211956d3333SMarcel Moolenaar SIGISMEMBER(psp->ps_sigonstack, sig)) { 212645682fdSLuoqi Chen fp = (struct linux_sigframe *)(p->p_sigstk.ss_sp + 213645682fdSLuoqi Chen p->p_sigstk.ss_size - sizeof(struct linux_sigframe)); 214645682fdSLuoqi Chen p->p_sigstk.ss_flags |= SS_ONSTACK; 215d66a5066SPeter Wemm } else { 216213fdd80SPeter Wemm fp = (struct linux_sigframe *)regs->tf_esp - 1; 217d66a5066SPeter Wemm } 218d66a5066SPeter Wemm 219d66a5066SPeter Wemm /* 220d66a5066SPeter Wemm * grow() will return FALSE if the fp will not fit inside the stack 221d66a5066SPeter Wemm * and the stack can not be grown. useracc will return FALSE 222d66a5066SPeter Wemm * if access is denied. 223d66a5066SPeter Wemm */ 2246626c604SJulian Elischer if ((grow_stack (p, (int)fp) == FALSE) || 225d66a5066SPeter Wemm (useracc((caddr_t)fp, sizeof (struct linux_sigframe), B_WRITE) == FALSE)) { 226d66a5066SPeter Wemm /* 227d66a5066SPeter Wemm * Process has trashed its stack; give it an illegal 228d66a5066SPeter Wemm * instruction to halt it in its tracks. 229d66a5066SPeter Wemm */ 230d66a5066SPeter Wemm SIGACTION(p, SIGILL) = SIG_DFL; 231956d3333SMarcel Moolenaar SIGDELSET(p->p_sigignore, SIGILL); 232956d3333SMarcel Moolenaar SIGDELSET(p->p_sigcatch, SIGILL); 233956d3333SMarcel Moolenaar SIGDELSET(p->p_sigmask, SIGILL); 234d66a5066SPeter Wemm psignal(p, SIGILL); 235d66a5066SPeter Wemm return; 236d66a5066SPeter Wemm } 237d66a5066SPeter Wemm 238d66a5066SPeter Wemm /* 239d66a5066SPeter Wemm * Build the argument list for the signal handler. 240d66a5066SPeter Wemm */ 241956d3333SMarcel Moolenaar if (p->p_sysent->sv_sigtbl) 242956d3333SMarcel Moolenaar if (sig <= p->p_sysent->sv_sigsize) 243956d3333SMarcel Moolenaar sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 244d66a5066SPeter Wemm 245d66a5066SPeter Wemm frame.sf_handler = catcher; 246d66a5066SPeter Wemm frame.sf_sig = sig; 247d66a5066SPeter Wemm 248d66a5066SPeter Wemm /* 249d66a5066SPeter Wemm * Build the signal context to be used by sigreturn. 250d66a5066SPeter Wemm */ 251956d3333SMarcel Moolenaar frame.sf_sc.sc_mask = mask->__bits[0]; 2525206bca1SLuoqi Chen frame.sf_sc.sc_gs = rgs(); 2535206bca1SLuoqi Chen frame.sf_sc.sc_fs = regs->tf_fs; 254213fdd80SPeter Wemm frame.sf_sc.sc_es = regs->tf_es; 255213fdd80SPeter Wemm frame.sf_sc.sc_ds = regs->tf_ds; 256213fdd80SPeter Wemm frame.sf_sc.sc_edi = regs->tf_edi; 257213fdd80SPeter Wemm frame.sf_sc.sc_esi = regs->tf_esi; 258213fdd80SPeter Wemm frame.sf_sc.sc_ebp = regs->tf_ebp; 259213fdd80SPeter Wemm frame.sf_sc.sc_ebx = regs->tf_ebx; 260213fdd80SPeter Wemm frame.sf_sc.sc_edx = regs->tf_edx; 261213fdd80SPeter Wemm frame.sf_sc.sc_ecx = regs->tf_ecx; 262213fdd80SPeter Wemm frame.sf_sc.sc_eax = regs->tf_eax; 263213fdd80SPeter Wemm frame.sf_sc.sc_eip = regs->tf_eip; 264213fdd80SPeter Wemm frame.sf_sc.sc_cs = regs->tf_cs; 265213fdd80SPeter Wemm frame.sf_sc.sc_eflags = regs->tf_eflags; 266213fdd80SPeter Wemm frame.sf_sc.sc_esp_at_signal = regs->tf_esp; 267213fdd80SPeter Wemm frame.sf_sc.sc_ss = regs->tf_ss; 268213fdd80SPeter Wemm frame.sf_sc.sc_err = regs->tf_err; 269d66a5066SPeter Wemm frame.sf_sc.sc_trapno = code; /* XXX ???? */ 270d66a5066SPeter Wemm 271d66a5066SPeter Wemm if (copyout(&frame, fp, sizeof(frame)) != 0) { 272d66a5066SPeter Wemm /* 273d66a5066SPeter Wemm * Process has trashed its stack; give it an illegal 274d66a5066SPeter Wemm * instruction to halt it in its tracks. 275d66a5066SPeter Wemm */ 276d66a5066SPeter Wemm sigexit(p, SIGILL); 277d66a5066SPeter Wemm /* NOTREACHED */ 278d66a5066SPeter Wemm } 279d66a5066SPeter Wemm 280d66a5066SPeter Wemm /* 281d66a5066SPeter Wemm * Build context to run handler in. 282d66a5066SPeter Wemm */ 283213fdd80SPeter Wemm regs->tf_esp = (int)fp; 2844c56fcdeSBruce Evans regs->tf_eip = PS_STRINGS - *(p->p_sysent->sv_szsigcode); 285213fdd80SPeter Wemm regs->tf_eflags &= ~PSL_VM; 286213fdd80SPeter Wemm regs->tf_cs = _ucodesel; 287213fdd80SPeter Wemm regs->tf_ds = _udatasel; 288213fdd80SPeter Wemm regs->tf_es = _udatasel; 2895206bca1SLuoqi Chen regs->tf_fs = _udatasel; 290645682fdSLuoqi Chen load_gs(_udatasel); 291213fdd80SPeter Wemm regs->tf_ss = _udatasel; 292d66a5066SPeter Wemm } 293d66a5066SPeter Wemm 294d66a5066SPeter Wemm /* 295d66a5066SPeter Wemm * System call to cleanup state after a signal 296d66a5066SPeter Wemm * has been taken. Reset signal mask and 297d66a5066SPeter Wemm * stack state from context left by sendsig (above). 298d66a5066SPeter Wemm * Return to previous pc and psl as specified by 299d66a5066SPeter Wemm * context left by sendsig. Check carefully to 300d66a5066SPeter Wemm * make sure that the user has not modified the 301d66a5066SPeter Wemm * psl to gain improper privileges or to cause 302d66a5066SPeter Wemm * a machine fault. 303d66a5066SPeter Wemm */ 304d66a5066SPeter Wemm int 305cb226aaaSPoul-Henning Kamp linux_sigreturn(p, args) 306d66a5066SPeter Wemm struct proc *p; 307d66a5066SPeter Wemm struct linux_sigreturn_args *args; 308d66a5066SPeter Wemm { 309d66a5066SPeter Wemm struct linux_sigcontext *scp, context; 310213fdd80SPeter Wemm register struct trapframe *regs; 311d66a5066SPeter Wemm int eflags; 312d66a5066SPeter Wemm 313d66a5066SPeter Wemm regs = p->p_md.md_regs; 314d66a5066SPeter Wemm 315d66a5066SPeter Wemm #ifdef DEBUG 316e4e6ae13SBruce Evans printf("Linux-emul(%ld): linux_sigreturn(%p)\n", 317e4e6ae13SBruce Evans (long)p->p_pid, (void *)args->scp); 318d66a5066SPeter Wemm #endif 319d66a5066SPeter Wemm /* 320d66a5066SPeter Wemm * The trampoline code hands us the context. 321d66a5066SPeter Wemm * It is unsafe to keep track of it ourselves, in the event that a 322d66a5066SPeter Wemm * program jumps out of a signal handler. 323d66a5066SPeter Wemm */ 324ecbb00a2SDoug Rabson scp = SCARG(args,scp); 325d66a5066SPeter Wemm if (copyin((caddr_t)scp, &context, sizeof(*scp)) != 0) 326d66a5066SPeter Wemm return (EFAULT); 327d66a5066SPeter Wemm 328d66a5066SPeter Wemm /* 329d66a5066SPeter Wemm * Check for security violations. 330d66a5066SPeter Wemm */ 331d66a5066SPeter Wemm #define EFLAGS_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) 332d66a5066SPeter Wemm eflags = context.sc_eflags; 333d66a5066SPeter Wemm /* 334d66a5066SPeter Wemm * XXX do allow users to change the privileged flag PSL_RF. The 335d66a5066SPeter Wemm * cpu sets PSL_RF in tf_eflags for faults. Debuggers should 336d66a5066SPeter Wemm * sometimes set it there too. tf_eflags is kept in the signal 337d66a5066SPeter Wemm * context during signal handling and there is no other place 338d66a5066SPeter Wemm * to remember it, so the PSL_RF bit may be corrupted by the 339d66a5066SPeter Wemm * signal handler without us knowing. Corruption of the PSL_RF 340d66a5066SPeter Wemm * bit at worst causes one more or one less debugger trap, so 341d66a5066SPeter Wemm * allowing it is fairly harmless. 342d66a5066SPeter Wemm */ 343213fdd80SPeter Wemm if (!EFLAGS_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) { 344d66a5066SPeter Wemm return(EINVAL); 345d66a5066SPeter Wemm } 346d66a5066SPeter Wemm 347d66a5066SPeter Wemm /* 348d66a5066SPeter Wemm * Don't allow users to load a valid privileged %cs. Let the 349d66a5066SPeter Wemm * hardware check for invalid selectors, excess privilege in 350d66a5066SPeter Wemm * other selectors, invalid %eip's and invalid %esp's. 351d66a5066SPeter Wemm */ 35240d50994SPhilippe Charnier #define CS_SECURE(cs) (ISPL(cs) == SEL_UPL) 353d66a5066SPeter Wemm if (!CS_SECURE(context.sc_cs)) { 354d66a5066SPeter Wemm trapsignal(p, SIGBUS, T_PROTFLT); 355d66a5066SPeter Wemm return(EINVAL); 356d66a5066SPeter Wemm } 357d66a5066SPeter Wemm 358645682fdSLuoqi Chen p->p_sigstk.ss_flags &= ~SS_ONSTACK; 359645682fdSLuoqi Chen SIGSETOLD(p->p_sigmask, context.sc_mask); 360645682fdSLuoqi Chen SIG_CANTMASK(p->p_sigmask); 361956d3333SMarcel Moolenaar 362d66a5066SPeter Wemm /* 363d66a5066SPeter Wemm * Restore signal context. 364d66a5066SPeter Wemm */ 3655206bca1SLuoqi Chen /* %gs was restored by the trampoline. */ 3665206bca1SLuoqi Chen regs->tf_fs = context.sc_fs; 367213fdd80SPeter Wemm regs->tf_es = context.sc_es; 368213fdd80SPeter Wemm regs->tf_ds = context.sc_ds; 369213fdd80SPeter Wemm regs->tf_edi = context.sc_edi; 370213fdd80SPeter Wemm regs->tf_esi = context.sc_esi; 371213fdd80SPeter Wemm regs->tf_ebp = context.sc_ebp; 372213fdd80SPeter Wemm regs->tf_ebx = context.sc_ebx; 373213fdd80SPeter Wemm regs->tf_edx = context.sc_edx; 374213fdd80SPeter Wemm regs->tf_ecx = context.sc_ecx; 375213fdd80SPeter Wemm regs->tf_eax = context.sc_eax; 376213fdd80SPeter Wemm regs->tf_eip = context.sc_eip; 377213fdd80SPeter Wemm regs->tf_cs = context.sc_cs; 378213fdd80SPeter Wemm regs->tf_eflags = eflags; 379213fdd80SPeter Wemm regs->tf_esp = context.sc_esp_at_signal; 380213fdd80SPeter Wemm regs->tf_ss = context.sc_ss; 381d66a5066SPeter Wemm 382d66a5066SPeter Wemm return (EJUSTRETURN); 383d66a5066SPeter Wemm } 384d66a5066SPeter Wemm 385303b270bSEivind Eklund static void 386d66a5066SPeter Wemm linux_prepsyscall(struct trapframe *tf, int *args, u_int *code, caddr_t *params) 387d66a5066SPeter Wemm { 388d66a5066SPeter Wemm args[0] = tf->tf_ebx; 389d66a5066SPeter Wemm args[1] = tf->tf_ecx; 390d66a5066SPeter Wemm args[2] = tf->tf_edx; 391d66a5066SPeter Wemm args[3] = tf->tf_esi; 392d66a5066SPeter Wemm args[4] = tf->tf_edi; 393d66a5066SPeter Wemm *params = NULL; /* no copyin */ 394d66a5066SPeter Wemm } 395d66a5066SPeter Wemm 396d66a5066SPeter Wemm struct sysentvec linux_sysvec = { 397e1743d02SSøren Schmidt LINUX_SYS_MAXSYSCALL, 398d66a5066SPeter Wemm linux_sysent, 399d66a5066SPeter Wemm 0xff, 400956d3333SMarcel Moolenaar LINUX_SIGTBLSZ, 401d66a5066SPeter Wemm bsd_to_linux_signal, 40285f118c8SDmitrij Tejblum ELAST + 1, 403d66a5066SPeter Wemm bsd_to_linux_errno, 404288078beSEivind Eklund translate_traps, 405d66a5066SPeter Wemm linux_fixup, 406d66a5066SPeter Wemm linux_sendsig, 407d66a5066SPeter Wemm linux_sigcode, 408d66a5066SPeter Wemm &linux_szsigcode, 409d66a5066SPeter Wemm linux_prepsyscall, 41022d4b0fbSJohn Polstra "Linux a.out", 41122d4b0fbSJohn Polstra aout_coredump 412d66a5066SPeter Wemm }; 413e1743d02SSøren Schmidt 414e1743d02SSøren Schmidt struct sysentvec elf_linux_sysvec = { 415e1743d02SSøren Schmidt LINUX_SYS_MAXSYSCALL, 416e1743d02SSøren Schmidt linux_sysent, 417e1743d02SSøren Schmidt 0xff, 418956d3333SMarcel Moolenaar LINUX_SIGTBLSZ, 419e1743d02SSøren Schmidt bsd_to_linux_signal, 42085f118c8SDmitrij Tejblum ELAST + 1, 421e1743d02SSøren Schmidt bsd_to_linux_errno, 422288078beSEivind Eklund translate_traps, 423e1743d02SSøren Schmidt elf_linux_fixup, 424e1743d02SSøren Schmidt linux_sendsig, 425e1743d02SSøren Schmidt linux_sigcode, 426e1743d02SSøren Schmidt &linux_szsigcode, 427e1743d02SSøren Schmidt linux_prepsyscall, 42822d4b0fbSJohn Polstra "Linux ELF", 42922d4b0fbSJohn Polstra elf_coredump 430e1743d02SSøren Schmidt }; 431e1743d02SSøren Schmidt 432514058dcSAlexander Langer static Elf32_Brandinfo linux_brand = { 433ea5a2b2eSSøren Schmidt "Linux", 434ea5a2b2eSSøren Schmidt "/compat/linux", 4355cf588ebSPeter Wemm "/lib/ld-linux.so.1", 436ea5a2b2eSSøren Schmidt &elf_linux_sysvec 4375cf588ebSPeter Wemm }; 4385cf588ebSPeter Wemm 439514058dcSAlexander Langer static Elf32_Brandinfo linux_glibc2brand = { 4404e138a28SMike Smith "Linux", 4414e138a28SMike Smith "/compat/linux", 4424e138a28SMike Smith "/lib/ld-linux.so.2", 4434e138a28SMike Smith &elf_linux_sysvec 4444e138a28SMike Smith }; 4454e138a28SMike Smith 446514058dcSAlexander Langer Elf32_Brandinfo *linux_brandlist[] = { 447514058dcSAlexander Langer &linux_brand, 448514058dcSAlexander Langer &linux_glibc2brand, 449514058dcSAlexander Langer NULL 450514058dcSAlexander Langer }; 451514058dcSAlexander Langer 452aa855a59SPeter Wemm static int 453c25ded31SBruce Evans linux_elf_modevent(module_t mod, int type, void *data) 454d30ea4f5SPeter Wemm { 455514058dcSAlexander Langer Elf32_Brandinfo **brandinfo; 456514058dcSAlexander Langer int error; 457514058dcSAlexander Langer 458514058dcSAlexander Langer error = 0; 459514058dcSAlexander Langer 460aa855a59SPeter Wemm switch(type) { 461aa855a59SPeter Wemm case MOD_LOAD: 462aa855a59SPeter Wemm for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL; 463aa855a59SPeter Wemm ++brandinfo) 464514058dcSAlexander Langer if (elf_insert_brand_entry(*brandinfo) < 0) 465aa855a59SPeter Wemm error = EINVAL; 466514058dcSAlexander Langer if (error) 467d30ea4f5SPeter Wemm printf("cannot insert Linux elf brand handler\n"); 468d30ea4f5SPeter Wemm else if (bootverbose) 469d30ea4f5SPeter Wemm printf("Linux-ELF exec handler installed\n"); 470aa855a59SPeter Wemm break; 471aa855a59SPeter Wemm case MOD_UNLOAD: 472aa855a59SPeter Wemm for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL; 473aa855a59SPeter Wemm ++brandinfo) 474d2758342SMark Newton if (elf_brand_inuse(*brandinfo)) { 475d2758342SMark Newton error = EBUSY; 476d2758342SMark Newton } 477d2758342SMark Newton 478d2758342SMark Newton if (error == 0) { 479d2758342SMark Newton for (brandinfo = &linux_brandlist[0]; 480d2758342SMark Newton *brandinfo != NULL; ++brandinfo) 481aa855a59SPeter Wemm if (elf_remove_brand_entry(*brandinfo) < 0) 482aa855a59SPeter Wemm error = EINVAL; 483d2758342SMark Newton } 484aa855a59SPeter Wemm if (error) 485aa855a59SPeter Wemm printf("Could not deinstall ELF interpreter entry\n"); 486aa855a59SPeter Wemm else if (bootverbose) 487aa855a59SPeter Wemm printf("Linux-elf exec handler removed\n"); 488aa855a59SPeter Wemm break; 489aa855a59SPeter Wemm default: 490aa855a59SPeter Wemm break; 491d30ea4f5SPeter Wemm } 492aa855a59SPeter Wemm return error; 493aa855a59SPeter Wemm } 494aa855a59SPeter Wemm static moduledata_t linux_elf_mod = { 495aa855a59SPeter Wemm "linuxelf", 496aa855a59SPeter Wemm linux_elf_modevent, 497aa855a59SPeter Wemm 0 498aa855a59SPeter Wemm }; 499aa855a59SPeter Wemm DECLARE_MODULE(linuxelf, linux_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY); 500