1*f7ac1bd3Serh /* $NetBSD: linux_exec_elf32.c,v 1.31 1998/10/01 03:11:33 erh Exp $ */ 28fb507a3Schristos 38fb507a3Schristos /*- 4*f7ac1bd3Serh * Copyright (c) 1998 The NetBSD Foundation, Inc. 58fb507a3Schristos * All rights reserved. 68fb507a3Schristos * 78fb507a3Schristos * This code is derived from software contributed to The NetBSD Foundation 8*f7ac1bd3Serh * by Eric Haszlakiewicz. 9*f7ac1bd3Serh * 10*f7ac1bd3Serh * This code is derived from software contributed to The NetBSD Foundation 118fb507a3Schristos * by Christos Zoulas. 128fb507a3Schristos * 138fb507a3Schristos * Redistribution and use in source and binary forms, with or without 148fb507a3Schristos * modification, are permitted provided that the following conditions 158fb507a3Schristos * are met: 168fb507a3Schristos * 1. Redistributions of source code must retain the above copyright 178fb507a3Schristos * notice, this list of conditions and the following disclaimer. 188fb507a3Schristos * 2. Redistributions in binary form must reproduce the above copyright 198fb507a3Schristos * notice, this list of conditions and the following disclaimer in the 208fb507a3Schristos * documentation and/or other materials provided with the distribution. 218fb507a3Schristos * 3. All advertising materials mentioning features or use of this software 228fb507a3Schristos * must display the following acknowledgement: 238fb507a3Schristos * This product includes software developed by the NetBSD 248fb507a3Schristos * Foundation, Inc. and its contributors. 258fb507a3Schristos * 4. Neither the name of The NetBSD Foundation nor the names of its 268fb507a3Schristos * contributors may be used to endorse or promote products derived 278fb507a3Schristos * from this software without specific prior written permission. 288fb507a3Schristos * 298fb507a3Schristos * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 308fb507a3Schristos * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 318fb507a3Schristos * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 328fb507a3Schristos * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 338fb507a3Schristos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 348fb507a3Schristos * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 358fb507a3Schristos * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 368fb507a3Schristos * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 378fb507a3Schristos * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 388fb507a3Schristos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 398fb507a3Schristos * POSSIBILITY OF SUCH DAMAGE. 408fb507a3Schristos */ 413bf459f3Sfvdl 423bf459f3Sfvdl /* 433bf459f3Sfvdl * Copyright (c) 1995 Frank van der Linden 443bf459f3Sfvdl * All rights reserved. 453bf459f3Sfvdl * 463bf459f3Sfvdl * Redistribution and use in source and binary forms, with or without 473bf459f3Sfvdl * modification, are permitted provided that the following conditions 483bf459f3Sfvdl * are met: 493bf459f3Sfvdl * 1. Redistributions of source code must retain the above copyright 503bf459f3Sfvdl * notice, this list of conditions and the following disclaimer. 513bf459f3Sfvdl * 2. Redistributions in binary form must reproduce the above copyright 523bf459f3Sfvdl * notice, this list of conditions and the following disclaimer in the 533bf459f3Sfvdl * documentation and/or other materials provided with the distribution. 54fb777788Sfvdl * 3. The name of the author may not be used to endorse or promote products 553bf459f3Sfvdl * derived from this software without specific prior written permission 563bf459f3Sfvdl * 573bf459f3Sfvdl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 583bf459f3Sfvdl * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 593bf459f3Sfvdl * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 603bf459f3Sfvdl * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 613bf459f3Sfvdl * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 623bf459f3Sfvdl * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 633bf459f3Sfvdl * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 643bf459f3Sfvdl * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 653bf459f3Sfvdl * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 663bf459f3Sfvdl * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 673bf459f3Sfvdl * 68fb777788Sfvdl * based on exec_aout.c, sunos_exec.c and svr4_exec.c 693bf459f3Sfvdl */ 703bf459f3Sfvdl 71*f7ac1bd3Serh #ifndef ELFSIZE 727c325577Scgd #define ELFSIZE 32 /* XXX should die */ 73*f7ac1bd3Serh #endif 749c3e274cScgd 753bf459f3Sfvdl #include <sys/param.h> 763bf459f3Sfvdl #include <sys/systm.h> 773bf459f3Sfvdl #include <sys/kernel.h> 783bf459f3Sfvdl #include <sys/proc.h> 793bf459f3Sfvdl #include <sys/malloc.h> 803bf459f3Sfvdl #include <sys/namei.h> 813bf459f3Sfvdl #include <sys/vnode.h> 82151fa70fSchristos #include <sys/mount.h> 83d551a4edSchristos #include <sys/exec.h> 84c4aaa600Sfvdl #include <sys/exec_elf.h> 853bf459f3Sfvdl 863bf459f3Sfvdl #include <sys/mman.h> 87151fa70fSchristos #include <sys/syscallargs.h> 88151fa70fSchristos 893bf459f3Sfvdl #include <vm/vm.h> 903bf459f3Sfvdl #include <vm/vm_param.h> 913bf459f3Sfvdl #include <vm/vm_map.h> 923bf459f3Sfvdl 933bf459f3Sfvdl #include <machine/cpu.h> 943bf459f3Sfvdl #include <machine/reg.h> 953bf459f3Sfvdl 963bf459f3Sfvdl #include <compat/linux/linux_types.h> 9744eef7c2Schristos #include <compat/linux/linux_syscall.h> 9888b8e43aSmycroft #include <compat/linux/linux_signal.h> 99*f7ac1bd3Serh #include <compat/linux/linux_siginfo.h> 1003bf459f3Sfvdl #include <compat/linux/linux_syscallargs.h> 1013bf459f3Sfvdl #include <compat/linux/linux_util.h> 1023bf459f3Sfvdl #include <compat/linux/linux_exec.h> 1033bf459f3Sfvdl 104*f7ac1bd3Serh #include <compat/linux/linux_machdep.h> 105fc7cfb5fSfvdl 106*f7ac1bd3Serh static int ELFNAME2(linux,signature) __P((struct proc *, struct exec_package *, 107*f7ac1bd3Serh Elf_Ehdr *)); 108*f7ac1bd3Serh #ifdef LINUX_GCC_SIGNATURE 109*f7ac1bd3Serh static int ELFNAME2(linux,gcc_signature) __P((struct proc *p, 110*f7ac1bd3Serh struct exec_package *, Elf_Ehdr *)); 111*f7ac1bd3Serh #endif 112*f7ac1bd3Serh 113c4aaa600Sfvdl #define LINUX_ELF_AUX_ARGSIZ (sizeof(AuxInfo) * 8 / sizeof(char *)) 114c4aaa600Sfvdl 11544eef7c2Schristos 11644eef7c2Schristos extern int linux_error[]; 117245f292fSmycroft extern char linux_sigcode[], linux_esigcode[]; 11844eef7c2Schristos extern struct sysent linux_sysent[]; 11944eef7c2Schristos extern char *linux_syscallnames[]; 12044eef7c2Schristos 121*f7ac1bd3Serh struct emul ELFNAMEEND(emul_linux) = { 122fc7cfb5fSfvdl "linux", 123fc7cfb5fSfvdl linux_error, 124fc7cfb5fSfvdl linux_sendsig, 125fc7cfb5fSfvdl LINUX_SYS_syscall, 126fc7cfb5fSfvdl LINUX_SYS_MAXSYSCALL, 127fc7cfb5fSfvdl linux_sysent, 128fc7cfb5fSfvdl linux_syscallnames, 129fc7cfb5fSfvdl LINUX_ELF_AUX_ARGSIZ, 130*f7ac1bd3Serh ELFNAME(copyargs), 13172623d84Smycroft linux_setregs, 13244eef7c2Schristos linux_sigcode, 13344eef7c2Schristos linux_esigcode, 13444eef7c2Schristos }; 13544eef7c2Schristos 13644eef7c2Schristos 137*f7ac1bd3Serh #ifdef LINUX_GCC_SIGNATURE 1384d9a6e09Schristos /* 1394d9a6e09Schristos * Take advantage of the fact that all the linux binaries are compiled 1404d9a6e09Schristos * with gcc, and gcc sticks in the comment field a signature. Note that 1414d9a6e09Schristos * on SVR4 binaries, the gcc signature will follow the OS name signature, 1424d9a6e09Schristos * that will not be a problem. We don't bother to read in the string table, 1434d9a6e09Schristos * but we check all the progbits headers. 144*f7ac1bd3Serh * 145*f7ac1bd3Serh * XXX This only works in the i386. On the alpha (at least) 146*f7ac1bd3Serh * XXX we have the same gcc signature which incorrectly identifies 147*f7ac1bd3Serh * XXX NetBSD binaries as Linux. 1484d9a6e09Schristos */ 1494d9a6e09Schristos static int 150*f7ac1bd3Serh ELFNAME2(linux,gcc_signature)(p, epp, eh) 151fc7cfb5fSfvdl struct proc *p; 152fc7cfb5fSfvdl struct exec_package *epp; 153*f7ac1bd3Serh Elf_Ehdr *eh; 1544d9a6e09Schristos { 155*f7ac1bd3Serh size_t shsize = sizeof(Elf_Shdr) * eh->e_shnum; 1564d9a6e09Schristos size_t i; 1574d9a6e09Schristos static const char signature[] = "\0GCC: (GNU) "; 1584d9a6e09Schristos char buf[sizeof(signature) - 1]; 159*f7ac1bd3Serh Elf_Shdr *sh; 1604d9a6e09Schristos int error; 1614d9a6e09Schristos 162*f7ac1bd3Serh printf("XAXlinuxgccsig.\n"); 163*f7ac1bd3Serh DELAY(500000); 164*f7ac1bd3Serh error = ENOEXEC; 165*f7ac1bd3Serh sh = (Elf_Shdr *) malloc(shsize, M_TEMP, M_WAITOK); 1664d9a6e09Schristos 167*f7ac1bd3Serh if ((error = ELFNAME(read_from)(p, epp->ep_vp, eh->e_shoff, 1684d9a6e09Schristos (caddr_t) sh, shsize)) != 0) 1694d9a6e09Schristos goto out; 1704d9a6e09Schristos 1714d9a6e09Schristos for (i = 0; i < eh->e_shnum; i++) { 172*f7ac1bd3Serh Elf_Shdr *s = &sh[i]; 1734d9a6e09Schristos 1744d9a6e09Schristos /* 1754d9a6e09Schristos * Identify candidates for the comment header; 176d83602c1Schristos * Header cannot have a load address, or flags and 1774d9a6e09Schristos * it must be large enough. 1784d9a6e09Schristos */ 179fb2727b7Sjtk if (s->sh_type != Elf_sht_progbits || 1804d9a6e09Schristos s->sh_addr != 0 || 1814d9a6e09Schristos s->sh_flags != 0 || 1824d9a6e09Schristos s->sh_size < sizeof(signature) - 1) 1834d9a6e09Schristos continue; 1844d9a6e09Schristos 185*f7ac1bd3Serh if ((error = ELFNAME(read_from)(p, epp->ep_vp, s->sh_offset, 186d83602c1Schristos (caddr_t) buf, sizeof(signature) - 1)) != 0) 1874d9a6e09Schristos goto out; 1884d9a6e09Schristos 189d83602c1Schristos /* 190d83602c1Schristos * error is 0, if the signatures match we are done. 191d83602c1Schristos */ 192e1601dc2Sperry if (memcmp(buf, signature, sizeof(signature) - 1) == 0) 1934d9a6e09Schristos goto out; 1944d9a6e09Schristos } 1954d9a6e09Schristos 1964d9a6e09Schristos out: 1974d9a6e09Schristos free(sh, M_TEMP); 1984d9a6e09Schristos return error; 1994d9a6e09Schristos } 200*f7ac1bd3Serh #endif 2014d9a6e09Schristos 202*f7ac1bd3Serh static int 203*f7ac1bd3Serh ELFNAME2(linux,signature)(p, epp, eh) 2044d9a6e09Schristos struct proc *p; 2054d9a6e09Schristos struct exec_package *epp; 206*f7ac1bd3Serh Elf_Ehdr *eh; 207*f7ac1bd3Serh { 208*f7ac1bd3Serh size_t i; 209*f7ac1bd3Serh Elf_Phdr *ph; 210*f7ac1bd3Serh Elf_Note *notep; 211*f7ac1bd3Serh char *testp; 212*f7ac1bd3Serh size_t phsize; 213*f7ac1bd3Serh int error = ENOEXEC; 214*f7ac1bd3Serh 215*f7ac1bd3Serh phsize = eh->e_phnum * sizeof(Elf_Phdr); 216*f7ac1bd3Serh ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK); 217*f7ac1bd3Serh if ((error = ELFNAME(read_from)(p, epp->ep_vp, eh->e_phoff, 218*f7ac1bd3Serh (caddr_t) ph, phsize)) != 0) 219*f7ac1bd3Serh goto out1; 220*f7ac1bd3Serh 221*f7ac1bd3Serh for (i = 0; i < eh->e_phnum; i++) { 222*f7ac1bd3Serh Elf_Phdr *ephp = &ph[i]; 223*f7ac1bd3Serh u_int32_t ostype; 224*f7ac1bd3Serh 225*f7ac1bd3Serh /* XAX 226*f7ac1bd3Serh use interp field. 227*f7ac1bd3Serh /lib/ld-linux 228*f7ac1bd3Serh 1234567890123 = 13 229*f7ac1bd3Serh */ 230*f7ac1bd3Serh printf("inloop:%d is %d\n", i, ephp->p_type); 231*f7ac1bd3Serh if (ephp->p_type != Elf_pt_interp /* XAX pt_note */ 232*f7ac1bd3Serh /* ephp->p_flags != 0 || 233*f7ac1bd3Serh ephp->p_filesz < sizeof(Elf_Note))*/ ) 234*f7ac1bd3Serh continue; 235*f7ac1bd3Serh 236*f7ac1bd3Serh notep = (Elf_Note *)malloc(ephp->p_filesz, M_TEMP, M_WAITOK); 237*f7ac1bd3Serh if ((error = ELFNAME(read_from)(p, epp->ep_vp, ephp->p_offset, 238*f7ac1bd3Serh (caddr_t)notep, ephp->p_filesz)) != 0) 239*f7ac1bd3Serh goto out3; 240*f7ac1bd3Serh 241*f7ac1bd3Serh testp = (char *)notep; 242*f7ac1bd3Serh testp[16] = '\0'; 243*f7ac1bd3Serh printf("interp:%s\n", testp); 244*f7ac1bd3Serh if (testp[8] == 'l' && testp[9] == 'i' && testp[12] == 'x') { 245*f7ac1bd3Serh printf("okok\n"); 246*f7ac1bd3Serh error = 0; 247*f7ac1bd3Serh goto out3; 248*f7ac1bd3Serh } 249*f7ac1bd3Serh 250*f7ac1bd3Serh goto out2; 251*f7ac1bd3Serh 252*f7ac1bd3Serh printf("checkosverfor:%d\n", ELF_NOTE_TYPE_OSVERSION); 253*f7ac1bd3Serh /* XXX XAX Should handle NETBSD_TYPE_EMULNAME */ 254*f7ac1bd3Serh if (notep->type != ELF_NOTE_TYPE_OSVERSION) { 255*f7ac1bd3Serh free(notep, M_TEMP); 256*f7ac1bd3Serh continue; 257*f7ac1bd3Serh } 258*f7ac1bd3Serh 259*f7ac1bd3Serh printf("checksize: n=%d, d=%d\n", notep->namesz, notep->descsz); 260*f7ac1bd3Serh /* Check the name and description sizes. */ 261*f7ac1bd3Serh if (notep->namesz != ELF_NOTE_GNU_NAMESZ || 262*f7ac1bd3Serh notep->descsz != ELF_NOTE_GNU_DESCSZ) 263*f7ac1bd3Serh goto out2; 264*f7ac1bd3Serh 265*f7ac1bd3Serh printf("checkname: %s\n", (char *)(notep + sizeof(Elf_Note))); 266*f7ac1bd3Serh /* Is the name "GNU\0"? */ 267*f7ac1bd3Serh if (memcmp((notep + sizeof(Elf_Note)), 268*f7ac1bd3Serh ELF_NOTE_GNU_NAME, ELF_NOTE_GNU_NAMESZ)) 269*f7ac1bd3Serh goto out2; 270*f7ac1bd3Serh 271*f7ac1bd3Serh /* Make sure the OS is Linux */ 272*f7ac1bd3Serh ostype = (u_int32_t)(*((u_int32_t *)notep + sizeof(Elf_Note) 273*f7ac1bd3Serh + notep->namesz)) 274*f7ac1bd3Serh & ELF_NOTE_GNU_OSMASK; 275*f7ac1bd3Serh printf("ostype:%d\n", ostype); 276*f7ac1bd3Serh if (ostype != ELF_NOTE_GNU_OSLINUX) 277*f7ac1bd3Serh goto out2; 278*f7ac1bd3Serh 279*f7ac1bd3Serh printf("allok\n"); 280*f7ac1bd3Serh /* All checks succeeded. */ 281*f7ac1bd3Serh error = 0; 282*f7ac1bd3Serh goto out3; 283*f7ac1bd3Serh } 284*f7ac1bd3Serh 285*f7ac1bd3Serh error = ENOEXEC; 286*f7ac1bd3Serh 287*f7ac1bd3Serh out1: 288*f7ac1bd3Serh free(ph, M_TEMP); 289*f7ac1bd3Serh return error; 290*f7ac1bd3Serh 291*f7ac1bd3Serh out2: 292*f7ac1bd3Serh error = ENOEXEC; 293*f7ac1bd3Serh out3: 294*f7ac1bd3Serh free(notep, M_TEMP); 295*f7ac1bd3Serh free(ph, M_TEMP); 296*f7ac1bd3Serh return error; 297*f7ac1bd3Serh } 298*f7ac1bd3Serh 299*f7ac1bd3Serh int 300*f7ac1bd3Serh ELFNAME2(linux,probe)(p, epp, eh, itp, pos) 301*f7ac1bd3Serh struct proc *p; 302*f7ac1bd3Serh struct exec_package *epp; 303*f7ac1bd3Serh Elf_Ehdr *eh; 304c4aaa600Sfvdl char *itp; 305*f7ac1bd3Serh Elf_Addr *pos; 306fc7cfb5fSfvdl { 307c4aaa600Sfvdl char *bp; 308fc7cfb5fSfvdl int error; 309c4aaa600Sfvdl size_t len; 310fc7cfb5fSfvdl 311*f7ac1bd3Serh if ((error = ELFNAME2(linux,signature)(p, epp, eh)) != 0) 312*f7ac1bd3Serh #ifdef LINUX_GCC_SIGNATURE 313*f7ac1bd3Serh if ((error = ELFNAME2(linux,gcc_signature)(p, epp, eh)) != 0) 3144d9a6e09Schristos return error; 315*f7ac1bd3Serh #else 316*f7ac1bd3Serh return error; 317*f7ac1bd3Serh #endif 3184d9a6e09Schristos 319c4aaa600Sfvdl if (itp[0]) { 3206b95b513Schristos if ((error = emul_find(p, NULL, linux_emul_path, itp, &bp, 0))) 321c4aaa600Sfvdl return error; 322c4aaa600Sfvdl if ((error = copystr(bp, itp, MAXPATHLEN, &len))) 323c4aaa600Sfvdl return error; 324c4aaa600Sfvdl free(bp, M_TEMP); 325fc7cfb5fSfvdl } 326*f7ac1bd3Serh epp->ep_emul = &ELFNAMEEND(emul_linux); 327*f7ac1bd3Serh *pos = ELF_NO_ADDR; 328*f7ac1bd3Serh printf("ret0\n"); 329c4aaa600Sfvdl return 0; 330fc7cfb5fSfvdl } 331c4aaa600Sfvdl 332