xref: /netbsd-src/sys/kern/exec_elf32.c (revision 9c1da17e908379b8a470f1117a6395bd6a0ca559)
1 /*	$NetBSD: exec_elf32.c,v 1.106 2005/07/17 23:53:57 junyoung Exp $	*/
2 
3 /*-
4  * Copyright (c) 1994, 2000, 2005 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Christos Zoulas.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the NetBSD
21  *	Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 /*
40  * Copyright (c) 1996 Christopher G. Demetriou
41  * All rights reserved.
42  *
43  * Redistribution and use in source and binary forms, with or without
44  * modification, are permitted provided that the following conditions
45  * are met:
46  * 1. Redistributions of source code must retain the above copyright
47  *    notice, this list of conditions and the following disclaimer.
48  * 2. Redistributions in binary form must reproduce the above copyright
49  *    notice, this list of conditions and the following disclaimer in the
50  *    documentation and/or other materials provided with the distribution.
51  * 3. The name of the author may not be used to endorse or promote products
52  *    derived from this software without specific prior written permission
53  *
54  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
55  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
56  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
57  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
58  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
59  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
60  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
61  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
62  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
63  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64  */
65 
66 #include <sys/cdefs.h>
67 __KERNEL_RCSID(1, "$NetBSD: exec_elf32.c,v 1.106 2005/07/17 23:53:57 junyoung Exp $");
68 
69 /* If not included by exec_elf64.c, ELFSIZE won't be defined. */
70 #ifndef ELFSIZE
71 #define	ELFSIZE		32
72 #endif
73 
74 #include <sys/param.h>
75 #include <sys/proc.h>
76 #include <sys/malloc.h>
77 #include <sys/namei.h>
78 #include <sys/vnode.h>
79 #include <sys/exec.h>
80 #include <sys/exec_elf.h>
81 #include <sys/syscall.h>
82 #include <sys/signalvar.h>
83 #include <sys/mount.h>
84 #include <sys/stat.h>
85 
86 #include <machine/cpu.h>
87 #include <machine/reg.h>
88 
89 extern const struct emul emul_netbsd;
90 
91 #define elf_check_header	ELFNAME(check_header)
92 #define elf_copyargs		ELFNAME(copyargs)
93 #define elf_load_file		ELFNAME(load_file)
94 #define elf_load_psection	ELFNAME(load_psection)
95 #define exec_elf_makecmds	ELFNAME2(exec,makecmds)
96 #define netbsd_elf_signature	ELFNAME2(netbsd,signature)
97 #define netbsd_elf_probe	ELFNAME2(netbsd,probe)
98 
99 int	elf_load_file(struct proc *, struct exec_package *, char *,
100 	    struct exec_vmcmd_set *, u_long *, struct elf_args *, Elf_Addr *);
101 void	elf_load_psection(struct exec_vmcmd_set *, struct vnode *,
102 	    const Elf_Phdr *, Elf_Addr *, u_long *, int *, int);
103 
104 int	netbsd_elf_signature(struct proc *, struct exec_package *, Elf_Ehdr *);
105 int	netbsd_elf_probe(struct proc *, struct exec_package *, void *, char *,
106 	    vaddr_t *);
107 
108 /* round up and down to page boundaries. */
109 #define	ELF_ROUND(a, b)		(((a) + (b) - 1) & ~((b) - 1))
110 #define	ELF_TRUNC(a, b)		((a) & ~((b) - 1))
111 
112 #define MAXPHNUM	50
113 
114 /*
115  * Copy arguments onto the stack in the normal way, but add some
116  * extra information in case of dynamic binding.
117  */
118 int
119 elf_copyargs(struct proc *p, struct exec_package *pack,
120     struct ps_strings *arginfo, char **stackp, void *argp)
121 {
122 	size_t len;
123 	AuxInfo ai[ELF_AUX_ENTRIES], *a;
124 	struct elf_args *ap;
125 	int error;
126 
127 	if ((error = copyargs(p, pack, arginfo, stackp, argp)) != 0)
128 		return error;
129 
130 	a = ai;
131 
132 	/*
133 	 * Push extra arguments on the stack needed by dynamically
134 	 * linked binaries
135 	 */
136 	if ((ap = (struct elf_args *)pack->ep_emul_arg)) {
137 		struct vattr *vap = pack->ep_vap;
138 
139 		a->a_type = AT_PHDR;
140 		a->a_v = ap->arg_phaddr;
141 		a++;
142 
143 		a->a_type = AT_PHENT;
144 		a->a_v = ap->arg_phentsize;
145 		a++;
146 
147 		a->a_type = AT_PHNUM;
148 		a->a_v = ap->arg_phnum;
149 		a++;
150 
151 		a->a_type = AT_PAGESZ;
152 		a->a_v = PAGE_SIZE;
153 		a++;
154 
155 		a->a_type = AT_BASE;
156 		a->a_v = ap->arg_interp;
157 		a++;
158 
159 		a->a_type = AT_FLAGS;
160 		a->a_v = 0;
161 		a++;
162 
163 		a->a_type = AT_ENTRY;
164 		a->a_v = ap->arg_entry;
165 		a++;
166 
167 		a->a_type = AT_EUID;
168 		if (vap->va_mode & S_ISUID)
169 			a->a_v = vap->va_uid;
170 		else
171 			a->a_v = p->p_ucred->cr_uid;
172 		a++;
173 
174 		a->a_type = AT_RUID;
175 		a->a_v = p->p_cred->p_ruid;
176 		a++;
177 
178 		a->a_type = AT_EGID;
179 		if (vap->va_mode & S_ISGID)
180 			a->a_v = vap->va_gid;
181 		else
182 			a->a_v = p->p_ucred->cr_gid;
183 		a++;
184 
185 		a->a_type = AT_RGID;
186 		a->a_v = p->p_cred->p_rgid;
187 		a++;
188 
189 		free(ap, M_TEMP);
190 		pack->ep_emul_arg = NULL;
191 	}
192 
193 	a->a_type = AT_NULL;
194 	a->a_v = 0;
195 	a++;
196 
197 	len = (a - ai) * sizeof(AuxInfo);
198 	if ((error = copyout(ai, *stackp, len)) != 0)
199 		return error;
200 	*stackp += len;
201 
202 	return 0;
203 }
204 
205 /*
206  * elf_check_header():
207  *
208  * Check header for validity; return 0 of ok ENOEXEC if error
209  */
210 int
211 elf_check_header(Elf_Ehdr *eh, int type)
212 {
213 
214 	if (memcmp(eh->e_ident, ELFMAG, SELFMAG) != 0 ||
215 	    eh->e_ident[EI_CLASS] != ELFCLASS)
216 		return ENOEXEC;
217 
218 	switch (eh->e_machine) {
219 
220 	ELFDEFNNAME(MACHDEP_ID_CASES)
221 
222 	default:
223 		return ENOEXEC;
224 	}
225 
226 	if (ELF_EHDR_FLAGS_OK(eh) == 0)
227 		return ENOEXEC;
228 
229 	if (eh->e_type != type)
230 		return ENOEXEC;
231 
232 	if (eh->e_shnum > 32768 || eh->e_phnum > 128)
233 		return ENOEXEC;
234 
235 	return 0;
236 }
237 
238 /*
239  * elf_load_psection():
240  *
241  * Load a psection at the appropriate address
242  */
243 void
244 elf_load_psection(struct exec_vmcmd_set *vcset, struct vnode *vp,
245     const Elf_Phdr *ph, Elf_Addr *addr, u_long *size, int *prot, int flags)
246 {
247 	u_long msize, psize, rm, rf;
248 	long diff, offset;
249 
250 	/*
251 	 * If the user specified an address, then we load there.
252 	 */
253 	if (*addr == ELFDEFNNAME(NO_ADDR))
254 		*addr = ph->p_vaddr;
255 
256 	if (ph->p_align > 1) {
257 		/*
258 		 * Make sure we are virtually aligned as we are supposed to be.
259 		 */
260 		diff = ph->p_vaddr - ELF_TRUNC(ph->p_vaddr, ph->p_align);
261 		KASSERT(*addr - diff == ELF_TRUNC(*addr, ph->p_align));
262 		/*
263 		 * But make sure to not map any pages before the start of the
264 		 * psection by limiting the difference to within a page.
265 		 */
266 		diff &= PAGE_MASK;
267 	} else
268 		diff = 0;
269 
270 	*prot |= (ph->p_flags & PF_R) ? VM_PROT_READ : 0;
271 	*prot |= (ph->p_flags & PF_W) ? VM_PROT_WRITE : 0;
272 	*prot |= (ph->p_flags & PF_X) ? VM_PROT_EXECUTE : 0;
273 
274 	/*
275 	 * Adjust everything so it all starts on a page boundary.
276 	 */
277 	*addr -= diff;
278 	offset = ph->p_offset - diff;
279 	*size = ph->p_filesz + diff;
280 	msize = ph->p_memsz + diff;
281 
282 	if (ph->p_align >= PAGE_SIZE) {
283 		if ((ph->p_flags & PF_W) != 0) {
284 			/*
285 			 * Because the pagedvn pager can't handle zero fill
286 			 * of the last data page if it's not page aligned we
287 			 * map the last page readvn.
288 			 */
289 			psize = trunc_page(*size);
290 		} else {
291 			psize = round_page(*size);
292 		}
293 	} else {
294 		psize = *size;
295 	}
296 
297 	if (psize > 0) {
298 		NEW_VMCMD2(vcset, ph->p_align < PAGE_SIZE ?
299 		    vmcmd_map_readvn : vmcmd_map_pagedvn, psize, *addr, vp,
300 		    offset, *prot, flags);
301 		flags &= VMCMD_RELATIVE;
302 	}
303 	if (psize < *size) {
304 		NEW_VMCMD2(vcset, vmcmd_map_readvn, *size - psize,
305 		    *addr + psize, vp, offset + psize, *prot, flags);
306 	}
307 
308 	/*
309 	 * Check if we need to extend the size of the segment (does
310 	 * bss extend page the next page boundary)?
311 	 */
312 	rm = round_page(*addr + msize);
313 	rf = round_page(*addr + *size);
314 
315 	if (rm != rf) {
316 		NEW_VMCMD2(vcset, vmcmd_map_zero, rm - rf, rf, NULLVP,
317 		    0, *prot, flags & VMCMD_RELATIVE);
318 		*size = msize;
319 	}
320 }
321 
322 /*
323  * elf_load_file():
324  *
325  * Load a file (interpreter/library) pointed to by path
326  * [stolen from coff_load_shlib()]. Made slightly generic
327  * so it might be used externally.
328  */
329 int
330 elf_load_file(struct proc *p, struct exec_package *epp, char *path,
331     struct exec_vmcmd_set *vcset, u_long *entryoff, struct elf_args *ap,
332     Elf_Addr *last)
333 {
334 	int error, i;
335 	struct nameidata nd;
336 	struct vnode *vp;
337 	struct vattr attr;
338 	Elf_Ehdr eh;
339 	Elf_Phdr *ph = NULL;
340 	const Elf_Phdr *ph0;
341 	const Elf_Phdr *base_ph;
342 	const Elf_Phdr *last_ph;
343 	u_long phsize;
344 	Elf_Addr addr = *last;
345 
346 	/*
347 	 * 1. open file
348 	 * 2. read filehdr
349 	 * 3. map text, data, and bss out of it using VM_*
350 	 */
351 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, path, p);
352 	if ((error = namei(&nd)) != 0)
353 		return error;
354 	vp = nd.ni_vp;
355 
356 	/*
357 	 * Similarly, if it's not marked as executable, or it's not a regular
358 	 * file, we don't allow it to be used.
359 	 */
360 	if (vp->v_type != VREG) {
361 		error = EACCES;
362 		goto badunlock;
363 	}
364 	if ((error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p)) != 0)
365 		goto badunlock;
366 
367 	/* get attributes */
368 	if ((error = VOP_GETATTR(vp, &attr, p->p_ucred, p)) != 0)
369 		goto badunlock;
370 
371 	/*
372 	 * Check mount point.  Though we're not trying to exec this binary,
373 	 * we will be executing code from it, so if the mount point
374 	 * disallows execution or set-id-ness, we punt or kill the set-id.
375 	 */
376 	if (vp->v_mount->mnt_flag & MNT_NOEXEC) {
377 		error = EACCES;
378 		goto badunlock;
379 	}
380 	if (vp->v_mount->mnt_flag & MNT_NOSUID)
381 		epp->ep_vap->va_mode &= ~(S_ISUID | S_ISGID);
382 
383 #ifdef notyet /* XXX cgd 960926 */
384 	XXX cgd 960926: (maybe) VOP_OPEN it (and VOP_CLOSE in copyargs?)
385 #endif
386 
387 	error = vn_marktext(vp);
388 	if (error)
389 		goto badunlock;
390 
391 	VOP_UNLOCK(vp, 0);
392 
393 	if ((error = exec_read_from(p, vp, 0, &eh, sizeof(eh))) != 0)
394 		goto bad;
395 
396 	if ((error = elf_check_header(&eh, ET_DYN)) != 0)
397 		goto bad;
398 
399 	if (eh.e_phnum > MAXPHNUM)
400 		goto bad;
401 
402 	phsize = eh.e_phnum * sizeof(Elf_Phdr);
403 	ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK);
404 
405 	if ((error = exec_read_from(p, vp, eh.e_phoff, ph, phsize)) != 0)
406 		goto bad;
407 
408 	/*
409 	 * If no position to load the interpreter was set by a probe
410 	 * function, pick the same address that a non-fixed mmap(0, ..)
411 	 * would (i.e. something safely out of the way).
412 	 */
413 	if (*last == ELFDEFNNAME(NO_ADDR)) {
414 		u_long limit = 0;
415 		/*
416 		 * Find the start and ending addresses of the psections to
417 		 * be loaded.  This will give us the size.
418 		 */
419 		for (i = 0, ph0 = ph, base_ph = NULL; i < eh.e_phnum;
420 		     i++, ph0++) {
421 			if (ph0->p_type == PT_LOAD) {
422 				u_long psize = ph0->p_vaddr + ph0->p_memsz;
423 				if (base_ph == NULL)
424 					base_ph = ph0;
425 				if (psize > limit)
426 					limit = psize;
427 			}
428 		}
429 
430 		/*
431 		 * Now compute the size and load address.
432 		 */
433 		addr = (*epp->ep_esch->es_emul->e_vm_default_addr)(p,
434 		    epp->ep_daddr,
435 		    round_page(limit) - trunc_page(base_ph->p_vaddr));
436 	} else
437 		addr = *last; /* may be ELF_LINK_ADDR */
438 
439 	/*
440 	 * Load all the necessary sections
441 	 */
442 	for (i = 0, ph0 = ph, base_ph = NULL, last_ph = NULL;
443 	     i < eh.e_phnum; i++, ph0++) {
444 		switch (ph0->p_type) {
445 		case PT_LOAD: {
446 			u_long size;
447 			int prot = 0;
448 			int flags;
449 
450 			if (base_ph == NULL) {
451 				/*
452 				 * First encountered psection is always the
453 				 * base psection.  Make sure it's aligned
454 				 * properly (align down for topdown and align
455 				 * upwards for not topdown).
456 				 */
457 				base_ph = ph0;
458 				flags = VMCMD_BASE;
459 				if (addr == ELF_LINK_ADDR)
460 					addr = ph0->p_vaddr;
461 				if (p->p_vmspace->vm_map.flags & VM_MAP_TOPDOWN)
462 					addr = ELF_TRUNC(addr, ph0->p_align);
463 				else
464 					addr = ELF_ROUND(addr, ph0->p_align);
465 			} else {
466 				u_long limit = round_page(last_ph->p_vaddr
467 				    + last_ph->p_memsz);
468 				u_long base = trunc_page(ph0->p_vaddr);
469 
470 				/*
471 				 * If there is a gap in between the psections,
472 				 * map it as inaccessible so nothing else
473 				 * mmap'ed will be placed there.
474 				 */
475 				if (limit != base) {
476 					NEW_VMCMD2(vcset, vmcmd_map_zero,
477 					    base - limit,
478 					    limit - base_ph->p_vaddr, NULLVP,
479 					    0, VM_PROT_NONE, VMCMD_RELATIVE);
480 				}
481 
482 				addr = ph0->p_vaddr - base_ph->p_vaddr;
483 				flags = VMCMD_RELATIVE;
484 			}
485 			last_ph = ph0;
486 			elf_load_psection(vcset, vp, &ph[i], &addr,
487 			    &size, &prot, flags);
488 			/*
489 			 * If entry is within this psection then this
490 			 * must contain the .text section.  *entryoff is
491 			 * relative to the base psection.
492 			 */
493 			if (eh.e_entry >= ph0->p_vaddr &&
494 			    eh.e_entry < (ph0->p_vaddr + size)) {
495 				*entryoff = eh.e_entry - base_ph->p_vaddr;
496 			}
497 			addr += size;
498 			break;
499 		}
500 
501 		case PT_DYNAMIC:
502 		case PT_PHDR:
503 		case PT_NOTE:
504 			break;
505 
506 		default:
507 			break;
508 		}
509 	}
510 
511 	free(ph, M_TEMP);
512 	/*
513 	 * This value is ignored if TOPDOWN.
514 	 */
515 	*last = addr;
516 	vrele(vp);
517 	return 0;
518 
519 badunlock:
520 	VOP_UNLOCK(vp, 0);
521 
522 bad:
523 	if (ph != NULL)
524 		free(ph, M_TEMP);
525 #ifdef notyet /* XXX cgd 960926 */
526 	(maybe) VOP_CLOSE it
527 #endif
528 	vrele(vp);
529 	return error;
530 }
531 
532 /*
533  * exec_elf_makecmds(): Prepare an Elf binary's exec package
534  *
535  * First, set of the various offsets/lengths in the exec package.
536  *
537  * Then, mark the text image busy (so it can be demand paged) or error
538  * out if this is not possible.  Finally, set up vmcmds for the
539  * text, data, bss, and stack segments.
540  */
541 int
542 exec_elf_makecmds(struct proc *p, struct exec_package *epp)
543 {
544 	Elf_Ehdr *eh = epp->ep_hdr;
545 	Elf_Phdr *ph, *pp;
546 	Elf_Addr phdr = 0, pos = 0;
547 	int error, i, nload;
548 	char *interp = NULL;
549 	u_long phsize;
550 
551 	if (epp->ep_hdrvalid < sizeof(Elf_Ehdr))
552 		return ENOEXEC;
553 
554 	/*
555 	 * XXX allow for executing shared objects. It seems silly
556 	 * but other ELF-based systems allow it as well.
557 	 */
558 	if (elf_check_header(eh, ET_EXEC) != 0 &&
559 	    elf_check_header(eh, ET_DYN) != 0)
560 		return ENOEXEC;
561 
562 	if (eh->e_phnum > MAXPHNUM)
563 		return ENOEXEC;
564 
565 	error = vn_marktext(epp->ep_vp);
566 	if (error)
567 		return error;
568 
569 	/*
570 	 * Allocate space to hold all the program headers, and read them
571 	 * from the file
572 	 */
573 	phsize = eh->e_phnum * sizeof(Elf_Phdr);
574 	ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK);
575 
576 	if ((error = exec_read_from(p, epp->ep_vp, eh->e_phoff, ph, phsize)) !=
577 	    0)
578 		goto bad;
579 
580 	epp->ep_taddr = epp->ep_tsize = ELFDEFNNAME(NO_ADDR);
581 	epp->ep_daddr = epp->ep_dsize = ELFDEFNNAME(NO_ADDR);
582 
583 	for (i = 0; i < eh->e_phnum; i++) {
584 		pp = &ph[i];
585 		if (pp->p_type == PT_INTERP) {
586 			if (pp->p_filesz >= MAXPATHLEN)
587 				goto bad;
588 			MALLOC(interp, char *, MAXPATHLEN, M_TEMP, M_WAITOK);
589 			interp[0] = '\0';
590 			if ((error = exec_read_from(p, epp->ep_vp,
591 			    pp->p_offset, interp, pp->p_filesz)) != 0)
592 				goto bad;
593 			break;
594 		}
595 	}
596 
597 	/*
598 	 * On the same architecture, we may be emulating different systems.
599 	 * See which one will accept this executable.
600 	 *
601 	 * Probe functions would normally see if the interpreter (if any)
602 	 * exists. Emulation packages may possibly replace the interpreter in
603 	 * interp[] with a changed path (/emul/xxx/<path>).
604 	 */
605 	pos = ELFDEFNNAME(NO_ADDR);
606 	if (epp->ep_esch->u.elf_probe_func) {
607 		vaddr_t startp = (vaddr_t)pos;
608 
609 		error = (*epp->ep_esch->u.elf_probe_func)(p, epp, eh, interp,
610 							  &startp);
611 		if (error)
612 			goto bad;
613 		pos = (Elf_Addr)startp;
614 	}
615 
616 	/*
617 	 * Load all the necessary sections
618 	 */
619 	for (i = nload = 0; i < eh->e_phnum; i++) {
620 		Elf_Addr  addr = ELFDEFNNAME(NO_ADDR);
621 		u_long size = 0;
622 		int prot = 0;
623 
624 		pp = &ph[i];
625 
626 		switch (ph[i].p_type) {
627 		case PT_LOAD:
628 			/*
629 			 * XXX
630 			 * Can handle only 2 sections: text and data
631 			 */
632 			if (nload++ == 2)
633 				goto bad;
634 			elf_load_psection(&epp->ep_vmcmds, epp->ep_vp,
635 			    &ph[i], &addr, &size, &prot, VMCMD_FIXED);
636 
637 			/*
638 			 * Decide whether it's text or data by looking
639 			 * at the entry point.
640 			 */
641 			if (eh->e_entry >= addr &&
642 			    eh->e_entry < (addr + size)) {
643 				epp->ep_taddr = addr;
644 				epp->ep_tsize = size;
645 				if (epp->ep_daddr == ELFDEFNNAME(NO_ADDR)) {
646 					epp->ep_daddr = addr;
647 					epp->ep_dsize = size;
648 				}
649 			} else {
650 				epp->ep_daddr = addr;
651 				epp->ep_dsize = size;
652 			}
653 			break;
654 
655 		case PT_SHLIB:
656 			/* SCO has these sections. */
657 		case PT_INTERP:
658 			/* Already did this one. */
659 		case PT_DYNAMIC:
660 		case PT_NOTE:
661 			break;
662 
663 		case PT_PHDR:
664 			/* Note address of program headers (in text segment) */
665 			phdr = pp->p_vaddr;
666 			break;
667 
668 		default:
669 			/*
670 			 * Not fatal; we don't need to understand everything.
671 			 */
672 			break;
673 		}
674 	}
675 
676 	/*
677 	 * Check if we found a dynamically linked binary and arrange to load
678 	 * its interpreter
679 	 */
680 	if (interp) {
681 		struct elf_args *ap;
682 		int j = epp->ep_vmcmds.evs_used;
683 		u_long interp_offset;
684 
685 		MALLOC(ap, struct elf_args *, sizeof(struct elf_args),
686 		    M_TEMP, M_WAITOK);
687 		if ((error = elf_load_file(p, epp, interp,
688 		    &epp->ep_vmcmds, &interp_offset, ap, &pos)) != 0) {
689 			FREE(ap, M_TEMP);
690 			goto bad;
691 		}
692 		ap->arg_interp = epp->ep_vmcmds.evs_cmds[j].ev_addr;
693 		epp->ep_entry = ap->arg_interp + interp_offset;
694 		ap->arg_phaddr = phdr;
695 
696 		ap->arg_phentsize = eh->e_phentsize;
697 		ap->arg_phnum = eh->e_phnum;
698 		ap->arg_entry = eh->e_entry;
699 
700 		epp->ep_emul_arg = ap;
701 
702 		FREE(interp, M_TEMP);
703 	} else
704 		epp->ep_entry = eh->e_entry;
705 
706 #ifdef ELF_MAP_PAGE_ZERO
707 	/* Dell SVR4 maps page zero, yeuch! */
708 	NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, PAGE_SIZE, 0,
709 	    epp->ep_vp, 0, VM_PROT_READ);
710 #endif
711 	free(ph, M_TEMP);
712 	return (*epp->ep_esch->es_setup_stack)(p, epp);
713 
714 bad:
715 	if (interp)
716 		FREE(interp, M_TEMP);
717 	free(ph, M_TEMP);
718 	kill_vmcmds(&epp->ep_vmcmds);
719 	return ENOEXEC;
720 }
721 
722 int
723 netbsd_elf_signature(struct proc *p, struct exec_package *epp,
724     Elf_Ehdr *eh)
725 {
726 	size_t i;
727 	Elf_Phdr *ph;
728 	size_t phsize;
729 	int error;
730 
731 	if (eh->e_phnum > MAXPHNUM)
732 		return ENOEXEC;
733 
734 	phsize = eh->e_phnum * sizeof(Elf_Phdr);
735 	ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK);
736 	error = exec_read_from(p, epp->ep_vp, eh->e_phoff, ph, phsize);
737 	if (error)
738 		goto out;
739 
740 	for (i = 0; i < eh->e_phnum; i++) {
741 		Elf_Phdr *ephp = &ph[i];
742 		Elf_Nhdr *np;
743 
744 		if (ephp->p_type != PT_NOTE ||
745 		    ephp->p_filesz > 1024 ||
746 		    ephp->p_filesz < sizeof(Elf_Nhdr) + ELF_NOTE_NETBSD_NAMESZ)
747 			continue;
748 
749 		np = (Elf_Nhdr *)malloc(ephp->p_filesz, M_TEMP, M_WAITOK);
750 		error = exec_read_from(p, epp->ep_vp, ephp->p_offset, np,
751 		    ephp->p_filesz);
752 		if (error)
753 			goto next;
754 
755 		if (np->n_type != ELF_NOTE_TYPE_NETBSD_TAG ||
756 		    np->n_namesz != ELF_NOTE_NETBSD_NAMESZ ||
757 		    np->n_descsz != ELF_NOTE_NETBSD_DESCSZ ||
758 		    memcmp((caddr_t)(np + 1), ELF_NOTE_NETBSD_NAME,
759 		    ELF_NOTE_NETBSD_NAMESZ))
760 			goto next;
761 
762 		error = 0;
763 		free(np, M_TEMP);
764 		goto out;
765 
766 	next:
767 		free(np, M_TEMP);
768 		continue;
769 	}
770 
771 	error = ENOEXEC;
772 out:
773 	free(ph, M_TEMP);
774 	return error;
775 }
776 
777 int
778 netbsd_elf_probe(struct proc *p, struct exec_package *epp,
779     void *eh, char *itp, vaddr_t *pos)
780 {
781 	int error;
782 
783 	if ((error = netbsd_elf_signature(p, epp, eh)) != 0)
784 		return error;
785 #ifdef ELF_INTERP_NON_RELOCATABLE
786 	*pos = ELF_LINK_ADDR;
787 #endif
788 	return 0;
789 }
790