1c21dee17SSøren Schmidt /*- 2e1743d02SSøren Schmidt * Copyright (c) 1994-1996 S�ren Schmidt 3c21dee17SSøren Schmidt * All rights reserved. 4c21dee17SSøren Schmidt * 5c21dee17SSøren Schmidt * Based heavily on /sys/kern/imgact_aout.c which is: 6c21dee17SSøren Schmidt * Copyright (c) 1993, David Greenman 7c21dee17SSøren Schmidt * 8c21dee17SSøren Schmidt * Redistribution and use in source and binary forms, with or without 9c21dee17SSøren Schmidt * modification, are permitted provided that the following conditions 10c21dee17SSøren Schmidt * are met: 11c21dee17SSøren Schmidt * 1. Redistributions of source code must retain the above copyright 12c21dee17SSøren Schmidt * notice, this list of conditions and the following disclaimer 13c21dee17SSøren Schmidt * in this position and unchanged. 14c21dee17SSøren Schmidt * 2. Redistributions in binary form must reproduce the above copyright 15c21dee17SSøren Schmidt * notice, this list of conditions and the following disclaimer in the 16c21dee17SSøren Schmidt * documentation and/or other materials provided with the distribution. 17c21dee17SSøren Schmidt * 3. The name of the author may not be used to endorse or promote products 18c21dee17SSøren Schmidt * derived from this software withough specific prior written permission 19c21dee17SSøren Schmidt * 20c21dee17SSøren Schmidt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21c21dee17SSøren Schmidt * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22c21dee17SSøren Schmidt * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23c21dee17SSøren Schmidt * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24c21dee17SSøren Schmidt * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25c21dee17SSøren Schmidt * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26c21dee17SSøren Schmidt * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27c21dee17SSøren Schmidt * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28c21dee17SSøren Schmidt * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29c21dee17SSøren Schmidt * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30c21dee17SSøren Schmidt * 31a794e791SBruce Evans * $Id: imgact_linux.c,v 1.13 1996/03/19 15:02:33 bde Exp $ 32c21dee17SSøren Schmidt */ 33c21dee17SSøren Schmidt 34c21dee17SSøren Schmidt #include <sys/param.h> 35c21dee17SSøren Schmidt #include <sys/systm.h> 36c21dee17SSøren Schmidt #include <sys/resourcevar.h> 37c21dee17SSøren Schmidt #include <sys/exec.h> 38c21dee17SSøren Schmidt #include <sys/mman.h> 39c21dee17SSøren Schmidt #include <sys/imgact.h> 40c21dee17SSøren Schmidt #include <sys/imgact_aout.h> 41c21dee17SSøren Schmidt #include <sys/kernel.h> 42a794e791SBruce Evans #include <sys/proc.h> 43c21dee17SSøren Schmidt #include <sys/sysent.h> 44a794e791SBruce Evans #include <sys/vnode.h> 45c21dee17SSøren Schmidt 46c21dee17SSøren Schmidt #include <vm/vm.h> 47c21dee17SSøren Schmidt #include <vm/vm_kern.h> 48ac9a8f2fSPeter Wemm #include <vm/vm_param.h> 49ac9a8f2fSPeter Wemm #include <vm/pmap.h> 50ac9a8f2fSPeter Wemm #include <vm/lock.h> 51ac9a8f2fSPeter Wemm #include <vm/vm_map.h> 52ac9a8f2fSPeter Wemm #include <vm/vm_prot.h> 53e0067d71SBruce Evans #include <vm/vm_extern.h> 54c21dee17SSøren Schmidt 55d66a5066SPeter Wemm #include <i386/linux/linux.h> 56d66a5066SPeter Wemm #include <i386/linux/linux_proto.h> 571f3dad5aSBruce Evans 581f3dad5aSBruce Evans extern int exec_linux_imgact __P((struct image_params *iparams)); 591f3dad5aSBruce Evans 60c21dee17SSøren Schmidt int 61c52007c2SDavid Greenman exec_linux_imgact(imgp) 62c52007c2SDavid Greenman struct image_params *imgp; 63c21dee17SSøren Schmidt { 64c52007c2SDavid Greenman struct exec *a_out = (struct exec *) imgp->image_header; 65c52007c2SDavid Greenman struct vmspace *vmspace = imgp->proc->p_vmspace; 66ede8dc43SBruce Evans vm_offset_t vmaddr; 67ede8dc43SBruce Evans unsigned long virtual_offset, file_offset; 68ede8dc43SBruce Evans vm_offset_t buffer; 69ede8dc43SBruce Evans unsigned long bss_size; 70c21dee17SSøren Schmidt int error; 71c21dee17SSøren Schmidt 72c21dee17SSøren Schmidt if (((a_out->a_magic >> 16) & 0xff) != 0x64) 73c21dee17SSøren Schmidt return -1; 74c21dee17SSøren Schmidt 75c21dee17SSøren Schmidt /* 76c21dee17SSøren Schmidt * Set file/virtual offset based on a.out variant. 77c21dee17SSøren Schmidt */ 78c21dee17SSøren Schmidt switch ((int)(a_out->a_magic & 0xffff)) { 79c21dee17SSøren Schmidt case 0413: 80c21dee17SSøren Schmidt virtual_offset = 0; 81c21dee17SSøren Schmidt file_offset = 1024; 82c21dee17SSøren Schmidt break; 83c21dee17SSøren Schmidt case 0314: 84c21dee17SSøren Schmidt virtual_offset = 4096; 85c21dee17SSøren Schmidt file_offset = 0; 86c21dee17SSøren Schmidt break; 87c21dee17SSøren Schmidt default: 88c21dee17SSøren Schmidt return (-1); 89c21dee17SSøren Schmidt } 90c21dee17SSøren Schmidt bss_size = round_page(a_out->a_bss); 91d66a5066SPeter Wemm #ifdef DEBUG 92d66a5066SPeter Wemm printf("imgact: text: %08x, data: %08x, bss: %08x\n", a_out->a_text, a_out->a_data, bss_size); 93d66a5066SPeter Wemm #endif 94c21dee17SSøren Schmidt 95c21dee17SSøren Schmidt /* 96c21dee17SSøren Schmidt * Check various fields in header for validity/bounds. 97c21dee17SSøren Schmidt */ 98c21dee17SSøren Schmidt if (a_out->a_entry < virtual_offset || 99c21dee17SSøren Schmidt a_out->a_entry >= virtual_offset + a_out->a_text || 100c21dee17SSøren Schmidt a_out->a_text % NBPG || a_out->a_data % NBPG) 101c21dee17SSøren Schmidt return (-1); 102c21dee17SSøren Schmidt 103c21dee17SSøren Schmidt /* text + data can't exceed file size */ 104c52007c2SDavid Greenman if (a_out->a_data + a_out->a_text > imgp->attr->va_size) 105c21dee17SSøren Schmidt return (EFAULT); 106c21dee17SSøren Schmidt /* 107c21dee17SSøren Schmidt * text/data/bss must not exceed limits 108c21dee17SSøren Schmidt */ 109c21dee17SSøren Schmidt if (a_out->a_text > MAXTSIZ || a_out->a_data + bss_size > MAXDSIZ || 110c52007c2SDavid Greenman a_out->a_data+bss_size > imgp->proc->p_rlimit[RLIMIT_DATA].rlim_cur) 111c21dee17SSøren Schmidt return (ENOMEM); 112c21dee17SSøren Schmidt 113c21dee17SSøren Schmidt /* copy in arguments and/or environment from old process */ 114c52007c2SDavid Greenman error = exec_extract_strings(imgp); 115c21dee17SSøren Schmidt if (error) 116c21dee17SSøren Schmidt return (error); 117c21dee17SSøren Schmidt 118c21dee17SSøren Schmidt /* 119c21dee17SSøren Schmidt * Destroy old process VM and create a new one (with a new stack) 120c21dee17SSøren Schmidt */ 121c52007c2SDavid Greenman exec_new_vmspace(imgp); 122c21dee17SSøren Schmidt 123c21dee17SSøren Schmidt /* 124c21dee17SSøren Schmidt * Check if file_offset page aligned,. 125c21dee17SSøren Schmidt * Currently we cannot handle misalinged file offsets, 126c21dee17SSøren Schmidt * and so we read in the entire image (what a waste). 127c21dee17SSøren Schmidt */ 128c21dee17SSøren Schmidt if (file_offset & PGOFSET) { 129c21dee17SSøren Schmidt #ifdef DEBUG 130c21dee17SSøren Schmidt printf("imgact: Non page aligned binary %d\n", file_offset); 131c21dee17SSøren Schmidt #endif 132c21dee17SSøren Schmidt /* 1335297fc55SPeter Wemm * Map text+data+bss read/write/execute 134c21dee17SSøren Schmidt */ 135c21dee17SSøren Schmidt vmaddr = virtual_offset; 136c21dee17SSøren Schmidt error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr, 1375297fc55SPeter Wemm a_out->a_text + a_out->a_data + bss_size, FALSE, 138a4fc5c1aSJohn Dyson VM_PROT_ALL, VM_PROT_ALL, 0); 139c21dee17SSøren Schmidt if (error) 140c21dee17SSøren Schmidt return error; 141c21dee17SSøren Schmidt 142c21dee17SSøren Schmidt error = vm_mmap(kernel_map, &buffer, 1435297fc55SPeter Wemm round_page(a_out->a_text + a_out->a_data + file_offset), 14471d7d1b1SPeter Wemm VM_PROT_READ, VM_PROT_READ, 0, 145c52007c2SDavid Greenman (caddr_t) imgp->vp, trunc_page(file_offset)); 146c21dee17SSøren Schmidt if (error) 147c21dee17SSøren Schmidt return error; 148c21dee17SSøren Schmidt 149c21dee17SSøren Schmidt error = copyout((caddr_t)(buffer + file_offset), (caddr_t)vmaddr, 1505297fc55SPeter Wemm a_out->a_text + a_out->a_data); 1515297fc55SPeter Wemm 1525297fc55SPeter Wemm vm_map_remove(kernel_map, buffer, 1530946c36cSPeter Wemm buffer + round_page(a_out->a_text + a_out->a_data + file_offset)); 1545297fc55SPeter Wemm 155c21dee17SSøren Schmidt if (error) 156c21dee17SSøren Schmidt return error; 157c21dee17SSøren Schmidt 158c21dee17SSøren Schmidt /* 1595297fc55SPeter Wemm * remove write enable on the 'text' part 160c21dee17SSøren Schmidt */ 1610946c36cSPeter Wemm error = vm_map_protect(&vmspace->vm_map, 1620946c36cSPeter Wemm vmaddr, 1630946c36cSPeter Wemm vmaddr + a_out->a_text, 1640946c36cSPeter Wemm VM_PROT_EXECUTE|VM_PROT_READ, 1650946c36cSPeter Wemm TRUE); 166c21dee17SSøren Schmidt if (error) 167c21dee17SSøren Schmidt return error; 168c21dee17SSøren Schmidt } 169c21dee17SSøren Schmidt else { 170c21dee17SSøren Schmidt #ifdef DEBUG 171c21dee17SSøren Schmidt printf("imgact: Page aligned binary %d\n", file_offset); 172c21dee17SSøren Schmidt #endif 173c21dee17SSøren Schmidt /* 1745297fc55SPeter Wemm * Map text+data read/execute 175c21dee17SSøren Schmidt */ 176c21dee17SSøren Schmidt vmaddr = virtual_offset; 1775297fc55SPeter Wemm error = vm_mmap(&vmspace->vm_map, &vmaddr, 1785297fc55SPeter Wemm a_out->a_text + a_out->a_data, 179c21dee17SSøren Schmidt VM_PROT_READ | VM_PROT_EXECUTE, 1805297fc55SPeter Wemm VM_PROT_ALL, 181c21dee17SSøren Schmidt MAP_PRIVATE | MAP_FIXED, 182c52007c2SDavid Greenman (caddr_t)imgp->vp, file_offset); 183c21dee17SSøren Schmidt if (error) 184c21dee17SSøren Schmidt return (error); 185c21dee17SSøren Schmidt 186d66a5066SPeter Wemm #ifdef DEBUG 187d66a5066SPeter Wemm printf("imgact: startaddr=%08x, length=%08x\n", vmaddr, a_out->a_text + a_out->a_data); 188d66a5066SPeter Wemm #endif 189c21dee17SSøren Schmidt /* 1905297fc55SPeter Wemm * allow read/write of data 191c21dee17SSøren Schmidt */ 1925297fc55SPeter Wemm error = vm_map_protect(&vmspace->vm_map, 1935297fc55SPeter Wemm vmaddr + a_out->a_text, 1945297fc55SPeter Wemm vmaddr + a_out->a_text + a_out->a_data, 1955297fc55SPeter Wemm VM_PROT_ALL, 1965297fc55SPeter Wemm FALSE); 197c21dee17SSøren Schmidt if (error) 198c21dee17SSøren Schmidt return (error); 199c21dee17SSøren Schmidt 200c21dee17SSøren Schmidt /* 2015297fc55SPeter Wemm * Allocate anon demand-zeroed area for uninitialized data 202c21dee17SSøren Schmidt */ 203c21dee17SSøren Schmidt if (bss_size != 0) { 204c21dee17SSøren Schmidt vmaddr = virtual_offset + a_out->a_text + a_out->a_data; 205c21dee17SSøren Schmidt error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr, 206a4fc5c1aSJohn Dyson bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); 207c21dee17SSøren Schmidt if (error) 208c21dee17SSøren Schmidt return (error); 209d66a5066SPeter Wemm #ifdef DEBUG 210d66a5066SPeter Wemm printf("imgact: bssaddr=%08x, length=%08x\n", vmaddr, bss_size); 211d66a5066SPeter Wemm #endif 212d66a5066SPeter Wemm 213c21dee17SSøren Schmidt } 214c0e5de7dSDavid Greenman /* Indicate that this file should not be modified */ 215c52007c2SDavid Greenman imgp->vp->v_flag |= VTEXT; 216c21dee17SSøren Schmidt } 217c21dee17SSøren Schmidt /* Fill in process VM information */ 218c21dee17SSøren Schmidt vmspace->vm_tsize = round_page(a_out->a_text) >> PAGE_SHIFT; 219c21dee17SSøren Schmidt vmspace->vm_dsize = round_page(a_out->a_data + bss_size) >> PAGE_SHIFT; 220c21dee17SSøren Schmidt vmspace->vm_taddr = (caddr_t)virtual_offset; 221c21dee17SSøren Schmidt vmspace->vm_daddr = (caddr_t)virtual_offset + a_out->a_text; 222c21dee17SSøren Schmidt 223c21dee17SSøren Schmidt /* Fill in image_params */ 224c52007c2SDavid Greenman imgp->interpreted = 0; 225c52007c2SDavid Greenman imgp->entry_addr = a_out->a_entry; 226c21dee17SSøren Schmidt 227c52007c2SDavid Greenman imgp->proc->p_sysent = &linux_sysvec; 228c21dee17SSøren Schmidt return (0); 229c21dee17SSøren Schmidt } 230c21dee17SSøren Schmidt 231c21dee17SSøren Schmidt /* 232c21dee17SSøren Schmidt * Tell kern_execve.c about it, with a little help from the linker. 233c21dee17SSøren Schmidt * Since `const' objects end up in the text segment, TEXT_SET is the 234c21dee17SSøren Schmidt * correct directive to use. 235c21dee17SSøren Schmidt */ 236e1743d02SSøren Schmidt const struct execsw linux_execsw = { exec_linux_imgact, "linux a.out" }; 237c21dee17SSøren Schmidt TEXT_SET(execsw_set, linux_execsw); 238c21dee17SSøren Schmidt 239