Date: Thu, 24 May 2018 16:25:18 +0000 (UTC) From: Brooks Davis <brooks@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r334165 - in head/sys: amd64/linux amd64/linux32 i386/linux kern sys Message-ID: <201805241625.w4OGPIGh065498@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: brooks Date: Thu May 24 16:25:18 2018 New Revision: 334165 URL: https://svnweb.freebsd.org/changeset/base/334165 Log: Avoid two suword() calls per auxarg entry. Instead, construct an auxargs array and copy it out all at once. Use an array of Elf_Auxinfo rather than pairs of Elf_Addr * to represent the array. This is the correct type where pairs of words just happend to work. To reduce the size of the diff, AUXARGS_ENTRY is altered to act on this array rather than introducing a new macro. Return errors on copyout() and suword() failures and handle them in the caller. Incidentally fixes AT_RANDOM and AT_EXECFN in 32-bit linux on amd64 which incorrectly used AUXARG_ENTRY instead of AUXARGS_ENTRY_32 (now removed due to the use of proper types). Reviewed by: kib Comments from: emaste, jhb Obtained from: CheriBSD Sponsored by: DARPA, AFRL Differential Revision: https://reviews.freebsd.org/D15485 Modified: head/sys/amd64/linux/linux_sysvec.c head/sys/amd64/linux32/linux32_sysvec.c head/sys/i386/linux/linux_sysvec.c head/sys/kern/imgact_elf.c head/sys/kern/kern_exec.c head/sys/sys/imgact_elf.h Modified: head/sys/amd64/linux/linux_sysvec.c ============================================================================== --- head/sys/amd64/linux/linux_sysvec.c Thu May 24 16:07:47 2018 (r334164) +++ head/sys/amd64/linux/linux_sysvec.c Thu May 24 16:25:18 2018 (r334165) @@ -240,11 +240,11 @@ static int linux_fixup_elf(register_t **stack_base, struct image_params *imgp) { Elf_Auxargs *args; - Elf_Addr *base; - Elf_Addr *pos; + Elf_Auxinfo *argarray, *pos; + Elf_Addr *auxbase, *base; struct ps_strings *arginfo; struct proc *p; - int issetugid; + int error, issetugid; p = imgp->proc; arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings; @@ -253,7 +253,9 @@ linux_fixup_elf(register_t **stack_base, struct image_ ("unsafe linux_fixup_elf(), should be curproc")); base = (Elf64_Addr *)*stack_base; args = (Elf64_Auxargs *)imgp->auxargs; - pos = base + (imgp->args->argc + imgp->args->envc + 2); + auxbase = base + imgp->args->argc + 1 + imgp->args->envc + 1; + argarray = pos = malloc(LINUX_AT_COUNT * sizeof(*pos), M_TEMP, + M_WAITOK | M_ZERO); issetugid = p->p_flag & P_SUGID ? 1 : 0; AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO_EHDR, @@ -281,9 +283,17 @@ linux_fixup_elf(register_t **stack_base, struct image_ AUXARGS_ENTRY(pos, AT_NULL, 0); free(imgp->auxargs, M_TEMP); imgp->auxargs = NULL; + KASSERT((pos - argarray) / sizeof(*pos) <= LINUX_AT_COUNT, + ("Too many auxargs")); + error = copyout(argarray, auxbase, sizeof(*argarray) * LINUX_AT_COUNT); + free(argarray, M_TEMP); + if (error != 0) + return (error); + base--; - suword(base, (uint64_t)imgp->args->argc); + if (suword(base, (uint64_t)imgp->args->argc) == -1) + return (EFAULT); *stack_base = (register_t *)base; return (0); Modified: head/sys/amd64/linux32/linux32_sysvec.c ============================================================================== --- head/sys/amd64/linux32/linux32_sysvec.c Thu May 24 16:07:47 2018 (r334164) +++ head/sys/amd64/linux32/linux32_sysvec.c Thu May 24 16:25:18 2018 (r334165) @@ -89,12 +89,6 @@ __FBSDID("$FreeBSD$"); MODULE_VERSION(linux, 1); -#define AUXARGS_ENTRY_32(pos, id, val) \ - do { \ - suword32(pos++, id); \ - suword32(pos++, val); \ - } while (0) - /* * Allow the sendsig functions to use the ldebug() facility even though they * are not syscalls themselves. Map them to syscall 0. This is slightly less @@ -202,10 +196,10 @@ static int linux_fixup_elf(register_t **stack_base, struct image_params *imgp) { Elf32_Auxargs *args; - Elf32_Addr *base; - Elf32_Addr *pos; + Elf32_Auxinfo *argarray, *pos; + Elf32_Addr *auxbase, *base; struct linux32_ps_strings *arginfo; - int issetugid; + int error, issetugid; arginfo = (struct linux32_ps_strings *)LINUX32_PS_STRINGS; @@ -213,13 +207,15 @@ linux_fixup_elf(register_t **stack_base, struct image_ ("unsafe linux_fixup_elf(), should be curproc")); base = (Elf32_Addr *)*stack_base; args = (Elf32_Auxargs *)imgp->auxargs; - pos = base + (imgp->args->argc + imgp->args->envc + 2); + auxbase = base + (imgp->args->argc + 1 + imgp->args->envc + 1); + argarray = pos = malloc(LINUX_AT_COUNT * sizeof(*pos), M_TEMP, + M_WAITOK | M_ZERO); issetugid = imgp->proc->p_flag & P_SUGID ? 1 : 0; - AUXARGS_ENTRY_32(pos, LINUX_AT_SYSINFO_EHDR, + AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO_EHDR, imgp->proc->p_sysent->sv_shared_page_base); - AUXARGS_ENTRY_32(pos, LINUX_AT_SYSINFO, linux32_vsyscall); - AUXARGS_ENTRY_32(pos, LINUX_AT_HWCAP, cpu_feature); + AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO, linux32_vsyscall); + AUXARGS_ENTRY(pos, LINUX_AT_HWCAP, cpu_feature); /* * Do not export AT_CLKTCK when emulating Linux kernel prior to 2.4.0, @@ -230,32 +226,40 @@ linux_fixup_elf(register_t **stack_base, struct image_ * Also see linux_times() implementation. */ if (linux_kernver(curthread) >= LINUX_KERNVER_2004000) - AUXARGS_ENTRY_32(pos, LINUX_AT_CLKTCK, stclohz); - AUXARGS_ENTRY_32(pos, AT_PHDR, args->phdr); - AUXARGS_ENTRY_32(pos, AT_PHENT, args->phent); - AUXARGS_ENTRY_32(pos, AT_PHNUM, args->phnum); - AUXARGS_ENTRY_32(pos, AT_PAGESZ, args->pagesz); - AUXARGS_ENTRY_32(pos, AT_FLAGS, args->flags); - AUXARGS_ENTRY_32(pos, AT_ENTRY, args->entry); - AUXARGS_ENTRY_32(pos, AT_BASE, args->base); - AUXARGS_ENTRY_32(pos, LINUX_AT_SECURE, issetugid); - AUXARGS_ENTRY_32(pos, AT_UID, imgp->proc->p_ucred->cr_ruid); - AUXARGS_ENTRY_32(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid); - AUXARGS_ENTRY_32(pos, AT_GID, imgp->proc->p_ucred->cr_rgid); - AUXARGS_ENTRY_32(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid); - AUXARGS_ENTRY_32(pos, LINUX_AT_PLATFORM, PTROUT(linux_platform)); + AUXARGS_ENTRY(pos, LINUX_AT_CLKTCK, stclohz); + AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); + AUXARGS_ENTRY(pos, AT_PHENT, args->phent); + AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum); + AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz); + AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); + AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); + AUXARGS_ENTRY(pos, AT_BASE, args->base); + AUXARGS_ENTRY(pos, LINUX_AT_SECURE, issetugid); + AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid); + AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid); + AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid); + AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid); + AUXARGS_ENTRY(pos, LINUX_AT_PLATFORM, PTROUT(linux_platform)); AUXARGS_ENTRY(pos, LINUX_AT_RANDOM, PTROUT(imgp->canary)); if (imgp->execpathp != 0) AUXARGS_ENTRY(pos, LINUX_AT_EXECFN, PTROUT(imgp->execpathp)); if (args->execfd != -1) - AUXARGS_ENTRY_32(pos, AT_EXECFD, args->execfd); - AUXARGS_ENTRY_32(pos, AT_NULL, 0); + AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); + AUXARGS_ENTRY(pos, AT_NULL, 0); free(imgp->auxargs, M_TEMP); imgp->auxargs = NULL; + KASSERT((pos - argarray) / sizeof(*pos) <= AT_COUNT, + ("Too many auxargs")); + error = copyout(&argarray[0], auxbase, sizeof(*argarray) * AT_COUNT); + free(argarray, M_TEMP); + if (error != 0) + return (error); + base--; - suword32(base, (uint32_t)imgp->args->argc); + if (suword32(base, (uint32_t)imgp->args->argc) == -1) + return (EFAULT); *stack_base = (register_t *)base; return (0); } Modified: head/sys/i386/linux/linux_sysvec.c ============================================================================== --- head/sys/i386/linux/linux_sysvec.c Thu May 24 16:07:47 2018 (r334164) +++ head/sys/i386/linux/linux_sysvec.c Thu May 24 16:25:18 2018 (r334165) @@ -207,10 +207,10 @@ linux_fixup_elf(register_t **stack_base, struct image_ { struct proc *p; Elf32_Auxargs *args; - Elf32_Addr *uplatform; + Elf32_Auxinfo *argarray, *pos; + Elf32_Addr *auxbase, *uplatform; struct ps_strings *arginfo; - register_t *pos; - int issetugid; + int error, issetugid; KASSERT(curthread->td_proc == imgp->proc, ("unsafe linux_fixup_elf(), should be curproc")); @@ -220,7 +220,9 @@ linux_fixup_elf(register_t **stack_base, struct image_ arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings; uplatform = (Elf32_Addr *)((caddr_t)arginfo - linux_szplatform); args = (Elf32_Auxargs *)imgp->auxargs; - pos = *stack_base + (imgp->args->argc + imgp->args->envc + 2); + 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); AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO_EHDR, imgp->proc->p_sysent->sv_shared_page_base); @@ -259,9 +261,17 @@ linux_fixup_elf(register_t **stack_base, struct image_ free(imgp->auxargs, M_TEMP); imgp->auxargs = NULL; + KASSERT((pos - argarray) / sizeof(*pos) <= LINUX_AT_COUNT, + ("Too many auxargs")); + error = copyout(argarray, auxbase, sizeof(*argarray) * LINUX_AT_COUNT); + free(argarray, M_TEMP); + if (error != 0) + return (error); + (*stack_base)--; - suword(*stack_base, (register_t)imgp->args->argc); + if (suword(*stack_base, (register_t)imgp->args->argc) == -1) + return (EFAULT); return (0); } Modified: head/sys/kern/imgact_elf.c ============================================================================== --- head/sys/kern/imgact_elf.c Thu May 24 16:07:47 2018 (r334164) +++ head/sys/kern/imgact_elf.c Thu May 24 16:25:18 2018 (r334165) @@ -1098,11 +1098,14 @@ int __elfN(freebsd_fixup)(register_t **stack_base, struct image_params *imgp) { Elf_Auxargs *args = (Elf_Auxargs *)imgp->auxargs; - Elf_Addr *base; - Elf_Addr *pos; + Elf_Auxinfo *argarray, *pos; + Elf_Addr *base, *auxbase; + int error; base = (Elf_Addr *)*stack_base; - pos = base + (imgp->args->argc + imgp->args->envc + 2); + auxbase = base + imgp->args->argc + 1 + imgp->args->envc + 1; + argarray = pos = malloc(AT_COUNT * sizeof(*pos), M_TEMP, + M_WAITOK | M_ZERO); if (args->execfd != -1) AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); @@ -1142,9 +1145,17 @@ __elfN(freebsd_fixup)(register_t **stack_base, struct free(imgp->auxargs, M_TEMP); imgp->auxargs = NULL; + KASSERT((pos - argarray) / sizeof(*pos) <= AT_COUNT, + ("Too many auxargs")); + error = copyout(argarray, auxbase, sizeof(*argarray) * AT_COUNT); + free(argarray, M_TEMP); + if (error != 0) + return (error); + base--; - suword(base, (long)imgp->args->argc); + if (suword(base, imgp->args->argc) == -1) + return (EFAULT); *stack_base = (register_t *)base; return (0); } Modified: head/sys/kern/kern_exec.c ============================================================================== --- head/sys/kern/kern_exec.c Thu May 24 16:07:47 2018 (r334164) +++ head/sys/kern/kern_exec.c Thu May 24 16:25:18 2018 (r334165) @@ -691,9 +691,12 @@ interpret: * Else stuff argument count as first item on stack */ if (p->p_sysent->sv_fixup != NULL) - (*p->p_sysent->sv_fixup)(&stack_base, imgp); + error = (*p->p_sysent->sv_fixup)(&stack_base, imgp); else - suword(--stack_base, imgp->args->argc); + error = suword(--stack_base, imgp->args->argc) == 0 ? + 0 : EFAULT; + if (error != 0) + goto exec_fail_dealloc; if (args->fdp != NULL) { /* Install a brand new file descriptor table. */ Modified: head/sys/sys/imgact_elf.h ============================================================================== --- head/sys/sys/imgact_elf.h Thu May 24 16:07:47 2018 (r334164) +++ head/sys/sys/imgact_elf.h Thu May 24 16:25:18 2018 (r334165) @@ -37,7 +37,8 @@ #ifdef _KERNEL -#define AUXARGS_ENTRY(pos, id, val) {suword(pos++, id); suword(pos++, val);} +#define AUXARGS_ENTRY(pos, id, val) \ + {(pos)->a_type = (id); (pos)->a_un.a_val = (val); (pos)++;} struct image_params; struct thread;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201805241625.w4OGPIGh065498>