1*47cd9b85Sjdolecek /* $NetBSD: linux_exec_elf32.c,v 1.60 2002/11/29 19:13:16 jdolecek 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*47cd9b85Sjdolecek __KERNEL_RCSID(0, "$NetBSD: linux_exec_elf32.c,v 1.60 2002/11/29 19:13:16 jdolecek 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> 633bf459f3Sfvdl 643bf459f3Sfvdl #include <sys/mman.h> 65151fa70fSchristos #include <sys/syscallargs.h> 66151fa70fSchristos 673bf459f3Sfvdl #include <machine/cpu.h> 683bf459f3Sfvdl #include <machine/reg.h> 693bf459f3Sfvdl 70908291d2Schristos #include <compat/linux/common/linux_types.h> 71908291d2Schristos #include <compat/linux/common/linux_signal.h> 72908291d2Schristos #include <compat/linux/common/linux_util.h> 73908291d2Schristos #include <compat/linux/common/linux_exec.h> 74908291d2Schristos #include <compat/linux/common/linux_machdep.h> 753bf459f3Sfvdl 76908291d2Schristos #include <compat/linux/linux_syscallargs.h> 77908291d2Schristos #include <compat/linux/linux_syscall.h> 78fc7cfb5fSfvdl 79f7ac1bd3Serh static int ELFNAME2(linux,signature) __P((struct proc *, struct exec_package *, 80b29180b2Smycroft Elf_Ehdr *, char *)); 81f7ac1bd3Serh #ifdef LINUX_GCC_SIGNATURE 82f7ac1bd3Serh static int ELFNAME2(linux,gcc_signature) __P((struct proc *p, 83f7ac1bd3Serh struct exec_package *, Elf_Ehdr *)); 84f7ac1bd3Serh #endif 85ac10cf69Smanu #ifdef LINUX_ATEXIT_SIGNATURE 86ac10cf69Smanu static int ELFNAME2(linux,atexit_signature) __P((struct proc *p, 87ac10cf69Smanu struct exec_package *, Elf_Ehdr *)); 88ac10cf69Smanu #endif 89ac10cf69Smanu 9065fc8539Schristos #ifdef DEBUG_LINUX 9165fc8539Schristos #define DPRINTF(a) uprintf a 9265fc8539Schristos #else 9365fc8539Schristos #define DPRINTF(a) 9465fc8539Schristos #endif 9565fc8539Schristos 96ac10cf69Smanu #ifdef LINUX_ATEXIT_SIGNATURE 97ac10cf69Smanu /* 98ac10cf69Smanu * On the PowerPC, statically linked Linux binaries are not recognized 99ac10cf69Smanu * by linux_signature nor by linux_gcc_signature. Fortunately, thoses 100ac10cf69Smanu * binaries features a __libc_atexit ELF section. We therefore assume we 101ac10cf69Smanu * have a Linux binary if we find this section. 102ac10cf69Smanu */ 103ac10cf69Smanu static int 104ac10cf69Smanu ELFNAME2(linux,atexit_signature)(p, epp, eh) 105ac10cf69Smanu struct proc *p; 106ac10cf69Smanu struct exec_package *epp; 107ac10cf69Smanu Elf_Ehdr *eh; 108ac10cf69Smanu { 109ac10cf69Smanu size_t shsize; 110ac10cf69Smanu int strndx; 111ac10cf69Smanu size_t i; 112ac10cf69Smanu static const char signature[] = "__libc_atexit"; 113ac10cf69Smanu char* strtable; 114ac10cf69Smanu Elf_Shdr *sh; 115ac10cf69Smanu 116ac10cf69Smanu int error; 117ac10cf69Smanu 118ac10cf69Smanu /* 119ac10cf69Smanu * load the section header table 120ac10cf69Smanu */ 121ac10cf69Smanu shsize = eh->e_shnum * sizeof(Elf_Shdr); 122ac10cf69Smanu sh = (Elf_Shdr *) malloc(shsize, M_TEMP, M_WAITOK); 12397c9d7a9Schristos error = exec_read_from(p, epp->ep_vp, eh->e_shoff, sh, shsize); 124ac10cf69Smanu if (error) 125ac10cf69Smanu goto out; 126ac10cf69Smanu 127ac10cf69Smanu /* 128ac10cf69Smanu * Now let's find the string table. If it does not exists, give up. 129ac10cf69Smanu */ 130ac10cf69Smanu strndx = (int)(eh->e_shstrndx); 131ac10cf69Smanu if (strndx == SHN_UNDEF) { 132ac10cf69Smanu error = ENOEXEC; 133ac10cf69Smanu goto out; 134ac10cf69Smanu } 135ac10cf69Smanu 136ac10cf69Smanu /* 13797c9d7a9Schristos * strndx is the index in section header table of the string table 13897c9d7a9Schristos * section get the whole string table in strtable, and then we get access to the names 139ac10cf69Smanu * s->sh_name is the offset of the section name in strtable. 140ac10cf69Smanu */ 141ac10cf69Smanu strtable = malloc(sh[strndx].sh_size, M_TEMP, M_WAITOK); 14297c9d7a9Schristos error = exec_read_from(p, epp->ep_vp, sh[strndx].sh_offset, strtable, 14397c9d7a9Schristos sh[strndx].sh_size); 144ac10cf69Smanu if (error) 145ac10cf69Smanu goto out; 146ac10cf69Smanu 147ac10cf69Smanu for (i = 0; i < eh->e_shnum; i++) { 148ac10cf69Smanu Elf_Shdr *s = &sh[i]; 149ac10cf69Smanu if (!memcmp((void*)(&(strtable[s->sh_name])), signature, 150ac10cf69Smanu sizeof(signature))) { 15165fc8539Schristos DPRINTF(("linux_atexit_sig=%s\n", 15265fc8539Schristos &(strtable[s->sh_name]))); 153ac10cf69Smanu error = 0; 154ac10cf69Smanu goto out; 155ac10cf69Smanu } 156ac10cf69Smanu } 157ac10cf69Smanu error = ENOEXEC; 158ac10cf69Smanu 159ac10cf69Smanu out: 160ac10cf69Smanu free(sh, M_TEMP); 161ac10cf69Smanu free(strtable, M_TEMP); 162ac10cf69Smanu return (error); 163ac10cf69Smanu } 164ac10cf69Smanu #endif 165f7ac1bd3Serh 166f7ac1bd3Serh #ifdef LINUX_GCC_SIGNATURE 1674d9a6e09Schristos /* 1684d9a6e09Schristos * Take advantage of the fact that all the linux binaries are compiled 1694d9a6e09Schristos * with gcc, and gcc sticks in the comment field a signature. Note that 1704d9a6e09Schristos * on SVR4 binaries, the gcc signature will follow the OS name signature, 1714d9a6e09Schristos * that will not be a problem. We don't bother to read in the string table, 1724d9a6e09Schristos * but we check all the progbits headers. 173f7ac1bd3Serh * 174f7ac1bd3Serh * XXX This only works in the i386. On the alpha (at least) 175f7ac1bd3Serh * XXX we have the same gcc signature which incorrectly identifies 176f7ac1bd3Serh * XXX NetBSD binaries as Linux. 1774d9a6e09Schristos */ 1784d9a6e09Schristos static int 179f7ac1bd3Serh ELFNAME2(linux,gcc_signature)(p, epp, eh) 180fc7cfb5fSfvdl struct proc *p; 181fc7cfb5fSfvdl struct exec_package *epp; 182f7ac1bd3Serh Elf_Ehdr *eh; 1834d9a6e09Schristos { 184b29180b2Smycroft size_t shsize; 1854d9a6e09Schristos size_t i; 1864d9a6e09Schristos static const char signature[] = "\0GCC: (GNU) "; 1874d9a6e09Schristos char buf[sizeof(signature) - 1]; 188f7ac1bd3Serh Elf_Shdr *sh; 1894d9a6e09Schristos int error; 1904d9a6e09Schristos 191b29180b2Smycroft shsize = eh->e_shnum * sizeof(Elf_Shdr); 192f7ac1bd3Serh sh = (Elf_Shdr *) malloc(shsize, M_TEMP, M_WAITOK); 19397c9d7a9Schristos error = exec_read_from(p, epp->ep_vp, eh->e_shoff, sh, shsize); 194b29180b2Smycroft if (error) 1954d9a6e09Schristos goto out; 1964d9a6e09Schristos 1974d9a6e09Schristos for (i = 0; i < eh->e_shnum; i++) { 198f7ac1bd3Serh Elf_Shdr *s = &sh[i]; 1994d9a6e09Schristos 2004d9a6e09Schristos /* 2014d9a6e09Schristos * Identify candidates for the comment header; 202d83602c1Schristos * Header cannot have a load address, or flags and 2034d9a6e09Schristos * it must be large enough. 2044d9a6e09Schristos */ 205522cbf02Skleink if (s->sh_type != SHT_PROGBITS || 2064d9a6e09Schristos s->sh_addr != 0 || 2074d9a6e09Schristos s->sh_flags != 0 || 2084d9a6e09Schristos s->sh_size < sizeof(signature) - 1) 2094d9a6e09Schristos continue; 2104d9a6e09Schristos 21197c9d7a9Schristos error = exec_read_from(p, epp->ep_vp, s->sh_offset, buf, 21297c9d7a9Schristos sizeof(signature) - 1); 213b29180b2Smycroft if (error) 214b29180b2Smycroft continue; 2154d9a6e09Schristos 216d83602c1Schristos /* 217d83602c1Schristos * error is 0, if the signatures match we are done. 218d83602c1Schristos */ 21965fc8539Schristos DPRINTF(("linux_gcc_sig: sig=%s\n", buf)); 220b29180b2Smycroft if (!memcmp(buf, signature, sizeof(signature) - 1)) { 221b29180b2Smycroft error = 0; 2224d9a6e09Schristos goto out; 2234d9a6e09Schristos } 224b29180b2Smycroft } 225b29180b2Smycroft error = ENOEXEC; 2264d9a6e09Schristos 2274d9a6e09Schristos out: 2284d9a6e09Schristos free(sh, M_TEMP); 229b29180b2Smycroft return (error); 2304d9a6e09Schristos } 231f7ac1bd3Serh #endif 2324d9a6e09Schristos 233f7ac1bd3Serh static int 234b29180b2Smycroft ELFNAME2(linux,signature)(p, epp, eh, itp) 2354d9a6e09Schristos struct proc *p; 2364d9a6e09Schristos struct exec_package *epp; 237f7ac1bd3Serh Elf_Ehdr *eh; 238b29180b2Smycroft char *itp; 239f7ac1bd3Serh { 240f7ac1bd3Serh size_t i; 241f7ac1bd3Serh Elf_Phdr *ph; 242f7ac1bd3Serh size_t phsize; 243b29180b2Smycroft int error; 2446cc14962Schristos static const char linux[] = "Linux"; 2456cc14962Schristos 2466cc14962Schristos if (eh->e_ident[EI_OSABI] == 3 || 2476cc14962Schristos memcmp(&eh->e_ident[EI_ABIVERSION], linux, sizeof(linux)) == 0) 2486cc14962Schristos return 0; 249f7ac1bd3Serh 250f7ac1bd3Serh phsize = eh->e_phnum * sizeof(Elf_Phdr); 251f7ac1bd3Serh ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK); 25297c9d7a9Schristos error = exec_read_from(p, epp->ep_vp, eh->e_phoff, ph, phsize); 253b29180b2Smycroft if (error) 254b29180b2Smycroft goto out; 255f7ac1bd3Serh 256f7ac1bd3Serh for (i = 0; i < eh->e_phnum; i++) { 257f7ac1bd3Serh Elf_Phdr *ephp = &ph[i]; 258b29180b2Smycroft Elf_Nhdr *np; 259b29180b2Smycroft u_int32_t *abi; 260f7ac1bd3Serh 261b29180b2Smycroft if (ephp->p_type != PT_NOTE || 262b29180b2Smycroft ephp->p_filesz > 1024 || 263b29180b2Smycroft ephp->p_filesz < sizeof(Elf_Nhdr) + 20) 264f7ac1bd3Serh continue; 265f7ac1bd3Serh 266b29180b2Smycroft np = (Elf_Nhdr *)malloc(ephp->p_filesz, M_TEMP, M_WAITOK); 26797c9d7a9Schristos error = exec_read_from(p, epp->ep_vp, ephp->p_offset, np, 26897c9d7a9Schristos ephp->p_filesz); 269b29180b2Smycroft if (error) 270b29180b2Smycroft goto next; 271f7ac1bd3Serh 272b29180b2Smycroft if (np->n_type != ELF_NOTE_TYPE_ABI_TAG || 273b29180b2Smycroft np->n_namesz != ELF_NOTE_ABI_NAMESZ || 274b29180b2Smycroft np->n_descsz != ELF_NOTE_ABI_DESCSZ || 275b29180b2Smycroft memcmp((caddr_t)(np + 1), ELF_NOTE_ABI_NAME, 276b29180b2Smycroft ELF_NOTE_ABI_NAMESZ)) 277b29180b2Smycroft goto next; 278b29180b2Smycroft 279b29180b2Smycroft /* Make sure the OS is Linux. */ 280b29180b2Smycroft abi = (u_int32_t *)((caddr_t)np + sizeof(Elf_Nhdr) + 281b29180b2Smycroft np->n_namesz); 282b29180b2Smycroft if (abi[0] == ELF_NOTE_ABI_OS_LINUX) 283f7ac1bd3Serh error = 0; 284b29180b2Smycroft else 285b29180b2Smycroft error = ENOEXEC; 286b29180b2Smycroft free(np, M_TEMP); 287b29180b2Smycroft goto out; 288f7ac1bd3Serh 289b29180b2Smycroft next: 290b29180b2Smycroft free(np, M_TEMP); 291f7ac1bd3Serh continue; 292f7ac1bd3Serh } 293f7ac1bd3Serh 294b29180b2Smycroft /* Check for certain intepreter names. */ 295b29180b2Smycroft if (itp[0]) { 296b29180b2Smycroft if (!strncmp(itp, "/lib/ld-linux", 13) || 297b29180b2Smycroft !strncmp(itp, "/lib/ld.so.", 11)) 298f7ac1bd3Serh error = 0; 299b29180b2Smycroft else 300b29180b2Smycroft error = ENOEXEC; 301b29180b2Smycroft goto out; 302f7ac1bd3Serh } 303f7ac1bd3Serh 304f7ac1bd3Serh error = ENOEXEC; 305b29180b2Smycroft out: 306f7ac1bd3Serh free(ph, M_TEMP); 307b29180b2Smycroft return (error); 308f7ac1bd3Serh } 309f7ac1bd3Serh 310f7ac1bd3Serh int 311f7ac1bd3Serh ELFNAME2(linux,probe)(p, epp, eh, itp, pos) 312f7ac1bd3Serh struct proc *p; 313f7ac1bd3Serh struct exec_package *epp; 314baae0324Sjdolecek void *eh; 315c4aaa600Sfvdl char *itp; 316baae0324Sjdolecek vaddr_t *pos; 317fc7cfb5fSfvdl { 318fc7cfb5fSfvdl int error; 319fc7cfb5fSfvdl 3208537f76cSmanu if (((error = ELFNAME2(linux,signature)(p, epp, eh, itp)) != 0) && 321f7ac1bd3Serh #ifdef LINUX_GCC_SIGNATURE 3228537f76cSmanu ((error = ELFNAME2(linux,gcc_signature)(p, epp, eh)) != 0) && 3238537f76cSmanu #endif 324ac10cf69Smanu #ifdef LINUX_ATEXIT_SIGNATURE 3258537f76cSmanu ((error = ELFNAME2(linux,atexit_signature)(p, epp, eh)) != 0) && 326ac10cf69Smanu #endif 3278537f76cSmanu 1) 3288537f76cSmanu return error; 3294d9a6e09Schristos 330c4aaa600Sfvdl if (itp[0]) { 331*47cd9b85Sjdolecek if ((error = emul_find_interp(p, epp->ep_esch->es_emul->e_path, 332*47cd9b85Sjdolecek itp))) 333*47cd9b85Sjdolecek return (error); 334fc7cfb5fSfvdl } 335f7ac1bd3Serh *pos = ELF_NO_ADDR; 33665fc8539Schristos DPRINTF(("linux_probe: returning 0\n")); 337c4aaa600Sfvdl return 0; 338fc7cfb5fSfvdl } 339c4aaa600Sfvdl 340cee43b67Sjdolecek #ifndef LINUX_MACHDEP_ELF_COPYARGS 341cee43b67Sjdolecek /* 342cee43b67Sjdolecek * Copy arguments onto the stack in the normal way, but add some 343cee43b67Sjdolecek * extra information in case of dynamic binding. 344cee43b67Sjdolecek */ 345cee43b67Sjdolecek int 346cee43b67Sjdolecek ELFNAME2(linux,copyargs)(struct proc *p, struct exec_package *pack, 347cee43b67Sjdolecek struct ps_strings *arginfo, char **stackp, void *argp) 348cee43b67Sjdolecek { 349cee43b67Sjdolecek size_t len; 350cee43b67Sjdolecek AuxInfo ai[LINUX_ELF_AUX_ENTRIES], *a; 351cee43b67Sjdolecek struct elf_args *ap; 352cee43b67Sjdolecek int error; 353cee43b67Sjdolecek struct vattr *vap; 354cee43b67Sjdolecek 355cee43b67Sjdolecek if ((error = copyargs(p, pack, arginfo, stackp, argp)) != 0) 356cee43b67Sjdolecek return error; 357cee43b67Sjdolecek 358cee43b67Sjdolecek a = ai; 359cee43b67Sjdolecek 360cee43b67Sjdolecek /* 361cee43b67Sjdolecek * Push extra arguments used by glibc on the stack. 362cee43b67Sjdolecek */ 363cee43b67Sjdolecek 364cee43b67Sjdolecek a->a_type = AT_PAGESZ; 365cee43b67Sjdolecek a->a_v = PAGE_SIZE; 366cee43b67Sjdolecek a++; 367cee43b67Sjdolecek 368cee43b67Sjdolecek if ((ap = (struct elf_args *)pack->ep_emul_arg)) { 369cee43b67Sjdolecek 370cee43b67Sjdolecek a->a_type = AT_PHDR; 371cee43b67Sjdolecek a->a_v = ap->arg_phaddr; 372cee43b67Sjdolecek a++; 373cee43b67Sjdolecek 374cee43b67Sjdolecek a->a_type = AT_PHENT; 375cee43b67Sjdolecek a->a_v = ap->arg_phentsize; 376cee43b67Sjdolecek a++; 377cee43b67Sjdolecek 378cee43b67Sjdolecek a->a_type = AT_PHNUM; 379cee43b67Sjdolecek a->a_v = ap->arg_phnum; 380cee43b67Sjdolecek a++; 381cee43b67Sjdolecek 382cee43b67Sjdolecek a->a_type = AT_BASE; 383cee43b67Sjdolecek a->a_v = ap->arg_interp; 384cee43b67Sjdolecek a++; 385cee43b67Sjdolecek 386cee43b67Sjdolecek a->a_type = AT_FLAGS; 387cee43b67Sjdolecek a->a_v = 0; 388cee43b67Sjdolecek a++; 389cee43b67Sjdolecek 390cee43b67Sjdolecek a->a_type = AT_ENTRY; 391cee43b67Sjdolecek a->a_v = ap->arg_entry; 392cee43b67Sjdolecek a++; 393cee43b67Sjdolecek 394cee43b67Sjdolecek free(pack->ep_emul_arg, M_TEMP); 395cee43b67Sjdolecek pack->ep_emul_arg = NULL; 396cee43b67Sjdolecek } 397cee43b67Sjdolecek 398cee43b67Sjdolecek /* Linux-specific items */ 399cee43b67Sjdolecek a->a_type = LINUX_AT_CLKTCK; 400cee43b67Sjdolecek a->a_v = hz; 401cee43b67Sjdolecek a++; 402cee43b67Sjdolecek 403cee43b67Sjdolecek vap = pack->ep_vap; 404cee43b67Sjdolecek 405cee43b67Sjdolecek a->a_type = LINUX_AT_UID; 406cee43b67Sjdolecek a->a_v = p->p_cred->p_ruid; 407cee43b67Sjdolecek a++; 408cee43b67Sjdolecek 409cee43b67Sjdolecek a->a_type = LINUX_AT_EUID; 410cee43b67Sjdolecek if (vap->va_mode & S_ISUID) 411cee43b67Sjdolecek a->a_v = vap->va_uid; 412cee43b67Sjdolecek else 413cee43b67Sjdolecek a->a_v = p->p_ucred->cr_uid; 414cee43b67Sjdolecek a++; 415cee43b67Sjdolecek 416cee43b67Sjdolecek a->a_type = LINUX_AT_GID; 417cee43b67Sjdolecek a->a_v = p->p_cred->p_rgid; 418cee43b67Sjdolecek a++; 419cee43b67Sjdolecek 420cee43b67Sjdolecek a->a_type = LINUX_AT_EGID; 421cee43b67Sjdolecek if (vap->va_mode & S_ISGID) 422cee43b67Sjdolecek a->a_v = vap->va_gid; 423cee43b67Sjdolecek else 424cee43b67Sjdolecek a->a_v = p->p_ucred->cr_gid; 425cee43b67Sjdolecek a++; 426cee43b67Sjdolecek 427cee43b67Sjdolecek a->a_type = AT_NULL; 428cee43b67Sjdolecek a->a_v = 0; 429cee43b67Sjdolecek a++; 430cee43b67Sjdolecek 431cee43b67Sjdolecek len = (a - ai) * sizeof(AuxInfo); 432cee43b67Sjdolecek if ((error = copyout(ai, *stackp, len)) != 0) 433cee43b67Sjdolecek return error; 434cee43b67Sjdolecek *stackp += len; 435cee43b67Sjdolecek 436cee43b67Sjdolecek return 0; 437cee43b67Sjdolecek } 438cee43b67Sjdolecek #endif /* !LINUX_MACHDEP_ELF_COPYARGS */ 439