Index: head/sys/amd64/linux/linux_sysvec.c =================================================================== --- head/sys/amd64/linux/linux_sysvec.c +++ head/sys/amd64/linux/linux_sysvec.c @@ -222,24 +222,17 @@ set_pcb_flags(td->td_pcb, PCB_FULL_IRET); } -static int -linux_fixup_elf(register_t **stack_base, struct image_params *imgp) +static void +linux_copyout_auxargs(struct image_params *imgp, u_long *base) { Elf_Auxargs *args; Elf_Auxinfo *argarray, *pos; - Elf_Addr *auxbase, *base; - struct ps_strings *arginfo; + u_long auxlen; struct proc *p; - int error, issetugid; + int issetugid; p = imgp->proc; - arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings; - - KASSERT(curthread->td_proc == imgp->proc, - ("unsafe linux_fixup_elf(), should be curproc")); - base = (Elf64_Addr *)*stack_base; args = (Elf64_Auxargs *)imgp->auxargs; - auxbase = base + imgp->args->argc + 1 + imgp->args->envc + 1; argarray = pos = malloc(LINUX_AT_COUNT * sizeof(*pos), M_TEMP, M_WAITOK | M_ZERO); @@ -267,15 +260,23 @@ if (args->execfd != -1) AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); AUXARGS_ENTRY(pos, AT_NULL, 0); + free(imgp->auxargs, M_TEMP); imgp->auxargs = NULL; KASSERT(pos - argarray <= LINUX_AT_COUNT, ("Too many auxargs")); - error = copyout(argarray, auxbase, sizeof(*argarray) * LINUX_AT_COUNT); + auxlen = sizeof(*argarray) * (pos - argarray); + *base -= auxlen; + copyout(argarray, (void *)*base, auxlen); free(argarray, M_TEMP); - if (error != 0) - return (error); +} +static int +linux_fixup_elf(register_t **stack_base, struct image_params *imgp) +{ + Elf_Addr *base; + + base = (Elf64_Addr *)*stack_base; base--; if (suword(base, (uint64_t)imgp->args->argc) == -1) return (EFAULT); @@ -327,27 +328,22 @@ copyout(canary, (void *)imgp->canary, sizeof(canary)); vectp = (char **)destp; - if (imgp->auxargs) { - /* - * Allocate room on the stack for the ELF auxargs - * array. It has LINUX_AT_COUNT entries. - */ - vectp -= howmany(LINUX_AT_COUNT * sizeof(Elf64_Auxinfo), - sizeof(*vectp)); - } /* - * Allocate room for the argv[] and env vectors including the - * terminating NULL pointers. - */ - 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); + if (imgp->auxargs) + imgp->sysent->sv_copyout_auxargs(imgp, (u_long *)&vectp); + + /* + * Allocate room for the argv[] and env vectors including the + * terminating NULL pointers. + */ + vectp -= imgp->args->argc + 1 + imgp->args->envc + 1; + /* vectp also becomes our initial stack base. */ stack_base = (register_t *)vectp; @@ -715,6 +711,7 @@ .sv_usrstack = USRSTACK, .sv_psstrings = PS_STRINGS, .sv_stackprot = VM_PROT_ALL, + .sv_copyout_auxargs = linux_copyout_auxargs, .sv_copyout_strings = linux_copyout_strings, .sv_setregs = linux_exec_setregs, .sv_fixlimit = NULL, Index: head/sys/amd64/linux32/linux32_sysvec.c =================================================================== --- head/sys/amd64/linux32/linux32_sysvec.c +++ head/sys/amd64/linux32/linux32_sysvec.c @@ -185,22 +185,15 @@ } } -static int -linux_fixup_elf(register_t **stack_base, struct image_params *imgp) +static void +linux_copyout_auxargs(struct image_params *imgp, u_long *base) { Elf32_Auxargs *args; Elf32_Auxinfo *argarray, *pos; - Elf32_Addr *auxbase, *base; - struct linux32_ps_strings *arginfo; - int error, issetugid; + u_long auxlen; + int issetugid; - arginfo = (struct linux32_ps_strings *)LINUX32_PS_STRINGS; - - KASSERT(curthread->td_proc == imgp->proc, - ("unsafe linux_fixup_elf(), should be curproc")); - base = (Elf32_Addr *)*stack_base; args = (Elf32_Auxargs *)imgp->auxargs; - auxbase = base + (imgp->args->argc + 1 + imgp->args->envc + 1); argarray = pos = malloc(LINUX_AT_COUNT * sizeof(*pos), M_TEMP, M_WAITOK | M_ZERO); @@ -244,12 +237,18 @@ imgp->auxargs = NULL; KASSERT(pos - argarray <= LINUX_AT_COUNT, ("Too many auxargs")); - error = copyout(&argarray[0], auxbase, - sizeof(*argarray) * LINUX_AT_COUNT); + auxlen = sizeof(*argarray) * (pos - argarray); + *base -= auxlen; + copyout(argarray, (void *)*base, auxlen); free(argarray, M_TEMP); - if (error != 0) - return (error); +} +static int +linux_fixup_elf(register_t **stack_base, struct image_params *imgp) +{ + Elf32_Addr *base; + + base = (Elf32_Addr *)*stack_base; base--; if (suword32(base, (uint32_t)imgp->args->argc) == -1) return (EFAULT); @@ -755,14 +754,8 @@ copyout(canary, (void *)imgp->canary, sizeof(canary)); vectp = (uint32_t *)destp; - if (imgp->auxargs) { - /* - * Allocate room on the stack for the ELF auxargs - * array. It has LINUX_AT_COUNT entries. - */ - vectp -= howmany(LINUX_AT_COUNT * sizeof(Elf32_Auxinfo), - sizeof(*vectp)); - } + if (imgp->auxargs) + imgp->sysent->sv_copyout_auxargs(imgp, (u_long *)&vectp); /* * Allocate room for the argv[] and env vectors including the @@ -875,6 +868,7 @@ .sv_usrstack = LINUX32_USRSTACK, .sv_psstrings = LINUX32_PS_STRINGS, .sv_stackprot = VM_PROT_ALL, + .sv_copyout_auxargs = linux_copyout_auxargs, .sv_copyout_strings = linux_copyout_strings, .sv_setregs = linux_exec_setregs, .sv_fixlimit = linux32_fixlimit, Index: head/sys/arm64/linux/linux_sysvec.c =================================================================== --- head/sys/arm64/linux/linux_sysvec.c +++ head/sys/arm64/linux/linux_sysvec.c @@ -87,6 +87,7 @@ /* DTrace probes */ LIN_SDT_PROBE_DEFINE2(sysvec, linux_translate_traps, todo, "int", "int"); LIN_SDT_PROBE_DEFINE0(sysvec, linux_exec_setregs, todo); +LIN_SDT_PROBE_DEFINE0(sysvec, linux_copyout_auxargs, todo); LIN_SDT_PROBE_DEFINE0(sysvec, linux_elf_fixup, todo); LIN_SDT_PROBE_DEFINE0(sysvec, linux_rt_sigreturn, todo); LIN_SDT_PROBE_DEFINE0(sysvec, linux_rt_sendsig, todo); @@ -140,26 +141,19 @@ cpu_set_syscall_retval(td, error); } -static int -linux_elf_fixup(register_t **stack_base, struct image_params *imgp) +static void +linux_copyout_auxargs(struct image_params *imgp, u_long *base) { Elf_Auxargs *args; Elf_Auxinfo *argarray, *pos; - Elf_Addr *auxbase, *base; - struct ps_strings *arginfo; + u_long auxlen; struct proc *p; - int error, issetugid; + int issetugid; - LIN_SDT_PROBE0(sysvec, linux_elf_fixup, todo); + LIN_SDT_PROBE0(sysvec, linux_copyout_auxargs, todo); p = imgp->proc; - arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings; - KASSERT(curthread->td_proc == imgp->proc, - ("unsafe linux_elf_fixup(), should be curproc")); - base = (Elf64_Addr *)*stack_base; args = (Elf64_Auxargs *)imgp->auxargs; - /* Auxargs after argc, and NULL-terminated argv and envv lists. */ - auxbase = base + 1 + imgp->args->argc + 1 + imgp->args->envc + 1; argarray = pos = malloc(LINUX_AT_COUNT * sizeof(*pos), M_TEMP, M_WAITOK | M_ZERO); @@ -195,11 +189,18 @@ imgp->auxargs = NULL; KASSERT(pos - argarray <= LINUX_AT_COUNT, ("Too many auxargs")); - error = copyout(argarray, auxbase, sizeof(*argarray) * LINUX_AT_COUNT); + auxlen = sizeof(*argarray) * (pos - argarray); + *base -= auxlen; + copyout(argarray, (void *)*base, auxlen); free(argarray, M_TEMP); - if (error != 0) - return (error); +} +static int +linux_elf_fixup(register_t **stack_base, struct image_params *imgp) +{ + + LIN_SDT_PROBE0(sysvec, linux_elf_fixup, todo); + return (0); } @@ -247,14 +248,8 @@ copyout(canary, (void *)imgp->canary, sizeof(canary)); vectp = (char **)destp; - if (imgp->auxargs) { - /* - * Allocate room on the stack for the ELF auxargs - * array. It has up to LINUX_AT_COUNT entries. - */ - vectp -= howmany(LINUX_AT_COUNT * sizeof(Elf64_Auxinfo), - sizeof(*vectp)); - } + if (imgp->auxargs) + imgp->sysent->sv_copyout_auxargs(imgp, (u_long *)&vectp); /* * Allocate room for argc and the argv[] and env vectors including the @@ -372,6 +367,7 @@ .sv_usrstack = USRSTACK, .sv_psstrings = PS_STRINGS, /* XXX */ .sv_stackprot = VM_PROT_READ | VM_PROT_WRITE, + .sv_copyout_auxargs = linux_copyout_auxargs, .sv_copyout_strings = linux_copyout_strings, .sv_setregs = linux_exec_setregs, .sv_fixlimit = NULL, Index: head/sys/i386/linux/linux_sysvec.c =================================================================== --- head/sys/i386/linux/linux_sysvec.c +++ head/sys/i386/linux/linux_sysvec.c @@ -188,25 +188,22 @@ return (0); } -static int -linux_fixup_elf(register_t **stack_base, struct image_params *imgp) +static void +linux_copyout_auxargs(struct image_params *imgp, u_long *base) { struct proc *p; Elf32_Auxargs *args; Elf32_Auxinfo *argarray, *pos; - Elf32_Addr *auxbase, *uplatform; + Elf32_Addr *uplatform; struct ps_strings *arginfo; - int error, issetugid; + u_long auxlen; + int issetugid; - KASSERT(curthread->td_proc == imgp->proc, - ("unsafe linux_fixup_elf(), should be curproc")); - p = imgp->proc; issetugid = imgp->proc->p_flag & P_SUGID ? 1 : 0; arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings; uplatform = (Elf32_Addr *)((caddr_t)arginfo - linux_szplatform); args = (Elf32_Auxargs *)imgp->auxargs; - auxbase = *stack_base + imgp->args->argc + 1 + imgp->args->envc + 1; argarray = pos = malloc(LINUX_AT_COUNT * sizeof(*pos), M_TEMP, M_WAITOK | M_ZERO); @@ -249,11 +246,16 @@ imgp->auxargs = NULL; KASSERT(pos - argarray <= LINUX_AT_COUNT, ("Too many auxargs")); - error = copyout(argarray, auxbase, sizeof(*argarray) * LINUX_AT_COUNT); + auxlen = sizeof(*argarray) * (pos - argarray); + *base -= auxlen; + copyout(argarray, (void *)*base, auxlen); free(argarray, M_TEMP); - if (error != 0) - return (error); +} +static int +linux_fixup_elf(register_t **stack_base, struct image_params *imgp) +{ + (*stack_base)--; if (suword(*stack_base, (register_t)imgp->args->argc) == -1) return (EFAULT); @@ -305,14 +307,8 @@ copyout(canary, (void *)imgp->canary, sizeof(canary)); vectp = (char **)destp; - if (imgp->auxargs) { - /* - * Allocate room on the stack for the ELF auxargs - * array. It has LINUX_AT_COUNT entries. - */ - vectp -= howmany(LINUX_AT_COUNT * sizeof(Elf32_Auxinfo), - sizeof(*vectp)); - } + if (imgp->auxargs) + imgp->sysent->sv_copyout_auxargs(imgp, (u_long *)&vectp); /* * Allocate room for the argv[] and env vectors including the @@ -851,6 +847,7 @@ .sv_usrstack = LINUX_USRSTACK, .sv_psstrings = LINUX_PS_STRINGS, .sv_stackprot = VM_PROT_ALL, + .sv_copyout_auxargs = linux_copyout_auxargs, .sv_copyout_strings = linux_copyout_strings, .sv_setregs = linux_exec_setregs, .sv_fixlimit = NULL,