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;
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to