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/amd64/linux32/linux32_sysvec.c | |
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/amd64/linux32/linux32_sysvec.c')
-rw-r--r-- | sys/amd64/linux32/linux32_sysvec.c | 64 |
1 files changed, 34 insertions, 30 deletions
diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c index c8d922a207f6..aedf0c5dec98 100644 --- a/sys/amd64/linux32/linux32_sysvec.c +++ b/sys/amd64/linux32/linux32_sysvec.c @@ -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_params *imgp) ("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_params *imgp) * 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); } |