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