Home | History | Annotate | Line # | Download | only in common
linux_exec_elf32.c revision 1.59
      1 /*	$NetBSD: linux_exec_elf32.c,v 1.59 2002/11/13 15:16:29 jdolecek Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1995, 1998, 2000, 2001 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, Frank van der Linden, Eric Haszlakiewicz and
      9  * Emmanuel Dreyfus.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  * 3. All advertising materials mentioning features or use of this software
     20  *    must display the following acknowledgement:
     21  *	This product includes software developed by the NetBSD
     22  *	Foundation, Inc. and its contributors.
     23  * 4. Neither the name of The NetBSD Foundation nor the names of its
     24  *    contributors may be used to endorse or promote products derived
     25  *    from this software without specific prior written permission.
     26  *
     27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     37  * POSSIBILITY OF SUCH DAMAGE.
     38  */
     39 
     40 /*
     41  * based on exec_aout.c, sunos_exec.c and svr4_exec.c
     42  */
     43 
     44 #include <sys/cdefs.h>
     45 __KERNEL_RCSID(0, "$NetBSD: linux_exec_elf32.c,v 1.59 2002/11/13 15:16:29 jdolecek Exp $");
     46 
     47 #ifndef ELFSIZE
     48 /* XXX should die */
     49 #define	ELFSIZE		32
     50 #endif
     51 
     52 #include <sys/param.h>
     53 #include <sys/systm.h>
     54 #include <sys/kernel.h>
     55 #include <sys/proc.h>
     56 #include <sys/malloc.h>
     57 #include <sys/namei.h>
     58 #include <sys/vnode.h>
     59 #include <sys/mount.h>
     60 #include <sys/exec.h>
     61 #include <sys/exec_elf.h>
     62 #include <sys/stat.h>
     63 
     64 #include <sys/mman.h>
     65 #include <sys/syscallargs.h>
     66 
     67 #include <machine/cpu.h>
     68 #include <machine/reg.h>
     69 
     70 #include <compat/linux/common/linux_types.h>
     71 #include <compat/linux/common/linux_signal.h>
     72 #include <compat/linux/common/linux_util.h>
     73 #include <compat/linux/common/linux_exec.h>
     74 #include <compat/linux/common/linux_machdep.h>
     75 
     76 #include <compat/linux/linux_syscallargs.h>
     77 #include <compat/linux/linux_syscall.h>
     78 
     79 static int ELFNAME2(linux,signature) __P((struct proc *, struct exec_package *,
     80 	Elf_Ehdr *, char *));
     81 #ifdef LINUX_GCC_SIGNATURE
     82 static int ELFNAME2(linux,gcc_signature) __P((struct proc *p,
     83 	struct exec_package *, Elf_Ehdr *));
     84 #endif
     85 #ifdef LINUX_ATEXIT_SIGNATURE
     86 static int ELFNAME2(linux,atexit_signature) __P((struct proc *p,
     87 	struct exec_package *, Elf_Ehdr *));
     88 #endif
     89 
     90 #ifdef DEBUG_LINUX
     91 #define DPRINTF(a)	uprintf a
     92 #else
     93 #define DPRINTF(a)
     94 #endif
     95 
     96 #ifdef LINUX_ATEXIT_SIGNATURE
     97 /*
     98  * On the PowerPC, statically linked Linux binaries are not recognized
     99  * by linux_signature nor by linux_gcc_signature. Fortunately, thoses
    100  * binaries features a __libc_atexit ELF section. We therefore assume we
    101  * have a Linux binary if we find this section.
    102  */
    103 static int
    104 ELFNAME2(linux,atexit_signature)(p, epp, eh)
    105 	struct proc *p;
    106 	struct exec_package *epp;
    107 	Elf_Ehdr *eh;
    108 {
    109 	size_t shsize;
    110 	int	strndx;
    111 	size_t i;
    112 	static const char signature[] = "__libc_atexit";
    113 	char* strtable;
    114 	Elf_Shdr *sh;
    115 
    116 	int error;
    117 
    118 	/*
    119 	 * load the section header table
    120 	 */
    121 	shsize = eh->e_shnum * sizeof(Elf_Shdr);
    122 	sh = (Elf_Shdr *) malloc(shsize, M_TEMP, M_WAITOK);
    123 	error = exec_read_from(p, epp->ep_vp, eh->e_shoff, sh, shsize);
    124 	if (error)
    125 		goto out;
    126 
    127 	/*
    128 	 * Now let's find the string table. If it does not exists, give up.
    129 	 */
    130 	strndx = (int)(eh->e_shstrndx);
    131 	if (strndx == SHN_UNDEF) {
    132 		error = ENOEXEC;
    133 		goto out;
    134 	}
    135 
    136 	/*
    137 	 * strndx is the index in section header table of the string table
    138 	 * section get the whole string table in strtable, and then we get access to the names
    139 	 * s->sh_name is the offset of the section name in strtable.
    140 	 */
    141 	strtable = malloc(sh[strndx].sh_size, M_TEMP, M_WAITOK);
    142 	error = exec_read_from(p, epp->ep_vp, sh[strndx].sh_offset, strtable,
    143 	    sh[strndx].sh_size);
    144 	if (error)
    145 		goto out;
    146 
    147 	for (i = 0; i < eh->e_shnum; i++) {
    148 		Elf_Shdr *s = &sh[i];
    149 		if (!memcmp((void*)(&(strtable[s->sh_name])), signature,
    150 				sizeof(signature))) {
    151 			DPRINTF(("linux_atexit_sig=%s\n",
    152 			    &(strtable[s->sh_name])));
    153 			error = 0;
    154 			goto out;
    155 		}
    156 	}
    157 	error = ENOEXEC;
    158 
    159 out:
    160 	free(sh, M_TEMP);
    161 	free(strtable, M_TEMP);
    162 	return (error);
    163 }
    164 #endif
    165 
    166 #ifdef LINUX_GCC_SIGNATURE
    167 /*
    168  * Take advantage of the fact that all the linux binaries are compiled
    169  * with gcc, and gcc sticks in the comment field a signature. Note that
    170  * on SVR4 binaries, the gcc signature will follow the OS name signature,
    171  * that will not be a problem. We don't bother to read in the string table,
    172  * but we check all the progbits headers.
    173  *
    174  * XXX This only works in the i386.  On the alpha (at least)
    175  * XXX we have the same gcc signature which incorrectly identifies
    176  * XXX NetBSD binaries as Linux.
    177  */
    178 static int
    179 ELFNAME2(linux,gcc_signature)(p, epp, eh)
    180 	struct proc *p;
    181 	struct exec_package *epp;
    182 	Elf_Ehdr *eh;
    183 {
    184 	size_t shsize;
    185 	size_t i;
    186 	static const char signature[] = "\0GCC: (GNU) ";
    187 	char buf[sizeof(signature) - 1];
    188 	Elf_Shdr *sh;
    189 	int error;
    190 
    191 	shsize = eh->e_shnum * sizeof(Elf_Shdr);
    192 	sh = (Elf_Shdr *) malloc(shsize, M_TEMP, M_WAITOK);
    193 	error = exec_read_from(p, epp->ep_vp, eh->e_shoff, sh, shsize);
    194 	if (error)
    195 		goto out;
    196 
    197 	for (i = 0; i < eh->e_shnum; i++) {
    198 		Elf_Shdr *s = &sh[i];
    199 
    200 		/*
    201 		 * Identify candidates for the comment header;
    202 		 * Header cannot have a load address, or flags and
    203 		 * it must be large enough.
    204 		 */
    205 		if (s->sh_type != SHT_PROGBITS ||
    206 		    s->sh_addr != 0 ||
    207 		    s->sh_flags != 0 ||
    208 		    s->sh_size < sizeof(signature) - 1)
    209 			continue;
    210 
    211 		error = exec_read_from(p, epp->ep_vp, s->sh_offset, buf,
    212 		    sizeof(signature) - 1);
    213 		if (error)
    214 			continue;
    215 
    216 		/*
    217 		 * error is 0, if the signatures match we are done.
    218 		 */
    219 		DPRINTF(("linux_gcc_sig: sig=%s\n", buf));
    220 		if (!memcmp(buf, signature, sizeof(signature) - 1)) {
    221 			error = 0;
    222 			goto out;
    223 		}
    224 	}
    225 	error = ENOEXEC;
    226 
    227 out:
    228 	free(sh, M_TEMP);
    229 	return (error);
    230 }
    231 #endif
    232 
    233 static int
    234 ELFNAME2(linux,signature)(p, epp, eh, itp)
    235 	struct proc *p;
    236 	struct exec_package *epp;
    237 	Elf_Ehdr *eh;
    238 	char *itp;
    239 {
    240 	size_t i;
    241 	Elf_Phdr *ph;
    242 	size_t phsize;
    243 	int error;
    244 	static const char linux[] = "Linux";
    245 
    246 	if (eh->e_ident[EI_OSABI] == 3 ||
    247 	    memcmp(&eh->e_ident[EI_ABIVERSION], linux, sizeof(linux)) == 0)
    248 		return 0;
    249 
    250 	phsize = eh->e_phnum * sizeof(Elf_Phdr);
    251 	ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK);
    252 	error = exec_read_from(p, epp->ep_vp, eh->e_phoff, ph, phsize);
    253 	if (error)
    254 		goto out;
    255 
    256 	for (i = 0; i < eh->e_phnum; i++) {
    257 		Elf_Phdr *ephp = &ph[i];
    258 		Elf_Nhdr *np;
    259 		u_int32_t *abi;
    260 
    261 		if (ephp->p_type != PT_NOTE ||
    262 		    ephp->p_filesz > 1024 ||
    263 		    ephp->p_filesz < sizeof(Elf_Nhdr) + 20)
    264 			continue;
    265 
    266 		np = (Elf_Nhdr *)malloc(ephp->p_filesz, M_TEMP, M_WAITOK);
    267 		error = exec_read_from(p, epp->ep_vp, ephp->p_offset, np,
    268 		    ephp->p_filesz);
    269 		if (error)
    270 			goto next;
    271 
    272 		if (np->n_type != ELF_NOTE_TYPE_ABI_TAG ||
    273 		    np->n_namesz != ELF_NOTE_ABI_NAMESZ ||
    274 		    np->n_descsz != ELF_NOTE_ABI_DESCSZ ||
    275 		    memcmp((caddr_t)(np + 1), ELF_NOTE_ABI_NAME,
    276 		    ELF_NOTE_ABI_NAMESZ))
    277 			goto next;
    278 
    279 		/* Make sure the OS is Linux. */
    280 		abi = (u_int32_t *)((caddr_t)np + sizeof(Elf_Nhdr) +
    281 		    np->n_namesz);
    282 		if (abi[0] == ELF_NOTE_ABI_OS_LINUX)
    283 			error = 0;
    284 		else
    285 			error = ENOEXEC;
    286 		free(np, M_TEMP);
    287 		goto out;
    288 
    289 	next:
    290 		free(np, M_TEMP);
    291 		continue;
    292 	}
    293 
    294 	/* Check for certain intepreter names. */
    295 	if (itp[0]) {
    296 		if (!strncmp(itp, "/lib/ld-linux", 13) ||
    297 		    !strncmp(itp, "/lib/ld.so.", 11))
    298 			error = 0;
    299 		else
    300 			error = ENOEXEC;
    301 		goto out;
    302 	}
    303 
    304 	error = ENOEXEC;
    305 out:
    306 	free(ph, M_TEMP);
    307 	return (error);
    308 }
    309 
    310 int
    311 ELFNAME2(linux,probe)(p, epp, eh, itp, pos)
    312 	struct proc *p;
    313 	struct exec_package *epp;
    314 	void *eh;
    315 	char *itp;
    316 	vaddr_t *pos;
    317 {
    318 	const char *bp;
    319 	int error;
    320 	size_t len;
    321 
    322 	if (((error = ELFNAME2(linux,signature)(p, epp, eh, itp)) != 0) &&
    323 #ifdef LINUX_GCC_SIGNATURE
    324 	    ((error = ELFNAME2(linux,gcc_signature)(p, epp, eh)) != 0) &&
    325 #endif
    326 #ifdef LINUX_ATEXIT_SIGNATURE
    327 	    ((error = ELFNAME2(linux,atexit_signature)(p, epp, eh)) != 0) &&
    328 #endif
    329 	    1)
    330 			return error;
    331 
    332 	if (itp[0]) {
    333 		if ((error = emul_find(p, NULL, epp->ep_esch->es_emul->e_path,
    334 		    itp, &bp, 0)))
    335 			return error;
    336 		if ((error = copystr(bp, itp, MAXPATHLEN, &len)))
    337 			return error;
    338 		free((void *)bp, M_TEMP);
    339 	}
    340 	*pos = ELF_NO_ADDR;
    341 	DPRINTF(("linux_probe: returning 0\n"));
    342 	return 0;
    343 }
    344 
    345 #ifndef LINUX_MACHDEP_ELF_COPYARGS
    346 /*
    347  * Copy arguments onto the stack in the normal way, but add some
    348  * extra information in case of dynamic binding.
    349  */
    350 int
    351 ELFNAME2(linux,copyargs)(struct proc *p, struct exec_package *pack,
    352     struct ps_strings *arginfo, char **stackp, void *argp)
    353 {
    354 	size_t len;
    355 	AuxInfo ai[LINUX_ELF_AUX_ENTRIES], *a;
    356 	struct elf_args *ap;
    357 	int error;
    358 	struct vattr *vap;
    359 
    360 	if ((error = copyargs(p, pack, arginfo, stackp, argp)) != 0)
    361 		return error;
    362 
    363 	a = ai;
    364 
    365 	/*
    366 	 * Push extra arguments used by glibc on the stack.
    367 	 */
    368 
    369 	a->a_type = AT_PAGESZ;
    370 	a->a_v = PAGE_SIZE;
    371 	a++;
    372 
    373 	if ((ap = (struct elf_args *)pack->ep_emul_arg)) {
    374 
    375 		a->a_type = AT_PHDR;
    376 		a->a_v = ap->arg_phaddr;
    377 		a++;
    378 
    379 		a->a_type = AT_PHENT;
    380 		a->a_v = ap->arg_phentsize;
    381 		a++;
    382 
    383 		a->a_type = AT_PHNUM;
    384 		a->a_v = ap->arg_phnum;
    385 		a++;
    386 
    387 		a->a_type = AT_BASE;
    388 		a->a_v = ap->arg_interp;
    389 		a++;
    390 
    391 		a->a_type = AT_FLAGS;
    392 		a->a_v = 0;
    393 		a++;
    394 
    395 		a->a_type = AT_ENTRY;
    396 		a->a_v = ap->arg_entry;
    397 		a++;
    398 
    399 		free(pack->ep_emul_arg, M_TEMP);
    400 		pack->ep_emul_arg = NULL;
    401 	}
    402 
    403 	/* Linux-specific items */
    404 	a->a_type = LINUX_AT_CLKTCK;
    405 	a->a_v = hz;
    406 	a++;
    407 
    408 	vap = pack->ep_vap;
    409 
    410 	a->a_type = LINUX_AT_UID;
    411 	a->a_v = p->p_cred->p_ruid;
    412 	a++;
    413 
    414 	a->a_type = LINUX_AT_EUID;
    415 	if (vap->va_mode & S_ISUID)
    416 		a->a_v = vap->va_uid;
    417 	else
    418 		a->a_v = p->p_ucred->cr_uid;
    419 	a++;
    420 
    421 	a->a_type = LINUX_AT_GID;
    422 	a->a_v = p->p_cred->p_rgid;
    423 	a++;
    424 
    425 	a->a_type = LINUX_AT_EGID;
    426 	if (vap->va_mode & S_ISGID)
    427 		a->a_v = vap->va_gid;
    428 	else
    429 		a->a_v = p->p_ucred->cr_gid;
    430 	a++;
    431 
    432 	a->a_type = AT_NULL;
    433 	a->a_v = 0;
    434 	a++;
    435 
    436 	len = (a - ai) * sizeof(AuxInfo);
    437 	if ((error = copyout(ai, *stackp, len)) != 0)
    438 		return error;
    439 	*stackp += len;
    440 
    441 	return 0;
    442 }
    443 #endif /* !LINUX_MACHDEP_ELF_COPYARGS */
    444