svn commit: r341449 - head/sys/kern
Brooks Davis
brooks at FreeBSD.org
Tue Dec 4 00:15:48 UTC 2018
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;
More information about the svn-src-head
mailing list