xref: /freebsd/sys/kern/imgact_elf.c (revision 8c64af4f750d8c5fdc217c194d0d3ab5651617c3)
1 /*-
2  * Copyright (c) 1995-1996 S�ren Schmidt
3  * Copyright (c) 1996 Peter Wemm
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer
11  *    in this position and unchanged.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software withough specific prior written permission
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  *	$Id: imgact_elf.c,v 1.30 1998/09/14 05:36:49 jdp Exp $
30  */
31 
32 #include "opt_rlimit.h"
33 
34 #include <sys/param.h>
35 #include <sys/acct.h>
36 #include <sys/exec.h>
37 #include <sys/fcntl.h>
38 #include <sys/imgact.h>
39 #include <sys/imgact_elf.h>
40 #include <sys/kernel.h>
41 #include <sys/malloc.h>
42 #include <sys/mman.h>
43 #include <sys/namei.h>
44 #include <sys/pioctl.h>
45 #include <sys/proc.h>
46 #include <sys/procfs.h>
47 #include <sys/resourcevar.h>
48 #include <sys/signalvar.h>
49 #include <sys/stat.h>
50 #include <sys/syscall.h>
51 #include <sys/sysctl.h>
52 #include <sys/sysent.h>
53 #include <sys/systm.h>
54 #include <sys/vnode.h>
55 
56 #include <vm/vm.h>
57 #include <vm/vm_kern.h>
58 #include <vm/vm_param.h>
59 #include <vm/pmap.h>
60 #include <sys/lock.h>
61 #include <vm/vm_map.h>
62 #include <vm/vm_prot.h>
63 #include <vm/vm_extern.h>
64 
65 #include <machine/md_var.h>
66 
67 #define MAX_PHDR	32	/* XXX enough ? */
68 
69 #if ELF_TARG_CLASS == ELFCLASS32
70 
71 #define Elf_Ehdr	Elf32_Ehdr
72 #define Elf_Phdr	Elf32_Phdr
73 #define Elf_Auxargs	Elf32_Auxargs
74 #define Elf_Brandinfo	Elf32_Brandinfo
75 
76 #else
77 
78 #define Elf_Ehdr	Elf64_Ehdr
79 #define Elf_Phdr	Elf64_Phdr
80 #define Elf_Auxargs	Elf64_Auxargs
81 #define Elf_Brandinfo	Elf64_Brandinfo
82 
83 #endif
84 
85 
86 static int elf_check_header __P((const Elf_Ehdr *hdr, int type));
87 static int elf_freebsd_fixup __P((long **stack_base,
88     struct image_params *imgp));
89 static int elf_load_file __P((struct proc *p, char *file, u_long *addr,
90     u_long *entry));
91 static int elf_load_section __P((struct vmspace *vmspace, struct vnode *vp,
92     vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz,
93     vm_prot_t prot));
94 static int exec_elf_imgact __P((struct image_params *imgp));
95 
96 static int elf_trace = 0;
97 SYSCTL_INT(_debug, OID_AUTO, elf_trace, CTLFLAG_RW, &elf_trace, 0, "");
98 #define UPRINTF if (elf_trace) uprintf
99 
100 static struct sysentvec elf_freebsd_sysvec = {
101         SYS_MAXSYSCALL,
102         sysent,
103         0,
104         0,
105         0,
106         0,
107         0,
108         0,
109         elf_freebsd_fixup,
110         sendsig,
111         sigcode,
112         &szsigcode,
113         0,
114 	"FreeBSD ELF",
115 	elf_coredump
116 };
117 
118 static Elf_Brandinfo freebsd_brand_info = {
119 						"FreeBSD",
120 						"",
121 						"/usr/libexec/ld-elf.so.1",
122 						&elf_freebsd_sysvec
123 					  };
124 static Elf_Brandinfo *elf_brand_list[MAX_BRANDS] = {
125 							&freebsd_brand_info,
126 							NULL, NULL, NULL,
127 							NULL, NULL, NULL, NULL
128 						    };
129 
130 int
131 elf_insert_brand_entry(Elf_Brandinfo *entry)
132 {
133 	int i;
134 
135 	for (i=1; i<MAX_BRANDS; i++) {
136 		if (elf_brand_list[i] == NULL) {
137 			elf_brand_list[i] = entry;
138 			break;
139 		}
140 	}
141 	if (i == MAX_BRANDS)
142 		return -1;
143 	return 0;
144 }
145 
146 int
147 elf_remove_brand_entry(Elf_Brandinfo *entry)
148 {
149 	int i;
150 
151 	for (i=1; i<MAX_BRANDS; i++) {
152 		if (elf_brand_list[i] == entry) {
153 			elf_brand_list[i] = NULL;
154 			break;
155 		}
156 	}
157 	if (i == MAX_BRANDS)
158 		return -1;
159 	return 0;
160 }
161 
162 static int
163 elf_check_header(const Elf_Ehdr *hdr, int type)
164 {
165 	if (!(hdr->e_ident[EI_MAG0] == ELFMAG0 &&
166 	      hdr->e_ident[EI_MAG1] == ELFMAG1 &&
167 	      hdr->e_ident[EI_MAG2] == ELFMAG2 &&
168 	      hdr->e_ident[EI_MAG3] == ELFMAG3))
169 		return ENOEXEC;
170 
171 #ifdef __i386__
172 	if (hdr->e_machine != EM_386 && hdr->e_machine != EM_486)
173 #endif
174 #ifdef __alpha__
175 	if (hdr->e_machine != EM_ALPHA)
176 #endif
177 		return ENOEXEC;
178 
179 
180 	if (hdr->e_type != type)
181 		return ENOEXEC;
182 
183 	return 0;
184 }
185 
186 static int
187 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)
188 {
189 	size_t map_len;
190 	vm_offset_t map_addr;
191 	int error;
192 	unsigned char *data_buf = 0;
193 	size_t copy_len;
194 
195 	map_addr = trunc_page(vmaddr);
196 
197 	if (memsz > filsz)
198 		map_len = trunc_page(offset+filsz) - trunc_page(offset);
199 	else
200 		map_len = round_page(offset+filsz) - trunc_page(offset);
201 
202 	if (error = vm_mmap (&vmspace->vm_map,
203 			     &map_addr,
204 			     map_len,
205 			     prot,
206 			     VM_PROT_ALL,
207 			     MAP_PRIVATE | MAP_FIXED,
208 			     (caddr_t)vp,
209 			     trunc_page(offset)))
210 		return error;
211 
212 	if (memsz == filsz)
213 		return 0;
214 
215 	/*
216 	 * We have to map the remaining bit of the file into the kernel's
217 	 * memory map, allocate some anonymous memory, and copy that last
218 	 * bit into it. The remaining space should be .bss...
219 	 */
220 	copy_len = (offset + filsz) - trunc_page(offset + filsz);
221 	map_addr = trunc_page(vmaddr + filsz);
222 	map_len = round_page(vmaddr + memsz) - map_addr;
223 
224         if (map_len != 0) {
225 		if (error = vm_map_find(&vmspace->vm_map, NULL, 0,
226 					&map_addr, map_len, FALSE,
227 					VM_PROT_ALL, VM_PROT_ALL,0))
228 			return error;
229 	}
230 
231 	if (error = vm_mmap(exec_map,
232 			    (vm_offset_t *)&data_buf,
233 			    PAGE_SIZE,
234 			    VM_PROT_READ,
235 			    VM_PROT_READ,
236 			    0,
237 			    (caddr_t)vp,
238 			    trunc_page(offset + filsz)))
239 		return error;
240 
241 	error = copyout(data_buf, (caddr_t)map_addr, copy_len);
242 
243         vm_map_remove(exec_map, (vm_offset_t)data_buf,
244 		      (vm_offset_t)data_buf + PAGE_SIZE);
245 
246 	/*
247 	 * set it to the specified protection
248 	 */
249 	vm_map_protect(&vmspace->vm_map, map_addr, map_addr + map_len,  prot,
250 		       FALSE);
251 
252 	UPRINTF("bss size %d (%x)\n", map_len-copy_len, map_len-copy_len);
253 	return error;
254 }
255 
256 static int
257 elf_load_file(struct proc *p, char *file, u_long *addr, u_long *entry)
258 {
259 	Elf_Ehdr *hdr = NULL;
260 	Elf_Phdr *phdr = NULL;
261 	struct nameidata nd;
262 	struct vmspace *vmspace = p->p_vmspace;
263 	struct vattr attr;
264 	struct image_params image_params, *imgp;
265 	vm_prot_t prot = 0;
266 	unsigned long text_size = 0, data_size = 0;
267 	unsigned long text_addr = 0, data_addr = 0;
268 	int header_size = 0;
269         int error, i;
270 
271 	imgp = &image_params;
272 	/*
273 	 * Initialize part of the common data
274 	 */
275 	imgp->proc = p;
276 	imgp->uap = NULL;
277 	imgp->attr = &attr;
278 	imgp->firstpage = NULL;
279 	imgp->image_header = (char *)kmem_alloc_wait(exec_map, PAGE_SIZE);
280 
281 	if (imgp->image_header == NULL) {
282 		nd.ni_vp = NULL;
283 		error = ENOMEM;
284 		goto fail;
285 	}
286 
287         NDINIT(&nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_SYSSPACE, file, p);
288 
289 	if (error = namei(&nd)) {
290 		nd.ni_vp = NULL;
291 		goto fail;
292 	}
293 
294 	imgp->vp = nd.ni_vp;
295 
296 	/*
297 	 * Check permissions, modes, uid, etc on the file, and "open" it.
298 	 */
299 	error = exec_check_permissions(imgp);
300 	if (error) {
301 		VOP_UNLOCK(nd.ni_vp, 0, p);
302 		goto fail;
303 	}
304 
305 	error = exec_map_first_page(imgp);
306 	VOP_UNLOCK(nd.ni_vp, 0, p);
307 	if (error)
308                 goto fail;
309 
310 	hdr = (Elf_Ehdr *)imgp->image_header;
311 	if (error = elf_check_header(hdr, ET_DYN))
312 		goto fail;
313 
314 	/*
315 	 * ouch, need to bounds check in case user gives us a corrupted
316 	 * file with an insane header size
317 	 */
318 	if (hdr->e_phnum > MAX_PHDR) {	/* XXX: ever more than this? */
319 		error = ENOEXEC;
320 		goto fail;
321 	}
322 
323 	header_size = hdr->e_phentsize * hdr->e_phnum;
324 
325 	/* Only support headers that fit within first page for now */
326 	if (header_size + hdr->e_phoff > PAGE_SIZE) {
327 		error = ENOEXEC;
328 		goto fail;
329 	}
330 
331 	phdr = (Elf_Phdr *)(imgp->image_header + hdr->e_phoff);
332 
333 	for (i = 0; i < hdr->e_phnum; i++) {
334 		switch(phdr[i].p_type) {
335 
336 	   	case PT_NULL:	/* NULL section */
337 	    		UPRINTF ("ELF(file) PT_NULL section\n");
338 			break;
339 		case PT_LOAD:	/* Loadable segment */
340 		{
341 	    		UPRINTF ("ELF(file) PT_LOAD section ");
342 			if (phdr[i].p_flags & PF_X)
343   				prot |= VM_PROT_EXECUTE;
344 			if (phdr[i].p_flags & PF_W)
345   				prot |= VM_PROT_WRITE;
346 			if (phdr[i].p_flags & PF_R)
347   				prot |= VM_PROT_READ;
348 
349 			if (error = elf_load_section(vmspace, nd.ni_vp,
350   						     phdr[i].p_offset,
351   						     (caddr_t)phdr[i].p_vaddr +
352 							(*addr),
353   						     phdr[i].p_memsz,
354   						     phdr[i].p_filesz, prot))
355 				goto fail;
356 
357 			/*
358 			 * Is this .text or .data ??
359 			 *
360 			 * We only handle one each of those yet XXX
361 			 */
362 			if (hdr->e_entry >= phdr[i].p_vaddr &&
363 			hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) {
364   				text_addr = trunc_page(phdr[i].p_vaddr+(*addr));
365   				text_size = round_page(phdr[i].p_memsz +
366 						       phdr[i].p_vaddr -
367 						       trunc_page(phdr[i].p_vaddr));
368 				*entry=(unsigned long)hdr->e_entry+(*addr);
369 	    			UPRINTF(".text <%08lx,%08lx> entry=%08lx\n",
370 					text_addr, text_size, *entry);
371 			} else {
372   				data_addr = trunc_page(phdr[i].p_vaddr+(*addr));
373   				data_size = round_page(phdr[i].p_memsz +
374 						       phdr[i].p_vaddr -
375 						       trunc_page(phdr[i].p_vaddr));
376 	    			UPRINTF(".data <%08lx,%08lx>\n",
377 					data_addr, data_size);
378 			}
379 		}
380 		break;
381 
382 	   	case PT_DYNAMIC:/* Dynamic link information */
383 	    		UPRINTF ("ELF(file) PT_DYNAMIC section\n");
384 			break;
385 	  	case PT_INTERP:	/* Path to interpreter */
386 	    		UPRINTF ("ELF(file) PT_INTERP section\n");
387 			break;
388 	  	case PT_NOTE:	/* Note section */
389 	    		UPRINTF ("ELF(file) PT_NOTE section\n");
390 			break;
391 	  	case PT_SHLIB:	/* Shared lib section  */
392 	    		UPRINTF ("ELF(file) PT_SHLIB section\n");
393 			break;
394 		case PT_PHDR: 	/* Program header table info */
395 	    		UPRINTF ("ELF(file) PT_PHDR section\n");
396 			break;
397 		default:
398 	    		UPRINTF ("ELF(file) %d section ??\n", phdr[i].p_type );
399 		}
400 	}
401 
402 fail:
403 	if (imgp->firstpage)
404 		exec_unmap_first_page(imgp);
405 	if (imgp->image_header)
406 		kmem_free_wakeup(exec_map, (vm_offset_t)imgp->image_header,
407 			PAGE_SIZE);
408 	if (nd.ni_vp)
409 		vrele(nd.ni_vp);
410 
411 	return error;
412 }
413 
414 static int
415 exec_elf_imgact(struct image_params *imgp)
416 {
417 	const Elf_Ehdr *hdr = (const Elf_Ehdr *) imgp->image_header;
418 	const Elf_Phdr *phdr, *mapped_phdr = NULL;
419 	Elf_Auxargs *elf_auxargs = NULL;
420 	struct vmspace *vmspace;
421 	vm_prot_t prot = 0;
422 	u_long text_size = 0, data_size = 0;
423 	u_long text_addr = 0, data_addr = 0;
424 	u_long addr, entry = 0, proghdr = 0;
425 	int error, i, header_size = 0;
426 	const char *interp = NULL;
427 	char *brand = NULL;
428 	char path[MAXPATHLEN];
429 
430 	/*
431 	 * Do we have a valid ELF header ?
432 	 */
433 	if (elf_check_header(hdr, ET_EXEC))
434 		return -1;
435 
436 	/*
437 	 * From here on down, we return an errno, not -1, as we've
438 	 * detected an ELF file.
439 	 */
440 
441 	/*
442 	 * ouch, need to bounds check in case user gives us a corrupted
443 	 * file with an insane header size
444 	 */
445 	if (hdr->e_phnum > MAX_PHDR) {	/* XXX: ever more than this? */
446 		return ENOEXEC;
447 	}
448 
449 	header_size = hdr->e_phentsize * hdr->e_phnum;
450 
451 	if ((hdr->e_phoff > PAGE_SIZE) ||
452 	    (hdr->e_phoff + header_size) > PAGE_SIZE) {
453 		/* Only support headers in first page for now */
454 		return ENOEXEC;
455 	} else {
456 		phdr = (const Elf_Phdr*)
457 		       ((const char *)imgp->image_header + hdr->e_phoff);
458 	}
459 
460 	/*
461 	 * From this point on, we may have resources that need to be freed.
462 	 */
463 	if (error = exec_extract_strings(imgp))
464 		goto fail;
465 
466 	exec_new_vmspace(imgp);
467 
468 	vmspace = imgp->proc->p_vmspace;
469 
470 	for (i = 0; i < hdr->e_phnum; i++) {
471 		switch(phdr[i].p_type) {
472 
473 	   	case PT_NULL:	/* NULL section */
474 	    		UPRINTF ("ELF PT_NULL section\n");
475 			break;
476 		case PT_LOAD:	/* Loadable segment */
477 		{
478 	    		UPRINTF ("ELF PT_LOAD section ");
479 			if (phdr[i].p_flags & PF_X)
480   				prot |= VM_PROT_EXECUTE;
481 			if (phdr[i].p_flags & PF_W)
482   				prot |= VM_PROT_WRITE;
483 			if (phdr[i].p_flags & PF_R)
484   				prot |= VM_PROT_READ;
485 
486 			if (error = elf_load_section(vmspace, imgp->vp,
487   						     phdr[i].p_offset,
488   						     (caddr_t)phdr[i].p_vaddr,
489   						     phdr[i].p_memsz,
490   						     phdr[i].p_filesz, prot))
491   				goto fail;
492 
493 			/*
494 			 * Is this .text or .data ??
495 			 *
496 			 * We only handle one each of those yet XXX
497 			 */
498 			if (hdr->e_entry >= phdr[i].p_vaddr &&
499 			hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) {
500   				text_addr = trunc_page(phdr[i].p_vaddr);
501   				text_size = round_page(phdr[i].p_memsz +
502 						       phdr[i].p_vaddr -
503 						       text_addr);
504 				entry = (u_long)hdr->e_entry;
505 	    			UPRINTF(".text <%08lx,%08lx> entry=%08lx\n",
506 					text_addr, text_size, entry);
507 			} else {
508   				data_addr = trunc_page(phdr[i].p_vaddr);
509   				data_size = round_page(phdr[i].p_memsz +
510 						       phdr[i].p_vaddr -
511 						       data_addr);
512 	    			UPRINTF(".data <%08lx,%08lx>\n",
513 					data_addr, data_size);
514 			}
515 		}
516 		break;
517 
518 	   	case PT_DYNAMIC:/* Dynamic link information */
519 	    		UPRINTF ("ELF PT_DYNAMIC section ??\n");
520 			break;
521 	  	case PT_INTERP:	/* Path to interpreter */
522 	    		UPRINTF ("ELF PT_INTERP section ");
523 			if (phdr[i].p_filesz > MAXPATHLEN ||
524 			    phdr[i].p_offset + phdr[i].p_filesz > PAGE_SIZE) {
525 				error = ENOEXEC;
526 				goto fail;
527 			}
528 			interp = imgp->image_header + phdr[i].p_offset;
529 			UPRINTF("<%s>\n", interp);
530 			break;
531 	  	case PT_NOTE:	/* Note section */
532 	    		UPRINTF ("ELF PT_NOTE section\n");
533 			break;
534 	  	case PT_SHLIB:	/* Shared lib section  */
535 	    		UPRINTF ("ELF PT_SHLIB section\n");
536 			break;
537 		case PT_PHDR: 	/* Program header table info */
538 	    		UPRINTF ("ELF PT_PHDR section <%x>\n", phdr[i].p_vaddr);
539 			proghdr = phdr[i].p_vaddr;
540 			break;
541 		default:
542 	    		UPRINTF ("ELF %d section ??\n", phdr[i].p_type);
543 		}
544 	}
545 
546 	vmspace->vm_tsize = text_size >> PAGE_SHIFT;
547 	vmspace->vm_taddr = (caddr_t)(uintptr_t)text_addr;
548 	vmspace->vm_dsize = data_size >> PAGE_SHIFT;
549 	vmspace->vm_daddr = (caddr_t)(uintptr_t)data_addr;
550 
551 	addr = 2L*MAXDSIZ; /* May depend on OS type XXX */
552 
553 	imgp->entry_addr = entry;
554 
555 	/*
556 	 * So which kind (brand) of ELF binary do we have at hand
557 	 * FreeBSD, Linux, SVR4 or something else ??
558 	 * If its has a interpreter section try that first
559 	 */
560         if (interp) {
561                 for (i=0; i<MAX_BRANDS; i++) {
562                         if (elf_brand_list[i] != NULL) {
563                                 if (!strcmp(interp, elf_brand_list[i]->interp_path)) {
564                                         imgp->proc->p_sysent =
565                                                 elf_brand_list[i]->sysvec;
566                                         strcpy(path, elf_brand_list[i]->emul_path);
567                                         strcat(path, elf_brand_list[i]->interp_path);
568                                         UPRINTF("interpreter=<%s> %s\n",
569                                                 elf_brand_list[i]->interp_path,
570                                                 elf_brand_list[i]->emul_path);
571                                         break;
572                                 }
573                         }
574                 }
575         }
576 
577 	/*
578 	 * If there is no interpreter, or recognition of it
579 	 * failed, se if the binary is branded.
580 	 */
581 	if (!interp || i == MAX_BRANDS) {
582 		brand = (char *)&(hdr->e_ident[EI_BRAND]);
583 		for (i=0; i<MAX_BRANDS; i++) {
584 			if (elf_brand_list[i] != NULL) {
585 				if (!strcmp(brand, elf_brand_list[i]->brand)) {
586 					imgp->proc->p_sysent = elf_brand_list[i]->sysvec;
587 					if (interp) {
588 						strcpy(path, elf_brand_list[i]->emul_path);
589 						strcat(path, elf_brand_list[i]->interp_path);
590 						UPRINTF("interpreter=<%s> %s\n",
591 						elf_brand_list[i]->interp_path,
592 						elf_brand_list[i]->emul_path);
593 					}
594 					break;
595 				}
596 			}
597 		}
598 	}
599 	if (i == MAX_BRANDS) {
600 #ifndef __alpha__
601 		uprintf("ELF binary type not known\n");
602 		error = ENOEXEC;
603 		goto fail;
604 #else
605 		i = 0;		/* assume freebsd */
606 		imgp->proc->p_sysent = elf_brand_list[i]->sysvec;
607 		if (interp) {
608 			strcpy(path, elf_brand_list[i]->emul_path);
609 			strcat(path, elf_brand_list[i]->interp_path);
610 			UPRINTF("interpreter=<%s> %s\n",
611 				elf_brand_list[i]->interp_path,
612 				elf_brand_list[i]->emul_path);
613 		}
614 #endif
615 	}
616 	if (interp) {
617                 if (error = elf_load_file(imgp->proc,
618                                           path,
619                                           &addr,        /* XXX */
620                                           &imgp->entry_addr)) {
621                         uprintf("ELF interpreter %s not found\n", path);
622                         goto fail;
623                 }
624 	}
625 
626 	UPRINTF("Executing %s binary\n", elf_brand_list[i]->brand);
627 
628 	/*
629 	 * Construct auxargs table (used by the fixup routine)
630 	 */
631 	elf_auxargs = malloc(sizeof(Elf_Auxargs), M_TEMP, M_WAITOK);
632 	elf_auxargs->execfd = -1;
633 	elf_auxargs->phdr = proghdr;
634 	elf_auxargs->phent = hdr->e_phentsize;
635 	elf_auxargs->phnum = hdr->e_phnum;
636 	elf_auxargs->pagesz = PAGE_SIZE;
637 	elf_auxargs->base = addr;
638 	elf_auxargs->flags = 0;
639 	elf_auxargs->entry = entry;
640 	elf_auxargs->trace = elf_trace;
641 
642 	imgp->auxargs = elf_auxargs;
643 	imgp->interpreted = 0;
644 
645 	/* don't allow modifying the file while we run it */
646 	imgp->vp->v_flag |= VTEXT;
647 
648 fail:
649 	return error;
650 }
651 
652 static int
653 elf_freebsd_fixup(long **stack_base, struct image_params *imgp)
654 {
655 	Elf_Auxargs *args = (Elf_Auxargs *)imgp->auxargs;
656 	long *pos;
657 
658 	pos = *stack_base + (imgp->argc + imgp->envc + 2);
659 
660 	if (args->trace) {
661 		AUXARGS_ENTRY(pos, AT_DEBUG, 1);
662 	}
663 	if (args->execfd != -1) {
664 		AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
665 	}
666 	AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
667 	AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
668 	AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
669 	AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
670 	AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
671 	AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
672 	AUXARGS_ENTRY(pos, AT_BASE, args->base);
673 	AUXARGS_ENTRY(pos, AT_NULL, 0);
674 
675 	free(imgp->auxargs, M_TEMP);
676 	imgp->auxargs = NULL;
677 
678 	(*stack_base)--;
679 	**stack_base = (long)imgp->argc;
680 	return 0;
681 }
682 
683 /*
684  * Code for generating ELF core dumps.
685  */
686 
687 static int elf_corehdr __P((struct proc *, struct vnode *, struct ucred *));
688 static size_t elf_hdrsize(void);
689 static void elf_puthdr(void *, size_t *, const prstatus_t *,
690     const prfpregset_t *, const prpsinfo_t *, const void *, size_t,
691     const void *, size_t);
692 static void elf_putnote(void *, size_t *, const char *, int, const void *,
693     size_t);
694 
695 extern int osreldate;
696 
697 int
698 elf_coredump(p)
699 	register struct proc *p;
700 {
701 	register struct vnode *vp;
702 	register struct ucred *cred = p->p_cred->pc_ucred;
703 	register struct vmspace *vm = p->p_vmspace;
704 	struct nameidata nd;
705 	struct vattr vattr;
706 	int error, error1;
707 	char *name;			/* name of corefile */
708 	size_t hdrsize;
709 
710 	STOPEVENT(p, S_CORE, 0);
711 
712 	if (sugid_coredump == 0 && p->p_flag & P_SUGID)
713 		return (EFAULT);
714 	hdrsize = elf_hdrsize();
715 	if (hdrsize + ctob(vm->vm_dsize + vm->vm_ssize) >=
716 	    p->p_rlimit[RLIMIT_CORE].rlim_cur)
717 		return (EFAULT);
718 	name = expand_name(p->p_comm, p->p_ucred->cr_uid, p->p_pid);
719 	if (name == NULL)
720 		return (EFAULT);	/* XXX -- not the best error */
721 
722 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, name, p);
723 	error = vn_open(&nd, O_CREAT | FWRITE, S_IRUSR | S_IWUSR);
724 	free(name, M_TEMP);
725 	if (error)
726 		return (error);
727 	vp = nd.ni_vp;
728 
729 	/* Don't dump to non-regular files or files with links. */
730 	if (vp->v_type != VREG ||
731 	    VOP_GETATTR(vp, &vattr, cred, p) || vattr.va_nlink != 1) {
732 		error = EFAULT;
733 		goto out;
734 	}
735 	VATTR_NULL(&vattr);
736 	vattr.va_size = 0;
737 	VOP_LEASE(vp, p, cred, LEASE_WRITE);
738 	VOP_SETATTR(vp, &vattr, cred, p);
739 	p->p_acflag |= ACORE;
740 	error = elf_corehdr(p, vp, cred);
741 	if (error == 0)
742 		error = vn_rdwr(UIO_WRITE, vp, vm->vm_daddr,
743 		    (int)ctob(vm->vm_dsize), (off_t)hdrsize, UIO_USERSPACE,
744 		    IO_NODELOCKED|IO_UNIT, cred, (int *) NULL, p);
745 	if (error == 0)
746 		error = vn_rdwr(UIO_WRITE, vp,
747 		    (caddr_t) trunc_page(USRSTACK - ctob(vm->vm_ssize)),
748 		    round_page(ctob(vm->vm_ssize)),
749 		    (off_t)hdrsize + ctob(vm->vm_dsize), UIO_USERSPACE,
750 		    IO_NODELOCKED|IO_UNIT, cred, (int *) NULL, p);
751 out:
752 	VOP_UNLOCK(vp, 0, p);
753 	error1 = vn_close(vp, FWRITE, cred, p);
754 	if (error == 0)
755 		error = error1;
756 	return (error);
757 }
758 
759 static int
760 elf_corehdr(p, vp, cred)
761 	struct proc *p;
762 	struct vnode *vp;
763 	struct ucred *cred;
764 {
765 	struct vmspace *vm = p->p_vmspace;
766 	size_t off;
767 	size_t hdrsize;
768 	prstatus_t status;
769 	prfpregset_t fpregset;
770 	prpsinfo_t psinfo;
771 	void *hdr;
772 	int error;
773 
774 	/* Gather the information for the header. */
775 	bzero(&status, sizeof status);
776 	status.pr_version = PRSTATUS_VERSION;
777 	status.pr_statussz = sizeof(prstatus_t);
778 	status.pr_gregsetsz = sizeof(gregset_t);
779 	status.pr_fpregsetsz = sizeof(fpregset_t);
780 	status.pr_osreldate = osreldate;
781 	status.pr_cursig = p->p_sigacts->ps_sig;
782 	status.pr_pid = p->p_pid;
783 	fill_regs(p, &status.pr_reg);
784 
785 	fill_fpregs(p, &fpregset);
786 
787 	bzero(&psinfo, sizeof psinfo);
788 	psinfo.pr_version = PRPSINFO_VERSION;
789 	psinfo.pr_psinfosz = sizeof(prpsinfo_t);
790 	strncpy(psinfo.pr_fname, p->p_comm, MAXCOMLEN);
791 	psinfo.pr_psargs[0] = '\0';	/* XXX - args not implemented yet */
792 
793 	/* Allocate memory for building the header. */
794 	hdrsize = elf_hdrsize();
795 	hdr = malloc(hdrsize, M_TEMP, M_WAITOK);
796 	if (hdr == NULL)
797 		return EINVAL;
798 	bzero(hdr, hdrsize);
799 
800 	/* Fill in the header. */
801 	off = 0;
802 	elf_puthdr(hdr, &off, &status, &fpregset, &psinfo,
803 	    vm->vm_daddr, ctob(vm->vm_dsize),
804 	    (void *)trunc_page(USRSTACK - ctob(vm->vm_ssize)),
805 	    ctob(vm->vm_ssize));
806 
807 	/* Write it to the core file. */
808 	error = vn_rdwr(UIO_WRITE, vp, hdr, hdrsize, (off_t)0,
809 	    UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, NULL, p);
810 
811 	free(hdr, M_TEMP);
812 	return error;
813 }
814 
815 static size_t
816 elf_hdrsize(void)
817 {
818 	size_t off;
819 
820 	off = 0;
821 	elf_puthdr(NULL, &off, NULL, NULL, NULL, NULL, 0, NULL, 0);
822 	return off;
823 }
824 
825 static void
826 elf_puthdr(void *dst, size_t *off, const prstatus_t *status,
827     const prfpregset_t *fpregset, const prpsinfo_t *psinfo,
828     const void *data, size_t datasz, const void *stack, size_t stacksz)
829 {
830 	size_t ehoff;
831 	size_t phoff;
832 	size_t noteoff;
833 	size_t notesz;
834 	size_t dataoff;
835 	size_t stackoff;
836 	int numsegs = 3;
837 
838 	ehoff = *off;
839 	*off += sizeof(Elf_Ehdr);
840 
841 	phoff = *off;
842 	*off += numsegs * sizeof(Elf_Phdr);
843 
844 	noteoff = *off;
845 	elf_putnote(dst, off, "FreeBSD", NT_PRSTATUS, status,
846 	    sizeof *status);
847 	elf_putnote(dst, off, "FreeBSD", NT_FPREGSET, fpregset,
848 	    sizeof *fpregset);
849 	elf_putnote(dst, off, "FreeBSD", NT_PRPSINFO, psinfo,
850 	    sizeof *psinfo);
851 	notesz = *off - noteoff;
852 
853 	/* Align up to a page boundary for the data segment. */
854 	*off = round_page(*off);
855 
856 	if (dst != NULL) {
857 		Elf_Ehdr *ehdr;
858 		Elf_Phdr *phdr;
859 
860 		/*
861 		 * Fill in the ELF header.
862 		 */
863 		ehdr = (Elf_Ehdr *)((char *)dst + ehoff);
864 		ehdr->e_ident[EI_MAG0] = ELFMAG0;
865 		ehdr->e_ident[EI_MAG1] = ELFMAG1;
866 		ehdr->e_ident[EI_MAG2] = ELFMAG2;
867 		ehdr->e_ident[EI_MAG3] = ELFMAG3;
868 		ehdr->e_ident[EI_CLASS] = ELF_CLASS;
869 		ehdr->e_ident[EI_DATA] = ELF_DATA;
870 		ehdr->e_ident[EI_VERSION] = EV_CURRENT;
871 		ehdr->e_ident[EI_PAD] = 0;
872 		strncpy(ehdr->e_ident + EI_BRAND, "FreeBSD",
873 		    EI_NIDENT - EI_BRAND);
874 		ehdr->e_type = ET_CORE;
875 		ehdr->e_machine = ELF_ARCH;
876 		ehdr->e_version = EV_CURRENT;
877 		ehdr->e_entry = 0;
878 		ehdr->e_phoff = phoff;
879 		ehdr->e_flags = 0;
880 		ehdr->e_ehsize = sizeof(Elf_Ehdr);
881 		ehdr->e_phentsize = sizeof(Elf_Phdr);
882 		ehdr->e_phnum = numsegs;
883 		ehdr->e_shentsize = sizeof(Elf_Shdr);
884 		ehdr->e_shnum = 0;
885 		ehdr->e_shstrndx = SHN_UNDEF;
886 
887 		/*
888 		 * Fill in the program header entries.
889 		 */
890 		phdr = (Elf_Phdr *)((char *)dst + phoff);
891 
892 		/* The note segement. */
893 		phdr->p_type = PT_NOTE;
894 		phdr->p_offset = noteoff;
895 		phdr->p_vaddr = 0;
896 		phdr->p_paddr = 0;
897 		phdr->p_filesz = notesz;
898 		phdr->p_memsz = 0;
899 		phdr->p_flags = 0;
900 		phdr->p_align = 0;
901 		phdr++;
902 
903 		/* The data segment. */
904 		phdr->p_type = PT_LOAD;
905 		phdr->p_offset = *off;
906 		phdr->p_vaddr = (Elf_Addr)data;
907 		phdr->p_paddr = 0;
908 		phdr->p_filesz = phdr->p_memsz = datasz;
909 		phdr->p_align = PAGE_SIZE;
910 		phdr->p_flags = PF_R | PF_W | PF_X;
911 		phdr++;
912 
913 		/* The stack segment. */
914 		phdr->p_type = PT_LOAD;
915 		phdr->p_offset = *off + datasz;
916 		phdr->p_vaddr = (Elf_Addr)stack;
917 		phdr->p_paddr = 0;
918 		phdr->p_filesz = phdr->p_memsz = stacksz;
919 		phdr->p_align = PAGE_SIZE;
920 		phdr->p_flags = PF_R | PF_W | PF_X;
921 		phdr++;
922 	}
923 }
924 
925 static void
926 elf_putnote(void *dst, size_t *off, const char *name, int type,
927     const void *desc, size_t descsz)
928 {
929 	Elf_Note note;
930 
931 	note.n_namesz = strlen(name) + 1;
932 	note.n_descsz = descsz;
933 	note.n_type = type;
934 	if (dst != NULL)
935 		bcopy(&note, (char *)dst + *off, sizeof note);
936 	*off += sizeof note;
937 	if (dst != NULL)
938 		bcopy(name, (char *)dst + *off, note.n_namesz);
939 	*off += roundup2(note.n_namesz, sizeof(Elf_Size));
940 	if (dst != NULL)
941 		bcopy(desc, (char *)dst + *off, note.n_descsz);
942 	*off += roundup2(note.n_descsz, sizeof(Elf_Size));
943 }
944 
945 /*
946  * Tell kern_execve.c about it, with a little help from the linker.
947  * Since `const' objects end up in the text segment, TEXT_SET is the
948  * correct directive to use.
949  */
950 static const struct execsw elf_execsw = {exec_elf_imgact, "ELF"};
951 TEXT_SET(execsw_set, elf_execsw);
952 
953