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