svn commit: r334165 - in head/sys: amd64/linux amd64/linux32 i386/linux kern sys
Brooks Davis
brooks at FreeBSD.org
Thu May 24 16:25:20 UTC 2018
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;
More information about the svn-src-head
mailing list