Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 4 Dec 2018 00:15:47 +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: r341449 - head/sys/kern
Message-ID:  <201812040015.wB40Flla015023@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: brooks
Date: Tue Dec  4 00:15:47 2018
New Revision: 341449
URL: https://svnweb.freebsd.org/changeset/base/341449

Log:
  Remove a needlessly clever hack to start init with sys_exec().
  
  Construct a struct image_args with the help of new exec_args_*() helper
  functions and call kern_execve().
  
  The previous code mapped a page in userspace, copied arguments out
  to it one at a time, and then constructed a struct execve_args all so
  that sys_execve() can call exec_copyin_args() to copy the data back in
  to a struct image_args.
  
  Opencode the part of pre_execve()/post_execve() that releases a
  reference to the initial vmspace. We don't need to stop threads like
  they do.
  
  Reviewed by:	kib, jhb (prior version)
  Obtained from:	CheriBSD
  Sponsored by:	DARPA, AFRL
  Differential Revision:	https://reviews.freebsd.org/D15469

Modified:
  head/sys/kern/init_main.c

Modified: head/sys/kern/init_main.c
==============================================================================
--- head/sys/kern/init_main.c	Mon Dec  3 23:42:04 2018	(r341448)
+++ head/sys/kern/init_main.c	Tue Dec  4 00:15:47 2018	(r341449)
@@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/exec.h>
 #include <sys/file.h>
 #include <sys/filedesc.h>
+#include <sys/imgact.h>
 #include <sys/jail.h>
 #include <sys/ktr.h>
 #include <sys/lock.h>
@@ -716,15 +717,15 @@ SYSCTL_INT(_kern, OID_AUTO, init_shutdown_timeout,
 static void
 start_init(void *dummy)
 {
-	vm_offset_t addr;
-	struct execve_args args;
+	struct image_args args;
 	int options, error;
 	size_t pathlen;
+	char flags[8], *flagp;
 	char *var, *path;
 	char *free_init_path, *tmp_init_path;
-	char *ucp, **uap, *arg0, *arg1;
 	struct thread *td;
 	struct proc *p;
+	struct vmspace *oldvmspace;
 
 	TSENTER();	/* Here so we don't overlap with mi_startup. */
 
@@ -736,16 +737,6 @@ start_init(void *dummy)
 	/* Wipe GELI passphrase from the environment. */
 	kern_unsetenv("kern.geom.eli.passphrase");
 
-	/*
-	 * Need just enough stack to hold the faked-up "execve()" arguments.
-	 */
-	addr = p->p_sysent->sv_usrstack - PAGE_SIZE;
-	if (vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &addr, PAGE_SIZE, 0,
-	    VMFS_NO_SPACE, VM_PROT_ALL, VM_PROT_ALL, 0) != 0)
-		panic("init: couldn't allocate argument space");
-	p->p_vmspace->vm_maxsaddr = (caddr_t)addr;
-	p->p_vmspace->vm_ssize = 1;
-
 	if ((var = kern_getenv("init_path")) != NULL) {
 		strlcpy(init_path, var, sizeof(init_path));
 		freeenv(var);
@@ -757,63 +748,65 @@ start_init(void *dummy)
 		if (bootverbose)
 			printf("start_init: trying %s\n", path);
 			
-		/*
-		 * Move out the boot flag argument.
-		 */
+		memset(&args, 0, sizeof(args));
+		error = exec_alloc_args(&args);
+		if (error != 0)
+			panic("%s: Can't allocate space for init arguments %d",
+			    __func__, error);
+
+		error = exec_args_add_fname(&args, path, UIO_SYSSPACE);
+		if (error != 0)
+			panic("%s: Can't add fname %d", __func__, error);
+
+		error = exec_args_add_arg(&args, path, UIO_SYSSPACE);
+		if (error != 0)
+			panic("%s: Can't add argv[0] %d", __func__, error);
+
 		options = 0;
-		ucp = (char *)p->p_sysent->sv_usrstack;
-		(void)subyte(--ucp, 0);		/* trailing zero */
+		flagp = &flags[0];
+		*flagp++ = '-';
 		if (boothowto & RB_SINGLE) {
-			(void)subyte(--ucp, 's');
-			options = 1;
+			*flagp++ = 's';
+			options++;
 		}
 #ifdef notyet
                 if (boothowto & RB_FASTBOOT) {
-			(void)subyte(--ucp, 'f');
-			options = 1;
+			*flagp++ = 'f';
+			options++;
 		}
 #endif
-
 #ifdef BOOTCDROM
-		(void)subyte(--ucp, 'C');
-		options = 1;
+		*flagp++ = 'C';
+		options++;
 #endif
-
 		if (options == 0)
-			(void)subyte(--ucp, '-');
-		(void)subyte(--ucp, '-');		/* leading hyphen */
-		arg1 = ucp;
+			*flagp++ = '-';
+		*flagp++ = 0;
+		KASSERT(flagp <= &flags[0] + sizeof(flags), ("Overran flags"));
+		error = exec_args_add_arg(&args, flags, UIO_SYSSPACE);
+		if (error != 0)
+			panic("%s: Can't add argv[0] %d", __func__, error);
 
 		/*
-		 * Move out the file name (also arg 0).
-		 */
-		ucp -= pathlen;
-		copyout(path, ucp, pathlen);
-		arg0 = ucp;
-
-		/*
-		 * Move out the arg pointers.
-		 */
-		uap = (char **)rounddown2((intptr_t)ucp, sizeof(intptr_t));
-		(void)suword((caddr_t)--uap, (long)0);	/* terminator */
-		(void)suword((caddr_t)--uap, (long)(intptr_t)arg1);
-		(void)suword((caddr_t)--uap, (long)(intptr_t)arg0);
-
-		/*
-		 * Point at the arguments.
-		 */
-		args.fname = arg0;
-		args.argv = uap;
-		args.envv = NULL;
-
-		/*
 		 * Now try to exec the program.  If can't for any reason
 		 * other than it doesn't exist, complain.
 		 *
 		 * Otherwise, return via fork_trampoline() all the way
 		 * to user mode as init!
 		 */
-		if ((error = sys_execve(td, &args)) == EJUSTRETURN) {
+		KASSERT((td->td_pflags & TDP_EXECVMSPC) == 0,
+		    ("nested execve"));
+		oldvmspace = td->td_proc->p_vmspace;
+		error = kern_execve(td, &args, NULL);
+		KASSERT(error != 0,
+		    ("kern_execve returned success, not EJUSTRETURN"));
+		if (error == EJUSTRETURN) {
+			if ((td->td_pflags & TDP_EXECVMSPC) != 0) {
+				KASSERT(p->p_vmspace != oldvmspace,
+				    ("oldvmspace still used"));
+				vmspace_free(oldvmspace);
+				td->td_pflags &= ~TDP_EXECVMSPC;
+			}
 			free(free_init_path, M_TEMP);
 			TSEXIT();
 			return;



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