imgact_aout.c revision 68520
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 * 2650477Speter * $FreeBSD: head/sys/kern/imgact_aout.c 68520 2000-11-09 08:25:48Z marcel $ 27885Swollman */ 28885Swollman 291549Srgrimes#include <sys/param.h> 301549Srgrimes#include <sys/resourcevar.h> 311549Srgrimes#include <sys/exec.h> 3239154Sjdp#include <sys/fcntl.h> 331549Srgrimes#include <sys/imgact.h> 343058Sdg#include <sys/imgact_aout.h> 351549Srgrimes#include <sys/kernel.h> 3639154Sjdp#include <sys/namei.h> 3739154Sjdp#include <sys/pioctl.h> 3815494Sbde#include <sys/proc.h> 3965681Sdfr#include <sys/systm.h> 4039154Sjdp#include <sys/signalvar.h> 4139154Sjdp#include <sys/stat.h> 422257Ssos#include <sys/sysent.h> 4339154Sjdp#include <sys/syscall.h> 4415494Sbde#include <sys/vnode.h> 4539154Sjdp#include <machine/md_var.h> 46885Swollman 471549Srgrimes#include <vm/vm.h> 4812662Sdg#include <vm/vm_param.h> 4922521Sdyson#include <sys/lock.h> 5012662Sdg#include <vm/pmap.h> 5112662Sdg#include <vm/vm_map.h> 5232446Sdyson#include <vm/vm_object.h> 5339154Sjdp#include <sys/user.h> 54885Swollman 5512568Sbdestatic int exec_aout_imgact __P((struct image_params *imgp)); 5612568Sbde 5739154Sjdpstruct sysentvec aout_sysvec = { 5839154Sjdp SYS_MAXSYSCALL, 5939154Sjdp sysent, 6039154Sjdp 0, 6139154Sjdp 0, 6239154Sjdp 0, 6339154Sjdp 0, 6439154Sjdp 0, 6539154Sjdp 0, 6639154Sjdp 0, 6739154Sjdp sendsig, 6839154Sjdp sigcode, 6939154Sjdp &szsigcode, 7039154Sjdp 0, 7139154Sjdp "FreeBSD a.out", 7268520Smarcel aout_coredump, 7368520Smarcel NULL, 7468520Smarcel MINSIGSTKSZ 7539154Sjdp}; 7639154Sjdp 7750901Sbdestatic int 7812130Sdgexec_aout_imgact(imgp) 7912130Sdg struct image_params *imgp; 80885Swollman{ 8117974Sbde const struct exec *a_out = (const struct exec *) imgp->image_header; 8224848Sdyson struct vmspace *vmspace; 8332446Sdyson struct vnode *vp; 8444469Salc vm_map_t map; 8532446Sdyson vm_object_t object; 8632446Sdyson vm_offset_t text_end, data_end; 8714703Sbde unsigned long virtual_offset; 8812767Sdyson unsigned long file_offset; 89885Swollman unsigned long bss_size; 903098Sphk int error; 91885Swollman 92885Swollman /* 936380Ssos * Linux and *BSD binaries look very much alike, 948876Srgrimes * only the machine id is different: 959202Srgrimes * 0x64 for Linux, 0x86 for *BSD, 0x00 for BSDI. 9614363Speter * NetBSD is in network byte order.. ugh. 976380Ssos */ 989202Srgrimes if (((a_out->a_magic >> 16) & 0xff) != 0x86 && 9914363Speter ((a_out->a_magic >> 16) & 0xff) != 0 && 10014363Speter ((((int)ntohl(a_out->a_magic)) >> 16) & 0xff) != 0x86) 1019202Srgrimes return -1; 1026380Ssos 1036380Ssos /* 104885Swollman * Set file/virtual offset based on a.out variant. 105885Swollman * We do two cases: host byte order and network byte order 106885Swollman * (for NetBSD compatibility) 107885Swollman */ 108885Swollman switch ((int)(a_out->a_magic & 0xffff)) { 109885Swollman case ZMAGIC: 110885Swollman virtual_offset = 0; 111885Swollman if (a_out->a_text) { 11215538Sphk file_offset = PAGE_SIZE; 113885Swollman } else { 114885Swollman /* Bill's "screwball mode" */ 115885Swollman file_offset = 0; 116885Swollman } 117885Swollman break; 118885Swollman case QMAGIC: 11915538Sphk virtual_offset = PAGE_SIZE; 120885Swollman file_offset = 0; 12145270Sjdp /* Pass PS_STRINGS for BSD/OS binaries only. */ 12245270Sjdp if (N_GETMID(*a_out) == MID_ZERO) 12345270Sjdp imgp->ps_strings = PS_STRINGS; 124885Swollman break; 125885Swollman default: 126885Swollman /* NetBSD compatibility */ 127885Swollman switch ((int)(ntohl(a_out->a_magic) & 0xffff)) { 128885Swollman case ZMAGIC: 129885Swollman case QMAGIC: 13015538Sphk virtual_offset = PAGE_SIZE; 131885Swollman file_offset = 0; 132885Swollman break; 133885Swollman default: 134885Swollman return (-1); 135885Swollman } 136885Swollman } 137885Swollman 13815538Sphk bss_size = roundup(a_out->a_bss, PAGE_SIZE); 139885Swollman 140885Swollman /* 141885Swollman * Check various fields in header for validity/bounds. 142885Swollman */ 143885Swollman if (/* entry point must lay with text region */ 144885Swollman a_out->a_entry < virtual_offset || 145885Swollman a_out->a_entry >= virtual_offset + a_out->a_text || 146885Swollman 147885Swollman /* text and data size must each be page rounded */ 14815538Sphk a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) 149885Swollman return (-1); 150885Swollman 151885Swollman /* text + data can't exceed file size */ 15212130Sdg if (a_out->a_data + a_out->a_text > imgp->attr->va_size) 153885Swollman return (EFAULT); 154885Swollman 155885Swollman /* 156885Swollman * text/data/bss must not exceed limits 157885Swollman */ 158885Swollman if (/* text can't exceed maximum text size */ 159885Swollman a_out->a_text > MAXTSIZ || 160885Swollman 161885Swollman /* data + bss can't exceed rlimit */ 162885Swollman a_out->a_data + bss_size > 16312130Sdg imgp->proc->p_rlimit[RLIMIT_DATA].rlim_cur) 164885Swollman return (ENOMEM); 165885Swollman 166885Swollman /* copy in arguments and/or environment from old process */ 16712130Sdg error = exec_extract_strings(imgp); 168885Swollman if (error) 169885Swollman return (error); 170885Swollman 171885Swollman /* 172885Swollman * Destroy old process VM and create a new one (with a new stack) 173885Swollman */ 17412130Sdg exec_new_vmspace(imgp); 175885Swollman 176885Swollman /* 17724848Sdyson * The vm space can be changed by exec_new_vmspace 17824848Sdyson */ 17924848Sdyson vmspace = imgp->proc->p_vmspace; 18024848Sdyson 18132446Sdyson vp = imgp->vp; 18244469Salc map = &vmspace->vm_map; 18344469Salc vm_map_lock(map); 18465770Sbp VOP_GETVOBJECT(vp, &object); 18532446Sdyson vm_object_reference(object); 18632446Sdyson 18732446Sdyson text_end = virtual_offset + a_out->a_text; 18844626Salc error = vm_map_insert(map, object, 18932446Sdyson file_offset, 19032446Sdyson virtual_offset, text_end, 19132446Sdyson VM_PROT_READ | VM_PROT_EXECUTE, VM_PROT_ALL, 19247258Salc MAP_COPY_ON_WRITE | MAP_PREFAULT); 19344469Salc if (error) { 19444469Salc vm_map_unlock(map); 195885Swollman return (error); 19644469Salc } 19732446Sdyson data_end = text_end + a_out->a_data; 19832446Sdyson if (a_out->a_data) { 19932446Sdyson vm_object_reference(object); 20044626Salc error = vm_map_insert(map, object, 20132446Sdyson file_offset + a_out->a_text, 20232446Sdyson text_end, data_end, 20332446Sdyson VM_PROT_ALL, VM_PROT_ALL, 20447258Salc MAP_COPY_ON_WRITE | MAP_PREFAULT); 20544469Salc if (error) { 20644469Salc vm_map_unlock(map); 20732446Sdyson return (error); 20844469Salc } 20932446Sdyson } 210885Swollman 21132446Sdyson if (bss_size) { 21244626Salc error = vm_map_insert(map, NULL, 0, 21332446Sdyson data_end, data_end + bss_size, 21432446Sdyson VM_PROT_ALL, VM_PROT_ALL, 0); 21544469Salc if (error) { 21644469Salc vm_map_unlock(map); 2176579Sdg return (error); 21844469Salc } 2196579Sdg } 22044469Salc vm_map_unlock(map); 22144469Salc 222885Swollman /* Fill in process VM information */ 223885Swollman vmspace->vm_tsize = a_out->a_text >> PAGE_SHIFT; 224885Swollman vmspace->vm_dsize = (a_out->a_data + bss_size) >> PAGE_SHIFT; 22537656Sbde vmspace->vm_taddr = (caddr_t) (uintptr_t) virtual_offset; 22637656Sbde vmspace->vm_daddr = (caddr_t) (uintptr_t) 22737656Sbde (virtual_offset + a_out->a_text); 228885Swollman 229885Swollman /* Fill in image_params */ 23012130Sdg imgp->interpreted = 0; 23112130Sdg imgp->entry_addr = a_out->a_entry; 2328876Srgrimes 23312130Sdg imgp->proc->p_sysent = &aout_sysvec; 23410221Sdg 23510221Sdg /* Indicate that this file should not be modified */ 23612130Sdg imgp->vp->v_flag |= VTEXT; 23710221Sdg 238885Swollman return (0); 239885Swollman} 240886Swollman 241886Swollman/* 24242237Sbde * Dump core, into a file named as described in the comments for 24342237Sbde * expand_name(), unless the process was setuid/setgid. 24439154Sjdp */ 24539154Sjdpint 24650717Sjulianaout_coredump(p, vp, limit) 24739154Sjdp register struct proc *p; 24850717Sjulian register struct vnode *vp; 24950717Sjulian off_t limit; 25039154Sjdp{ 25153503Sphk register struct ucred *cred = p->p_ucred; 25239154Sjdp register struct vmspace *vm = p->p_vmspace; 25350901Sbde int error; 25439154Sjdp 25550901Sbde if (ctob(UPAGES + vm->vm_dsize + vm->vm_ssize) >= limit) 25639154Sjdp return (EFAULT); 25739154Sjdp bcopy(p, &p->p_addr->u_kproc.kp_proc, sizeof(struct proc)); 25839154Sjdp fill_eproc(p, &p->p_addr->u_kproc.kp_eproc); 25939154Sjdp error = cpu_coredump(p, vp, cred); 26039154Sjdp if (error == 0) 26139154Sjdp error = vn_rdwr(UIO_WRITE, vp, vm->vm_daddr, 26239154Sjdp (int)ctob(vm->vm_dsize), (off_t)ctob(UPAGES), UIO_USERSPACE, 26339154Sjdp IO_NODELOCKED|IO_UNIT, cred, (int *) NULL, p); 26439154Sjdp if (error == 0) 26539154Sjdp error = vn_rdwr(UIO_WRITE, vp, 26639154Sjdp (caddr_t) trunc_page(USRSTACK - ctob(vm->vm_ssize)), 26739154Sjdp round_page(ctob(vm->vm_ssize)), 26839154Sjdp (off_t)ctob(UPAGES) + ctob(vm->vm_dsize), UIO_USERSPACE, 26939154Sjdp IO_NODELOCKED|IO_UNIT, cred, (int *) NULL, p); 27050901Sbde return (error); 27139154Sjdp} 27239154Sjdp 27339154Sjdp/* 274886Swollman * Tell kern_execve.c about it, with a little help from the linker. 275886Swollman */ 27643402Sdillonstatic struct execsw aout_execsw = { exec_aout_imgact, "a.out" }; 27740435SpeterEXEC_SET(aout, aout_execsw); 278