svn commit: r354754 - in head/sys: amd64/linux amd64/linux32 arm64/linux i386/linux

John Baldwin jhb at FreeBSD.org
Fri Nov 15 23:01:44 UTC 2019


Author: jhb
Date: Fri Nov 15 23:01:43 2019
New Revision: 354754
URL: https://svnweb.freebsd.org/changeset/base/354754

Log:
  Use a sv_copyout_auxargs hook in the Linux ELF ABIs.
  
  Reviewed by:	emaste
  Tested on:	amd64 (linux64 only), i386
  Sponsored by:	DARPA
  Differential Revision:	https://reviews.freebsd.org/D22356

Modified:
  head/sys/amd64/linux/linux_sysvec.c
  head/sys/amd64/linux32/linux32_sysvec.c
  head/sys/arm64/linux/linux_sysvec.c
  head/sys/i386/linux/linux_sysvec.c

Modified: head/sys/amd64/linux/linux_sysvec.c
==============================================================================
--- head/sys/amd64/linux/linux_sysvec.c	Fri Nov 15 23:01:09 2019	(r354753)
+++ head/sys/amd64/linux/linux_sysvec.c	Fri Nov 15 23:01:43 2019	(r354754)
@@ -222,24 +222,17 @@ linux_set_syscall_retval(struct thread *td, int error)
 	set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
 }
 
