1ea0fabbcSTim J. Robbins /*- 2ea0fabbcSTim J. Robbins * Copyright (c) 2004 Tim J. Robbins 3ea0fabbcSTim J. Robbins * Copyright (c) 2003 Peter Wemm 4ea0fabbcSTim J. Robbins * Copyright (c) 2002 Doug Rabson 5ea0fabbcSTim J. Robbins * Copyright (c) 1998-1999 Andrew Gallatin 6ea0fabbcSTim J. Robbins * Copyright (c) 1994-1996 S�ren Schmidt 7ea0fabbcSTim J. Robbins * All rights reserved. 8ea0fabbcSTim J. Robbins * 9ea0fabbcSTim J. Robbins * Redistribution and use in source and binary forms, with or without 10ea0fabbcSTim J. Robbins * modification, are permitted provided that the following conditions 11ea0fabbcSTim J. Robbins * are met: 12ea0fabbcSTim J. Robbins * 1. Redistributions of source code must retain the above copyright 13ea0fabbcSTim J. Robbins * notice, this list of conditions and the following disclaimer 14ea0fabbcSTim J. Robbins * in this position and unchanged. 15ea0fabbcSTim J. Robbins * 2. Redistributions in binary form must reproduce the above copyright 16ea0fabbcSTim J. Robbins * notice, this list of conditions and the following disclaimer in the 17ea0fabbcSTim J. Robbins * documentation and/or other materials provided with the distribution. 18ea0fabbcSTim J. Robbins * 3. The name of the author may not be used to endorse or promote products 19ea0fabbcSTim J. Robbins * derived from this software without specific prior written permission 20ea0fabbcSTim J. Robbins * 21ea0fabbcSTim J. Robbins * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22ea0fabbcSTim J. Robbins * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23ea0fabbcSTim J. Robbins * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24ea0fabbcSTim J. Robbins * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25ea0fabbcSTim J. Robbins * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26ea0fabbcSTim J. Robbins * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27ea0fabbcSTim J. Robbins * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28ea0fabbcSTim J. Robbins * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29ea0fabbcSTim J. Robbins * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30ea0fabbcSTim J. Robbins * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31ea0fabbcSTim J. Robbins */ 32ea0fabbcSTim J. Robbins 33ea0fabbcSTim J. Robbins #include <sys/cdefs.h> 34ea0fabbcSTim J. Robbins __FBSDID("$FreeBSD$"); 35ea0fabbcSTim J. Robbins 36ea0fabbcSTim J. Robbins /* XXX we use functions that might not exist. */ 37ea0fabbcSTim J. Robbins #include "opt_compat.h" 38ea0fabbcSTim J. Robbins #include "opt_ia32.h" 39ea0fabbcSTim J. Robbins 40ea0fabbcSTim J. Robbins #ifndef COMPAT_43 41ea0fabbcSTim J. Robbins #error "Unable to compile Linux-emulator due to missing COMPAT_43 option!" 42ea0fabbcSTim J. Robbins #endif 43ea0fabbcSTim J. Robbins #ifndef IA32 44ea0fabbcSTim J. Robbins #error "Unable to compile Linux-emulator due to missing IA32 option!" 45ea0fabbcSTim J. Robbins #endif 46ea0fabbcSTim J. Robbins 47ea0fabbcSTim J. Robbins #define __ELF_WORD_SIZE 32 48ea0fabbcSTim J. Robbins 49ea0fabbcSTim J. Robbins #include <sys/param.h> 50ea0fabbcSTim J. Robbins #include <sys/systm.h> 51ea0fabbcSTim J. Robbins #include <sys/exec.h> 52ea0fabbcSTim J. Robbins #include <sys/imgact.h> 53ea0fabbcSTim J. Robbins #include <sys/imgact_elf.h> 54ea0fabbcSTim J. Robbins #include <sys/kernel.h> 55ea0fabbcSTim J. Robbins #include <sys/lock.h> 56ea0fabbcSTim J. Robbins #include <sys/malloc.h> 57ea0fabbcSTim J. Robbins #include <sys/module.h> 58ea0fabbcSTim J. Robbins #include <sys/mutex.h> 59ea0fabbcSTim J. Robbins #include <sys/proc.h> 60ea0fabbcSTim J. Robbins #include <sys/signalvar.h> 61ea0fabbcSTim J. Robbins #include <sys/sysctl.h> 62ea0fabbcSTim J. Robbins #include <sys/syscallsubr.h> 63ea0fabbcSTim J. Robbins #include <sys/sysent.h> 64ea0fabbcSTim J. Robbins #include <sys/sysproto.h> 65ea0fabbcSTim J. Robbins #include <sys/user.h> 66ea0fabbcSTim J. Robbins #include <sys/vnode.h> 67ea0fabbcSTim J. Robbins 68ea0fabbcSTim J. Robbins #include <vm/vm.h> 69ea0fabbcSTim J. Robbins #include <vm/pmap.h> 70ea0fabbcSTim J. Robbins #include <vm/vm_extern.h> 71ea0fabbcSTim J. Robbins #include <vm/vm_map.h> 72ea0fabbcSTim J. Robbins #include <vm/vm_object.h> 73ea0fabbcSTim J. Robbins #include <vm/vm_page.h> 74ea0fabbcSTim J. Robbins #include <vm/vm_param.h> 75ea0fabbcSTim J. Robbins 76ea0fabbcSTim J. Robbins #include <machine/cpu.h> 77ea0fabbcSTim J. Robbins #include <machine/md_var.h> 78ea0fabbcSTim J. Robbins #include <machine/specialreg.h> 79ea0fabbcSTim J. Robbins 80ea0fabbcSTim J. Robbins #include <amd64/linux32/linux.h> 81ea0fabbcSTim J. Robbins #include <amd64/linux32/linux32_proto.h> 82ea0fabbcSTim J. Robbins #include <compat/linux/linux_mib.h> 83ea0fabbcSTim J. Robbins #include <compat/linux/linux_signal.h> 84ea0fabbcSTim J. Robbins #include <compat/linux/linux_util.h> 85ea0fabbcSTim J. Robbins 86ea0fabbcSTim J. Robbins MODULE_VERSION(linux, 1); 87ea0fabbcSTim J. Robbins MODULE_DEPEND(linux, sysvmsg, 1, 1, 1); 88ea0fabbcSTim J. Robbins MODULE_DEPEND(linux, sysvsem, 1, 1, 1); 89ea0fabbcSTim J. Robbins MODULE_DEPEND(linux, sysvshm, 1, 1, 1); 90ea0fabbcSTim J. Robbins 91ea0fabbcSTim J. Robbins MALLOC_DEFINE(M_LINUX, "linux", "Linux mode structures"); 92ea0fabbcSTim J. Robbins 93ea0fabbcSTim J. Robbins #define AUXARGS_ENTRY_32(pos, id, val) \ 94ea0fabbcSTim J. Robbins do { \ 95ea0fabbcSTim J. Robbins suword32(pos++, id); \ 96ea0fabbcSTim J. Robbins suword32(pos++, val); \ 97ea0fabbcSTim J. Robbins } while (0) 98ea0fabbcSTim J. Robbins 99ea0fabbcSTim J. Robbins #if BYTE_ORDER == LITTLE_ENDIAN 100ea0fabbcSTim J. Robbins #define SHELLMAGIC 0x2123 /* #! */ 101ea0fabbcSTim J. Robbins #else 102ea0fabbcSTim J. Robbins #define SHELLMAGIC 0x2321 103ea0fabbcSTim J. Robbins #endif 104ea0fabbcSTim J. Robbins 105ea0fabbcSTim J. Robbins /* 106ea0fabbcSTim J. Robbins * Allow the sendsig functions to use the ldebug() facility 107ea0fabbcSTim J. Robbins * even though they are not syscalls themselves. Map them 108ea0fabbcSTim J. Robbins * to syscall 0. This is slightly less bogus than using 109ea0fabbcSTim J. Robbins * ldebug(sigreturn). 110ea0fabbcSTim J. Robbins */ 111ea0fabbcSTim J. Robbins #define LINUX_SYS_linux_rt_sendsig 0 112ea0fabbcSTim J. Robbins #define LINUX_SYS_linux_sendsig 0 113ea0fabbcSTim J. Robbins 114ea0fabbcSTim J. Robbins extern char linux_sigcode[]; 115ea0fabbcSTim J. Robbins extern int linux_szsigcode; 116ea0fabbcSTim J. Robbins 117ea0fabbcSTim J. Robbins extern struct sysent linux_sysent[LINUX_SYS_MAXSYSCALL]; 118ea0fabbcSTim J. Robbins 119ea0fabbcSTim J. Robbins SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler); 120ea0fabbcSTim J. Robbins 121ea0fabbcSTim J. Robbins static int elf_linux_fixup(register_t **stack_base, 122ea0fabbcSTim J. Robbins struct image_params *iparams); 123ea0fabbcSTim J. Robbins static register_t *linux_copyout_strings(struct image_params *imgp); 124ea0fabbcSTim J. Robbins static void linux_prepsyscall(struct trapframe *tf, int *args, u_int *code, 125ea0fabbcSTim J. Robbins caddr_t *params); 126ea0fabbcSTim J. Robbins static void linux_sendsig(sig_t catcher, int sig, sigset_t *mask, 127ea0fabbcSTim J. Robbins u_long code); 128ea0fabbcSTim J. Robbins static void exec_linux_setregs(struct thread *td, u_long entry, 129ea0fabbcSTim J. Robbins u_long stack, u_long ps_strings); 130ea0fabbcSTim J. Robbins static void linux32_fixlimits(struct image_params *imgp); 131ea0fabbcSTim J. Robbins 132ea0fabbcSTim J. Robbins /* 133ea0fabbcSTim J. Robbins * Linux syscalls return negative errno's, we do positive and map them 134ea0fabbcSTim J. Robbins */ 135ea0fabbcSTim J. Robbins static int bsd_to_linux_errno[ELAST + 1] = { 136ea0fabbcSTim J. Robbins -0, -1, -2, -3, -4, -5, -6, -7, -8, -9, 137ea0fabbcSTim J. Robbins -10, -35, -12, -13, -14, -15, -16, -17, -18, -19, 138ea0fabbcSTim J. Robbins -20, -21, -22, -23, -24, -25, -26, -27, -28, -29, 139ea0fabbcSTim J. Robbins -30, -31, -32, -33, -34, -11,-115,-114, -88, -89, 140ea0fabbcSTim J. Robbins -90, -91, -92, -93, -94, -95, -96, -97, -98, -99, 141ea0fabbcSTim J. Robbins -100,-101,-102,-103,-104,-105,-106,-107,-108,-109, 142ea0fabbcSTim J. Robbins -110,-111, -40, -36,-112,-113, -39, -11, -87,-122, 143ea0fabbcSTim J. Robbins -116, -66, -6, -6, -6, -6, -6, -37, -38, -9, 144ea0fabbcSTim J. Robbins -6, -6, -43, -42, -75, -6, -84 145ea0fabbcSTim J. Robbins }; 146ea0fabbcSTim J. Robbins 147ea0fabbcSTim J. Robbins int bsd_to_linux_signal[LINUX_SIGTBLSZ] = { 148ea0fabbcSTim J. Robbins LINUX_SIGHUP, LINUX_SIGINT, LINUX_SIGQUIT, LINUX_SIGILL, 149ea0fabbcSTim J. Robbins LINUX_SIGTRAP, LINUX_SIGABRT, 0, LINUX_SIGFPE, 150ea0fabbcSTim J. Robbins LINUX_SIGKILL, LINUX_SIGBUS, LINUX_SIGSEGV, LINUX_SIGSYS, 151ea0fabbcSTim J. Robbins LINUX_SIGPIPE, LINUX_SIGALRM, LINUX_SIGTERM, LINUX_SIGURG, 152ea0fabbcSTim J. Robbins LINUX_SIGSTOP, LINUX_SIGTSTP, LINUX_SIGCONT, LINUX_SIGCHLD, 153ea0fabbcSTim J. Robbins LINUX_SIGTTIN, LINUX_SIGTTOU, LINUX_SIGIO, LINUX_SIGXCPU, 154ea0fabbcSTim J. Robbins LINUX_SIGXFSZ, LINUX_SIGVTALRM, LINUX_SIGPROF, LINUX_SIGWINCH, 155ea0fabbcSTim J. Robbins 0, LINUX_SIGUSR1, LINUX_SIGUSR2 156ea0fabbcSTim J. Robbins }; 157ea0fabbcSTim J. Robbins 158ea0fabbcSTim J. Robbins int linux_to_bsd_signal[LINUX_SIGTBLSZ] = { 159ea0fabbcSTim J. Robbins SIGHUP, SIGINT, SIGQUIT, SIGILL, 160ea0fabbcSTim J. Robbins SIGTRAP, SIGABRT, SIGBUS, SIGFPE, 161ea0fabbcSTim J. Robbins SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, 162ea0fabbcSTim J. Robbins SIGPIPE, SIGALRM, SIGTERM, SIGBUS, 163ea0fabbcSTim J. Robbins SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, 164ea0fabbcSTim J. Robbins SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, 165ea0fabbcSTim J. Robbins SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH, 166ea0fabbcSTim J. Robbins SIGIO, SIGURG, SIGSYS 167ea0fabbcSTim J. Robbins }; 168ea0fabbcSTim J. Robbins 169ea0fabbcSTim J. Robbins #define LINUX_T_UNKNOWN 255 170ea0fabbcSTim J. Robbins static int _bsd_to_linux_trapcode[] = { 171ea0fabbcSTim J. Robbins LINUX_T_UNKNOWN, /* 0 */ 172ea0fabbcSTim J. Robbins 6, /* 1 T_PRIVINFLT */ 173ea0fabbcSTim J. Robbins LINUX_T_UNKNOWN, /* 2 */ 174ea0fabbcSTim J. Robbins 3, /* 3 T_BPTFLT */ 175ea0fabbcSTim J. Robbins LINUX_T_UNKNOWN, /* 4 */ 176ea0fabbcSTim J. Robbins LINUX_T_UNKNOWN, /* 5 */ 177ea0fabbcSTim J. Robbins 16, /* 6 T_ARITHTRAP */ 178ea0fabbcSTim J. Robbins 254, /* 7 T_ASTFLT */ 179ea0fabbcSTim J. Robbins LINUX_T_UNKNOWN, /* 8 */ 180ea0fabbcSTim J. Robbins 13, /* 9 T_PROTFLT */ 181ea0fabbcSTim J. Robbins 1, /* 10 T_TRCTRAP */ 182ea0fabbcSTim J. Robbins LINUX_T_UNKNOWN, /* 11 */ 183ea0fabbcSTim J. Robbins 14, /* 12 T_PAGEFLT */ 184ea0fabbcSTim J. Robbins LINUX_T_UNKNOWN, /* 13 */ 185ea0fabbcSTim J. Robbins 17, /* 14 T_ALIGNFLT */ 186ea0fabbcSTim J. Robbins LINUX_T_UNKNOWN, /* 15 */ 187ea0fabbcSTim J. Robbins LINUX_T_UNKNOWN, /* 16 */ 188ea0fabbcSTim J. Robbins LINUX_T_UNKNOWN, /* 17 */ 189ea0fabbcSTim J. Robbins 0, /* 18 T_DIVIDE */ 190ea0fabbcSTim J. Robbins 2, /* 19 T_NMI */ 191ea0fabbcSTim J. Robbins 4, /* 20 T_OFLOW */ 192ea0fabbcSTim J. Robbins 5, /* 21 T_BOUND */ 193ea0fabbcSTim J. Robbins 7, /* 22 T_DNA */ 194ea0fabbcSTim J. Robbins 8, /* 23 T_DOUBLEFLT */ 195ea0fabbcSTim J. Robbins 9, /* 24 T_FPOPFLT */ 196ea0fabbcSTim J. Robbins 10, /* 25 T_TSSFLT */ 197ea0fabbcSTim J. Robbins 11, /* 26 T_SEGNPFLT */ 198ea0fabbcSTim J. Robbins 12, /* 27 T_STKFLT */ 199ea0fabbcSTim J. Robbins 18, /* 28 T_MCHK */ 200ea0fabbcSTim J. Robbins 19, /* 29 T_XMMFLT */ 201ea0fabbcSTim J. Robbins 15 /* 30 T_RESERVED */ 202ea0fabbcSTim J. Robbins }; 203ea0fabbcSTim J. Robbins #define bsd_to_linux_trapcode(code) \ 204ea0fabbcSTim J. Robbins ((code)<sizeof(_bsd_to_linux_trapcode)/sizeof(*_bsd_to_linux_trapcode)? \ 205ea0fabbcSTim J. Robbins _bsd_to_linux_trapcode[(code)]: \ 206ea0fabbcSTim J. Robbins LINUX_T_UNKNOWN) 207ea0fabbcSTim J. Robbins 208ea0fabbcSTim J. Robbins struct linux32_ps_strings { 209ea0fabbcSTim J. Robbins u_int32_t ps_argvstr; /* first of 0 or more argument strings */ 210ea0fabbcSTim J. Robbins int ps_nargvstr; /* the number of argument strings */ 211ea0fabbcSTim J. Robbins u_int32_t ps_envstr; /* first of 0 or more environment strings */ 212ea0fabbcSTim J. Robbins int ps_nenvstr; /* the number of environment strings */ 213ea0fabbcSTim J. Robbins }; 214ea0fabbcSTim J. Robbins 215ea0fabbcSTim J. Robbins /* 216ea0fabbcSTim J. Robbins * If FreeBSD & Linux have a difference of opinion about what a trap 217ea0fabbcSTim J. Robbins * means, deal with it here. 218ea0fabbcSTim J. Robbins * 219ea0fabbcSTim J. Robbins * MPSAFE 220ea0fabbcSTim J. Robbins */ 221ea0fabbcSTim J. Robbins static int 222ea0fabbcSTim J. Robbins translate_traps(int signal, int trap_code) 223ea0fabbcSTim J. Robbins { 224ea0fabbcSTim J. Robbins if (signal != SIGBUS) 225ea0fabbcSTim J. Robbins return signal; 226ea0fabbcSTim J. Robbins switch (trap_code) { 227ea0fabbcSTim J. Robbins case T_PROTFLT: 228ea0fabbcSTim J. Robbins case T_TSSFLT: 229ea0fabbcSTim J. Robbins case T_DOUBLEFLT: 230ea0fabbcSTim J. Robbins case T_PAGEFLT: 231ea0fabbcSTim J. Robbins return SIGSEGV; 232ea0fabbcSTim J. Robbins default: 233ea0fabbcSTim J. Robbins return signal; 234ea0fabbcSTim J. Robbins } 235ea0fabbcSTim J. Robbins } 236ea0fabbcSTim J. Robbins 237ea0fabbcSTim J. Robbins static int 238ea0fabbcSTim J. Robbins elf_linux_fixup(register_t **stack_base, struct image_params *imgp) 239ea0fabbcSTim J. Robbins { 240ea0fabbcSTim J. Robbins Elf32_Auxargs *args; 241ea0fabbcSTim J. Robbins Elf32_Addr *base; 242ea0fabbcSTim J. Robbins Elf32_Addr *pos; 243ea0fabbcSTim J. Robbins 244ea0fabbcSTim J. Robbins KASSERT(curthread->td_proc == imgp->proc && 245ea0fabbcSTim J. Robbins (curthread->td_proc->p_flag & P_SA) == 0, 246ea0fabbcSTim J. Robbins ("unsafe elf_linux_fixup(), should be curproc")); 247ea0fabbcSTim J. Robbins base = (Elf32_Addr *)*stack_base; 248ea0fabbcSTim J. Robbins args = (Elf32_Auxargs *)imgp->auxargs; 249ea0fabbcSTim J. Robbins pos = base + (imgp->argc + imgp->envc + 2); 250ea0fabbcSTim J. Robbins 251ea0fabbcSTim J. Robbins if (args->trace) 252ea0fabbcSTim J. Robbins AUXARGS_ENTRY_32(pos, AT_DEBUG, 1); 253ea0fabbcSTim J. Robbins if (args->execfd != -1) 254ea0fabbcSTim J. Robbins AUXARGS_ENTRY_32(pos, AT_EXECFD, args->execfd); 255ea0fabbcSTim J. Robbins AUXARGS_ENTRY_32(pos, AT_PHDR, args->phdr); 256ea0fabbcSTim J. Robbins AUXARGS_ENTRY_32(pos, AT_PHENT, args->phent); 257ea0fabbcSTim J. Robbins AUXARGS_ENTRY_32(pos, AT_PHNUM, args->phnum); 258ea0fabbcSTim J. Robbins AUXARGS_ENTRY_32(pos, AT_PAGESZ, args->pagesz); 259ea0fabbcSTim J. Robbins AUXARGS_ENTRY_32(pos, AT_FLAGS, args->flags); 260ea0fabbcSTim J. Robbins AUXARGS_ENTRY_32(pos, AT_ENTRY, args->entry); 261ea0fabbcSTim J. Robbins AUXARGS_ENTRY_32(pos, AT_BASE, args->base); 262ea0fabbcSTim J. Robbins AUXARGS_ENTRY_32(pos, AT_UID, imgp->proc->p_ucred->cr_ruid); 263ea0fabbcSTim J. Robbins AUXARGS_ENTRY_32(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid); 264ea0fabbcSTim J. Robbins AUXARGS_ENTRY_32(pos, AT_GID, imgp->proc->p_ucred->cr_rgid); 265ea0fabbcSTim J. Robbins AUXARGS_ENTRY_32(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid); 266ea0fabbcSTim J. Robbins AUXARGS_ENTRY_32(pos, AT_NULL, 0); 267ea0fabbcSTim J. Robbins 268ea0fabbcSTim J. Robbins free(imgp->auxargs, M_TEMP); 269ea0fabbcSTim J. Robbins imgp->auxargs = NULL; 270ea0fabbcSTim J. Robbins 271ea0fabbcSTim J. Robbins base--; 272ea0fabbcSTim J. Robbins suword32(base, (uint32_t)imgp->argc); 273ea0fabbcSTim J. Robbins *stack_base = (register_t *)base; 274ea0fabbcSTim J. Robbins return 0; 275ea0fabbcSTim J. Robbins } 276ea0fabbcSTim J. Robbins 277ea0fabbcSTim J. Robbins extern int _ucodesel, _ucode32sel, _udatasel; 278ea0fabbcSTim J. Robbins extern unsigned long linux_sznonrtsigcode; 279ea0fabbcSTim J. Robbins 280ea0fabbcSTim J. Robbins static void 281ea0fabbcSTim J. Robbins linux_rt_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) 282ea0fabbcSTim J. Robbins { 283ea0fabbcSTim J. Robbins struct thread *td = curthread; 284ea0fabbcSTim J. Robbins struct proc *p = td->td_proc; 285ea0fabbcSTim J. Robbins struct sigacts *psp; 286ea0fabbcSTim J. Robbins struct trapframe *regs; 287ea0fabbcSTim J. Robbins struct l_rt_sigframe *fp, frame; 288ea0fabbcSTim J. Robbins int oonstack; 289ea0fabbcSTim J. Robbins 290ea0fabbcSTim J. Robbins PROC_LOCK_ASSERT(p, MA_OWNED); 291ea0fabbcSTim J. Robbins psp = p->p_sigacts; 292ea0fabbcSTim J. Robbins mtx_assert(&psp->ps_mtx, MA_OWNED); 293ea0fabbcSTim J. Robbins regs = td->td_frame; 294ea0fabbcSTim J. Robbins oonstack = sigonstack(regs->tf_rsp); 295ea0fabbcSTim J. Robbins 296ea0fabbcSTim J. Robbins #ifdef DEBUG 297ea0fabbcSTim J. Robbins if (ldebug(rt_sendsig)) 298ea0fabbcSTim J. Robbins printf(ARGS(rt_sendsig, "%p, %d, %p, %lu"), 299ea0fabbcSTim J. Robbins catcher, sig, (void*)mask, code); 300ea0fabbcSTim J. Robbins #endif 301ea0fabbcSTim J. Robbins /* 302ea0fabbcSTim J. Robbins * Allocate space for the signal handler context. 303ea0fabbcSTim J. Robbins */ 304ea0fabbcSTim J. Robbins if ((td->td_pflags & TDP_ALTSTACK) && !oonstack && 305ea0fabbcSTim J. Robbins SIGISMEMBER(psp->ps_sigonstack, sig)) { 306ea0fabbcSTim J. Robbins fp = (struct l_rt_sigframe *)(td->td_sigstk.ss_sp + 307ea0fabbcSTim J. Robbins td->td_sigstk.ss_size - sizeof(struct l_rt_sigframe)); 308ea0fabbcSTim J. Robbins } else 309ea0fabbcSTim J. Robbins fp = (struct l_rt_sigframe *)regs->tf_rsp - 1; 310ea0fabbcSTim J. Robbins mtx_unlock(&psp->ps_mtx); 311ea0fabbcSTim J. Robbins 312ea0fabbcSTim J. Robbins /* 313ea0fabbcSTim J. Robbins * Build the argument list for the signal handler. 314ea0fabbcSTim J. Robbins */ 315ea0fabbcSTim J. Robbins if (p->p_sysent->sv_sigtbl) 316ea0fabbcSTim J. Robbins if (sig <= p->p_sysent->sv_sigsize) 317ea0fabbcSTim J. Robbins sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 318ea0fabbcSTim J. Robbins 319ea0fabbcSTim J. Robbins bzero(&frame, sizeof(frame)); 320ea0fabbcSTim J. Robbins 321ea0fabbcSTim J. Robbins frame.sf_handler = PTROUT(catcher); 322ea0fabbcSTim J. Robbins frame.sf_sig = sig; 323ea0fabbcSTim J. Robbins frame.sf_siginfo = PTROUT(&fp->sf_si); 324ea0fabbcSTim J. Robbins frame.sf_ucontext = PTROUT(&fp->sf_sc); 325ea0fabbcSTim J. Robbins 326ea0fabbcSTim J. Robbins /* Fill in POSIX parts */ 327ea0fabbcSTim J. Robbins frame.sf_si.lsi_signo = sig; 328ea0fabbcSTim J. Robbins frame.sf_si.lsi_code = code; 329ea0fabbcSTim J. Robbins frame.sf_si.lsi_addr = PTROUT(regs->tf_err); 330ea0fabbcSTim J. Robbins 331ea0fabbcSTim J. Robbins /* 332ea0fabbcSTim J. Robbins * Build the signal context to be used by sigreturn. 333ea0fabbcSTim J. Robbins */ 334ea0fabbcSTim J. Robbins frame.sf_sc.uc_flags = 0; /* XXX ??? */ 335ea0fabbcSTim J. Robbins frame.sf_sc.uc_link = 0; /* XXX ??? */ 336ea0fabbcSTim J. Robbins 337ea0fabbcSTim J. Robbins frame.sf_sc.uc_stack.ss_sp = PTROUT(td->td_sigstk.ss_sp); 338ea0fabbcSTim J. Robbins frame.sf_sc.uc_stack.ss_size = td->td_sigstk.ss_size; 339ea0fabbcSTim J. Robbins frame.sf_sc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) 340ea0fabbcSTim J. Robbins ? ((oonstack) ? LINUX_SS_ONSTACK : 0) : LINUX_SS_DISABLE; 341ea0fabbcSTim J. Robbins PROC_UNLOCK(p); 342ea0fabbcSTim J. Robbins 343ea0fabbcSTim J. Robbins bsd_to_linux_sigset(mask, &frame.sf_sc.uc_sigmask); 344ea0fabbcSTim J. Robbins 345ea0fabbcSTim J. Robbins frame.sf_sc.uc_mcontext.sc_mask = frame.sf_sc.uc_sigmask.__bits[0]; 346ea0fabbcSTim J. Robbins frame.sf_sc.uc_mcontext.sc_gs = rgs(); 347ea0fabbcSTim J. Robbins frame.sf_sc.uc_mcontext.sc_fs = rfs(); 348ea0fabbcSTim J. Robbins __asm __volatile("movl %%es,%0" : 349ea0fabbcSTim J. Robbins "=rm" (frame.sf_sc.uc_mcontext.sc_es)); 350ea0fabbcSTim J. Robbins __asm __volatile("movl %%ds,%0" : 351ea0fabbcSTim J. Robbins "=rm" (frame.sf_sc.uc_mcontext.sc_ds)); 352ea0fabbcSTim J. Robbins frame.sf_sc.uc_mcontext.sc_edi = regs->tf_rdi; 353ea0fabbcSTim J. Robbins frame.sf_sc.uc_mcontext.sc_esi = regs->tf_rsi; 354ea0fabbcSTim J. Robbins frame.sf_sc.uc_mcontext.sc_ebp = regs->tf_rbp; 355ea0fabbcSTim J. Robbins frame.sf_sc.uc_mcontext.sc_ebx = regs->tf_rbx; 356ea0fabbcSTim J. Robbins frame.sf_sc.uc_mcontext.sc_edx = regs->tf_rdx; 357ea0fabbcSTim J. Robbins frame.sf_sc.uc_mcontext.sc_ecx = regs->tf_rcx; 358ea0fabbcSTim J. Robbins frame.sf_sc.uc_mcontext.sc_eax = regs->tf_rax; 359ea0fabbcSTim J. Robbins frame.sf_sc.uc_mcontext.sc_eip = regs->tf_rip; 360ea0fabbcSTim J. Robbins frame.sf_sc.uc_mcontext.sc_cs = regs->tf_cs; 361ea0fabbcSTim J. Robbins frame.sf_sc.uc_mcontext.sc_eflags = regs->tf_rflags; 362ea0fabbcSTim J. Robbins frame.sf_sc.uc_mcontext.sc_esp_at_signal = regs->tf_rsp; 363ea0fabbcSTim J. Robbins frame.sf_sc.uc_mcontext.sc_ss = regs->tf_ss; 364ea0fabbcSTim J. Robbins frame.sf_sc.uc_mcontext.sc_err = regs->tf_err; 365ea0fabbcSTim J. Robbins frame.sf_sc.uc_mcontext.sc_trapno = bsd_to_linux_trapcode(code); 366ea0fabbcSTim J. Robbins 367ea0fabbcSTim J. Robbins #ifdef DEBUG 368ea0fabbcSTim J. Robbins if (ldebug(rt_sendsig)) 369ea0fabbcSTim J. Robbins printf(LMSG("rt_sendsig flags: 0x%x, sp: %p, ss: 0x%x, mask: 0x%x"), 370ea0fabbcSTim J. Robbins frame.sf_sc.uc_stack.ss_flags, td->td_sigstk.ss_sp, 371ea0fabbcSTim J. Robbins td->td_sigstk.ss_size, frame.sf_sc.uc_mcontext.sc_mask); 372ea0fabbcSTim J. Robbins #endif 373ea0fabbcSTim J. Robbins 374ea0fabbcSTim J. Robbins if (copyout(&frame, fp, sizeof(frame)) != 0) { 375ea0fabbcSTim J. Robbins /* 376ea0fabbcSTim J. Robbins * Process has trashed its stack; give it an illegal 377ea0fabbcSTim J. Robbins * instruction to halt it in its tracks. 378ea0fabbcSTim J. Robbins */ 379ea0fabbcSTim J. Robbins #ifdef DEBUG 380ea0fabbcSTim J. Robbins if (ldebug(rt_sendsig)) 381ea0fabbcSTim J. Robbins printf(LMSG("rt_sendsig: bad stack %p, oonstack=%x"), 382ea0fabbcSTim J. Robbins fp, oonstack); 383ea0fabbcSTim J. Robbins #endif 384ea0fabbcSTim J. Robbins PROC_LOCK(p); 385ea0fabbcSTim J. Robbins sigexit(td, SIGILL); 386ea0fabbcSTim J. Robbins } 387ea0fabbcSTim J. Robbins 388ea0fabbcSTim J. Robbins /* 389ea0fabbcSTim J. Robbins * Build context to run handler in. 390ea0fabbcSTim J. Robbins */ 391ea0fabbcSTim J. Robbins regs->tf_rsp = PTROUT(fp); 392ea0fabbcSTim J. Robbins regs->tf_rip = LINUX32_PS_STRINGS - *(p->p_sysent->sv_szsigcode) + 393ea0fabbcSTim J. Robbins linux_sznonrtsigcode; 394ea0fabbcSTim J. Robbins regs->tf_rflags &= ~PSL_T; 395ea0fabbcSTim J. Robbins regs->tf_cs = _ucode32sel; 396ea0fabbcSTim J. Robbins regs->tf_ss = _udatasel; 397ea0fabbcSTim J. Robbins load_ds(_udatasel); 398ea0fabbcSTim J. Robbins td->td_pcb->pcb_ds = _udatasel; 399ea0fabbcSTim J. Robbins load_es(_udatasel); 400ea0fabbcSTim J. Robbins td->td_pcb->pcb_es = _udatasel; 401ea0fabbcSTim J. Robbins PROC_LOCK(p); 402ea0fabbcSTim J. Robbins mtx_lock(&psp->ps_mtx); 403ea0fabbcSTim J. Robbins } 404ea0fabbcSTim J. Robbins 405ea0fabbcSTim J. Robbins 406ea0fabbcSTim J. Robbins /* 407ea0fabbcSTim J. Robbins * Send an interrupt to process. 408ea0fabbcSTim J. Robbins * 409ea0fabbcSTim J. Robbins * Stack is set up to allow sigcode stored 410ea0fabbcSTim J. Robbins * in u. to call routine, followed by kcall 411ea0fabbcSTim J. Robbins * to sigreturn routine below. After sigreturn 412ea0fabbcSTim J. Robbins * resets the signal mask, the stack, and the 413ea0fabbcSTim J. Robbins * frame pointer, it returns to the user 414ea0fabbcSTim J. Robbins * specified pc, psl. 415ea0fabbcSTim J. Robbins */ 416ea0fabbcSTim J. Robbins static void 417ea0fabbcSTim J. Robbins linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) 418ea0fabbcSTim J. Robbins { 419ea0fabbcSTim J. Robbins struct thread *td = curthread; 420ea0fabbcSTim J. Robbins struct proc *p = td->td_proc; 421ea0fabbcSTim J. Robbins struct sigacts *psp; 422ea0fabbcSTim J. Robbins struct trapframe *regs; 423ea0fabbcSTim J. Robbins struct l_sigframe *fp, frame; 424ea0fabbcSTim J. Robbins l_sigset_t lmask; 425ea0fabbcSTim J. Robbins int oonstack, i; 426ea0fabbcSTim J. Robbins 427ea0fabbcSTim J. Robbins PROC_LOCK_ASSERT(p, MA_OWNED); 428ea0fabbcSTim J. Robbins psp = p->p_sigacts; 429ea0fabbcSTim J. Robbins mtx_assert(&psp->ps_mtx, MA_OWNED); 430ea0fabbcSTim J. Robbins if (SIGISMEMBER(psp->ps_siginfo, sig)) { 431ea0fabbcSTim J. Robbins /* Signal handler installed with SA_SIGINFO. */ 432ea0fabbcSTim J. Robbins linux_rt_sendsig(catcher, sig, mask, code); 433ea0fabbcSTim J. Robbins return; 434ea0fabbcSTim J. Robbins } 435ea0fabbcSTim J. Robbins 436ea0fabbcSTim J. Robbins regs = td->td_frame; 437ea0fabbcSTim J. Robbins oonstack = sigonstack(regs->tf_rsp); 438ea0fabbcSTim J. Robbins 439ea0fabbcSTim J. Robbins #ifdef DEBUG 440ea0fabbcSTim J. Robbins if (ldebug(sendsig)) 441ea0fabbcSTim J. Robbins printf(ARGS(sendsig, "%p, %d, %p, %lu"), 442ea0fabbcSTim J. Robbins catcher, sig, (void*)mask, code); 443ea0fabbcSTim J. Robbins #endif 444ea0fabbcSTim J. Robbins 445ea0fabbcSTim J. Robbins /* 446ea0fabbcSTim J. Robbins * Allocate space for the signal handler context. 447ea0fabbcSTim J. Robbins */ 448ea0fabbcSTim J. Robbins if ((td->td_pflags & TDP_ALTSTACK) && !oonstack && 449ea0fabbcSTim J. Robbins SIGISMEMBER(psp->ps_sigonstack, sig)) { 450ea0fabbcSTim J. Robbins fp = (struct l_sigframe *)(td->td_sigstk.ss_sp + 451ea0fabbcSTim J. Robbins td->td_sigstk.ss_size - sizeof(struct l_sigframe)); 452ea0fabbcSTim J. Robbins } else 453ea0fabbcSTim J. Robbins fp = (struct l_sigframe *)regs->tf_rsp - 1; 454ea0fabbcSTim J. Robbins mtx_unlock(&psp->ps_mtx); 455ea0fabbcSTim J. Robbins PROC_UNLOCK(p); 456ea0fabbcSTim J. Robbins 457ea0fabbcSTim J. Robbins /* 458ea0fabbcSTim J. Robbins * Build the argument list for the signal handler. 459ea0fabbcSTim J. Robbins */ 460ea0fabbcSTim J. Robbins if (p->p_sysent->sv_sigtbl) 461ea0fabbcSTim J. Robbins if (sig <= p->p_sysent->sv_sigsize) 462ea0fabbcSTim J. Robbins sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 463ea0fabbcSTim J. Robbins 464ea0fabbcSTim J. Robbins bzero(&frame, sizeof(frame)); 465ea0fabbcSTim J. Robbins 466ea0fabbcSTim J. Robbins frame.sf_handler = PTROUT(catcher); 467ea0fabbcSTim J. Robbins frame.sf_sig = sig; 468ea0fabbcSTim J. Robbins 469ea0fabbcSTim J. Robbins bsd_to_linux_sigset(mask, &lmask); 470ea0fabbcSTim J. Robbins 471ea0fabbcSTim J. Robbins /* 472ea0fabbcSTim J. Robbins * Build the signal context to be used by sigreturn. 473ea0fabbcSTim J. Robbins */ 474ea0fabbcSTim J. Robbins frame.sf_sc.sc_mask = lmask.__bits[0]; 475ea0fabbcSTim J. Robbins frame.sf_sc.sc_gs = rgs(); 476ea0fabbcSTim J. Robbins frame.sf_sc.sc_fs = rfs(); 477ea0fabbcSTim J. Robbins __asm __volatile("movl %%es,%0" : "=rm" (frame.sf_sc.sc_es)); 478ea0fabbcSTim J. Robbins __asm __volatile("movl %%ds,%0" : "=rm" (frame.sf_sc.sc_ds)); 479ea0fabbcSTim J. Robbins frame.sf_sc.sc_edi = regs->tf_rdi; 480ea0fabbcSTim J. Robbins frame.sf_sc.sc_esi = regs->tf_rsi; 481ea0fabbcSTim J. Robbins frame.sf_sc.sc_ebp = regs->tf_rbp; 482ea0fabbcSTim J. Robbins frame.sf_sc.sc_ebx = regs->tf_rbx; 483ea0fabbcSTim J. Robbins frame.sf_sc.sc_edx = regs->tf_rdx; 484ea0fabbcSTim J. Robbins frame.sf_sc.sc_ecx = regs->tf_rcx; 485ea0fabbcSTim J. Robbins frame.sf_sc.sc_eax = regs->tf_rax; 486ea0fabbcSTim J. Robbins frame.sf_sc.sc_eip = regs->tf_rip; 487ea0fabbcSTim J. Robbins frame.sf_sc.sc_cs = regs->tf_cs; 488ea0fabbcSTim J. Robbins frame.sf_sc.sc_eflags = regs->tf_rflags; 489ea0fabbcSTim J. Robbins frame.sf_sc.sc_esp_at_signal = regs->tf_rsp; 490ea0fabbcSTim J. Robbins frame.sf_sc.sc_ss = regs->tf_ss; 491ea0fabbcSTim J. Robbins frame.sf_sc.sc_err = regs->tf_err; 492ea0fabbcSTim J. Robbins frame.sf_sc.sc_trapno = bsd_to_linux_trapcode(code); 493ea0fabbcSTim J. Robbins 494ea0fabbcSTim J. Robbins for (i = 0; i < (LINUX_NSIG_WORDS-1); i++) 495ea0fabbcSTim J. Robbins frame.sf_extramask[i] = lmask.__bits[i+1]; 496ea0fabbcSTim J. Robbins 497ea0fabbcSTim J. Robbins if (copyout(&frame, fp, sizeof(frame)) != 0) { 498ea0fabbcSTim J. Robbins /* 499ea0fabbcSTim J. Robbins * Process has trashed its stack; give it an illegal 500ea0fabbcSTim J. Robbins * instruction to halt it in its tracks. 501ea0fabbcSTim J. Robbins */ 502ea0fabbcSTim J. Robbins PROC_LOCK(p); 503ea0fabbcSTim J. Robbins sigexit(td, SIGILL); 504ea0fabbcSTim J. Robbins } 505ea0fabbcSTim J. Robbins 506ea0fabbcSTim J. Robbins /* 507ea0fabbcSTim J. Robbins * Build context to run handler in. 508ea0fabbcSTim J. Robbins */ 509ea0fabbcSTim J. Robbins regs->tf_rsp = PTROUT(fp); 510ea0fabbcSTim J. Robbins regs->tf_rip = LINUX32_PS_STRINGS - *(p->p_sysent->sv_szsigcode); 511ea0fabbcSTim J. Robbins regs->tf_rflags &= ~PSL_T; 512ea0fabbcSTim J. Robbins regs->tf_cs = _ucode32sel; 513ea0fabbcSTim J. Robbins regs->tf_ss = _udatasel; 514ea0fabbcSTim J. Robbins load_ds(_udatasel); 515ea0fabbcSTim J. Robbins td->td_pcb->pcb_ds = _udatasel; 516ea0fabbcSTim J. Robbins load_es(_udatasel); 517ea0fabbcSTim J. Robbins td->td_pcb->pcb_es = _udatasel; 518ea0fabbcSTim J. Robbins PROC_LOCK(p); 519ea0fabbcSTim J. Robbins mtx_lock(&psp->ps_mtx); 520ea0fabbcSTim J. Robbins } 521ea0fabbcSTim J. Robbins 522ea0fabbcSTim J. Robbins /* 523ea0fabbcSTim J. Robbins * System call to cleanup state after a signal 524ea0fabbcSTim J. Robbins * has been taken. Reset signal mask and 525ea0fabbcSTim J. Robbins * stack state from context left by sendsig (above). 526ea0fabbcSTim J. Robbins * Return to previous pc and psl as specified by 527ea0fabbcSTim J. Robbins * context left by sendsig. Check carefully to 528ea0fabbcSTim J. Robbins * make sure that the user has not modified the 529ea0fabbcSTim J. Robbins * psl to gain improper privileges or to cause 530ea0fabbcSTim J. Robbins * a machine fault. 531ea0fabbcSTim J. Robbins */ 532ea0fabbcSTim J. Robbins int 533ea0fabbcSTim J. Robbins linux_sigreturn(struct thread *td, struct linux_sigreturn_args *args) 534ea0fabbcSTim J. Robbins { 535ea0fabbcSTim J. Robbins struct proc *p = td->td_proc; 536ea0fabbcSTim J. Robbins struct l_sigframe frame; 537ea0fabbcSTim J. Robbins struct trapframe *regs; 538ea0fabbcSTim J. Robbins l_sigset_t lmask; 539ea0fabbcSTim J. Robbins int eflags, i; 540ea0fabbcSTim J. Robbins 541ea0fabbcSTim J. Robbins regs = td->td_frame; 542ea0fabbcSTim J. Robbins 543ea0fabbcSTim J. Robbins #ifdef DEBUG 544ea0fabbcSTim J. Robbins if (ldebug(sigreturn)) 545ea0fabbcSTim J. Robbins printf(ARGS(sigreturn, "%p"), (void *)args->sfp); 546ea0fabbcSTim J. Robbins #endif 547ea0fabbcSTim J. Robbins /* 548ea0fabbcSTim J. Robbins * The trampoline code hands us the sigframe. 549ea0fabbcSTim J. Robbins * It is unsafe to keep track of it ourselves, in the event that a 550ea0fabbcSTim J. Robbins * program jumps out of a signal handler. 551ea0fabbcSTim J. Robbins */ 552ea0fabbcSTim J. Robbins if (copyin(args->sfp, &frame, sizeof(frame)) != 0) 553ea0fabbcSTim J. Robbins return (EFAULT); 554ea0fabbcSTim J. Robbins 555ea0fabbcSTim J. Robbins /* 556ea0fabbcSTim J. Robbins * Check for security violations. 557ea0fabbcSTim J. Robbins */ 558ea0fabbcSTim J. Robbins #define EFLAGS_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) 559ea0fabbcSTim J. Robbins eflags = frame.sf_sc.sc_eflags; 560ea0fabbcSTim J. Robbins /* 561ea0fabbcSTim J. Robbins * XXX do allow users to change the privileged flag PSL_RF. The 562ea0fabbcSTim J. Robbins * cpu sets PSL_RF in tf_eflags for faults. Debuggers should 563ea0fabbcSTim J. Robbins * sometimes set it there too. tf_eflags is kept in the signal 564ea0fabbcSTim J. Robbins * context during signal handling and there is no other place 565ea0fabbcSTim J. Robbins * to remember it, so the PSL_RF bit may be corrupted by the 566ea0fabbcSTim J. Robbins * signal handler without us knowing. Corruption of the PSL_RF 567ea0fabbcSTim J. Robbins * bit at worst causes one more or one less debugger trap, so 568ea0fabbcSTim J. Robbins * allowing it is fairly harmless. 569ea0fabbcSTim J. Robbins */ 570ea0fabbcSTim J. Robbins if (!EFLAGS_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) 571ea0fabbcSTim J. Robbins return(EINVAL); 572ea0fabbcSTim J. Robbins 573ea0fabbcSTim J. Robbins /* 574ea0fabbcSTim J. Robbins * Don't allow users to load a valid privileged %cs. Let the 575ea0fabbcSTim J. Robbins * hardware check for invalid selectors, excess privilege in 576ea0fabbcSTim J. Robbins * other selectors, invalid %eip's and invalid %esp's. 577ea0fabbcSTim J. Robbins */ 578ea0fabbcSTim J. Robbins #define CS_SECURE(cs) (ISPL(cs) == SEL_UPL) 579ea0fabbcSTim J. Robbins if (!CS_SECURE(frame.sf_sc.sc_cs)) { 580ea0fabbcSTim J. Robbins trapsignal(td, SIGBUS, T_PROTFLT); 581ea0fabbcSTim J. Robbins return(EINVAL); 582ea0fabbcSTim J. Robbins } 583ea0fabbcSTim J. Robbins 584ea0fabbcSTim J. Robbins lmask.__bits[0] = frame.sf_sc.sc_mask; 585ea0fabbcSTim J. Robbins for (i = 0; i < (LINUX_NSIG_WORDS-1); i++) 586ea0fabbcSTim J. Robbins lmask.__bits[i+1] = frame.sf_extramask[i]; 587ea0fabbcSTim J. Robbins PROC_LOCK(p); 588ea0fabbcSTim J. Robbins linux_to_bsd_sigset(&lmask, &td->td_sigmask); 589ea0fabbcSTim J. Robbins SIG_CANTMASK(td->td_sigmask); 590ea0fabbcSTim J. Robbins signotify(td); 591ea0fabbcSTim J. Robbins PROC_UNLOCK(p); 592ea0fabbcSTim J. Robbins 593ea0fabbcSTim J. Robbins /* 594ea0fabbcSTim J. Robbins * Restore signal context. 595ea0fabbcSTim J. Robbins */ 596ea0fabbcSTim J. Robbins /* Selectors were restored by the trampoline. */ 597ea0fabbcSTim J. Robbins regs->tf_rdi = frame.sf_sc.sc_edi; 598ea0fabbcSTim J. Robbins regs->tf_rsi = frame.sf_sc.sc_esi; 599ea0fabbcSTim J. Robbins regs->tf_rbp = frame.sf_sc.sc_ebp; 600ea0fabbcSTim J. Robbins regs->tf_rbx = frame.sf_sc.sc_ebx; 601ea0fabbcSTim J. Robbins regs->tf_rdx = frame.sf_sc.sc_edx; 602ea0fabbcSTim J. Robbins regs->tf_rcx = frame.sf_sc.sc_ecx; 603ea0fabbcSTim J. Robbins regs->tf_rax = frame.sf_sc.sc_eax; 604ea0fabbcSTim J. Robbins regs->tf_rip = frame.sf_sc.sc_eip; 605ea0fabbcSTim J. Robbins regs->tf_cs = frame.sf_sc.sc_cs; 606ea0fabbcSTim J. Robbins regs->tf_rflags = eflags; 607ea0fabbcSTim J. Robbins regs->tf_rsp = frame.sf_sc.sc_esp_at_signal; 608ea0fabbcSTim J. Robbins regs->tf_ss = frame.sf_sc.sc_ss; 609ea0fabbcSTim J. Robbins 610ea0fabbcSTim J. Robbins return (EJUSTRETURN); 611ea0fabbcSTim J. Robbins } 612ea0fabbcSTim J. Robbins 613ea0fabbcSTim J. Robbins /* 614ea0fabbcSTim J. Robbins * System call to cleanup state after a signal 615ea0fabbcSTim J. Robbins * has been taken. Reset signal mask and 616ea0fabbcSTim J. Robbins * stack state from context left by rt_sendsig (above). 617ea0fabbcSTim J. Robbins * Return to previous pc and psl as specified by 618ea0fabbcSTim J. Robbins * context left by sendsig. Check carefully to 619ea0fabbcSTim J. Robbins * make sure that the user has not modified the 620ea0fabbcSTim J. Robbins * psl to gain improper privileges or to cause 621ea0fabbcSTim J. Robbins * a machine fault. 622ea0fabbcSTim J. Robbins */ 623ea0fabbcSTim J. Robbins int 624ea0fabbcSTim J. Robbins linux_rt_sigreturn(struct thread *td, struct linux_rt_sigreturn_args *args) 625ea0fabbcSTim J. Robbins { 626ea0fabbcSTim J. Robbins struct proc *p = td->td_proc; 627ea0fabbcSTim J. Robbins struct l_ucontext uc; 628ea0fabbcSTim J. Robbins struct l_sigcontext *context; 629ea0fabbcSTim J. Robbins l_stack_t *lss; 630ea0fabbcSTim J. Robbins stack_t ss; 631ea0fabbcSTim J. Robbins struct trapframe *regs; 632ea0fabbcSTim J. Robbins int eflags; 633ea0fabbcSTim J. Robbins 634ea0fabbcSTim J. Robbins regs = td->td_frame; 635ea0fabbcSTim J. Robbins 636ea0fabbcSTim J. Robbins #ifdef DEBUG 637ea0fabbcSTim J. Robbins if (ldebug(rt_sigreturn)) 638ea0fabbcSTim J. Robbins printf(ARGS(rt_sigreturn, "%p"), (void *)args->ucp); 639ea0fabbcSTim J. Robbins #endif 640ea0fabbcSTim J. Robbins /* 641ea0fabbcSTim J. Robbins * The trampoline code hands us the ucontext. 642ea0fabbcSTim J. Robbins * It is unsafe to keep track of it ourselves, in the event that a 643ea0fabbcSTim J. Robbins * program jumps out of a signal handler. 644ea0fabbcSTim J. Robbins */ 645ea0fabbcSTim J. Robbins if (copyin(args->ucp, &uc, sizeof(uc)) != 0) 646ea0fabbcSTim J. Robbins return (EFAULT); 647ea0fabbcSTim J. Robbins 648ea0fabbcSTim J. Robbins context = &uc.uc_mcontext; 649ea0fabbcSTim J. Robbins 650ea0fabbcSTim J. Robbins /* 651ea0fabbcSTim J. Robbins * Check for security violations. 652ea0fabbcSTim J. Robbins */ 653ea0fabbcSTim J. Robbins #define EFLAGS_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) 654ea0fabbcSTim J. Robbins eflags = context->sc_eflags; 655ea0fabbcSTim J. Robbins /* 656ea0fabbcSTim J. Robbins * XXX do allow users to change the privileged flag PSL_RF. The 657ea0fabbcSTim J. Robbins * cpu sets PSL_RF in tf_eflags for faults. Debuggers should 658ea0fabbcSTim J. Robbins * sometimes set it there too. tf_eflags is kept in the signal 659ea0fabbcSTim J. Robbins * context during signal handling and there is no other place 660ea0fabbcSTim J. Robbins * to remember it, so the PSL_RF bit may be corrupted by the 661ea0fabbcSTim J. Robbins * signal handler without us knowing. Corruption of the PSL_RF 662ea0fabbcSTim J. Robbins * bit at worst causes one more or one less debugger trap, so 663ea0fabbcSTim J. Robbins * allowing it is fairly harmless. 664ea0fabbcSTim J. Robbins */ 665ea0fabbcSTim J. Robbins if (!EFLAGS_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) 666ea0fabbcSTim J. Robbins return(EINVAL); 667ea0fabbcSTim J. Robbins 668ea0fabbcSTim J. Robbins /* 669ea0fabbcSTim J. Robbins * Don't allow users to load a valid privileged %cs. Let the 670ea0fabbcSTim J. Robbins * hardware check for invalid selectors, excess privilege in 671ea0fabbcSTim J. Robbins * other selectors, invalid %eip's and invalid %esp's. 672ea0fabbcSTim J. Robbins */ 673ea0fabbcSTim J. Robbins #define CS_SECURE(cs) (ISPL(cs) == SEL_UPL) 674ea0fabbcSTim J. Robbins if (!CS_SECURE(context->sc_cs)) { 675ea0fabbcSTim J. Robbins trapsignal(td, SIGBUS, T_PROTFLT); 676ea0fabbcSTim J. Robbins return(EINVAL); 677ea0fabbcSTim J. Robbins } 678ea0fabbcSTim J. Robbins 679ea0fabbcSTim J. Robbins PROC_LOCK(p); 680ea0fabbcSTim J. Robbins linux_to_bsd_sigset(&uc.uc_sigmask, &td->td_sigmask); 681ea0fabbcSTim J. Robbins SIG_CANTMASK(td->td_sigmask); 682ea0fabbcSTim J. Robbins signotify(td); 683ea0fabbcSTim J. Robbins PROC_UNLOCK(p); 684ea0fabbcSTim J. Robbins 685ea0fabbcSTim J. Robbins /* 686ea0fabbcSTim J. Robbins * Restore signal context 687ea0fabbcSTim J. Robbins */ 688ea0fabbcSTim J. Robbins /* Selectors were restored by the trampoline. */ 689ea0fabbcSTim J. Robbins regs->tf_rdi = context->sc_edi; 690ea0fabbcSTim J. Robbins regs->tf_rsi = context->sc_esi; 691ea0fabbcSTim J. Robbins regs->tf_rbp = context->sc_ebp; 692ea0fabbcSTim J. Robbins regs->tf_rbx = context->sc_ebx; 693ea0fabbcSTim J. Robbins regs->tf_rdx = context->sc_edx; 694ea0fabbcSTim J. Robbins regs->tf_rcx = context->sc_ecx; 695ea0fabbcSTim J. Robbins regs->tf_rax = context->sc_eax; 696ea0fabbcSTim J. Robbins regs->tf_rip = context->sc_eip; 697ea0fabbcSTim J. Robbins regs->tf_cs = context->sc_cs; 698ea0fabbcSTim J. Robbins regs->tf_rflags = eflags; 699ea0fabbcSTim J. Robbins regs->tf_rsp = context->sc_esp_at_signal; 700ea0fabbcSTim J. Robbins regs->tf_ss = context->sc_ss; 701ea0fabbcSTim J. Robbins 702ea0fabbcSTim J. Robbins /* 703ea0fabbcSTim J. Robbins * call sigaltstack & ignore results.. 704ea0fabbcSTim J. Robbins */ 705ea0fabbcSTim J. Robbins lss = &uc.uc_stack; 706ea0fabbcSTim J. Robbins ss.ss_sp = PTRIN(lss->ss_sp); 707ea0fabbcSTim J. Robbins ss.ss_size = lss->ss_size; 708ea0fabbcSTim J. Robbins ss.ss_flags = linux_to_bsd_sigaltstack(lss->ss_flags); 709ea0fabbcSTim J. Robbins 710ea0fabbcSTim J. Robbins #ifdef DEBUG 711ea0fabbcSTim J. Robbins if (ldebug(rt_sigreturn)) 712ea0fabbcSTim J. Robbins printf(LMSG("rt_sigret flags: 0x%x, sp: %p, ss: 0x%x, mask: 0x%x"), 713ea0fabbcSTim J. Robbins ss.ss_flags, ss.ss_sp, ss.ss_size, context->sc_mask); 714ea0fabbcSTim J. Robbins #endif 715ea0fabbcSTim J. Robbins (void)kern_sigaltstack(td, &ss, NULL); 716ea0fabbcSTim J. Robbins 717ea0fabbcSTim J. Robbins return (EJUSTRETURN); 718ea0fabbcSTim J. Robbins } 719ea0fabbcSTim J. Robbins 720ea0fabbcSTim J. Robbins /* 721ea0fabbcSTim J. Robbins * MPSAFE 722ea0fabbcSTim J. Robbins */ 723ea0fabbcSTim J. Robbins static void 724ea0fabbcSTim J. Robbins linux_prepsyscall(struct trapframe *tf, int *args, u_int *code, caddr_t *params) 725ea0fabbcSTim J. Robbins { 726ea0fabbcSTim J. Robbins args[0] = tf->tf_rbx; 727ea0fabbcSTim J. Robbins args[1] = tf->tf_rcx; 728ea0fabbcSTim J. Robbins args[2] = tf->tf_rdx; 729ea0fabbcSTim J. Robbins args[3] = tf->tf_rsi; 730ea0fabbcSTim J. Robbins args[4] = tf->tf_rdi; 731ea0fabbcSTim J. Robbins args[5] = tf->tf_rbp; /* Unconfirmed */ 732ea0fabbcSTim J. Robbins *params = NULL; /* no copyin */ 733ea0fabbcSTim J. Robbins } 734ea0fabbcSTim J. Robbins 735ea0fabbcSTim J. Robbins /* 736ea0fabbcSTim J. Robbins * If a linux binary is exec'ing something, try this image activator 737ea0fabbcSTim J. Robbins * first. We override standard shell script execution in order to 738ea0fabbcSTim J. Robbins * be able to modify the interpreter path. We only do this if a linux 739ea0fabbcSTim J. Robbins * binary is doing the exec, so we do not create an EXEC module for it. 740ea0fabbcSTim J. Robbins */ 741ea0fabbcSTim J. Robbins static int exec_linux_imgact_try(struct image_params *iparams); 742ea0fabbcSTim J. Robbins 743ea0fabbcSTim J. Robbins static int 744ea0fabbcSTim J. Robbins exec_linux_imgact_try(struct image_params *imgp) 745ea0fabbcSTim J. Robbins { 746ea0fabbcSTim J. Robbins const char *head = (const char *)imgp->image_header; 747ea0fabbcSTim J. Robbins int error = -1; 748ea0fabbcSTim J. Robbins 749ea0fabbcSTim J. Robbins /* 750ea0fabbcSTim J. Robbins * The interpreter for shell scripts run from a linux binary needs 751ea0fabbcSTim J. Robbins * to be located in /compat/linux if possible in order to recursively 752ea0fabbcSTim J. Robbins * maintain linux path emulation. 753ea0fabbcSTim J. Robbins */ 754ea0fabbcSTim J. Robbins if (((const short *)head)[0] == SHELLMAGIC) { 755ea0fabbcSTim J. Robbins /* 756ea0fabbcSTim J. Robbins * Run our normal shell image activator. If it succeeds attempt 757ea0fabbcSTim J. Robbins * to use the alternate path for the interpreter. If an alternate 758ea0fabbcSTim J. Robbins * path is found, use our stringspace to store it. 759ea0fabbcSTim J. Robbins */ 760ea0fabbcSTim J. Robbins if ((error = exec_shell_imgact(imgp)) == 0) { 761ea0fabbcSTim J. Robbins char *rpath = NULL; 762ea0fabbcSTim J. Robbins 763ea0fabbcSTim J. Robbins linux_emul_find(FIRST_THREAD_IN_PROC(imgp->proc), NULL, 764ea0fabbcSTim J. Robbins imgp->interpreter_name, &rpath, 0); 765ea0fabbcSTim J. Robbins if (rpath != imgp->interpreter_name) { 766ea0fabbcSTim J. Robbins int len = strlen(rpath) + 1; 767ea0fabbcSTim J. Robbins 768ea0fabbcSTim J. Robbins if (len <= MAXSHELLCMDLEN) { 769ea0fabbcSTim J. Robbins memcpy(imgp->interpreter_name, rpath, len); 770ea0fabbcSTim J. Robbins } 771ea0fabbcSTim J. Robbins free(rpath, M_TEMP); 772ea0fabbcSTim J. Robbins } 773ea0fabbcSTim J. Robbins } 774ea0fabbcSTim J. Robbins } 775ea0fabbcSTim J. Robbins return(error); 776ea0fabbcSTim J. Robbins } 777ea0fabbcSTim J. Robbins 778ea0fabbcSTim J. Robbins /* 779ea0fabbcSTim J. Robbins * Clear registers on exec 780ea0fabbcSTim J. Robbins * XXX copied from ia32_signal.c. 781ea0fabbcSTim J. Robbins */ 782ea0fabbcSTim J. Robbins static void 783ea0fabbcSTim J. Robbins exec_linux_setregs(td, entry, stack, ps_strings) 784ea0fabbcSTim J. Robbins struct thread *td; 785ea0fabbcSTim J. Robbins u_long entry; 786ea0fabbcSTim J. Robbins u_long stack; 787ea0fabbcSTim J. Robbins u_long ps_strings; 788ea0fabbcSTim J. Robbins { 789ea0fabbcSTim J. Robbins struct trapframe *regs = td->td_frame; 790ea0fabbcSTim J. Robbins struct pcb *pcb = td->td_pcb; 791ea0fabbcSTim J. Robbins 792ea0fabbcSTim J. Robbins wrmsr(MSR_FSBASE, 0); 793ea0fabbcSTim J. Robbins wrmsr(MSR_KGSBASE, 0); /* User value while we're in the kernel */ 794ea0fabbcSTim J. Robbins pcb->pcb_fsbase = 0; 795ea0fabbcSTim J. Robbins pcb->pcb_gsbase = 0; 796ea0fabbcSTim J. Robbins load_ds(_udatasel); 797ea0fabbcSTim J. Robbins load_es(_udatasel); 798ea0fabbcSTim J. Robbins load_fs(_udatasel); 799ea0fabbcSTim J. Robbins load_gs(0); 800ea0fabbcSTim J. Robbins pcb->pcb_ds = _udatasel; 801ea0fabbcSTim J. Robbins pcb->pcb_es = _udatasel; 802ea0fabbcSTim J. Robbins pcb->pcb_fs = _udatasel; 803ea0fabbcSTim J. Robbins pcb->pcb_gs = 0; 804ea0fabbcSTim J. Robbins 805ea0fabbcSTim J. Robbins bzero((char *)regs, sizeof(struct trapframe)); 806ea0fabbcSTim J. Robbins regs->tf_rip = entry; 807ea0fabbcSTim J. Robbins regs->tf_rsp = stack; 808ea0fabbcSTim J. Robbins regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T); 809ea0fabbcSTim J. Robbins regs->tf_ss = _udatasel; 810ea0fabbcSTim J. Robbins regs->tf_cs = _ucode32sel; 811ea0fabbcSTim J. Robbins regs->tf_rbx = ps_strings; 812ea0fabbcSTim J. Robbins load_cr0(rcr0() | CR0_MP | CR0_TS); 813ea0fabbcSTim J. Robbins 814ea0fabbcSTim J. Robbins /* Return via doreti so that we can change to a different %cs */ 815ea0fabbcSTim J. Robbins pcb->pcb_flags |= PCB_FULLCTX; 816ea0fabbcSTim J. Robbins td->td_retval[1] = 0; 817ea0fabbcSTim J. Robbins } 818ea0fabbcSTim J. Robbins 819ea0fabbcSTim J. Robbins /* 820ea0fabbcSTim J. Robbins * XXX copied from ia32_sysvec.c. 821ea0fabbcSTim J. Robbins */ 822ea0fabbcSTim J. Robbins static register_t * 823ea0fabbcSTim J. Robbins linux_copyout_strings(struct image_params *imgp) 824ea0fabbcSTim J. Robbins { 825ea0fabbcSTim J. Robbins int argc, envc; 826ea0fabbcSTim J. Robbins u_int32_t *vectp; 827ea0fabbcSTim J. Robbins char *stringp, *destp; 828ea0fabbcSTim J. Robbins u_int32_t *stack_base; 829ea0fabbcSTim J. Robbins struct linux32_ps_strings *arginfo; 830ea0fabbcSTim J. Robbins int sigcodesz; 831ea0fabbcSTim J. Robbins 832ea0fabbcSTim J. Robbins /* 833ea0fabbcSTim J. Robbins * Calculate string base and vector table pointers. 834ea0fabbcSTim J. Robbins * Also deal with signal trampoline code for this exec type. 835ea0fabbcSTim J. Robbins */ 836ea0fabbcSTim J. Robbins arginfo = (struct linux32_ps_strings *)LINUX32_PS_STRINGS; 837ea0fabbcSTim J. Robbins sigcodesz = *(imgp->proc->p_sysent->sv_szsigcode); 838ea0fabbcSTim J. Robbins destp = (caddr_t)arginfo - sigcodesz - SPARE_USRSPACE - 839ea0fabbcSTim J. Robbins roundup((ARG_MAX - imgp->stringspace), sizeof(char *)); 840ea0fabbcSTim J. Robbins 841ea0fabbcSTim J. Robbins /* 842ea0fabbcSTim J. Robbins * install sigcode 843ea0fabbcSTim J. Robbins */ 844ea0fabbcSTim J. Robbins if (sigcodesz) 845ea0fabbcSTim J. Robbins copyout(imgp->proc->p_sysent->sv_sigcode, 846ea0fabbcSTim J. Robbins ((caddr_t)arginfo - sigcodesz), szsigcode); 847ea0fabbcSTim J. Robbins 848ea0fabbcSTim J. Robbins /* 849ea0fabbcSTim J. Robbins * If we have a valid auxargs ptr, prepare some room 850ea0fabbcSTim J. Robbins * on the stack. 851ea0fabbcSTim J. Robbins */ 852ea0fabbcSTim J. Robbins if (imgp->auxargs) { 853ea0fabbcSTim J. Robbins /* 854ea0fabbcSTim J. Robbins * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for 855ea0fabbcSTim J. Robbins * lower compatibility. 856ea0fabbcSTim J. Robbins */ 857ea0fabbcSTim J. Robbins imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size 858ea0fabbcSTim J. Robbins : (AT_COUNT * 2); 859ea0fabbcSTim J. Robbins /* 860ea0fabbcSTim J. Robbins * The '+ 2' is for the null pointers at the end of each of 861ea0fabbcSTim J. Robbins * the arg and env vector sets,and imgp->auxarg_size is room 862ea0fabbcSTim J. Robbins * for argument of Runtime loader. 863ea0fabbcSTim J. Robbins */ 864ea0fabbcSTim J. Robbins vectp = (u_int32_t *) (destp - (imgp->argc + imgp->envc + 2 + 865ea0fabbcSTim J. Robbins imgp->auxarg_size) * sizeof(u_int32_t)); 866ea0fabbcSTim J. Robbins 867ea0fabbcSTim J. Robbins } else 868ea0fabbcSTim J. Robbins /* 869ea0fabbcSTim J. Robbins * The '+ 2' is for the null pointers at the end of each of 870ea0fabbcSTim J. Robbins * the arg and env vector sets 871ea0fabbcSTim J. Robbins */ 872ea0fabbcSTim J. Robbins vectp = (u_int32_t *) 873ea0fabbcSTim J. Robbins (destp - (imgp->argc + imgp->envc + 2) * sizeof(u_int32_t)); 874ea0fabbcSTim J. Robbins 875ea0fabbcSTim J. Robbins /* 876ea0fabbcSTim J. Robbins * vectp also becomes our initial stack base 877ea0fabbcSTim J. Robbins */ 878ea0fabbcSTim J. Robbins stack_base = vectp; 879ea0fabbcSTim J. Robbins 880ea0fabbcSTim J. Robbins stringp = imgp->stringbase; 881ea0fabbcSTim J. Robbins argc = imgp->argc; 882ea0fabbcSTim J. Robbins envc = imgp->envc; 883ea0fabbcSTim J. Robbins /* 884ea0fabbcSTim J. Robbins * Copy out strings - arguments and environment. 885ea0fabbcSTim J. Robbins */ 886ea0fabbcSTim J. Robbins copyout(stringp, destp, ARG_MAX - imgp->stringspace); 887ea0fabbcSTim J. Robbins 888ea0fabbcSTim J. Robbins /* 889ea0fabbcSTim J. Robbins * Fill in "ps_strings" struct for ps, w, etc. 890ea0fabbcSTim J. Robbins */ 891ea0fabbcSTim J. Robbins suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp); 892ea0fabbcSTim J. Robbins suword32(&arginfo->ps_nargvstr, argc); 893ea0fabbcSTim J. Robbins 894ea0fabbcSTim J. Robbins /* 895ea0fabbcSTim J. Robbins * Fill in argument portion of vector table. 896ea0fabbcSTim J. Robbins */ 897ea0fabbcSTim J. Robbins for (; argc > 0; --argc) { 898ea0fabbcSTim J. Robbins suword32(vectp++, (u_int32_t)(intptr_t)destp); 899ea0fabbcSTim J. Robbins while (*stringp++ != 0) 900ea0fabbcSTim J. Robbins destp++; 901ea0fabbcSTim J. Robbins destp++; 902ea0fabbcSTim J. Robbins } 903ea0fabbcSTim J. Robbins 904ea0fabbcSTim J. Robbins /* a null vector table pointer separates the argp's from the envp's */ 905ea0fabbcSTim J. Robbins suword32(vectp++, 0); 906ea0fabbcSTim J. Robbins 907ea0fabbcSTim J. Robbins suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp); 908ea0fabbcSTim J. Robbins suword32(&arginfo->ps_nenvstr, envc); 909ea0fabbcSTim J. Robbins 910ea0fabbcSTim J. Robbins /* 911ea0fabbcSTim J. Robbins * Fill in environment portion of vector table. 912ea0fabbcSTim J. Robbins */ 913ea0fabbcSTim J. Robbins for (; envc > 0; --envc) { 914ea0fabbcSTim J. Robbins suword32(vectp++, (u_int32_t)(intptr_t)destp); 915ea0fabbcSTim J. Robbins while (*stringp++ != 0) 916ea0fabbcSTim J. Robbins destp++; 917ea0fabbcSTim J. Robbins destp++; 918ea0fabbcSTim J. Robbins } 919ea0fabbcSTim J. Robbins 920ea0fabbcSTim J. Robbins /* end of vector table is a null pointer */ 921ea0fabbcSTim J. Robbins suword32(vectp, 0); 922ea0fabbcSTim J. Robbins 923ea0fabbcSTim J. Robbins return ((register_t *)stack_base); 924ea0fabbcSTim J. Robbins } 925ea0fabbcSTim J. Robbins 926ea0fabbcSTim J. Robbins SYSCTL_NODE(_compat, OID_AUTO, linux32, CTLFLAG_RW, 0, 927ea0fabbcSTim J. Robbins "32-bit Linux emulation"); 928ea0fabbcSTim J. Robbins 929ea0fabbcSTim J. Robbins static u_long linux32_maxdsiz = LINUX32_MAXDSIZ; 930ea0fabbcSTim J. Robbins SYSCTL_ULONG(_compat_linux32, OID_AUTO, maxdsiz, CTLFLAG_RW, 931ea0fabbcSTim J. Robbins &linux32_maxdsiz, 0, ""); 932ea0fabbcSTim J. Robbins static u_long linux32_maxssiz = LINUX32_MAXSSIZ; 933ea0fabbcSTim J. Robbins SYSCTL_ULONG(_compat_linux32, OID_AUTO, maxssiz, CTLFLAG_RW, 934ea0fabbcSTim J. Robbins &linux32_maxssiz, 0, ""); 935ea0fabbcSTim J. Robbins static u_long linux32_maxvmem = LINUX32_MAXVMEM; 936ea0fabbcSTim J. Robbins SYSCTL_ULONG(_compat_linux32, OID_AUTO, maxvmem, CTLFLAG_RW, 937ea0fabbcSTim J. Robbins &linux32_maxvmem, 0, ""); 938ea0fabbcSTim J. Robbins 939ea0fabbcSTim J. Robbins /* 940ea0fabbcSTim J. Robbins * XXX copied from ia32_sysvec.c. 941ea0fabbcSTim J. Robbins */ 942ea0fabbcSTim J. Robbins static void 943ea0fabbcSTim J. Robbins linux32_fixlimits(struct image_params *imgp) 944ea0fabbcSTim J. Robbins { 945ea0fabbcSTim J. Robbins struct proc *p = imgp->proc; 946ea0fabbcSTim J. Robbins struct plimit *oldlim, *newlim; 947ea0fabbcSTim J. Robbins 948ea0fabbcSTim J. Robbins if (linux32_maxdsiz == 0 && linux32_maxssiz == 0 && 949ea0fabbcSTim J. Robbins linux32_maxvmem == 0) 950ea0fabbcSTim J. Robbins return; 951ea0fabbcSTim J. Robbins newlim = lim_alloc(); 952ea0fabbcSTim J. Robbins PROC_LOCK(p); 953ea0fabbcSTim J. Robbins oldlim = p->p_limit; 954ea0fabbcSTim J. Robbins lim_copy(newlim, oldlim); 955ea0fabbcSTim J. Robbins if (linux32_maxdsiz != 0) { 956ea0fabbcSTim J. Robbins if (newlim->pl_rlimit[RLIMIT_DATA].rlim_cur > linux32_maxdsiz) 957ea0fabbcSTim J. Robbins newlim->pl_rlimit[RLIMIT_DATA].rlim_cur = linux32_maxdsiz; 958ea0fabbcSTim J. Robbins if (newlim->pl_rlimit[RLIMIT_DATA].rlim_max > linux32_maxdsiz) 959ea0fabbcSTim J. Robbins newlim->pl_rlimit[RLIMIT_DATA].rlim_max = linux32_maxdsiz; 960ea0fabbcSTim J. Robbins } 961ea0fabbcSTim J. Robbins if (linux32_maxssiz != 0) { 962ea0fabbcSTim J. Robbins if (newlim->pl_rlimit[RLIMIT_STACK].rlim_cur > linux32_maxssiz) 963ea0fabbcSTim J. Robbins newlim->pl_rlimit[RLIMIT_STACK].rlim_cur = linux32_maxssiz; 964ea0fabbcSTim J. Robbins if (newlim->pl_rlimit[RLIMIT_STACK].rlim_max > linux32_maxssiz) 965ea0fabbcSTim J. Robbins newlim->pl_rlimit[RLIMIT_STACK].rlim_max = linux32_maxssiz; 966ea0fabbcSTim J. Robbins } 967ea0fabbcSTim J. Robbins if (linux32_maxvmem != 0) { 968ea0fabbcSTim J. Robbins if (newlim->pl_rlimit[RLIMIT_VMEM].rlim_cur > linux32_maxvmem) 969ea0fabbcSTim J. Robbins newlim->pl_rlimit[RLIMIT_VMEM].rlim_cur = linux32_maxvmem; 970ea0fabbcSTim J. Robbins if (newlim->pl_rlimit[RLIMIT_VMEM].rlim_max > linux32_maxvmem) 971ea0fabbcSTim J. Robbins newlim->pl_rlimit[RLIMIT_VMEM].rlim_max = linux32_maxvmem; 972ea0fabbcSTim J. Robbins } 973ea0fabbcSTim J. Robbins p->p_limit = newlim; 974ea0fabbcSTim J. Robbins PROC_UNLOCK(p); 975ea0fabbcSTim J. Robbins lim_free(oldlim); 976ea0fabbcSTim J. Robbins } 977ea0fabbcSTim J. Robbins 978ea0fabbcSTim J. Robbins struct sysentvec elf_linux_sysvec = { 979ea0fabbcSTim J. Robbins LINUX_SYS_MAXSYSCALL, 980ea0fabbcSTim J. Robbins linux_sysent, 981ea0fabbcSTim J. Robbins 0xff, 982ea0fabbcSTim J. Robbins LINUX_SIGTBLSZ, 983ea0fabbcSTim J. Robbins bsd_to_linux_signal, 984ea0fabbcSTim J. Robbins ELAST + 1, 985ea0fabbcSTim J. Robbins bsd_to_linux_errno, 986ea0fabbcSTim J. Robbins translate_traps, 987ea0fabbcSTim J. Robbins elf_linux_fixup, 988ea0fabbcSTim J. Robbins linux_sendsig, 989ea0fabbcSTim J. Robbins linux_sigcode, 990ea0fabbcSTim J. Robbins &linux_szsigcode, 991ea0fabbcSTim J. Robbins linux_prepsyscall, 992ea0fabbcSTim J. Robbins "Linux ELF32", 993ea0fabbcSTim J. Robbins elf32_coredump, 994ea0fabbcSTim J. Robbins exec_linux_imgact_try, 995ea0fabbcSTim J. Robbins LINUX_MINSIGSTKSZ, 996ea0fabbcSTim J. Robbins PAGE_SIZE, 997ea0fabbcSTim J. Robbins VM_MIN_ADDRESS, 998ea0fabbcSTim J. Robbins LINUX32_USRSTACK, 999ea0fabbcSTim J. Robbins LINUX32_USRSTACK, 1000ea0fabbcSTim J. Robbins LINUX32_PS_STRINGS, 1001ea0fabbcSTim J. Robbins VM_PROT_ALL, 1002ea0fabbcSTim J. Robbins linux_copyout_strings, 1003ea0fabbcSTim J. Robbins exec_linux_setregs, 1004ea0fabbcSTim J. Robbins linux32_fixlimits 1005ea0fabbcSTim J. Robbins }; 1006ea0fabbcSTim J. Robbins 1007ea0fabbcSTim J. Robbins static Elf32_Brandinfo linux_brand = { 1008ea0fabbcSTim J. Robbins ELFOSABI_LINUX, 1009ea0fabbcSTim J. Robbins EM_386, 1010ea0fabbcSTim J. Robbins "Linux", 1011ea0fabbcSTim J. Robbins "/compat/linux", 1012ea0fabbcSTim J. Robbins "/lib/ld-linux.so.1", 1013ea0fabbcSTim J. Robbins &elf_linux_sysvec, 1014ea0fabbcSTim J. Robbins NULL, 1015ea0fabbcSTim J. Robbins }; 1016ea0fabbcSTim J. Robbins 1017ea0fabbcSTim J. Robbins static Elf32_Brandinfo linux_glibc2brand = { 1018ea0fabbcSTim J. Robbins ELFOSABI_LINUX, 1019ea0fabbcSTim J. Robbins EM_386, 1020ea0fabbcSTim J. Robbins "Linux", 1021ea0fabbcSTim J. Robbins "/compat/linux", 1022ea0fabbcSTim J. Robbins "/lib/ld-linux.so.2", 1023ea0fabbcSTim J. Robbins &elf_linux_sysvec, 1024ea0fabbcSTim J. Robbins NULL, 1025ea0fabbcSTim J. Robbins }; 1026ea0fabbcSTim J. Robbins 1027ea0fabbcSTim J. Robbins Elf32_Brandinfo *linux_brandlist[] = { 1028ea0fabbcSTim J. Robbins &linux_brand, 1029ea0fabbcSTim J. Robbins &linux_glibc2brand, 1030ea0fabbcSTim J. Robbins NULL 1031ea0fabbcSTim J. Robbins }; 1032ea0fabbcSTim J. Robbins 1033ea0fabbcSTim J. Robbins static int 1034ea0fabbcSTim J. Robbins linux_elf_modevent(module_t mod, int type, void *data) 1035ea0fabbcSTim J. Robbins { 1036ea0fabbcSTim J. Robbins Elf32_Brandinfo **brandinfo; 1037ea0fabbcSTim J. Robbins int error; 1038ea0fabbcSTim J. Robbins struct linux_ioctl_handler **lihp; 1039ea0fabbcSTim J. Robbins 1040ea0fabbcSTim J. Robbins error = 0; 1041ea0fabbcSTim J. Robbins 1042ea0fabbcSTim J. Robbins switch(type) { 1043ea0fabbcSTim J. Robbins case MOD_LOAD: 1044ea0fabbcSTim J. Robbins for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL; 1045ea0fabbcSTim J. Robbins ++brandinfo) 1046ea0fabbcSTim J. Robbins if (elf32_insert_brand_entry(*brandinfo) < 0) 1047ea0fabbcSTim J. Robbins error = EINVAL; 1048ea0fabbcSTim J. Robbins if (error == 0) { 1049ea0fabbcSTim J. Robbins SET_FOREACH(lihp, linux_ioctl_handler_set) 1050ea0fabbcSTim J. Robbins linux_ioctl_register_handler(*lihp); 1051ea0fabbcSTim J. Robbins if (bootverbose) 1052ea0fabbcSTim J. Robbins printf("Linux ELF exec handler installed\n"); 1053ea0fabbcSTim J. Robbins } else 1054ea0fabbcSTim J. Robbins printf("cannot insert Linux ELF brand handler\n"); 1055ea0fabbcSTim J. Robbins break; 1056ea0fabbcSTim J. Robbins case MOD_UNLOAD: 1057ea0fabbcSTim J. Robbins for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL; 1058ea0fabbcSTim J. Robbins ++brandinfo) 1059ea0fabbcSTim J. Robbins if (elf32_brand_inuse(*brandinfo)) 1060ea0fabbcSTim J. Robbins error = EBUSY; 1061ea0fabbcSTim J. Robbins if (error == 0) { 1062ea0fabbcSTim J. Robbins for (brandinfo = &linux_brandlist[0]; 1063ea0fabbcSTim J. Robbins *brandinfo != NULL; ++brandinfo) 1064ea0fabbcSTim J. Robbins if (elf32_remove_brand_entry(*brandinfo) < 0) 1065ea0fabbcSTim J. Robbins error = EINVAL; 1066ea0fabbcSTim J. Robbins } 1067ea0fabbcSTim J. Robbins if (error == 0) { 1068ea0fabbcSTim J. Robbins SET_FOREACH(lihp, linux_ioctl_handler_set) 1069ea0fabbcSTim J. Robbins linux_ioctl_unregister_handler(*lihp); 1070ea0fabbcSTim J. Robbins if (bootverbose) 1071ea0fabbcSTim J. Robbins printf("Linux ELF exec handler removed\n"); 1072ea0fabbcSTim J. Robbins linux_mib_destroy(); 1073ea0fabbcSTim J. Robbins } else 1074ea0fabbcSTim J. Robbins printf("Could not deinstall ELF interpreter entry\n"); 1075ea0fabbcSTim J. Robbins break; 1076ea0fabbcSTim J. Robbins default: 1077ea0fabbcSTim J. Robbins break; 1078ea0fabbcSTim J. Robbins } 1079ea0fabbcSTim J. Robbins return error; 1080ea0fabbcSTim J. Robbins } 1081ea0fabbcSTim J. Robbins 1082ea0fabbcSTim J. Robbins static moduledata_t linux_elf_mod = { 1083ea0fabbcSTim J. Robbins "linuxelf", 1084ea0fabbcSTim J. Robbins linux_elf_modevent, 1085ea0fabbcSTim J. Robbins 0 1086ea0fabbcSTim J. Robbins }; 1087ea0fabbcSTim J. Robbins 1088ea0fabbcSTim J. Robbins DECLARE_MODULE(linuxelf, linux_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY); 1089