imgact_elf.c revision 40435
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.39 1998/10/15 09:52:19 dfr 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_object.h>
63#include <vm/vm_prot.h>
64#include <vm/vm_extern.h>
65
66#include <machine/md_var.h>
67
68#define MAX_PHDR	32	/* XXX enough ? */
69
70#if ELF_TARG_CLASS == ELFCLASS32
71
72#define Elf_Ehdr	Elf32_Ehdr
73#define Elf_Phdr	Elf32_Phdr
74#define Elf_Auxargs	Elf32_Auxargs
75#define Elf_Brandinfo	Elf32_Brandinfo
76
77#else
78
79#define Elf_Ehdr	Elf64_Ehdr
80#define Elf_Phdr	Elf64_Phdr
81#define Elf_Auxargs	Elf64_Auxargs
82#define Elf_Brandinfo	Elf64_Brandinfo
83
84#endif
85
86
87static int elf_check_header __P((const Elf_Ehdr *hdr, int type));
88static int elf_freebsd_fixup __P((long **stack_base,
89    struct image_params *imgp));
90static int elf_load_file __P((struct proc *p, char *file, u_long *addr,
91    u_long *entry));
92static int elf_load_section __P((struct vmspace *vmspace, struct vnode *vp,
93    vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz,
94    vm_prot_t prot));
95static int exec_elf_imgact __P((struct image_params *imgp));
96
97static int elf_trace = 0;
98SYSCTL_INT(_debug, OID_AUTO, elf_trace, CTLFLAG_RW, &elf_trace, 0, "");
99#define UPRINTF if (elf_trace) uprintf
100
101static struct sysentvec elf_freebsd_sysvec = {
102        SYS_MAXSYSCALL,
103        sysent,
104        0,
105        0,
106        0,
107        0,
108        0,
109        0,
110        elf_freebsd_fixup,
111        sendsig,
112        sigcode,
113        &szsigcode,
114        0,
115	"FreeBSD ELF",
116	elf_coredump
117};
118
119static Elf_Brandinfo freebsd_brand_info = {
120						"FreeBSD",
121						"",
122						"/usr/libexec/ld-elf.so.1",
123						&elf_freebsd_sysvec
124					  };
125static Elf_Brandinfo *elf_brand_list[MAX_BRANDS] = {
126							&freebsd_brand_info,
127							NULL, NULL, NULL,
128							NULL, NULL, NULL, NULL
129						    };
130
131int
132elf_insert_brand_entry(Elf_Brandinfo *entry)
133{
134	int i;
135
136	for (i=1; i<MAX_BRANDS; i++) {
137		if (elf_brand_list[i] == NULL) {
138			elf_brand_list[i] = entry;
139			break;
140		}
141	}
142	if (i == MAX_BRANDS)
143		return -1;
144	return 0;
145}
146
147int
148elf_remove_brand_entry(Elf_Brandinfo *entry)
149{
150	int i;
151
152	for (i=1; i<MAX_BRANDS; i++) {
153		if (elf_brand_list[i] == entry) {
154			elf_brand_list[i] = NULL;
155			break;
156		}
157	}
158	if (i == MAX_BRANDS)
159		return -1;
160	return 0;
161}
162
163static int
164elf_check_header(const Elf_Ehdr *hdr, int type)
165{
166	if (!(hdr->e_ident[EI_MAG0] == ELFMAG0 &&
167	      hdr->e_ident[EI_MAG1] == ELFMAG1 &&
168	      hdr->e_ident[EI_MAG2] == ELFMAG2 &&
169	      hdr->e_ident[EI_MAG3] == ELFMAG3))
170		return ENOEXEC;
171
172#ifdef __i386__
173	if (hdr->e_machine != EM_386 && hdr->e_machine != EM_486)
174#endif
175#ifdef __alpha__
176	if (hdr->e_machine != EM_ALPHA)
177#endif
178		return ENOEXEC;
179
180
181	if (hdr->e_type != type)
182		return ENOEXEC;
183
184	return 0;
185}
186
187static int
188elf_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)
189{
190	size_t map_len;
191	vm_offset_t map_addr;
192	int error;
193	unsigned char *data_buf = 0;
194	size_t copy_len;
195
196	map_addr = trunc_page((vm_offset_t)vmaddr);
197
198	if (memsz > filsz)
199		map_len = trunc_page(offset+filsz) - trunc_page(offset);
200	else
201		map_len = round_page(offset+filsz) - trunc_page(offset);
202
203	if (error = vm_mmap (&vmspace->vm_map,
204			     &map_addr,
205			     map_len,
206			     prot,
207			     VM_PROT_ALL,
208			     MAP_PRIVATE | MAP_FIXED,
209			     (caddr_t)vp,
210			     trunc_page(offset)))
211		return error;
212
213	if (memsz == filsz)
214		return 0;
215
216	/*
217	 * We have to map the remaining bit of the file into the kernel's
218	 * memory map, allocate some anonymous memory, and copy that last
219	 * bit into it. The remaining space should be .bss...
220	 */
221	copy_len = (offset + filsz) - trunc_page(offset + filsz);
222	map_addr = trunc_page((vm_offset_t)vmaddr + filsz);
223	map_len = round_page((vm_offset_t)vmaddr + memsz) - map_addr;
224
225        if (map_len != 0) {
226		if (error = vm_map_find(&vmspace->vm_map, NULL, 0,
227					&map_addr, map_len, FALSE,
228					VM_PROT_ALL, VM_PROT_ALL,0))
229			return error;
230	}
231
232	if (error = vm_mmap(exec_map,
233			    (vm_offset_t *)&data_buf,
234			    PAGE_SIZE,
235			    VM_PROT_READ,
236			    VM_PROT_READ,
237			    0,
238			    (caddr_t)vp,
239			    trunc_page(offset + filsz)))
240		return error;
241
242	error = copyout(data_buf, (caddr_t)map_addr, copy_len);
243
244        vm_map_remove(exec_map, (vm_offset_t)data_buf,
245		      (vm_offset_t)data_buf + PAGE_SIZE);
246
247	/*
248	 * set it to the specified protection
249	 */
250	vm_map_protect(&vmspace->vm_map, map_addr, map_addr + map_len,  prot,
251		       FALSE);
252
253	UPRINTF("bss size %d (%x)\n", map_len-copy_len, map_len-copy_len);
254	return error;
255}
256
257static int
258elf_load_file(struct proc *p, char *file, u_long *addr, u_long *entry)
259{
260	Elf_Ehdr *hdr = NULL;
261	Elf_Phdr *phdr = NULL;
262	struct nameidata nd;
263	struct vmspace *vmspace = p->p_vmspace;
264	struct vattr attr;
265	struct image_params image_params, *imgp;
266	vm_prot_t prot = 0;
267	unsigned long text_size = 0, data_size = 0;
268	unsigned long text_addr = 0, data_addr = 0;
269	int header_size = 0;
270        int error, i;
271
272	imgp = &image_params;
273	/*
274	 * Initialize part of the common data
275	 */
276	imgp->proc = p;
277	imgp->uap = NULL;
278	imgp->attr = &attr;
279	imgp->firstpage = NULL;
280	imgp->image_header = (char *)kmem_alloc_wait(exec_map, PAGE_SIZE);
281
282	if (imgp->image_header == NULL) {
283		nd.ni_vp = NULL;
284		error = ENOMEM;
285		goto fail;
286	}
287
288        NDINIT(&nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_SYSSPACE, file, p);
289
290	if (error = namei(&nd)) {
291		nd.ni_vp = NULL;
292		goto fail;
293	}
294
295	imgp->vp = nd.ni_vp;
296
297	/*
298	 * Check permissions, modes, uid, etc on the file, and "open" it.
299	 */
300	error = exec_check_permissions(imgp);
301	if (error) {
302		VOP_UNLOCK(nd.ni_vp, 0, p);
303		goto fail;
304	}
305
306	error = exec_map_first_page(imgp);
307	VOP_UNLOCK(nd.ni_vp, 0, p);
308	if (error)
309                goto fail;
310
311	hdr = (Elf_Ehdr *)imgp->image_header;
312	if (error = elf_check_header(hdr, ET_DYN))
313		goto fail;
314
315	/*
316	 * ouch, need to bounds check in case user gives us a corrupted
317	 * file with an insane header size
318	 */
319	if (hdr->e_phnum > MAX_PHDR) {	/* XXX: ever more than this? */
320		error = ENOEXEC;
321		goto fail;
322	}
323
324	header_size = hdr->e_phentsize * hdr->e_phnum;
325
326	/* Only support headers that fit within first page for now */
327	if (header_size + hdr->e_phoff > PAGE_SIZE) {
328		error = ENOEXEC;
329		goto fail;
330	}
331
332	phdr = (Elf_Phdr *)(imgp->image_header + hdr->e_phoff);
333
334	for (i = 0; i < hdr->e_phnum; i++) {
335		switch(phdr[i].p_type) {
336
337	   	case PT_NULL:	/* NULL section */
338	    		UPRINTF ("ELF(file) PT_NULL section\n");
339			break;
340		case PT_LOAD:	/* Loadable segment */
341		{
342	    		UPRINTF ("ELF(file) PT_LOAD section ");
343			if (phdr[i].p_flags & PF_X)
344  				prot |= VM_PROT_EXECUTE;
345			if (phdr[i].p_flags & PF_W)
346  				prot |= VM_PROT_WRITE;
347			if (phdr[i].p_flags & PF_R)
348  				prot |= VM_PROT_READ;
349
350			if (error = elf_load_section(vmspace, nd.ni_vp,
351  						     phdr[i].p_offset,
352  						     (caddr_t)phdr[i].p_vaddr +
353							(*addr),
354  						     phdr[i].p_memsz,
355  						     phdr[i].p_filesz, prot))
356				goto fail;
357
358			/*
359			 * Is this .text or .data ??
360			 *
361			 * We only handle one each of those yet XXX
362			 */
363			if (hdr->e_entry >= phdr[i].p_vaddr &&
364			hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) {
365  				text_addr = trunc_page(phdr[i].p_vaddr+(*addr));
366  				text_size = round_page(phdr[i].p_memsz +
367						       phdr[i].p_vaddr -
368						       trunc_page(phdr[i].p_vaddr));
369				*entry=(unsigned long)hdr->e_entry+(*addr);
370	    			UPRINTF(".text <%08lx,%08lx> entry=%08lx\n",
371					text_addr, text_size, *entry);
372			} else {
373  				data_addr = trunc_page(phdr[i].p_vaddr+(*addr));
374  				data_size = round_page(phdr[i].p_memsz +
375						       phdr[i].p_vaddr -
376						       trunc_page(phdr[i].p_vaddr));
377	    			UPRINTF(".data <%08lx,%08lx>\n",
378					data_addr, data_size);
379			}
380		}
381		break;
382
383	   	case PT_DYNAMIC:/* Dynamic link information */
384	    		UPRINTF ("ELF(file) PT_DYNAMIC section\n");
385			break;
386	  	case PT_INTERP:	/* Path to interpreter */
387	    		UPRINTF ("ELF(file) PT_INTERP section\n");
388			break;
389	  	case PT_NOTE:	/* Note section */
390	    		UPRINTF ("ELF(file) PT_NOTE section\n");
391			break;
392	  	case PT_SHLIB:	/* Shared lib section  */
393	    		UPRINTF ("ELF(file) PT_SHLIB section\n");
394			break;
395		case PT_PHDR: 	/* Program header table info */
396	    		UPRINTF ("ELF(file) PT_PHDR section\n");
397			break;
398		default:
399	    		UPRINTF ("ELF(file) %d section ??\n", phdr[i].p_type );
400		}
401	}
402
403fail:
404	if (imgp->firstpage)
405		exec_unmap_first_page(imgp);
406	if (imgp->image_header)
407		kmem_free_wakeup(exec_map, (vm_offset_t)imgp->image_header,
408			PAGE_SIZE);
409	if (nd.ni_vp)
410		vrele(nd.ni_vp);
411
412	return error;
413}
414
415static int
416exec_elf_imgact(struct image_params *imgp)
417{
418	const Elf_Ehdr *hdr = (const Elf_Ehdr *) imgp->image_header;
419	const Elf_Phdr *phdr, *mapped_phdr = NULL;
420	Elf_Auxargs *elf_auxargs = NULL;
421	struct vmspace *vmspace;
422	vm_prot_t prot = 0;
423	u_long text_size = 0, data_size = 0;
424	u_long text_addr = 0, data_addr = 0;
425	u_long addr, entry = 0, proghdr = 0;
426	int error, i, header_size = 0;
427	const char *interp = NULL;
428	Elf_Brandinfo *brand_info;
429	char *brand;
430	char path[MAXPATHLEN];
431
432	/*
433	 * Do we have a valid ELF header ?
434	 */
435	if (elf_check_header(hdr, ET_EXEC))
436		return -1;
437
438	/*
439	 * From here on down, we return an errno, not -1, as we've
440	 * detected an ELF file.
441	 */
442
443	/*
444	 * ouch, need to bounds check in case user gives us a corrupted
445	 * file with an insane header size
446	 */
447	if (hdr->e_phnum > MAX_PHDR) {	/* XXX: ever more than this? */
448		return ENOEXEC;
449	}
450
451	header_size = hdr->e_phentsize * hdr->e_phnum;
452
453	if ((hdr->e_phoff > PAGE_SIZE) ||
454	    (hdr->e_phoff + header_size) > PAGE_SIZE) {
455		/* Only support headers in first page for now */
456		return ENOEXEC;
457	} else {
458		phdr = (const Elf_Phdr*)
459		       ((const char *)imgp->image_header + hdr->e_phoff);
460	}
461
462	/*
463	 * From this point on, we may have resources that need to be freed.
464	 */
465	if (error = exec_extract_strings(imgp))
466		goto fail;
467
468	exec_new_vmspace(imgp);
469
470	vmspace = imgp->proc->p_vmspace;
471
472	for (i = 0; i < hdr->e_phnum; i++) {
473		switch(phdr[i].p_type) {
474
475	   	case PT_NULL:	/* NULL section */
476	    		UPRINTF ("ELF PT_NULL section\n");
477			break;
478		case PT_LOAD:	/* Loadable segment */
479		{
480	    		UPRINTF ("ELF PT_LOAD section ");
481			if (phdr[i].p_flags & PF_X)
482  				prot |= VM_PROT_EXECUTE;
483			if (phdr[i].p_flags & PF_W)
484  				prot |= VM_PROT_WRITE;
485			if (phdr[i].p_flags & PF_R)
486  				prot |= VM_PROT_READ;
487
488			if (error = elf_load_section(vmspace, imgp->vp,
489  						     phdr[i].p_offset,
490  						     (caddr_t)phdr[i].p_vaddr,
491  						     phdr[i].p_memsz,
492  						     phdr[i].p_filesz, prot))
493  				goto fail;
494
495			/*
496			 * Is this .text or .data ??
497			 *
498			 * We only handle one each of those yet XXX
499			 */
500			if (hdr->e_entry >= phdr[i].p_vaddr &&
501			hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) {
502  				text_addr = trunc_page(phdr[i].p_vaddr);
503  				text_size = round_page(phdr[i].p_memsz +
504						       phdr[i].p_vaddr -
505						       text_addr);
506				entry = (u_long)hdr->e_entry;
507	    			UPRINTF(".text <%08lx,%08lx> entry=%08lx\n",
508					text_addr, text_size, entry);
509			} else {
510  				data_addr = trunc_page(phdr[i].p_vaddr);
511  				data_size = round_page(phdr[i].p_memsz +
512						       phdr[i].p_vaddr -
513						       data_addr);
514	    			UPRINTF(".data <%08lx,%08lx>\n",
515					data_addr, data_size);
516			}
517		}
518		break;
519
520	   	case PT_DYNAMIC:/* Dynamic link information */
521	    		UPRINTF ("ELF PT_DYNAMIC section ??\n");
522			break;
523	  	case PT_INTERP:	/* Path to interpreter */
524	    		UPRINTF ("ELF PT_INTERP section ");
525			if (phdr[i].p_filesz > MAXPATHLEN ||
526			    phdr[i].p_offset + phdr[i].p_filesz > PAGE_SIZE) {
527				error = ENOEXEC;
528				goto fail;
529			}
530			interp = imgp->image_header + phdr[i].p_offset;
531			UPRINTF("<%s>\n", interp);
532			break;
533	  	case PT_NOTE:	/* Note section */
534	    		UPRINTF ("ELF PT_NOTE section\n");
535			break;
536	  	case PT_SHLIB:	/* Shared lib section  */
537	    		UPRINTF ("ELF PT_SHLIB section\n");
538			break;
539		case PT_PHDR: 	/* Program header table info */
540	    		UPRINTF ("ELF PT_PHDR section <%x>\n", phdr[i].p_vaddr);
541			proghdr = phdr[i].p_vaddr;
542			break;
543		default:
544	    		UPRINTF ("ELF %d section ??\n", phdr[i].p_type);
545		}
546	}
547
548	vmspace->vm_tsize = text_size >> PAGE_SHIFT;
549	vmspace->vm_taddr = (caddr_t)(uintptr_t)text_addr;
550	vmspace->vm_dsize = data_size >> PAGE_SHIFT;
551	vmspace->vm_daddr = (caddr_t)(uintptr_t)data_addr;
552
553	addr = 2L*MAXDSIZ; /* May depend on OS type XXX */
554
555	imgp->entry_addr = entry;
556
557	/* If the executable has a brand, search for it in the brand list. */
558	brand_info = NULL;
559	brand = (char *)&hdr->e_ident[EI_BRAND];
560	if (brand[0] != '\0') {
561		for (i = 0;  i < MAX_BRANDS;  i++) {
562			Elf_Brandinfo *bi = elf_brand_list[i];
563
564			if (bi != NULL && strcmp(brand, bi->brand) == 0) {
565				brand_info = bi;
566				break;
567			}
568		}
569	}
570
571	/* Lacking a known brand, search for a recognized interpreter. */
572	if (brand_info == NULL && interp != NULL) {
573		for (i = 0;  i < MAX_BRANDS;  i++) {
574			Elf_Brandinfo *bi = elf_brand_list[i];
575
576			if (bi != NULL &&
577			    strcmp(interp, bi->interp_path) == 0) {
578				brand_info = bi;
579				break;
580			}
581		}
582	}
583
584#ifdef __alpha__
585	/* XXX - Assume FreeBSD on the alpha. */
586	if (brand_info == NULL)
587		brand_info = &freebsd_brand_info;
588#endif
589
590	if (brand_info == NULL) {
591		if (brand[0] == 0)
592			uprintf("ELF binary type not known."
593			    "  Use \"brandelf\" to brand it.\n");
594		else
595			uprintf("ELF binary type \"%.*s\" not known.\n",
596			    EI_NIDENT - EI_BRAND, brand);
597		error = ENOEXEC;
598		goto fail;
599	}
600
601	imgp->proc->p_sysent = brand_info->sysvec;
602	if (interp != NULL) {
603		strcpy(path, brand_info->emul_path);
604		strcat(path, interp);
605		UPRINTF("interpreter=<%s> %s\n", interp, brand_info->emul_path);
606                if ((error = elf_load_file(imgp->proc, path, &addr,
607		    &imgp->entry_addr)) != 0) {
608                        uprintf("ELF interpreter %s not found\n", path);
609                        goto fail;
610                }
611	}
612
613	UPRINTF("Executing %s binary\n", brand_info->brand);
614
615	/*
616	 * Construct auxargs table (used by the fixup routine)
617	 */
618	elf_auxargs = malloc(sizeof(Elf_Auxargs), M_TEMP, M_WAITOK);
619	elf_auxargs->execfd = -1;
620	elf_auxargs->phdr = proghdr;
621	elf_auxargs->phent = hdr->e_phentsize;
622	elf_auxargs->phnum = hdr->e_phnum;
623	elf_auxargs->pagesz = PAGE_SIZE;
624	elf_auxargs->base = addr;
625	elf_auxargs->flags = 0;
626	elf_auxargs->entry = entry;
627	elf_auxargs->trace = elf_trace;
628
629	imgp->auxargs = elf_auxargs;
630	imgp->interpreted = 0;
631
632	/* don't allow modifying the file while we run it */
633	imgp->vp->v_flag |= VTEXT;
634
635fail:
636	return error;
637}
638
639static int
640elf_freebsd_fixup(long **stack_base, struct image_params *imgp)
641{
642	Elf_Auxargs *args = (Elf_Auxargs *)imgp->auxargs;
643	long *pos;
644
645	pos = *stack_base + (imgp->argc + imgp->envc + 2);
646
647	if (args->trace) {
648		AUXARGS_ENTRY(pos, AT_DEBUG, 1);
649	}
650	if (args->execfd != -1) {
651		AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
652	}
653	AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
654	AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
655	AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
656	AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
657	AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
658	AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
659	AUXARGS_ENTRY(pos, AT_BASE, args->base);
660	AUXARGS_ENTRY(pos, AT_NULL, 0);
661
662	free(imgp->auxargs, M_TEMP);
663	imgp->auxargs = NULL;
664
665	(*stack_base)--;
666	suword(*stack_base, (long) imgp->argc);
667	return 0;
668}
669
670/*
671 * Code for generating ELF core dumps.
672 */
673
674typedef void (*segment_callback) __P((vm_map_entry_t, void *));
675
676/* Closure for cb_put_phdr(). */
677struct phdr_closure {
678	Elf_Phdr *phdr;		/* Program header to fill in */
679	Elf_Off offset;		/* Offset of segment in core file */
680};
681
682/* Closure for cb_size_segment(). */
683struct sseg_closure {
684	int count;		/* Count of writable segments. */
685	size_t size;		/* Total size of all writable segments. */
686};
687
688static void cb_put_phdr __P((vm_map_entry_t, void *));
689static void cb_size_segment __P((vm_map_entry_t, void *));
690static void each_writable_segment __P((struct proc *, segment_callback,
691    void *));
692static int elf_corehdr __P((struct proc *, struct vnode *, struct ucred *,
693    int, void *, size_t));
694static void elf_puthdr __P((struct proc *, void *, size_t *,
695    const prstatus_t *, const prfpregset_t *, const prpsinfo_t *, int));
696static void elf_putnote __P((void *, size_t *, const char *, int,
697    const void *, size_t));
698
699extern int osreldate;
700
701int
702elf_coredump(p)
703	register struct proc *p;
704{
705	register struct vnode *vp;
706	register struct ucred *cred = p->p_cred->pc_ucred;
707	register struct vmspace *vm = p->p_vmspace;
708	struct nameidata nd;
709	struct vattr vattr;
710	int error, error1;
711	char *name;			/* name of corefile */
712	struct sseg_closure seginfo;
713	void *hdr;
714	size_t hdrsize;
715
716	STOPEVENT(p, S_CORE, 0);
717
718	if (sugid_coredump == 0 && p->p_flag & P_SUGID)
719		return (EFAULT);
720
721	/* Size the program segments. */
722	seginfo.count = 0;
723	seginfo.size = 0;
724	each_writable_segment(p, cb_size_segment, &seginfo);
725
726	/*
727	 * Calculate the size of the core file header area by making
728	 * a dry run of generating it.  Nothing is written, but the
729	 * size is calculated.
730	 */
731	hdrsize = 0;
732	elf_puthdr((struct proc *)NULL, (void *)NULL, &hdrsize,
733	    (const prstatus_t *)NULL, (const prfpregset_t *)NULL,
734	    (const prpsinfo_t *)NULL, seginfo.count);
735
736	if (hdrsize + seginfo.size >= p->p_rlimit[RLIMIT_CORE].rlim_cur)
737		return (EFAULT);
738	name = expand_name(p->p_comm, p->p_ucred->cr_uid, p->p_pid);
739	if (name == NULL)
740		return (EFAULT);	/* XXX -- not the best error */
741
742	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, name, p);
743	error = vn_open(&nd, O_CREAT | FWRITE, S_IRUSR | S_IWUSR);
744	free(name, M_TEMP);
745	if (error)
746		return (error);
747	vp = nd.ni_vp;
748
749	/* Don't dump to non-regular files or files with links. */
750	if (vp->v_type != VREG ||
751	    VOP_GETATTR(vp, &vattr, cred, p) || vattr.va_nlink != 1) {
752		error = EFAULT;
753		goto out;
754	}
755	VATTR_NULL(&vattr);
756	vattr.va_size = 0;
757	VOP_LEASE(vp, p, cred, LEASE_WRITE);
758	VOP_SETATTR(vp, &vattr, cred, p);
759	p->p_acflag |= ACORE;
760
761
762	/*
763	 * Allocate memory for building the header, fill it up,
764	 * and write it out.
765	 */
766	hdr = malloc(hdrsize, M_TEMP, M_WAITOK);
767	if (hdr == NULL) {
768		error = EINVAL;
769		goto out;
770	}
771	error = elf_corehdr(p, vp, cred, seginfo.count, hdr, hdrsize);
772
773	/* Write the contents of all of the writable segments. */
774	if (error == 0) {
775		Elf_Phdr *php;
776		off_t offset;
777		int i;
778
779		php = (Elf_Phdr *)((char *)hdr + sizeof(Elf_Ehdr)) + 1;
780		offset = hdrsize;
781		for (i = 0;  i < seginfo.count;  i++) {
782			error = vn_rdwr(UIO_WRITE, vp, (caddr_t)php->p_vaddr,
783			    php->p_filesz, offset, UIO_USERSPACE,
784			    IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, p);
785			if (error != 0)
786				break;
787			offset += php->p_filesz;
788			php++;
789		}
790	}
791	free(hdr, M_TEMP);
792
793out:
794	VOP_UNLOCK(vp, 0, p);
795	error1 = vn_close(vp, FWRITE, cred, p);
796	if (error == 0)
797		error = error1;
798	return (error);
799}
800
801/*
802 * A callback for each_writable_segment() to write out the segment's
803 * program header entry.
804 */
805static void
806cb_put_phdr(entry, closure)
807	vm_map_entry_t entry;
808	void *closure;
809{
810	struct phdr_closure *phc = (struct phdr_closure *)closure;
811	Elf_Phdr *phdr = phc->phdr;
812
813	phc->offset = round_page(phc->offset);
814
815	phdr->p_type = PT_LOAD;
816	phdr->p_offset = phc->offset;
817	phdr->p_vaddr = entry->start;
818	phdr->p_paddr = 0;
819	phdr->p_filesz = phdr->p_memsz = entry->end - entry->start;
820	phdr->p_align = PAGE_SIZE;
821	phdr->p_flags = 0;
822	if (entry->protection & VM_PROT_READ)
823		phdr->p_flags |= PF_R;
824	if (entry->protection & VM_PROT_WRITE)
825		phdr->p_flags |= PF_W;
826	if (entry->protection & VM_PROT_EXECUTE)
827		phdr->p_flags |= PF_X;
828
829	phc->offset += phdr->p_filesz;
830	phc->phdr++;
831}
832
833/*
834 * A callback for each_writable_segment() to gather information about
835 * the number of segments and their total size.
836 */
837static void
838cb_size_segment(entry, closure)
839	vm_map_entry_t entry;
840	void *closure;
841{
842	struct sseg_closure *ssc = (struct sseg_closure *)closure;
843
844	ssc->count++;
845	ssc->size += entry->end - entry->start;
846}
847
848/*
849 * For each writable segment in the process's memory map, call the given
850 * function with a pointer to the map entry and some arbitrary
851 * caller-supplied data.
852 */
853static void
854each_writable_segment(p, func, closure)
855	struct proc *p;
856	segment_callback func;
857	void *closure;
858{
859	vm_map_t map = &p->p_vmspace->vm_map;
860	vm_map_entry_t entry;
861
862	for (entry = map->header.next;  entry != &map->header;
863	    entry = entry->next) {
864		vm_object_t obj;
865
866		if (entry->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP) ||
867		    (entry->protection & (VM_PROT_READ|VM_PROT_WRITE)) !=
868		    (VM_PROT_READ|VM_PROT_WRITE))
869			continue;
870
871		if ((obj = entry->object.vm_object) == NULL)
872			continue;
873
874		/* Find the deepest backing object. */
875		while (obj->backing_object != NULL)
876			obj = obj->backing_object;
877
878		/* Ignore memory-mapped devices and such things. */
879		if (obj->type != OBJT_DEFAULT &&
880		    obj->type != OBJT_SWAP &&
881		    obj->type != OBJT_VNODE)
882			continue;
883
884		(*func)(entry, closure);
885	}
886}
887
888/*
889 * Write the core file header to the file, including padding up to
890 * the page boundary.
891 */
892static int
893elf_corehdr(p, vp, cred, numsegs, hdr, hdrsize)
894	struct proc *p;
895	struct vnode *vp;
896	struct ucred *cred;
897	int numsegs;
898	size_t hdrsize;
899	void *hdr;
900{
901	struct vmspace *vm = p->p_vmspace;
902	size_t off;
903	prstatus_t status;
904	prfpregset_t fpregset;
905	prpsinfo_t psinfo;
906
907	/* Gather the information for the header. */
908	bzero(&status, sizeof status);
909	status.pr_version = PRSTATUS_VERSION;
910	status.pr_statussz = sizeof(prstatus_t);
911	status.pr_gregsetsz = sizeof(gregset_t);
912	status.pr_fpregsetsz = sizeof(fpregset_t);
913	status.pr_osreldate = osreldate;
914	status.pr_cursig = p->p_sigacts->ps_sig;
915	status.pr_pid = p->p_pid;
916	fill_regs(p, &status.pr_reg);
917
918	fill_fpregs(p, &fpregset);
919
920	bzero(&psinfo, sizeof psinfo);
921	psinfo.pr_version = PRPSINFO_VERSION;
922	psinfo.pr_psinfosz = sizeof(prpsinfo_t);
923	strncpy(psinfo.pr_fname, p->p_comm, MAXCOMLEN);
924	/* XXX - We don't fill in the command line arguments properly yet. */
925	strncpy(psinfo.pr_psargs, p->p_comm, PRARGSZ);
926
927	/* Fill in the header. */
928	bzero(hdr, hdrsize);
929	off = 0;
930	elf_puthdr(p, hdr, &off, &status, &fpregset, &psinfo, numsegs);
931
932	/* Write it to the core file. */
933	return vn_rdwr(UIO_WRITE, vp, hdr, hdrsize, (off_t)0,
934	    UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, NULL, p);
935}
936
937static void
938elf_puthdr(struct proc *p, void *dst, size_t *off, const prstatus_t *status,
939    const prfpregset_t *fpregset, const prpsinfo_t *psinfo, int numsegs)
940{
941	size_t ehoff;
942	size_t phoff;
943	size_t noteoff;
944	size_t notesz;
945
946	ehoff = *off;
947	*off += sizeof(Elf_Ehdr);
948
949	phoff = *off;
950	*off += (numsegs + 1) * sizeof(Elf_Phdr);
951
952	noteoff = *off;
953	elf_putnote(dst, off, "FreeBSD", NT_PRSTATUS, status,
954	    sizeof *status);
955	elf_putnote(dst, off, "FreeBSD", NT_FPREGSET, fpregset,
956	    sizeof *fpregset);
957	elf_putnote(dst, off, "FreeBSD", NT_PRPSINFO, psinfo,
958	    sizeof *psinfo);
959	notesz = *off - noteoff;
960
961	/* Align up to a page boundary for the program segments. */
962	*off = round_page(*off);
963
964	if (dst != NULL) {
965		Elf_Ehdr *ehdr;
966		Elf_Phdr *phdr;
967		struct phdr_closure phc;
968
969		/*
970		 * Fill in the ELF header.
971		 */
972		ehdr = (Elf_Ehdr *)((char *)dst + ehoff);
973		ehdr->e_ident[EI_MAG0] = ELFMAG0;
974		ehdr->e_ident[EI_MAG1] = ELFMAG1;
975		ehdr->e_ident[EI_MAG2] = ELFMAG2;
976		ehdr->e_ident[EI_MAG3] = ELFMAG3;
977		ehdr->e_ident[EI_CLASS] = ELF_CLASS;
978		ehdr->e_ident[EI_DATA] = ELF_DATA;
979		ehdr->e_ident[EI_VERSION] = EV_CURRENT;
980		ehdr->e_ident[EI_PAD] = 0;
981		strncpy(ehdr->e_ident + EI_BRAND, "FreeBSD",
982		    EI_NIDENT - EI_BRAND);
983		ehdr->e_type = ET_CORE;
984		ehdr->e_machine = ELF_ARCH;
985		ehdr->e_version = EV_CURRENT;
986		ehdr->e_entry = 0;
987		ehdr->e_phoff = phoff;
988		ehdr->e_flags = 0;
989		ehdr->e_ehsize = sizeof(Elf_Ehdr);
990		ehdr->e_phentsize = sizeof(Elf_Phdr);
991		ehdr->e_phnum = numsegs + 1;
992		ehdr->e_shentsize = sizeof(Elf_Shdr);
993		ehdr->e_shnum = 0;
994		ehdr->e_shstrndx = SHN_UNDEF;
995
996		/*
997		 * Fill in the program header entries.
998		 */
999		phdr = (Elf_Phdr *)((char *)dst + phoff);
1000
1001		/* The note segement. */
1002		phdr->p_type = PT_NOTE;
1003		phdr->p_offset = noteoff;
1004		phdr->p_vaddr = 0;
1005		phdr->p_paddr = 0;
1006		phdr->p_filesz = notesz;
1007		phdr->p_memsz = 0;
1008		phdr->p_flags = 0;
1009		phdr->p_align = 0;
1010		phdr++;
1011
1012		/* All the writable segments from the program. */
1013		phc.phdr = phdr;
1014		phc.offset = *off;
1015		each_writable_segment(p, cb_put_phdr, &phc);
1016	}
1017}
1018
1019static void
1020elf_putnote(void *dst, size_t *off, const char *name, int type,
1021    const void *desc, size_t descsz)
1022{
1023	Elf_Note note;
1024
1025	note.n_namesz = strlen(name) + 1;
1026	note.n_descsz = descsz;
1027	note.n_type = type;
1028	if (dst != NULL)
1029		bcopy(&note, (char *)dst + *off, sizeof note);
1030	*off += sizeof note;
1031	if (dst != NULL)
1032		bcopy(name, (char *)dst + *off, note.n_namesz);
1033	*off += roundup2(note.n_namesz, sizeof(Elf_Size));
1034	if (dst != NULL)
1035		bcopy(desc, (char *)dst + *off, note.n_descsz);
1036	*off += roundup2(note.n_descsz, sizeof(Elf_Size));
1037}
1038
1039/*
1040 * Tell kern_execve.c about it, with a little help from the linker.
1041 * Since `const' objects end up in the text segment, TEXT_SET is the
1042 * correct directive to use.
1043 */
1044static const struct execsw elf_execsw = {exec_elf_imgact, "ELF"};
1045EXEC_SET(elf, elf_execsw);
1046