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