Home | History | Annotate | Line # | Download | only in kern
exec_elf.c revision 1.1
      1 /*	$NetBSD: exec_elf.c,v 1.1 1995/06/22 21:29:53 fvdl 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 
     58 int (*elf_probe_funcs[])() = {
     59 #ifdef COMPAT_SVR4
     60 	svr4_elf_probe,
     61 #endif
     62 #ifdef COMPAT_LINUX
     63 	linux_elf_probe
     64 #endif
     65 };
     66 
     67 static int elf_set_segment __P((struct exec_package *, u_long, u_long,
     68 	int));
     69 static int elf_read_from __P((struct proc *, struct vnode *, u_long,
     70 	caddr_t, int));
     71 static void elf_load_psection __P((struct exec_vmcmd_set *,
     72 	struct vnode *, Elf32_Phdr *, u_long *, u_long *, int *));
     73 
     74 #define ELF_ALIGN(a, b) ((a) & ~((b) - 1))
     75 #define ELF_AUX_ARGSIZ (sizeof(AuxInfo) * 8 / sizeof(char *))
     76 
     77 /*
     78  * Copy arguments onto the stack in the normal way, but add some
     79  * extra information in case of dynamic binding.
     80  */
     81 void *
     82 elf_copyargs(pack, arginfo, stack, argp)
     83 	struct exec_package *pack;
     84 	struct ps_strings *arginfo;
     85 	void *stack;
     86 	void *argp;
     87 {
     88 	char **cpp = stack;
     89 	char *dp, *sp;
     90 	size_t len;
     91 	void *nullp = NULL;
     92 	int argc = arginfo->ps_nargvstr;
     93 	int envc = arginfo->ps_nenvstr;
     94 	AuxInfo *a;
     95 	struct elf_args *ap;
     96 
     97 	if (copyout(&argc, cpp++, sizeof(argc)))
     98 		return NULL;
     99 
    100 	dp = (char *) (cpp + argc + envc + 2 + pack->ep_emul->e_arglen);
    101 	sp = argp;
    102 
    103 	/* XXX don't copy them out, remap them! */
    104 	arginfo->ps_argvstr = cpp; /* remember location of argv for later */
    105 
    106 	for (; --argc >= 0; sp += len, dp += len)
    107 		if (copyout(&dp, cpp++, sizeof(dp)) ||
    108 		    copyoutstr(sp, dp, ARG_MAX, &len))
    109 			return NULL;
    110 
    111 	if (copyout(&nullp, cpp++, sizeof(nullp)))
    112 		return NULL;
    113 
    114 	arginfo->ps_envstr = cpp; /* remember location of envp for later */
    115 
    116 	for (; --envc >= 0; sp += len, dp += len)
    117 		if (copyout(&dp, cpp++, sizeof(dp)) ||
    118 		    copyoutstr(sp, dp, ARG_MAX, &len))
    119 			return NULL;
    120 
    121 	if (copyout(&nullp, cpp++, sizeof(nullp)))
    122 		return NULL;
    123 
    124 	/*
    125 	 * Push extra arguments on the stack needed by dynamically
    126 	 * linked binaries
    127 	 */
    128 	a = (AuxInfo *) cpp;
    129 	if ((ap = (struct elf_args *) pack->ep_emul_arg)) {
    130 
    131 		a->au_id = AUX_phdr;
    132 		a->au_v = ap->arg_phaddr;
    133 		a++;
    134 
    135 		a->au_id = AUX_phent;
    136 		a->au_v = ap->arg_phentsize;
    137 		a++;
    138 
    139 		a->au_id = AUX_phnum;
    140 		a->au_v = ap->arg_phnum;
    141 		a++;
    142 
    143 		a->au_id = AUX_pagesz;
    144 		a->au_v = NBPG;
    145 		a++;
    146 
    147 		a->au_id = AUX_base;
    148 		a->au_v = ap->arg_interp;
    149 		a++;
    150 
    151 		a->au_id = AUX_flags;
    152 		a->au_v = 0;
    153 		a++;
    154 
    155 		a->au_id = AUX_entry;
    156 		a->au_v = ap->arg_entry;
    157 		a++;
    158 
    159 		a->au_id = AUX_null;
    160 		a->au_v = 0;
    161 		a++;
    162 
    163 		free((char *) ap, M_TEMP);
    164 	}
    165 	return a;
    166 }
    167 
    168 /*
    169  * elf_check_header():
    170  *
    171  * Check header for validity; return 0 of ok ENOEXEC if error
    172  *
    173  * XXX machine type needs to be moved to <machine/param.h> so
    174  * just one comparison can be done. Unfortunately, there is both
    175  * em_486 and em_386, so this would not work on the i386.
    176  */
    177 int
    178 elf_check_header(eh, type)
    179 	Elf32_Ehdr *eh;
    180 	int type;
    181 {
    182 #ifdef sparc
    183   /* #$%@#$%@#$%! */
    184 # define memcmp bcmp
    185 #endif
    186 	if (memcmp(eh->e_ident, Elf32_e_ident, Elf32_e_siz) != 0)
    187 		return ENOEXEC;
    188 
    189 	switch (eh->e_machine) {
    190 	/* XXX */
    191 #ifdef i386
    192 	case Elf32_em_386:
    193 	case Elf32_em_486:
    194 #endif
    195 #ifdef sparc
    196 	case Elf32_em_sparc:
    197 #endif
    198 		break;
    199 
    200 	default:
    201 		return ENOEXEC;
    202 	}
    203 
    204 	if (eh->e_type != type)
    205 		return ENOEXEC;
    206 
    207 	return 0;
    208 }
    209 
    210 /*
    211  * elf_load_psection():
    212  *
    213  * Load a psection at the appropriate address
    214  */
    215 static void
    216 elf_load_psection(vcset, vp, ph, addr, size, prot)
    217 	struct exec_vmcmd_set *vcset;
    218 	struct vnode *vp;
    219 	Elf32_Phdr *ph;
    220 	u_long *addr;
    221 	u_long *size;
    222 	int *prot;
    223 {
    224 	u_long uaddr, msize, rm, rf;
    225 	long diff, offset;
    226 
    227 	/*
    228          * If the user specified an address, then we load there.
    229          */
    230 	if (*addr != ELF32_NO_ADDR) {
    231 		if (ph->p_align > 1) {
    232 			*addr = ELF_ALIGN(*addr + ph->p_align, ph->p_align);
    233 			uaddr = ELF_ALIGN(ph->p_vaddr, ph->p_align);
    234 		} else
    235 			uaddr = ph->p_vaddr;
    236 		diff = ph->p_vaddr - uaddr;
    237 	} else {
    238 		*addr = uaddr = ph->p_vaddr;
    239 		if (ph->p_align > 1)
    240 			*addr = ELF_ALIGN(uaddr, ph->p_align);
    241 		diff = uaddr - *addr;
    242 	}
    243 
    244 	*prot |= (ph->p_flags & Elf32_pf_r) ? VM_PROT_READ : 0;
    245 	*prot |= (ph->p_flags & Elf32_pf_w) ? VM_PROT_WRITE : 0;
    246 	*prot |= (ph->p_flags & Elf32_pf_x) ? VM_PROT_EXECUTE : 0;
    247 
    248 	offset = ph->p_offset - diff;
    249 	*size = ph->p_filesz + diff;
    250 	msize = ph->p_memsz + diff;
    251 
    252 	NEW_VMCMD(vcset, vmcmd_map_readvn, *size, *addr, vp, offset, *prot);
    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_VMCMD(vcset, vmcmd_map_zero, rm - rf, rf, NULLVP, 0, *prot);
    262 		*size = msize;
    263 	}
    264 }
    265 
    266 /*
    267  * elf_set_segment():
    268  *
    269  * Decide if the segment is text or data, depending on the protection
    270  * and set it appropriately
    271  */
    272 static int
    273 elf_set_segment(epp, vaddr, size, prot)
    274 	struct exec_package *epp;
    275 	u_long vaddr;
    276 	u_long size;
    277 	int prot;
    278 {
    279 	/*
    280          * Kludge: Unfortunately the current implementation of
    281          * exec package assumes a single text and data segment.
    282          * In Elf we can have more, but here we limit ourselves
    283          * to two and hope :-(
    284          * We also assume that the text is r-x, and data is rwx or rw-.
    285          */
    286 	switch (prot) {
    287 	case (VM_PROT_READ | VM_PROT_EXECUTE):
    288 		if (epp->ep_tsize != ELF32_NO_ADDR)
    289 			return ENOEXEC;
    290 		epp->ep_taddr = vaddr;
    291 		epp->ep_tsize = size;
    292 		break;
    293 
    294 	case (VM_PROT_READ | VM_PROT_WRITE):
    295 	case (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE):
    296 		if (epp->ep_dsize != ELF32_NO_ADDR)
    297 			return ENOEXEC;
    298 		epp->ep_daddr = vaddr;
    299 		epp->ep_dsize = size;
    300 		break;
    301 
    302 	default:
    303 		return ENOEXEC;
    304 	}
    305 	return 0;
    306 }
    307 
    308 /*
    309  * elf_read_from():
    310  *
    311  *	Read from vnode into buffer at offset.
    312  */
    313 static int
    314 elf_read_from(p, vp, off, buf, size)
    315 	struct vnode *vp;
    316 	u_long off;
    317 	struct proc *p;
    318 	caddr_t buf;
    319 	int size;
    320 {
    321 	int error;
    322 	int resid;
    323 
    324 	if ((error = vn_rdwr(UIO_READ, vp, buf, size,
    325 			     off, UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred,
    326 			     &resid, p)) != 0)
    327 		return error;
    328 	/*
    329          * See if we got all of it
    330          */
    331 	if (resid != 0)
    332 		return error;
    333 	return 0;
    334 }
    335 
    336 /*
    337  * elf_load_file():
    338  *
    339  * Load a file (interpreter/library) pointed to by path
    340  * [stolen from coff_load_shlib()]. Made slightly generic
    341  * so it might be used externally.
    342  */
    343 int
    344 elf_load_file(p, path, vcset, entry, ap, last)
    345 	struct proc *p;
    346 	char *path;
    347 	struct exec_vmcmd_set *vcset;
    348 	u_long *entry;
    349 	struct elf_args	*ap;
    350 	u_long *last;
    351 {
    352 	int error, i;
    353 	struct nameidata nd;
    354 	Elf32_Ehdr eh;
    355 	Elf32_Phdr *ph = NULL;
    356 	u_long phsize;
    357 	char *bp = NULL;
    358 	u_long addr = *last;
    359 
    360 	bp = path;
    361 	/*
    362          * 1. open file
    363          * 2. read filehdr
    364          * 3. map text, data, and bss out of it using VM_*
    365          */
    366 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, p);
    367 	if ((error = namei(&nd)) != 0) {
    368 		return error;
    369 	}
    370 	if ((error = elf_read_from(p, nd.ni_vp, 0, (caddr_t) &eh,
    371 				    sizeof(eh))) != 0)
    372 		goto bad;
    373 
    374 	if ((error = elf_check_header(&eh, Elf32_et_dyn)) != 0)
    375 		goto bad;
    376 
    377 	phsize = eh.e_phnum * sizeof(Elf32_Phdr);
    378 	ph = (Elf32_Phdr *) malloc(phsize, M_TEMP, M_WAITOK);
    379 
    380 	if ((error = elf_read_from(p, nd.ni_vp, eh.e_phoff,
    381 				    (caddr_t) ph, phsize)) != 0)
    382 		goto bad;
    383 
    384 	/*
    385          * Load all the necessary sections
    386          */
    387 	for (i = 0; i < eh.e_phnum; i++) {
    388 		u_long size = 0;
    389 		int prot = 0;
    390 
    391 		switch (ph[i].p_type) {
    392 		case Elf32_pt_load:
    393 			elf_load_psection(vcset, nd.ni_vp, &ph[i], &addr,
    394 						&size, &prot);
    395 			/* Assume that the text segment is r-x only */
    396 			if ((prot & PROT_WRITE) == 0) {
    397 				*entry = addr + eh.e_entry;
    398 				ap->arg_interp = addr;
    399 			}
    400 			addr += size;
    401 			break;
    402 
    403 		case Elf32_pt_dynamic:
    404 		case Elf32_pt_phdr:
    405 		case Elf32_pt_note:
    406 			break;
    407 
    408 		default:
    409 			break;
    410 		}
    411 	}
    412 
    413 bad:
    414 	if (ph != NULL)
    415 		free((char *) ph, M_TEMP);
    416 
    417 	*last = addr;
    418 	vrele(nd.ni_vp);
    419 	return error;
    420 }
    421 
    422 /*
    423  * exec_elf_makecmds(): Prepare an Elf binary's exec package
    424  *
    425  * First, set of the various offsets/lengths in the exec package.
    426  *
    427  * Then, mark the text image busy (so it can be demand paged) or error
    428  * out if this is not possible.  Finally, set up vmcmds for the
    429  * text, data, bss, and stack segments.
    430  *
    431  * XXX no demand paging (yet?)
    432  */
    433 int
    434 exec_elf_makecmds(p, epp)
    435 	struct proc *p;
    436 	struct exec_package *epp;
    437 {
    438 	Elf32_Ehdr *eh = epp->ep_hdr;
    439 	Elf32_Phdr *ph, *pp;
    440 	int error, i, n;
    441 	char interp[MAXPATHLEN];
    442 	u_long pos = 0, phsize;
    443 
    444 	if (epp->ep_hdrvalid < sizeof(Elf32_Ehdr))
    445 		return ENOEXEC;
    446 
    447 	if (elf_check_header(eh, Elf32_et_exec))
    448 		return ENOEXEC;
    449 
    450 	/*
    451          * check if vnode is in open for writing, because we want to
    452          * demand-page out of it.  if it is, don't do it, for various
    453          * reasons
    454          */
    455 	if (epp->ep_vp->v_writecount != 0) {
    456 #ifdef DIAGNOSTIC
    457 		if (epp->ep_vp->v_flag & VTEXT)
    458 			panic("exec: a VTEXT vnode has writecount != 0\n");
    459 #endif
    460 		return ETXTBSY;
    461 	}
    462 	/*
    463          * Allocate space to hold all the program headers, and read them
    464          * from the file
    465          */
    466 	phsize = eh->e_phnum * sizeof(Elf32_Phdr);
    467 	ph = (Elf32_Phdr *) malloc(phsize, M_TEMP, M_WAITOK);
    468 
    469 	if ((error = elf_read_from(p, epp->ep_vp, eh->e_phoff,
    470 				    (caddr_t) ph, phsize)) != 0)
    471 		goto bad;
    472 
    473 	epp->ep_tsize = ELF32_NO_ADDR;
    474 	epp->ep_dsize = ELF32_NO_ADDR;
    475 
    476 	interp[0] = '\0';
    477 
    478 	for (i = 0; i < eh->e_phnum; i++) {
    479 		pp = &ph[i];
    480 		if (pp->p_type == Elf32_pt_interp) {
    481 			if (pp->p_filesz >= sizeof(interp))
    482 				goto bad;
    483 			if ((error = elf_read_from(p, epp->ep_vp, pp->p_offset,
    484 				      (caddr_t) interp, pp->p_filesz)) != 0)
    485 				goto bad;
    486 			break;
    487 		}
    488 	}
    489 
    490 	/*
    491 	 * On the same architecture, we may be emulating different systems.
    492 	 * See which one will accept this executable. This currently only
    493 	 * applies to Linux and SVR4 on the i386.
    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>), and also
    498 	 * set the ep_emul field in the exec package structure.
    499 	 */
    500 	if ((n = sizeof elf_probe_funcs / sizeof elf_probe_funcs[0])) {
    501 		error = ENOEXEC;
    502 		for (i = 0; i < n && error; i++)
    503 			error = elf_probe_funcs[i](p, epp, interp, &pos);
    504 
    505 		if (error)
    506 			goto bad;
    507 	}
    508 
    509 	/*
    510          * Load all the necessary sections
    511          */
    512 	for (i = 0; i < eh->e_phnum; i++) {
    513 		u_long  addr = ELF32_NO_ADDR, size = 0;
    514 		int prot = 0;
    515 
    516 		pp = &ph[i];
    517 
    518 		switch (ph[i].p_type) {
    519 		case Elf32_pt_load:
    520 			elf_load_psection(&epp->ep_vmcmds, epp->ep_vp,
    521 				&ph[i], &addr, &size, &prot);
    522 			if ((error = elf_set_segment(epp, addr, size,
    523 						      prot)) != 0)
    524 				goto bad;
    525 			break;
    526 
    527 		case Elf32_pt_shlib:
    528 			error = ENOEXEC;
    529 			goto bad;
    530 
    531 		case Elf32_pt_interp:
    532 			/* Already did this one */
    533 		case Elf32_pt_dynamic:
    534 		case Elf32_pt_phdr:
    535 		case Elf32_pt_note:
    536 			break;
    537 
    538 		default:
    539 			/*
    540 			 * Not fatal, we don't need to understand everything
    541 			 * :-)
    542 			 */
    543 			break;
    544 		}
    545 	}
    546 
    547 	/*
    548          * Check if we found a dynamically linked binary and arrange to load
    549          * it's interpreter
    550          */
    551 	if (interp[0]) {
    552 		struct elf_args *ap;
    553 
    554 		ap = (struct elf_args *) malloc(sizeof(struct elf_args),
    555 						 M_TEMP, M_WAITOK);
    556 		if ((error = elf_load_file(p, interp, &epp->ep_vmcmds,
    557 				&epp->ep_entry, ap, &pos)) != 0) {
    558 			free((char *) ap, M_TEMP);
    559 			goto bad;
    560 		}
    561 		/* Arrange to load the program headers. */
    562 		pos = ELF_ALIGN(pos + NBPG, NBPG);
    563 		ap->arg_phaddr = pos;
    564 		NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, phsize,
    565 			  pos, epp->ep_vp, eh->e_phoff,
    566 			  VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
    567 		pos += phsize;
    568 
    569 		ap->arg_phentsize = eh->e_phentsize;
    570 		ap->arg_phnum = eh->e_phnum;
    571 		ap->arg_entry = eh->e_entry;
    572 
    573 		epp->ep_emul_arg = ap;
    574 	} else
    575 		epp->ep_entry = eh->e_entry;
    576 
    577 	free((char *) ph, M_TEMP);
    578 	epp->ep_vp->v_flag |= VTEXT;
    579 	return exec_aout_setup_stack(p, epp);
    580 
    581 bad:
    582 	free((char *) ph, M_TEMP);
    583 	kill_vmcmds(&epp->ep_vmcmds);
    584 	return ENOEXEC;
    585 }
    586