1*a03af6c5Schristos /* $NetBSD: linux_exec_elf32.c,v 1.97 2018/07/15 21:31:00 christos Exp $ */ 28fb507a3Schristos 38fb507a3Schristos /*- 4ac10cf69Smanu * Copyright (c) 1995, 1998, 2000, 2001 The NetBSD Foundation, Inc. 58fb507a3Schristos * All rights reserved. 68fb507a3Schristos * 78fb507a3Schristos * This code is derived from software contributed to The NetBSD Foundation 8ac10cf69Smanu * by Christos Zoulas, Frank van der Linden, Eric Haszlakiewicz and 9ac10cf69Smanu * Emmanuel Dreyfus. 108fb507a3Schristos * 118fb507a3Schristos * Redistribution and use in source and binary forms, with or without 128fb507a3Schristos * modification, are permitted provided that the following conditions 138fb507a3Schristos * are met: 148fb507a3Schristos * 1. Redistributions of source code must retain the above copyright 158fb507a3Schristos * notice, this list of conditions and the following disclaimer. 168fb507a3Schristos * 2. Redistributions in binary form must reproduce the above copyright 178fb507a3Schristos * notice, this list of conditions and the following disclaimer in the 188fb507a3Schristos * documentation and/or other materials provided with the distribution. 198fb507a3Schristos * 208fb507a3Schristos * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 218fb507a3Schristos * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 228fb507a3Schristos * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 238fb507a3Schristos * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 248fb507a3Schristos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 258fb507a3Schristos * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 268fb507a3Schristos * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 278fb507a3Schristos * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 288fb507a3Schristos * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 298fb507a3Schristos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 308fb507a3Schristos * POSSIBILITY OF SUCH DAMAGE. 318fb507a3Schristos */ 323bf459f3Sfvdl 333bf459f3Sfvdl /* 34fb777788Sfvdl * based on exec_aout.c, sunos_exec.c and svr4_exec.c 353bf459f3Sfvdl */ 363bf459f3Sfvdl 37dab6ef8bSlukem #include <sys/cdefs.h> 38*a03af6c5Schristos __KERNEL_RCSID(0, "$NetBSD: linux_exec_elf32.c,v 1.97 2018/07/15 21:31:00 christos Exp $"); 39dab6ef8bSlukem 40f7ac1bd3Serh #ifndef ELFSIZE 41ea0cda2cSchristos /* XXX should die */ 42ea0cda2cSchristos #define ELFSIZE 32 43f7ac1bd3Serh #endif 449c3e274cScgd 453bf459f3Sfvdl #include <sys/param.h> 463bf459f3Sfvdl #include <sys/systm.h> 473bf459f3Sfvdl #include <sys/kernel.h> 483bf459f3Sfvdl #include <sys/proc.h> 493bf459f3Sfvdl #include <sys/malloc.h> 503bf459f3Sfvdl #include <sys/namei.h> 513bf459f3Sfvdl #include <sys/vnode.h> 52151fa70fSchristos #include <sys/mount.h> 53d551a4edSchristos #include <sys/exec.h> 54c4aaa600Sfvdl #include <sys/exec_elf.h> 55cee43b67Sjdolecek #include <sys/stat.h> 56874fef37Selad #include <sys/kauth.h> 57e5a75de9Schs #include <sys/cprng.h> 583bf459f3Sfvdl 593bf459f3Sfvdl #include <sys/mman.h> 60151fa70fSchristos #include <sys/syscallargs.h> 61151fa70fSchristos 62a2a38285Sad #include <sys/cpu.h> 633bf459f3Sfvdl #include <machine/reg.h> 643bf459f3Sfvdl 65908291d2Schristos #include <compat/linux/common/linux_types.h> 66908291d2Schristos #include <compat/linux/common/linux_signal.h> 67908291d2Schristos #include <compat/linux/common/linux_util.h> 68908291d2Schristos #include <compat/linux/common/linux_exec.h> 69908291d2Schristos #include <compat/linux/common/linux_machdep.h> 701ab7ca8fSad #include <compat/linux/common/linux_ipc.h> 711ab7ca8fSad #include <compat/linux/common/linux_sem.h> 723bf459f3Sfvdl 73908291d2Schristos #include <compat/linux/linux_syscallargs.h> 74908291d2Schristos #include <compat/linux/linux_syscall.h> 75fc7cfb5fSfvdl 768be2e96dSchristos #define LINUX_GO_RT0_SIGNATURE 778be2e96dSchristos 7865fc8539Schristos #ifdef DEBUG_LINUX 7965fc8539Schristos #define DPRINTF(a) uprintf a 8065fc8539Schristos #else 819ab53722Smsaitoh #define DPRINTF(a) do {} while (0) 8265fc8539Schristos #endif 8365fc8539Schristos 84ac10cf69Smanu #ifdef LINUX_ATEXIT_SIGNATURE 85ac10cf69Smanu /* 86ac10cf69Smanu * On the PowerPC, statically linked Linux binaries are not recognized 87ac10cf69Smanu * by linux_signature nor by linux_gcc_signature. Fortunately, thoses 88ac10cf69Smanu * binaries features a __libc_atexit ELF section. We therefore assume we 89ac10cf69Smanu * have a Linux binary if we find this section. 90ac10cf69Smanu */ 91ee0c5b44Smanu int 921d7f24eaSmatt ELFNAME2(linux,atexit_signature)( 931d7f24eaSmatt struct lwp *l, 941d7f24eaSmatt struct exec_package *epp, 951d7f24eaSmatt Elf_Ehdr *eh) 96ac10cf69Smanu { 97c1cf2f47Smaxv Elf_Shdr *sh; 98ac10cf69Smanu size_t shsize; 99c1cf2f47Smaxv u_int shstrndx; 100ac10cf69Smanu size_t i; 101ac10cf69Smanu static const char signature[] = "__libc_atexit"; 102c1cf2f47Smaxv const size_t sigsz = sizeof(signature); 103c1cf2f47Smaxv char tbuf[sizeof(signature)]; 104ac10cf69Smanu int error; 105ac10cf69Smanu 106c1cf2f47Smaxv /* Load the section header table. */ 107ac10cf69Smanu shsize = eh->e_shnum * sizeof(Elf_Shdr); 108ac10cf69Smanu sh = (Elf_Shdr *) malloc(shsize, M_TEMP, M_WAITOK); 10995e1ffb1Schristos error = exec_read_from(l, epp->ep_vp, eh->e_shoff, sh, shsize); 110ac10cf69Smanu if (error) 111ac10cf69Smanu goto out; 112ac10cf69Smanu 113c1cf2f47Smaxv /* Now let's find the string table. If it does not exist, give up. */ 114c1cf2f47Smaxv shstrndx = eh->e_shstrndx; 115c1cf2f47Smaxv if (shstrndx == SHN_UNDEF || shstrndx >= eh->e_shnum) { 116ac10cf69Smanu error = ENOEXEC; 117ac10cf69Smanu goto out; 118ac10cf69Smanu } 119ac10cf69Smanu 120c1cf2f47Smaxv /* Check if any section has the name we're looking for. */ 121c1cf2f47Smaxv const off_t stroff = sh[shstrndx].sh_offset; 122ac10cf69Smanu for (i = 0; i < eh->e_shnum; i++) { 123ac10cf69Smanu Elf_Shdr *s = &sh[i]; 124c1cf2f47Smaxv 125c1cf2f47Smaxv if (s->sh_name + sigsz > sh[shstrndx].sh_size) 126c1cf2f47Smaxv continue; 127c1cf2f47Smaxv 128c1cf2f47Smaxv error = exec_read_from(l, epp->ep_vp, stroff + s->sh_name, tbuf, 129c1cf2f47Smaxv sigsz); 130c1cf2f47Smaxv if (error) 131c1cf2f47Smaxv goto out; 132c1cf2f47Smaxv if (!memcmp(tbuf, signature, sigsz)) { 133c1cf2f47Smaxv DPRINTF(("linux_atexit_sig=%s\n", tbuf)); 134ac10cf69Smanu error = 0; 135ac10cf69Smanu goto out; 136ac10cf69Smanu } 137ac10cf69Smanu } 138ac10cf69Smanu error = ENOEXEC; 139ac10cf69Smanu 140ac10cf69Smanu out: 141ac10cf69Smanu free(sh, M_TEMP); 142ac10cf69Smanu return (error); 143ac10cf69Smanu } 144ac10cf69Smanu #endif 145f7ac1bd3Serh 146f7ac1bd3Serh #ifdef LINUX_GCC_SIGNATURE 1474d9a6e09Schristos /* 1484d9a6e09Schristos * Take advantage of the fact that all the linux binaries are compiled 1494d9a6e09Schristos * with gcc, and gcc sticks in the comment field a signature. Note that 1504d9a6e09Schristos * on SVR4 binaries, the gcc signature will follow the OS name signature, 1514d9a6e09Schristos * that will not be a problem. We don't bother to read in the string table, 1524d9a6e09Schristos * but we check all the progbits headers. 153f7ac1bd3Serh * 154f7ac1bd3Serh * XXX This only works in the i386. On the alpha (at least) 155f7ac1bd3Serh * XXX we have the same gcc signature which incorrectly identifies 156f7ac1bd3Serh * XXX NetBSD binaries as Linux. 1574d9a6e09Schristos */ 158ee0c5b44Smanu int 1591d7f24eaSmatt ELFNAME2(linux,gcc_signature)( 1601d7f24eaSmatt struct lwp *l, 1611d7f24eaSmatt struct exec_package *epp, 1621d7f24eaSmatt Elf_Ehdr *eh) 1634d9a6e09Schristos { 164b29180b2Smycroft size_t shsize; 1654d9a6e09Schristos size_t i; 1664d9a6e09Schristos static const char signature[] = "\0GCC: (GNU) "; 167fb4b40b7Schristos char tbuf[sizeof(signature) - 1]; 168f7ac1bd3Serh Elf_Shdr *sh; 1694d9a6e09Schristos int error; 1704d9a6e09Schristos 171b29180b2Smycroft shsize = eh->e_shnum * sizeof(Elf_Shdr); 172f7ac1bd3Serh sh = (Elf_Shdr *) malloc(shsize, M_TEMP, M_WAITOK); 17395e1ffb1Schristos error = exec_read_from(l, epp->ep_vp, eh->e_shoff, sh, shsize); 174b29180b2Smycroft if (error) 1754d9a6e09Schristos goto out; 1764d9a6e09Schristos 1774d9a6e09Schristos for (i = 0; i < eh->e_shnum; i++) { 178f7ac1bd3Serh Elf_Shdr *s = &sh[i]; 1794d9a6e09Schristos 1804d9a6e09Schristos /* 1814d9a6e09Schristos * Identify candidates for the comment header; 182d83602c1Schristos * Header cannot have a load address, or flags and 1834d9a6e09Schristos * it must be large enough. 1844d9a6e09Schristos */ 185522cbf02Skleink if (s->sh_type != SHT_PROGBITS || 1864d9a6e09Schristos s->sh_addr != 0 || 1874d9a6e09Schristos s->sh_flags != 0 || 1884d9a6e09Schristos s->sh_size < sizeof(signature) - 1) 1894d9a6e09Schristos continue; 1904d9a6e09Schristos 19195e1ffb1Schristos error = exec_read_from(l, epp->ep_vp, s->sh_offset, tbuf, 19297c9d7a9Schristos sizeof(signature) - 1); 193b29180b2Smycroft if (error) 194b29180b2Smycroft continue; 1954d9a6e09Schristos 196d83602c1Schristos /* 197d83602c1Schristos * error is 0, if the signatures match we are done. 198d83602c1Schristos */ 199fb4b40b7Schristos DPRINTF(("linux_gcc_sig: sig=%s\n", tbuf)); 200fb4b40b7Schristos if (!memcmp(tbuf, signature, sizeof(signature) - 1)) { 201b29180b2Smycroft error = 0; 2024d9a6e09Schristos goto out; 2034d9a6e09Schristos } 204b29180b2Smycroft } 205b29180b2Smycroft error = ENOEXEC; 2064d9a6e09Schristos 2074d9a6e09Schristos out: 2084d9a6e09Schristos free(sh, M_TEMP); 209b29180b2Smycroft return (error); 2104d9a6e09Schristos } 211f7ac1bd3Serh #endif 2124d9a6e09Schristos 21305c8a1b8Smanu #ifdef LINUX_DEBUGLINK_SIGNATURE 21405c8a1b8Smanu /* 215c1cf2f47Smaxv * Look for a .gnu_debuglink, specific to x86_64 interpreter 21605c8a1b8Smanu */ 21705c8a1b8Smanu int 2189fca5da6Scegger ELFNAME2(linux,debuglink_signature)(struct lwp *l, struct exec_package *epp, Elf_Ehdr *eh) 21905c8a1b8Smanu { 220c1cf2f47Smaxv Elf_Shdr *sh; 22105c8a1b8Smanu size_t shsize; 222c1cf2f47Smaxv u_int shstrndx; 22305c8a1b8Smanu size_t i; 22405c8a1b8Smanu static const char signature[] = ".gnu_debuglink"; 225c1cf2f47Smaxv const size_t sigsz = sizeof(signature); 226c1cf2f47Smaxv char tbuf[sizeof(signature)]; 22705c8a1b8Smanu int error; 22805c8a1b8Smanu 229c1cf2f47Smaxv /* Load the section header table. */ 23005c8a1b8Smanu shsize = eh->e_shnum * sizeof(Elf_Shdr); 23105c8a1b8Smanu sh = (Elf_Shdr *) malloc(shsize, M_TEMP, M_WAITOK); 23205c8a1b8Smanu error = exec_read_from(l, epp->ep_vp, eh->e_shoff, sh, shsize); 23305c8a1b8Smanu if (error) 23405c8a1b8Smanu goto out; 23505c8a1b8Smanu 236c1cf2f47Smaxv /* Now let's find the string table. If it does not exist, give up. */ 237c1cf2f47Smaxv shstrndx = eh->e_shstrndx; 238c1cf2f47Smaxv if (shstrndx == SHN_UNDEF || shstrndx >= eh->e_shnum) { 23905c8a1b8Smanu error = ENOEXEC; 24005c8a1b8Smanu goto out; 24105c8a1b8Smanu } 24205c8a1b8Smanu 243c1cf2f47Smaxv /* Check if any section has the name we're looking for. */ 244c1cf2f47Smaxv const off_t stroff = sh[shstrndx].sh_offset; 24505c8a1b8Smanu for (i = 0; i < eh->e_shnum; i++) { 24605c8a1b8Smanu Elf_Shdr *s = &sh[i]; 24705c8a1b8Smanu 248c1cf2f47Smaxv if (s->sh_name + sigsz > sh[shstrndx].sh_size) 249c1cf2f47Smaxv continue; 250c1cf2f47Smaxv 251c1cf2f47Smaxv error = exec_read_from(l, epp->ep_vp, stroff + s->sh_name, tbuf, 252c1cf2f47Smaxv sigsz); 253c1cf2f47Smaxv if (error) 254c1cf2f47Smaxv goto out; 255c1cf2f47Smaxv if (!memcmp(tbuf, signature, sigsz)) { 256c1cf2f47Smaxv DPRINTF(("linux_debuglink_sig=%s\n", tbuf)); 25705c8a1b8Smanu error = 0; 25805c8a1b8Smanu goto out; 25905c8a1b8Smanu } 26005c8a1b8Smanu } 26105c8a1b8Smanu error = ENOEXEC; 26205c8a1b8Smanu 26305c8a1b8Smanu out: 26405c8a1b8Smanu free(sh, M_TEMP); 26505c8a1b8Smanu return (error); 26605c8a1b8Smanu } 26705c8a1b8Smanu #endif 26805c8a1b8Smanu 2698be2e96dSchristos #ifdef LINUX_GO_RT0_SIGNATURE 2708be2e96dSchristos /* 2718be2e96dSchristos * Look for a .gopclntab, specific to go binaries 2728be2e96dSchristos * in it look for a symbol called _rt0_<cpu>_linux 2738be2e96dSchristos */ 2748be2e96dSchristos static int 2758be2e96dSchristos ELFNAME2(linux,go_rt0_signature)(struct lwp *l, struct exec_package *epp, Elf_Ehdr *eh) 2768be2e96dSchristos { 2778be2e96dSchristos Elf_Shdr *sh; 2788be2e96dSchristos size_t shsize; 2798be2e96dSchristos u_int shstrndx; 2808be2e96dSchristos size_t i; 2818be2e96dSchristos static const char signature[] = ".gopclntab"; 2828be2e96dSchristos const size_t sigsz = sizeof(signature); 2838be2e96dSchristos char tbuf[sizeof(signature)], *tmp = NULL; 2848be2e96dSchristos char mbuf[64]; 2858be2e96dSchristos const char *m; 2868be2e96dSchristos int mlen; 2878be2e96dSchristos int error; 2888be2e96dSchristos 2898be2e96dSchristos /* Load the section header table. */ 2908be2e96dSchristos shsize = eh->e_shnum * sizeof(Elf_Shdr); 2918be2e96dSchristos sh = malloc(shsize, M_TEMP, M_WAITOK); 2928be2e96dSchristos error = exec_read_from(l, epp->ep_vp, eh->e_shoff, sh, shsize); 2938be2e96dSchristos if (error) 2948be2e96dSchristos goto out; 2958be2e96dSchristos 2968be2e96dSchristos /* Now let's find the string table. If it does not exist, give up. */ 2978be2e96dSchristos shstrndx = eh->e_shstrndx; 2988be2e96dSchristos if (shstrndx == SHN_UNDEF || shstrndx >= eh->e_shnum) { 2998be2e96dSchristos error = ENOEXEC; 3008be2e96dSchristos goto out; 3018be2e96dSchristos } 3028be2e96dSchristos 3038be2e96dSchristos /* Check if any section has the name we're looking for. */ 3048be2e96dSchristos const off_t stroff = sh[shstrndx].sh_offset; 3058be2e96dSchristos for (i = 0; i < eh->e_shnum; i++) { 3068be2e96dSchristos Elf_Shdr *s = &sh[i]; 3078be2e96dSchristos 3088be2e96dSchristos if (s->sh_name + sigsz > sh[shstrndx].sh_size) 3098be2e96dSchristos continue; 3108be2e96dSchristos 3118be2e96dSchristos error = exec_read_from(l, epp->ep_vp, stroff + s->sh_name, tbuf, 3128be2e96dSchristos sigsz); 3138be2e96dSchristos if (error) 3148be2e96dSchristos goto out; 3158be2e96dSchristos if (!memcmp(tbuf, signature, sigsz)) { 3169ab53722Smsaitoh DPRINTF(("linux_goplcntab_sig=%s\n", tbuf)); 3178be2e96dSchristos break; 3188be2e96dSchristos } 3198be2e96dSchristos } 3208be2e96dSchristos 3218be2e96dSchristos if (i == eh->e_shnum) { 3228be2e96dSchristos error = ENOEXEC; 3238be2e96dSchristos goto out; 3248be2e96dSchristos } 3258be2e96dSchristos 326*a03af6c5Schristos // Don't scan more than 1MB 327*a03af6c5Schristos if (sh[i].sh_size > 1024 * 1024) 328*a03af6c5Schristos sh[i].sh_size = 1024 * 1024; 3298be2e96dSchristos 3308be2e96dSchristos tmp = malloc(sh[i].sh_size, M_TEMP, M_WAITOK); 3318be2e96dSchristos error = exec_read_from(l, epp->ep_vp, sh[i].sh_offset, tmp, 3328be2e96dSchristos sh[i].sh_size); 3338be2e96dSchristos if (error) 3348be2e96dSchristos goto out; 3358be2e96dSchristos 3368be2e96dSchristos #if (ELFSIZE == 32) 337*a03af6c5Schristos extern const char machine32[] __weak; 338*a03af6c5Schristos if (machine32 != NULL) 339*a03af6c5Schristos m = machine32; 3408be2e96dSchristos else 3418be2e96dSchristos m = machine; 3428be2e96dSchristos #else 3438be2e96dSchristos m = machine; 3448be2e96dSchristos #endif 3458be2e96dSchristos mlen = snprintf(mbuf, sizeof(mbuf), "_rt0_%s_linux", m); 3468be2e96dSchristos if (memmem(tmp, sh[i].sh_size, mbuf, mlen) == NULL) 3478be2e96dSchristos error = ENOEXEC; 3488be2e96dSchristos else 3498be2e96dSchristos DPRINTF(("linux_rt0_sig=%s\n", mbuf)); 3508be2e96dSchristos out: 3518be2e96dSchristos if (tmp) 3528be2e96dSchristos free(tmp, M_TEMP); 3538be2e96dSchristos free(sh, M_TEMP); 3548be2e96dSchristos return error; 3558be2e96dSchristos } 3568be2e96dSchristos #endif 3578be2e96dSchristos 358ee0c5b44Smanu int 3599fca5da6Scegger ELFNAME2(linux,signature)(struct lwp *l, struct exec_package *epp, Elf_Ehdr *eh, char *itp) 360f7ac1bd3Serh { 361f7ac1bd3Serh size_t i; 362f7ac1bd3Serh Elf_Phdr *ph; 363f7ac1bd3Serh size_t phsize; 364b29180b2Smycroft int error; 3656cc14962Schristos static const char linux[] = "Linux"; 3666cc14962Schristos 367a2ad93deSuwe if (eh->e_ident[EI_OSABI] == ELFOSABI_LINUX || 3686cc14962Schristos memcmp(&eh->e_ident[EI_ABIVERSION], linux, sizeof(linux)) == 0) 3696cc14962Schristos return 0; 370f7ac1bd3Serh 371f7ac1bd3Serh phsize = eh->e_phnum * sizeof(Elf_Phdr); 372f7ac1bd3Serh ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK); 37395e1ffb1Schristos error = exec_read_from(l, epp->ep_vp, eh->e_phoff, ph, phsize); 374b29180b2Smycroft if (error) 375b29180b2Smycroft goto out; 376f7ac1bd3Serh 377f7ac1bd3Serh for (i = 0; i < eh->e_phnum; i++) { 378f7ac1bd3Serh Elf_Phdr *ephp = &ph[i]; 379b29180b2Smycroft Elf_Nhdr *np; 380b29180b2Smycroft u_int32_t *abi; 381f7ac1bd3Serh 382b29180b2Smycroft if (ephp->p_type != PT_NOTE || 383b29180b2Smycroft ephp->p_filesz > 1024 || 384b29180b2Smycroft ephp->p_filesz < sizeof(Elf_Nhdr) + 20) 385f7ac1bd3Serh continue; 386f7ac1bd3Serh 387b29180b2Smycroft np = (Elf_Nhdr *)malloc(ephp->p_filesz, M_TEMP, M_WAITOK); 38895e1ffb1Schristos error = exec_read_from(l, epp->ep_vp, ephp->p_offset, np, 38997c9d7a9Schristos ephp->p_filesz); 390b29180b2Smycroft if (error) 391b29180b2Smycroft goto next; 392f7ac1bd3Serh 393b29180b2Smycroft if (np->n_type != ELF_NOTE_TYPE_ABI_TAG || 394b29180b2Smycroft np->n_namesz != ELF_NOTE_ABI_NAMESZ || 395b29180b2Smycroft np->n_descsz != ELF_NOTE_ABI_DESCSZ || 39653524e44Schristos memcmp((void *)(np + 1), ELF_NOTE_ABI_NAME, 397b29180b2Smycroft ELF_NOTE_ABI_NAMESZ)) 398b29180b2Smycroft goto next; 399b29180b2Smycroft 400b29180b2Smycroft /* Make sure the OS is Linux. */ 40153524e44Schristos abi = (u_int32_t *)((char *)np + sizeof(Elf_Nhdr) + 402b29180b2Smycroft np->n_namesz); 403b29180b2Smycroft if (abi[0] == ELF_NOTE_ABI_OS_LINUX) 404f7ac1bd3Serh error = 0; 405b29180b2Smycroft else 406b29180b2Smycroft error = ENOEXEC; 407b29180b2Smycroft free(np, M_TEMP); 408b29180b2Smycroft goto out; 409f7ac1bd3Serh 410b29180b2Smycroft next: 411b29180b2Smycroft free(np, M_TEMP); 412f7ac1bd3Serh continue; 413f7ac1bd3Serh } 414f7ac1bd3Serh 415c1cf2f47Smaxv /* Check for certain interpreter names. */ 416714de045Sdrochner if (itp) { 417b29180b2Smycroft if (!strncmp(itp, "/lib/ld-linux", 13) || 41889647c7cSmanu #if (ELFSIZE == 64) 41989647c7cSmanu !strncmp(itp, "/lib64/ld-linux", 15) || 42089647c7cSmanu #endif 421b29180b2Smycroft !strncmp(itp, "/lib/ld.so.", 11)) 422f7ac1bd3Serh error = 0; 423b29180b2Smycroft else 424b29180b2Smycroft error = ENOEXEC; 425b29180b2Smycroft goto out; 426f7ac1bd3Serh } 427f7ac1bd3Serh 428f7ac1bd3Serh error = ENOEXEC; 429b29180b2Smycroft out: 430f7ac1bd3Serh free(ph, M_TEMP); 431b29180b2Smycroft return (error); 432f7ac1bd3Serh } 433f7ac1bd3Serh 434f7ac1bd3Serh int 4354d595fd7Schristos ELFNAME2(linux,probe)(struct lwp *l, struct exec_package *epp, void *eh, 436168cd830Schristos char *itp, vaddr_t *pos) 437fc7cfb5fSfvdl { 438fc7cfb5fSfvdl int error; 439fc7cfb5fSfvdl 44095e1ffb1Schristos if (((error = ELFNAME2(linux,signature)(l, epp, eh, itp)) != 0) && 441f7ac1bd3Serh #ifdef LINUX_GCC_SIGNATURE 44295e1ffb1Schristos ((error = ELFNAME2(linux,gcc_signature)(l, epp, eh)) != 0) && 4438537f76cSmanu #endif 444ac10cf69Smanu #ifdef LINUX_ATEXIT_SIGNATURE 44595e1ffb1Schristos ((error = ELFNAME2(linux,atexit_signature)(l, epp, eh)) != 0) && 446ac10cf69Smanu #endif 44705c8a1b8Smanu #ifdef LINUX_DEBUGLINK_SIGNATURE 44805c8a1b8Smanu ((error = ELFNAME2(linux,debuglink_signature)(l, epp, eh)) != 0) && 44905c8a1b8Smanu #endif 4508be2e96dSchristos #ifdef LINUX_GO_RT0_SIGNATURE 4518be2e96dSchristos ((error = ELFNAME2(linux,go_rt0_signature)(l, epp, eh)) != 0) && 4528be2e96dSchristos #endif 45305c8a1b8Smanu 1) { 45405c8a1b8Smanu DPRINTF(("linux_probe: returning %d\n", error)); 4558537f76cSmanu return error; 45605c8a1b8Smanu } 4574d9a6e09Schristos 458714de045Sdrochner if (itp) { 459b8fbaf8cSdsl if ((error = emul_find_interp(l, epp, itp))) 46047cd9b85Sjdolecek return (error); 461fc7cfb5fSfvdl } 462590b9069Schs epp->ep_flags |= EXEC_FORCEAUX; 46365fc8539Schristos DPRINTF(("linux_probe: returning 0\n")); 464c4aaa600Sfvdl return 0; 465fc7cfb5fSfvdl } 466c4aaa600Sfvdl 467cee43b67Sjdolecek #ifndef LINUX_MACHDEP_ELF_COPYARGS 468cee43b67Sjdolecek /* 469cee43b67Sjdolecek * Copy arguments onto the stack in the normal way, but add some 470cee43b67Sjdolecek * extra information in case of dynamic binding. 471cee43b67Sjdolecek */ 472cee43b67Sjdolecek int 47395e1ffb1Schristos ELFNAME2(linux,copyargs)(struct lwp *l, struct exec_package *pack, 474cee43b67Sjdolecek struct ps_strings *arginfo, char **stackp, void *argp) 475cee43b67Sjdolecek { 476cee43b67Sjdolecek size_t len; 477cee43b67Sjdolecek AuxInfo ai[LINUX_ELF_AUX_ENTRIES], *a; 478cee43b67Sjdolecek struct elf_args *ap; 479cee43b67Sjdolecek int error; 480cee43b67Sjdolecek struct vattr *vap; 4812084516cSchs uint32_t randbytes[4]; 482cee43b67Sjdolecek 48395e1ffb1Schristos if ((error = copyargs(l, pack, arginfo, stackp, argp)) != 0) 484cee43b67Sjdolecek return error; 485cee43b67Sjdolecek 486cee43b67Sjdolecek a = ai; 487cee43b67Sjdolecek 48806b89b30Smaxv memset(ai, 0, sizeof(ai)); 48906b89b30Smaxv 490cee43b67Sjdolecek /* 491cee43b67Sjdolecek * Push extra arguments used by glibc on the stack. 492cee43b67Sjdolecek */ 493cee43b67Sjdolecek 494cee43b67Sjdolecek a->a_type = AT_PAGESZ; 495cee43b67Sjdolecek a->a_v = PAGE_SIZE; 496cee43b67Sjdolecek a++; 497cee43b67Sjdolecek 498cee43b67Sjdolecek if ((ap = (struct elf_args *)pack->ep_emul_arg)) { 499cee43b67Sjdolecek 500cee43b67Sjdolecek a->a_type = AT_PHDR; 501cee43b67Sjdolecek a->a_v = ap->arg_phaddr; 502cee43b67Sjdolecek a++; 503cee43b67Sjdolecek 504cee43b67Sjdolecek a->a_type = AT_PHENT; 505cee43b67Sjdolecek a->a_v = ap->arg_phentsize; 506cee43b67Sjdolecek a++; 507cee43b67Sjdolecek 508cee43b67Sjdolecek a->a_type = AT_PHNUM; 509cee43b67Sjdolecek a->a_v = ap->arg_phnum; 510cee43b67Sjdolecek a++; 511cee43b67Sjdolecek 512cee43b67Sjdolecek a->a_type = AT_BASE; 513cee43b67Sjdolecek a->a_v = ap->arg_interp; 514cee43b67Sjdolecek a++; 515cee43b67Sjdolecek 516cee43b67Sjdolecek a->a_type = AT_FLAGS; 517cee43b67Sjdolecek a->a_v = 0; 518cee43b67Sjdolecek a++; 519cee43b67Sjdolecek 520cee43b67Sjdolecek a->a_type = AT_ENTRY; 521cee43b67Sjdolecek a->a_v = ap->arg_entry; 522cee43b67Sjdolecek a++; 523cee43b67Sjdolecek 5242210079eSmatt exec_free_emul_arg(pack); 525cee43b67Sjdolecek } 526cee43b67Sjdolecek 527cee43b67Sjdolecek /* Linux-specific items */ 528cee43b67Sjdolecek a->a_type = LINUX_AT_CLKTCK; 529cee43b67Sjdolecek a->a_v = hz; 530cee43b67Sjdolecek a++; 531cee43b67Sjdolecek 532cee43b67Sjdolecek vap = pack->ep_vap; 533cee43b67Sjdolecek 534cee43b67Sjdolecek a->a_type = LINUX_AT_UID; 535f474dcebSad a->a_v = kauth_cred_getuid(l->l_cred); 536cee43b67Sjdolecek a++; 537cee43b67Sjdolecek 538cee43b67Sjdolecek a->a_type = LINUX_AT_EUID; 539cee43b67Sjdolecek if (vap->va_mode & S_ISUID) 540cee43b67Sjdolecek a->a_v = vap->va_uid; 541cee43b67Sjdolecek else 542f474dcebSad a->a_v = kauth_cred_geteuid(l->l_cred); 543cee43b67Sjdolecek a++; 544cee43b67Sjdolecek 545cee43b67Sjdolecek a->a_type = LINUX_AT_GID; 546f474dcebSad a->a_v = kauth_cred_getgid(l->l_cred); 547cee43b67Sjdolecek a++; 548cee43b67Sjdolecek 549cee43b67Sjdolecek a->a_type = LINUX_AT_EGID; 550cee43b67Sjdolecek if (vap->va_mode & S_ISGID) 551cee43b67Sjdolecek a->a_v = vap->va_gid; 552cee43b67Sjdolecek else 553f474dcebSad a->a_v = kauth_cred_getegid(l->l_cred); 554cee43b67Sjdolecek a++; 555cee43b67Sjdolecek 5562084516cSchs a->a_type = LINUX_AT_RANDOM; 557d99aa73fSmatt a->a_v = (Elf_Addr)(uintptr_t)*stackp; 5582084516cSchs a++; 5592084516cSchs 560cee43b67Sjdolecek a->a_type = AT_NULL; 561cee43b67Sjdolecek a->a_v = 0; 562cee43b67Sjdolecek a++; 563cee43b67Sjdolecek 564e5a75de9Schs randbytes[0] = cprng_strong32(); 565e5a75de9Schs randbytes[1] = cprng_strong32(); 566e5a75de9Schs randbytes[2] = cprng_strong32(); 567e5a75de9Schs randbytes[3] = cprng_strong32(); 5682084516cSchs 5692084516cSchs len = sizeof(randbytes); 5702084516cSchs if ((error = copyout(randbytes, *stackp, len)) != 0) 5712084516cSchs return error; 5722084516cSchs *stackp += len; 5732084516cSchs 574cee43b67Sjdolecek len = (a - ai) * sizeof(AuxInfo); 5756e5d6d35Snjoly KASSERT(len <= LINUX_ELF_AUX_ENTRIES * sizeof(AuxInfo)); 576cee43b67Sjdolecek if ((error = copyout(ai, *stackp, len)) != 0) 577cee43b67Sjdolecek return error; 578cee43b67Sjdolecek *stackp += len; 579cee43b67Sjdolecek 580cee43b67Sjdolecek return 0; 581cee43b67Sjdolecek } 582cee43b67Sjdolecek #endif /* !LINUX_MACHDEP_ELF_COPYARGS */ 583