Date: Fri, 15 Nov 2019 23:01:43 +0000 (UTC) From: John Baldwin <jhb@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r354754 - in head/sys: amd64/linux amd64/linux32 arm64/linux i386/linux Message-ID: <201911152301.xAFN1hBM046422@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jhb Date: Fri Nov 15 23:01:43 2019 New Revision: 354754 URL: https://svnweb.freebsd.org/changeset/base/354754 Log: Use a sv_copyout_auxargs hook in the Linux ELF ABIs. Reviewed by: emaste Tested on: amd64 (linux64 only), i386 Sponsored by: DARPA Differential Revision: https://reviews.freebsd.org/D22356 Modified: head/sys/amd64/linux/linux_sysvec.c head/sys/amd64/linux32/linux32_sysvec.c head/sys/arm64/linux/linux_sysvec.c head/sys/i386/linux/linux_sysvec.c Modified: head/sys/amd64/linux/linux_sysvec.c ============================================================================== --- head/sys/amd64/linux/linux_sysvec.c Fri Nov 15 23:01:09 2019 (r354753) +++ head/sys/amd64/linux/linux_sysvec.c Fri Nov 15 23:01:43 2019 (r354754) @@ -222,24 +222,17 @@ linux_set_syscall_retval(struct thread *td, int error) 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 @@ linux_fixup_elf(register_t **stack_base, struct image_ 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 @@ linux_copyout_strings(struct image_params *imgp) 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 @@ struct sysentvec elf_linux_sysvec = { .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, Modified: head/sys/amd64/linux32/linux32_sysvec.c ============================================================================== --- head/sys/amd64/linux32/linux32_sysvec.c Fri Nov 15 23:01:09 2019 (r354753) +++ head/sys/amd64/linux32/linux32_sysvec.c Fri Nov 15 23:01:43 2019 (r354754) @@ -185,22 +185,15 @@ linux_translate_traps(int signal, int trap_code) } } -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 @@ linux_fixup_elf(register_t **stack_base, struct image_ 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 @@ linux_copyout_strings(struct image_params *imgp) 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 @@ struct sysentvec elf_linux_sysvec = { .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, Modified: head/sys/arm64/linux/linux_sysvec.c ============================================================================== --- head/sys/arm64/linux/linux_sysvec.c Fri Nov 15 23:01:09 2019 (r354753) +++ head/sys/arm64/linux/linux_sysvec.c Fri Nov 15 23:01:43 2019 (r354754) @@ -87,6 +87,7 @@ LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE); /* 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 @@ linux_set_syscall_retval(struct thread *td, int error) 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 @@ linux_elf_fixup(register_t **stack_base, struct image_ 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 @@ linux_copyout_strings(struct image_params *imgp) 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 @@ struct sysentvec elf_linux_sysvec = { .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, Modified: head/sys/i386/linux/linux_sysvec.c ============================================================================== --- head/sys/i386/linux/linux_sysvec.c Fri Nov 15 23:01:09 2019 (r354753) +++ head/sys/i386/linux/linux_sysvec.c Fri Nov 15 23:01:43 2019 (r354754) @@ -188,25 +188,22 @@ linux_fixup(register_t **stack_base, struct image_para 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 @@ linux_fixup_elf(register_t **stack_base, struct image_ 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 @@ linux_copyout_strings(struct image_params *imgp) 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 @@ struct sysentvec elf_linux_sysvec = { .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,
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201911152301.xAFN1hBM046422>