imgact_aout.c revision 138128
1885Swollman/* 2885Swollman * Copyright (c) 1993, David Greenman 3885Swollman * All rights reserved. 4885Swollman * 5885Swollman * Redistribution and use in source and binary forms, with or without 6885Swollman * modification, are permitted provided that the following conditions 7885Swollman * are met: 8885Swollman * 1. Redistributions of source code must retain the above copyright 9885Swollman * notice, this list of conditions and the following disclaimer. 10885Swollman * 2. Redistributions in binary form must reproduce the above copyright 11885Swollman * notice, this list of conditions and the following disclaimer in the 12885Swollman * documentation and/or other materials provided with the distribution. 13885Swollman * 14885Swollman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15885Swollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16885Swollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1710625Sdg * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18885Swollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19885Swollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20885Swollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21885Swollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22885Swollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23885Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24885Swollman * SUCH DAMAGE. 25885Swollman */ 26885Swollman 27116182Sobrien#include <sys/cdefs.h> 28116182Sobrien__FBSDID("$FreeBSD: head/sys/kern/imgact_aout.c 138128 2004-11-27 06:46:59Z das $"); 29116182Sobrien 301549Srgrimes#include <sys/param.h> 311549Srgrimes#include <sys/exec.h> 321549Srgrimes#include <sys/imgact.h> 333058Sdg#include <sys/imgact_aout.h> 341549Srgrimes#include <sys/kernel.h> 3576166Smarkm#include <sys/lock.h> 36103181Sbde#include <sys/malloc.h> 3776166Smarkm#include <sys/mutex.h> 3815494Sbde#include <sys/proc.h> 3976166Smarkm#include <sys/resourcevar.h> 4039154Sjdp#include <sys/signalvar.h> 41103181Sbde#include <sys/syscall.h> 422257Ssos#include <sys/sysent.h> 43103181Sbde#include <sys/systm.h> 4415494Sbde#include <sys/vnode.h> 4576166Smarkm 46103181Sbde#include <machine/frame.h> 4739154Sjdp#include <machine/md_var.h> 48885Swollman 491549Srgrimes#include <vm/vm.h> 5012662Sdg#include <vm/pmap.h> 5112662Sdg#include <vm/vm_map.h> 5232446Sdyson#include <vm/vm_object.h> 53103181Sbde#include <vm/vm_param.h> 54885Swollman 5592723Salfredstatic int exec_aout_imgact(struct image_params *imgp); 56102808Sjakestatic int aout_fixup(register_t **stack_base, struct image_params *imgp); 5712568Sbde 5839154Sjdpstruct sysentvec aout_sysvec = { 5939154Sjdp SYS_MAXSYSCALL, 6039154Sjdp sysent, 6139154Sjdp 0, 6239154Sjdp 0, 63102808Sjake NULL, 6439154Sjdp 0, 65102808Sjake NULL, 66102808Sjake NULL, 67102808Sjake aout_fixup, 6839154Sjdp sendsig, 6939154Sjdp sigcode, 7039154Sjdp &szsigcode, 71102808Sjake NULL, 7239154Sjdp "FreeBSD a.out", 7368520Smarcel NULL, 74138128Sdas NULL, 75102808Sjake MINSIGSTKSZ, 76102808Sjake PAGE_SIZE, 77102808Sjake VM_MIN_ADDRESS, 78102808Sjake VM_MAXUSER_ADDRESS, 79102808Sjake USRSTACK, 80102808Sjake PS_STRINGS, 81102808Sjake VM_PROT_ALL, 82102808Sjake exec_copyout_strings, 83120422Speter exec_setregs, 84120422Speter NULL 8539154Sjdp}; 8639154Sjdp 8750901Sbdestatic int 88102808Sjakeaout_fixup(stack_base, imgp) 89102808Sjake register_t **stack_base; 90102808Sjake struct image_params *imgp; 91102808Sjake{ 92102808Sjake 93102808Sjake return (suword(--(*stack_base), imgp->argc)); 94102808Sjake} 95102808Sjake 96102808Sjakestatic int 9712130Sdgexec_aout_imgact(imgp) 9812130Sdg struct image_params *imgp; 99885Swollman{ 10017974Sbde const struct exec *a_out = (const struct exec *) imgp->image_header; 10124848Sdyson struct vmspace *vmspace; 10232446Sdyson struct vnode *vp; 10344469Salc vm_map_t map; 10432446Sdyson vm_object_t object; 10532446Sdyson vm_offset_t text_end, data_end; 10614703Sbde unsigned long virtual_offset; 10712767Sdyson unsigned long file_offset; 108885Swollman unsigned long bss_size; 1093098Sphk int error; 110885Swollman 11179224Sdillon GIANT_REQUIRED; 11279224Sdillon 113885Swollman /* 1146380Ssos * Linux and *BSD binaries look very much alike, 1158876Srgrimes * only the machine id is different: 1169202Srgrimes * 0x64 for Linux, 0x86 for *BSD, 0x00 for BSDI. 11714363Speter * NetBSD is in network byte order.. ugh. 1186380Ssos */ 1199202Srgrimes if (((a_out->a_magic >> 16) & 0xff) != 0x86 && 12014363Speter ((a_out->a_magic >> 16) & 0xff) != 0 && 12114363Speter ((((int)ntohl(a_out->a_magic)) >> 16) & 0xff) != 0x86) 1229202Srgrimes return -1; 1236380Ssos 1246380Ssos /* 125885Swollman * Set file/virtual offset based on a.out variant. 126885Swollman * We do two cases: host byte order and network byte order 127885Swollman * (for NetBSD compatibility) 128885Swollman */ 129885Swollman switch ((int)(a_out->a_magic & 0xffff)) { 130885Swollman case ZMAGIC: 131885Swollman virtual_offset = 0; 132885Swollman if (a_out->a_text) { 13315538Sphk file_offset = PAGE_SIZE; 134885Swollman } else { 135885Swollman /* Bill's "screwball mode" */ 136885Swollman file_offset = 0; 137885Swollman } 138885Swollman break; 139885Swollman case QMAGIC: 14015538Sphk virtual_offset = PAGE_SIZE; 141885Swollman file_offset = 0; 14245270Sjdp /* Pass PS_STRINGS for BSD/OS binaries only. */ 14345270Sjdp if (N_GETMID(*a_out) == MID_ZERO) 144103767Sjake imgp->ps_strings = aout_sysvec.sv_psstrings; 145885Swollman break; 146885Swollman default: 147885Swollman /* NetBSD compatibility */ 148885Swollman switch ((int)(ntohl(a_out->a_magic) & 0xffff)) { 149885Swollman case ZMAGIC: 150885Swollman case QMAGIC: 15115538Sphk virtual_offset = PAGE_SIZE; 152885Swollman file_offset = 0; 153885Swollman break; 154885Swollman default: 155885Swollman return (-1); 156885Swollman } 157885Swollman } 158885Swollman 15915538Sphk bss_size = roundup(a_out->a_bss, PAGE_SIZE); 160885Swollman 161885Swollman /* 162885Swollman * Check various fields in header for validity/bounds. 163885Swollman */ 164885Swollman if (/* entry point must lay with text region */ 165885Swollman a_out->a_entry < virtual_offset || 166885Swollman a_out->a_entry >= virtual_offset + a_out->a_text || 167885Swollman 168885Swollman /* text and data size must each be page rounded */ 16915538Sphk a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) 170885Swollman return (-1); 171885Swollman 172885Swollman /* text + data can't exceed file size */ 17312130Sdg if (a_out->a_data + a_out->a_text > imgp->attr->va_size) 174885Swollman return (EFAULT); 175885Swollman 176885Swollman /* 177885Swollman * text/data/bss must not exceed limits 178885Swollman */ 179125454Sjhb PROC_LOCK(imgp->proc); 180885Swollman if (/* text can't exceed maximum text size */ 18184783Sps a_out->a_text > maxtsiz || 182885Swollman 183885Swollman /* data + bss can't exceed rlimit */ 184125454Sjhb a_out->a_data + bss_size > lim_cur(imgp->proc, RLIMIT_DATA)) { 185125454Sjhb PROC_UNLOCK(imgp->proc); 186885Swollman return (ENOMEM); 187125454Sjhb } 188125454Sjhb PROC_UNLOCK(imgp->proc); 189885Swollman 190885Swollman /* copy in arguments and/or environment from old process */ 19112130Sdg error = exec_extract_strings(imgp); 192885Swollman if (error) 193885Swollman return (error); 194885Swollman 195885Swollman /* 196885Swollman * Destroy old process VM and create a new one (with a new stack) 197885Swollman */ 198103767Sjake exec_new_vmspace(imgp, &aout_sysvec); 199885Swollman 200885Swollman /* 20124848Sdyson * The vm space can be changed by exec_new_vmspace 20224848Sdyson */ 20324848Sdyson vmspace = imgp->proc->p_vmspace; 20424848Sdyson 20532446Sdyson vp = imgp->vp; 20699487Sjeff object = imgp->object; 20744469Salc map = &vmspace->vm_map; 20844469Salc vm_map_lock(map); 20932446Sdyson vm_object_reference(object); 21032446Sdyson 21132446Sdyson text_end = virtual_offset + a_out->a_text; 21244626Salc error = vm_map_insert(map, object, 21332446Sdyson file_offset, 21432446Sdyson virtual_offset, text_end, 21532446Sdyson VM_PROT_READ | VM_PROT_EXECUTE, VM_PROT_ALL, 21647258Salc MAP_COPY_ON_WRITE | MAP_PREFAULT); 21744469Salc if (error) { 21844469Salc vm_map_unlock(map); 219885Swollman return (error); 22044469Salc } 22132446Sdyson data_end = text_end + a_out->a_data; 22232446Sdyson if (a_out->a_data) { 22332446Sdyson vm_object_reference(object); 22444626Salc error = vm_map_insert(map, object, 22532446Sdyson file_offset + a_out->a_text, 22632446Sdyson text_end, data_end, 22732446Sdyson VM_PROT_ALL, VM_PROT_ALL, 22847258Salc MAP_COPY_ON_WRITE | MAP_PREFAULT); 22944469Salc if (error) { 23044469Salc vm_map_unlock(map); 23132446Sdyson return (error); 23244469Salc } 23332446Sdyson } 234885Swollman 23532446Sdyson if (bss_size) { 23644626Salc error = vm_map_insert(map, NULL, 0, 23732446Sdyson data_end, data_end + bss_size, 23832446Sdyson VM_PROT_ALL, VM_PROT_ALL, 0); 23944469Salc if (error) { 24044469Salc vm_map_unlock(map); 2416579Sdg return (error); 24244469Salc } 2436579Sdg } 24444469Salc vm_map_unlock(map); 24544469Salc 246885Swollman /* Fill in process VM information */ 247885Swollman vmspace->vm_tsize = a_out->a_text >> PAGE_SHIFT; 248885Swollman vmspace->vm_dsize = (a_out->a_data + bss_size) >> PAGE_SHIFT; 24937656Sbde vmspace->vm_taddr = (caddr_t) (uintptr_t) virtual_offset; 25037656Sbde vmspace->vm_daddr = (caddr_t) (uintptr_t) 25137656Sbde (virtual_offset + a_out->a_text); 252885Swollman 253885Swollman /* Fill in image_params */ 25412130Sdg imgp->interpreted = 0; 25512130Sdg imgp->entry_addr = a_out->a_entry; 2568876Srgrimes 25712130Sdg imgp->proc->p_sysent = &aout_sysvec; 25810221Sdg 259885Swollman return (0); 260885Swollman} 261886Swollman 262886Swollman/* 263886Swollman * Tell kern_execve.c about it, with a little help from the linker. 264886Swollman */ 26543402Sdillonstatic struct execsw aout_execsw = { exec_aout_imgact, "a.out" }; 26640435SpeterEXEC_SET(aout, aout_execsw); 267