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
This commit is contained in:
parent
a66732de4f
commit
3a325dec32
@ -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,54 +748,44 @@ 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;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
*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);
|
||||
|
||||
/*
|
||||
* Now try to exec the program. If can't for any reason
|
||||
@ -813,7 +794,19 @@ start_init(void *dummy)
|
||||
* 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;
|
||||
|
Loading…
Reference in New Issue
Block a user