Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 24 May 2018 16:25:18 +0000 (UTC)
From:      Brooks Davis <brooks@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r334165 - in head/sys: amd64/linux amd64/linux32 i386/linux kern sys
Message-ID:  <201805241625.w4OGPIGh065498@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201805241625.w4OGPIGh065498>