1e1743d02SSøren Schmidt /*- 2e1743d02SSøren Schmidt * Copyright (c) 1995-1996 S�ren Schmidt 3e1743d02SSøren Schmidt * Copyright (c) 1996 Peter Wemm 4e1743d02SSøren Schmidt * All rights reserved. 5e1743d02SSøren Schmidt * 6e1743d02SSøren Schmidt * Redistribution and use in source and binary forms, with or without 7e1743d02SSøren Schmidt * modification, are permitted provided that the following conditions 8e1743d02SSøren Schmidt * are met: 9e1743d02SSøren Schmidt * 1. Redistributions of source code must retain the above copyright 10e1743d02SSøren Schmidt * notice, this list of conditions and the following disclaimer 11e1743d02SSøren Schmidt * in this position and unchanged. 12e1743d02SSøren Schmidt * 2. Redistributions in binary form must reproduce the above copyright 13e1743d02SSøren Schmidt * notice, this list of conditions and the following disclaimer in the 14e1743d02SSøren Schmidt * documentation and/or other materials provided with the distribution. 15e1743d02SSøren Schmidt * 3. The name of the author may not be used to endorse or promote products 16e1743d02SSøren Schmidt * derived from this software withough specific prior written permission 17e1743d02SSøren Schmidt * 18e1743d02SSøren Schmidt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19e1743d02SSøren Schmidt * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20e1743d02SSøren Schmidt * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21e1743d02SSøren Schmidt * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22e1743d02SSøren Schmidt * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23e1743d02SSøren Schmidt * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24e1743d02SSøren Schmidt * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25e1743d02SSøren Schmidt * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26e1743d02SSøren Schmidt * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27e1743d02SSøren Schmidt * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28e1743d02SSøren Schmidt * 29ecbb00a2SDoug Rabson * $Id: imgact_elf.c,v 1.24 1998/04/28 18:15:07 eivind Exp $ 30e1743d02SSøren Schmidt */ 31e1743d02SSøren Schmidt 32e9822d92SJoerg Wunsch #include "opt_rlimit.h" 33e9822d92SJoerg Wunsch 34e1743d02SSøren Schmidt #include <sys/param.h> 35e1743d02SSøren Schmidt #include <sys/systm.h> 36e1743d02SSøren Schmidt #include <sys/exec.h> 37e1743d02SSøren Schmidt #include <sys/mman.h> 38e1743d02SSøren Schmidt #include <sys/imgact.h> 39e1743d02SSøren Schmidt #include <sys/imgact_elf.h> 40e1743d02SSøren Schmidt #include <sys/kernel.h> 41e1743d02SSøren Schmidt #include <sys/sysent.h> 42e1743d02SSøren Schmidt #include <sys/malloc.h> 43a794e791SBruce Evans #include <sys/namei.h> 44a794e791SBruce Evans #include <sys/proc.h> 45e1743d02SSøren Schmidt #include <sys/syscall.h> 46e1743d02SSøren Schmidt #include <sys/signalvar.h> 47e1743d02SSøren Schmidt #include <sys/sysctl.h> 48a794e791SBruce Evans #include <sys/vnode.h> 49e1743d02SSøren Schmidt 50e1743d02SSøren Schmidt #include <vm/vm.h> 51e1743d02SSøren Schmidt #include <vm/vm_kern.h> 52e1743d02SSøren Schmidt #include <vm/vm_param.h> 53e1743d02SSøren Schmidt #include <vm/pmap.h> 54996c772fSJohn Dyson #include <sys/lock.h> 55e1743d02SSøren Schmidt #include <vm/vm_map.h> 56e1743d02SSøren Schmidt #include <vm/vm_prot.h> 57e1743d02SSøren Schmidt #include <vm/vm_extern.h> 58e1743d02SSøren Schmidt 59e1743d02SSøren Schmidt #include <machine/md_var.h> 60e1743d02SSøren Schmidt 61e1743d02SSøren Schmidt #define MAX_PHDR 32 /* XXX enough ? */ 62e1743d02SSøren Schmidt 63ecbb00a2SDoug Rabson #if ELF_TARG_CLASS == ELFCLASS32 64ecbb00a2SDoug Rabson 65ecbb00a2SDoug Rabson #define Elf_Ehdr Elf32_Ehdr 66ecbb00a2SDoug Rabson #define Elf_Phdr Elf32_Phdr 67ecbb00a2SDoug Rabson #define Elf_Auxargs Elf32_Auxargs 68ecbb00a2SDoug Rabson #define Elf_Brandinfo Elf32_Brandinfo 69ecbb00a2SDoug Rabson 70ecbb00a2SDoug Rabson #else 71ecbb00a2SDoug Rabson 72ecbb00a2SDoug Rabson #define Elf_Ehdr Elf64_Ehdr 73ecbb00a2SDoug Rabson #define Elf_Phdr Elf64_Phdr 74ecbb00a2SDoug Rabson #define Elf_Auxargs Elf64_Auxargs 75ecbb00a2SDoug Rabson #define Elf_Brandinfo Elf64_Brandinfo 76ecbb00a2SDoug Rabson 77ecbb00a2SDoug Rabson #endif 78ecbb00a2SDoug Rabson 79ecbb00a2SDoug Rabson 80ecbb00a2SDoug Rabson static int elf_check_header __P((const Elf_Ehdr *hdr, int type)); 81e1743d02SSøren Schmidt static int elf_load_section __P((struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot)); 82e1743d02SSøren Schmidt static int elf_load_file __P((struct proc *p, char *file, u_long *addr, u_long *entry)); 83ecbb00a2SDoug Rabson static int elf_freebsd_fixup __P((long **stack_base, struct image_params *imgp)); 84303b270bSEivind Eklund static int exec_elf_imgact __P((struct image_params *imgp)); 85e1743d02SSøren Schmidt 86d8a4f230SBruce Evans static int elf_trace = 0; 87d8a4f230SBruce Evans SYSCTL_INT(_debug, OID_AUTO, elf_trace, CTLFLAG_RW, &elf_trace, 0, ""); 88e1743d02SSøren Schmidt #define UPRINTF if (elf_trace) uprintf 89e1743d02SSøren Schmidt 90e1743d02SSøren Schmidt static struct sysentvec elf_freebsd_sysvec = { 91e1743d02SSøren Schmidt SYS_MAXSYSCALL, 92e1743d02SSøren Schmidt sysent, 93e1743d02SSøren Schmidt 0, 94e1743d02SSøren Schmidt 0, 95e1743d02SSøren Schmidt 0, 96e1743d02SSøren Schmidt 0, 97e1743d02SSøren Schmidt 0, 98288078beSEivind Eklund 0, 99e1743d02SSøren Schmidt elf_freebsd_fixup, 100e1743d02SSøren Schmidt sendsig, 101e1743d02SSøren Schmidt sigcode, 102e1743d02SSøren Schmidt &szsigcode, 103e1743d02SSøren Schmidt 0, 1046ead3eddSJohn Dyson "FreeBSD ELF" 105e1743d02SSøren Schmidt }; 106e1743d02SSøren Schmidt 107ecbb00a2SDoug Rabson static Elf_Brandinfo freebsd_brand_info = { 108ea5a2b2eSSøren Schmidt "FreeBSD", 109ea5a2b2eSSøren Schmidt "", 110e1743d02SSøren Schmidt "/usr/libexec/ld-elf.so.1", 111ea5a2b2eSSøren Schmidt &elf_freebsd_sysvec 112e1743d02SSøren Schmidt }; 113ecbb00a2SDoug Rabson static Elf_Brandinfo *elf_brand_list[MAX_BRANDS] = { 114ea5a2b2eSSøren Schmidt &freebsd_brand_info, 115e1743d02SSøren Schmidt NULL, NULL, NULL, 116e1743d02SSøren Schmidt NULL, NULL, NULL, NULL 117e1743d02SSøren Schmidt }; 118e1743d02SSøren Schmidt 119e1743d02SSøren Schmidt int 120ecbb00a2SDoug Rabson elf_insert_brand_entry(Elf_Brandinfo *entry) 121e1743d02SSøren Schmidt { 122e1743d02SSøren Schmidt int i; 123e1743d02SSøren Schmidt 124ea5a2b2eSSøren Schmidt for (i=1; i<MAX_BRANDS; i++) { 125ea5a2b2eSSøren Schmidt if (elf_brand_list[i] == NULL) { 126ea5a2b2eSSøren Schmidt elf_brand_list[i] = entry; 127e1743d02SSøren Schmidt break; 128e1743d02SSøren Schmidt } 129e1743d02SSøren Schmidt } 130ea5a2b2eSSøren Schmidt if (i == MAX_BRANDS) 131e1743d02SSøren Schmidt return -1; 132e1743d02SSøren Schmidt return 0; 133e1743d02SSøren Schmidt } 134e1743d02SSøren Schmidt 135e1743d02SSøren Schmidt int 136ecbb00a2SDoug Rabson elf_remove_brand_entry(Elf_Brandinfo *entry) 137e1743d02SSøren Schmidt { 138e1743d02SSøren Schmidt int i; 139e1743d02SSøren Schmidt 140ea5a2b2eSSøren Schmidt for (i=1; i<MAX_BRANDS; i++) { 141ea5a2b2eSSøren Schmidt if (elf_brand_list[i] == entry) { 142ea5a2b2eSSøren Schmidt elf_brand_list[i] = NULL; 143e1743d02SSøren Schmidt break; 144e1743d02SSøren Schmidt } 145e1743d02SSøren Schmidt } 146ea5a2b2eSSøren Schmidt if (i == MAX_BRANDS) 147e1743d02SSøren Schmidt return -1; 148e1743d02SSøren Schmidt return 0; 149e1743d02SSøren Schmidt } 150e1743d02SSøren Schmidt 151e1743d02SSøren Schmidt static int 152ecbb00a2SDoug Rabson elf_check_header(const Elf_Ehdr *hdr, int type) 153e1743d02SSøren Schmidt { 154e1743d02SSøren Schmidt if (!(hdr->e_ident[EI_MAG0] == ELFMAG0 && 155e1743d02SSøren Schmidt hdr->e_ident[EI_MAG1] == ELFMAG1 && 156e1743d02SSøren Schmidt hdr->e_ident[EI_MAG2] == ELFMAG2 && 157e1743d02SSøren Schmidt hdr->e_ident[EI_MAG3] == ELFMAG3)) 158e1743d02SSøren Schmidt return ENOEXEC; 159e1743d02SSøren Schmidt 160ecbb00a2SDoug Rabson #ifdef __i396__ 161e1743d02SSøren Schmidt if (hdr->e_machine != EM_386 && hdr->e_machine != EM_486) 162ecbb00a2SDoug Rabson #endif 163ecbb00a2SDoug Rabson #ifdef __alpha__ 164ecbb00a2SDoug Rabson if (hdr->e_machine != EM_ALPHA) 165ecbb00a2SDoug Rabson #endif 166e1743d02SSøren Schmidt return ENOEXEC; 167e1743d02SSøren Schmidt 168ecbb00a2SDoug Rabson 169e1743d02SSøren Schmidt if (hdr->e_type != type) 170e1743d02SSøren Schmidt return ENOEXEC; 171e1743d02SSøren Schmidt 172e1743d02SSøren Schmidt return 0; 173e1743d02SSøren Schmidt } 174e1743d02SSøren Schmidt 175e1743d02SSøren Schmidt static int 176e1743d02SSøren Schmidt elf_load_section(struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot) 177e1743d02SSøren Schmidt { 178e1743d02SSøren Schmidt size_t map_len; 179e1743d02SSøren Schmidt vm_offset_t map_addr; 180e1743d02SSøren Schmidt int error; 181e1743d02SSøren Schmidt unsigned char *data_buf = 0; 182e1743d02SSøren Schmidt size_t copy_len; 183e1743d02SSøren Schmidt 184e1743d02SSøren Schmidt map_addr = trunc_page(vmaddr); 185e1743d02SSøren Schmidt 186e1743d02SSøren Schmidt if (memsz > filsz) 187e1743d02SSøren Schmidt map_len = trunc_page(offset+filsz) - trunc_page(offset); 188e1743d02SSøren Schmidt else 189e1743d02SSøren Schmidt map_len = round_page(offset+filsz) - trunc_page(offset); 190e1743d02SSøren Schmidt 191e1743d02SSøren Schmidt if (error = vm_mmap (&vmspace->vm_map, 192e1743d02SSøren Schmidt &map_addr, 193e1743d02SSøren Schmidt map_len, 194e1743d02SSøren Schmidt prot, 195e1743d02SSøren Schmidt VM_PROT_ALL, 19671d7d1b1SPeter Wemm MAP_PRIVATE | MAP_FIXED, 197e1743d02SSøren Schmidt (caddr_t)vp, 198e1743d02SSøren Schmidt trunc_page(offset))) 199e1743d02SSøren Schmidt return error; 200e1743d02SSøren Schmidt 201e1743d02SSøren Schmidt if (memsz == filsz) 202e1743d02SSøren Schmidt return 0; 203e1743d02SSøren Schmidt 204e1743d02SSøren Schmidt /* 205e1743d02SSøren Schmidt * We have to map the remaining bit of the file into the kernel's 206e1743d02SSøren Schmidt * memory map, allocate some anonymous memory, and copy that last 207e1743d02SSøren Schmidt * bit into it. The remaining space should be .bss... 208e1743d02SSøren Schmidt */ 209e1743d02SSøren Schmidt copy_len = (offset + filsz) - trunc_page(offset + filsz); 210e1743d02SSøren Schmidt map_addr = trunc_page(vmaddr + filsz); 211250c11f9SPeter Wemm map_len = round_page(vmaddr + memsz) - map_addr; 212e1743d02SSøren Schmidt 2138191d577SPeter Wemm if (map_len != 0) { 214e1743d02SSøren Schmidt if (error = vm_map_find(&vmspace->vm_map, NULL, 0, 215e1743d02SSøren Schmidt &map_addr, map_len, FALSE, 216e1743d02SSøren Schmidt VM_PROT_ALL, VM_PROT_ALL,0)) 217e1743d02SSøren Schmidt return error; 2188191d577SPeter Wemm } 219e1743d02SSøren Schmidt 220c8a79999SPeter Wemm if (error = vm_mmap(exec_map, 221e1743d02SSøren Schmidt (vm_offset_t *)&data_buf, 222e1743d02SSøren Schmidt PAGE_SIZE, 223e1743d02SSøren Schmidt VM_PROT_READ, 224e1743d02SSøren Schmidt VM_PROT_READ, 22571d7d1b1SPeter Wemm 0, 226e1743d02SSøren Schmidt (caddr_t)vp, 227e1743d02SSøren Schmidt trunc_page(offset + filsz))) 228e1743d02SSøren Schmidt return error; 229e1743d02SSøren Schmidt 230e1743d02SSøren Schmidt error = copyout(data_buf, (caddr_t)map_addr, copy_len); 231e1743d02SSøren Schmidt 232c8a79999SPeter Wemm vm_map_remove(exec_map, (vm_offset_t)data_buf, 233e1743d02SSøren Schmidt (vm_offset_t)data_buf + PAGE_SIZE); 234e1743d02SSøren Schmidt 235e1743d02SSøren Schmidt /* 2368191d577SPeter Wemm * set it to the specified protection 237e1743d02SSøren Schmidt */ 2388191d577SPeter Wemm vm_map_protect(&vmspace->vm_map, map_addr, map_addr + map_len, prot, 2398191d577SPeter Wemm FALSE); 2408191d577SPeter Wemm 241e1743d02SSøren Schmidt UPRINTF("bss size %d (%x)\n", map_len-copy_len, map_len-copy_len); 242e1743d02SSøren Schmidt return error; 243e1743d02SSøren Schmidt } 244e1743d02SSøren Schmidt 245e1743d02SSøren Schmidt static int 246e1743d02SSøren Schmidt elf_load_file(struct proc *p, char *file, u_long *addr, u_long *entry) 247e1743d02SSøren Schmidt { 248ecbb00a2SDoug Rabson Elf_Ehdr *hdr = NULL; 249ecbb00a2SDoug Rabson Elf_Phdr *phdr = NULL; 250e1743d02SSøren Schmidt struct nameidata nd; 251e1743d02SSøren Schmidt struct vmspace *vmspace = p->p_vmspace; 252c8a79999SPeter Wemm struct vattr attr; 253c8a79999SPeter Wemm struct image_params image_params, *imgp; 254e1743d02SSøren Schmidt vm_prot_t prot = 0; 255e1743d02SSøren Schmidt unsigned long text_size = 0, data_size = 0; 256e1743d02SSøren Schmidt unsigned long text_addr = 0, data_addr = 0; 257e1743d02SSøren Schmidt int header_size = 0; 258e1743d02SSøren Schmidt int error, i; 259e1743d02SSøren Schmidt 260c8a79999SPeter Wemm imgp = &image_params; 261c8a79999SPeter Wemm /* 262c8a79999SPeter Wemm * Initialize part of the common data 263c8a79999SPeter Wemm */ 264c8a79999SPeter Wemm imgp->proc = p; 265c8a79999SPeter Wemm imgp->uap = NULL; 266c8a79999SPeter Wemm imgp->attr = &attr; 267c8a79999SPeter Wemm imgp->firstpage = NULL; 268c8a79999SPeter Wemm imgp->image_header = (char *)kmem_alloc_wait(exec_map, PAGE_SIZE); 269c8a79999SPeter Wemm 270c8a79999SPeter Wemm if (imgp->image_header == NULL) { 271c8a79999SPeter Wemm nd.ni_vp = NULL; 272c8a79999SPeter Wemm error = ENOMEM; 273c8a79999SPeter Wemm goto fail; 274c8a79999SPeter Wemm } 275c8a79999SPeter Wemm 276e1743d02SSøren Schmidt NDINIT(&nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_SYSSPACE, file, p); 277e1743d02SSøren Schmidt 2781560a9d5SPeter Wemm if (error = namei(&nd)) { 2791560a9d5SPeter Wemm nd.ni_vp = NULL; 280e1743d02SSøren Schmidt goto fail; 281e1743d02SSøren Schmidt } 282e1743d02SSøren Schmidt 283c8a79999SPeter Wemm imgp->vp = nd.ni_vp; 284c8a79999SPeter Wemm 285e1743d02SSøren Schmidt /* 286e1743d02SSøren Schmidt * Check permissions, modes, uid, etc on the file, and "open" it. 287e1743d02SSøren Schmidt */ 288c8a79999SPeter Wemm error = exec_check_permissions(imgp); 289c8a79999SPeter Wemm if (error) { 290996c772fSJohn Dyson VOP_UNLOCK(nd.ni_vp, 0, p); 291c8a79999SPeter Wemm goto fail; 292c8a79999SPeter Wemm } 293e1743d02SSøren Schmidt 294c8a79999SPeter Wemm error = exec_map_first_page(imgp); 295c8a79999SPeter Wemm VOP_UNLOCK(nd.ni_vp, 0, p); 296e1743d02SSøren Schmidt if (error) 297e1743d02SSøren Schmidt goto fail; 298e1743d02SSøren Schmidt 299ecbb00a2SDoug Rabson hdr = (Elf_Ehdr *)imgp->image_header; 300e1743d02SSøren Schmidt if (error = elf_check_header(hdr, ET_DYN)) 301e1743d02SSøren Schmidt goto fail; 302e1743d02SSøren Schmidt 303e1743d02SSøren Schmidt /* 304e1743d02SSøren Schmidt * ouch, need to bounds check in case user gives us a corrupted 305e1743d02SSøren Schmidt * file with an insane header size 306e1743d02SSøren Schmidt */ 307e1743d02SSøren Schmidt if (hdr->e_phnum > MAX_PHDR) { /* XXX: ever more than this? */ 308e1743d02SSøren Schmidt error = ENOEXEC; 309e1743d02SSøren Schmidt goto fail; 310e1743d02SSøren Schmidt } 311e1743d02SSøren Schmidt 312e1743d02SSøren Schmidt header_size = hdr->e_phentsize * hdr->e_phnum; 313e1743d02SSøren Schmidt 314c8a79999SPeter Wemm /* Only support headers that fit within first page for now */ 315c8a79999SPeter Wemm if (header_size + hdr->e_phoff > PAGE_SIZE) { 316c8a79999SPeter Wemm error = ENOEXEC; 317e1743d02SSøren Schmidt goto fail; 318c8a79999SPeter Wemm } 319c8a79999SPeter Wemm 320ecbb00a2SDoug Rabson phdr = (Elf_Phdr *)(imgp->image_header + hdr->e_phoff); 321e1743d02SSøren Schmidt 322e1743d02SSøren Schmidt for (i = 0; i < hdr->e_phnum; i++) { 323e1743d02SSøren Schmidt switch(phdr[i].p_type) { 324e1743d02SSøren Schmidt 325e1743d02SSøren Schmidt case PT_NULL: /* NULL section */ 326e1743d02SSøren Schmidt UPRINTF ("ELF(file) PT_NULL section\n"); 327e1743d02SSøren Schmidt break; 328e1743d02SSøren Schmidt case PT_LOAD: /* Loadable segment */ 329e1743d02SSøren Schmidt { 330e1743d02SSøren Schmidt UPRINTF ("ELF(file) PT_LOAD section "); 331e1743d02SSøren Schmidt if (phdr[i].p_flags & PF_X) 332e1743d02SSøren Schmidt prot |= VM_PROT_EXECUTE; 333e1743d02SSøren Schmidt if (phdr[i].p_flags & PF_W) 334e1743d02SSøren Schmidt prot |= VM_PROT_WRITE; 335e1743d02SSøren Schmidt if (phdr[i].p_flags & PF_R) 336e1743d02SSøren Schmidt prot |= VM_PROT_READ; 337e1743d02SSøren Schmidt 338e1743d02SSøren Schmidt if (error = elf_load_section(vmspace, nd.ni_vp, 339e1743d02SSøren Schmidt phdr[i].p_offset, 340e1743d02SSøren Schmidt (caddr_t)phdr[i].p_vaddr + 341e1743d02SSøren Schmidt (*addr), 342e1743d02SSøren Schmidt phdr[i].p_memsz, 343e1743d02SSøren Schmidt phdr[i].p_filesz, prot)) 344e1743d02SSøren Schmidt goto fail; 345e1743d02SSøren Schmidt 346e1743d02SSøren Schmidt /* 347e1743d02SSøren Schmidt * Is this .text or .data ?? 348e1743d02SSøren Schmidt * 349e1743d02SSøren Schmidt * We only handle one each of those yet XXX 350e1743d02SSøren Schmidt */ 351e1743d02SSøren Schmidt if (hdr->e_entry >= phdr[i].p_vaddr && 352e1743d02SSøren Schmidt hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) { 353e1743d02SSøren Schmidt text_addr = trunc_page(phdr[i].p_vaddr+(*addr)); 3548191d577SPeter Wemm text_size = round_page(phdr[i].p_memsz + 3558191d577SPeter Wemm phdr[i].p_vaddr - 3568191d577SPeter Wemm trunc_page(phdr[i].p_vaddr)); 357e1743d02SSøren Schmidt *entry=(unsigned long)hdr->e_entry+(*addr); 358e1743d02SSøren Schmidt UPRINTF(".text <%08x,%08x> entry=%08x\n", 359e1743d02SSøren Schmidt text_addr, text_size, *entry); 360e1743d02SSøren Schmidt } else { 361e1743d02SSøren Schmidt data_addr = trunc_page(phdr[i].p_vaddr+(*addr)); 3628191d577SPeter Wemm data_size = round_page(phdr[i].p_memsz + 3638191d577SPeter Wemm phdr[i].p_vaddr - 3648191d577SPeter Wemm trunc_page(phdr[i].p_vaddr)); 365e1743d02SSøren Schmidt UPRINTF(".data <%08x,%08x>\n", 366e1743d02SSøren Schmidt data_addr, data_size); 367e1743d02SSøren Schmidt } 368e1743d02SSøren Schmidt } 369e1743d02SSøren Schmidt break; 370e1743d02SSøren Schmidt 371e1743d02SSøren Schmidt case PT_DYNAMIC:/* Dynamic link information */ 372e1743d02SSøren Schmidt UPRINTF ("ELF(file) PT_DYNAMIC section\n"); 373e1743d02SSøren Schmidt break; 374e1743d02SSøren Schmidt case PT_INTERP: /* Path to interpreter */ 375e1743d02SSøren Schmidt UPRINTF ("ELF(file) PT_INTERP section\n"); 376e1743d02SSøren Schmidt break; 377e1743d02SSøren Schmidt case PT_NOTE: /* Note section */ 378e1743d02SSøren Schmidt UPRINTF ("ELF(file) PT_NOTE section\n"); 379e1743d02SSøren Schmidt break; 380e1743d02SSøren Schmidt case PT_SHLIB: /* Shared lib section */ 381e1743d02SSøren Schmidt UPRINTF ("ELF(file) PT_SHLIB section\n"); 382e1743d02SSøren Schmidt break; 383e1743d02SSøren Schmidt case PT_PHDR: /* Program header table info */ 384e1743d02SSøren Schmidt UPRINTF ("ELF(file) PT_PHDR section\n"); 385e1743d02SSøren Schmidt break; 386e1743d02SSøren Schmidt default: 387e1743d02SSøren Schmidt UPRINTF ("ELF(file) %d section ??\n", phdr[i].p_type ); 388e1743d02SSøren Schmidt } 389e1743d02SSøren Schmidt } 390e1743d02SSøren Schmidt 391e1743d02SSøren Schmidt fail: 392c8a79999SPeter Wemm if (imgp->firstpage) 393c8a79999SPeter Wemm exec_unmap_first_page(imgp); 394c8a79999SPeter Wemm if (imgp->image_header) 395c8a79999SPeter Wemm kmem_free_wakeup(exec_map, (vm_offset_t)imgp->image_header, 396c8a79999SPeter Wemm PAGE_SIZE); 3971560a9d5SPeter Wemm if (nd.ni_vp) 3981560a9d5SPeter Wemm vrele(nd.ni_vp); 399e1743d02SSøren Schmidt 400e1743d02SSøren Schmidt return error; 401e1743d02SSøren Schmidt } 402e1743d02SSøren Schmidt 403303b270bSEivind Eklund static int 404e1743d02SSøren Schmidt exec_elf_imgact(struct image_params *imgp) 405e1743d02SSøren Schmidt { 406ecbb00a2SDoug Rabson const Elf_Ehdr *hdr = (const Elf_Ehdr *) imgp->image_header; 407ecbb00a2SDoug Rabson const Elf_Phdr *phdr, *mapped_phdr = NULL; 408ecbb00a2SDoug Rabson Elf_Auxargs *elf_auxargs = NULL; 4095856e12eSJohn Dyson struct vmspace *vmspace; 410e1743d02SSøren Schmidt vm_prot_t prot = 0; 411e1743d02SSøren Schmidt u_long text_size = 0, data_size = 0; 412e1743d02SSøren Schmidt u_long text_addr = 0, data_addr = 0; 413e1743d02SSøren Schmidt u_long addr, entry = 0, proghdr = 0; 414c8a79999SPeter Wemm int error, i, header_size = 0; 415c8a79999SPeter Wemm const char *interp = NULL; 416ea5a2b2eSSøren Schmidt char *brand = NULL; 417ea5a2b2eSSøren Schmidt char path[MAXPATHLEN]; 418e1743d02SSøren Schmidt 419e1743d02SSøren Schmidt /* 420e1743d02SSøren Schmidt * Do we have a valid ELF header ? 421e1743d02SSøren Schmidt */ 422e1743d02SSøren Schmidt if (elf_check_header(hdr, ET_EXEC)) 423e1743d02SSøren Schmidt return -1; 424e1743d02SSøren Schmidt 425e1743d02SSøren Schmidt /* 426e1743d02SSøren Schmidt * From here on down, we return an errno, not -1, as we've 427e1743d02SSøren Schmidt * detected an ELF file. 428e1743d02SSøren Schmidt */ 429e1743d02SSøren Schmidt 430e1743d02SSøren Schmidt /* 431e1743d02SSøren Schmidt * ouch, need to bounds check in case user gives us a corrupted 432e1743d02SSøren Schmidt * file with an insane header size 433e1743d02SSøren Schmidt */ 434e1743d02SSøren Schmidt if (hdr->e_phnum > MAX_PHDR) { /* XXX: ever more than this? */ 435e1743d02SSøren Schmidt return ENOEXEC; 436e1743d02SSøren Schmidt } 437e1743d02SSøren Schmidt 438e1743d02SSøren Schmidt header_size = hdr->e_phentsize * hdr->e_phnum; 439e1743d02SSøren Schmidt 440e1743d02SSøren Schmidt if ((hdr->e_phoff > PAGE_SIZE) || 441e1743d02SSøren Schmidt (hdr->e_phoff + header_size) > PAGE_SIZE) { 442c8a79999SPeter Wemm /* Only support headers in first page for now */ 443c8a79999SPeter Wemm return ENOEXEC; 444e1743d02SSøren Schmidt } else { 445ecbb00a2SDoug Rabson phdr = (const Elf_Phdr*) 446e0c95ed9SBruce Evans ((const char *)imgp->image_header + hdr->e_phoff); 447e1743d02SSøren Schmidt } 448e1743d02SSøren Schmidt 449e1743d02SSøren Schmidt /* 450e1743d02SSøren Schmidt * From this point on, we may have resources that need to be freed. 451e1743d02SSøren Schmidt */ 452e1743d02SSøren Schmidt if (error = exec_extract_strings(imgp)) 453e1743d02SSøren Schmidt goto fail; 454e1743d02SSøren Schmidt 455e1743d02SSøren Schmidt exec_new_vmspace(imgp); 456e1743d02SSøren Schmidt 4575856e12eSJohn Dyson vmspace = imgp->proc->p_vmspace; 4585856e12eSJohn Dyson 459e1743d02SSøren Schmidt for (i = 0; i < hdr->e_phnum; i++) { 460e1743d02SSøren Schmidt switch(phdr[i].p_type) { 461e1743d02SSøren Schmidt 462e1743d02SSøren Schmidt case PT_NULL: /* NULL section */ 463e1743d02SSøren Schmidt UPRINTF ("ELF PT_NULL section\n"); 464e1743d02SSøren Schmidt break; 465e1743d02SSøren Schmidt case PT_LOAD: /* Loadable segment */ 466e1743d02SSøren Schmidt { 467e1743d02SSøren Schmidt UPRINTF ("ELF PT_LOAD section "); 468e1743d02SSøren Schmidt if (phdr[i].p_flags & PF_X) 469e1743d02SSøren Schmidt prot |= VM_PROT_EXECUTE; 470e1743d02SSøren Schmidt if (phdr[i].p_flags & PF_W) 471e1743d02SSøren Schmidt prot |= VM_PROT_WRITE; 472e1743d02SSøren Schmidt if (phdr[i].p_flags & PF_R) 473e1743d02SSøren Schmidt prot |= VM_PROT_READ; 474e1743d02SSøren Schmidt 475e1743d02SSøren Schmidt if (error = elf_load_section(vmspace, imgp->vp, 476e1743d02SSøren Schmidt phdr[i].p_offset, 477e1743d02SSøren Schmidt (caddr_t)phdr[i].p_vaddr, 478e1743d02SSøren Schmidt phdr[i].p_memsz, 479e1743d02SSøren Schmidt phdr[i].p_filesz, prot)) 480e1743d02SSøren Schmidt goto fail; 481e1743d02SSøren Schmidt 482e1743d02SSøren Schmidt /* 483e1743d02SSøren Schmidt * Is this .text or .data ?? 484e1743d02SSøren Schmidt * 485e1743d02SSøren Schmidt * We only handle one each of those yet XXX 486e1743d02SSøren Schmidt */ 487e1743d02SSøren Schmidt if (hdr->e_entry >= phdr[i].p_vaddr && 488e1743d02SSøren Schmidt hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) { 489e1743d02SSøren Schmidt text_addr = trunc_page(phdr[i].p_vaddr); 4908191d577SPeter Wemm text_size = round_page(phdr[i].p_memsz + 4918191d577SPeter Wemm phdr[i].p_vaddr - 4928191d577SPeter Wemm text_addr); 493e1743d02SSøren Schmidt entry = (u_long)hdr->e_entry; 494e1743d02SSøren Schmidt UPRINTF(".text <%08x,%08x> entry=%08x\n", 495e1743d02SSøren Schmidt text_addr, text_size, entry); 496e1743d02SSøren Schmidt } else { 497e1743d02SSøren Schmidt data_addr = trunc_page(phdr[i].p_vaddr); 4988191d577SPeter Wemm data_size = round_page(phdr[i].p_memsz + 4998191d577SPeter Wemm phdr[i].p_vaddr - 5008191d577SPeter Wemm data_addr); 501e1743d02SSøren Schmidt UPRINTF(".data <%08x,%08x>\n", 502e1743d02SSøren Schmidt data_addr, data_size); 503e1743d02SSøren Schmidt } 504e1743d02SSøren Schmidt } 505e1743d02SSøren Schmidt break; 506e1743d02SSøren Schmidt 507e1743d02SSøren Schmidt case PT_DYNAMIC:/* Dynamic link information */ 508e1743d02SSøren Schmidt UPRINTF ("ELF PT_DYNAMIC section ??\n"); 509e1743d02SSøren Schmidt break; 510e1743d02SSøren Schmidt case PT_INTERP: /* Path to interpreter */ 511e1743d02SSøren Schmidt UPRINTF ("ELF PT_INTERP section "); 512c8a79999SPeter Wemm if (phdr[i].p_filesz > MAXPATHLEN || 513c8a79999SPeter Wemm phdr[i].p_offset + phdr[i].p_filesz > PAGE_SIZE) { 514e1743d02SSøren Schmidt error = ENOEXEC; 515e1743d02SSøren Schmidt goto fail; 516e1743d02SSøren Schmidt } 517c8a79999SPeter Wemm interp = imgp->image_header + phdr[i].p_offset; 518e1743d02SSøren Schmidt UPRINTF("<%s>\n", interp); 519e1743d02SSøren Schmidt break; 520e1743d02SSøren Schmidt case PT_NOTE: /* Note section */ 521e1743d02SSøren Schmidt UPRINTF ("ELF PT_NOTE section\n"); 522e1743d02SSøren Schmidt break; 523e1743d02SSøren Schmidt case PT_SHLIB: /* Shared lib section */ 524e1743d02SSøren Schmidt UPRINTF ("ELF PT_SHLIB section\n"); 525e1743d02SSøren Schmidt break; 526e1743d02SSøren Schmidt case PT_PHDR: /* Program header table info */ 527e1743d02SSøren Schmidt UPRINTF ("ELF PT_PHDR section <%x>\n", phdr[i].p_vaddr); 528e1743d02SSøren Schmidt proghdr = phdr[i].p_vaddr; 529e1743d02SSøren Schmidt break; 530e1743d02SSøren Schmidt default: 531e1743d02SSøren Schmidt UPRINTF ("ELF %d section ??\n", phdr[i].p_type); 532e1743d02SSøren Schmidt } 533e1743d02SSøren Schmidt } 534e1743d02SSøren Schmidt 535e1743d02SSøren Schmidt vmspace->vm_tsize = text_size >> PAGE_SHIFT; 536e1743d02SSøren Schmidt vmspace->vm_taddr = (caddr_t)text_addr; 537e1743d02SSøren Schmidt vmspace->vm_dsize = data_size >> PAGE_SHIFT; 538e1743d02SSøren Schmidt vmspace->vm_daddr = (caddr_t)data_addr; 539e1743d02SSøren Schmidt 540ecbb00a2SDoug Rabson addr = 2L*MAXDSIZ; /* May depend on OS type XXX */ 541e1743d02SSøren Schmidt 542ea5a2b2eSSøren Schmidt imgp->entry_addr = entry; 543ea5a2b2eSSøren Schmidt 544e1743d02SSøren Schmidt /* 545ea5a2b2eSSøren Schmidt * So which kind (brand) of ELF binary do we have at hand 546ea5a2b2eSSøren Schmidt * FreeBSD, Linux, SVR4 or something else ?? 547ea5a2b2eSSøren Schmidt * If its has a interpreter section try that first 548e1743d02SSøren Schmidt */ 549ea5a2b2eSSøren Schmidt if (interp) { 550ea5a2b2eSSøren Schmidt for (i=0; i<MAX_BRANDS; i++) { 551ea5a2b2eSSøren Schmidt if (elf_brand_list[i] != NULL) { 552ea5a2b2eSSøren Schmidt if (!strcmp(interp, elf_brand_list[i]->interp_path)) { 553e1743d02SSøren Schmidt imgp->proc->p_sysent = 554ea5a2b2eSSøren Schmidt elf_brand_list[i]->sysvec; 555ea5a2b2eSSøren Schmidt strcpy(path, elf_brand_list[i]->emul_path); 556ea5a2b2eSSøren Schmidt strcat(path, elf_brand_list[i]->interp_path); 557e1743d02SSøren Schmidt UPRINTF("interpreter=<%s> %s\n", 558ea5a2b2eSSøren Schmidt elf_brand_list[i]->interp_path, 559ea5a2b2eSSøren Schmidt elf_brand_list[i]->emul_path); 560e1743d02SSøren Schmidt break; 561e1743d02SSøren Schmidt } 562e1743d02SSøren Schmidt } 563e1743d02SSøren Schmidt } 564ea5a2b2eSSøren Schmidt } 565ea5a2b2eSSøren Schmidt 566ea5a2b2eSSøren Schmidt /* 567ea5a2b2eSSøren Schmidt * If there is no interpreter, or recognition of it 568ea5a2b2eSSøren Schmidt * failed, se if the binary is branded. 569ea5a2b2eSSøren Schmidt */ 570ea5a2b2eSSøren Schmidt if (!interp || i == MAX_BRANDS) { 571ea5a2b2eSSøren Schmidt brand = (char *)&(hdr->e_ident[EI_BRAND]); 572ea5a2b2eSSøren Schmidt for (i=0; i<MAX_BRANDS; i++) { 573ea5a2b2eSSøren Schmidt if (elf_brand_list[i] != NULL) { 574ea5a2b2eSSøren Schmidt if (!strcmp(brand, elf_brand_list[i]->brand)) { 575ea5a2b2eSSøren Schmidt imgp->proc->p_sysent = elf_brand_list[i]->sysvec; 576ea5a2b2eSSøren Schmidt if (interp) { 577ea5a2b2eSSøren Schmidt strcpy(path, elf_brand_list[i]->emul_path); 578ea5a2b2eSSøren Schmidt strcat(path, elf_brand_list[i]->interp_path); 579ea5a2b2eSSøren Schmidt UPRINTF("interpreter=<%s> %s\n", 580ea5a2b2eSSøren Schmidt elf_brand_list[i]->interp_path, 581ea5a2b2eSSøren Schmidt elf_brand_list[i]->emul_path); 582ea5a2b2eSSøren Schmidt } 583d672246bSSøren Schmidt break; 584ea5a2b2eSSøren Schmidt } 585ea5a2b2eSSøren Schmidt } 586ea5a2b2eSSøren Schmidt } 587ea5a2b2eSSøren Schmidt } 588ea5a2b2eSSøren Schmidt if (i == MAX_BRANDS) { 589ea5a2b2eSSøren Schmidt uprintf("ELF binary type not known\n"); 590ecbb00a2SDoug Rabson #ifdef __alpha__ 591ecbb00a2SDoug Rabson uprintf("assuming FreeBSD\n"); 592ecbb00a2SDoug Rabson i = 0; 593ecbb00a2SDoug Rabson #else 594e1743d02SSøren Schmidt error = ENOEXEC; 595e1743d02SSøren Schmidt goto fail; 596ecbb00a2SDoug Rabson #endif 597e1743d02SSøren Schmidt } 598ea5a2b2eSSøren Schmidt if (interp) { 599e1743d02SSøren Schmidt if (error = elf_load_file(imgp->proc, 600e1743d02SSøren Schmidt path, 601e1743d02SSøren Schmidt &addr, /* XXX */ 602e1743d02SSøren Schmidt &imgp->entry_addr)) { 603e1743d02SSøren Schmidt uprintf("ELF interpreter %s not found\n", path); 604e1743d02SSøren Schmidt goto fail; 605e1743d02SSøren Schmidt } 606e1743d02SSøren Schmidt } 607ea5a2b2eSSøren Schmidt 608717fb679SSøren Schmidt UPRINTF("Executing %s binary\n", elf_brand_list[i]->brand); 609e1743d02SSøren Schmidt 610e1743d02SSøren Schmidt /* 611e1743d02SSøren Schmidt * Construct auxargs table (used by the fixup routine) 612e1743d02SSøren Schmidt */ 613ecbb00a2SDoug Rabson elf_auxargs = malloc(sizeof(Elf_Auxargs), M_TEMP, M_WAITOK); 614e1743d02SSøren Schmidt elf_auxargs->execfd = -1; 615e1743d02SSøren Schmidt elf_auxargs->phdr = proghdr; 616e1743d02SSøren Schmidt elf_auxargs->phent = hdr->e_phentsize; 617e1743d02SSøren Schmidt elf_auxargs->phnum = hdr->e_phnum; 618e1743d02SSøren Schmidt elf_auxargs->pagesz = PAGE_SIZE; 619e1743d02SSøren Schmidt elf_auxargs->base = addr; 620e1743d02SSøren Schmidt elf_auxargs->flags = 0; 621e1743d02SSøren Schmidt elf_auxargs->entry = entry; 622e1743d02SSøren Schmidt elf_auxargs->trace = elf_trace; 623e1743d02SSøren Schmidt 624e1743d02SSøren Schmidt imgp->auxargs = elf_auxargs; 625e1743d02SSøren Schmidt imgp->interpreted = 0; 626e1743d02SSøren Schmidt 627e1743d02SSøren Schmidt /* don't allow modifying the file while we run it */ 628e1743d02SSøren Schmidt imgp->vp->v_flag |= VTEXT; 629e1743d02SSøren Schmidt 630e1743d02SSøren Schmidt fail: 631e1743d02SSøren Schmidt return error; 632e1743d02SSøren Schmidt } 633e1743d02SSøren Schmidt 634e1743d02SSøren Schmidt static int 635ecbb00a2SDoug Rabson elf_freebsd_fixup(long **stack_base, struct image_params *imgp) 636e1743d02SSøren Schmidt { 637ecbb00a2SDoug Rabson Elf_Auxargs *args = (Elf_Auxargs *)imgp->auxargs; 638ecbb00a2SDoug Rabson long *pos; 639e1743d02SSøren Schmidt 640e1743d02SSøren Schmidt pos = *stack_base + (imgp->argc + imgp->envc + 2); 641e1743d02SSøren Schmidt 642e1743d02SSøren Schmidt if (args->trace) { 643e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_DEBUG, 1); 644e1743d02SSøren Schmidt } 645e1743d02SSøren Schmidt if (args->execfd != -1) { 646e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); 647e1743d02SSøren Schmidt } 648e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); 649e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_PHENT, args->phent); 650e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum); 651e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz); 652e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); 653e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); 654e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_BASE, args->base); 655e1743d02SSøren Schmidt AUXARGS_ENTRY(pos, AT_NULL, 0); 656e1743d02SSøren Schmidt 657e1743d02SSøren Schmidt free(imgp->auxargs, M_TEMP); 658e1743d02SSøren Schmidt imgp->auxargs = NULL; 659e1743d02SSøren Schmidt 660e1743d02SSøren Schmidt (*stack_base)--; 661ecbb00a2SDoug Rabson **stack_base = (long)imgp->argc; 662e1743d02SSøren Schmidt return 0; 663e1743d02SSøren Schmidt } 664e1743d02SSøren Schmidt 665e1743d02SSøren Schmidt /* 666e1743d02SSøren Schmidt * Tell kern_execve.c about it, with a little help from the linker. 667e1743d02SSøren Schmidt * Since `const' objects end up in the text segment, TEXT_SET is the 668e1743d02SSøren Schmidt * correct directive to use. 669e1743d02SSøren Schmidt */ 670d8a4f230SBruce Evans static const struct execsw elf_execsw = {exec_elf_imgact, "ELF"}; 671e1743d02SSøren Schmidt TEXT_SET(execsw_set, elf_execsw); 672e1743d02SSøren Schmidt 673