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.30 1998/09/14 05:36:49 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_prot.h> 63 #include <vm/vm_extern.h> 64 65 #include <machine/md_var.h> 66 67 #define MAX_PHDR 32 /* XXX enough ? */ 68 69 #if ELF_TARG_CLASS == ELFCLASS32 70 71 #define Elf_Ehdr Elf32_Ehdr 72 #define Elf_Phdr Elf32_Phdr 73 #define Elf_Auxargs Elf32_Auxargs 74 #define Elf_Brandinfo Elf32_Brandinfo 75 76 #else 77 78 #define Elf_Ehdr Elf64_Ehdr 79 #define Elf_Phdr Elf64_Phdr 80 #define Elf_Auxargs Elf64_Auxargs 81 #define Elf_Brandinfo Elf64_Brandinfo 82 83 #endif 84 85 86 static int elf_check_header __P((const Elf_Ehdr *hdr, int type)); 87 static int elf_freebsd_fixup __P((long **stack_base, 88 struct image_params *imgp)); 89 static int elf_load_file __P((struct proc *p, char *file, u_long *addr, 90 u_long *entry)); 91 static int elf_load_section __P((struct vmspace *vmspace, struct vnode *vp, 92 vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, 93 vm_prot_t prot)); 94 static int exec_elf_imgact __P((struct image_params *imgp)); 95 96 static int elf_trace = 0; 97 SYSCTL_INT(_debug, OID_AUTO, elf_trace, CTLFLAG_RW, &elf_trace, 0, ""); 98 #define UPRINTF if (elf_trace) uprintf 99 100 static struct sysentvec elf_freebsd_sysvec = { 101 SYS_MAXSYSCALL, 102 sysent, 103 0, 104 0, 105 0, 106 0, 107 0, 108 0, 109 elf_freebsd_fixup, 110 sendsig, 111 sigcode, 112 &szsigcode, 113 0, 114 "FreeBSD ELF", 115 elf_coredump 116 }; 117 118 static Elf_Brandinfo freebsd_brand_info = { 119 "FreeBSD", 120 "", 121 "/usr/libexec/ld-elf.so.1", 122 &elf_freebsd_sysvec 123 }; 124 static Elf_Brandinfo *elf_brand_list[MAX_BRANDS] = { 125 &freebsd_brand_info, 126 NULL, NULL, NULL, 127 NULL, NULL, NULL, NULL 128 }; 129 130 int 131 elf_insert_brand_entry(Elf_Brandinfo *entry) 132 { 133 int i; 134 135 for (i=1; i<MAX_BRANDS; i++) { 136 if (elf_brand_list[i] == NULL) { 137 elf_brand_list[i] = entry; 138 break; 139 } 140 } 141 if (i == MAX_BRANDS) 142 return -1; 143 return 0; 144 } 145 146 int 147 elf_remove_brand_entry(Elf_Brandinfo *entry) 148 { 149 int i; 150 151 for (i=1; i<MAX_BRANDS; i++) { 152 if (elf_brand_list[i] == entry) { 153 elf_brand_list[i] = NULL; 154 break; 155 } 156 } 157 if (i == MAX_BRANDS) 158 return -1; 159 return 0; 160 } 161 162 static int 163 elf_check_header(const Elf_Ehdr *hdr, int type) 164 { 165 if (!(hdr->e_ident[EI_MAG0] == ELFMAG0 && 166 hdr->e_ident[EI_MAG1] == ELFMAG1 && 167 hdr->e_ident[EI_MAG2] == ELFMAG2 && 168 hdr->e_ident[EI_MAG3] == ELFMAG3)) 169 return ENOEXEC; 170 171 #ifdef __i386__ 172 if (hdr->e_machine != EM_386 && hdr->e_machine != EM_486) 173 #endif 174 #ifdef __alpha__ 175 if (hdr->e_machine != EM_ALPHA) 176 #endif 177 return ENOEXEC; 178 179 180 if (hdr->e_type != type) 181 return ENOEXEC; 182 183 return 0; 184 } 185 186 static int 187 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) 188 { 189 size_t map_len; 190 vm_offset_t map_addr; 191 int error; 192 unsigned char *data_buf = 0; 193 size_t copy_len; 194 195 map_addr = trunc_page(vmaddr); 196 197 if (memsz > filsz) 198 map_len = trunc_page(offset+filsz) - trunc_page(offset); 199 else 200 map_len = round_page(offset+filsz) - trunc_page(offset); 201 202 if (error = vm_mmap (&vmspace->vm_map, 203 &map_addr, 204 map_len, 205 prot, 206 VM_PROT_ALL, 207 MAP_PRIVATE | MAP_FIXED, 208 (caddr_t)vp, 209 trunc_page(offset))) 210 return error; 211 212 if (memsz == filsz) 213 return 0; 214 215 /* 216 * We have to map the remaining bit of the file into the kernel's 217 * memory map, allocate some anonymous memory, and copy that last 218 * bit into it. The remaining space should be .bss... 219 */ 220 copy_len = (offset + filsz) - trunc_page(offset + filsz); 221 map_addr = trunc_page(vmaddr + filsz); 222 map_len = round_page(vmaddr + memsz) - map_addr; 223 224 if (map_len != 0) { 225 if (error = vm_map_find(&vmspace->vm_map, NULL, 0, 226 &map_addr, map_len, FALSE, 227 VM_PROT_ALL, VM_PROT_ALL,0)) 228 return error; 229 } 230 231 if (error = vm_mmap(exec_map, 232 (vm_offset_t *)&data_buf, 233 PAGE_SIZE, 234 VM_PROT_READ, 235 VM_PROT_READ, 236 0, 237 (caddr_t)vp, 238 trunc_page(offset + filsz))) 239 return error; 240 241 error = copyout(data_buf, (caddr_t)map_addr, copy_len); 242 243 vm_map_remove(exec_map, (vm_offset_t)data_buf, 244 (vm_offset_t)data_buf + PAGE_SIZE); 245 246 /* 247 * set it to the specified protection 248 */ 249 vm_map_protect(&vmspace->vm_map, map_addr, map_addr + map_len, prot, 250 FALSE); 251 252 UPRINTF("bss size %d (%x)\n", map_len-copy_len, map_len-copy_len); 253 return error; 254 } 255 256 static int 257 elf_load_file(struct proc *p, char *file, u_long *addr, u_long *entry) 258 { 259 Elf_Ehdr *hdr = NULL; 260 Elf_Phdr *phdr = NULL; 261 struct nameidata nd; 262 struct vmspace *vmspace = p->p_vmspace; 263 struct vattr attr; 264 struct image_params image_params, *imgp; 265 vm_prot_t prot = 0; 266 unsigned long text_size = 0, data_size = 0; 267 unsigned long text_addr = 0, data_addr = 0; 268 int header_size = 0; 269 int error, i; 270 271 imgp = &image_params; 272 /* 273 * Initialize part of the common data 274 */ 275 imgp->proc = p; 276 imgp->uap = NULL; 277 imgp->attr = &attr; 278 imgp->firstpage = NULL; 279 imgp->image_header = (char *)kmem_alloc_wait(exec_map, PAGE_SIZE); 280 281 if (imgp->image_header == NULL) { 282 nd.ni_vp = NULL; 283 error = ENOMEM; 284 goto fail; 285 } 286 287 NDINIT(&nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_SYSSPACE, file, p); 288 289 if (error = namei(&nd)) { 290 nd.ni_vp = NULL; 291 goto fail; 292 } 293 294 imgp->vp = nd.ni_vp; 295 296 /* 297 * Check permissions, modes, uid, etc on the file, and "open" it. 298 */ 299 error = exec_check_permissions(imgp); 300 if (error) { 301 VOP_UNLOCK(nd.ni_vp, 0, p); 302 goto fail; 303 } 304 305 error = exec_map_first_page(imgp); 306 VOP_UNLOCK(nd.ni_vp, 0, p); 307 if (error) 308 goto fail; 309 310 hdr = (Elf_Ehdr *)imgp->image_header; 311 if (error = elf_check_header(hdr, ET_DYN)) 312 goto fail; 313 314 /* 315 * ouch, need to bounds check in case user gives us a corrupted 316 * file with an insane header size 317 */ 318 if (hdr->e_phnum > MAX_PHDR) { /* XXX: ever more than this? */ 319 error = ENOEXEC; 320 goto fail; 321 } 322 323 header_size = hdr->e_phentsize * hdr->e_phnum; 324 325 /* Only support headers that fit within first page for now */ 326 if (header_size + hdr->e_phoff > PAGE_SIZE) { 327 error = ENOEXEC; 328 goto fail; 329 } 330 331 phdr = (Elf_Phdr *)(imgp->image_header + hdr->e_phoff); 332 333 for (i = 0; i < hdr->e_phnum; i++) { 334 switch(phdr[i].p_type) { 335 336 case PT_NULL: /* NULL section */ 337 UPRINTF ("ELF(file) PT_NULL section\n"); 338 break; 339 case PT_LOAD: /* Loadable segment */ 340 { 341 UPRINTF ("ELF(file) PT_LOAD section "); 342 if (phdr[i].p_flags & PF_X) 343 prot |= VM_PROT_EXECUTE; 344 if (phdr[i].p_flags & PF_W) 345 prot |= VM_PROT_WRITE; 346 if (phdr[i].p_flags & PF_R) 347 prot |= VM_PROT_READ; 348 349 if (error = elf_load_section(vmspace, nd.ni_vp, 350 phdr[i].p_offset, 351 (caddr_t)phdr[i].p_vaddr + 352 (*addr), 353 phdr[i].p_memsz, 354 phdr[i].p_filesz, prot)) 355 goto fail; 356 357 /* 358 * Is this .text or .data ?? 359 * 360 * We only handle one each of those yet XXX 361 */ 362 if (hdr->e_entry >= phdr[i].p_vaddr && 363 hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) { 364 text_addr = trunc_page(phdr[i].p_vaddr+(*addr)); 365 text_size = round_page(phdr[i].p_memsz + 366 phdr[i].p_vaddr - 367 trunc_page(phdr[i].p_vaddr)); 368 *entry=(unsigned long)hdr->e_entry+(*addr); 369 UPRINTF(".text <%08lx,%08lx> entry=%08lx\n", 370 text_addr, text_size, *entry); 371 } else { 372 data_addr = trunc_page(phdr[i].p_vaddr+(*addr)); 373 data_size = round_page(phdr[i].p_memsz + 374 phdr[i].p_vaddr - 375 trunc_page(phdr[i].p_vaddr)); 376 UPRINTF(".data <%08lx,%08lx>\n", 377 data_addr, data_size); 378 } 379 } 380 break; 381 382 case PT_DYNAMIC:/* Dynamic link information */ 383 UPRINTF ("ELF(file) PT_DYNAMIC section\n"); 384 break; 385 case PT_INTERP: /* Path to interpreter */ 386 UPRINTF ("ELF(file) PT_INTERP section\n"); 387 break; 388 case PT_NOTE: /* Note section */ 389 UPRINTF ("ELF(file) PT_NOTE section\n"); 390 break; 391 case PT_SHLIB: /* Shared lib section */ 392 UPRINTF ("ELF(file) PT_SHLIB section\n"); 393 break; 394 case PT_PHDR: /* Program header table info */ 395 UPRINTF ("ELF(file) PT_PHDR section\n"); 396 break; 397 default: 398 UPRINTF ("ELF(file) %d section ??\n", phdr[i].p_type ); 399 } 400 } 401 402 fail: 403 if (imgp->firstpage) 404 exec_unmap_first_page(imgp); 405 if (imgp->image_header) 406 kmem_free_wakeup(exec_map, (vm_offset_t)imgp->image_header, 407 PAGE_SIZE); 408 if (nd.ni_vp) 409 vrele(nd.ni_vp); 410 411 return error; 412 } 413 414 static int 415 exec_elf_imgact(struct image_params *imgp) 416 { 417 const Elf_Ehdr *hdr = (const Elf_Ehdr *) imgp->image_header; 418 const Elf_Phdr *phdr, *mapped_phdr = NULL; 419 Elf_Auxargs *elf_auxargs = NULL; 420 struct vmspace *vmspace; 421 vm_prot_t prot = 0; 422 u_long text_size = 0, data_size = 0; 423 u_long text_addr = 0, data_addr = 0; 424 u_long addr, entry = 0, proghdr = 0; 425 int error, i, header_size = 0; 426 const char *interp = NULL; 427 char *brand = NULL; 428 char path[MAXPATHLEN]; 429 430 /* 431 * Do we have a valid ELF header ? 432 */ 433 if (elf_check_header(hdr, ET_EXEC)) 434 return -1; 435 436 /* 437 * From here on down, we return an errno, not -1, as we've 438 * detected an ELF file. 439 */ 440 441 /* 442 * ouch, need to bounds check in case user gives us a corrupted 443 * file with an insane header size 444 */ 445 if (hdr->e_phnum > MAX_PHDR) { /* XXX: ever more than this? */ 446 return ENOEXEC; 447 } 448 449 header_size = hdr->e_phentsize * hdr->e_phnum; 450 451 if ((hdr->e_phoff > PAGE_SIZE) || 452 (hdr->e_phoff + header_size) > PAGE_SIZE) { 453 /* Only support headers in first page for now */ 454 return ENOEXEC; 455 } else { 456 phdr = (const Elf_Phdr*) 457 ((const char *)imgp->image_header + hdr->e_phoff); 458 } 459 460 /* 461 * From this point on, we may have resources that need to be freed. 462 */ 463 if (error = exec_extract_strings(imgp)) 464 goto fail; 465 466 exec_new_vmspace(imgp); 467 468 vmspace = imgp->proc->p_vmspace; 469 470 for (i = 0; i < hdr->e_phnum; i++) { 471 switch(phdr[i].p_type) { 472 473 case PT_NULL: /* NULL section */ 474 UPRINTF ("ELF PT_NULL section\n"); 475 break; 476 case PT_LOAD: /* Loadable segment */ 477 { 478 UPRINTF ("ELF PT_LOAD section "); 479 if (phdr[i].p_flags & PF_X) 480 prot |= VM_PROT_EXECUTE; 481 if (phdr[i].p_flags & PF_W) 482 prot |= VM_PROT_WRITE; 483 if (phdr[i].p_flags & PF_R) 484 prot |= VM_PROT_READ; 485 486 if (error = elf_load_section(vmspace, imgp->vp, 487 phdr[i].p_offset, 488 (caddr_t)phdr[i].p_vaddr, 489 phdr[i].p_memsz, 490 phdr[i].p_filesz, prot)) 491 goto fail; 492 493 /* 494 * Is this .text or .data ?? 495 * 496 * We only handle one each of those yet XXX 497 */ 498 if (hdr->e_entry >= phdr[i].p_vaddr && 499 hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) { 500 text_addr = trunc_page(phdr[i].p_vaddr); 501 text_size = round_page(phdr[i].p_memsz + 502 phdr[i].p_vaddr - 503 text_addr); 504 entry = (u_long)hdr->e_entry; 505 UPRINTF(".text <%08lx,%08lx> entry=%08lx\n", 506 text_addr, text_size, entry); 507 } else { 508 data_addr = trunc_page(phdr[i].p_vaddr); 509 data_size = round_page(phdr[i].p_memsz + 510 phdr[i].p_vaddr - 511 data_addr); 512 UPRINTF(".data <%08lx,%08lx>\n", 513 data_addr, data_size); 514 } 515 } 516 break; 517 518 case PT_DYNAMIC:/* Dynamic link information */ 519 UPRINTF ("ELF PT_DYNAMIC section ??\n"); 520 break; 521 case PT_INTERP: /* Path to interpreter */ 522 UPRINTF ("ELF PT_INTERP section "); 523 if (phdr[i].p_filesz > MAXPATHLEN || 524 phdr[i].p_offset + phdr[i].p_filesz > PAGE_SIZE) { 525 error = ENOEXEC; 526 goto fail; 527 } 528 interp = imgp->image_header + phdr[i].p_offset; 529 UPRINTF("<%s>\n", interp); 530 break; 531 case PT_NOTE: /* Note section */ 532 UPRINTF ("ELF PT_NOTE section\n"); 533 break; 534 case PT_SHLIB: /* Shared lib section */ 535 UPRINTF ("ELF PT_SHLIB section\n"); 536 break; 537 case PT_PHDR: /* Program header table info */ 538 UPRINTF ("ELF PT_PHDR section <%x>\n", phdr[i].p_vaddr); 539 proghdr = phdr[i].p_vaddr; 540 break; 541 default: 542 UPRINTF ("ELF %d section ??\n", phdr[i].p_type); 543 } 544 } 545 546 vmspace->vm_tsize = text_size >> PAGE_SHIFT; 547 vmspace->vm_taddr = (caddr_t)(uintptr_t)text_addr; 548 vmspace->vm_dsize = data_size >> PAGE_SHIFT; 549 vmspace->vm_daddr = (caddr_t)(uintptr_t)data_addr; 550 551 addr = 2L*MAXDSIZ; /* May depend on OS type XXX */ 552 553 imgp->entry_addr = entry; 554 555 /* 556 * So which kind (brand) of ELF binary do we have at hand 557 * FreeBSD, Linux, SVR4 or something else ?? 558 * If its has a interpreter section try that first 559 */ 560 if (interp) { 561 for (i=0; i<MAX_BRANDS; i++) { 562 if (elf_brand_list[i] != NULL) { 563 if (!strcmp(interp, elf_brand_list[i]->interp_path)) { 564 imgp->proc->p_sysent = 565 elf_brand_list[i]->sysvec; 566 strcpy(path, elf_brand_list[i]->emul_path); 567 strcat(path, elf_brand_list[i]->interp_path); 568 UPRINTF("interpreter=<%s> %s\n", 569 elf_brand_list[i]->interp_path, 570 elf_brand_list[i]->emul_path); 571 break; 572 } 573 } 574 } 575 } 576 577 /* 578 * If there is no interpreter, or recognition of it 579 * failed, se if the binary is branded. 580 */ 581 if (!interp || i == MAX_BRANDS) { 582 brand = (char *)&(hdr->e_ident[EI_BRAND]); 583 for (i=0; i<MAX_BRANDS; i++) { 584 if (elf_brand_list[i] != NULL) { 585 if (!strcmp(brand, elf_brand_list[i]->brand)) { 586 imgp->proc->p_sysent = elf_brand_list[i]->sysvec; 587 if (interp) { 588 strcpy(path, elf_brand_list[i]->emul_path); 589 strcat(path, elf_brand_list[i]->interp_path); 590 UPRINTF("interpreter=<%s> %s\n", 591 elf_brand_list[i]->interp_path, 592 elf_brand_list[i]->emul_path); 593 } 594 break; 595 } 596 } 597 } 598 } 599 if (i == MAX_BRANDS) { 600 #ifndef __alpha__ 601 uprintf("ELF binary type not known\n"); 602 error = ENOEXEC; 603 goto fail; 604 #else 605 i = 0; /* assume freebsd */ 606 imgp->proc->p_sysent = elf_brand_list[i]->sysvec; 607 if (interp) { 608 strcpy(path, elf_brand_list[i]->emul_path); 609 strcat(path, elf_brand_list[i]->interp_path); 610 UPRINTF("interpreter=<%s> %s\n", 611 elf_brand_list[i]->interp_path, 612 elf_brand_list[i]->emul_path); 613 } 614 #endif 615 } 616 if (interp) { 617 if (error = elf_load_file(imgp->proc, 618 path, 619 &addr, /* XXX */ 620 &imgp->entry_addr)) { 621 uprintf("ELF interpreter %s not found\n", path); 622 goto fail; 623 } 624 } 625 626 UPRINTF("Executing %s binary\n", elf_brand_list[i]->brand); 627 628 /* 629 * Construct auxargs table (used by the fixup routine) 630 */ 631 elf_auxargs = malloc(sizeof(Elf_Auxargs), M_TEMP, M_WAITOK); 632 elf_auxargs->execfd = -1; 633 elf_auxargs->phdr = proghdr; 634 elf_auxargs->phent = hdr->e_phentsize; 635 elf_auxargs->phnum = hdr->e_phnum; 636 elf_auxargs->pagesz = PAGE_SIZE; 637 elf_auxargs->base = addr; 638 elf_auxargs->flags = 0; 639 elf_auxargs->entry = entry; 640 elf_auxargs->trace = elf_trace; 641 642 imgp->auxargs = elf_auxargs; 643 imgp->interpreted = 0; 644 645 /* don't allow modifying the file while we run it */ 646 imgp->vp->v_flag |= VTEXT; 647 648 fail: 649 return error; 650 } 651 652 static int 653 elf_freebsd_fixup(long **stack_base, struct image_params *imgp) 654 { 655 Elf_Auxargs *args = (Elf_Auxargs *)imgp->auxargs; 656 long *pos; 657 658 pos = *stack_base + (imgp->argc + imgp->envc + 2); 659 660 if (args->trace) { 661 AUXARGS_ENTRY(pos, AT_DEBUG, 1); 662 } 663 if (args->execfd != -1) { 664 AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); 665 } 666 AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); 667 AUXARGS_ENTRY(pos, AT_PHENT, args->phent); 668 AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum); 669 AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz); 670 AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); 671 AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); 672 AUXARGS_ENTRY(pos, AT_BASE, args->base); 673 AUXARGS_ENTRY(pos, AT_NULL, 0); 674 675 free(imgp->auxargs, M_TEMP); 676 imgp->auxargs = NULL; 677 678 (*stack_base)--; 679 **stack_base = (long)imgp->argc; 680 return 0; 681 } 682 683 /* 684 * Code for generating ELF core dumps. 685 */ 686 687 static int elf_corehdr __P((struct proc *, struct vnode *, struct ucred *)); 688 static size_t elf_hdrsize(void); 689 static void elf_puthdr(void *, size_t *, const prstatus_t *, 690 const prfpregset_t *, const prpsinfo_t *, const void *, size_t, 691 const void *, size_t); 692 static void elf_putnote(void *, size_t *, const char *, int, const void *, 693 size_t); 694 695 extern int osreldate; 696 697 int 698 elf_coredump(p) 699 register struct proc *p; 700 { 701 register struct vnode *vp; 702 register struct ucred *cred = p->p_cred->pc_ucred; 703 register struct vmspace *vm = p->p_vmspace; 704 struct nameidata nd; 705 struct vattr vattr; 706 int error, error1; 707 char *name; /* name of corefile */ 708 size_t hdrsize; 709 710 STOPEVENT(p, S_CORE, 0); 711 712 if (sugid_coredump == 0 && p->p_flag & P_SUGID) 713 return (EFAULT); 714 hdrsize = elf_hdrsize(); 715 if (hdrsize + ctob(vm->vm_dsize + vm->vm_ssize) >= 716 p->p_rlimit[RLIMIT_CORE].rlim_cur) 717 return (EFAULT); 718 name = expand_name(p->p_comm, p->p_ucred->cr_uid, p->p_pid); 719 if (name == NULL) 720 return (EFAULT); /* XXX -- not the best error */ 721 722 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, name, p); 723 error = vn_open(&nd, O_CREAT | FWRITE, S_IRUSR | S_IWUSR); 724 free(name, M_TEMP); 725 if (error) 726 return (error); 727 vp = nd.ni_vp; 728 729 /* Don't dump to non-regular files or files with links. */ 730 if (vp->v_type != VREG || 731 VOP_GETATTR(vp, &vattr, cred, p) || vattr.va_nlink != 1) { 732 error = EFAULT; 733 goto out; 734 } 735 VATTR_NULL(&vattr); 736 vattr.va_size = 0; 737 VOP_LEASE(vp, p, cred, LEASE_WRITE); 738 VOP_SETATTR(vp, &vattr, cred, p); 739 p->p_acflag |= ACORE; 740 error = elf_corehdr(p, vp, cred); 741 if (error == 0) 742 error = vn_rdwr(UIO_WRITE, vp, vm->vm_daddr, 743 (int)ctob(vm->vm_dsize), (off_t)hdrsize, UIO_USERSPACE, 744 IO_NODELOCKED|IO_UNIT, cred, (int *) NULL, p); 745 if (error == 0) 746 error = vn_rdwr(UIO_WRITE, vp, 747 (caddr_t) trunc_page(USRSTACK - ctob(vm->vm_ssize)), 748 round_page(ctob(vm->vm_ssize)), 749 (off_t)hdrsize + ctob(vm->vm_dsize), UIO_USERSPACE, 750 IO_NODELOCKED|IO_UNIT, cred, (int *) NULL, p); 751 out: 752 VOP_UNLOCK(vp, 0, p); 753 error1 = vn_close(vp, FWRITE, cred, p); 754 if (error == 0) 755 error = error1; 756 return (error); 757 } 758 759 static int 760 elf_corehdr(p, vp, cred) 761 struct proc *p; 762 struct vnode *vp; 763 struct ucred *cred; 764 { 765 struct vmspace *vm = p->p_vmspace; 766 size_t off; 767 size_t hdrsize; 768 prstatus_t status; 769 prfpregset_t fpregset; 770 prpsinfo_t psinfo; 771 void *hdr; 772 int error; 773 774 /* Gather the information for the header. */ 775 bzero(&status, sizeof status); 776 status.pr_version = PRSTATUS_VERSION; 777 status.pr_statussz = sizeof(prstatus_t); 778 status.pr_gregsetsz = sizeof(gregset_t); 779 status.pr_fpregsetsz = sizeof(fpregset_t); 780 status.pr_osreldate = osreldate; 781 status.pr_cursig = p->p_sigacts->ps_sig; 782 status.pr_pid = p->p_pid; 783 fill_regs(p, &status.pr_reg); 784 785 fill_fpregs(p, &fpregset); 786 787 bzero(&psinfo, sizeof psinfo); 788 psinfo.pr_version = PRPSINFO_VERSION; 789 psinfo.pr_psinfosz = sizeof(prpsinfo_t); 790 strncpy(psinfo.pr_fname, p->p_comm, MAXCOMLEN); 791 psinfo.pr_psargs[0] = '\0'; /* XXX - args not implemented yet */ 792 793 /* Allocate memory for building the header. */ 794 hdrsize = elf_hdrsize(); 795 hdr = malloc(hdrsize, M_TEMP, M_WAITOK); 796 if (hdr == NULL) 797 return EINVAL; 798 bzero(hdr, hdrsize); 799 800 /* Fill in the header. */ 801 off = 0; 802 elf_puthdr(hdr, &off, &status, &fpregset, &psinfo, 803 vm->vm_daddr, ctob(vm->vm_dsize), 804 (void *)trunc_page(USRSTACK - ctob(vm->vm_ssize)), 805 ctob(vm->vm_ssize)); 806 807 /* Write it to the core file. */ 808 error = vn_rdwr(UIO_WRITE, vp, hdr, hdrsize, (off_t)0, 809 UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, NULL, p); 810 811 free(hdr, M_TEMP); 812 return error; 813 } 814 815 static size_t 816 elf_hdrsize(void) 817 { 818 size_t off; 819 820 off = 0; 821 elf_puthdr(NULL, &off, NULL, NULL, NULL, NULL, 0, NULL, 0); 822 return off; 823 } 824 825 static void 826 elf_puthdr(void *dst, size_t *off, const prstatus_t *status, 827 const prfpregset_t *fpregset, const prpsinfo_t *psinfo, 828 const void *data, size_t datasz, const void *stack, size_t stacksz) 829 { 830 size_t ehoff; 831 size_t phoff; 832 size_t noteoff; 833 size_t notesz; 834 size_t dataoff; 835 size_t stackoff; 836 int numsegs = 3; 837 838 ehoff = *off; 839 *off += sizeof(Elf_Ehdr); 840 841 phoff = *off; 842 *off += numsegs * sizeof(Elf_Phdr); 843 844 noteoff = *off; 845 elf_putnote(dst, off, "FreeBSD", NT_PRSTATUS, status, 846 sizeof *status); 847 elf_putnote(dst, off, "FreeBSD", NT_FPREGSET, fpregset, 848 sizeof *fpregset); 849 elf_putnote(dst, off, "FreeBSD", NT_PRPSINFO, psinfo, 850 sizeof *psinfo); 851 notesz = *off - noteoff; 852 853 /* Align up to a page boundary for the data segment. */ 854 *off = round_page(*off); 855 856 if (dst != NULL) { 857 Elf_Ehdr *ehdr; 858 Elf_Phdr *phdr; 859 860 /* 861 * Fill in the ELF header. 862 */ 863 ehdr = (Elf_Ehdr *)((char *)dst + ehoff); 864 ehdr->e_ident[EI_MAG0] = ELFMAG0; 865 ehdr->e_ident[EI_MAG1] = ELFMAG1; 866 ehdr->e_ident[EI_MAG2] = ELFMAG2; 867 ehdr->e_ident[EI_MAG3] = ELFMAG3; 868 ehdr->e_ident[EI_CLASS] = ELF_CLASS; 869 ehdr->e_ident[EI_DATA] = ELF_DATA; 870 ehdr->e_ident[EI_VERSION] = EV_CURRENT; 871 ehdr->e_ident[EI_PAD] = 0; 872 strncpy(ehdr->e_ident + EI_BRAND, "FreeBSD", 873 EI_NIDENT - EI_BRAND); 874 ehdr->e_type = ET_CORE; 875 ehdr->e_machine = ELF_ARCH; 876 ehdr->e_version = EV_CURRENT; 877 ehdr->e_entry = 0; 878 ehdr->e_phoff = phoff; 879 ehdr->e_flags = 0; 880 ehdr->e_ehsize = sizeof(Elf_Ehdr); 881 ehdr->e_phentsize = sizeof(Elf_Phdr); 882 ehdr->e_phnum = numsegs; 883 ehdr->e_shentsize = sizeof(Elf_Shdr); 884 ehdr->e_shnum = 0; 885 ehdr->e_shstrndx = SHN_UNDEF; 886 887 /* 888 * Fill in the program header entries. 889 */ 890 phdr = (Elf_Phdr *)((char *)dst + phoff); 891 892 /* The note segement. */ 893 phdr->p_type = PT_NOTE; 894 phdr->p_offset = noteoff; 895 phdr->p_vaddr = 0; 896 phdr->p_paddr = 0; 897 phdr->p_filesz = notesz; 898 phdr->p_memsz = 0; 899 phdr->p_flags = 0; 900 phdr->p_align = 0; 901 phdr++; 902 903 /* The data segment. */ 904 phdr->p_type = PT_LOAD; 905 phdr->p_offset = *off; 906 phdr->p_vaddr = (Elf_Addr)data; 907 phdr->p_paddr = 0; 908 phdr->p_filesz = phdr->p_memsz = datasz; 909 phdr->p_align = PAGE_SIZE; 910 phdr->p_flags = PF_R | PF_W | PF_X; 911 phdr++; 912 913 /* The stack segment. */ 914 phdr->p_type = PT_LOAD; 915 phdr->p_offset = *off + datasz; 916 phdr->p_vaddr = (Elf_Addr)stack; 917 phdr->p_paddr = 0; 918 phdr->p_filesz = phdr->p_memsz = stacksz; 919 phdr->p_align = PAGE_SIZE; 920 phdr->p_flags = PF_R | PF_W | PF_X; 921 phdr++; 922 } 923 } 924 925 static void 926 elf_putnote(void *dst, size_t *off, const char *name, int type, 927 const void *desc, size_t descsz) 928 { 929 Elf_Note note; 930 931 note.n_namesz = strlen(name) + 1; 932 note.n_descsz = descsz; 933 note.n_type = type; 934 if (dst != NULL) 935 bcopy(¬e, (char *)dst + *off, sizeof note); 936 *off += sizeof note; 937 if (dst != NULL) 938 bcopy(name, (char *)dst + *off, note.n_namesz); 939 *off += roundup2(note.n_namesz, sizeof(Elf_Size)); 940 if (dst != NULL) 941 bcopy(desc, (char *)dst + *off, note.n_descsz); 942 *off += roundup2(note.n_descsz, sizeof(Elf_Size)); 943 } 944 945 /* 946 * Tell kern_execve.c about it, with a little help from the linker. 947 * Since `const' objects end up in the text segment, TEXT_SET is the 948 * correct directive to use. 949 */ 950 static const struct execsw elf_execsw = {exec_elf_imgact, "ELF"}; 951 TEXT_SET(execsw_set, elf_execsw); 952 953