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