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