diff options
Diffstat (limited to 'sys/amd64/linux32/linux32_sysvec.c')
-rw-r--r-- | sys/amd64/linux32/linux32_sysvec.c | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c index a08372b66add..58edea923427 100644 --- a/sys/amd64/linux32/linux32_sysvec.c +++ b/sys/amd64/linux32/linux32_sysvec.c @@ -187,11 +187,10 @@ linux_translate_traps(int signal, int trap_code) } 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 @@ linux_copyout_auxargs(struct image_params *imgp, u_long *base) 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 @@ linux_copyout_strings(struct image_params *imgp, uintptr_t *stack_base) 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 @@ linux_copyout_strings(struct image_params *imgp, uintptr_t *stack_base) 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); } |