ia32_sysvec.c revision 197729
1100384Speter/*- 2100384Speter * Copyright (c) 2002 Doug Rabson 3114987Speter * Copyright (c) 2003 Peter Wemm 4100384Speter * All rights reserved. 5100384Speter * 6100384Speter * Redistribution and use in source and binary forms, with or without 7100384Speter * modification, are permitted provided that the following conditions 8100384Speter * are met: 9100384Speter * 1. Redistributions of source code must retain the above copyright 10100384Speter * notice, this list of conditions and the following disclaimer. 11100384Speter * 2. Redistributions in binary form must reproduce the above copyright 12100384Speter * notice, this list of conditions and the following disclaimer in the 13100384Speter * documentation and/or other materials provided with the distribution. 14100384Speter * 15100384Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16100384Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17100384Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18100384Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19100384Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20100384Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21100384Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22100384Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23100384Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24100384Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25100384Speter * SUCH DAMAGE. 26100384Speter */ 27100384Speter 28118031Sobrien#include <sys/cdefs.h> 29118031Sobrien__FBSDID("$FreeBSD: head/sys/compat/ia32/ia32_sysvec.c 197729 2009-10-03 11:57:21Z bz $"); 30118031Sobrien 31114987Speter#include "opt_compat.h" 32114987Speter 33100384Speter#define __ELF_WORD_SIZE 32 34100384Speter 35100384Speter#include <sys/param.h> 36100384Speter#include <sys/exec.h> 37100384Speter#include <sys/fcntl.h> 38100384Speter#include <sys/imgact.h> 39100384Speter#include <sys/kernel.h> 40100384Speter#include <sys/lock.h> 41100384Speter#include <sys/malloc.h> 42100384Speter#include <sys/mutex.h> 43100384Speter#include <sys/mman.h> 44100384Speter#include <sys/namei.h> 45100384Speter#include <sys/pioctl.h> 46100384Speter#include <sys/proc.h> 47100384Speter#include <sys/procfs.h> 48100384Speter#include <sys/resourcevar.h> 49100384Speter#include <sys/systm.h> 50100384Speter#include <sys/signalvar.h> 51100384Speter#include <sys/stat.h> 52100384Speter#include <sys/sx.h> 53100384Speter#include <sys/syscall.h> 54100384Speter#include <sys/sysctl.h> 55100384Speter#include <sys/sysent.h> 56100384Speter#include <sys/vnode.h> 57100384Speter#include <sys/imgact_elf.h> 58100384Speter 59100384Speter#include <vm/vm.h> 60100384Speter#include <vm/vm_kern.h> 61100384Speter#include <vm/vm_param.h> 62100384Speter#include <vm/pmap.h> 63100384Speter#include <vm/vm_map.h> 64100384Speter#include <vm/vm_object.h> 65100384Speter#include <vm/vm_extern.h> 66100384Speter 67163018Sdavidxu#include <compat/freebsd32/freebsd32_signal.h> 68119336Speter#include <compat/freebsd32/freebsd32_util.h> 69119336Speter#include <compat/freebsd32/freebsd32_proto.h> 70123422Speter#include <compat/freebsd32/freebsd32_syscall.h> 71119336Speter#include <compat/ia32/ia32_signal.h> 72123423Speter#ifdef __amd64__ 73114987Speter#include <machine/psl.h> 74114987Speter#include <machine/segments.h> 75114987Speter#include <machine/specialreg.h> 76123423Speter#else 77123423Speter#include <i386/include/psl.h> 78123423Speter#include <i386/include/segments.h> 79123423Speter#include <i386/include/specialreg.h> 80123423Speter#endif 81100384Speter#include <machine/frame.h> 82100384Speter#include <machine/md_var.h> 83114987Speter#include <machine/pcb.h> 84114987Speter#include <machine/cpufunc.h> 85100384Speter 86121720SpeterCTASSERT(sizeof(struct ia32_mcontext) == 640); 87121720SpeterCTASSERT(sizeof(struct ia32_ucontext) == 704); 88121720SpeterCTASSERT(sizeof(struct ia32_sigframe) == 800); 89163018SdavidxuCTASSERT(sizeof(struct siginfo32) == 64); 90121720Speter#ifdef COMPAT_FREEBSD4 91121720SpeterCTASSERT(sizeof(struct ia32_mcontext4) == 260); 92121720SpeterCTASSERT(sizeof(struct ia32_ucontext4) == 324); 93121720SpeterCTASSERT(sizeof(struct ia32_sigframe4) == 408); 94121720Speter#endif 95121720Speter 96100384Speterstatic register_t *ia32_copyout_strings(struct image_params *imgp); 97169565Sjhbstatic void ia32_fixlimit(struct rlimit *rl, int which); 98100384Speter 99120422SpeterSYSCTL_NODE(_compat, OID_AUTO, ia32, CTLFLAG_RW, 0, "ia32 mode"); 100120422Speter 101171410Sjhbstatic u_long ia32_maxdsiz = IA32_MAXDSIZ; 102171410SjhbSYSCTL_ULONG(_compat_ia32, OID_AUTO, maxdsiz, CTLFLAG_RW, &ia32_maxdsiz, 0, ""); 103172316SjhbTUNABLE_ULONG("compat.ia32.maxdsiz", &ia32_maxdsiz); 104171410Sjhbstatic u_long ia32_maxssiz = IA32_MAXSSIZ; 105171410SjhbSYSCTL_ULONG(_compat_ia32, OID_AUTO, maxssiz, CTLFLAG_RW, &ia32_maxssiz, 0, ""); 106172316SjhbTUNABLE_ULONG("compat.ia32.maxssiz", &ia32_maxssiz); 107171410Sjhbstatic u_long ia32_maxvmem = IA32_MAXVMEM; 108171410SjhbSYSCTL_ULONG(_compat_ia32, OID_AUTO, maxvmem, CTLFLAG_RW, &ia32_maxvmem, 0, ""); 109172316SjhbTUNABLE_ULONG("compat.ia32.maxvmem", &ia32_maxvmem); 110171410Sjhb 111100384Speterstruct sysentvec ia32_freebsd_sysvec = { 112183322Skib .sv_size = FREEBSD32_SYS_MAXSYSCALL, 113183322Skib .sv_table = freebsd32_sysent, 114183322Skib .sv_mask = 0, 115183322Skib .sv_sigsize = 0, 116183322Skib .sv_sigtbl = NULL, 117183322Skib .sv_errsize = 0, 118183322Skib .sv_errtbl = NULL, 119183322Skib .sv_transtrap = NULL, 120183322Skib .sv_fixup = elf32_freebsd_fixup, 121183322Skib .sv_sendsig = ia32_sendsig, 122183322Skib .sv_sigcode = ia32_sigcode, 123183322Skib .sv_szsigcode = &sz_ia32_sigcode, 124183322Skib .sv_prepsyscall = NULL, 125183322Skib .sv_name = "FreeBSD ELF32", 126183322Skib .sv_coredump = elf32_coredump, 127183322Skib .sv_imgact_try = NULL, 128183322Skib .sv_minsigstksz = MINSIGSTKSZ, 129183322Skib .sv_pagesize = IA32_PAGE_SIZE, 130183322Skib .sv_minuser = 0, 131183322Skib .sv_maxuser = FREEBSD32_USRSTACK, 132183322Skib .sv_usrstack = FREEBSD32_USRSTACK, 133183322Skib .sv_psstrings = FREEBSD32_PS_STRINGS, 134183322Skib .sv_stackprot = VM_PROT_ALL, 135183322Skib .sv_copyout_strings = ia32_copyout_strings, 136183322Skib .sv_setregs = ia32_setregs, 137183322Skib .sv_fixlimit = ia32_fixlimit, 138185169Skib .sv_maxssiz = &ia32_maxssiz, 139185169Skib .sv_flags = SV_ABI_FREEBSD | SV_IA32 | SV_ILP32 140100384Speter}; 141100384Speter 142114987Speter 143100384Speterstatic Elf32_Brandinfo ia32_brand_info = { 144183322Skib .brand = ELFOSABI_FREEBSD, 145183322Skib .machine = EM_386, 146183322Skib .compat_3_brand = "FreeBSD", 147183322Skib .emul_path = NULL, 148183322Skib .interp_path = "/libexec/ld-elf.so.1", 149183322Skib .sysvec = &ia32_freebsd_sysvec, 150183322Skib .interp_newpath = "/libexec/ld-elf32.so.1", 151189771Sdchagin .brand_note = &elf32_freebsd_brandnote, 152190708Sdchagin .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE 153183322Skib}; 154100384Speter 155197729SbzSYSINIT(ia32, SI_SUB_EXEC, SI_ORDER_MIDDLE, 156100384Speter (sysinit_cfunc_t) elf32_insert_brand_entry, 157100384Speter &ia32_brand_info); 158100384Speter 159123742Speterstatic Elf32_Brandinfo ia32_brand_oinfo = { 160183322Skib .brand = ELFOSABI_FREEBSD, 161183322Skib .machine = EM_386, 162183322Skib .compat_3_brand = "FreeBSD", 163183322Skib .emul_path = NULL, 164183322Skib .interp_path = "/usr/libexec/ld-elf.so.1", 165183322Skib .sysvec = &ia32_freebsd_sysvec, 166183322Skib .interp_newpath = "/libexec/ld-elf32.so.1", 167189771Sdchagin .brand_note = &elf32_freebsd_brandnote, 168190708Sdchagin .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE 169183322Skib}; 170123742Speter 171123742SpeterSYSINIT(oia32, SI_SUB_EXEC, SI_ORDER_ANY, 172123742Speter (sysinit_cfunc_t) elf32_insert_brand_entry, 173123742Speter &ia32_brand_oinfo); 174123742Speter 175196512Sbzstatic Elf32_Brandinfo kia32_brand_info = { 176196512Sbz .brand = ELFOSABI_FREEBSD, 177196512Sbz .machine = EM_386, 178196512Sbz .compat_3_brand = "FreeBSD", 179196512Sbz .emul_path = NULL, 180196512Sbz .interp_path = "/lib/ld.so.1", 181196512Sbz .sysvec = &ia32_freebsd_sysvec, 182196512Sbz .brand_note = &elf32_kfreebsd_brandnote, 183196653Sbz .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE_MANDATORY 184196512Sbz}; 185133464Smarcel 186196512SbzSYSINIT(kia32, SI_SUB_EXEC, SI_ORDER_ANY, 187196512Sbz (sysinit_cfunc_t) elf32_insert_brand_entry, 188196512Sbz &kia32_brand_info); 189196512Sbz 190196512Sbz 191133464Smarcelvoid 192133464Smarcelelf32_dump_thread(struct thread *td __unused, void *dst __unused, 193133464Smarcel size_t *off __unused) 194133464Smarcel{ 195133464Smarcel} 196133464Smarcel 197133464Smarcel 198119334Speter/* XXX may be freebsd32 MI */ 199100384Speterstatic register_t * 200100384Speteria32_copyout_strings(struct image_params *imgp) 201100384Speter{ 202100384Speter int argc, envc; 203100384Speter u_int32_t *vectp; 204100384Speter char *stringp, *destp; 205100384Speter u_int32_t *stack_base; 206119336Speter struct freebsd32_ps_strings *arginfo; 207189927Skib size_t execpath_len; 208100384Speter int szsigcode; 209100384Speter 210100384Speter /* 211100384Speter * Calculate string base and vector table pointers. 212100384Speter * Also deal with signal trampoline code for this exec type. 213100384Speter */ 214189927Skib if (imgp->execpath != NULL && imgp->auxargs != NULL) 215189927Skib execpath_len = strlen(imgp->execpath) + 1; 216189927Skib else 217189927Skib execpath_len = 0; 218119336Speter arginfo = (struct freebsd32_ps_strings *)FREEBSD32_PS_STRINGS; 219100384Speter szsigcode = *(imgp->proc->p_sysent->sv_szsigcode); 220100384Speter destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE - 221189927Skib roundup(execpath_len, sizeof(char *)) - 222140992Ssobomax roundup((ARG_MAX - imgp->args->stringspace), sizeof(char *)); 223100384Speter 224100384Speter /* 225100384Speter * install sigcode 226100384Speter */ 227100384Speter if (szsigcode) 228100384Speter copyout(imgp->proc->p_sysent->sv_sigcode, 229100384Speter ((caddr_t)arginfo - szsigcode), szsigcode); 230100384Speter 231100384Speter /* 232189927Skib * Copy the image path for the rtld. 233189927Skib */ 234189927Skib if (execpath_len != 0) { 235189927Skib imgp->execpathp = (uintptr_t)arginfo - szsigcode - execpath_len; 236189927Skib copyout(imgp->execpath, (void *)imgp->execpathp, 237189927Skib execpath_len); 238189927Skib } 239189927Skib 240189927Skib /* 241100384Speter * If we have a valid auxargs ptr, prepare some room 242100384Speter * on the stack. 243100384Speter */ 244100384Speter if (imgp->auxargs) { 245100384Speter /* 246100384Speter * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for 247100384Speter * lower compatibility. 248100384Speter */ 249100384Speter imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size 250100384Speter : (AT_COUNT * 2); 251100384Speter /* 252100384Speter * The '+ 2' is for the null pointers at the end of each of 253100384Speter * the arg and env vector sets,and imgp->auxarg_size is room 254100384Speter * for argument of Runtime loader. 255100384Speter */ 256189927Skib vectp = (u_int32_t *) (destp - (imgp->args->argc + 257189927Skib imgp->args->envc + 2 + imgp->auxarg_size + execpath_len) * 258189927Skib sizeof(u_int32_t)); 259100384Speter } else 260100384Speter /* 261100384Speter * The '+ 2' is for the null pointers at the end of each of 262100384Speter * the arg and env vector sets 263100384Speter */ 264100384Speter vectp = (u_int32_t *) 265140992Ssobomax (destp - (imgp->args->argc + imgp->args->envc + 2) * sizeof(u_int32_t)); 266100384Speter 267100384Speter /* 268100384Speter * vectp also becomes our initial stack base 269100384Speter */ 270100384Speter stack_base = vectp; 271100384Speter 272140992Ssobomax stringp = imgp->args->begin_argv; 273140992Ssobomax argc = imgp->args->argc; 274140992Ssobomax envc = imgp->args->envc; 275100384Speter /* 276100384Speter * Copy out strings - arguments and environment. 277100384Speter */ 278140992Ssobomax copyout(stringp, destp, ARG_MAX - imgp->args->stringspace); 279100384Speter 280100384Speter /* 281100384Speter * Fill in "ps_strings" struct for ps, w, etc. 282100384Speter */ 283100384Speter suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp); 284100384Speter suword32(&arginfo->ps_nargvstr, argc); 285100384Speter 286100384Speter /* 287100384Speter * Fill in argument portion of vector table. 288100384Speter */ 289100384Speter for (; argc > 0; --argc) { 290100384Speter suword32(vectp++, (u_int32_t)(intptr_t)destp); 291100384Speter while (*stringp++ != 0) 292100384Speter destp++; 293100384Speter destp++; 294100384Speter } 295100384Speter 296100384Speter /* a null vector table pointer separates the argp's from the envp's */ 297100384Speter suword32(vectp++, 0); 298100384Speter 299100384Speter suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp); 300100384Speter suword32(&arginfo->ps_nenvstr, envc); 301100384Speter 302100384Speter /* 303100384Speter * Fill in environment portion of vector table. 304100384Speter */ 305100384Speter for (; envc > 0; --envc) { 306100384Speter suword32(vectp++, (u_int32_t)(intptr_t)destp); 307100384Speter while (*stringp++ != 0) 308100384Speter destp++; 309100384Speter destp++; 310100384Speter } 311100384Speter 312100384Speter /* end of vector table is a null pointer */ 313100384Speter suword32(vectp, 0); 314100384Speter 315100384Speter return ((register_t *)stack_base); 316100384Speter} 317100384Speter 318120422Speterstatic void 319169565Sjhbia32_fixlimit(struct rlimit *rl, int which) 320120422Speter{ 321120422Speter 322169565Sjhb switch (which) { 323169565Sjhb case RLIMIT_DATA: 324169565Sjhb if (ia32_maxdsiz != 0) { 325169565Sjhb if (rl->rlim_cur > ia32_maxdsiz) 326169565Sjhb rl->rlim_cur = ia32_maxdsiz; 327169565Sjhb if (rl->rlim_max > ia32_maxdsiz) 328169565Sjhb rl->rlim_max = ia32_maxdsiz; 329169565Sjhb } 330169565Sjhb break; 331169565Sjhb case RLIMIT_STACK: 332169565Sjhb if (ia32_maxssiz != 0) { 333169565Sjhb if (rl->rlim_cur > ia32_maxssiz) 334169565Sjhb rl->rlim_cur = ia32_maxssiz; 335169565Sjhb if (rl->rlim_max > ia32_maxssiz) 336169565Sjhb rl->rlim_max = ia32_maxssiz; 337169565Sjhb } 338169565Sjhb break; 339169565Sjhb case RLIMIT_VMEM: 340169565Sjhb if (ia32_maxvmem != 0) { 341169565Sjhb if (rl->rlim_cur > ia32_maxvmem) 342169565Sjhb rl->rlim_cur = ia32_maxvmem; 343169565Sjhb if (rl->rlim_max > ia32_maxvmem) 344169565Sjhb rl->rlim_max = ia32_maxvmem; 345169565Sjhb } 346169565Sjhb break; 347120422Speter } 348120422Speter} 349