-static int
-linux_fixup_elf(register_t **stack_base, struct image_params *imgp)
+static void
+linux_copyout_auxargs(struct image_params *imgp, u_long *base)
 {
 	Elf_Auxargs *args;
 	Elf_Auxinfo *argarray, *pos;
-	Elf_Addr *auxbase, *base;
-	struct ps_strings *arginfo;
+	u_long auxlen;
 	struct proc *p;
-	int error, issetugid;
+	int issetugid;
 
 	p = imgp->proc;
-	arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings;
-
-	KASSERT(curthread->td_proc == imgp->proc,
-	    ("unsafe linux_fixup_elf(), should be curproc"));
-	base = (Elf64_Addr *)*stack_base;
 	args = (Elf64_Auxargs *)imgp->auxargs;
-	auxbase = base + imgp->args->argc + 1 + imgp->args->envc + 1;
 	argarray = pos = malloc(LINUX_AT_COUNT * sizeof(*pos), M_TEMP,
 	    M_WAITOK | M_ZERO);
 
@@ -267,15 +260,23 @@ linux_fixup_elf(register_t **stack_base, struct image_
 	if (args->execfd != -1)
 		AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
 	AUXARGS_ENTRY(pos, AT_NULL, 0);
+
 	free(imgp->auxargs, M_TEMP);
 	imgp->auxargs = NULL;
 	KASSERT(pos - argarray <= LINUX_AT_COUNT, ("Too many auxargs"));
 
-	error = copyout(argarray, auxbase, sizeof(*argarray) * LINUX_AT_COUNT);
+	auxlen = sizeof(*argarray) * (pos - argarray);
+	*base -= auxlen;
+	copyout(argarray, (void *)*base, auxlen);
 	free(argarray, M_TEMP);
-	if (error != 0)
-		return (error);
+}
 
+static int
+linux_fixup_elf(register_t **stack_base, struct image_params *imgp)
+{
+	Elf_Addr *base;
+
+	base = (Elf64_Addr *)*stack_base;
 	base--;
 	if (suword(base, (uint64_t)imgp->args->argc) == -1)
 		return (EFAULT);
@@ -327,27 +328,22 @@ linux_copyout_strings(struct image_params *imgp)
 	copyout(canary, (void *)imgp->canary, sizeof(canary));
 
 	vectp = (char **)destp;
-	if (imgp->auxargs) {
-		/*
-		 * Allocate room on the stack for the ELF auxargs
-		 * array.  It has LINUX_AT_COUNT entries.
-		 */
-		vectp -= howmany(LINUX_AT_COUNT * sizeof(Elf64_Auxinfo),
-		    sizeof(*vectp));
-	}
 
 	/*
-	 * Allocate room for the argv[] and env vectors including the
-	 * terminating NULL pointers.
-	 */
-	vectp -= imgp->args->argc + 1 + imgp->args->envc + 1;
-
-	/*
 	 * Starting with 2.24, glibc depends on a 16-byte stack alignment.
 	 * One "long argc" will be prepended later.
 	 */
 	vectp = (char **)((((uintptr_t)vectp + 8) & ~0xF) - 8);
 
+	if (imgp->auxargs)
+		imgp->sysent->sv_copyout_auxargs(imgp, (u_long *)&vectp);
+
+	/*
+	 * Allocate room for the argv[] and env vectors including the
+	 * terminating NULL pointers.
+	 */
+	vectp -= imgp->args->argc + 1 + imgp->args->envc + 1;
+
 	/* vectp also becomes our initial stack base. */
 	stack_base = (register_t *)vectp;
 
@@ -715,6 +711,7 @@ struct sysentvec elf_linux_sysvec = {
 	.sv_usrstack	= USRSTACK,
 	.sv_psstrings	= PS_STRINGS,
 	.sv_stackprot	= VM_PROT_ALL,
+	.sv_copyout_auxargs = linux_copyout_auxargs,
 	.sv_copyout_strings = linux_copyout_strings,
 	.sv_setregs	= linux_exec_setregs,
 	.sv_fixlimit	= NULL,

Modified: head/sys/amd64/linux32/linux32_sysvec.c
==============================================================================
--- head/sys/amd64/linux32/linux32_sysvec.c	Fri Nov 15 23:01:09 2019	(r354753)
+++ head/sys/amd64/linux32/linux32_sysvec.c	Fri Nov 15 23:01:43 2019	(r354754)
@@ -185,22 +185,15 @@ linux_translate_traps(int signal, int trap_code)
 	}
 }
 
-static int
-linux_fixup_elf(register_t **stack_base, struct image_params *imgp)
+static void
+linux_copyout_auxargs(struct image_params *imgp, u_long *base)
 {
 	Elf32_Auxargs *args;
 	Elf32_Auxinfo *argarray, *pos;
-	Elf32_Addr *auxbase, *base;
-	struct linux32_ps_strings *arginfo;
-	int error, issetugid;
+	u_long auxlen;
+	int issetugid;
 
-	arginfo = (struct linux32_ps_strings *)LINUX32_PS_STRINGS;
-
-	KASSERT(curthread->td_proc == imgp->proc,
-	    ("unsafe linux_fixup_elf(), should be curproc"));
-	base = (Elf32_Addr *)*stack_base;
 	args = (Elf32_Auxargs *)imgp->auxargs;
-	auxbase = base + (imgp->args->argc + 1 + imgp->args->envc + 1);
 	argarray = pos = malloc(LINUX_AT_COUNT * sizeof(*pos), M_TEMP,
 	    M_WAITOK | M_ZERO);
 
@@ -244,12 +237,18 @@ linux_fixup_elf(register_t **stack_base, struct image_
 	imgp->auxargs = NULL;
 	KASSERT(pos - argarray <= LINUX_AT_COUNT, ("Too many auxargs"));
 
-	error = copyout(&argarray[0], auxbase,
-	    sizeof(*argarray) * LINUX_AT_COUNT);
+	auxlen = sizeof(*argarray) * (pos - argarray);
+	*base -= auxlen;
+	copyout(argarray, (void *)*base, auxlen);
 	free(argarray, M_TEMP);
-	if (error != 0)
-		return (error);
+}
 
+static int
+linux_fixup_elf(register_t **stack_base, struct image_params *imgp)
+{
+	Elf32_Addr *base;
+
+	base = (Elf32_Addr *)*stack_base;
 	base--;
 	if (suword32(base, (uint32_t)imgp->args->argc) == -1)
 		return (EFAULT);
@@ -755,14 +754,8 @@ linux_copyout_strings(struct image_params *imgp)
 	copyout(canary, (void *)imgp->canary, sizeof(canary));
 
 	vectp = (uint32_t *)destp;
-	if (imgp->auxargs) {
-		/*
-		 * Allocate room on the stack for the ELF auxargs
-		 * array.  It has LINUX_AT_COUNT entries.
-		 */
-		vectp -= howmany(LINUX_AT_COUNT * sizeof(Elf32_Auxinfo),
-		    sizeof(*vectp));
-	}
+	if (imgp->auxargs)
+		imgp->sysent->sv_copyout_auxargs(imgp, (u_long *)&vectp);
 
 	/*
 	 * Allocate room for the argv[] and env vectors including the
@@ -875,6 +868,7 @@ struct sysentvec elf_linux_sysvec = {
 	.sv_usrstack	= LINUX32_USRSTACK,
 	.sv_psstrings	= LINUX32_PS_STRINGS,
 	.sv_stackprot	= VM_PROT_ALL,
+	.sv_copyout_auxargs = linux_copyout_auxargs,
 	.sv_copyout_strings = linux_copyout_strings,
 	.sv_setregs	= linux_exec_setregs,
 	.sv_fixlimit	= linux32_fixlimit,

Modified: head/sys/arm64/linux/linux_sysvec.c
==============================================================================
--- head/sys/arm64/linux/linux_sysvec.c	Fri Nov 15 23:01:09 2019	(r354753)
+++ head/sys/arm64/linux/linux_sysvec.c	Fri Nov 15 23:01:43 2019	(r354754)
@@ -87,6 +87,7 @@ LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
 /* DTrace probes */
 LIN_SDT_PROBE_DEFINE2(sysvec, linux_translate_traps, todo, "int", "int");
 LIN_SDT_PROBE_DEFINE0(sysvec, linux_exec_setregs, todo);
+LIN_SDT_PROBE_DEFINE0(sysvec, linux_copyout_auxargs, todo);
 LIN_SDT_PROBE_DEFINE0(sysvec, linux_elf_fixup, todo);
 LIN_SDT_PROBE_DEFINE0(sysvec, linux_rt_sigreturn, todo);
 LIN_SDT_PROBE_DEFINE0(sysvec, linux_rt_sendsig, todo);
@@ -140,26 +141,19 @@ linux_set_syscall_retval(struct thread *td, int error)
 	cpu_set_syscall_retval(td, error);
 }
 
-static int
-linux_elf_fixup(register_t **stack_base, struct image_params *imgp)
+static void
+linux_copyout_auxargs(struct image_params *imgp, u_long *base)
 {
 	Elf_Auxargs *args;
 	Elf_Auxinfo *argarray, *pos;
-	Elf_Addr *auxbase, *base;
-	struct ps_strings *arginfo;
+	u_long auxlen;
 	struct proc *p;
-	int error, issetugid;
+	int issetugid;
 
-	LIN_SDT_PROBE0(sysvec, linux_elf_fixup, todo);
+	LIN_SDT_PROBE0(sysvec, linux_copyout_auxargs, todo);
 	p = imgp->proc;
-	arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings;
 
-	KASSERT(curthread->td_proc == imgp->proc,
-	    ("unsafe linux_elf_fixup(), should be curproc"));
-	base = (Elf64_Addr *)*stack_base;
 	args = (Elf64_Auxargs *)imgp->auxargs;
-	/* Auxargs after argc, and NULL-terminated argv and envv lists. */
-	auxbase = base + 1 + imgp->args->argc + 1 + imgp->args->envc + 1;
 	argarray = pos = malloc(LINUX_AT_COUNT * sizeof(*pos), M_TEMP,
 	    M_WAITOK | M_ZERO);
 
@@ -195,11 +189,18 @@ linux_elf_fixup(register_t **stack_base, struct image_
 	imgp->auxargs = NULL;
 	KASSERT(pos - argarray <= LINUX_AT_COUNT, ("Too many auxargs"));
 
-	error = copyout(argarray, auxbase, sizeof(*argarray) * LINUX_AT_COUNT);
+	auxlen = sizeof(*argarray) * (pos - argarray);
+	*base -= auxlen;
+	copyout(argarray, (void *)*base, auxlen);
 	free(argarray, M_TEMP);
-	if (error != 0)
-		return (error);
+}
 
+static int
+linux_elf_fixup(register_t **stack_base, struct image_params *imgp)
+{
+
+	LIN_SDT_PROBE0(sysvec, linux_elf_fixup, todo);
+
 	return (0);
 }
 
@@ -247,14 +248,8 @@ linux_copyout_strings(struct image_params *imgp)
 	copyout(canary, (void *)imgp->canary, sizeof(canary));
 
 	vectp = (char **)destp;
-	if (imgp->auxargs) {
-		/*
-		 * Allocate room on the stack for the ELF auxargs
-		 * array.  It has up to LINUX_AT_COUNT entries.
-		 */
-		vectp -= howmany(LINUX_AT_COUNT * sizeof(Elf64_Auxinfo),
-		    sizeof(*vectp));
-	}
+	if (imgp->auxargs)
+		imgp->sysent->sv_copyout_auxargs(imgp, (u_long *)&vectp);
 
 	/*
 	 * Allocate room for argc and the argv[] and env vectors including the
@@ -372,6 +367,7 @@ struct sysentvec elf_linux_sysvec = {
 	.sv_usrstack	= USRSTACK,
 	.sv_psstrings	= PS_STRINGS, /* XXX */
 	.sv_stackprot	= VM_PROT_READ | VM_PROT_WRITE,
+	.sv_copyout_auxargs = linux_copyout_auxargs,
 	.sv_copyout_strings = linux_copyout_strings,
 	.sv_setregs	= linux_exec_setregs,
 	.sv_fixlimit	= NULL,

Modified: head/sys/i386/linux/linux_sysvec.c
==============================================================================
--- head/sys/i386/linux/linux_sysvec.c	Fri Nov 15 23:01:09 2019	(r354753)
+++ head/sys/i386/linux/linux_sysvec.c	Fri Nov 15 23:01:43 2019	(r354754)
@@ -188,25 +188,22 @@ linux_fixup(register_t **stack_base, struct image_para
 	return (0);
 }
 
-static int
-linux_fixup_elf(register_t **stack_base, struct image_params *imgp)
+static void
+linux_copyout_auxargs(struct image_params *imgp, u_long *base)
 {
 	struct proc *p;
 	Elf32_Auxargs *args;
 	Elf32_Auxinfo *argarray, *pos;
-	Elf32_Addr *auxbase, *uplatform;
+	Elf32_Addr *uplatform;
 	struct ps_strings *arginfo;
-	int error, issetugid;
+	u_long auxlen;
+	int issetugid;
 
-	KASSERT(curthread->td_proc == imgp->proc,
-	    ("unsafe linux_fixup_elf(), should be curproc"));
-
 	p = imgp->proc;
 	issetugid = imgp->proc->p_flag & P_SUGID ? 1 : 0;
 	arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings;
 	uplatform = (Elf32_Addr *)((caddr_t)arginfo - linux_szplatform);
 	args = (Elf32_Auxargs *)imgp->auxargs;
-	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);
 
@@ -249,11 +246,16 @@ linux_fixup_elf(register_t **stack_base, struct image_
 	imgp->auxargs = NULL;
 	KASSERT(pos - argarray <= LINUX_AT_COUNT, ("Too many auxargs"));
 
-	error = copyout(argarray, auxbase, sizeof(*argarray) * LINUX_AT_COUNT);
+	auxlen = sizeof(*argarray) * (pos - argarray);
+	*base -= auxlen;
+	copyout(argarray, (void *)*base, auxlen);
 	free(argarray, M_TEMP);
-	if (error != 0)
-		return (error);
+}
 
+static int
+linux_fixup_elf(register_t **stack_base, struct image_params *imgp)
+{
+
 	(*stack_base)--;
 	if (suword(*stack_base, (register_t)imgp->args->argc) == -1)
 		return (EFAULT);
@@ -305,14 +307,8 @@ linux_copyout_strings(struct image_params *imgp)
 	copyout(canary, (void *)imgp->canary, sizeof(canary));
 
 	vectp = (char **)destp;
-	if (imgp->auxargs) {
-		/*
-		 * Allocate room on the stack for the ELF auxargs
-		 * array.  It has LINUX_AT_COUNT entries.
-		 */
-		vectp -= howmany(LINUX_AT_COUNT * sizeof(Elf32_Auxinfo),
-		    sizeof(*vectp));
-	}
+	if (imgp->auxargs)
+		imgp->sysent->sv_copyout_auxargs(imgp, (u_long *)&vectp);
 
 	/*
 	 * Allocate room for the argv[] and env vectors including the
@@ -851,6 +847,7 @@ struct sysentvec elf_linux_sysvec = {
 	.sv_usrstack	= LINUX_USRSTACK,
 	.sv_psstrings	= LINUX_PS_STRINGS,
 	.sv_stackprot	= VM_PROT_ALL,
+	.sv_copyout_auxargs = linux_copyout_auxargs,
 	.sv_copyout_strings = linux_copyout_strings,
 	.sv_setregs	= linux_exec_setregs,
 	.sv_fixlimit	= NULL,


More information about the svn-src-head mailing list