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