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