exec_elf32.c revision 1.7
1/*	$NetBSD: exec_elf32.c,v 1.7 1996/06/13 18:35:25 christos Exp $	*/
2
3/*
4 * Copyright (c) 1994 Christos Zoulas
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
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 without 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 */
30
31#include <sys/param.h>
32#include <sys/systm.h>
33#include <sys/kernel.h>
34#include <sys/proc.h>
35#include <sys/malloc.h>
36#include <sys/namei.h>
37#include <sys/vnode.h>
38#include <sys/exec.h>
39#include <sys/exec_elf.h>
40
41#include <sys/mman.h>
42#include <vm/vm.h>
43#include <vm/vm_param.h>
44#include <vm/vm_map.h>
45
46#include <machine/cpu.h>
47#include <machine/reg.h>
48#include <machine/exec.h>
49
50#ifdef COMPAT_LINUX
51#include <compat/linux/linux_exec.h>
52#endif
53
54#ifdef COMPAT_SVR4
55#include <compat/svr4/svr4_exec.h>
56#endif
57
58int (*elf_probe_funcs[]) __P((struct proc *, struct exec_package *,
59			      Elf32_Ehdr *, char *, u_long *)) = {
60#ifdef COMPAT_LINUX
61	linux_elf_probe,
62#endif
63#ifdef COMPAT_SVR4
64	svr4_elf_probe,
65#endif
66};
67
68int elf_check_header __P((Elf32_Ehdr *, int));
69int elf_load_file __P((struct proc *, char *, struct exec_vmcmd_set *,
70		       u_long *, struct elf_args *, u_long *));
71
72static void elf_load_psection __P((struct exec_vmcmd_set *,
73	struct vnode *, Elf32_Phdr *, u_long *, u_long *, int *));
74
75#define ELF_ALIGN(a, b) ((a) & ~((b) - 1))
76
77/*
78 * Copy arguments onto the stack in the normal way, but add some
79 * extra information in case of dynamic binding.
80 */
81void *
82elf_copyargs(pack, arginfo, stack, argp)
83	struct exec_package *pack;
84	struct ps_strings *arginfo;
85	void *stack;
86	void *argp;
87{
88	size_t len;
89	AuxInfo ai[ELF_AUX_ENTRIES], *a;
90	struct elf_args *ap;
91
92	stack = copyargs(pack, arginfo, stack, argp);
93	if (!stack)
94		return NULL;
95
96	/*
97	 * Push extra arguments on the stack needed by dynamically
98	 * linked binaries
99	 */
100	if ((ap = (struct elf_args *) pack->ep_emul_arg)) {
101		a = ai;
102
103		a->au_id = AUX_phdr;
104		a->au_v = ap->arg_phaddr;
105		a++;
106
107		a->au_id = AUX_phent;
108		a->au_v = ap->arg_phentsize;
109		a++;
110
111		a->au_id = AUX_phnum;
112		a->au_v = ap->arg_phnum;
113		a++;
114
115		a->au_id = AUX_pagesz;
116		a->au_v = NBPG;
117		a++;
118
119		a->au_id = AUX_base;
120		a->au_v = ap->arg_interp;
121		a++;
122
123		a->au_id = AUX_flags;
124		a->au_v = 0;
125		a++;
126
127		a->au_id = AUX_entry;
128		a->au_v = ap->arg_entry;
129		a++;
130
131		a->au_id = AUX_null;
132		a->au_v = 0;
133		a++;
134
135		free((char *) ap, M_TEMP);
136		len = ELF_AUX_ENTRIES * sizeof (AuxInfo);
137		if (copyout(ai, stack, len))
138			return NULL;
139		stack += len;
140	}
141	return stack;
142}
143
144/*
145 * elf_check_header():
146 *
147 * Check header for validity; return 0 of ok ENOEXEC if error
148 *
149 * XXX machine type needs to be moved to <machine/param.h> so
150 * just one comparison can be done. Unfortunately, there is both
151 * em_486 and em_386, so this would not work on the i386.
152 */
153int
154elf_check_header(eh, type)
155	Elf32_Ehdr *eh;
156	int type;
157{
158
159	if (bcmp(eh->e_ident, Elf32_e_ident, Elf32_e_siz) != 0)
160		return ENOEXEC;
161
162	switch (eh->e_machine) {
163	/* XXX */
164#ifdef i386
165	case Elf32_em_386:
166	case Elf32_em_486:
167#endif
168#ifdef sparc
169	case Elf32_em_sparc:
170#endif
171		break;
172
173	default:
174		return ENOEXEC;
175	}
176
177	if (eh->e_type != type)
178		return ENOEXEC;
179
180	return 0;
181}
182
183/*
184 * elf_load_psection():
185 *
186 * Load a psection at the appropriate address
187 */
188static void
189elf_load_psection(vcset, vp, ph, addr, size, prot)
190	struct exec_vmcmd_set *vcset;
191	struct vnode *vp;
192	Elf32_Phdr *ph;
193	u_long *addr;
194	u_long *size;
195	int *prot;
196{
197	u_long uaddr, msize, rm, rf;
198	long diff, offset;
199
200	/*
201         * If the user specified an address, then we load there.
202         */
203	if (*addr != ELF32_NO_ADDR) {
204		if (ph->p_align > 1) {
205			*addr = ELF_ALIGN(*addr + ph->p_align, ph->p_align);
206			uaddr = ELF_ALIGN(ph->p_vaddr, ph->p_align);
207		} else
208			uaddr = ph->p_vaddr;
209		diff = ph->p_vaddr - uaddr;
210	} else {
211		*addr = uaddr = ph->p_vaddr;
212		if (ph->p_align > 1)
213			*addr = ELF_ALIGN(uaddr, ph->p_align);
214		diff = uaddr - *addr;
215	}
216
217	*prot |= (ph->p_flags & Elf32_pf_r) ? VM_PROT_READ : 0;
218	*prot |= (ph->p_flags & Elf32_pf_w) ? VM_PROT_WRITE : 0;
219	*prot |= (ph->p_flags & Elf32_pf_x) ? VM_PROT_EXECUTE : 0;
220
221	offset = ph->p_offset - diff;
222	*size = ph->p_filesz + diff;
223	msize = ph->p_memsz + diff;
224
225	NEW_VMCMD(vcset, vmcmd_map_readvn, *size, *addr, vp, offset, *prot);
226
227	/*
228         * Check if we need to extend the size of the segment
229         */
230	rm = round_page(*addr + msize);
231	rf = round_page(*addr + *size);
232
233	if (rm != rf) {
234		NEW_VMCMD(vcset, vmcmd_map_zero, rm - rf, rf, NULLVP, 0, *prot);
235		*size = msize;
236	}
237}
238
239/*
240 * elf_read_from():
241 *
242 *	Read from vnode into buffer at offset.
243 */
244int
245elf_read_from(p, vp, off, buf, size)
246	struct vnode *vp;
247	u_long off;
248	struct proc *p;
249	caddr_t buf;
250	int size;
251{
252	int error;
253	int resid;
254
255	if ((error = vn_rdwr(UIO_READ, vp, buf, size,
256			     off, UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred,
257			     &resid, p)) != 0)
258		return error;
259	/*
260         * See if we got all of it
261         */
262	if (resid != 0)
263		return ENOEXEC;
264	return 0;
265}
266
267/*
268 * elf_load_file():
269 *
270 * Load a file (interpreter/library) pointed to by path
271 * [stolen from coff_load_shlib()]. Made slightly generic
272 * so it might be used externally.
273 */
274int
275elf_load_file(p, path, vcset, entry, ap, last)
276	struct proc *p;
277	char *path;
278	struct exec_vmcmd_set *vcset;
279	u_long *entry;
280	struct elf_args	*ap;
281	u_long *last;
282{
283	int error, i;
284	struct nameidata nd;
285	Elf32_Ehdr eh;
286	Elf32_Phdr *ph = NULL;
287	u_long phsize;
288	char *bp = NULL;
289	u_long addr = *last;
290
291	bp = path;
292	/*
293         * 1. open file
294         * 2. read filehdr
295         * 3. map text, data, and bss out of it using VM_*
296         */
297	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, p);
298	if ((error = namei(&nd)) != 0) {
299		return error;
300	}
301	if ((error = elf_read_from(p, nd.ni_vp, 0, (caddr_t) &eh,
302				    sizeof(eh))) != 0)
303		goto bad;
304
305	if ((error = elf_check_header(&eh, Elf32_et_dyn)) != 0)
306		goto bad;
307
308	phsize = eh.e_phnum * sizeof(Elf32_Phdr);
309	ph = (Elf32_Phdr *) malloc(phsize, M_TEMP, M_WAITOK);
310
311	if ((error = elf_read_from(p, nd.ni_vp, eh.e_phoff,
312				    (caddr_t) ph, phsize)) != 0)
313		goto bad;
314
315	/*
316         * Load all the necessary sections
317         */
318	for (i = 0; i < eh.e_phnum; i++) {
319		u_long size = 0;
320		int prot = 0;
321
322		switch (ph[i].p_type) {
323		case Elf32_pt_load:
324			elf_load_psection(vcset, nd.ni_vp, &ph[i], &addr,
325						&size, &prot);
326			/* If entry is within this section it must be text */
327			if (eh.e_entry >= ph[i].p_vaddr &&
328			    eh.e_entry < (ph[i].p_vaddr + size)) {
329				*entry = addr + eh.e_entry;
330				ap->arg_interp = addr;
331			}
332			addr += size;
333			break;
334
335		case Elf32_pt_dynamic:
336		case Elf32_pt_phdr:
337		case Elf32_pt_note:
338			break;
339
340		default:
341			break;
342		}
343	}
344
345bad:
346	if (ph != NULL)
347		free((char *) ph, M_TEMP);
348
349	*last = addr;
350	vrele(nd.ni_vp);
351	return error;
352}
353
354/*
355 * exec_elf_makecmds(): Prepare an Elf binary's exec package
356 *
357 * First, set of the various offsets/lengths in the exec package.
358 *
359 * Then, mark the text image busy (so it can be demand paged) or error
360 * out if this is not possible.  Finally, set up vmcmds for the
361 * text, data, bss, and stack segments.
362 *
363 * XXX no demand paging (yet?)
364 */
365int
366exec_elf_makecmds(p, epp)
367	struct proc *p;
368	struct exec_package *epp;
369{
370	Elf32_Ehdr *eh = epp->ep_hdr;
371	Elf32_Phdr *ph, *pp;
372	Elf32_Addr phdr = 0;
373	int error, i, n, nload;
374	char interp[MAXPATHLEN];
375	u_long pos = 0, phsize;
376
377	if (epp->ep_hdrvalid < sizeof(Elf32_Ehdr))
378		return ENOEXEC;
379
380	if (elf_check_header(eh, Elf32_et_exec))
381		return ENOEXEC;
382
383	/*
384         * check if vnode is in open for writing, because we want to
385         * demand-page out of it.  if it is, don't do it, for various
386         * reasons
387         */
388	if (epp->ep_vp->v_writecount != 0) {
389#ifdef DIAGNOSTIC
390		if (epp->ep_vp->v_flag & VTEXT)
391			panic("exec: a VTEXT vnode has writecount != 0\n");
392#endif
393		return ETXTBSY;
394	}
395	/*
396         * Allocate space to hold all the program headers, and read them
397         * from the file
398         */
399	phsize = eh->e_phnum * sizeof(Elf32_Phdr);
400	ph = (Elf32_Phdr *) malloc(phsize, M_TEMP, M_WAITOK);
401
402	if ((error = elf_read_from(p, epp->ep_vp, eh->e_phoff,
403				    (caddr_t) ph, phsize)) != 0)
404		goto bad;
405
406	epp->ep_tsize = ELF32_NO_ADDR;
407	epp->ep_dsize = ELF32_NO_ADDR;
408
409	interp[0] = '\0';
410
411	for (i = 0; i < eh->e_phnum; i++) {
412		pp = &ph[i];
413		if (pp->p_type == Elf32_pt_interp) {
414			if (pp->p_filesz >= sizeof(interp))
415				goto bad;
416			if ((error = elf_read_from(p, epp->ep_vp, pp->p_offset,
417				      (caddr_t) interp, pp->p_filesz)) != 0)
418				goto bad;
419			break;
420		}
421	}
422
423	/*
424	 * On the same architecture, we may be emulating different systems.
425	 * See which one will accept this executable. This currently only
426	 * applies to Linux and SVR4 on the i386.
427	 *
428	 * Probe functions would normally see if the interpreter (if any)
429	 * exists. Emulation packages may possibly replace the interpreter in
430	 * interp[] with a changed path (/emul/xxx/<path>), and also
431	 * set the ep_emul field in the exec package structure.
432	 */
433	if ((n = sizeof elf_probe_funcs / sizeof elf_probe_funcs[0])) {
434		error = ENOEXEC;
435		for (i = 0; i < n && error; i++)
436			error = elf_probe_funcs[i](p, epp, eh, interp, &pos);
437
438		if (error)
439			goto bad;
440	}
441
442	/*
443         * Load all the necessary sections
444         */
445	for (i = nload = 0; i < eh->e_phnum; i++) {
446		u_long  addr = ELF32_NO_ADDR, size = 0;
447		int prot = 0;
448
449		pp = &ph[i];
450
451		switch (ph[i].p_type) {
452		case Elf32_pt_load:
453			/*
454			 * XXX
455			 * Can handle only 2 sections: text and data
456			 */
457			if (nload++ == 2)
458				goto bad;
459			elf_load_psection(&epp->ep_vmcmds, epp->ep_vp,
460				&ph[i], &addr, &size, &prot);
461			/*
462			 * Decide whether it's text or data by looking
463			 * at the entry point.
464			 */
465			if (eh->e_entry >= addr && eh->e_entry < (addr + size)){
466				epp->ep_taddr = addr;
467				epp->ep_tsize = size;
468			} else {
469				epp->ep_daddr = addr;
470				epp->ep_dsize = size;
471			}
472			break;
473
474		case Elf32_pt_shlib:
475			error = ENOEXEC;
476			goto bad;
477
478		case Elf32_pt_interp:
479			/* Already did this one */
480		case Elf32_pt_dynamic:
481		case Elf32_pt_note:
482			break;
483
484		case Elf32_pt_phdr:
485			/* Note address of program headers (in text segment) */
486			phdr = pp->p_vaddr;
487			break;
488
489		default:
490			/*
491			 * Not fatal, we don't need to understand everything
492			 * :-)
493			 */
494			break;
495		}
496	}
497
498	/*
499	 * If no position to load the interpreter was set by a probe
500	 * function, pick the same address that a non-fixed mmap(0, ..)
501	 * would (i.e. something safely out of the way).
502	 */
503	if (pos == ELF32_NO_ADDR)
504		pos = round_page(epp->ep_daddr + MAXDSIZ);
505
506	/*
507         * Check if we found a dynamically linked binary and arrange to load
508         * it's interpreter
509         */
510	if (interp[0]) {
511		struct elf_args *ap;
512
513		ap = (struct elf_args *) malloc(sizeof(struct elf_args),
514						 M_TEMP, M_WAITOK);
515		if ((error = elf_load_file(p, interp, &epp->ep_vmcmds,
516				&epp->ep_entry, ap, &pos)) != 0) {
517			free((char *) ap, M_TEMP);
518			goto bad;
519		}
520		pos += phsize;
521		ap->arg_phaddr = phdr;
522
523		ap->arg_phentsize = eh->e_phentsize;
524		ap->arg_phnum = eh->e_phnum;
525		ap->arg_entry = eh->e_entry;
526
527		epp->ep_emul_arg = ap;
528	} else
529		epp->ep_entry = eh->e_entry;
530
531	free((char *) ph, M_TEMP);
532	epp->ep_vp->v_flag |= VTEXT;
533	return exec_aout_setup_stack(p, epp);
534
535bad:
536	free((char *) ph, M_TEMP);
537	kill_vmcmds(&epp->ep_vmcmds);
538	return ENOEXEC;
539}
540