From owner-svn-src-all@freebsd.org Mon Dec 9 19:17:31 2019 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 007081DD26A; Mon, 9 Dec 2019 19:17:31 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 47WtHZ6zZnz3xxM; Mon, 9 Dec 2019 19:17:30 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id D099A1F27E; Mon, 9 Dec 2019 19:17:30 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id xB9JHU1V020725; Mon, 9 Dec 2019 19:17:30 GMT (envelope-from jhb@FreeBSD.org) Received: (from jhb@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id xB9JHSFO020716; Mon, 9 Dec 2019 19:17:28 GMT (envelope-from jhb@FreeBSD.org) Message-Id: <201912091917.xB9JHSFO020716@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jhb set sender to jhb@FreeBSD.org using -f From: John Baldwin Date: Mon, 9 Dec 2019 19:17:28 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r355567 - in head/sys: amd64/linux amd64/linux32 arm64/linux compat/freebsd32 i386/linux kern sys X-SVN-Group: head X-SVN-Commit-Author: jhb X-SVN-Commit-Paths: in head/sys: amd64/linux amd64/linux32 arm64/linux compat/freebsd32 i386/linux kern sys X-SVN-Commit-Revision: 355567 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 09 Dec 2019 19:17:31 -0000 Author: jhb Date: Mon Dec 9 19:17:28 2019 New Revision: 355567 URL: https://svnweb.freebsd.org/changeset/base/355567 Log: Copy out aux args after the argument and environment vectors. Partially revert r354741 and r354754 and go back to allocating a fixed-size chunk of stack space for the auxiliary vector. Keep sv_copyout_auxargs but change it to accept the address at the end of the environment vector as an input stack address and no longer allocate room on the stack. It is now called at the end of copyout_strings after the argv and environment vectors have been copied out. This should fix a regression in r354754 that broke the stack alignment for newer Linux amd64 binaries (and probably broke Linux arm64 as well). Reviewed by: kib Tested on: amd64 (native, linux64 (only linux-base-c7), and i386) Sponsored by: DARPA Differential Revision: https://reviews.freebsd.org/D22695 Modified: head/sys/amd64/linux/linux_sysvec.c head/sys/amd64/linux32/linux32_sysvec.c head/sys/arm64/linux/linux_sysvec.c head/sys/compat/freebsd32/freebsd32_misc.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 head/sys/sys/sysent.h Modified: head/sys/amd64/linux/linux_sysvec.c ============================================================================== --- head/sys/amd64/linux/linux_sysvec.c Mon Dec 9 19:10:42 2019 (r355566) +++ head/sys/amd64/linux/linux_sysvec.c Mon Dec 9 19:17:28 2019 (r355567) @@ -224,11 +224,10 @@ linux_set_syscall_retval(struct thread *td, int error) } 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 @@ linux_copyout_auxargs(struct image_params *imgp, uintp 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 @@ linux_copyout_strings(struct image_params *imgp, uintp 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 @@ linux_copyout_strings(struct image_params *imgp, uintp */ 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; @@ -404,6 +404,14 @@ linux_copyout_strings(struct image_params *imgp, uintp /* The end of the vector table is a null pointer. */ 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); } Modified: head/sys/amd64/linux32/linux32_sysvec.c ============================================================================== --- head/sys/amd64/linux32/linux32_sysvec.c Mon Dec 9 19:10:42 2019 (r355566) +++ head/sys/amd64/linux32/linux32_sysvec.c Mon Dec 9 19:17:28 2019 (r355567) @@ -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_lon 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, uintp 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; @@ -824,6 +825,14 @@ linux_copyout_strings(struct image_params *imgp, uintp /* The end of the vector table is a null pointer. */ 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); } Modified: head/sys/arm64/linux/linux_sysvec.c ============================================================================== --- head/sys/arm64/linux/linux_sysvec.c Mon Dec 9 19:10:42 2019 (r355566) +++ head/sys/arm64/linux/linux_sysvec.c Mon Dec 9 19:17:28 2019 (r355567) @@ -143,11 +143,10 @@ linux_set_syscall_retval(struct thread *td, int error) } 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 @@ linux_copyout_auxargs(struct image_params *imgp, uintp 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 @@ linux_copyout_strings(struct image_params *imgp, uintp 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; @@ -321,6 +322,14 @@ linux_copyout_strings(struct image_params *imgp, uintp /* The end of the vector table is a null pointer. */ 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); } Modified: head/sys/compat/freebsd32/freebsd32_misc.c ============================================================================== --- head/sys/compat/freebsd32/freebsd32_misc.c Mon Dec 9 19:10:42 2019 (r355566) +++ head/sys/compat/freebsd32/freebsd32_misc.c Mon Dec 9 19:17:28 2019 (r355567) @@ -3206,9 +3206,12 @@ freebsd32_copyout_strings(struct image_params *imgp, u 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; @@ -3275,6 +3278,14 @@ freebsd32_copyout_strings(struct image_params *imgp, u /* end of vector table is a null pointer */ 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); } Modified: head/sys/i386/linux/linux_sysvec.c ============================================================================== --- head/sys/i386/linux/linux_sysvec.c Mon Dec 9 19:10:42 2019 (r355566) +++ head/sys/i386/linux/linux_sysvec.c Mon Dec 9 19:17:28 2019 (r355567) @@ -192,14 +192,13 @@ linux_fixup(uintptr_t *stack_base, struct image_params } 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 @@ linux_copyout_auxargs(struct image_params *imgp, uintp 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 @@ linux_copyout_strings(struct image_params *imgp, uintp 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; @@ -383,6 +384,14 @@ linux_copyout_strings(struct image_params *imgp, uintp /* The end of the vector table is a null pointer. */ 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); } Modified: head/sys/kern/imgact_elf.c ============================================================================== --- head/sys/kern/imgact_elf.c Mon Dec 9 19:10:42 2019 (r355566) +++ head/sys/kern/imgact_elf.c Mon Dec 9 19:17:28 2019 (r355567) @@ -1324,11 +1324,10 @@ ret: #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 @@ __elfN(freebsd_copyout_auxargs)(struct image_params *i 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); } Modified: head/sys/kern/kern_exec.c ============================================================================== --- head/sys/kern/kern_exec.c Mon Dec 9 19:10:42 2019 (r355566) +++ head/sys/kern/kern_exec.c Mon Dec 9 19:17:28 2019 (r355567) @@ -1661,9 +1661,12 @@ exec_copyout_strings(struct image_params *imgp, uintpt 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; @@ -1731,6 +1734,14 @@ exec_copyout_strings(struct image_params *imgp, uintpt /* end of vector table is a null pointer */ 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); } Modified: head/sys/sys/imgact_elf.h ============================================================================== --- head/sys/sys/imgact_elf.h Mon Dec 9 19:10:42 2019 (r355566) +++ head/sys/sys/imgact_elf.h Mon Dec 9 19:17:28 2019 (r355567) @@ -99,7 +99,7 @@ int __elfN(freebsd_fixup)(uintptr_t *, struct image_pa 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 *); Modified: head/sys/sys/sysent.h ============================================================================== --- head/sys/sys/sysent.h Mon Dec 9 19:10:42 2019 (r355566) +++ head/sys/sys/sysent.h Mon Dec 9 19:17:28 2019 (r355567) @@ -111,7 +111,7 @@ struct sysentvec { 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 */