1 /*- 2 * Copyright (c) 2000 David O'Brien 3 * Copyright (c) 1995-1996 S�ren Schmidt 4 * Copyright (c) 1996 Peter Wemm 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer 12 * in this position and unchanged. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * $FreeBSD$ 31 */ 32 33 #include <sys/param.h> 34 #include <sys/exec.h> 35 #include <sys/fcntl.h> 36 #include <sys/imgact.h> 37 #include <sys/imgact_elf.h> 38 #include <sys/kernel.h> 39 #include <sys/lock.h> 40 #include <sys/malloc.h> 41 #include <sys/mutex.h> 42 #include <sys/mman.h> 43 #include <sys/namei.h> 44 #include <sys/pioctl.h> 45 #include <sys/proc.h> 46 #include <sys/procfs.h> 47 #include <sys/resourcevar.h> 48 #include <sys/systm.h> 49 #include <sys/signalvar.h> 50 #include <sys/stat.h> 51 #include <sys/sx.h> 52 #include <sys/syscall.h> 53 #include <sys/sysctl.h> 54 #include <sys/sysent.h> 55 #include <sys/vnode.h> 56 57 #include <vm/vm.h> 58 #include <vm/vm_kern.h> 59 #include <vm/vm_param.h> 60 #include <vm/pmap.h> 61 #include <vm/vm_map.h> 62 #include <vm/vm_object.h> 63 #include <vm/vm_extern.h> 64 65 #include <machine/elf.h> 66 #include <machine/md_var.h> 67 68 #define OLD_EI_BRAND 8 69 70 __ElfType(Brandinfo); 71 __ElfType(Auxargs); 72 73 static int elf_check_header(const Elf_Ehdr *hdr); 74 static int elf_freebsd_fixup(register_t **stack_base, 75 struct image_params *imgp); 76 static int elf_load_file(struct proc *p, const char *file, u_long *addr, 77 u_long *entry); 78 static int elf_load_section(struct proc *p, 79 struct vmspace *vmspace, struct vnode *vp, vm_object_t object, 80 vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, 81 vm_prot_t prot); 82 static int exec_elf_imgact(struct image_params *imgp); 83 84 static int elf_trace = 0; 85 SYSCTL_INT(_debug, OID_AUTO, elf_trace, CTLFLAG_RW, &elf_trace, 0, ""); 86 87 struct sysentvec elf_freebsd_sysvec = { 88 SYS_MAXSYSCALL, 89 sysent, 90 0, 91 0, 92 0, 93 0, 94 0, 95 0, 96 elf_freebsd_fixup, 97 sendsig, 98 sigcode, 99 &szsigcode, 100 0, 101 "FreeBSD ELF", 102 elf_coredump, 103 NULL, 104 MINSIGSTKSZ 105 }; 106 107 static Elf_Brandinfo freebsd_brand_info = { 108 ELFOSABI_FREEBSD, 109 "FreeBSD", 110 "", 111 "/usr/libexec/ld-elf.so.1", 112 &elf_freebsd_sysvec 113 }; 114 static Elf_Brandinfo *elf_brand_list[MAX_BRANDS] = { 115 &freebsd_brand_info, 116 NULL, NULL, NULL, 117 NULL, NULL, NULL, NULL 118 }; 119 120 int 121 elf_insert_brand_entry(Elf_Brandinfo *entry) 122 { 123 int i; 124 125 for (i=1; i<MAX_BRANDS; i++) { 126 if (elf_brand_list[i] == NULL) { 127 elf_brand_list[i] = entry; 128 break; 129 } 130 } 131 if (i == MAX_BRANDS) 132 return -1; 133 return 0; 134 } 135 136 int 137 elf_remove_brand_entry(Elf_Brandinfo *entry) 138 { 139 int i; 140 141 for (i=1; i<MAX_BRANDS; i++) { 142 if (elf_brand_list[i] == entry) { 143 elf_brand_list[i] = NULL; 144 break; 145 } 146 } 147 if (i == MAX_BRANDS) 148 return -1; 149 return 0; 150 } 151 152 int 153 elf_brand_inuse(Elf_Brandinfo *entry) 154 { 155 struct proc *p; 156 int rval = FALSE; 157 158 sx_slock(&allproc_lock); 159 LIST_FOREACH(p, &allproc, p_list) { 160 if (p->p_sysent == entry->sysvec) { 161 rval = TRUE; 162 break; 163 } 164 } 165 sx_sunlock(&allproc_lock); 166 167 return (rval); 168 } 169 170 static int 171 elf_check_header(const Elf_Ehdr *hdr) 172 { 173 if (!IS_ELF(*hdr) || 174 hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || 175 hdr->e_ident[EI_DATA] != ELF_TARG_DATA || 176 hdr->e_ident[EI_VERSION] != EV_CURRENT) 177 return ENOEXEC; 178 179 if (!ELF_MACHINE_OK(hdr->e_machine)) 180 return ENOEXEC; 181 182 if (hdr->e_version != ELF_TARG_VER) 183 return ENOEXEC; 184 185 return 0; 186 } 187 188 static int 189 elf_load_section(struct proc *p, struct vmspace *vmspace, struct vnode *vp, vm_object_t object, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot) 190 { 191 size_t map_len; 192 vm_offset_t map_addr; 193 int error, rv; 194 size_t copy_len; 195 vm_offset_t file_addr; 196 vm_offset_t data_buf = 0; 197 198 GIANT_REQUIRED; 199 200 error = 0; 201 202 /* 203 * It's necessary to fail if the filsz + offset taken from the 204 * header is greater than the actual file pager object's size. 205 * If we were to allow this, then the vm_map_find() below would 206 * walk right off the end of the file object and into the ether. 207 * 208 * While I'm here, might as well check for something else that 209 * is invalid: filsz cannot be greater than memsz. 210 */ 211 if ((off_t)filsz + offset > object->un_pager.vnp.vnp_size || 212 filsz > memsz) { 213 uprintf("elf_load_section: truncated ELF file\n"); 214 return (ENOEXEC); 215 } 216 217 map_addr = trunc_page((vm_offset_t)vmaddr); 218 file_addr = trunc_page(offset); 219 220 /* 221 * We have two choices. We can either clear the data in the last page 222 * of an oversized mapping, or we can start the anon mapping a page 223 * early and copy the initialized data into that first page. We 224 * choose the second.. 225 */ 226 if (memsz > filsz) 227 map_len = trunc_page(offset+filsz) - file_addr; 228 else 229 map_len = round_page(offset+filsz) - file_addr; 230 231 if (map_len != 0) { 232 vm_object_reference(object); 233 vm_map_lock(&vmspace->vm_map); 234 rv = vm_map_insert(&vmspace->vm_map, 235 object, 236 file_addr, /* file offset */ 237 map_addr, /* virtual start */ 238 map_addr + map_len,/* virtual end */ 239 prot, 240 VM_PROT_ALL, 241 MAP_COPY_ON_WRITE | MAP_PREFAULT); 242 vm_map_unlock(&vmspace->vm_map); 243 if (rv != KERN_SUCCESS) { 244 vm_object_deallocate(object); 245 return EINVAL; 246 } 247 248 /* we can stop now if we've covered it all */ 249 if (memsz == filsz) { 250 return 0; 251 } 252 } 253 254 255 /* 256 * We have to get the remaining bit of the file into the first part 257 * of the oversized map segment. This is normally because the .data 258 * segment in the file is extended to provide bss. It's a neat idea 259 * to try and save a page, but it's a pain in the behind to implement. 260 */ 261 copy_len = (offset + filsz) - trunc_page(offset + filsz); 262 map_addr = trunc_page((vm_offset_t)vmaddr + filsz); 263 map_len = round_page((vm_offset_t)vmaddr + memsz) - map_addr; 264 265 /* This had damn well better be true! */ 266 if (map_len != 0) { 267 vm_map_lock(&vmspace->vm_map); 268 rv = vm_map_insert(&vmspace->vm_map, NULL, 0, 269 map_addr, map_addr + map_len, 270 VM_PROT_ALL, VM_PROT_ALL, 0); 271 vm_map_unlock(&vmspace->vm_map); 272 if (rv != KERN_SUCCESS) { 273 return EINVAL; 274 } 275 } 276 277 if (copy_len != 0) { 278 vm_object_reference(object); 279 rv = vm_map_find(exec_map, 280 object, 281 trunc_page(offset + filsz), 282 &data_buf, 283 PAGE_SIZE, 284 TRUE, 285 VM_PROT_READ, 286 VM_PROT_ALL, 287 MAP_COPY_ON_WRITE | MAP_PREFAULT_PARTIAL); 288 if (rv != KERN_SUCCESS) { 289 vm_object_deallocate(object); 290 return EINVAL; 291 } 292 293 /* send the page fragment to user space */ 294 error = copyout((caddr_t)data_buf, (caddr_t)map_addr, copy_len); 295 vm_map_remove(exec_map, data_buf, data_buf + PAGE_SIZE); 296 if (error) { 297 return (error); 298 } 299 } 300 301 /* 302 * set it to the specified protection 303 */ 304 vm_map_protect(&vmspace->vm_map, map_addr, map_addr + map_len, prot, 305 FALSE); 306 307 return error; 308 } 309 310 /* 311 * Load the file "file" into memory. It may be either a shared object 312 * or an executable. 313 * 314 * The "addr" reference parameter is in/out. On entry, it specifies 315 * the address where a shared object should be loaded. If the file is 316 * an executable, this value is ignored. On exit, "addr" specifies 317 * where the file was actually loaded. 318 * 319 * The "entry" reference parameter is out only. On exit, it specifies 320 * the entry point for the loaded file. 321 */ 322 static int 323 elf_load_file(struct proc *p, const char *file, u_long *addr, u_long *entry) 324 { 325 struct { 326 struct nameidata nd; 327 struct vattr attr; 328 struct image_params image_params; 329 } *tempdata; 330 const Elf_Ehdr *hdr = NULL; 331 const Elf_Phdr *phdr = NULL; 332 struct nameidata *nd; 333 struct vmspace *vmspace = p->p_vmspace; 334 struct vattr *attr; 335 struct image_params *imgp; 336 vm_prot_t prot; 337 u_long rbase; 338 u_long base_addr = 0; 339 int error, i, numsegs; 340 341 if (curthread->td_proc != p) 342 panic("elf_load_file - thread"); /* XXXKSE DIAGNOSTIC */ 343 344 tempdata = malloc(sizeof(*tempdata), M_TEMP, M_WAITOK); 345 nd = &tempdata->nd; 346 attr = &tempdata->attr; 347 imgp = &tempdata->image_params; 348 349 /* 350 * Initialize part of the common data 351 */ 352 imgp->proc = p; 353 imgp->uap = NULL; 354 imgp->attr = attr; 355 imgp->firstpage = NULL; 356 imgp->image_header = (char *)kmem_alloc_wait(exec_map, PAGE_SIZE); 357 imgp->object = NULL; 358 359 if (imgp->image_header == NULL) { 360 nd->ni_vp = NULL; 361 error = ENOMEM; 362 goto fail; 363 } 364 365 /* XXXKSE */ 366 NDINIT(nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_SYSSPACE, file, curthread); 367 368 if ((error = namei(nd)) != 0) { 369 nd->ni_vp = NULL; 370 goto fail; 371 } 372 NDFREE(nd, NDF_ONLY_PNBUF); 373 imgp->vp = nd->ni_vp; 374 375 /* 376 * Check permissions, modes, uid, etc on the file, and "open" it. 377 */ 378 error = exec_check_permissions(imgp); 379 if (error) { 380 VOP_UNLOCK(nd->ni_vp, 0, curthread); /* XXXKSE */ 381 goto fail; 382 } 383 384 error = exec_map_first_page(imgp); 385 /* 386 * Also make certain that the interpreter stays the same, so set 387 * its VTEXT flag, too. 388 */ 389 if (error == 0) 390 nd->ni_vp->v_flag |= VTEXT; 391 VOP_GETVOBJECT(nd->ni_vp, &imgp->object); 392 vm_object_reference(imgp->object); 393 394 VOP_UNLOCK(nd->ni_vp, 0, curthread); /* XXXKSE */ 395 if (error) 396 goto fail; 397 398 hdr = (const Elf_Ehdr *)imgp->image_header; 399 if ((error = elf_check_header(hdr)) != 0) 400 goto fail; 401 if (hdr->e_type == ET_DYN) 402 rbase = *addr; 403 else if (hdr->e_type == ET_EXEC) 404 rbase = 0; 405 else { 406 error = ENOEXEC; 407 goto fail; 408 } 409 410 /* Only support headers that fit within first page for now */ 411 if ((hdr->e_phoff > PAGE_SIZE) || 412 (hdr->e_phoff + hdr->e_phentsize * hdr->e_phnum) > PAGE_SIZE) { 413 error = ENOEXEC; 414 goto fail; 415 } 416 417 phdr = (const Elf_Phdr *)(imgp->image_header + hdr->e_phoff); 418 419 for (i = 0, numsegs = 0; i < hdr->e_phnum; i++) { 420 if (phdr[i].p_type == PT_LOAD) { /* Loadable segment */ 421 prot = 0; 422 if (phdr[i].p_flags & PF_X) 423 prot |= VM_PROT_EXECUTE; 424 if (phdr[i].p_flags & PF_W) 425 prot |= VM_PROT_WRITE; 426 if (phdr[i].p_flags & PF_R) 427 prot |= VM_PROT_READ; 428 429 if ((error = elf_load_section(p, vmspace, nd->ni_vp, 430 imgp->object, 431 phdr[i].p_offset, 432 (caddr_t)phdr[i].p_vaddr + 433 rbase, 434 phdr[i].p_memsz, 435 phdr[i].p_filesz, prot)) != 0) 436 goto fail; 437 /* 438 * Establish the base address if this is the 439 * first segment. 440 */ 441 if (numsegs == 0) 442 base_addr = trunc_page(phdr[i].p_vaddr + rbase); 443 numsegs++; 444 } 445 } 446 *addr = base_addr; 447 *entry=(unsigned long)hdr->e_entry + rbase; 448 449 fail: 450 if (imgp->firstpage) 451 exec_unmap_first_page(imgp); 452 if (imgp->image_header) 453 kmem_free_wakeup(exec_map, (vm_offset_t)imgp->image_header, 454 PAGE_SIZE); 455 if (imgp->object) 456 vm_object_deallocate(imgp->object); 457 458 if (nd->ni_vp) 459 vrele(nd->ni_vp); 460 461 free(tempdata, M_TEMP); 462 463 return error; 464 } 465 466 /* 467 * non static, as it can be overridden by start_init() 468 */ 469 #ifdef __ia64__ 470 int fallback_elf_brand = ELFOSABI_FREEBSD; 471 #else 472 int fallback_elf_brand = -1; 473 #endif 474 SYSCTL_INT(_kern, OID_AUTO, fallback_elf_brand, CTLFLAG_RW, 475 &fallback_elf_brand, -1, 476 "ELF brand of last resort"); 477 478 static int 479 exec_elf_imgact(struct image_params *imgp) 480 { 481 const Elf_Ehdr *hdr = (const Elf_Ehdr *) imgp->image_header; 482 const Elf_Phdr *phdr; 483 Elf_Auxargs *elf_auxargs = NULL; 484 struct vmspace *vmspace; 485 vm_prot_t prot; 486 u_long text_size = 0, data_size = 0; 487 u_long text_addr = 0, data_addr = 0; 488 u_long addr, entry = 0, proghdr = 0; 489 int error, i; 490 const char *interp = NULL; 491 Elf_Brandinfo *brand_info; 492 char *path; 493 494 GIANT_REQUIRED; 495 496 /* 497 * Do we have a valid ELF header ? 498 */ 499 if (elf_check_header(hdr) != 0 || hdr->e_type != ET_EXEC) 500 return -1; 501 502 /* 503 * From here on down, we return an errno, not -1, as we've 504 * detected an ELF file. 505 */ 506 507 if ((hdr->e_phoff > PAGE_SIZE) || 508 (hdr->e_phoff + hdr->e_phentsize * hdr->e_phnum) > PAGE_SIZE) { 509 /* Only support headers in first page for now */ 510 return ENOEXEC; 511 } 512 phdr = (const Elf_Phdr*)(imgp->image_header + hdr->e_phoff); 513 514 /* 515 * From this point on, we may have resources that need to be freed. 516 */ 517 518 /* 519 * Yeah, I'm paranoid. There is every reason in the world to get 520 * VTEXT now since from here on out, there are places we can have 521 * a context switch. Better safe than sorry; I really don't want 522 * the file to change while it's being loaded. 523 */ 524 mtx_lock(&imgp->vp->v_interlock); 525 imgp->vp->v_flag |= VTEXT; 526 mtx_unlock(&imgp->vp->v_interlock); 527 528 if ((error = exec_extract_strings(imgp)) != 0) 529 goto fail; 530 531 exec_new_vmspace(imgp); 532 533 vmspace = imgp->proc->p_vmspace; 534 535 for (i = 0; i < hdr->e_phnum; i++) { 536 switch(phdr[i].p_type) { 537 538 case PT_LOAD: /* Loadable segment */ 539 prot = 0; 540 if (phdr[i].p_flags & PF_X) 541 prot |= VM_PROT_EXECUTE; 542 if (phdr[i].p_flags & PF_W) 543 prot |= VM_PROT_WRITE; 544 if (phdr[i].p_flags & PF_R) 545 prot |= VM_PROT_READ; 546 547 if ((error = elf_load_section(imgp->proc, 548 vmspace, imgp->vp, 549 imgp->object, 550 phdr[i].p_offset, 551 (caddr_t)phdr[i].p_vaddr, 552 phdr[i].p_memsz, 553 phdr[i].p_filesz, prot)) != 0) 554 goto fail; 555 556 /* 557 * Is this .text or .data ?? 558 * 559 * We only handle one each of those yet XXX 560 */ 561 if (hdr->e_entry >= phdr[i].p_vaddr && 562 hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) { 563 text_addr = trunc_page(phdr[i].p_vaddr); 564 text_size = round_page(phdr[i].p_memsz + 565 phdr[i].p_vaddr - 566 text_addr); 567 entry = (u_long)hdr->e_entry; 568 } else { 569 data_addr = trunc_page(phdr[i].p_vaddr); 570 data_size = round_page(phdr[i].p_memsz + 571 phdr[i].p_vaddr - 572 data_addr); 573 } 574 break; 575 case PT_INTERP: /* Path to interpreter */ 576 if (phdr[i].p_filesz > MAXPATHLEN || 577 phdr[i].p_offset + phdr[i].p_filesz > PAGE_SIZE) { 578 error = ENOEXEC; 579 goto fail; 580 } 581 interp = imgp->image_header + phdr[i].p_offset; 582 break; 583 case PT_PHDR: /* Program header table info */ 584 proghdr = phdr[i].p_vaddr; 585 break; 586 default: 587 break; 588 } 589 } 590 591 vmspace->vm_tsize = text_size >> PAGE_SHIFT; 592 vmspace->vm_taddr = (caddr_t)(uintptr_t)text_addr; 593 vmspace->vm_dsize = data_size >> PAGE_SHIFT; 594 vmspace->vm_daddr = (caddr_t)(uintptr_t)data_addr; 595 596 addr = ELF_RTLD_ADDR(vmspace); 597 598 imgp->entry_addr = entry; 599 600 brand_info = NULL; 601 602 /* We support three types of branding -- (1) the ELF EI_OSABI field 603 * that SCO added to the ELF spec, (2) FreeBSD 3.x's traditional string 604 * branding w/in the ELF header, and (3) path of the `interp_path' 605 * field. We should also look for an ".note.ABI-tag" ELF section now 606 * in all Linux ELF binaries, FreeBSD 4.1+, and some NetBSD ones. 607 */ 608 609 /* If the executable has a brand, search for it in the brand list. */ 610 if (brand_info == NULL) { 611 for (i = 0; i < MAX_BRANDS; i++) { 612 Elf_Brandinfo *bi = elf_brand_list[i]; 613 614 if (bi != NULL && 615 (hdr->e_ident[EI_OSABI] == bi->brand 616 || 0 == 617 strncmp((const char *)&hdr->e_ident[OLD_EI_BRAND], 618 bi->compat_3_brand, strlen(bi->compat_3_brand)))) { 619 brand_info = bi; 620 break; 621 } 622 } 623 } 624 625 /* Lacking a known brand, search for a recognized interpreter. */ 626 if (brand_info == NULL && interp != NULL) { 627 for (i = 0; i < MAX_BRANDS; i++) { 628 Elf_Brandinfo *bi = elf_brand_list[i]; 629 630 if (bi != NULL && 631 strcmp(interp, bi->interp_path) == 0) { 632 brand_info = bi; 633 break; 634 } 635 } 636 } 637 638 /* Lacking a recognized interpreter, try the default brand */ 639 if (brand_info == NULL) { 640 for (i = 0; i < MAX_BRANDS; i++) { 641 Elf_Brandinfo *bi = elf_brand_list[i]; 642 643 if (bi != NULL && fallback_elf_brand == bi->brand) { 644 brand_info = bi; 645 break; 646 } 647 } 648 } 649 650 if (brand_info == NULL) { 651 uprintf("ELF binary type \"%u\" not known.\n", 652 hdr->e_ident[EI_OSABI]); 653 error = ENOEXEC; 654 goto fail; 655 } 656 657 imgp->proc->p_sysent = brand_info->sysvec; 658 if (interp != NULL) { 659 path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 660 snprintf(path, MAXPATHLEN, "%s%s", 661 brand_info->emul_path, interp); 662 if ((error = elf_load_file(imgp->proc, path, &addr, 663 &imgp->entry_addr)) != 0) { 664 if ((error = elf_load_file(imgp->proc, interp, &addr, 665 &imgp->entry_addr)) != 0) { 666 uprintf("ELF interpreter %s not found\n", path); 667 free(path, M_TEMP); 668 goto fail; 669 } 670 } 671 free(path, M_TEMP); 672 } 673 674 /* 675 * Construct auxargs table (used by the fixup routine) 676 */ 677 elf_auxargs = malloc(sizeof(Elf_Auxargs), M_TEMP, M_WAITOK); 678 elf_auxargs->execfd = -1; 679 elf_auxargs->phdr = proghdr; 680 elf_auxargs->phent = hdr->e_phentsize; 681 elf_auxargs->phnum = hdr->e_phnum; 682 elf_auxargs->pagesz = PAGE_SIZE; 683 elf_auxargs->base = addr; 684 elf_auxargs->flags = 0; 685 elf_auxargs->entry = entry; 686 elf_auxargs->trace = elf_trace; 687 688 imgp->auxargs = elf_auxargs; 689 imgp->interpreted = 0; 690 691 fail: 692 return error; 693 } 694 695 static int 696 elf_freebsd_fixup(register_t **stack_base, struct image_params *imgp) 697 { 698 Elf_Auxargs *args = (Elf_Auxargs *)imgp->auxargs; 699 register_t *pos; 700 701 pos = *stack_base + (imgp->argc + imgp->envc + 2); 702 703 if (args->trace) { 704 AUXARGS_ENTRY(pos, AT_DEBUG, 1); 705 } 706 if (args->execfd != -1) { 707 AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); 708 } 709 AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); 710 AUXARGS_ENTRY(pos, AT_PHENT, args->phent); 711 AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum); 712 AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz); 713 AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); 714 AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); 715 AUXARGS_ENTRY(pos, AT_BASE, args->base); 716 AUXARGS_ENTRY(pos, AT_NULL, 0); 717 718 free(imgp->auxargs, M_TEMP); 719 imgp->auxargs = NULL; 720 721 (*stack_base)--; 722 suword(*stack_base, (long) imgp->argc); 723 return 0; 724 } 725 726 /* 727 * Code for generating ELF core dumps. 728 */ 729 730 typedef void (*segment_callback)(vm_map_entry_t, void *); 731 732 /* Closure for cb_put_phdr(). */ 733 struct phdr_closure { 734 Elf_Phdr *phdr; /* Program header to fill in */ 735 Elf_Off offset; /* Offset of segment in core file */ 736 }; 737 738 /* Closure for cb_size_segment(). */ 739 struct sseg_closure { 740 int count; /* Count of writable segments. */ 741 size_t size; /* Total size of all writable segments. */ 742 }; 743 744 static void cb_put_phdr(vm_map_entry_t, void *); 745 static void cb_size_segment(vm_map_entry_t, void *); 746 static void each_writable_segment(struct proc *, segment_callback, void *); 747 static int elf_corehdr(struct thread *, struct vnode *, struct ucred *, 748 int, void *, size_t); 749 static void elf_puthdr(struct proc *, void *, size_t *, 750 const prstatus_t *, const prfpregset_t *, const prpsinfo_t *, int); 751 static void elf_putnote(void *, size_t *, const char *, int, 752 const void *, size_t); 753 754 extern int osreldate; 755 756 int 757 elf_coredump(td, vp, limit) 758 struct thread *td; 759 register struct vnode *vp; 760 off_t limit; 761 { 762 register struct proc *p = td->td_proc; 763 register struct ucred *cred = td->td_ucred; 764 int error = 0; 765 struct sseg_closure seginfo; 766 void *hdr; 767 size_t hdrsize; 768 769 /* Size the program segments. */ 770 seginfo.count = 0; 771 seginfo.size = 0; 772 each_writable_segment(p, cb_size_segment, &seginfo); 773 774 /* 775 * Calculate the size of the core file header area by making 776 * a dry run of generating it. Nothing is written, but the 777 * size is calculated. 778 */ 779 hdrsize = 0; 780 elf_puthdr((struct proc *)NULL, (void *)NULL, &hdrsize, 781 (const prstatus_t *)NULL, (const prfpregset_t *)NULL, 782 (const prpsinfo_t *)NULL, seginfo.count); 783 784 if (hdrsize + seginfo.size >= limit) 785 return (EFAULT); 786 787 /* 788 * Allocate memory for building the header, fill it up, 789 * and write it out. 790 */ 791 hdr = malloc(hdrsize, M_TEMP, M_WAITOK); 792 if (hdr == NULL) { 793 return EINVAL; 794 } 795 error = elf_corehdr(td, vp, cred, seginfo.count, hdr, hdrsize); 796 797 /* Write the contents of all of the writable segments. */ 798 if (error == 0) { 799 Elf_Phdr *php; 800 off_t offset; 801 int i; 802 803 php = (Elf_Phdr *)((char *)hdr + sizeof(Elf_Ehdr)) + 1; 804 offset = hdrsize; 805 for (i = 0; i < seginfo.count; i++) { 806 error = vn_rdwr_inchunks(UIO_WRITE, vp, 807 (caddr_t)php->p_vaddr, 808 php->p_filesz, offset, UIO_USERSPACE, 809 IO_UNIT | IO_DIRECT, cred, (int *)NULL, curthread); /* XXXKSE */ 810 if (error != 0) 811 break; 812 offset += php->p_filesz; 813 php++; 814 } 815 } 816 free(hdr, M_TEMP); 817 818 return error; 819 } 820 821 /* 822 * A callback for each_writable_segment() to write out the segment's 823 * program header entry. 824 */ 825 static void 826 cb_put_phdr(entry, closure) 827 vm_map_entry_t entry; 828 void *closure; 829 { 830 struct phdr_closure *phc = (struct phdr_closure *)closure; 831 Elf_Phdr *phdr = phc->phdr; 832 833 phc->offset = round_page(phc->offset); 834 835 phdr->p_type = PT_LOAD; 836 phdr->p_offset = phc->offset; 837 phdr->p_vaddr = entry->start; 838 phdr->p_paddr = 0; 839 phdr->p_filesz = phdr->p_memsz = entry->end - entry->start; 840 phdr->p_align = PAGE_SIZE; 841 phdr->p_flags = 0; 842 if (entry->protection & VM_PROT_READ) 843 phdr->p_flags |= PF_R; 844 if (entry->protection & VM_PROT_WRITE) 845 phdr->p_flags |= PF_W; 846 if (entry->protection & VM_PROT_EXECUTE) 847 phdr->p_flags |= PF_X; 848 849 phc->offset += phdr->p_filesz; 850 phc->phdr++; 851 } 852 853 /* 854 * A callback for each_writable_segment() to gather information about 855 * the number of segments and their total size. 856 */ 857 static void 858 cb_size_segment(entry, closure) 859 vm_map_entry_t entry; 860 void *closure; 861 { 862 struct sseg_closure *ssc = (struct sseg_closure *)closure; 863 864 ssc->count++; 865 ssc->size += entry->end - entry->start; 866 } 867 868 /* 869 * For each writable segment in the process's memory map, call the given 870 * function with a pointer to the map entry and some arbitrary 871 * caller-supplied data. 872 */ 873 static void 874 each_writable_segment(p, func, closure) 875 struct proc *p; 876 segment_callback func; 877 void *closure; 878 { 879 vm_map_t map = &p->p_vmspace->vm_map; 880 vm_map_entry_t entry; 881 882 for (entry = map->header.next; entry != &map->header; 883 entry = entry->next) { 884 vm_object_t obj; 885 886 if ((entry->eflags & MAP_ENTRY_IS_SUB_MAP) || 887 (entry->protection & (VM_PROT_READ|VM_PROT_WRITE)) != 888 (VM_PROT_READ|VM_PROT_WRITE)) 889 continue; 890 891 /* 892 ** Dont include memory segment in the coredump if 893 ** MAP_NOCORE is set in mmap(2) or MADV_NOCORE in 894 ** madvise(2). 895 */ 896 if (entry->eflags & MAP_ENTRY_NOCOREDUMP) 897 continue; 898 899 if ((obj = entry->object.vm_object) == NULL) 900 continue; 901 902 /* Find the deepest backing object. */ 903 while (obj->backing_object != NULL) 904 obj = obj->backing_object; 905 906 /* Ignore memory-mapped devices and such things. */ 907 if (obj->type != OBJT_DEFAULT && 908 obj->type != OBJT_SWAP && 909 obj->type != OBJT_VNODE) 910 continue; 911 912 (*func)(entry, closure); 913 } 914 } 915 916 /* 917 * Write the core file header to the file, including padding up to 918 * the page boundary. 919 */ 920 static int 921 elf_corehdr(td, vp, cred, numsegs, hdr, hdrsize) 922 struct thread *td; 923 struct vnode *vp; 924 struct ucred *cred; 925 int numsegs; 926 size_t hdrsize; 927 void *hdr; 928 { 929 struct { 930 prstatus_t status; 931 prfpregset_t fpregset; 932 prpsinfo_t psinfo; 933 } *tempdata; 934 struct proc *p = td->td_proc; 935 size_t off; 936 prstatus_t *status; 937 prfpregset_t *fpregset; 938 prpsinfo_t *psinfo; 939 940 tempdata = malloc(sizeof(*tempdata), M_TEMP, M_ZERO | M_WAITOK); 941 status = &tempdata->status; 942 fpregset = &tempdata->fpregset; 943 psinfo = &tempdata->psinfo; 944 945 /* Gather the information for the header. */ 946 status->pr_version = PRSTATUS_VERSION; 947 status->pr_statussz = sizeof(prstatus_t); 948 status->pr_gregsetsz = sizeof(gregset_t); 949 status->pr_fpregsetsz = sizeof(fpregset_t); 950 status->pr_osreldate = osreldate; 951 status->pr_cursig = p->p_sig; 952 status->pr_pid = p->p_pid; 953 fill_regs(td, &status->pr_reg); 954 955 fill_fpregs(td, fpregset); 956 957 psinfo->pr_version = PRPSINFO_VERSION; 958 psinfo->pr_psinfosz = sizeof(prpsinfo_t); 959 strncpy(psinfo->pr_fname, p->p_comm, sizeof(psinfo->pr_fname) - 1); 960 961 /* XXX - We don't fill in the command line arguments properly yet. */ 962 strncpy(psinfo->pr_psargs, p->p_comm, PRARGSZ); 963 964 /* Fill in the header. */ 965 bzero(hdr, hdrsize); 966 off = 0; 967 elf_puthdr(p, hdr, &off, status, fpregset, psinfo, numsegs); 968 969 free(tempdata, M_TEMP); 970 971 /* Write it to the core file. */ 972 return vn_rdwr_inchunks(UIO_WRITE, vp, hdr, hdrsize, (off_t)0, 973 UIO_SYSSPACE, IO_UNIT | IO_DIRECT, cred, NULL, td); /* XXXKSE */ 974 } 975 976 static void 977 elf_puthdr(struct proc *p, void *dst, size_t *off, const prstatus_t *status, 978 const prfpregset_t *fpregset, const prpsinfo_t *psinfo, int numsegs) 979 { 980 size_t ehoff; 981 size_t phoff; 982 size_t noteoff; 983 size_t notesz; 984 985 ehoff = *off; 986 *off += sizeof(Elf_Ehdr); 987 988 phoff = *off; 989 *off += (numsegs + 1) * sizeof(Elf_Phdr); 990 991 noteoff = *off; 992 elf_putnote(dst, off, "FreeBSD", NT_PRSTATUS, status, 993 sizeof *status); 994 elf_putnote(dst, off, "FreeBSD", NT_FPREGSET, fpregset, 995 sizeof *fpregset); 996 elf_putnote(dst, off, "FreeBSD", NT_PRPSINFO, psinfo, 997 sizeof *psinfo); 998 notesz = *off - noteoff; 999 1000 /* Align up to a page boundary for the program segments. */ 1001 *off = round_page(*off); 1002 1003 if (dst != NULL) { 1004 Elf_Ehdr *ehdr; 1005 Elf_Phdr *phdr; 1006 struct phdr_closure phc; 1007 1008 /* 1009 * Fill in the ELF header. 1010 */ 1011 ehdr = (Elf_Ehdr *)((char *)dst + ehoff); 1012 ehdr->e_ident[EI_MAG0] = ELFMAG0; 1013 ehdr->e_ident[EI_MAG1] = ELFMAG1; 1014 ehdr->e_ident[EI_MAG2] = ELFMAG2; 1015 ehdr->e_ident[EI_MAG3] = ELFMAG3; 1016 ehdr->e_ident[EI_CLASS] = ELF_CLASS; 1017 ehdr->e_ident[EI_DATA] = ELF_DATA; 1018 ehdr->e_ident[EI_VERSION] = EV_CURRENT; 1019 ehdr->e_ident[EI_OSABI] = ELFOSABI_FREEBSD; 1020 ehdr->e_ident[EI_ABIVERSION] = 0; 1021 ehdr->e_ident[EI_PAD] = 0; 1022 ehdr->e_type = ET_CORE; 1023 ehdr->e_machine = ELF_ARCH; 1024 ehdr->e_version = EV_CURRENT; 1025 ehdr->e_entry = 0; 1026 ehdr->e_phoff = phoff; 1027 ehdr->e_flags = 0; 1028 ehdr->e_ehsize = sizeof(Elf_Ehdr); 1029 ehdr->e_phentsize = sizeof(Elf_Phdr); 1030 ehdr->e_phnum = numsegs + 1; 1031 ehdr->e_shentsize = sizeof(Elf_Shdr); 1032 ehdr->e_shnum = 0; 1033 ehdr->e_shstrndx = SHN_UNDEF; 1034 1035 /* 1036 * Fill in the program header entries. 1037 */ 1038 phdr = (Elf_Phdr *)((char *)dst + phoff); 1039 1040 /* The note segement. */ 1041 phdr->p_type = PT_NOTE; 1042 phdr->p_offset = noteoff; 1043 phdr->p_vaddr = 0; 1044 phdr->p_paddr = 0; 1045 phdr->p_filesz = notesz; 1046 phdr->p_memsz = 0; 1047 phdr->p_flags = 0; 1048 phdr->p_align = 0; 1049 phdr++; 1050 1051 /* All the writable segments from the program. */ 1052 phc.phdr = phdr; 1053 phc.offset = *off; 1054 each_writable_segment(p, cb_put_phdr, &phc); 1055 } 1056 } 1057 1058 static void 1059 elf_putnote(void *dst, size_t *off, const char *name, int type, 1060 const void *desc, size_t descsz) 1061 { 1062 Elf_Note note; 1063 1064 note.n_namesz = strlen(name) + 1; 1065 note.n_descsz = descsz; 1066 note.n_type = type; 1067 if (dst != NULL) 1068 bcopy(¬e, (char *)dst + *off, sizeof note); 1069 *off += sizeof note; 1070 if (dst != NULL) 1071 bcopy(name, (char *)dst + *off, note.n_namesz); 1072 *off += roundup2(note.n_namesz, sizeof(Elf_Size)); 1073 if (dst != NULL) 1074 bcopy(desc, (char *)dst + *off, note.n_descsz); 1075 *off += roundup2(note.n_descsz, sizeof(Elf_Size)); 1076 } 1077 1078 /* 1079 * Tell kern_execve.c about it, with a little help from the linker. 1080 */ 1081 static struct execsw elf_execsw = {exec_elf_imgact, "ELF"}; 1082 EXEC_SET(elf, elf_execsw); 1083