Index: sys/amd64/linux/linux_sysvec.c =================================================================== --- sys/amd64/linux/linux_sysvec.c +++ sys/amd64/linux/linux_sysvec.c @@ -224,11 +224,10 @@ } static int -linux_copyout_auxargs(struct image_params *imgp, uintptr_t *base) +linux_copyout_auxargs(struct image_params *imgp, uintptr_t base) { Elf_Auxargs *args; Elf_Auxinfo *argarray, *pos; - u_long auxlen; struct proc *p; int error, issetugid; @@ -266,9 +265,8 @@ imgp->auxargs = NULL; KASSERT(pos - argarray <= LINUX_AT_COUNT, ("Too many auxargs")); - auxlen = sizeof(*argarray) * (pos - argarray); - *base -= auxlen; - error = copyout(argarray, (void *)*base, auxlen); + error = copyout(argarray, (void *)base, + sizeof(*argarray) * LINUX_AT_COUNT); free(argarray, M_TEMP); return (error); } @@ -336,17 +334,13 @@ destp = rounddown2(destp, sizeof(void *)); ustringp = destp; - /* - * Starting with 2.24, glibc depends on a 16-byte stack alignment. - * One "long argc" will be prepended later. - */ - if (destp % 16 == 0) - destp -= 8; - if (imgp->auxargs) { - error = imgp->sysent->sv_copyout_auxargs(imgp, &destp); - if (error != 0) - return (error); + /* + * Allocate room on the stack for the ELF auxargs + * array. It has LINUX_AT_COUNT entries. + */ + destp -= LINUX_AT_COUNT * sizeof(Elf64_Auxinfo); + destp = rounddown2(destp, sizeof(void *)); } vectp = (char **)destp; @@ -357,6 +351,12 @@ */ vectp -= imgp->args->argc + 1 + imgp->args->envc + 1; + /* + * Starting with 2.24, glibc depends on a 16-byte stack alignment. + * One "long argc" will be prepended later. + */ + vectp = (char **)((((uintptr_t)vectp + 8) & ~0xF) - 8); + /* vectp also becomes our initial stack base. */ *stack_base = (uintptr_t)vectp; @@ -405,6 +405,14 @@ if (suword(vectp, 0) != 0) return (EFAULT); + if (imgp->auxargs) { + vectp++; + error = imgp->sysent->sv_copyout_auxargs(imgp, + (uintptr_t)vectp); + if (error != 0) + return (error); + } + return (0); } Index: sys/amd64/linux32/linux32_sysvec.c =================================================================== --- sys/amd64/linux32/linux32_sysvec.c +++ sys/amd64/linux32/linux32_sysvec.c @@ -187,11 +187,10 @@ } static int -linux_copyout_auxargs(struct image_params *imgp, u_long *base) +linux_copyout_auxargs(struct image_params *imgp, uintptr_t base) { Elf32_Auxargs *args; Elf32_Auxinfo *argarray, *pos; - u_long auxlen; int error, issetugid; args = (Elf32_Auxargs *)imgp->auxargs; @@ -238,9 +237,8 @@ imgp->auxargs = NULL; KASSERT(pos - argarray <= LINUX_AT_COUNT, ("Too many auxargs")); - auxlen = sizeof(*argarray) * (pos - argarray); - *base -= auxlen; - error = copyout(argarray, (void *)*base, auxlen); + error = copyout(argarray, (void *)base, + sizeof(*argarray) * LINUX_AT_COUNT); free(argarray, M_TEMP); return (error); } @@ -764,9 +762,12 @@ ustringp = destp; if (imgp->auxargs) { - error = imgp->sysent->sv_copyout_auxargs(imgp, &destp); - if (error != 0) - return (error); + /* + * Allocate room on the stack for the ELF auxargs + * array. It has LINUX_AT_COUNT entries. + */ + destp -= LINUX_AT_COUNT * sizeof(Elf32_Auxinfo); + destp = rounddown2(destp, sizeof(void *)); } vectp = (uint32_t *)destp; @@ -825,6 +826,14 @@ if (suword32(vectp, 0) != 0) return (EFAULT); + if (imgp->auxargs) { + vectp++; + error = imgp->sysent->sv_copyout_auxargs(imgp, + (uintptr_t)vectp); + if (error != 0) + return (error); + } + return (0); } Index: sys/arm64/linux/linux_sysvec.c =================================================================== --- sys/arm64/linux/linux_sysvec.c +++ sys/arm64/linux/linux_sysvec.c @@ -143,11 +143,10 @@ } static int -linux_copyout_auxargs(struct image_params *imgp, uintptr_t *base) +linux_copyout_auxargs(struct image_params *imgp, uintptr_t base) { Elf_Auxargs *args; Elf_Auxinfo *argarray, *pos; - u_long auxlen; struct proc *p; int error, issetugid; @@ -190,9 +189,8 @@ imgp->auxargs = NULL; KASSERT(pos - argarray <= LINUX_AT_COUNT, ("Too many auxargs")); - auxlen = sizeof(*argarray) * (pos - argarray); - *base -= auxlen; - error = copyout(argarray, (void *)*base, auxlen); + error = copyout(argarray, (void *)base, + sizeof(*argarray) * LINUX_AT_COUNT); free(argarray, M_TEMP); return (error); } @@ -257,9 +255,12 @@ ustringp = destp; if (imgp->auxargs) { - error = imgp->sysent->sv_copyout_auxargs(imgp, &destp); - if (error != 0) - return (error); + /* + * Allocate room on the stack for the ELF auxargs + * array. It has up to LINUX_AT_COUNT entries. + */ + destp -= LINUX_AT_COUNT * sizeof(Elf64_Auxinfo); + destp = rounddown2(destp, sizeof(void *)); } vectp = (char **)destp; @@ -322,6 +323,14 @@ if (suword(vectp, 0) != 0) return (EFAULT); + if (imgp->auxargs) { + vectp++; + error = imgp->sysent->sv_copyout_auxargs(imgp, + (uintptr_t)vectp); + if (error != 0) + return (error); + } + return (0); } Index: sys/compat/freebsd32/freebsd32_misc.c =================================================================== --- sys/compat/freebsd32/freebsd32_misc.c +++ sys/compat/freebsd32/freebsd32_misc.c @@ -3206,9 +3206,12 @@ imgp->sysent->sv_stackgap(imgp, &destp); if (imgp->auxargs) { - error = imgp->sysent->sv_copyout_auxargs(imgp, &destp); - if (error != 0) - return (error); + /* + * Allocate room on the stack for the ELF auxargs + * array. It has up to AT_COUNT entries. + */ + destp -= AT_COUNT * sizeof(Elf32_Auxinfo); + destp = rounddown2(destp, sizeof(uint32_t)); } vectp = (uint32_t *)destp; @@ -3276,6 +3279,14 @@ if (suword32(vectp, 0) != 0) return (EFAULT); + if (imgp->auxargs) { + vectp++; + error = imgp->sysent->sv_copyout_auxargs(imgp, + (uintptr_t)vectp); + if (error != 0) + return (error); + } + return (0); } Index: sys/i386/linux/linux_sysvec.c =================================================================== --- sys/i386/linux/linux_sysvec.c +++ sys/i386/linux/linux_sysvec.c @@ -192,14 +192,13 @@ } static int -linux_copyout_auxargs(struct image_params *imgp, uintptr_t *base) +linux_copyout_auxargs(struct image_params *imgp, uintptr_t base) { struct proc *p; Elf32_Auxargs *args; Elf32_Auxinfo *argarray, *pos; Elf32_Addr *uplatform; struct ps_strings *arginfo; - u_long auxlen; int error, issetugid; p = imgp->proc; @@ -249,9 +248,8 @@ imgp->auxargs = NULL; KASSERT(pos - argarray <= LINUX_AT_COUNT, ("Too many auxargs")); - auxlen = sizeof(*argarray) * (pos - argarray); - *base -= auxlen; - error = copyout(argarray, (void *)*base, auxlen); + error = copyout(argarray, (void *)base, + sizeof(*argarray) * LINUX_AT_COUNT); free(argarray, M_TEMP); return (error); } @@ -323,9 +321,12 @@ ustringp = destp; if (imgp->auxargs) { - error = imgp->sysent->sv_copyout_auxargs(imgp, &destp); - if (error != 0) - return (error); + /* + * Allocate room on the stack for the ELF auxargs + * array. It has LINUX_AT_COUNT entries. + */ + destp -= LINUX_AT_COUNT * sizeof(Elf32_Auxinfo); + destp = rounddown2(destp, sizeof(void *)); } vectp = (char **)destp; @@ -384,6 +385,14 @@ if (suword(vectp, 0) != 0) return (EFAULT); + if (imgp->auxargs) { + vectp++; + error = imgp->sysent->sv_copyout_auxargs(imgp, + (uintptr_t)vectp); + if (error != 0) + return (error); + } + return (0); } Index: sys/kern/imgact_elf.c =================================================================== --- sys/kern/imgact_elf.c +++ sys/kern/imgact_elf.c @@ -1324,11 +1324,10 @@ #define suword __CONCAT(suword, __ELF_WORD_SIZE) int -__elfN(freebsd_copyout_auxargs)(struct image_params *imgp, uintptr_t *base) +__elfN(freebsd_copyout_auxargs)(struct image_params *imgp, uintptr_t base) { Elf_Auxargs *args = (Elf_Auxargs *)imgp->auxargs; Elf_Auxinfo *argarray, *pos; - u_long auxlen; int error; argarray = pos = malloc(AT_COUNT * sizeof(*pos), M_TEMP, @@ -1374,9 +1373,7 @@ imgp->auxargs = NULL; KASSERT(pos - argarray <= AT_COUNT, ("Too many auxargs")); - auxlen = sizeof(*argarray) * (pos - argarray); - *base -= auxlen; - error = copyout(argarray, (void *)*base, auxlen); + error = copyout(argarray, (void *)base, sizeof(*argarray) * AT_COUNT); free(argarray, M_TEMP); return (error); } Index: sys/kern/kern_exec.c =================================================================== --- sys/kern/kern_exec.c +++ sys/kern/kern_exec.c @@ -1661,9 +1661,12 @@ imgp->sysent->sv_stackgap(imgp, &destp); if (imgp->auxargs) { - error = imgp->sysent->sv_copyout_auxargs(imgp, &destp); - if (error != 0) - return (error); + /* + * Allocate room on the stack for the ELF auxargs + * array. It has up to AT_COUNT entries. + */ + destp -= AT_COUNT * sizeof(Elf_Auxinfo); + destp = rounddown2(destp, sizeof(void *)); } vectp = (char **)destp; @@ -1732,6 +1735,14 @@ if (suword(vectp, 0) != 0) return (EFAULT); + if (imgp->auxargs) { + vectp++; + error = imgp->sysent->sv_copyout_auxargs(imgp, + (uintptr_t)vectp); + if (error != 0) + return (error); + } + return (0); } Index: sys/sys/imgact_elf.h =================================================================== --- sys/sys/imgact_elf.h +++ sys/sys/imgact_elf.h @@ -99,7 +99,7 @@ int __elfN(coredump)(struct thread *, struct vnode *, off_t, int); size_t __elfN(populate_note)(int, void *, void *, size_t, void **); void __elfN(stackgap)(struct image_params *, uintptr_t *); -int __elfN(freebsd_copyout_auxargs)(struct image_params *, uintptr_t *); +int __elfN(freebsd_copyout_auxargs)(struct image_params *, uintptr_t); /* Machine specific function to dump per-thread information. */ void __elfN(dump_thread)(struct thread *, void *, size_t *); Index: sys/sys/sysent.h =================================================================== --- sys/sys/sysent.h +++ sys/sys/sysent.h @@ -111,7 +111,7 @@ int (*sv_imgact_try)(struct image_params *); void (*sv_stackgap)(struct image_params *, uintptr_t *); int (*sv_copyout_auxargs)(struct image_params *, - uintptr_t *); + uintptr_t); int sv_minsigstksz; /* minimum signal stack size */ vm_offset_t sv_minuser; /* VM_MIN_ADDRESS */ vm_offset_t sv_maxuser; /* VM_MAXUSER_ADDRESS */