imgact_svr4.c revision 144501
143412Snewton/*- 243412Snewton * Copyright (c) 1998 Mark Newton 343412Snewton * Copyright (c) 1994-1996 S�ren Schmidt 443412Snewton * All rights reserved. 543412Snewton * 643412Snewton * Based heavily on /sys/kern/imgact_aout.c which is: 743412Snewton * Copyright (c) 1993, David Greenman 843412Snewton * 943412Snewton * Redistribution and use in source and binary forms, with or without 1043412Snewton * modification, are permitted provided that the following conditions 1143412Snewton * are met: 1243412Snewton * 1. Redistributions of source code must retain the above copyright 1343412Snewton * notice, this list of conditions and the following disclaimer 1443412Snewton * in this position and unchanged. 1543412Snewton * 2. Redistributions in binary form must reproduce the above copyright 1643412Snewton * notice, this list of conditions and the following disclaimer in the 1743412Snewton * documentation and/or other materials provided with the distribution. 1843412Snewton * 3. The name of the author may not be used to endorse or promote products 1997748Sschweikh * derived from this software without specific prior written permission 2043412Snewton * 2143412Snewton * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2243412Snewton * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2343412Snewton * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2443412Snewton * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2543412Snewton * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2643412Snewton * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2743412Snewton * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2843412Snewton * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2943412Snewton * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3043412Snewton * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3143412Snewton */ 3243412Snewton 33116174Sobrien#include <sys/cdefs.h> 34116174Sobrien__FBSDID("$FreeBSD: head/sys/compat/svr4/imgact_svr4.c 144501 2005-04-01 20:00:11Z jhb $"); 35116174Sobrien 3643412Snewton#include <sys/param.h> 3743412Snewton#include <sys/systm.h> 3843412Snewton#include <sys/exec.h> 3943412Snewton#include <sys/imgact.h> 4043412Snewton#include <sys/imgact_aout.h> 4143412Snewton#include <sys/kernel.h> 4243412Snewton#include <sys/lock.h> 4376166Smarkm#include <sys/mman.h> 4476166Smarkm#include <sys/mutex.h> 4543412Snewton#include <sys/proc.h> 4676166Smarkm#include <sys/resourcevar.h> 4743412Snewton#include <sys/vnode.h> 4843412Snewton 4943412Snewton#include <vm/vm.h> 5043412Snewton#include <vm/vm_kern.h> 5143412Snewton#include <vm/vm_param.h> 5243412Snewton#include <vm/pmap.h> 5343412Snewton#include <vm/vm_map.h> 5443412Snewton#include <vm/vm_extern.h> 5543412Snewton 5665302Sobrien#include <compat/svr4/svr4.h> 5743412Snewton 5892761Salfredstatic int exec_svr4_imgact(struct image_params *iparams); 5943412Snewton 6043412Snewtonstatic int 6143412Snewtonexec_svr4_imgact(imgp) 6243412Snewton struct image_params *imgp; 6343412Snewton{ 6443412Snewton const struct exec *a_out = (const struct exec *) imgp->image_header; 6543412Snewton struct vmspace *vmspace; 6643412Snewton vm_offset_t vmaddr; 6743412Snewton unsigned long virtual_offset, file_offset; 6843412Snewton vm_offset_t buffer; 6943412Snewton unsigned long bss_size; 7043412Snewton int error; 71101771Sjeff struct thread *td = curthread; 7243412Snewton 7343412Snewton if (((a_out->a_magic >> 16) & 0xff) != 0x64) 7443412Snewton return -1; 7543412Snewton 7643412Snewton /* 7743412Snewton * Set file/virtual offset based on a.out variant. 7843412Snewton */ 7943412Snewton switch ((int)(a_out->a_magic & 0xffff)) { 8043412Snewton case 0413: 8143412Snewton virtual_offset = 0; 8243412Snewton file_offset = 1024; 8343412Snewton break; 8443412Snewton case 0314: 8543412Snewton virtual_offset = 4096; 8643412Snewton file_offset = 0; 8743412Snewton break; 8843412Snewton default: 8943412Snewton return (-1); 9043412Snewton } 9143412Snewton bss_size = round_page(a_out->a_bss); 9243412Snewton#ifdef DEBUG 93131013Sobrien printf("imgact: text: %08lx, data: %08lx, bss: %08lx\n", (u_long)a_out->a_text, (u_long)a_out->a_data, bss_size); 9443412Snewton#endif 9543412Snewton 9643412Snewton /* 9743412Snewton * Check various fields in header for validity/bounds. 9843412Snewton */ 9943412Snewton if (a_out->a_entry < virtual_offset || 10043412Snewton a_out->a_entry >= virtual_offset + a_out->a_text || 10143412Snewton a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) 10243412Snewton return (-1); 10343412Snewton 10443412Snewton /* text + data can't exceed file size */ 10543412Snewton if (a_out->a_data + a_out->a_text > imgp->attr->va_size) 10643412Snewton return (EFAULT); 10743412Snewton /* 10843412Snewton * text/data/bss must not exceed limits 10943412Snewton */ 110125454Sjhb PROC_LOCK(imgp->proc); 11184783Sps if (a_out->a_text > maxtsiz || 112125454Sjhb a_out->a_data + bss_size > lim_cur(imgp->proc, RLIMIT_DATA)) { 113125454Sjhb PROC_UNLOCK(imgp->proc); 11443412Snewton return (ENOMEM); 115125454Sjhb } 116125454Sjhb PROC_UNLOCK(imgp->proc); 11743412Snewton 118101771Sjeff VOP_UNLOCK(imgp->vp, 0, td); 119101771Sjeff 12043412Snewton /* 12143412Snewton * Destroy old process VM and create a new one (with a new stack) 12243412Snewton */ 123103767Sjake exec_new_vmspace(imgp, &svr4_sysvec); 12443412Snewton vmspace = imgp->proc->p_vmspace; 12543412Snewton 12643412Snewton /* 12743412Snewton * Check if file_offset page aligned,. 12843412Snewton * Currently we cannot handle misalinged file offsets, 12943412Snewton * and so we read in the entire image (what a waste). 13043412Snewton */ 13143412Snewton if (file_offset & PAGE_MASK) { 13243412Snewton#ifdef DEBUG 13380114Sassar printf("imgact: Non page aligned binary %lu\n", file_offset); 13443412Snewton#endif 13543412Snewton /* 13643412Snewton * Map text+data+bss read/write/execute 13743412Snewton */ 13843412Snewton vmaddr = virtual_offset; 13943412Snewton error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr, 14043412Snewton a_out->a_text + a_out->a_data + bss_size, FALSE, 14143412Snewton VM_PROT_ALL, VM_PROT_ALL, 0); 14243412Snewton if (error) 143101771Sjeff goto fail; 14443412Snewton 14543412Snewton error = vm_mmap(kernel_map, &buffer, 14643412Snewton round_page(a_out->a_text + a_out->a_data + file_offset), 14743412Snewton VM_PROT_READ, VM_PROT_READ, 0, 148144501Sjhb OBJT_VNODE, imgp->vp, trunc_page(file_offset)); 14943412Snewton if (error) 150101771Sjeff goto fail; 15143412Snewton 15243412Snewton error = copyout((caddr_t)(buffer + file_offset), (caddr_t)vmaddr, 15343412Snewton a_out->a_text + a_out->a_data); 15443412Snewton 15543412Snewton vm_map_remove(kernel_map, buffer, 15643412Snewton buffer + round_page(a_out->a_text + a_out->a_data + file_offset)); 15743412Snewton 15843412Snewton if (error) 159101771Sjeff goto fail; 16043412Snewton 16143412Snewton /* 16243412Snewton * remove write enable on the 'text' part 16343412Snewton */ 16443412Snewton error = vm_map_protect(&vmspace->vm_map, 16543412Snewton vmaddr, 16643412Snewton vmaddr + a_out->a_text, 16743412Snewton VM_PROT_EXECUTE|VM_PROT_READ, 16843412Snewton TRUE); 16943412Snewton if (error) 170101771Sjeff goto fail; 17143412Snewton } 17243412Snewton else { 17343412Snewton#ifdef DEBUG 17480114Sassar printf("imgact: Page aligned binary %lu\n", file_offset); 17543412Snewton#endif 17643412Snewton /* 17743412Snewton * Map text+data read/execute 17843412Snewton */ 17943412Snewton vmaddr = virtual_offset; 18043412Snewton error = vm_mmap(&vmspace->vm_map, &vmaddr, 18143412Snewton a_out->a_text + a_out->a_data, 18243412Snewton VM_PROT_READ | VM_PROT_EXECUTE, 18343412Snewton VM_PROT_ALL, 18443412Snewton MAP_PRIVATE | MAP_FIXED, 185144501Sjhb OBJT_VNODE, imgp->vp, file_offset); 18643412Snewton if (error) 187101771Sjeff goto fail; 18843412Snewton 18943412Snewton#ifdef DEBUG 19080114Sassar printf("imgact: startaddr=%08lx, length=%08lx\n", (u_long)vmaddr, 191131013Sobrien (u_long)a_out->a_text + a_out->a_data); 19243412Snewton#endif 19343412Snewton /* 19443412Snewton * allow read/write of data 19543412Snewton */ 19643412Snewton error = vm_map_protect(&vmspace->vm_map, 19743412Snewton vmaddr + a_out->a_text, 19843412Snewton vmaddr + a_out->a_text + a_out->a_data, 19943412Snewton VM_PROT_ALL, 20043412Snewton FALSE); 20143412Snewton if (error) 202101771Sjeff goto fail; 20343412Snewton 20443412Snewton /* 20543412Snewton * Allocate anon demand-zeroed area for uninitialized data 20643412Snewton */ 20743412Snewton if (bss_size != 0) { 20843412Snewton vmaddr = virtual_offset + a_out->a_text + a_out->a_data; 20943412Snewton error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr, 21043412Snewton bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); 21143412Snewton if (error) 212101771Sjeff goto fail; 21343412Snewton#ifdef DEBUG 21480114Sassar printf("imgact: bssaddr=%08lx, length=%08lx\n", 21580114Sassar (u_long)vmaddr, bss_size); 21643412Snewton#endif 21743412Snewton 21843412Snewton } 21943412Snewton } 22043412Snewton /* Fill in process VM information */ 22143412Snewton vmspace->vm_tsize = round_page(a_out->a_text) >> PAGE_SHIFT; 22243412Snewton vmspace->vm_dsize = round_page(a_out->a_data + bss_size) >> PAGE_SHIFT; 22343412Snewton vmspace->vm_taddr = (caddr_t)virtual_offset; 22443412Snewton vmspace->vm_daddr = (caddr_t)virtual_offset + a_out->a_text; 22543412Snewton 22643412Snewton /* Fill in image_params */ 22743412Snewton imgp->interpreted = 0; 22843412Snewton imgp->entry_addr = a_out->a_entry; 22943412Snewton 23043412Snewton imgp->proc->p_sysent = &svr4_sysvec; 231101771Sjefffail: 232101846Sjeff vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY, td); 233101771Sjeff return (error); 23443412Snewton} 23543412Snewton 23643412Snewton/* 23743412Snewton * Tell kern_execve.c about it, with a little help from the linker. 23843412Snewton */ 23946889Speterstruct execsw svr4_execsw = { exec_svr4_imgact, "svr4 ELF" }; 24045738SpeterEXEC_SET(execsw_set, svr4_execsw); 24143412Snewton 242