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.8 1996/08/31 16:52:23 bde Exp $ 30 */ 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/resourcevar.h> 35 #include <sys/exec.h> 36 #include <sys/mman.h> 37 #include <sys/imgact.h> 38 #include <sys/imgact_elf.h> 39 #include <sys/kernel.h> 40 #include <sys/sysent.h> 41 #include <sys/file.h> 42 #include <sys/malloc.h> 43 #include <sys/mount.h> 44 #include <sys/namei.h> 45 #include <sys/proc.h> 46 #include <sys/sysproto.h> 47 #include <sys/syscall.h> 48 #include <sys/signalvar.h> 49 #include <sys/sysctl.h> 50 #include <sys/vnode.h> 51 52 #include <vm/vm.h> 53 #include <vm/vm_kern.h> 54 #include <vm/vm_param.h> 55 #include <vm/pmap.h> 56 #include <vm/lock.h> 57 #include <vm/vm_map.h> 58 #include <vm/vm_prot.h> 59 #include <vm/vm_extern.h> 60 61 #include <machine/md_var.h> 62 #include <i386/linux/linux_syscall.h> 63 #include <i386/linux/linux.h> 64 65 #define MAX_PHDR 32 /* XXX enough ? */ 66 67 static int map_pages __P((struct vnode *vp, vm_offset_t offset, vm_offset_t *buf, vm_size_t size)); 68 static void unmap_pages __P((vm_offset_t buf, vm_size_t size)); 69 static int elf_check_permissions __P((struct proc *p, struct vnode *vp)); 70 static int elf_check_header __P((const Elf32_Ehdr *hdr, int type)); 71 static int elf_load_section __P((struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot)); 72 static int elf_load_file __P((struct proc *p, char *file, u_long *addr, u_long *entry)); 73 static int elf_freebsd_fixup __P((int **stack_base, struct image_params *imgp)); 74 int exec_elf_imgact __P((struct image_params *imgp)); 75 76 int elf_trace = 0; 77 SYSCTL_INT(_debug, 1, elf_trace, CTLFLAG_RW, &elf_trace, 0, ""); 78 #define UPRINTF if (elf_trace) uprintf 79 80 static struct sysentvec elf_freebsd_sysvec = { 81 SYS_MAXSYSCALL, 82 sysent, 83 0, 84 0, 85 0, 86 0, 87 0, 88 elf_freebsd_fixup, 89 sendsig, 90 sigcode, 91 &szsigcode, 92 0, 93 "FreeBSD ELF" 94 }; 95 96 static Elf32_Interp_info freebsd_interp = { 97 &elf_freebsd_sysvec, 98 "/usr/libexec/ld-elf.so.1", 99 "" 100 }; 101 static Elf32_Interp_info *interp_list[MAX_INTERP] = { 102 &freebsd_interp, 103 NULL, NULL, NULL, 104 NULL, NULL, NULL, NULL 105 }; 106 107 int 108 elf_insert_interp(Elf32_Interp_info *entry) 109 { 110 int i; 111 112 for (i=1; i<MAX_INTERP; i++) { 113 if (interp_list[i] == NULL) { 114 interp_list[i] = entry; 115 break; 116 } 117 } 118 if (i == MAX_INTERP) 119 return -1; 120 return 0; 121 } 122 123 int 124 elf_remove_interp(Elf32_Interp_info *entry) 125 { 126 int i; 127 128 for (i=1; i<MAX_INTERP; i++) { 129 if (interp_list[i] == entry) { 130 interp_list[i] = NULL; 131 break; 132 } 133 } 134 if (i == MAX_INTERP) 135 return -1; 136 return 0; 137 } 138 139 static int 140 map_pages(struct vnode *vp, vm_offset_t offset, 141 vm_offset_t *buf, vm_size_t size) 142 { 143 int error; 144 vm_offset_t kern_buf; 145 vm_size_t pageoff; 146 147 /* 148 * The request may not be aligned, and may even cross several 149 * page boundaries in the file... 150 */ 151 pageoff = (offset & PAGE_MASK); 152 offset -= pageoff; /* start of first aligned page to map */ 153 size += pageoff; 154 size = round_page(size); /* size of aligned pages to map */ 155 156 if (error = vm_mmap(kernel_map, 157 &kern_buf, 158 size, 159 VM_PROT_READ, 160 VM_PROT_READ, 161 0, 162 (caddr_t)vp, 163 offset)) 164 return error; 165 166 *buf = kern_buf + pageoff; 167 168 return 0; 169 } 170 171 static void 172 unmap_pages(vm_offset_t buf, vm_size_t size) 173 { 174 vm_size_t pageoff; 175 176 pageoff = (buf & PAGE_MASK); 177 buf -= pageoff; /* start of first aligned page to map */ 178 size += pageoff; 179 size = round_page(size);/* size of aligned pages to map */ 180 181 vm_map_remove(kernel_map, buf, buf + size); 182 } 183 184 static int 185 elf_check_permissions(struct proc *p, struct vnode *vp) 186 { 187 struct vattr attr; 188 int error; 189 190 /* 191 * Check number of open-for-writes on the file and deny execution 192 * if there are any. 193 */ 194 if (vp->v_writecount) { 195 return (ETXTBSY); 196 } 197 198 /* Get file attributes */ 199 error = VOP_GETATTR(vp, &attr, p->p_ucred, p); 200 if (error) 201 return (error); 202 203 /* 204 * 1) Check if file execution is disabled for the filesystem that this 205 * file resides on. 206 * 2) Insure that at least one execute bit is on - otherwise root 207 * will always succeed, and we don't want to happen unless the 208 * file really is executable. 209 * 3) Insure that the file is a regular file. 210 */ 211 if ((vp->v_mount->mnt_flag & MNT_NOEXEC) || 212 ((attr.va_mode & 0111) == 0) || 213 (attr.va_type != VREG)) { 214 return (EACCES); 215 } 216 217 /* 218 * Zero length files can't be exec'd 219 */ 220 if (attr.va_size == 0) 221 return (ENOEXEC); 222 223 /* 224 * Check for execute permission to file based on current credentials. 225 * Then call filesystem specific open routine (which does nothing 226 * in the general case). 227 */ 228 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 229 if (error) 230 return (error); 231 232 error = VOP_OPEN(vp, FREAD, p->p_ucred, p); 233 if (error) 234 return (error); 235 236 return (0); 237 } 238 239 static int 240 elf_check_header(const Elf32_Ehdr *hdr, int type) 241 { 242 if (!(hdr->e_ident[EI_MAG0] == ELFMAG0 && 243 hdr->e_ident[EI_MAG1] == ELFMAG1 && 244 hdr->e_ident[EI_MAG2] == ELFMAG2 && 245 hdr->e_ident[EI_MAG3] == ELFMAG3)) 246 return ENOEXEC; 247 248 if (hdr->e_machine != EM_386 && hdr->e_machine != EM_486) 249 return ENOEXEC; 250 251 if (hdr->e_type != type) 252 return ENOEXEC; 253 254 return 0; 255 } 256 257 static int 258 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) 259 { 260 size_t map_len; 261 vm_offset_t map_addr; 262 int error; 263 unsigned char *data_buf = 0; 264 size_t copy_len; 265 266 map_addr = trunc_page(vmaddr); 267 268 if (memsz > filsz) 269 map_len = trunc_page(offset+filsz) - trunc_page(offset); 270 else 271 map_len = round_page(offset+filsz) - trunc_page(offset); 272 273 if (error = vm_mmap (&vmspace->vm_map, 274 &map_addr, 275 map_len, 276 prot, 277 VM_PROT_ALL, 278 MAP_PRIVATE | MAP_FIXED, 279 (caddr_t)vp, 280 trunc_page(offset))) 281 return error; 282 283 if (memsz == filsz) 284 return 0; 285 286 /* 287 * We have to map the remaining bit of the file into the kernel's 288 * memory map, allocate some anonymous memory, and copy that last 289 * bit into it. The remaining space should be .bss... 290 */ 291 copy_len = (offset + filsz) - trunc_page(offset + filsz); 292 map_addr = trunc_page(vmaddr + filsz); 293 map_len = round_page(vmaddr + memsz) - map_addr; 294 295 if (map_len != 0) { 296 if (error = vm_map_find(&vmspace->vm_map, NULL, 0, 297 &map_addr, map_len, FALSE, 298 VM_PROT_ALL, VM_PROT_ALL,0)) 299 return error; 300 } 301 302 if (error = vm_mmap(kernel_map, 303 (vm_offset_t *)&data_buf, 304 PAGE_SIZE, 305 VM_PROT_READ, 306 VM_PROT_READ, 307 0, 308 (caddr_t)vp, 309 trunc_page(offset + filsz))) 310 return error; 311 312 error = copyout(data_buf, (caddr_t)map_addr, copy_len); 313 314 vm_map_remove(kernel_map, (vm_offset_t)data_buf, 315 (vm_offset_t)data_buf + PAGE_SIZE); 316 317 /* 318 * set it to the specified protection 319 */ 320 vm_map_protect(&vmspace->vm_map, map_addr, map_addr + map_len, prot, 321 FALSE); 322 323 UPRINTF("bss size %d (%x)\n", map_len-copy_len, map_len-copy_len); 324 return error; 325 } 326 327 static int 328 elf_load_file(struct proc *p, char *file, u_long *addr, u_long *entry) 329 { 330 Elf32_Ehdr *hdr = NULL; 331 Elf32_Phdr *phdr = NULL; 332 struct nameidata nd; 333 struct vmspace *vmspace = p->p_vmspace; 334 vm_prot_t prot = 0; 335 unsigned long text_size = 0, data_size = 0; 336 unsigned long text_addr = 0, data_addr = 0; 337 int header_size = 0; 338 int error, i; 339 340 NDINIT(&nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_SYSSPACE, file, p); 341 342 if (error = namei(&nd)) 343 goto fail; 344 345 if (nd.ni_vp == NULL) { 346 error = ENOEXEC; 347 goto fail; 348 } 349 350 /* 351 * Check permissions, modes, uid, etc on the file, and "open" it. 352 */ 353 error = elf_check_permissions(p, nd.ni_vp); 354 355 /* 356 * No longer need this, and it prevents demand paging. 357 */ 358 VOP_UNLOCK(nd.ni_vp); 359 360 if (error) 361 goto fail; 362 363 /* 364 * Map in the header 365 */ 366 if (error = map_pages(nd.ni_vp, 0, (vm_offset_t *)&hdr, sizeof(hdr))) 367 goto fail; 368 369 /* 370 * Do we have a valid ELF header ? 371 */ 372 if (error = elf_check_header(hdr, ET_DYN)) 373 goto fail; 374 375 /* 376 * ouch, need to bounds check in case user gives us a corrupted 377 * file with an insane header size 378 */ 379 if (hdr->e_phnum > MAX_PHDR) { /* XXX: ever more than this? */ 380 error = ENOEXEC; 381 goto fail; 382 } 383 384 header_size = hdr->e_phentsize * hdr->e_phnum; 385 386 if (error = map_pages(nd.ni_vp, hdr->e_phoff, (vm_offset_t *)&phdr, 387 header_size)) 388 goto fail; 389 390 for (i = 0; i < hdr->e_phnum; i++) { 391 switch(phdr[i].p_type) { 392 393 case PT_NULL: /* NULL section */ 394 UPRINTF ("ELF(file) PT_NULL section\n"); 395 break; 396 case PT_LOAD: /* Loadable segment */ 397 { 398 UPRINTF ("ELF(file) PT_LOAD section "); 399 if (phdr[i].p_flags & PF_X) 400 prot |= VM_PROT_EXECUTE; 401 if (phdr[i].p_flags & PF_W) 402 prot |= VM_PROT_WRITE; 403 if (phdr[i].p_flags & PF_R) 404 prot |= VM_PROT_READ; 405 406 if (error = elf_load_section(vmspace, nd.ni_vp, 407 phdr[i].p_offset, 408 (caddr_t)phdr[i].p_vaddr + 409 (*addr), 410 phdr[i].p_memsz, 411 phdr[i].p_filesz, prot)) 412 goto fail; 413 414 /* 415 * Is this .text or .data ?? 416 * 417 * We only handle one each of those yet XXX 418 */ 419 if (hdr->e_entry >= phdr[i].p_vaddr && 420 hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) { 421 text_addr = trunc_page(phdr[i].p_vaddr+(*addr)); 422 text_size = round_page(phdr[i].p_memsz + 423 phdr[i].p_vaddr - 424 trunc_page(phdr[i].p_vaddr)); 425 *entry=(unsigned long)hdr->e_entry+(*addr); 426 UPRINTF(".text <%08x,%08x> entry=%08x\n", 427 text_addr, text_size, *entry); 428 } else { 429 data_addr = trunc_page(phdr[i].p_vaddr+(*addr)); 430 data_size = round_page(phdr[i].p_memsz + 431 phdr[i].p_vaddr - 432 trunc_page(phdr[i].p_vaddr)); 433 UPRINTF(".data <%08x,%08x>\n", 434 data_addr, data_size); 435 } 436 } 437 break; 438 439 case PT_DYNAMIC:/* Dynamic link information */ 440 UPRINTF ("ELF(file) PT_DYNAMIC section\n"); 441 break; 442 case PT_INTERP: /* Path to interpreter */ 443 UPRINTF ("ELF(file) PT_INTERP section\n"); 444 break; 445 case PT_NOTE: /* Note section */ 446 UPRINTF ("ELF(file) PT_NOTE section\n"); 447 break; 448 case PT_SHLIB: /* Shared lib section */ 449 UPRINTF ("ELF(file) PT_SHLIB section\n"); 450 break; 451 case PT_PHDR: /* Program header table info */ 452 UPRINTF ("ELF(file) PT_PHDR section\n"); 453 break; 454 default: 455 UPRINTF ("ELF(file) %d section ??\n", phdr[i].p_type ); 456 } 457 } 458 459 fail: 460 if (phdr) 461 unmap_pages((vm_offset_t)phdr, header_size); 462 if (hdr) 463 unmap_pages((vm_offset_t)hdr, sizeof(hdr)); 464 465 return error; 466 } 467 468 int 469 exec_elf_imgact(struct image_params *imgp) 470 { 471 const Elf32_Ehdr *hdr = (const Elf32_Ehdr *) imgp->image_header; 472 const Elf32_Phdr *phdr, *mapped_phdr = NULL; 473 Elf32_Auxargs *elf_auxargs = NULL; 474 struct vmspace *vmspace = imgp->proc->p_vmspace; 475 vm_prot_t prot = 0; 476 u_long text_size = 0, data_size = 0; 477 u_long text_addr = 0, data_addr = 0; 478 u_long addr, entry = 0, proghdr = 0; 479 int error, i, header_size = 0, interp_len = 0; 480 char *interp = NULL; 481 482 /* 483 * Do we have a valid ELF header ? 484 */ 485 if (elf_check_header(hdr, ET_EXEC)) 486 return -1; 487 488 /* 489 * From here on down, we return an errno, not -1, as we've 490 * detected an ELF file. 491 */ 492 493 /* 494 * ouch, need to bounds check in case user gives us a corrupted 495 * file with an insane header size 496 */ 497 if (hdr->e_phnum > MAX_PHDR) { /* XXX: ever more than this? */ 498 return ENOEXEC; 499 } 500 501 header_size = hdr->e_phentsize * hdr->e_phnum; 502 503 if ((hdr->e_phoff > PAGE_SIZE) || 504 (hdr->e_phoff + header_size) > PAGE_SIZE) { 505 /* 506 * Ouch ! we only get one page full of header... 507 * Try to map it in ourselves, and see how we go. 508 */ 509 if (error = map_pages(imgp->vp, hdr->e_phoff, 510 (vm_offset_t *)&mapped_phdr, header_size)) 511 return (error); 512 /* 513 * Save manual mapping for cleanup 514 */ 515 phdr = mapped_phdr; 516 } else { 517 phdr = (const Elf32_Phdr*) 518 ((const char *)imgp->image_header + hdr->e_phoff); 519 } 520 521 /* 522 * From this point on, we may have resources that need to be freed. 523 */ 524 if (error = exec_extract_strings(imgp)) 525 goto fail; 526 527 exec_new_vmspace(imgp); 528 529 for (i = 0; i < hdr->e_phnum; i++) { 530 switch(phdr[i].p_type) { 531 532 case PT_NULL: /* NULL section */ 533 UPRINTF ("ELF PT_NULL section\n"); 534 break; 535 case PT_LOAD: /* Loadable segment */ 536 { 537 UPRINTF ("ELF PT_LOAD section "); 538 if (phdr[i].p_flags & PF_X) 539 prot |= VM_PROT_EXECUTE; 540 if (phdr[i].p_flags & PF_W) 541 prot |= VM_PROT_WRITE; 542 if (phdr[i].p_flags & PF_R) 543 prot |= VM_PROT_READ; 544 545 if (error = elf_load_section(vmspace, imgp->vp, 546 phdr[i].p_offset, 547 (caddr_t)phdr[i].p_vaddr, 548 phdr[i].p_memsz, 549 phdr[i].p_filesz, prot)) 550 goto fail; 551 552 /* 553 * Is this .text or .data ?? 554 * 555 * We only handle one each of those yet XXX 556 */ 557 if (hdr->e_entry >= phdr[i].p_vaddr && 558 hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) { 559 text_addr = trunc_page(phdr[i].p_vaddr); 560 text_size = round_page(phdr[i].p_memsz + 561 phdr[i].p_vaddr - 562 text_addr); 563 entry = (u_long)hdr->e_entry; 564 UPRINTF(".text <%08x,%08x> entry=%08x\n", 565 text_addr, text_size, entry); 566 } else { 567 data_addr = trunc_page(phdr[i].p_vaddr); 568 data_size = round_page(phdr[i].p_memsz + 569 phdr[i].p_vaddr - 570 data_addr); 571 UPRINTF(".data <%08x,%08x>\n", 572 data_addr, data_size); 573 } 574 } 575 break; 576 577 case PT_DYNAMIC:/* Dynamic link information */ 578 UPRINTF ("ELF PT_DYNAMIC section ??\n"); 579 break; 580 case PT_INTERP: /* Path to interpreter */ 581 UPRINTF ("ELF PT_INTERP section "); 582 if (phdr[i].p_filesz > MAXPATHLEN) { 583 error = ENOEXEC; 584 goto fail; 585 } 586 interp_len = MAXPATHLEN; 587 if (error = map_pages(imgp->vp, phdr[i].p_offset, 588 (vm_offset_t *)&interp, interp_len)) 589 goto fail; 590 UPRINTF("<%s>\n", interp); 591 break; 592 case PT_NOTE: /* Note section */ 593 UPRINTF ("ELF PT_NOTE section\n"); 594 break; 595 case PT_SHLIB: /* Shared lib section */ 596 UPRINTF ("ELF PT_SHLIB section\n"); 597 break; 598 case PT_PHDR: /* Program header table info */ 599 UPRINTF ("ELF PT_PHDR section <%x>\n", phdr[i].p_vaddr); 600 proghdr = phdr[i].p_vaddr; 601 break; 602 default: 603 UPRINTF ("ELF %d section ??\n", phdr[i].p_type); 604 } 605 } 606 607 vmspace->vm_tsize = text_size >> PAGE_SHIFT; 608 vmspace->vm_taddr = (caddr_t)text_addr; 609 vmspace->vm_dsize = data_size >> PAGE_SHIFT; 610 vmspace->vm_daddr = (caddr_t)data_addr; 611 612 addr = 2*MAXDSIZ; /* May depend on OS type XXX */ 613 614 if (interp) { 615 char path[MAXPATHLEN]; 616 /* 617 * So which kind of ELF binary do we have at hand 618 * FreeBSD, SVR4 or Linux ?? 619 */ 620 for (i=0; i<MAX_INTERP; i++) { 621 if (interp_list[i] != NULL) { 622 if (!strcmp(interp, interp_list[i]->path)) { 623 imgp->proc->p_sysent = 624 interp_list[i]->sysvec; 625 strcpy(path, interp_list[i]->emul_path); 626 strcat(path, interp_list[i]->path); 627 UPRINTF("interpreter=<%s> %s\n", 628 interp_list[i]->path, 629 interp_list[i]->emul_path); 630 break; 631 } 632 } 633 } 634 if (i == MAX_INTERP) { 635 uprintf("ELF interpreter %s not known\n", interp); 636 error = ENOEXEC; 637 goto fail; 638 } 639 if (error = elf_load_file(imgp->proc, 640 path, 641 &addr, /* XXX */ 642 &imgp->entry_addr)) { 643 uprintf("ELF interpreter %s not found\n", path); 644 goto fail; 645 } 646 } 647 else 648 imgp->entry_addr = entry; 649 650 /* 651 * Construct auxargs table (used by the fixup routine) 652 */ 653 elf_auxargs = malloc(sizeof(Elf32_Auxargs), M_TEMP, M_WAITOK); 654 elf_auxargs->execfd = -1; 655 elf_auxargs->phdr = proghdr; 656 elf_auxargs->phent = hdr->e_phentsize; 657 elf_auxargs->phnum = hdr->e_phnum; 658 elf_auxargs->pagesz = PAGE_SIZE; 659 elf_auxargs->base = addr; 660 elf_auxargs->flags = 0; 661 elf_auxargs->entry = entry; 662 elf_auxargs->trace = elf_trace; 663 664 imgp->auxargs = elf_auxargs; 665 imgp->interpreted = 0; 666 667 /* don't allow modifying the file while we run it */ 668 imgp->vp->v_flag |= VTEXT; 669 670 fail: 671 if (mapped_phdr) 672 unmap_pages((vm_offset_t)mapped_phdr, header_size); 673 if (interp) 674 unmap_pages((vm_offset_t)interp, interp_len); 675 676 return error; 677 } 678 679 static int 680 elf_freebsd_fixup(int **stack_base, struct image_params *imgp) 681 { 682 Elf32_Auxargs *args = (Elf32_Auxargs *)imgp->auxargs; 683 int *pos; 684 685 pos = *stack_base + (imgp->argc + imgp->envc + 2); 686 687 if (args->trace) { 688 AUXARGS_ENTRY(pos, AT_DEBUG, 1); 689 } 690 if (args->execfd != -1) { 691 AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); 692 } 693 AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); 694 AUXARGS_ENTRY(pos, AT_PHENT, args->phent); 695 AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum); 696 AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz); 697 AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); 698 AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); 699 AUXARGS_ENTRY(pos, AT_BASE, args->base); 700 AUXARGS_ENTRY(pos, AT_NULL, 0); 701 702 free(imgp->auxargs, M_TEMP); 703 imgp->auxargs = NULL; 704 705 (*stack_base)--; 706 **stack_base = (int)imgp->argc; 707 return 0; 708 } 709 710 /* 711 * Tell kern_execve.c about it, with a little help from the linker. 712 * Since `const' objects end up in the text segment, TEXT_SET is the 713 * correct directive to use. 714 */ 715 const struct execsw elf_execsw = {exec_elf_imgact, "ELF"}; 716 TEXT_SET(execsw_set, elf_execsw); 717 718