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;
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to