aboutsummaryrefslogtreecommitdiff
path: root/sys/i386/linux
diff options
context:
space:
mode:
authorBrooks Davis <brooks@FreeBSD.org>2018-05-24 16:25:18 +0000
committerBrooks Davis <brooks@FreeBSD.org>2018-05-24 16:25:18 +0000
commit5f77b8a88b5e22cb5068f2e8d3ab3518634b1f45 (patch)
tree7212a92f6b96f6e3d2970b81524ccc7f5b2ae5a1 /sys/i386/linux
parentb50b5555ef129a682af90439f68ed428b9095668 (diff)
downloadsrc-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.c20
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);
}