xref: /netbsd-src/sys/kern/exec_elf32.c (revision 1ca5c1b28139779176bd5c13ad7c5f25c0bcd5f8)
1 /*	$NetBSD: exec_elf32.c,v 1.69 2001/11/12 15:25:03 lukem Exp $	*/
2 
3 /*-
4  * Copyright (c) 1994, 2000 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.69 2001/11/12 15:25:03 lukem 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 int	ELFNAME(check_header)(Elf_Ehdr *, int);
92 int	ELFNAME(load_file)(struct proc *, struct exec_package *, char *,
93 	    struct exec_vmcmd_set *, u_long *, struct elf_args *, Elf_Addr *);
94 void	ELFNAME(load_psection)(struct exec_vmcmd_set *, struct vnode *,
95 	    const Elf_Phdr *, Elf_Addr *, u_long *, int *, int);
96 
97 int ELFNAME2(netbsd,signature)(struct proc *, struct exec_package *,
98     Elf_Ehdr *);
99 int ELFNAME2(netbsd,probe)(struct proc *, struct exec_package *,
100     void *, char *, vaddr_t *);
101 
102 /* round up and down to page boundaries. */
103 #define	ELF_ROUND(a, b)		(((a) + (b) - 1) & ~((b) - 1))
104 #define	ELF_TRUNC(a, b)		((a) & ~((b) - 1))
105 
106 /*
107  * Copy arguments onto the stack in the normal way, but add some
108  * extra information in case of dynamic binding.
109  */
110 int
111 ELFNAME(copyargs)(struct exec_package *pack, struct ps_strings *arginfo,
112     char **stackp, void *argp)
113 {
114 	size_t len;
115 	AuxInfo ai[ELF_AUX_ENTRIES], *a;
116 	struct elf_args *ap;
117 	int error;
118 
119 	if ((error = copyargs(pack, arginfo, stackp, argp)) != 0)
120 		return error;
121 
122 	a = ai;
123 
124 	/*
125 	 * Push extra arguments on the stack needed by dynamically
126 	 * linked binaries
127 	 */
128 	if ((ap = (struct elf_args *)pack->ep_emul_arg)) {
129 
130 		a->a_type = AT_PHDR;
131 		a->a_v = ap->arg_phaddr;
132 		a++;
133 
134 		a->a_type = AT_PHENT;
135 		a->a_v = ap->arg_phentsize;
136 		a++;
137 
138 		a->a_type = AT_PHNUM;
139 		a->a_v = ap->arg_phnum;
140 		a++;
141 
142 		a->a_type = AT_PAGESZ;
143 		a->a_v = PAGE_SIZE;
144 		a++;
145 
146 		a->a_type = AT_BASE;
147 		a->a_v = ap->arg_interp;
148 		a++;
149 
150 		a->a_type = AT_FLAGS;
151 		a->a_v = 0;
152 		a++;
153 
154 		a->a_type = AT_ENTRY;
155 		a->a_v = ap->arg_entry;
156 		a++;
157 
158 		free((char *)ap, M_TEMP);
159 		pack->ep_emul_arg = NULL;
160 	}
161 
162 	a->a_type = AT_NULL;
163 	a->a_v = 0;
164 	a++;
165 
166 	len = (a - ai) * sizeof(AuxInfo);
167 	if ((error = copyout(ai, *stackp, len)) != 0)
168 		return error;
169 	*stackp += len;
170 
171 	return 0;
172 }
173 
174 /*
175  * elf_check_header():
176  *
177  * Check header for validity; return 0 of ok ENOEXEC if error
178  */
179 int
180 ELFNAME(check_header)(Elf_Ehdr *eh, int type)
181 {
182 
183 	if (memcmp(eh->e_ident, ELFMAG, SELFMAG) != 0 ||
184 	    eh->e_ident[EI_CLASS] != ELFCLASS)
185 		return (ENOEXEC);
186 
187 	switch (eh->e_machine) {
188 
189 	ELFDEFNNAME(MACHDEP_ID_CASES)
190 
191 	default:
192 		return (ENOEXEC);
193 	}
194 
195 	if (eh->e_type != type)
196 		return (ENOEXEC);
197 
198 	if (eh->e_shnum > 512 ||
199 	    eh->e_phnum > 128)
200 		return (ENOEXEC);
201 
202 	return (0);
203 }
204 
205 /*
206  * elf_load_psection():
207  *
208  * Load a psection at the appropriate address
209  */
210 void
211 ELFNAME(load_psection)(struct exec_vmcmd_set *vcset, struct vnode *vp,
212     const Elf_Phdr *ph, Elf_Addr *addr, u_long *size, int *prot, int flags)
213 {
214 	u_long uaddr, msize, psize, rm, rf;
215 	long diff, offset;
216 
217 	/*
218 	 * If the user specified an address, then we load there.
219 	 */
220 	if (*addr != ELFDEFNNAME(NO_ADDR)) {
221 		if (ph->p_align > 1) {
222 			*addr = ELF_TRUNC(*addr, ph->p_align);
223 			uaddr = ELF_TRUNC(ph->p_vaddr, ph->p_align);
224 		} else
225 			uaddr = ph->p_vaddr;
226 		diff = ph->p_vaddr - uaddr;
227 	} else {
228 		*addr = uaddr = ph->p_vaddr;
229 		if (ph->p_align > 1)
230 			*addr = ELF_TRUNC(uaddr, ph->p_align);
231 		diff = uaddr - *addr;
232 	}
233 
234 	*prot |= (ph->p_flags & PF_R) ? VM_PROT_READ : 0;
235 	*prot |= (ph->p_flags & PF_W) ? VM_PROT_WRITE : 0;
236 	*prot |= (ph->p_flags & PF_X) ? VM_PROT_EXECUTE : 0;
237 
238 	offset = ph->p_offset - diff;
239 	*size = ph->p_filesz + diff;
240 	msize = ph->p_memsz + diff;
241 
242 	if (ph->p_align >= PAGE_SIZE) {
243 		if ((ph->p_flags & PF_W) != 0) {
244 			/*
245 			 * Because the pagedvn pager can't handle zero fill
246 			 * of the last data page if it's not page aligned we
247 			 * map the last page readvn.
248 			 */
249 			psize = trunc_page(*size);
250 		} else {
251 			psize = round_page(*size);
252 		}
253 	} else {
254 		psize = *size;
255 	}
256 
257 	if (psize > 0) {
258 		NEW_VMCMD2(vcset, ph->p_align < PAGE_SIZE ?
259 		    vmcmd_map_readvn : vmcmd_map_pagedvn, psize, *addr, vp,
260 		    offset, *prot, flags);
261 	}
262 	if (psize < *size) {
263 		NEW_VMCMD2(vcset, vmcmd_map_readvn, *size - psize,
264 		    *addr + psize, vp, offset + psize, *prot,
265 		    psize > 0 ? flags & VMCMD_RELATIVE : flags);
266 	}
267 
268 	/*
269 	 * Check if we need to extend the size of the segment
270 	 */
271 	rm = round_page(*addr + msize);
272 	rf = round_page(*addr + *size);
273 
274 	if (rm != rf) {
275 		NEW_VMCMD2(vcset, vmcmd_map_zero, rm - rf, rf, NULLVP,
276 		    0, *prot, flags & VMCMD_RELATIVE);
277 		*size = msize;
278 	}
279 }
280 
281 /*
282  * elf_load_file():
283  *
284  * Load a file (interpreter/library) pointed to by path
285  * [stolen from coff_load_shlib()]. Made slightly generic
286  * so it might be used externally.
287  */
288 int
289 ELFNAME(load_file)(struct proc *p, struct exec_package *epp, char *path,
290     struct exec_vmcmd_set *vcset, u_long *entry, struct elf_args *ap,
291     Elf_Addr *last)
292 {
293 	int error, i;
294 	struct nameidata nd;
295 	struct vnode *vp;
296 	struct vattr attr;
297 	Elf_Ehdr eh;
298 	Elf_Phdr *ph = NULL;
299 	Elf_Phdr *base_ph = NULL;
300 	u_long phsize;
301 	char *bp = NULL;
302 	Elf_Addr addr = *last;
303 
304 	bp = path;
305 	/*
306 	 * 1. open file
307 	 * 2. read filehdr
308 	 * 3. map text, data, and bss out of it using VM_*
309 	 */
310 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, path, p);
311 	if ((error = namei(&nd)) != 0)
312 		return error;
313 	vp = nd.ni_vp;
314 
315 	/*
316 	 * Similarly, if it's not marked as executable, or it's not a regular
317 	 * file, we don't allow it to be used.
318 	 */
319 	if (vp->v_type != VREG) {
320 		error = EACCES;
321 		goto badunlock;
322 	}
323 	if ((error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p)) != 0)
324 		goto badunlock;
325 
326 	/* get attributes */
327 	if ((error = VOP_GETATTR(vp, &attr, p->p_ucred, p)) != 0)
328 		goto badunlock;
329 
330 	/*
331 	 * Check mount point.  Though we're not trying to exec this binary,
332 	 * we will be executing code from it, so if the mount point
333 	 * disallows execution or set-id-ness, we punt or kill the set-id.
334 	 */
335 	if (vp->v_mount->mnt_flag & MNT_NOEXEC) {
336 		error = EACCES;
337 		goto badunlock;
338 	}
339 	if (vp->v_mount->mnt_flag & MNT_NOSUID)
340 		epp->ep_vap->va_mode &= ~(S_ISUID | S_ISGID);
341 
342 #ifdef notyet /* XXX cgd 960926 */
343 	XXX cgd 960926: (maybe) VOP_OPEN it (and VOP_CLOSE in copyargs?)
344 #endif
345 	VOP_UNLOCK(vp, 0);
346 
347 	if ((error = exec_read_from(p, vp, 0, &eh, sizeof(eh))) != 0)
348 		goto bad;
349 
350 	if ((error = ELFNAME(check_header)(&eh, ET_DYN)) != 0)
351 		goto bad;
352 
353 	phsize = eh.e_phnum * sizeof(Elf_Phdr);
354 	ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK);
355 
356 	if ((error = exec_read_from(p, vp, eh.e_phoff, ph, phsize)) != 0)
357 		goto bad;
358 
359 	/*
360 	 * Load all the necessary sections
361 	 */
362 	for (i = 0; i < eh.e_phnum; i++) {
363 		u_long size = 0;
364 		int prot = 0;
365 		int flags;
366 
367 		switch (ph[i].p_type) {
368 		case PT_LOAD:
369 			if (base_ph == NULL) {
370 				addr = *last;
371 				flags = VMCMD_BASE;
372 			} else {
373 				addr = ph[i].p_vaddr - base_ph->p_vaddr;
374 				flags = VMCMD_RELATIVE;
375 			}
376 			ELFNAME(load_psection)(vcset, vp, &ph[i], &addr,
377 			    &size, &prot, flags);
378 			/* If entry is within this section it must be text */
379 			if (eh.e_entry >= ph[i].p_vaddr &&
380 			    eh.e_entry < (ph[i].p_vaddr + size)) {
381 				/* XXX */
382 				*entry = addr + eh.e_entry;
383 #ifdef mips
384 				*entry -= ph[i].p_vaddr;
385 #endif
386 				ap->arg_interp = addr;
387 			}
388 			if (base_ph == NULL)
389 				base_ph = &ph[i];
390 			addr += size;
391 			break;
392 
393 		case PT_DYNAMIC:
394 		case PT_PHDR:
395 		case PT_NOTE:
396 			break;
397 
398 		default:
399 			break;
400 		}
401 	}
402 
403 	free((char *)ph, M_TEMP);
404 	*last = addr;
405 	vrele(vp);
406 	return 0;
407 
408 badunlock:
409 	VOP_UNLOCK(vp, 0);
410 
411 bad:
412 	if (ph != NULL)
413 		free((char *)ph, M_TEMP);
414 #ifdef notyet /* XXX cgd 960926 */
415 	(maybe) VOP_CLOSE it
416 #endif
417 	vrele(vp);
418 	return error;
419 }
420 
421 /*
422  * exec_elf_makecmds(): Prepare an Elf binary's exec package
423  *
424  * First, set of the various offsets/lengths in the exec package.
425  *
426  * Then, mark the text image busy (so it can be demand paged) or error
427  * out if this is not possible.  Finally, set up vmcmds for the
428  * text, data, bss, and stack segments.
429  */
430 int
431 ELFNAME2(exec,makecmds)(struct proc *p, struct exec_package *epp)
432 {
433 	Elf_Ehdr *eh = epp->ep_hdr;
434 	Elf_Phdr *ph, *pp;
435 	Elf_Addr phdr = 0, pos = 0;
436 	int error, i, nload;
437 	char *interp = NULL;
438 	u_long phsize;
439 
440 	if (epp->ep_hdrvalid < sizeof(Elf_Ehdr))
441 		return ENOEXEC;
442 
443 	/*
444 	 * XXX allow for executing shared objects. It seems silly
445 	 * but other ELF-based systems allow it as well.
446 	 */
447 	if (ELFNAME(check_header)(eh, ET_EXEC) != 0 &&
448 	    ELFNAME(check_header)(eh, ET_DYN) != 0)
449 		return ENOEXEC;
450 
451 	/*
452 	 * check if vnode is in open for writing, because we want to
453 	 * demand-page out of it.  if it is, don't do it, for various
454 	 * reasons
455 	 */
456 	if (epp->ep_vp->v_writecount != 0) {
457 #ifdef DIAGNOSTIC
458 		if (epp->ep_vp->v_flag & VTEXT)
459 			panic("exec: a VTEXT vnode has writecount != 0\n");
460 #endif
461 		return ETXTBSY;
462 	}
463 	/*
464 	 * Allocate space to hold all the program headers, and read them
465 	 * from the file
466 	 */
467 	phsize = eh->e_phnum * sizeof(Elf_Phdr);
468 	ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK);
469 
470 	if ((error = exec_read_from(p, epp->ep_vp, eh->e_phoff, ph, phsize)) !=
471 	    0)
472 		goto bad;
473 
474 	epp->ep_taddr = epp->ep_tsize = ELFDEFNNAME(NO_ADDR);
475 	epp->ep_daddr = epp->ep_dsize = ELFDEFNNAME(NO_ADDR);
476 
477 	MALLOC(interp, char *, MAXPATHLEN, M_TEMP, M_WAITOK);
478 	interp[0] = '\0';
479 
480 	for (i = 0; i < eh->e_phnum; i++) {
481 		pp = &ph[i];
482 		if (pp->p_type == PT_INTERP) {
483 			if (pp->p_filesz >= MAXPATHLEN)
484 				goto bad;
485 			if ((error = exec_read_from(p, epp->ep_vp,
486 			    pp->p_offset, interp, pp->p_filesz)) != 0)
487 				goto bad;
488 			break;
489 		}
490 	}
491 
492 	/*
493 	 * On the same architecture, we may be emulating different systems.
494 	 * See which one will accept this executable. This currently only
495 	 * applies to SVR4, and IBCS2 on the i386 and Linux on the i386
496 	 * and the Alpha.
497 	 *
498 	 * Probe functions would normally see if the interpreter (if any)
499 	 * exists. Emulation packages may possibly replace the interpreter in
500 	 * interp[] with a changed path (/emul/xxx/<path>).
501 	 */
502 	if (!epp->ep_esch->u.elf_probe_func) {
503 		pos = ELFDEFNNAME(NO_ADDR);
504 	} else {
505 		vaddr_t startp = 0;
506 
507 		error = (*epp->ep_esch->u.elf_probe_func)(p, epp, eh, interp,
508 							  &startp);
509 		pos = (Elf_Addr)startp;
510 		if (error)
511 			goto bad;
512 	}
513 
514 	/*
515 	 * Load all the necessary sections
516 	 */
517 	for (i = nload = 0; i < eh->e_phnum; i++) {
518 		Elf_Addr  addr = ELFDEFNNAME(NO_ADDR);
519 		u_long size = 0;
520 		int prot = 0;
521 
522 		pp = &ph[i];
523 
524 		switch (ph[i].p_type) {
525 		case PT_LOAD:
526 			/*
527 			 * XXX
528 			 * Can handle only 2 sections: text and data
529 			 */
530 			if (nload++ == 2)
531 				goto bad;
532 			ELFNAME(load_psection)(&epp->ep_vmcmds, epp->ep_vp,
533 			    &ph[i], &addr, &size, &prot, 0);
534 
535 			/*
536 			 * Decide whether it's text or data by looking
537 			 * at the entry point.
538 			 */
539 			if (eh->e_entry >= addr &&
540 			    eh->e_entry < (addr + size)) {
541 				epp->ep_taddr = addr;
542 				epp->ep_tsize = size;
543 				if (epp->ep_daddr == ELFDEFNNAME(NO_ADDR)) {
544 					epp->ep_daddr = addr;
545 					epp->ep_dsize = size;
546 				}
547 			} else {
548 				epp->ep_daddr = addr;
549 				epp->ep_dsize = size;
550 			}
551 			break;
552 
553 		case PT_SHLIB:
554 			/* SCO has these sections. */
555 		case PT_INTERP:
556 			/* Already did this one. */
557 		case PT_DYNAMIC:
558 		case PT_NOTE:
559 			break;
560 
561 		case PT_PHDR:
562 			/* Note address of program headers (in text segment) */
563 			phdr = pp->p_vaddr;
564 			break;
565 
566 		default:
567 			/*
568 			 * Not fatal; we don't need to understand everything.
569 			 */
570 			break;
571 		}
572 	}
573 
574 	/* this breaks on, e.g., OpenBSD-compatible mips shared binaries. */
575 #ifndef ELF_INTERP_NON_RELOCATABLE
576 	/*
577 	 * If no position to load the interpreter was set by a probe
578 	 * function, pick the same address that a non-fixed mmap(0, ..)
579 	 * would (i.e. something safely out of the way).
580 	 */
581 	if (pos == ELFDEFNNAME(NO_ADDR))
582 		pos = round_page(epp->ep_daddr + MAXDSIZ);
583 #endif	/* !ELF_INTERP_NON_RELOCATABLE */
584 
585 	/*
586 	 * Check if we found a dynamically linked binary and arrange to load
587 	 * it's interpreter
588 	 */
589 	if (interp[0]) {
590 		struct elf_args *ap;
591 
592 		MALLOC(ap, struct elf_args *, sizeof(struct elf_args),
593 		    M_TEMP, M_WAITOK);
594 		if ((error = ELFNAME(load_file)(p, epp, interp,
595 		    &epp->ep_vmcmds, &epp->ep_entry, ap, &pos)) != 0) {
596 			FREE((char *)ap, M_TEMP);
597 			goto bad;
598 		}
599 		pos += phsize;
600 		ap->arg_phaddr = phdr;
601 
602 		ap->arg_phentsize = eh->e_phentsize;
603 		ap->arg_phnum = eh->e_phnum;
604 		ap->arg_entry = eh->e_entry;
605 
606 		epp->ep_emul_arg = ap;
607 	} else
608 		epp->ep_entry = eh->e_entry;
609 
610 #ifdef ELF_MAP_PAGE_ZERO
611 	/* Dell SVR4 maps page zero, yeuch! */
612 	NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, PAGE_SIZE, 0,
613 	    epp->ep_vp, 0, VM_PROT_READ);
614 #endif
615 	FREE(interp, M_TEMP);
616 	free((char *)ph, M_TEMP);
617 	epp->ep_vp->v_flag |= VTEXT;
618 	return exec_elf_setup_stack(p, epp);
619 
620 bad:
621 	if (interp)
622 		FREE(interp, M_TEMP);
623 	free((char *)ph, M_TEMP);
624 	kill_vmcmds(&epp->ep_vmcmds);
625 	return ENOEXEC;
626 }
627 
628 int
629 ELFNAME2(netbsd,signature)(struct proc *p, struct exec_package *epp,
630     Elf_Ehdr *eh)
631 {
632 	size_t i;
633 	Elf_Phdr *ph;
634 	size_t phsize;
635 	int error;
636 
637 	phsize = eh->e_phnum * sizeof(Elf_Phdr);
638 	ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK);
639 	error = exec_read_from(p, epp->ep_vp, eh->e_phoff, ph, phsize);
640 	if (error)
641 		goto out;
642 
643 	for (i = 0; i < eh->e_phnum; i++) {
644 		Elf_Phdr *ephp = &ph[i];
645 		Elf_Nhdr *np;
646 
647 		if (ephp->p_type != PT_NOTE ||
648 		    ephp->p_filesz > 1024 ||
649 		    ephp->p_filesz < sizeof(Elf_Nhdr) + ELF_NOTE_NETBSD_NAMESZ)
650 			continue;
651 
652 		np = (Elf_Nhdr *)malloc(ephp->p_filesz, M_TEMP, M_WAITOK);
653 		error = exec_read_from(p, epp->ep_vp, ephp->p_offset, np,
654 		    ephp->p_filesz);
655 		if (error)
656 			goto next;
657 
658 		if (np->n_type != ELF_NOTE_TYPE_NETBSD_TAG ||
659 		    np->n_namesz != ELF_NOTE_NETBSD_NAMESZ ||
660 		    np->n_descsz != ELF_NOTE_NETBSD_DESCSZ ||
661 		    memcmp((caddr_t)(np + 1), ELF_NOTE_NETBSD_NAME,
662 		    ELF_NOTE_NETBSD_NAMESZ))
663 			goto next;
664 
665 		error = 0;
666 		free(np, M_TEMP);
667 		goto out;
668 
669 	next:
670 		free(np, M_TEMP);
671 		continue;
672 	}
673 
674 	error = ENOEXEC;
675 out:
676 	free(ph, M_TEMP);
677 	return (error);
678 }
679 
680 int
681 ELFNAME2(netbsd,probe)(struct proc *p, struct exec_package *epp,
682     void *eh, char *itp, vaddr_t *pos)
683 {
684 	int error;
685 
686 	if ((error = ELFNAME2(netbsd,signature)(p, epp, eh)) != 0)
687 		return error;
688 	*pos = ELFDEFNNAME(NO_ADDR);
689 	return 0;
690 }
691