diff options
author | Brooks Davis <brooks@FreeBSD.org> | 2018-05-24 16:25:18 +0000 |
---|---|---|
committer | Brooks Davis <brooks@FreeBSD.org> | 2018-05-24 16:25:18 +0000 |
commit | 5f77b8a88b5e22cb5068f2e8d3ab3518634b1f45 (patch) | |
tree | 7212a92f6b96f6e3d2970b81524ccc7f5b2ae5a1 /sys/i386/linux | |
parent | b50b5555ef129a682af90439f68ed428b9095668 (diff) | |
download | src-5f77b8a88b5e22cb5068f2e8d3ab3518634b1f45.tar.gz src-5f77b8a88b5e22cb5068f2e8d3ab3518634b1f45.zip |
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
Notes
Notes:
svn path=/head/; revision=334165
Diffstat (limited to 'sys/i386/linux')
-rw-r--r-- | sys/i386/linux/linux_sysvec.c | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c index 43625a122f68..e13ba87598d1 100644 --- a/sys/i386/linux/linux_sysvec.c +++ b/sys/i386/linux/linux_sysvec.c @@ -207,10 +207,10 @@ linux_fixup_elf(register_t **stack_base, struct image_params *imgp) { 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_params *imgp) 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_params *imgp) 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); } |