1*c1cf2f47Smaxv /* $NetBSD: linux_exec_elf32.c,v 1.91 2014/04/15 17:29:00 maxv 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*c1cf2f47Smaxv __KERNEL_RCSID(0, "$NetBSD: linux_exec_elf32.c,v 1.91 2014/04/15 17:29:00 maxv 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 7665fc8539Schristos #ifdef DEBUG_LINUX 7765fc8539Schristos #define DPRINTF(a) uprintf a 7865fc8539Schristos #else 7965fc8539Schristos #define DPRINTF(a) 8065fc8539Schristos #endif 8165fc8539Schristos 82ac10cf69Smanu #ifdef LINUX_ATEXIT_SIGNATURE 83ac10cf69Smanu /* 84ac10cf69Smanu * On the PowerPC, statically linked Linux binaries are not recognized 85ac10cf69Smanu * by linux_signature nor by linux_gcc_signature. Fortunately, thoses 86ac10cf69Smanu * binaries features a __libc_atexit ELF section. We therefore assume we 87ac10cf69Smanu * have a Linux binary if we find this section. 88ac10cf69Smanu */ 89ee0c5b44Smanu int 901d7f24eaSmatt ELFNAME2(linux,atexit_signature)( 911d7f24eaSmatt struct lwp *l, 921d7f24eaSmatt struct exec_package *epp, 931d7f24eaSmatt Elf_Ehdr *eh) 94ac10cf69Smanu { 95*c1cf2f47Smaxv Elf_Shdr *sh; 96ac10cf69Smanu size_t shsize; 97*c1cf2f47Smaxv u_int shstrndx; 98ac10cf69Smanu size_t i; 99ac10cf69Smanu static const char signature[] = "__libc_atexit"; 100*c1cf2f47Smaxv const size_t sigsz = sizeof(signature); 101*c1cf2f47Smaxv char tbuf[sizeof(signature)]; 102ac10cf69Smanu int error; 103ac10cf69Smanu 104*c1cf2f47Smaxv /* Load the section header table. */ 105ac10cf69Smanu shsize = eh->e_shnum * sizeof(Elf_Shdr); 106ac10cf69Smanu sh = (Elf_Shdr *) malloc(shsize, M_TEMP, M_WAITOK); 10795e1ffb1Schristos error = exec_read_from(l, epp->ep_vp, eh->e_shoff, sh, shsize); 108ac10cf69Smanu if (error) 109ac10cf69Smanu goto out; 110ac10cf69Smanu 111*c1cf2f47Smaxv /* Now let's find the string table. If it does not exist, give up. */ 112*c1cf2f47Smaxv shstrndx = eh->e_shstrndx; 113*c1cf2f47Smaxv if (shstrndx == SHN_UNDEF || shstrndx >= eh->e_shnum) { 114ac10cf69Smanu error = ENOEXEC; 115ac10cf69Smanu goto out; 116ac10cf69Smanu } 117ac10cf69Smanu 118*c1cf2f47Smaxv /* Check if any section has the name we're looking for. */ 119*c1cf2f47Smaxv const off_t stroff = sh[shstrndx].sh_offset; 120ac10cf69Smanu for (i = 0; i < eh->e_shnum; i++) { 121ac10cf69Smanu Elf_Shdr *s = &sh[i]; 122*c1cf2f47Smaxv 123*c1cf2f47Smaxv if (s->sh_name + sigsz > sh[shstrndx].sh_size) 124*c1cf2f47Smaxv continue; 125*c1cf2f47Smaxv 126*c1cf2f47Smaxv error = exec_read_from(l, epp->ep_vp, stroff + s->sh_name, tbuf, 127*c1cf2f47Smaxv sigsz); 128*c1cf2f47Smaxv if (error) 129*c1cf2f47Smaxv goto out; 130*c1cf2f47Smaxv if (!memcmp(tbuf, signature, sigsz)) { 131*c1cf2f47Smaxv DPRINTF(("linux_atexit_sig=%s\n", tbuf)); 132ac10cf69Smanu error = 0; 133ac10cf69Smanu goto out; 134ac10cf69Smanu } 135ac10cf69Smanu } 136ac10cf69Smanu error = ENOEXEC; 137ac10cf69Smanu 138ac10cf69Smanu out: 139ac10cf69Smanu free(sh, M_TEMP); 140ac10cf69Smanu return (error); 141ac10cf69Smanu } 142ac10cf69Smanu #endif 143f7ac1bd3Serh 144f7ac1bd3Serh #ifdef LINUX_GCC_SIGNATURE 1454d9a6e09Schristos /* 1464d9a6e09Schristos * Take advantage of the fact that all the linux binaries are compiled 1474d9a6e09Schristos * with gcc, and gcc sticks in the comment field a signature. Note that 1484d9a6e09Schristos * on SVR4 binaries, the gcc signature will follow the OS name signature, 1494d9a6e09Schristos * that will not be a problem. We don't bother to read in the string table, 1504d9a6e09Schristos * but we check all the progbits headers. 151f7ac1bd3Serh * 152f7ac1bd3Serh * XXX This only works in the i386. On the alpha (at least) 153f7ac1bd3Serh * XXX we have the same gcc signature which incorrectly identifies 154f7ac1bd3Serh * XXX NetBSD binaries as Linux. 1554d9a6e09Schristos */ 156ee0c5b44Smanu int 1571d7f24eaSmatt ELFNAME2(linux,gcc_signature)( 1581d7f24eaSmatt struct lwp *l, 1591d7f24eaSmatt struct exec_package *epp, 1601d7f24eaSmatt Elf_Ehdr *eh) 1614d9a6e09Schristos { 162b29180b2Smycroft size_t shsize; 1634d9a6e09Schristos size_t i; 1644d9a6e09Schristos static const char signature[] = "\0GCC: (GNU) "; 165fb4b40b7Schristos char tbuf[sizeof(signature) - 1]; 166f7ac1bd3Serh Elf_Shdr *sh; 1674d9a6e09Schristos int error; 1684d9a6e09Schristos 169b29180b2Smycroft shsize = eh->e_shnum * sizeof(Elf_Shdr); 170f7ac1bd3Serh sh = (Elf_Shdr *) malloc(shsize, M_TEMP, M_WAITOK); 17195e1ffb1Schristos error = exec_read_from(l, epp->ep_vp, eh->e_shoff, sh, shsize); 172b29180b2Smycroft if (error) 1734d9a6e09Schristos goto out; 1744d9a6e09Schristos 1754d9a6e09Schristos for (i = 0; i < eh->e_shnum; i++) { 176f7ac1bd3Serh Elf_Shdr *s = &sh[i]; 1774d9a6e09Schristos 1784d9a6e09Schristos /* 1794d9a6e09Schristos * Identify candidates for the comment header; 180d83602c1Schristos * Header cannot have a load address, or flags and 1814d9a6e09Schristos * it must be large enough. 1824d9a6e09Schristos */ 183522cbf02Skleink if (s->sh_type != SHT_PROGBITS || 1844d9a6e09Schristos s->sh_addr != 0 || 1854d9a6e09Schristos s->sh_flags != 0 || 1864d9a6e09Schristos s->sh_size < sizeof(signature) - 1) 1874d9a6e09Schristos continue; 1884d9a6e09Schristos 18995e1ffb1Schristos error = exec_read_from(l, epp->ep_vp, s->sh_offset, tbuf, 19097c9d7a9Schristos sizeof(signature) - 1); 191b29180b2Smycroft if (error) 192b29180b2Smycroft continue; 1934d9a6e09Schristos 194d83602c1Schristos /* 195d83602c1Schristos * error is 0, if the signatures match we are done. 196d83602c1Schristos */ 197fb4b40b7Schristos DPRINTF(("linux_gcc_sig: sig=%s\n", tbuf)); 198fb4b40b7Schristos if (!memcmp(tbuf, signature, sizeof(signature) - 1)) { 199b29180b2Smycroft error = 0; 2004d9a6e09Schristos goto out; 2014d9a6e09Schristos } 202b29180b2Smycroft } 203b29180b2Smycroft error = ENOEXEC; 2044d9a6e09Schristos 2054d9a6e09Schristos out: 2064d9a6e09Schristos free(sh, M_TEMP); 207b29180b2Smycroft return (error); 2084d9a6e09Schristos } 209f7ac1bd3Serh #endif 2104d9a6e09Schristos 21105c8a1b8Smanu #ifdef LINUX_DEBUGLINK_SIGNATURE 21205c8a1b8Smanu /* 213*c1cf2f47Smaxv * Look for a .gnu_debuglink, specific to x86_64 interpreter 21405c8a1b8Smanu */ 21505c8a1b8Smanu int 2169fca5da6Scegger ELFNAME2(linux,debuglink_signature)(struct lwp *l, struct exec_package *epp, Elf_Ehdr *eh) 21705c8a1b8Smanu { 218*c1cf2f47Smaxv Elf_Shdr *sh; 21905c8a1b8Smanu size_t shsize; 220*c1cf2f47Smaxv u_int shstrndx; 22105c8a1b8Smanu size_t i; 22205c8a1b8Smanu static const char signature[] = ".gnu_debuglink"; 223*c1cf2f47Smaxv const size_t sigsz = sizeof(signature); 224*c1cf2f47Smaxv char tbuf[sizeof(signature)]; 22505c8a1b8Smanu int error; 22605c8a1b8Smanu 227*c1cf2f47Smaxv /* Load the section header table. */ 22805c8a1b8Smanu shsize = eh->e_shnum * sizeof(Elf_Shdr); 22905c8a1b8Smanu sh = (Elf_Shdr *) malloc(shsize, M_TEMP, M_WAITOK); 23005c8a1b8Smanu error = exec_read_from(l, epp->ep_vp, eh->e_shoff, sh, shsize); 23105c8a1b8Smanu if (error) 23205c8a1b8Smanu goto out; 23305c8a1b8Smanu 234*c1cf2f47Smaxv /* Now let's find the string table. If it does not exist, give up. */ 235*c1cf2f47Smaxv shstrndx = eh->e_shstrndx; 236*c1cf2f47Smaxv if (shstrndx == SHN_UNDEF || shstrndx >= eh->e_shnum) { 23705c8a1b8Smanu error = ENOEXEC; 23805c8a1b8Smanu goto out; 23905c8a1b8Smanu } 24005c8a1b8Smanu 241*c1cf2f47Smaxv /* Check if any section has the name we're looking for. */ 242*c1cf2f47Smaxv const off_t stroff = sh[shstrndx].sh_offset; 24305c8a1b8Smanu for (i = 0; i < eh->e_shnum; i++) { 24405c8a1b8Smanu Elf_Shdr *s = &sh[i]; 24505c8a1b8Smanu 246*c1cf2f47Smaxv if (s->sh_name + sigsz > sh[shstrndx].sh_size) 247*c1cf2f47Smaxv continue; 248*c1cf2f47Smaxv 249*c1cf2f47Smaxv error = exec_read_from(l, epp->ep_vp, stroff + s->sh_name, tbuf, 250*c1cf2f47Smaxv sigsz); 251*c1cf2f47Smaxv if (error) 252*c1cf2f47Smaxv goto out; 253*c1cf2f47Smaxv if (!memcmp(tbuf, signature, sigsz)) { 254*c1cf2f47Smaxv DPRINTF(("linux_debuglink_sig=%s\n", tbuf)); 25505c8a1b8Smanu error = 0; 25605c8a1b8Smanu goto out; 25705c8a1b8Smanu } 25805c8a1b8Smanu } 25905c8a1b8Smanu error = ENOEXEC; 26005c8a1b8Smanu 26105c8a1b8Smanu out: 26205c8a1b8Smanu free(sh, M_TEMP); 26305c8a1b8Smanu return (error); 26405c8a1b8Smanu } 26505c8a1b8Smanu #endif 26605c8a1b8Smanu 267ee0c5b44Smanu int 2689fca5da6Scegger ELFNAME2(linux,signature)(struct lwp *l, struct exec_package *epp, Elf_Ehdr *eh, char *itp) 269f7ac1bd3Serh { 270f7ac1bd3Serh size_t i; 271f7ac1bd3Serh Elf_Phdr *ph; 272f7ac1bd3Serh size_t phsize; 273b29180b2Smycroft int error; 2746cc14962Schristos static const char linux[] = "Linux"; 2756cc14962Schristos 2766cc14962Schristos if (eh->e_ident[EI_OSABI] == 3 || 2776cc14962Schristos memcmp(&eh->e_ident[EI_ABIVERSION], linux, sizeof(linux)) == 0) 2786cc14962Schristos return 0; 279f7ac1bd3Serh 280f7ac1bd3Serh phsize = eh->e_phnum * sizeof(Elf_Phdr); 281f7ac1bd3Serh ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK); 28295e1ffb1Schristos error = exec_read_from(l, epp->ep_vp, eh->e_phoff, ph, phsize); 283b29180b2Smycroft if (error) 284b29180b2Smycroft goto out; 285f7ac1bd3Serh 286f7ac1bd3Serh for (i = 0; i < eh->e_phnum; i++) { 287f7ac1bd3Serh Elf_Phdr *ephp = &ph[i]; 288b29180b2Smycroft Elf_Nhdr *np; 289b29180b2Smycroft u_int32_t *abi; 290f7ac1bd3Serh 291b29180b2Smycroft if (ephp->p_type != PT_NOTE || 292b29180b2Smycroft ephp->p_filesz > 1024 || 293b29180b2Smycroft ephp->p_filesz < sizeof(Elf_Nhdr) + 20) 294f7ac1bd3Serh continue; 295f7ac1bd3Serh 296b29180b2Smycroft np = (Elf_Nhdr *)malloc(ephp->p_filesz, M_TEMP, M_WAITOK); 29795e1ffb1Schristos error = exec_read_from(l, epp->ep_vp, ephp->p_offset, np, 29897c9d7a9Schristos ephp->p_filesz); 299b29180b2Smycroft if (error) 300b29180b2Smycroft goto next; 301f7ac1bd3Serh 302b29180b2Smycroft if (np->n_type != ELF_NOTE_TYPE_ABI_TAG || 303b29180b2Smycroft np->n_namesz != ELF_NOTE_ABI_NAMESZ || 304b29180b2Smycroft np->n_descsz != ELF_NOTE_ABI_DESCSZ || 30553524e44Schristos memcmp((void *)(np + 1), ELF_NOTE_ABI_NAME, 306b29180b2Smycroft ELF_NOTE_ABI_NAMESZ)) 307b29180b2Smycroft goto next; 308b29180b2Smycroft 309b29180b2Smycroft /* Make sure the OS is Linux. */ 31053524e44Schristos abi = (u_int32_t *)((char *)np + sizeof(Elf_Nhdr) + 311b29180b2Smycroft np->n_namesz); 312b29180b2Smycroft if (abi[0] == ELF_NOTE_ABI_OS_LINUX) 313f7ac1bd3Serh error = 0; 314b29180b2Smycroft else 315b29180b2Smycroft error = ENOEXEC; 316b29180b2Smycroft free(np, M_TEMP); 317b29180b2Smycroft goto out; 318f7ac1bd3Serh 319b29180b2Smycroft next: 320b29180b2Smycroft free(np, M_TEMP); 321f7ac1bd3Serh continue; 322f7ac1bd3Serh } 323f7ac1bd3Serh 324*c1cf2f47Smaxv /* Check for certain interpreter names. */ 325714de045Sdrochner if (itp) { 326b29180b2Smycroft if (!strncmp(itp, "/lib/ld-linux", 13) || 32789647c7cSmanu #if (ELFSIZE == 64) 32889647c7cSmanu !strncmp(itp, "/lib64/ld-linux", 15) || 32989647c7cSmanu #endif 330b29180b2Smycroft !strncmp(itp, "/lib/ld.so.", 11)) 331f7ac1bd3Serh error = 0; 332b29180b2Smycroft else 333b29180b2Smycroft error = ENOEXEC; 334b29180b2Smycroft goto out; 335f7ac1bd3Serh } 336f7ac1bd3Serh 337f7ac1bd3Serh error = ENOEXEC; 338b29180b2Smycroft out: 339f7ac1bd3Serh free(ph, M_TEMP); 340b29180b2Smycroft return (error); 341f7ac1bd3Serh } 342f7ac1bd3Serh 343f7ac1bd3Serh int 3444d595fd7Schristos ELFNAME2(linux,probe)(struct lwp *l, struct exec_package *epp, void *eh, 345168cd830Schristos char *itp, vaddr_t *pos) 346fc7cfb5fSfvdl { 347fc7cfb5fSfvdl int error; 348fc7cfb5fSfvdl 34995e1ffb1Schristos if (((error = ELFNAME2(linux,signature)(l, epp, eh, itp)) != 0) && 350f7ac1bd3Serh #ifdef LINUX_GCC_SIGNATURE 35195e1ffb1Schristos ((error = ELFNAME2(linux,gcc_signature)(l, epp, eh)) != 0) && 3528537f76cSmanu #endif 353ac10cf69Smanu #ifdef LINUX_ATEXIT_SIGNATURE 35495e1ffb1Schristos ((error = ELFNAME2(linux,atexit_signature)(l, epp, eh)) != 0) && 355ac10cf69Smanu #endif 35605c8a1b8Smanu #ifdef LINUX_DEBUGLINK_SIGNATURE 35705c8a1b8Smanu ((error = ELFNAME2(linux,debuglink_signature)(l, epp, eh)) != 0) && 35805c8a1b8Smanu #endif 35905c8a1b8Smanu 1) { 36005c8a1b8Smanu DPRINTF(("linux_probe: returning %d\n", error)); 3618537f76cSmanu return error; 36205c8a1b8Smanu } 3634d9a6e09Schristos 364714de045Sdrochner if (itp) { 365b8fbaf8cSdsl if ((error = emul_find_interp(l, epp, itp))) 36647cd9b85Sjdolecek return (error); 367fc7cfb5fSfvdl } 368590b9069Schs epp->ep_flags |= EXEC_FORCEAUX; 36965fc8539Schristos DPRINTF(("linux_probe: returning 0\n")); 370c4aaa600Sfvdl return 0; 371fc7cfb5fSfvdl } 372c4aaa600Sfvdl 373cee43b67Sjdolecek #ifndef LINUX_MACHDEP_ELF_COPYARGS 374cee43b67Sjdolecek /* 375cee43b67Sjdolecek * Copy arguments onto the stack in the normal way, but add some 376cee43b67Sjdolecek * extra information in case of dynamic binding. 377cee43b67Sjdolecek */ 378cee43b67Sjdolecek int 37995e1ffb1Schristos ELFNAME2(linux,copyargs)(struct lwp *l, struct exec_package *pack, 380cee43b67Sjdolecek struct ps_strings *arginfo, char **stackp, void *argp) 381cee43b67Sjdolecek { 382cee43b67Sjdolecek size_t len; 383cee43b67Sjdolecek AuxInfo ai[LINUX_ELF_AUX_ENTRIES], *a; 384cee43b67Sjdolecek struct elf_args *ap; 385cee43b67Sjdolecek int error; 386cee43b67Sjdolecek struct vattr *vap; 3872084516cSchs uint32_t randbytes[4]; 388cee43b67Sjdolecek 38995e1ffb1Schristos if ((error = copyargs(l, pack, arginfo, stackp, argp)) != 0) 390cee43b67Sjdolecek return error; 391cee43b67Sjdolecek 392cee43b67Sjdolecek a = ai; 393cee43b67Sjdolecek 394cee43b67Sjdolecek /* 395cee43b67Sjdolecek * Push extra arguments used by glibc on the stack. 396cee43b67Sjdolecek */ 397cee43b67Sjdolecek 398cee43b67Sjdolecek a->a_type = AT_PAGESZ; 399cee43b67Sjdolecek a->a_v = PAGE_SIZE; 400cee43b67Sjdolecek a++; 401cee43b67Sjdolecek 402cee43b67Sjdolecek if ((ap = (struct elf_args *)pack->ep_emul_arg)) { 403cee43b67Sjdolecek 404cee43b67Sjdolecek a->a_type = AT_PHDR; 405cee43b67Sjdolecek a->a_v = ap->arg_phaddr; 406cee43b67Sjdolecek a++; 407cee43b67Sjdolecek 408cee43b67Sjdolecek a->a_type = AT_PHENT; 409cee43b67Sjdolecek a->a_v = ap->arg_phentsize; 410cee43b67Sjdolecek a++; 411cee43b67Sjdolecek 412cee43b67Sjdolecek a->a_type = AT_PHNUM; 413cee43b67Sjdolecek a->a_v = ap->arg_phnum; 414cee43b67Sjdolecek a++; 415cee43b67Sjdolecek 416cee43b67Sjdolecek a->a_type = AT_BASE; 417cee43b67Sjdolecek a->a_v = ap->arg_interp; 418cee43b67Sjdolecek a++; 419cee43b67Sjdolecek 420cee43b67Sjdolecek a->a_type = AT_FLAGS; 421cee43b67Sjdolecek a->a_v = 0; 422cee43b67Sjdolecek a++; 423cee43b67Sjdolecek 424cee43b67Sjdolecek a->a_type = AT_ENTRY; 425cee43b67Sjdolecek a->a_v = ap->arg_entry; 426cee43b67Sjdolecek a++; 427cee43b67Sjdolecek 4282210079eSmatt exec_free_emul_arg(pack); 429cee43b67Sjdolecek } 430cee43b67Sjdolecek 431cee43b67Sjdolecek /* Linux-specific items */ 432cee43b67Sjdolecek a->a_type = LINUX_AT_CLKTCK; 433cee43b67Sjdolecek a->a_v = hz; 434cee43b67Sjdolecek a++; 435cee43b67Sjdolecek 436cee43b67Sjdolecek vap = pack->ep_vap; 437cee43b67Sjdolecek 438cee43b67Sjdolecek a->a_type = LINUX_AT_UID; 439f474dcebSad a->a_v = kauth_cred_getuid(l->l_cred); 440cee43b67Sjdolecek a++; 441cee43b67Sjdolecek 442cee43b67Sjdolecek a->a_type = LINUX_AT_EUID; 443cee43b67Sjdolecek if (vap->va_mode & S_ISUID) 444cee43b67Sjdolecek a->a_v = vap->va_uid; 445cee43b67Sjdolecek else 446f474dcebSad a->a_v = kauth_cred_geteuid(l->l_cred); 447cee43b67Sjdolecek a++; 448cee43b67Sjdolecek 449cee43b67Sjdolecek a->a_type = LINUX_AT_GID; 450f474dcebSad a->a_v = kauth_cred_getgid(l->l_cred); 451cee43b67Sjdolecek a++; 452cee43b67Sjdolecek 453cee43b67Sjdolecek a->a_type = LINUX_AT_EGID; 454cee43b67Sjdolecek if (vap->va_mode & S_ISGID) 455cee43b67Sjdolecek a->a_v = vap->va_gid; 456cee43b67Sjdolecek else 457f474dcebSad a->a_v = kauth_cred_getegid(l->l_cred); 458cee43b67Sjdolecek a++; 459cee43b67Sjdolecek 4602084516cSchs a->a_type = LINUX_AT_RANDOM; 4612084516cSchs a->a_v = (Elf_Addr)*stackp; 4622084516cSchs a++; 4632084516cSchs 464cee43b67Sjdolecek a->a_type = AT_NULL; 465cee43b67Sjdolecek a->a_v = 0; 466cee43b67Sjdolecek a++; 467cee43b67Sjdolecek 468e5a75de9Schs randbytes[0] = cprng_strong32(); 469e5a75de9Schs randbytes[1] = cprng_strong32(); 470e5a75de9Schs randbytes[2] = cprng_strong32(); 471e5a75de9Schs randbytes[3] = cprng_strong32(); 4722084516cSchs 4732084516cSchs len = sizeof(randbytes); 4742084516cSchs if ((error = copyout(randbytes, *stackp, len)) != 0) 4752084516cSchs return error; 4762084516cSchs *stackp += len; 4772084516cSchs 478cee43b67Sjdolecek len = (a - ai) * sizeof(AuxInfo); 4796e5d6d35Snjoly KASSERT(len <= LINUX_ELF_AUX_ENTRIES * sizeof(AuxInfo)); 480cee43b67Sjdolecek if ((error = copyout(ai, *stackp, len)) != 0) 481cee43b67Sjdolecek return error; 482cee43b67Sjdolecek *stackp += len; 483cee43b67Sjdolecek 484cee43b67Sjdolecek return 0; 485cee43b67Sjdolecek } 486cee43b67Sjdolecek #endif /* !LINUX_MACHDEP_ELF_COPYARGS */ 487