aboutsummaryrefslogtreecommitdiff
path: root/sys/amd64/linux32/linux32_sysvec.c
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/amd64/linux32/linux32_sysvec.c
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/amd64/linux32/linux32_sysvec.c')
-rw-r--r--sys/amd64/linux32/linux32_sysvec.c64
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);
}