xref: /freebsd/sys/kern/imgact_elf.c (revision 303b270b0a55fd0dc287afb82267317ca7826a7b)
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  *
29303b270bSEivind Eklund  *	$Id: imgact_elf.c,v 1.20 1997/09/21 03:13:21 peter Exp $
30e1743d02SSøren Schmidt  */
31e1743d02SSøren Schmidt 
32e9822d92SJoerg Wunsch #include "opt_rlimit.h"
33e9822d92SJoerg Wunsch 
34e1743d02SSøren Schmidt #include <sys/param.h>
35e1743d02SSøren Schmidt #include <sys/systm.h>
36e1743d02SSøren Schmidt #include <sys/exec.h>
37e1743d02SSøren Schmidt #include <sys/mman.h>
38e1743d02SSøren Schmidt #include <sys/imgact.h>
39e1743d02SSøren Schmidt #include <sys/imgact_elf.h>
40e1743d02SSøren Schmidt #include <sys/kernel.h>
41e1743d02SSøren Schmidt #include <sys/sysent.h>
423ac4d1efSBruce Evans #include <sys/fcntl.h>
43e1743d02SSøren Schmidt #include <sys/malloc.h>
44e1743d02SSøren Schmidt #include <sys/mount.h>
45a794e791SBruce Evans #include <sys/namei.h>
46a794e791SBruce Evans #include <sys/proc.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>
56996c772fSJohn Dyson #include <sys/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 
63e1743d02SSøren Schmidt #define MAX_PHDR	32	/* XXX enough ? */
64e1743d02SSøren Schmidt 
65e1743d02SSøren Schmidt static int map_pages __P((struct vnode *vp, vm_offset_t offset, vm_offset_t *buf, vm_size_t size));
661a7eb2dcSPeter Wemm static void unmap_pages __P((vm_offset_t buf, vm_size_t size));
67250c11f9SPeter Wemm static int elf_check_permissions __P((struct proc *p, struct vnode *vp));
68e0c95ed9SBruce Evans static int elf_check_header __P((const Elf32_Ehdr *hdr, int type));
69e1743d02SSø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));
70e1743d02SSøren Schmidt static int elf_load_file __P((struct proc *p, char *file, u_long *addr, u_long *entry));
71e1743d02SSøren Schmidt static int elf_freebsd_fixup __P((int **stack_base, struct image_params *imgp));
72303b270bSEivind Eklund static int exec_elf_imgact __P((struct image_params *imgp));
73e1743d02SSøren Schmidt 
74d8a4f230SBruce Evans static int elf_trace = 0;
75d8a4f230SBruce Evans SYSCTL_INT(_debug, OID_AUTO, elf_trace, CTLFLAG_RW, &elf_trace, 0, "");
76e1743d02SSøren Schmidt #define UPRINTF if (elf_trace) uprintf
77e1743d02SSøren Schmidt 
78e1743d02SSøren Schmidt static struct sysentvec elf_freebsd_sysvec = {
79e1743d02SSøren Schmidt         SYS_MAXSYSCALL,
80e1743d02SSøren Schmidt         sysent,
81e1743d02SSøren Schmidt         0,
82e1743d02SSøren Schmidt         0,
83e1743d02SSøren Schmidt         0,
84e1743d02SSøren Schmidt         0,
85e1743d02SSøren Schmidt         0,
86e1743d02SSøren Schmidt         elf_freebsd_fixup,
87e1743d02SSøren Schmidt         sendsig,
88e1743d02SSøren Schmidt         sigcode,
89e1743d02SSøren Schmidt         &szsigcode,
90e1743d02SSøren Schmidt         0,
916ead3eddSJohn Dyson 	"FreeBSD ELF"
92e1743d02SSøren Schmidt };
93e1743d02SSøren Schmidt 
94ea5a2b2eSSøren Schmidt static Elf32_Brandinfo freebsd_brand_info = {
95ea5a2b2eSSøren Schmidt 						"FreeBSD",
96ea5a2b2eSSøren Schmidt 						"",
97e1743d02SSøren Schmidt 						"/usr/libexec/ld-elf.so.1",
98ea5a2b2eSSøren Schmidt 						&elf_freebsd_sysvec
99e1743d02SSøren Schmidt 					  };
100ea5a2b2eSSøren Schmidt static Elf32_Brandinfo *elf_brand_list[MAX_BRANDS] = {
101ea5a2b2eSSøren Schmidt 							&freebsd_brand_info,
102e1743d02SSøren Schmidt 							NULL, NULL, NULL,
103e1743d02SSøren Schmidt 							NULL, NULL, NULL, NULL
104e1743d02SSøren Schmidt 						    };
105e1743d02SSøren Schmidt 
106e1743d02SSøren Schmidt int
107ea5a2b2eSSøren Schmidt elf_insert_brand_entry(Elf32_Brandinfo *entry)
108e1743d02SSøren Schmidt {
109e1743d02SSøren Schmidt 	int i;
110e1743d02SSøren Schmidt 
111ea5a2b2eSSøren Schmidt 	for (i=1; i<MAX_BRANDS; i++) {
112ea5a2b2eSSøren Schmidt 		if (elf_brand_list[i] == NULL) {
113ea5a2b2eSSøren Schmidt 			elf_brand_list[i] = entry;
114e1743d02SSøren Schmidt 			break;
115e1743d02SSøren Schmidt 		}
116e1743d02SSøren Schmidt 	}
117ea5a2b2eSSøren Schmidt 	if (i == MAX_BRANDS)
118e1743d02SSøren Schmidt 		return -1;
119e1743d02SSøren Schmidt 	return 0;
120e1743d02SSøren Schmidt }
121e1743d02SSøren Schmidt 
122e1743d02SSøren Schmidt int
123ea5a2b2eSSøren Schmidt elf_remove_brand_entry(Elf32_Brandinfo *entry)
124e1743d02SSøren Schmidt {
125e1743d02SSøren Schmidt 	int i;
126e1743d02SSøren Schmidt 
127ea5a2b2eSSøren Schmidt 	for (i=1; i<MAX_BRANDS; i++) {
128ea5a2b2eSSøren Schmidt 		if (elf_brand_list[i] == entry) {
129ea5a2b2eSSøren Schmidt 			elf_brand_list[i] = NULL;
130e1743d02SSøren Schmidt 			break;
131e1743d02SSøren Schmidt 		}
132e1743d02SSøren Schmidt 	}
133ea5a2b2eSSøren Schmidt 	if (i == MAX_BRANDS)
134e1743d02SSøren Schmidt 		return -1;
135e1743d02SSøren Schmidt 	return 0;
136e1743d02SSøren Schmidt }
137e1743d02SSøren Schmidt 
138e1743d02SSøren Schmidt static int
139e1743d02SSøren Schmidt map_pages(struct vnode *vp, vm_offset_t offset,
140e1743d02SSøren Schmidt 	     vm_offset_t *buf, vm_size_t size)
141e1743d02SSøren Schmidt {
142c23670e2SGary Palmer 	int error;
143e1743d02SSøren Schmidt 	vm_offset_t kern_buf;
144e1743d02SSøren Schmidt 	vm_size_t pageoff;
145e1743d02SSøren Schmidt 
146e1743d02SSøren Schmidt 	/*
147e1743d02SSøren Schmidt 	 * The request may not be aligned, and may even cross several
148e1743d02SSøren Schmidt 	 * page boundaries in the file...
149e1743d02SSøren Schmidt 	 */
150e1743d02SSøren Schmidt 	pageoff = (offset & PAGE_MASK);
151e1743d02SSøren Schmidt 	offset -= pageoff;		/* start of first aligned page to map */
152e1743d02SSøren Schmidt 	size += pageoff;
153e1743d02SSøren Schmidt 	size = round_page(size);	/* size of aligned pages to map */
154e1743d02SSøren Schmidt 
155e1743d02SSøren Schmidt 	if (error = vm_mmap(kernel_map,
156e1743d02SSøren Schmidt 			    &kern_buf,
157e1743d02SSøren Schmidt 			    size,
158e1743d02SSøren Schmidt 			    VM_PROT_READ,
159e1743d02SSøren Schmidt 			    VM_PROT_READ,
16071d7d1b1SPeter Wemm 			    0,
161e1743d02SSøren Schmidt 			    (caddr_t)vp,
162e1743d02SSøren Schmidt 			    offset))
163e1743d02SSøren Schmidt 		return error;
164e1743d02SSøren Schmidt 
165e1743d02SSøren Schmidt 	*buf = kern_buf + pageoff;
166e1743d02SSøren Schmidt 
167e1743d02SSøren Schmidt 	return 0;
168e1743d02SSøren Schmidt }
169e1743d02SSøren Schmidt 
170e1743d02SSøren Schmidt static void
1711a7eb2dcSPeter Wemm unmap_pages(vm_offset_t buf, vm_size_t size)
172e1743d02SSøren Schmidt {
173e1743d02SSøren Schmidt 	vm_size_t pageoff;
174e1743d02SSøren Schmidt 
175e1743d02SSøren Schmidt 	pageoff = (buf & PAGE_MASK);
176e1743d02SSøren Schmidt 	buf -= pageoff;		/* start of first aligned page to map */
177e1743d02SSøren Schmidt 	size += pageoff;
178e1743d02SSøren Schmidt 	size = round_page(size);/* size of aligned pages to map */
179e1743d02SSøren Schmidt 
1808191d577SPeter Wemm       	vm_map_remove(kernel_map, buf, buf + size);
181e1743d02SSøren Schmidt }
182e1743d02SSøren Schmidt 
183e1743d02SSøren Schmidt static int
184e1743d02SSøren Schmidt elf_check_permissions(struct proc *p, struct vnode *vp)
185e1743d02SSøren Schmidt {
186e1743d02SSøren Schmidt 	struct vattr attr;
187e1743d02SSøren Schmidt 	int error;
188e1743d02SSøren Schmidt 
189e1743d02SSøren Schmidt 	/*
190e1743d02SSøren Schmidt 	 * Check number of open-for-writes on the file and deny execution
191e1743d02SSøren Schmidt 	 *	if there are any.
192e1743d02SSøren Schmidt 	 */
193e1743d02SSøren Schmidt 	if (vp->v_writecount) {
194e1743d02SSøren Schmidt 		return (ETXTBSY);
195e1743d02SSøren Schmidt 	}
196e1743d02SSøren Schmidt 
197e1743d02SSøren Schmidt 	/* Get file attributes */
198e1743d02SSøren Schmidt 	error = VOP_GETATTR(vp, &attr, p->p_ucred, p);
199e1743d02SSøren Schmidt 	if (error)
200e1743d02SSøren Schmidt 		return (error);
201e1743d02SSøren Schmidt 
202e1743d02SSøren Schmidt 	/*
203e1743d02SSøren Schmidt 	 * 1) Check if file execution is disabled for the filesystem that this
204e1743d02SSøren Schmidt 	 *	file resides on.
205e1743d02SSøren Schmidt 	 * 2) Insure that at least one execute bit is on - otherwise root
206e1743d02SSøren Schmidt 	 *	will always succeed, and we don't want to happen unless the
207e1743d02SSøren Schmidt 	 *	file really is executable.
208e1743d02SSøren Schmidt 	 * 3) Insure that the file is a regular file.
209e1743d02SSøren Schmidt 	 */
210e1743d02SSøren Schmidt 	if ((vp->v_mount->mnt_flag & MNT_NOEXEC) ||
211e1743d02SSøren Schmidt 	    ((attr.va_mode & 0111) == 0) ||
212e1743d02SSøren Schmidt 	    (attr.va_type != VREG)) {
213e1743d02SSøren Schmidt 		return (EACCES);
214e1743d02SSøren Schmidt 	}
215e1743d02SSøren Schmidt 
216e1743d02SSøren Schmidt 	/*
217e1743d02SSøren Schmidt 	 * Zero length files can't be exec'd
218e1743d02SSøren Schmidt 	 */
219e1743d02SSøren Schmidt 	if (attr.va_size == 0)
220e1743d02SSøren Schmidt 		return (ENOEXEC);
221e1743d02SSøren Schmidt 
222e1743d02SSøren Schmidt 	/*
223e1743d02SSøren Schmidt 	 *  Check for execute permission to file based on current credentials.
224e1743d02SSøren Schmidt 	 *	Then call filesystem specific open routine (which does nothing
225e1743d02SSøren Schmidt 	 *	in the general case).
226e1743d02SSøren Schmidt 	 */
227e1743d02SSøren Schmidt 	error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
228e1743d02SSøren Schmidt 	if (error)
229e1743d02SSøren Schmidt 		return (error);
230e1743d02SSøren Schmidt 
231e1743d02SSøren Schmidt 	error = VOP_OPEN(vp, FREAD, p->p_ucred, p);
232e1743d02SSøren Schmidt 	if (error)
233e1743d02SSøren Schmidt 		return (error);
234e1743d02SSøren Schmidt 
235e1743d02SSøren Schmidt 	return (0);
236e1743d02SSøren Schmidt }
237e1743d02SSøren Schmidt 
238e1743d02SSøren Schmidt static int
239e0c95ed9SBruce Evans elf_check_header(const Elf32_Ehdr *hdr, int type)
240e1743d02SSøren Schmidt {
241e1743d02SSøren Schmidt 	if (!(hdr->e_ident[EI_MAG0] == ELFMAG0 &&
242e1743d02SSøren Schmidt 	      hdr->e_ident[EI_MAG1] == ELFMAG1 &&
243e1743d02SSøren Schmidt 	      hdr->e_ident[EI_MAG2] == ELFMAG2 &&
244e1743d02SSøren Schmidt 	      hdr->e_ident[EI_MAG3] == ELFMAG3))
245e1743d02SSøren Schmidt 		return ENOEXEC;
246e1743d02SSøren Schmidt 
247e1743d02SSøren Schmidt 	if (hdr->e_machine != EM_386 && hdr->e_machine != EM_486)
248e1743d02SSøren Schmidt 		return ENOEXEC;
249e1743d02SSøren Schmidt 
250e1743d02SSøren Schmidt 	if (hdr->e_type != type)
251e1743d02SSøren Schmidt 		return ENOEXEC;
252e1743d02SSøren Schmidt 
253e1743d02SSøren Schmidt 	return 0;
254e1743d02SSøren Schmidt }
255e1743d02SSøren Schmidt 
256e1743d02SSøren Schmidt static int
257e1743d02SSø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)
258e1743d02SSøren Schmidt {
259e1743d02SSøren Schmidt 	size_t map_len;
260e1743d02SSøren Schmidt 	vm_offset_t map_addr;
261e1743d02SSøren Schmidt 	int error;
262e1743d02SSøren Schmidt 	unsigned char *data_buf = 0;
263e1743d02SSøren Schmidt 	size_t copy_len;
264e1743d02SSøren Schmidt 
265e1743d02SSøren Schmidt 	map_addr = trunc_page(vmaddr);
266e1743d02SSøren Schmidt 
267e1743d02SSøren Schmidt 	if (memsz > filsz)
268e1743d02SSøren Schmidt 		map_len = trunc_page(offset+filsz) - trunc_page(offset);
269e1743d02SSøren Schmidt 	else
270e1743d02SSøren Schmidt 		map_len = round_page(offset+filsz) - trunc_page(offset);
271e1743d02SSøren Schmidt 
272e1743d02SSøren Schmidt 	if (error = vm_mmap (&vmspace->vm_map,
273e1743d02SSøren Schmidt 			     &map_addr,
274e1743d02SSøren Schmidt 			     map_len,
275e1743d02SSøren Schmidt 			     prot,
276e1743d02SSøren Schmidt 			     VM_PROT_ALL,
27771d7d1b1SPeter Wemm 			     MAP_PRIVATE | MAP_FIXED,
278e1743d02SSøren Schmidt 			     (caddr_t)vp,
279e1743d02SSøren Schmidt 			     trunc_page(offset)))
280e1743d02SSøren Schmidt 		return error;
281e1743d02SSøren Schmidt 
282e1743d02SSøren Schmidt 	if (memsz == filsz)
283e1743d02SSøren Schmidt 		return 0;
284e1743d02SSøren Schmidt 
285e1743d02SSøren Schmidt 	/*
286e1743d02SSøren Schmidt 	 * We have to map the remaining bit of the file into the kernel's
287e1743d02SSøren Schmidt 	 * memory map, allocate some anonymous memory, and copy that last
288e1743d02SSøren Schmidt 	 * bit into it. The remaining space should be .bss...
289e1743d02SSøren Schmidt 	 */
290e1743d02SSøren Schmidt 	copy_len = (offset + filsz) - trunc_page(offset + filsz);
291e1743d02SSøren Schmidt 	map_addr = trunc_page(vmaddr + filsz);
292250c11f9SPeter Wemm 	map_len = round_page(vmaddr + memsz) - map_addr;
293e1743d02SSøren Schmidt 
2948191d577SPeter Wemm         if (map_len != 0) {
295e1743d02SSøren Schmidt 		if (error = vm_map_find(&vmspace->vm_map, NULL, 0,
296e1743d02SSøren Schmidt 					&map_addr, map_len, FALSE,
297e1743d02SSøren Schmidt 					VM_PROT_ALL, VM_PROT_ALL,0))
298e1743d02SSøren Schmidt 			return error;
2998191d577SPeter Wemm 	}
300e1743d02SSøren Schmidt 
301e1743d02SSøren Schmidt 	if (error = vm_mmap(kernel_map,
302e1743d02SSøren Schmidt 			    (vm_offset_t *)&data_buf,
303e1743d02SSøren Schmidt 			    PAGE_SIZE,
304e1743d02SSøren Schmidt 			    VM_PROT_READ,
305e1743d02SSøren Schmidt 			    VM_PROT_READ,
30671d7d1b1SPeter Wemm 			    0,
307e1743d02SSøren Schmidt 			    (caddr_t)vp,
308e1743d02SSøren Schmidt 			    trunc_page(offset + filsz)))
309e1743d02SSøren Schmidt 		return error;
310e1743d02SSøren Schmidt 
311e1743d02SSøren Schmidt 	error = copyout(data_buf, (caddr_t)map_addr, copy_len);
312e1743d02SSøren Schmidt 
313e1743d02SSøren Schmidt         vm_map_remove(kernel_map, (vm_offset_t)data_buf,
314e1743d02SSøren Schmidt 		      (vm_offset_t)data_buf + PAGE_SIZE);
315e1743d02SSøren Schmidt 
316e1743d02SSøren Schmidt 	/*
3178191d577SPeter Wemm 	 * set it to the specified protection
318e1743d02SSøren Schmidt 	 */
3198191d577SPeter Wemm 	vm_map_protect(&vmspace->vm_map, map_addr, map_addr + map_len,  prot,
3208191d577SPeter Wemm 		       FALSE);
3218191d577SPeter Wemm 
322e1743d02SSøren Schmidt 	UPRINTF("bss size %d (%x)\n", map_len-copy_len, map_len-copy_len);
323e1743d02SSøren Schmidt 	return error;
324e1743d02SSøren Schmidt }
325e1743d02SSøren Schmidt 
326e1743d02SSøren Schmidt static int
327e1743d02SSøren Schmidt elf_load_file(struct proc *p, char *file, u_long *addr, u_long *entry)
328e1743d02SSøren Schmidt {
329e1743d02SSøren Schmidt 	Elf32_Ehdr *hdr = NULL;
330e1743d02SSøren Schmidt 	Elf32_Phdr *phdr = NULL;
331e1743d02SSøren Schmidt 	struct nameidata nd;
332e1743d02SSøren Schmidt 	struct vmspace *vmspace = p->p_vmspace;
333e1743d02SSøren Schmidt 	vm_prot_t prot = 0;
334e1743d02SSøren Schmidt 	unsigned long text_size = 0, data_size = 0;
335e1743d02SSøren Schmidt 	unsigned long text_addr = 0, data_addr = 0;
336e1743d02SSøren Schmidt 	int header_size = 0;
337e1743d02SSøren Schmidt         int error, i;
338e1743d02SSøren Schmidt 
339e1743d02SSøren Schmidt         NDINIT(&nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_SYSSPACE, file, p);
340e1743d02SSøren Schmidt 
3411560a9d5SPeter Wemm 	if (error = namei(&nd)) {
3421560a9d5SPeter Wemm 		nd.ni_vp = NULL;
343e1743d02SSøren Schmidt 		goto fail;
344e1743d02SSøren Schmidt 	}
345e1743d02SSøren Schmidt 
346e1743d02SSøren Schmidt 	/*
347e1743d02SSøren Schmidt 	 * Check permissions, modes, uid, etc on the file, and "open" it.
348e1743d02SSøren Schmidt 	 */
349e1743d02SSøren Schmidt 	error = elf_check_permissions(p, nd.ni_vp);
350e1743d02SSøren Schmidt 
351e1743d02SSøren Schmidt 	/*
352e1743d02SSøren Schmidt 	 * No longer need this, and it prevents demand paging.
353e1743d02SSøren Schmidt 	 */
354996c772fSJohn Dyson 	VOP_UNLOCK(nd.ni_vp, 0, p);
355e1743d02SSøren Schmidt 
356e1743d02SSøren Schmidt 	if (error)
357e1743d02SSøren Schmidt                 goto fail;
358e1743d02SSøren Schmidt 
359e1743d02SSøren Schmidt 	/*
360e1743d02SSøren Schmidt 	 * Map in the header
361e1743d02SSøren Schmidt 	 */
362e1743d02SSøren Schmidt 	if (error = map_pages(nd.ni_vp, 0, (vm_offset_t *)&hdr, sizeof(hdr)))
363e1743d02SSøren Schmidt                 goto fail;
364e1743d02SSøren Schmidt 
365e1743d02SSøren Schmidt 	/*
366e1743d02SSøren Schmidt 	 * Do we have a valid ELF header ?
367e1743d02SSøren Schmidt 	 */
368e1743d02SSøren Schmidt 	if (error = elf_check_header(hdr, ET_DYN))
369e1743d02SSøren Schmidt 		goto fail;
370e1743d02SSøren Schmidt 
371e1743d02SSøren Schmidt 	/*
372e1743d02SSøren Schmidt 	 * ouch, need to bounds check in case user gives us a corrupted
373e1743d02SSøren Schmidt 	 * file with an insane header size
374e1743d02SSøren Schmidt 	 */
375e1743d02SSøren Schmidt 	if (hdr->e_phnum > MAX_PHDR) {	/* XXX: ever more than this? */
376e1743d02SSøren Schmidt 		error = ENOEXEC;
377e1743d02SSøren Schmidt 		goto fail;
378e1743d02SSøren Schmidt 	}
379e1743d02SSøren Schmidt 
380e1743d02SSøren Schmidt 	header_size = hdr->e_phentsize * hdr->e_phnum;
381e1743d02SSøren Schmidt 
382e1743d02SSøren Schmidt 	if (error = map_pages(nd.ni_vp, hdr->e_phoff, (vm_offset_t *)&phdr,
383e1743d02SSøren Schmidt 			         header_size))
384e1743d02SSøren Schmidt         	goto fail;
385e1743d02SSøren Schmidt 
386e1743d02SSøren Schmidt 	for (i = 0; i < hdr->e_phnum; i++) {
387e1743d02SSøren Schmidt 		switch(phdr[i].p_type) {
388e1743d02SSøren Schmidt 
389e1743d02SSøren Schmidt 	   	case PT_NULL:	/* NULL section */
390e1743d02SSøren Schmidt 	    		UPRINTF ("ELF(file) PT_NULL section\n");
391e1743d02SSøren Schmidt 			break;
392e1743d02SSøren Schmidt 		case PT_LOAD:	/* Loadable segment */
393e1743d02SSøren Schmidt 		{
394e1743d02SSøren Schmidt 	    		UPRINTF ("ELF(file) PT_LOAD section ");
395e1743d02SSøren Schmidt 			if (phdr[i].p_flags & PF_X)
396e1743d02SSøren Schmidt   				prot |= VM_PROT_EXECUTE;
397e1743d02SSøren Schmidt 			if (phdr[i].p_flags & PF_W)
398e1743d02SSøren Schmidt   				prot |= VM_PROT_WRITE;
399e1743d02SSøren Schmidt 			if (phdr[i].p_flags & PF_R)
400e1743d02SSøren Schmidt   				prot |= VM_PROT_READ;
401e1743d02SSøren Schmidt 
402e1743d02SSøren Schmidt 			if (error = elf_load_section(vmspace, nd.ni_vp,
403e1743d02SSøren Schmidt   						     phdr[i].p_offset,
404e1743d02SSøren Schmidt   						     (caddr_t)phdr[i].p_vaddr +
405e1743d02SSøren Schmidt 							(*addr),
406e1743d02SSøren Schmidt   						     phdr[i].p_memsz,
407e1743d02SSøren Schmidt   						     phdr[i].p_filesz, prot))
408e1743d02SSøren Schmidt 				goto fail;
409e1743d02SSøren Schmidt 
410e1743d02SSøren Schmidt 			/*
411e1743d02SSøren Schmidt 			 * Is this .text or .data ??
412e1743d02SSøren Schmidt 			 *
413e1743d02SSøren Schmidt 			 * We only handle one each of those yet XXX
414e1743d02SSøren Schmidt 			 */
415e1743d02SSøren Schmidt 			if (hdr->e_entry >= phdr[i].p_vaddr &&
416e1743d02SSøren Schmidt 			hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) {
417e1743d02SSøren Schmidt   				text_addr = trunc_page(phdr[i].p_vaddr+(*addr));
4188191d577SPeter Wemm   				text_size = round_page(phdr[i].p_memsz +
4198191d577SPeter Wemm 						       phdr[i].p_vaddr -
4208191d577SPeter Wemm 						       trunc_page(phdr[i].p_vaddr));
421e1743d02SSøren Schmidt 				*entry=(unsigned long)hdr->e_entry+(*addr);
422e1743d02SSøren Schmidt 	    			UPRINTF(".text <%08x,%08x> entry=%08x\n",
423e1743d02SSøren Schmidt 					text_addr, text_size, *entry);
424e1743d02SSøren Schmidt 			} else {
425e1743d02SSøren Schmidt   				data_addr = trunc_page(phdr[i].p_vaddr+(*addr));
4268191d577SPeter Wemm   				data_size = round_page(phdr[i].p_memsz +
4278191d577SPeter Wemm 						       phdr[i].p_vaddr -
4288191d577SPeter Wemm 						       trunc_page(phdr[i].p_vaddr));
429e1743d02SSøren Schmidt 	    			UPRINTF(".data <%08x,%08x>\n",
430e1743d02SSøren Schmidt 					data_addr, data_size);
431e1743d02SSøren Schmidt 			}
432e1743d02SSøren Schmidt 		}
433e1743d02SSøren Schmidt 		break;
434e1743d02SSøren Schmidt 
435e1743d02SSøren Schmidt 	   	case PT_DYNAMIC:/* Dynamic link information */
436e1743d02SSøren Schmidt 	    		UPRINTF ("ELF(file) PT_DYNAMIC section\n");
437e1743d02SSøren Schmidt 			break;
438e1743d02SSøren Schmidt 	  	case PT_INTERP:	/* Path to interpreter */
439e1743d02SSøren Schmidt 	    		UPRINTF ("ELF(file) PT_INTERP section\n");
440e1743d02SSøren Schmidt 			break;
441e1743d02SSøren Schmidt 	  	case PT_NOTE:	/* Note section */
442e1743d02SSøren Schmidt 	    		UPRINTF ("ELF(file) PT_NOTE section\n");
443e1743d02SSøren Schmidt 			break;
444e1743d02SSøren Schmidt 	  	case PT_SHLIB:	/* Shared lib section  */
445e1743d02SSøren Schmidt 	    		UPRINTF ("ELF(file) PT_SHLIB section\n");
446e1743d02SSøren Schmidt 			break;
447e1743d02SSøren Schmidt 		case PT_PHDR: 	/* Program header table info */
448e1743d02SSøren Schmidt 	    		UPRINTF ("ELF(file) PT_PHDR section\n");
449e1743d02SSøren Schmidt 			break;
450e1743d02SSøren Schmidt 		default:
451e1743d02SSøren Schmidt 	    		UPRINTF ("ELF(file) %d section ??\n", phdr[i].p_type );
452e1743d02SSøren Schmidt 		}
453e1743d02SSøren Schmidt 	}
454e1743d02SSøren Schmidt 
455e1743d02SSøren Schmidt fail:
456e1743d02SSøren Schmidt 	if (phdr)
4571a7eb2dcSPeter Wemm 		unmap_pages((vm_offset_t)phdr, header_size);
458e1743d02SSøren Schmidt 	if (hdr)
4591a7eb2dcSPeter Wemm 		unmap_pages((vm_offset_t)hdr, sizeof(hdr));
4601560a9d5SPeter Wemm 	if (nd.ni_vp)
4611560a9d5SPeter Wemm 		vrele(nd.ni_vp);
462e1743d02SSøren Schmidt 
463e1743d02SSøren Schmidt 	return error;
464e1743d02SSøren Schmidt }
465e1743d02SSøren Schmidt 
466303b270bSEivind Eklund static int
467e1743d02SSøren Schmidt exec_elf_imgact(struct image_params *imgp)
468e1743d02SSøren Schmidt {
469e0c95ed9SBruce Evans 	const Elf32_Ehdr *hdr = (const Elf32_Ehdr *) imgp->image_header;
470e0c95ed9SBruce Evans 	const Elf32_Phdr *phdr, *mapped_phdr = NULL;
471e1743d02SSøren Schmidt 	Elf32_Auxargs *elf_auxargs = NULL;
4725856e12eSJohn Dyson 	struct vmspace *vmspace;
473e1743d02SSøren Schmidt 	vm_prot_t prot = 0;
474e1743d02SSøren Schmidt 	u_long text_size = 0, data_size = 0;
475e1743d02SSøren Schmidt 	u_long text_addr = 0, data_addr = 0;
476e1743d02SSøren Schmidt 	u_long addr, entry = 0, proghdr = 0;
477e1743d02SSøren Schmidt 	int error, i, header_size = 0, interp_len = 0;
478e1743d02SSøren Schmidt 	char *interp = NULL;
479ea5a2b2eSSøren Schmidt 	char *brand = NULL;
480ea5a2b2eSSøren Schmidt 	char path[MAXPATHLEN];
481e1743d02SSøren Schmidt 
482e1743d02SSøren Schmidt 	/*
483e1743d02SSøren Schmidt 	 * Do we have a valid ELF header ?
484e1743d02SSøren Schmidt 	 */
485e1743d02SSøren Schmidt 	if (elf_check_header(hdr, ET_EXEC))
486e1743d02SSøren Schmidt 		return -1;
487e1743d02SSøren Schmidt 
488e1743d02SSøren Schmidt 	/*
489e1743d02SSøren Schmidt 	 * From here on down, we return an errno, not -1, as we've
490e1743d02SSøren Schmidt 	 * detected an ELF file.
491e1743d02SSøren Schmidt 	 */
492e1743d02SSøren Schmidt 
493e1743d02SSøren Schmidt 	/*
494e1743d02SSøren Schmidt 	 * ouch, need to bounds check in case user gives us a corrupted
495e1743d02SSøren Schmidt 	 * file with an insane header size
496e1743d02SSøren Schmidt 	 */
497e1743d02SSøren Schmidt 	if (hdr->e_phnum > MAX_PHDR) {	/* XXX: ever more than this? */
498e1743d02SSøren Schmidt 		return ENOEXEC;
499e1743d02SSøren Schmidt 	}
500e1743d02SSøren Schmidt 
501e1743d02SSøren Schmidt 	header_size = hdr->e_phentsize * hdr->e_phnum;
502e1743d02SSøren Schmidt 
503e1743d02SSøren Schmidt 	if ((hdr->e_phoff > PAGE_SIZE) ||
504e1743d02SSøren Schmidt 	    (hdr->e_phoff + header_size) > PAGE_SIZE) {
505e1743d02SSøren Schmidt 	  	/*
506e1743d02SSøren Schmidt 		 * Ouch ! we only get one page full of header...
507e1743d02SSøren Schmidt 		 * Try to map it in ourselves, and see how we go.
508e1743d02SSøren Schmidt 	   	 */
509e1743d02SSøren Schmidt 		if (error = map_pages(imgp->vp, hdr->e_phoff,
510e1743d02SSøren Schmidt 				(vm_offset_t *)&mapped_phdr, header_size))
511e1743d02SSøren Schmidt 			return (error);
512e1743d02SSøren Schmidt 		/*
513e1743d02SSøren Schmidt 		 * Save manual mapping for cleanup
514e1743d02SSøren Schmidt 		 */
515e1743d02SSøren Schmidt 		phdr = mapped_phdr;
516e1743d02SSøren Schmidt 	} else {
517e0c95ed9SBruce Evans 		phdr = (const Elf32_Phdr*)
518e0c95ed9SBruce Evans 		       ((const char *)imgp->image_header + hdr->e_phoff);
519e1743d02SSøren Schmidt 	}
520e1743d02SSøren Schmidt 
521e1743d02SSøren Schmidt 	/*
522e1743d02SSøren Schmidt 	 * From this point on, we may have resources that need to be freed.
523e1743d02SSøren Schmidt 	 */
524e1743d02SSøren Schmidt 	if (error = exec_extract_strings(imgp))
525e1743d02SSøren Schmidt 		goto fail;
526e1743d02SSøren Schmidt 
527e1743d02SSøren Schmidt 	exec_new_vmspace(imgp);
528e1743d02SSøren Schmidt 
5295856e12eSJohn Dyson 	vmspace = imgp->proc->p_vmspace;
5305856e12eSJohn Dyson 
531e1743d02SSøren Schmidt 	for (i = 0; i < hdr->e_phnum; i++) {
532e1743d02SSøren Schmidt 		switch(phdr[i].p_type) {
533e1743d02SSøren Schmidt 
534e1743d02SSøren Schmidt 	   	case PT_NULL:	/* NULL section */
535e1743d02SSøren Schmidt 	    		UPRINTF ("ELF PT_NULL section\n");
536e1743d02SSøren Schmidt 			break;
537e1743d02SSøren Schmidt 		case PT_LOAD:	/* Loadable segment */
538e1743d02SSøren Schmidt 		{
539e1743d02SSøren Schmidt 	    		UPRINTF ("ELF PT_LOAD section ");
540e1743d02SSøren Schmidt 			if (phdr[i].p_flags & PF_X)
541e1743d02SSøren Schmidt   				prot |= VM_PROT_EXECUTE;
542e1743d02SSøren Schmidt 			if (phdr[i].p_flags & PF_W)
543e1743d02SSøren Schmidt   				prot |= VM_PROT_WRITE;
544e1743d02SSøren Schmidt 			if (phdr[i].p_flags & PF_R)
545e1743d02SSøren Schmidt   				prot |= VM_PROT_READ;
546e1743d02SSøren Schmidt 
547e1743d02SSøren Schmidt 			if (error = elf_load_section(vmspace, imgp->vp,
548e1743d02SSøren Schmidt   						     phdr[i].p_offset,
549e1743d02SSøren Schmidt   						     (caddr_t)phdr[i].p_vaddr,
550e1743d02SSøren Schmidt   						     phdr[i].p_memsz,
551e1743d02SSøren Schmidt   						     phdr[i].p_filesz, prot))
552e1743d02SSøren Schmidt   				goto fail;
553e1743d02SSøren Schmidt 
554e1743d02SSøren Schmidt 			/*
555e1743d02SSøren Schmidt 			 * Is this .text or .data ??
556e1743d02SSøren Schmidt 			 *
557e1743d02SSøren Schmidt 			 * We only handle one each of those yet XXX
558e1743d02SSøren Schmidt 			 */
559e1743d02SSøren Schmidt 			if (hdr->e_entry >= phdr[i].p_vaddr &&
560e1743d02SSøren Schmidt 			hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) {
561e1743d02SSøren Schmidt   				text_addr = trunc_page(phdr[i].p_vaddr);
5628191d577SPeter Wemm   				text_size = round_page(phdr[i].p_memsz +
5638191d577SPeter Wemm 						       phdr[i].p_vaddr -
5648191d577SPeter Wemm 						       text_addr);
565e1743d02SSøren Schmidt 				entry = (u_long)hdr->e_entry;
566e1743d02SSøren Schmidt 	    			UPRINTF(".text <%08x,%08x> entry=%08x\n",
567e1743d02SSøren Schmidt 					text_addr, text_size, entry);
568e1743d02SSøren Schmidt 			} else {
569e1743d02SSøren Schmidt   				data_addr = trunc_page(phdr[i].p_vaddr);
5708191d577SPeter Wemm   				data_size = round_page(phdr[i].p_memsz +
5718191d577SPeter Wemm 						       phdr[i].p_vaddr -
5728191d577SPeter Wemm 						       data_addr);
573e1743d02SSøren Schmidt 	    			UPRINTF(".data <%08x,%08x>\n",
574e1743d02SSøren Schmidt 					data_addr, data_size);
575e1743d02SSøren Schmidt 			}
576e1743d02SSøren Schmidt 		}
577e1743d02SSøren Schmidt 		break;
578e1743d02SSøren Schmidt 
579e1743d02SSøren Schmidt 	   	case PT_DYNAMIC:/* Dynamic link information */
580e1743d02SSøren Schmidt 	    		UPRINTF ("ELF PT_DYNAMIC section ??\n");
581e1743d02SSøren Schmidt 			break;
582e1743d02SSøren Schmidt 	  	case PT_INTERP:	/* Path to interpreter */
583e1743d02SSøren Schmidt 	    		UPRINTF ("ELF PT_INTERP section ");
584e1743d02SSøren Schmidt 			if (phdr[i].p_filesz > MAXPATHLEN) {
585e1743d02SSøren Schmidt 				error = ENOEXEC;
586e1743d02SSøren Schmidt 				goto fail;
587e1743d02SSøren Schmidt 			}
588e1743d02SSøren Schmidt 			interp_len = MAXPATHLEN;
589e1743d02SSøren Schmidt 			if (error = map_pages(imgp->vp, phdr[i].p_offset,
590e1743d02SSøren Schmidt 					 (vm_offset_t *)&interp, interp_len))
591e1743d02SSøren Schmidt 				goto fail;
592e1743d02SSøren Schmidt 			UPRINTF("<%s>\n", interp);
593e1743d02SSøren Schmidt 			break;
594e1743d02SSøren Schmidt 	  	case PT_NOTE:	/* Note section */
595e1743d02SSøren Schmidt 	    		UPRINTF ("ELF PT_NOTE section\n");
596e1743d02SSøren Schmidt 			break;
597e1743d02SSøren Schmidt 	  	case PT_SHLIB:	/* Shared lib section  */
598e1743d02SSøren Schmidt 	    		UPRINTF ("ELF PT_SHLIB section\n");
599e1743d02SSøren Schmidt 			break;
600e1743d02SSøren Schmidt 		case PT_PHDR: 	/* Program header table info */
601e1743d02SSøren Schmidt 	    		UPRINTF ("ELF PT_PHDR section <%x>\n", phdr[i].p_vaddr);
602e1743d02SSøren Schmidt 			proghdr = phdr[i].p_vaddr;
603e1743d02SSøren Schmidt 			break;
604e1743d02SSøren Schmidt 		default:
605e1743d02SSøren Schmidt 	    		UPRINTF ("ELF %d section ??\n", phdr[i].p_type);
606e1743d02SSøren Schmidt 		}
607e1743d02SSøren Schmidt 	}
608e1743d02SSøren Schmidt 
609e1743d02SSøren Schmidt 	vmspace->vm_tsize = text_size >> PAGE_SHIFT;
610e1743d02SSøren Schmidt 	vmspace->vm_taddr = (caddr_t)text_addr;
611e1743d02SSøren Schmidt 	vmspace->vm_dsize = data_size >> PAGE_SHIFT;
612e1743d02SSøren Schmidt 	vmspace->vm_daddr = (caddr_t)data_addr;
613e1743d02SSøren Schmidt 
614e1743d02SSøren Schmidt 	addr = 2*MAXDSIZ; /* May depend on OS type XXX */
615e1743d02SSøren Schmidt 
616ea5a2b2eSSøren Schmidt 	imgp->entry_addr = entry;
617ea5a2b2eSSøren Schmidt 
618e1743d02SSøren Schmidt 	/*
619ea5a2b2eSSøren Schmidt 	 * So which kind (brand) of ELF binary do we have at hand
620ea5a2b2eSSøren Schmidt 	 * FreeBSD, Linux, SVR4 or something else ??
621ea5a2b2eSSøren Schmidt 	 * If its has a interpreter section try that first
622e1743d02SSøren Schmidt 	 */
623ea5a2b2eSSøren Schmidt         if (interp) {
624ea5a2b2eSSøren Schmidt                 for (i=0; i<MAX_BRANDS; i++) {
625ea5a2b2eSSøren Schmidt                         if (elf_brand_list[i] != NULL) {
626ea5a2b2eSSøren Schmidt                                 if (!strcmp(interp, elf_brand_list[i]->interp_path)) {
627e1743d02SSøren Schmidt                                         imgp->proc->p_sysent =
628ea5a2b2eSSøren Schmidt                                                 elf_brand_list[i]->sysvec;
629ea5a2b2eSSøren Schmidt                                         strcpy(path, elf_brand_list[i]->emul_path);
630ea5a2b2eSSøren Schmidt                                         strcat(path, elf_brand_list[i]->interp_path);
631e1743d02SSøren Schmidt                                         UPRINTF("interpreter=<%s> %s\n",
632ea5a2b2eSSøren Schmidt                                                 elf_brand_list[i]->interp_path,
633ea5a2b2eSSøren Schmidt                                                 elf_brand_list[i]->emul_path);
634e1743d02SSøren Schmidt                                         break;
635e1743d02SSøren Schmidt                                 }
636e1743d02SSøren Schmidt                         }
637e1743d02SSøren Schmidt                 }
638ea5a2b2eSSøren Schmidt         }
639ea5a2b2eSSøren Schmidt 
640ea5a2b2eSSøren Schmidt 	/*
641ea5a2b2eSSøren Schmidt 	 * If there is no interpreter, or recognition of it
642ea5a2b2eSSøren Schmidt 	 * failed, se if the binary is branded.
643ea5a2b2eSSøren Schmidt 	 */
644ea5a2b2eSSøren Schmidt 	if (!interp || i == MAX_BRANDS) {
645ea5a2b2eSSøren Schmidt 		brand = (char *)&(hdr->e_ident[EI_BRAND]);
646ea5a2b2eSSøren Schmidt 		for (i=0; i<MAX_BRANDS; i++) {
647ea5a2b2eSSøren Schmidt 			if (elf_brand_list[i] != NULL) {
648ea5a2b2eSSøren Schmidt 				if (!strcmp(brand, elf_brand_list[i]->brand)) {
649ea5a2b2eSSøren Schmidt 					imgp->proc->p_sysent = elf_brand_list[i]->sysvec;
650ea5a2b2eSSøren Schmidt 					if (interp) {
651ea5a2b2eSSøren Schmidt 						strcpy(path, elf_brand_list[i]->emul_path);
652ea5a2b2eSSøren Schmidt 						strcat(path, elf_brand_list[i]->interp_path);
653ea5a2b2eSSøren Schmidt 						UPRINTF("interpreter=<%s> %s\n",
654ea5a2b2eSSøren Schmidt 						elf_brand_list[i]->interp_path,
655ea5a2b2eSSøren Schmidt 						elf_brand_list[i]->emul_path);
656ea5a2b2eSSøren Schmidt 					}
657d672246bSSøren Schmidt 					break;
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 
677717fb679SSø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  */
744d8a4f230SBruce Evans static const struct execsw elf_execsw = {exec_elf_imgact, "ELF"};
745e1743d02SSøren Schmidt TEXT_SET(execsw_set, elf_execsw);
746e1743d02SSøren Schmidt 
747