1*a2a38285Sad /* $NetBSD: linux_exec_elf32.c,v 1.80 2007/10/19 12:16:39 ad 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 * 3. All advertising materials mentioning features or use of this software 208fb507a3Schristos * must display the following acknowledgement: 218fb507a3Schristos * This product includes software developed by the NetBSD 228fb507a3Schristos * Foundation, Inc. and its contributors. 238fb507a3Schristos * 4. Neither the name of The NetBSD Foundation nor the names of its 248fb507a3Schristos * contributors may be used to endorse or promote products derived 258fb507a3Schristos * from this software without specific prior written permission. 268fb507a3Schristos * 278fb507a3Schristos * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 288fb507a3Schristos * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 298fb507a3Schristos * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 308fb507a3Schristos * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 318fb507a3Schristos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 328fb507a3Schristos * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 338fb507a3Schristos * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 348fb507a3Schristos * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 358fb507a3Schristos * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 368fb507a3Schristos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 378fb507a3Schristos * POSSIBILITY OF SUCH DAMAGE. 388fb507a3Schristos */ 393bf459f3Sfvdl 403bf459f3Sfvdl /* 41fb777788Sfvdl * based on exec_aout.c, sunos_exec.c and svr4_exec.c 423bf459f3Sfvdl */ 433bf459f3Sfvdl 44dab6ef8bSlukem #include <sys/cdefs.h> 45*a2a38285Sad __KERNEL_RCSID(0, "$NetBSD: linux_exec_elf32.c,v 1.80 2007/10/19 12:16:39 ad Exp $"); 46dab6ef8bSlukem 47f7ac1bd3Serh #ifndef ELFSIZE 48ea0cda2cSchristos /* XXX should die */ 49ea0cda2cSchristos #define ELFSIZE 32 50f7ac1bd3Serh #endif 519c3e274cScgd 523bf459f3Sfvdl #include <sys/param.h> 533bf459f3Sfvdl #include <sys/systm.h> 543bf459f3Sfvdl #include <sys/kernel.h> 553bf459f3Sfvdl #include <sys/proc.h> 563bf459f3Sfvdl #include <sys/malloc.h> 573bf459f3Sfvdl #include <sys/namei.h> 583bf459f3Sfvdl #include <sys/vnode.h> 59151fa70fSchristos #include <sys/mount.h> 60d551a4edSchristos #include <sys/exec.h> 61c4aaa600Sfvdl #include <sys/exec_elf.h> 62cee43b67Sjdolecek #include <sys/stat.h> 63874fef37Selad #include <sys/kauth.h> 643bf459f3Sfvdl 653bf459f3Sfvdl #include <sys/mman.h> 66151fa70fSchristos #include <sys/syscallargs.h> 67151fa70fSchristos 68*a2a38285Sad #include <sys/cpu.h> 693bf459f3Sfvdl #include <machine/reg.h> 703bf459f3Sfvdl 71908291d2Schristos #include <compat/linux/common/linux_types.h> 72908291d2Schristos #include <compat/linux/common/linux_signal.h> 73908291d2Schristos #include <compat/linux/common/linux_util.h> 74908291d2Schristos #include <compat/linux/common/linux_exec.h> 75908291d2Schristos #include <compat/linux/common/linux_machdep.h> 763bf459f3Sfvdl 77908291d2Schristos #include <compat/linux/linux_syscallargs.h> 78908291d2Schristos #include <compat/linux/linux_syscall.h> 79fc7cfb5fSfvdl 8065fc8539Schristos #ifdef DEBUG_LINUX 8165fc8539Schristos #define DPRINTF(a) uprintf a 8265fc8539Schristos #else 8365fc8539Schristos #define DPRINTF(a) 8465fc8539Schristos #endif 8565fc8539Schristos 86ac10cf69Smanu #ifdef LINUX_ATEXIT_SIGNATURE 87ac10cf69Smanu /* 88ac10cf69Smanu * On the PowerPC, statically linked Linux binaries are not recognized 89ac10cf69Smanu * by linux_signature nor by linux_gcc_signature. Fortunately, thoses 90ac10cf69Smanu * binaries features a __libc_atexit ELF section. We therefore assume we 91ac10cf69Smanu * have a Linux binary if we find this section. 92ac10cf69Smanu */ 93ee0c5b44Smanu int 9495e1ffb1Schristos ELFNAME2(linux,atexit_signature)(l, epp, eh) 9595e1ffb1Schristos struct lwp *l; 96ac10cf69Smanu struct exec_package *epp; 97ac10cf69Smanu Elf_Ehdr *eh; 98ac10cf69Smanu { 99ac10cf69Smanu size_t shsize; 100ac10cf69Smanu int strndx; 101ac10cf69Smanu size_t i; 102ac10cf69Smanu static const char signature[] = "__libc_atexit"; 1033b6d3c71Schs char *strtable = NULL; 104ac10cf69Smanu Elf_Shdr *sh; 105ac10cf69Smanu 106ac10cf69Smanu int error; 107ac10cf69Smanu 108ac10cf69Smanu /* 109ac10cf69Smanu * load the section header table 110ac10cf69Smanu */ 111ac10cf69Smanu shsize = eh->e_shnum * sizeof(Elf_Shdr); 112ac10cf69Smanu sh = (Elf_Shdr *) malloc(shsize, M_TEMP, M_WAITOK); 11395e1ffb1Schristos error = exec_read_from(l, epp->ep_vp, eh->e_shoff, sh, shsize); 114ac10cf69Smanu if (error) 115ac10cf69Smanu goto out; 116ac10cf69Smanu 117ac10cf69Smanu /* 118ac10cf69Smanu * Now let's find the string table. If it does not exists, give up. 119ac10cf69Smanu */ 120ac10cf69Smanu strndx = (int)(eh->e_shstrndx); 121ac10cf69Smanu if (strndx == SHN_UNDEF) { 122ac10cf69Smanu error = ENOEXEC; 123ac10cf69Smanu goto out; 124ac10cf69Smanu } 125ac10cf69Smanu 126ac10cf69Smanu /* 12797c9d7a9Schristos * strndx is the index in section header table of the string table 12897c9d7a9Schristos * section get the whole string table in strtable, and then we get access to the names 129ac10cf69Smanu * s->sh_name is the offset of the section name in strtable. 130ac10cf69Smanu */ 131ac10cf69Smanu strtable = malloc(sh[strndx].sh_size, M_TEMP, M_WAITOK); 13295e1ffb1Schristos error = exec_read_from(l, epp->ep_vp, sh[strndx].sh_offset, strtable, 13397c9d7a9Schristos sh[strndx].sh_size); 134ac10cf69Smanu if (error) 135ac10cf69Smanu goto out; 136ac10cf69Smanu 137ac10cf69Smanu for (i = 0; i < eh->e_shnum; i++) { 138ac10cf69Smanu Elf_Shdr *s = &sh[i]; 139ac10cf69Smanu if (!memcmp((void*)(&(strtable[s->sh_name])), signature, 140ac10cf69Smanu sizeof(signature))) { 14165fc8539Schristos DPRINTF(("linux_atexit_sig=%s\n", 14265fc8539Schristos &(strtable[s->sh_name]))); 143ac10cf69Smanu error = 0; 144ac10cf69Smanu goto out; 145ac10cf69Smanu } 146ac10cf69Smanu } 147ac10cf69Smanu error = ENOEXEC; 148ac10cf69Smanu 149ac10cf69Smanu out: 150ac10cf69Smanu free(sh, M_TEMP); 1513b6d3c71Schs if (strtable) 152ac10cf69Smanu free(strtable, M_TEMP); 153ac10cf69Smanu return (error); 154ac10cf69Smanu } 155ac10cf69Smanu #endif 156f7ac1bd3Serh 157f7ac1bd3Serh #ifdef LINUX_GCC_SIGNATURE 1584d9a6e09Schristos /* 1594d9a6e09Schristos * Take advantage of the fact that all the linux binaries are compiled 1604d9a6e09Schristos * with gcc, and gcc sticks in the comment field a signature. Note that 1614d9a6e09Schristos * on SVR4 binaries, the gcc signature will follow the OS name signature, 1624d9a6e09Schristos * that will not be a problem. We don't bother to read in the string table, 1634d9a6e09Schristos * but we check all the progbits headers. 164f7ac1bd3Serh * 165f7ac1bd3Serh * XXX This only works in the i386. On the alpha (at least) 166f7ac1bd3Serh * XXX we have the same gcc signature which incorrectly identifies 167f7ac1bd3Serh * XXX NetBSD binaries as Linux. 1684d9a6e09Schristos */ 169ee0c5b44Smanu int 17095e1ffb1Schristos ELFNAME2(linux,gcc_signature)(l, epp, eh) 17195e1ffb1Schristos struct lwp *l; 172fc7cfb5fSfvdl struct exec_package *epp; 173f7ac1bd3Serh Elf_Ehdr *eh; 1744d9a6e09Schristos { 175b29180b2Smycroft size_t shsize; 1764d9a6e09Schristos size_t i; 1774d9a6e09Schristos static const char signature[] = "\0GCC: (GNU) "; 178fb4b40b7Schristos char tbuf[sizeof(signature) - 1]; 179f7ac1bd3Serh Elf_Shdr *sh; 1804d9a6e09Schristos int error; 1814d9a6e09Schristos 182b29180b2Smycroft shsize = eh->e_shnum * sizeof(Elf_Shdr); 183f7ac1bd3Serh sh = (Elf_Shdr *) malloc(shsize, M_TEMP, M_WAITOK); 18495e1ffb1Schristos error = exec_read_from(l, epp->ep_vp, eh->e_shoff, sh, shsize); 185b29180b2Smycroft if (error) 1864d9a6e09Schristos goto out; 1874d9a6e09Schristos 1884d9a6e09Schristos for (i = 0; i < eh->e_shnum; i++) { 189f7ac1bd3Serh Elf_Shdr *s = &sh[i]; 1904d9a6e09Schristos 1914d9a6e09Schristos /* 1924d9a6e09Schristos * Identify candidates for the comment header; 193d83602c1Schristos * Header cannot have a load address, or flags and 1944d9a6e09Schristos * it must be large enough. 1954d9a6e09Schristos */ 196522cbf02Skleink if (s->sh_type != SHT_PROGBITS || 1974d9a6e09Schristos s->sh_addr != 0 || 1984d9a6e09Schristos s->sh_flags != 0 || 1994d9a6e09Schristos s->sh_size < sizeof(signature) - 1) 2004d9a6e09Schristos continue; 2014d9a6e09Schristos 20295e1ffb1Schristos error = exec_read_from(l, epp->ep_vp, s->sh_offset, tbuf, 20397c9d7a9Schristos sizeof(signature) - 1); 204b29180b2Smycroft if (error) 205b29180b2Smycroft continue; 2064d9a6e09Schristos 207d83602c1Schristos /* 208d83602c1Schristos * error is 0, if the signatures match we are done. 209d83602c1Schristos */ 210fb4b40b7Schristos DPRINTF(("linux_gcc_sig: sig=%s\n", tbuf)); 211fb4b40b7Schristos if (!memcmp(tbuf, signature, sizeof(signature) - 1)) { 212b29180b2Smycroft error = 0; 2134d9a6e09Schristos goto out; 2144d9a6e09Schristos } 215b29180b2Smycroft } 216b29180b2Smycroft error = ENOEXEC; 2174d9a6e09Schristos 2184d9a6e09Schristos out: 2194d9a6e09Schristos free(sh, M_TEMP); 220b29180b2Smycroft return (error); 2214d9a6e09Schristos } 222f7ac1bd3Serh #endif 2234d9a6e09Schristos 22405c8a1b8Smanu #ifdef LINUX_DEBUGLINK_SIGNATURE 22505c8a1b8Smanu /* 22605c8a1b8Smanu * Look for a .gnu_debuglink, specific to x86_64 interpeter 22705c8a1b8Smanu */ 22805c8a1b8Smanu int 22905c8a1b8Smanu ELFNAME2(linux,debuglink_signature)(l, epp, eh) 23005c8a1b8Smanu struct lwp *l; 23105c8a1b8Smanu struct exec_package *epp; 23205c8a1b8Smanu Elf_Ehdr *eh; 23305c8a1b8Smanu { 23405c8a1b8Smanu size_t shsize; 23505c8a1b8Smanu int strndx; 23605c8a1b8Smanu size_t i; 23705c8a1b8Smanu static const char signature[] = ".gnu_debuglink"; 23805c8a1b8Smanu char *strtable = NULL; 23905c8a1b8Smanu Elf_Shdr *sh; 24005c8a1b8Smanu 24105c8a1b8Smanu int error; 24205c8a1b8Smanu 24305c8a1b8Smanu /* 24405c8a1b8Smanu * load the section header table 24505c8a1b8Smanu */ 24605c8a1b8Smanu shsize = eh->e_shnum * sizeof(Elf_Shdr); 24705c8a1b8Smanu sh = (Elf_Shdr *) malloc(shsize, M_TEMP, M_WAITOK); 24805c8a1b8Smanu error = exec_read_from(l, epp->ep_vp, eh->e_shoff, sh, shsize); 24905c8a1b8Smanu if (error) 25005c8a1b8Smanu goto out; 25105c8a1b8Smanu 25205c8a1b8Smanu /* 25305c8a1b8Smanu * Now let's find the string table. If it does not exists, give up. 25405c8a1b8Smanu */ 25505c8a1b8Smanu strndx = (int)(eh->e_shstrndx); 25605c8a1b8Smanu if (strndx == SHN_UNDEF) { 25705c8a1b8Smanu error = ENOEXEC; 25805c8a1b8Smanu goto out; 25905c8a1b8Smanu } 26005c8a1b8Smanu 26105c8a1b8Smanu /* 26205c8a1b8Smanu * strndx is the index in section header table of the string table 26305c8a1b8Smanu * section get the whole string table in strtable, and then we get access to the names 26405c8a1b8Smanu * s->sh_name is the offset of the section name in strtable. 26505c8a1b8Smanu */ 26605c8a1b8Smanu strtable = malloc(sh[strndx].sh_size, M_TEMP, M_WAITOK); 26705c8a1b8Smanu error = exec_read_from(l, epp->ep_vp, sh[strndx].sh_offset, strtable, 26805c8a1b8Smanu sh[strndx].sh_size); 26905c8a1b8Smanu if (error) 27005c8a1b8Smanu goto out; 27105c8a1b8Smanu 27205c8a1b8Smanu for (i = 0; i < eh->e_shnum; i++) { 27305c8a1b8Smanu Elf_Shdr *s = &sh[i]; 27405c8a1b8Smanu 27505c8a1b8Smanu if (!memcmp((void*)(&(strtable[s->sh_name])), signature, 27605c8a1b8Smanu sizeof(signature))) { 27705c8a1b8Smanu DPRINTF(("linux_debuglink_sig=%s\n", 27805c8a1b8Smanu &(strtable[s->sh_name]))); 27905c8a1b8Smanu error = 0; 28005c8a1b8Smanu goto out; 28105c8a1b8Smanu } 28205c8a1b8Smanu } 28305c8a1b8Smanu error = ENOEXEC; 28405c8a1b8Smanu 28505c8a1b8Smanu out: 28605c8a1b8Smanu free(sh, M_TEMP); 28705c8a1b8Smanu if (strtable) 28805c8a1b8Smanu free(strtable, M_TEMP); 28905c8a1b8Smanu return (error); 29005c8a1b8Smanu } 29105c8a1b8Smanu #endif 29205c8a1b8Smanu 293ee0c5b44Smanu int 29495e1ffb1Schristos ELFNAME2(linux,signature)(l, epp, eh, itp) 29595e1ffb1Schristos struct lwp *l; 2964d9a6e09Schristos struct exec_package *epp; 297f7ac1bd3Serh Elf_Ehdr *eh; 298b29180b2Smycroft char *itp; 299f7ac1bd3Serh { 300f7ac1bd3Serh size_t i; 301f7ac1bd3Serh Elf_Phdr *ph; 302f7ac1bd3Serh size_t phsize; 303b29180b2Smycroft int error; 3046cc14962Schristos static const char linux[] = "Linux"; 3056cc14962Schristos 3066cc14962Schristos if (eh->e_ident[EI_OSABI] == 3 || 3076cc14962Schristos memcmp(&eh->e_ident[EI_ABIVERSION], linux, sizeof(linux)) == 0) 3086cc14962Schristos return 0; 309f7ac1bd3Serh 310f7ac1bd3Serh phsize = eh->e_phnum * sizeof(Elf_Phdr); 311f7ac1bd3Serh ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK); 31295e1ffb1Schristos error = exec_read_from(l, epp->ep_vp, eh->e_phoff, ph, phsize); 313b29180b2Smycroft if (error) 314b29180b2Smycroft goto out; 315f7ac1bd3Serh 316f7ac1bd3Serh for (i = 0; i < eh->e_phnum; i++) { 317f7ac1bd3Serh Elf_Phdr *ephp = &ph[i]; 318b29180b2Smycroft Elf_Nhdr *np; 319b29180b2Smycroft u_int32_t *abi; 320f7ac1bd3Serh 321b29180b2Smycroft if (ephp->p_type != PT_NOTE || 322b29180b2Smycroft ephp->p_filesz > 1024 || 323b29180b2Smycroft ephp->p_filesz < sizeof(Elf_Nhdr) + 20) 324f7ac1bd3Serh continue; 325f7ac1bd3Serh 326b29180b2Smycroft np = (Elf_Nhdr *)malloc(ephp->p_filesz, M_TEMP, M_WAITOK); 32795e1ffb1Schristos error = exec_read_from(l, epp->ep_vp, ephp->p_offset, np, 32897c9d7a9Schristos ephp->p_filesz); 329b29180b2Smycroft if (error) 330b29180b2Smycroft goto next; 331f7ac1bd3Serh 332b29180b2Smycroft if (np->n_type != ELF_NOTE_TYPE_ABI_TAG || 333b29180b2Smycroft np->n_namesz != ELF_NOTE_ABI_NAMESZ || 334b29180b2Smycroft np->n_descsz != ELF_NOTE_ABI_DESCSZ || 33553524e44Schristos memcmp((void *)(np + 1), ELF_NOTE_ABI_NAME, 336b29180b2Smycroft ELF_NOTE_ABI_NAMESZ)) 337b29180b2Smycroft goto next; 338b29180b2Smycroft 339b29180b2Smycroft /* Make sure the OS is Linux. */ 34053524e44Schristos abi = (u_int32_t *)((char *)np + sizeof(Elf_Nhdr) + 341b29180b2Smycroft np->n_namesz); 342b29180b2Smycroft if (abi[0] == ELF_NOTE_ABI_OS_LINUX) 343f7ac1bd3Serh error = 0; 344b29180b2Smycroft else 345b29180b2Smycroft error = ENOEXEC; 346b29180b2Smycroft free(np, M_TEMP); 347b29180b2Smycroft goto out; 348f7ac1bd3Serh 349b29180b2Smycroft next: 350b29180b2Smycroft free(np, M_TEMP); 351f7ac1bd3Serh continue; 352f7ac1bd3Serh } 353f7ac1bd3Serh 354b29180b2Smycroft /* Check for certain intepreter names. */ 355714de045Sdrochner if (itp) { 356b29180b2Smycroft if (!strncmp(itp, "/lib/ld-linux", 13) || 35789647c7cSmanu #if (ELFSIZE == 64) 35889647c7cSmanu !strncmp(itp, "/lib64/ld-linux", 15) || 35989647c7cSmanu #endif 360b29180b2Smycroft !strncmp(itp, "/lib/ld.so.", 11)) 361f7ac1bd3Serh error = 0; 362b29180b2Smycroft else 363b29180b2Smycroft error = ENOEXEC; 364b29180b2Smycroft goto out; 365f7ac1bd3Serh } 366f7ac1bd3Serh 367f7ac1bd3Serh error = ENOEXEC; 368b29180b2Smycroft out: 369f7ac1bd3Serh free(ph, M_TEMP); 370b29180b2Smycroft return (error); 371f7ac1bd3Serh } 372f7ac1bd3Serh 373f7ac1bd3Serh int 3744d595fd7Schristos ELFNAME2(linux,probe)(struct lwp *l, struct exec_package *epp, void *eh, 375168cd830Schristos char *itp, vaddr_t *pos) 376fc7cfb5fSfvdl { 377fc7cfb5fSfvdl int error; 378fc7cfb5fSfvdl 37995e1ffb1Schristos if (((error = ELFNAME2(linux,signature)(l, epp, eh, itp)) != 0) && 380f7ac1bd3Serh #ifdef LINUX_GCC_SIGNATURE 38195e1ffb1Schristos ((error = ELFNAME2(linux,gcc_signature)(l, epp, eh)) != 0) && 3828537f76cSmanu #endif 383ac10cf69Smanu #ifdef LINUX_ATEXIT_SIGNATURE 38495e1ffb1Schristos ((error = ELFNAME2(linux,atexit_signature)(l, epp, eh)) != 0) && 385ac10cf69Smanu #endif 38605c8a1b8Smanu #ifdef LINUX_DEBUGLINK_SIGNATURE 38705c8a1b8Smanu ((error = ELFNAME2(linux,debuglink_signature)(l, epp, eh)) != 0) && 38805c8a1b8Smanu #endif 38905c8a1b8Smanu 1) { 39005c8a1b8Smanu DPRINTF(("linux_probe: returning %d\n", error)); 3918537f76cSmanu return error; 39205c8a1b8Smanu } 3934d9a6e09Schristos 394714de045Sdrochner if (itp) { 395b8fbaf8cSdsl if ((error = emul_find_interp(l, epp, itp))) 39647cd9b85Sjdolecek return (error); 397fc7cfb5fSfvdl } 39865fc8539Schristos DPRINTF(("linux_probe: returning 0\n")); 399c4aaa600Sfvdl return 0; 400fc7cfb5fSfvdl } 401c4aaa600Sfvdl 402cee43b67Sjdolecek #ifndef LINUX_MACHDEP_ELF_COPYARGS 403cee43b67Sjdolecek /* 404cee43b67Sjdolecek * Copy arguments onto the stack in the normal way, but add some 405cee43b67Sjdolecek * extra information in case of dynamic binding. 406cee43b67Sjdolecek */ 407cee43b67Sjdolecek int 40895e1ffb1Schristos ELFNAME2(linux,copyargs)(struct lwp *l, struct exec_package *pack, 409cee43b67Sjdolecek struct ps_strings *arginfo, char **stackp, void *argp) 410cee43b67Sjdolecek { 411cee43b67Sjdolecek size_t len; 412cee43b67Sjdolecek AuxInfo ai[LINUX_ELF_AUX_ENTRIES], *a; 413cee43b67Sjdolecek struct elf_args *ap; 414cee43b67Sjdolecek int error; 415cee43b67Sjdolecek struct vattr *vap; 416cee43b67Sjdolecek 41795e1ffb1Schristos if ((error = copyargs(l, pack, arginfo, stackp, argp)) != 0) 418cee43b67Sjdolecek return error; 419cee43b67Sjdolecek 420cee43b67Sjdolecek a = ai; 421cee43b67Sjdolecek 422cee43b67Sjdolecek /* 423cee43b67Sjdolecek * Push extra arguments used by glibc on the stack. 424cee43b67Sjdolecek */ 425cee43b67Sjdolecek 426cee43b67Sjdolecek a->a_type = AT_PAGESZ; 427cee43b67Sjdolecek a->a_v = PAGE_SIZE; 428cee43b67Sjdolecek a++; 429cee43b67Sjdolecek 430cee43b67Sjdolecek if ((ap = (struct elf_args *)pack->ep_emul_arg)) { 431cee43b67Sjdolecek 432cee43b67Sjdolecek a->a_type = AT_PHDR; 433cee43b67Sjdolecek a->a_v = ap->arg_phaddr; 434cee43b67Sjdolecek a++; 435cee43b67Sjdolecek 436cee43b67Sjdolecek a->a_type = AT_PHENT; 437cee43b67Sjdolecek a->a_v = ap->arg_phentsize; 438cee43b67Sjdolecek a++; 439cee43b67Sjdolecek 440cee43b67Sjdolecek a->a_type = AT_PHNUM; 441cee43b67Sjdolecek a->a_v = ap->arg_phnum; 442cee43b67Sjdolecek a++; 443cee43b67Sjdolecek 444cee43b67Sjdolecek a->a_type = AT_BASE; 445cee43b67Sjdolecek a->a_v = ap->arg_interp; 446cee43b67Sjdolecek a++; 447cee43b67Sjdolecek 448cee43b67Sjdolecek a->a_type = AT_FLAGS; 449cee43b67Sjdolecek a->a_v = 0; 450cee43b67Sjdolecek a++; 451cee43b67Sjdolecek 452cee43b67Sjdolecek a->a_type = AT_ENTRY; 453cee43b67Sjdolecek a->a_v = ap->arg_entry; 454cee43b67Sjdolecek a++; 455cee43b67Sjdolecek 456cee43b67Sjdolecek free(pack->ep_emul_arg, M_TEMP); 457cee43b67Sjdolecek pack->ep_emul_arg = NULL; 458cee43b67Sjdolecek } 459cee43b67Sjdolecek 460cee43b67Sjdolecek /* Linux-specific items */ 461cee43b67Sjdolecek a->a_type = LINUX_AT_CLKTCK; 462cee43b67Sjdolecek a->a_v = hz; 463cee43b67Sjdolecek a++; 464cee43b67Sjdolecek 465cee43b67Sjdolecek vap = pack->ep_vap; 466cee43b67Sjdolecek 467cee43b67Sjdolecek a->a_type = LINUX_AT_UID; 468f474dcebSad a->a_v = kauth_cred_getuid(l->l_cred); 469cee43b67Sjdolecek a++; 470cee43b67Sjdolecek 471cee43b67Sjdolecek a->a_type = LINUX_AT_EUID; 472cee43b67Sjdolecek if (vap->va_mode & S_ISUID) 473cee43b67Sjdolecek a->a_v = vap->va_uid; 474cee43b67Sjdolecek else 475f474dcebSad a->a_v = kauth_cred_geteuid(l->l_cred); 476cee43b67Sjdolecek a++; 477cee43b67Sjdolecek 478cee43b67Sjdolecek a->a_type = LINUX_AT_GID; 479f474dcebSad a->a_v = kauth_cred_getgid(l->l_cred); 480cee43b67Sjdolecek a++; 481cee43b67Sjdolecek 482cee43b67Sjdolecek a->a_type = LINUX_AT_EGID; 483cee43b67Sjdolecek if (vap->va_mode & S_ISGID) 484cee43b67Sjdolecek a->a_v = vap->va_gid; 485cee43b67Sjdolecek else 486f474dcebSad a->a_v = kauth_cred_getegid(l->l_cred); 487cee43b67Sjdolecek a++; 488cee43b67Sjdolecek 489cee43b67Sjdolecek a->a_type = AT_NULL; 490cee43b67Sjdolecek a->a_v = 0; 491cee43b67Sjdolecek a++; 492cee43b67Sjdolecek 493cee43b67Sjdolecek len = (a - ai) * sizeof(AuxInfo); 494cee43b67Sjdolecek if ((error = copyout(ai, *stackp, len)) != 0) 495cee43b67Sjdolecek return error; 496cee43b67Sjdolecek *stackp += len; 497cee43b67Sjdolecek 498cee43b67Sjdolecek return 0; 499cee43b67Sjdolecek } 500cee43b67Sjdolecek #endif /* !LINUX_MACHDEP_ELF_COPYARGS */ 501