imgact_svr4.c revision 173361
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 173361 2007-11-05 11:36:16Z kib $"); 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 */ 123173361Skib error = exec_new_vmspace(imgp, &svr4_sysvec); 124173361Skib if (error) 125173361Skib goto fail; 12643412Snewton vmspace = imgp->proc->p_vmspace; 12743412Snewton 12843412Snewton /* 12943412Snewton * Check if file_offset page aligned,. 13043412Snewton * Currently we cannot handle misalinged file offsets, 13143412Snewton * and so we read in the entire image (what a waste). 13243412Snewton */ 13343412Snewton if (file_offset & PAGE_MASK) { 13443412Snewton#ifdef DEBUG 13580114Sassar printf("imgact: Non page aligned binary %lu\n", file_offset); 13643412Snewton#endif 13743412Snewton /* 13843412Snewton * Map text+data+bss read/write/execute 13943412Snewton */ 14043412Snewton vmaddr = virtual_offset; 14143412Snewton error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr, 14243412Snewton a_out->a_text + a_out->a_data + bss_size, FALSE, 14343412Snewton VM_PROT_ALL, VM_PROT_ALL, 0); 14443412Snewton if (error) 145101771Sjeff goto fail; 14643412Snewton 14743412Snewton error = vm_mmap(kernel_map, &buffer, 14843412Snewton round_page(a_out->a_text + a_out->a_data + file_offset), 14943412Snewton VM_PROT_READ, VM_PROT_READ, 0, 150144501Sjhb OBJT_VNODE, imgp->vp, trunc_page(file_offset)); 15143412Snewton if (error) 152101771Sjeff goto fail; 15343412Snewton 15443412Snewton error = copyout((caddr_t)(buffer + file_offset), (caddr_t)vmaddr, 15543412Snewton a_out->a_text + a_out->a_data); 15643412Snewton 15743412Snewton vm_map_remove(kernel_map, buffer, 15843412Snewton buffer + round_page(a_out->a_text + a_out->a_data + file_offset)); 15943412Snewton 16043412Snewton if (error) 161101771Sjeff goto fail; 16243412Snewton 16343412Snewton /* 16443412Snewton * remove write enable on the 'text' part 16543412Snewton */ 16643412Snewton error = vm_map_protect(&vmspace->vm_map, 16743412Snewton vmaddr, 16843412Snewton vmaddr + a_out->a_text, 16943412Snewton VM_PROT_EXECUTE|VM_PROT_READ, 17043412Snewton TRUE); 17143412Snewton if (error) 172101771Sjeff goto fail; 17343412Snewton } 17443412Snewton else { 17543412Snewton#ifdef DEBUG 17680114Sassar printf("imgact: Page aligned binary %lu\n", file_offset); 17743412Snewton#endif 17843412Snewton /* 17943412Snewton * Map text+data read/execute 18043412Snewton */ 18143412Snewton vmaddr = virtual_offset; 18243412Snewton error = vm_mmap(&vmspace->vm_map, &vmaddr, 18343412Snewton a_out->a_text + a_out->a_data, 18443412Snewton VM_PROT_READ | VM_PROT_EXECUTE, 18543412Snewton VM_PROT_ALL, 18643412Snewton MAP_PRIVATE | MAP_FIXED, 187144501Sjhb OBJT_VNODE, imgp->vp, file_offset); 18843412Snewton if (error) 189101771Sjeff goto fail; 19043412Snewton 19143412Snewton#ifdef DEBUG 19280114Sassar printf("imgact: startaddr=%08lx, length=%08lx\n", (u_long)vmaddr, 193131013Sobrien (u_long)a_out->a_text + a_out->a_data); 19443412Snewton#endif 19543412Snewton /* 19643412Snewton * allow read/write of data 19743412Snewton */ 19843412Snewton error = vm_map_protect(&vmspace->vm_map, 19943412Snewton vmaddr + a_out->a_text, 20043412Snewton vmaddr + a_out->a_text + a_out->a_data, 20143412Snewton VM_PROT_ALL, 20243412Snewton FALSE); 20343412Snewton if (error) 204101771Sjeff goto fail; 20543412Snewton 20643412Snewton /* 20743412Snewton * Allocate anon demand-zeroed area for uninitialized data 20843412Snewton */ 20943412Snewton if (bss_size != 0) { 21043412Snewton vmaddr = virtual_offset + a_out->a_text + a_out->a_data; 21143412Snewton error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr, 21243412Snewton bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); 21343412Snewton if (error) 214101771Sjeff goto fail; 21543412Snewton#ifdef DEBUG 21680114Sassar printf("imgact: bssaddr=%08lx, length=%08lx\n", 21780114Sassar (u_long)vmaddr, bss_size); 21843412Snewton#endif 21943412Snewton 22043412Snewton } 22143412Snewton } 22243412Snewton /* Fill in process VM information */ 22343412Snewton vmspace->vm_tsize = round_page(a_out->a_text) >> PAGE_SHIFT; 22443412Snewton vmspace->vm_dsize = round_page(a_out->a_data + bss_size) >> PAGE_SHIFT; 22543412Snewton vmspace->vm_taddr = (caddr_t)virtual_offset; 22643412Snewton vmspace->vm_daddr = (caddr_t)virtual_offset + a_out->a_text; 22743412Snewton 22843412Snewton /* Fill in image_params */ 22943412Snewton imgp->interpreted = 0; 23043412Snewton imgp->entry_addr = a_out->a_entry; 23143412Snewton 23243412Snewton imgp->proc->p_sysent = &svr4_sysvec; 233101771Sjefffail: 234101846Sjeff vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY, td); 235101771Sjeff return (error); 23643412Snewton} 23743412Snewton 23843412Snewton/* 23943412Snewton * Tell kern_execve.c about it, with a little help from the linker. 24043412Snewton */ 24146889Speterstruct execsw svr4_execsw = { exec_svr4_imgact, "svr4 ELF" }; 24245738SpeterEXEC_SET(execsw_set, svr4_execsw); 24343412Snewton 244