Changeset View
Changeset View
Standalone View
Standalone View
head/sys/kern/kern_exec.c
Show First 20 Lines • Show All 112 Lines • ▼ Show 20 Lines | |||||
SYSCTL_INT(_kern, OID_AUTO, coredump_pack_vmmapinfo, CTLFLAG_RWTUN, | SYSCTL_INT(_kern, OID_AUTO, coredump_pack_vmmapinfo, CTLFLAG_RWTUN, | ||||
&coredump_pack_vmmapinfo, 0, | &coredump_pack_vmmapinfo, 0, | ||||
"Enable file path packing in 'procstat -v' coredump notes"); | "Enable file path packing in 'procstat -v' coredump notes"); | ||||
static int sysctl_kern_ps_strings(SYSCTL_HANDLER_ARGS); | static int sysctl_kern_ps_strings(SYSCTL_HANDLER_ARGS); | ||||
static int sysctl_kern_usrstack(SYSCTL_HANDLER_ARGS); | static int sysctl_kern_usrstack(SYSCTL_HANDLER_ARGS); | ||||
static int sysctl_kern_stackprot(SYSCTL_HANDLER_ARGS); | static int sysctl_kern_stackprot(SYSCTL_HANDLER_ARGS); | ||||
static int do_execve(struct thread *td, struct image_args *args, | static int do_execve(struct thread *td, struct image_args *args, | ||||
struct mac *mac_p); | struct mac *mac_p, struct vmspace *oldvmspace); | ||||
/* XXX This should be vm_size_t. */ | /* XXX This should be vm_size_t. */ | ||||
SYSCTL_PROC(_kern, KERN_PS_STRINGS, ps_strings, CTLTYPE_ULONG|CTLFLAG_RD| | SYSCTL_PROC(_kern, KERN_PS_STRINGS, ps_strings, CTLTYPE_ULONG|CTLFLAG_RD| | ||||
CTLFLAG_CAPRD|CTLFLAG_MPSAFE, NULL, 0, sysctl_kern_ps_strings, "LU", | CTLFLAG_CAPRD|CTLFLAG_MPSAFE, NULL, 0, sysctl_kern_ps_strings, "LU", | ||||
"Location of process' ps_strings structure"); | "Location of process' ps_strings structure"); | ||||
/* XXX This should be vm_size_t. */ | /* XXX This should be vm_size_t. */ | ||||
SYSCTL_PROC(_kern, KERN_USRSTACK, usrstack, CTLTYPE_ULONG|CTLFLAG_RD| | SYSCTL_PROC(_kern, KERN_USRSTACK, usrstack, CTLTYPE_ULONG|CTLFLAG_RD| | ||||
▲ Show 20 Lines • Show All 88 Lines • ▼ Show 20 Lines | sys_execve(struct thread *td, struct execve_args *uap) | ||||
int error; | int error; | ||||
error = pre_execve(td, &oldvmspace); | error = pre_execve(td, &oldvmspace); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
error = exec_copyin_args(&args, uap->fname, UIO_USERSPACE, | error = exec_copyin_args(&args, uap->fname, UIO_USERSPACE, | ||||
uap->argv, uap->envv); | uap->argv, uap->envv); | ||||
if (error == 0) | if (error == 0) | ||||
error = kern_execve(td, &args, NULL); | error = kern_execve(td, &args, NULL, oldvmspace); | ||||
post_execve(td, error, oldvmspace); | post_execve(td, error, oldvmspace); | ||||
return (error); | return (error); | ||||
} | } | ||||
#ifndef _SYS_SYSPROTO_H_ | #ifndef _SYS_SYSPROTO_H_ | ||||
struct fexecve_args { | struct fexecve_args { | ||||
int fd; | int fd; | ||||
char **argv; | char **argv; | ||||
Show All 9 Lines | sys_fexecve(struct thread *td, struct fexecve_args *uap) | ||||
error = pre_execve(td, &oldvmspace); | error = pre_execve(td, &oldvmspace); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
error = exec_copyin_args(&args, NULL, UIO_SYSSPACE, | error = exec_copyin_args(&args, NULL, UIO_SYSSPACE, | ||||
uap->argv, uap->envv); | uap->argv, uap->envv); | ||||
if (error == 0) { | if (error == 0) { | ||||
args.fd = uap->fd; | args.fd = uap->fd; | ||||
error = kern_execve(td, &args, NULL); | error = kern_execve(td, &args, NULL, oldvmspace); | ||||
} | } | ||||
post_execve(td, error, oldvmspace); | post_execve(td, error, oldvmspace); | ||||
return (error); | return (error); | ||||
} | } | ||||
#ifndef _SYS_SYSPROTO_H_ | #ifndef _SYS_SYSPROTO_H_ | ||||
struct __mac_execve_args { | struct __mac_execve_args { | ||||
char *fname; | char *fname; | ||||
Show All 12 Lines | #ifdef MAC | ||||
int error; | int error; | ||||
error = pre_execve(td, &oldvmspace); | error = pre_execve(td, &oldvmspace); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
error = exec_copyin_args(&args, uap->fname, UIO_USERSPACE, | error = exec_copyin_args(&args, uap->fname, UIO_USERSPACE, | ||||
uap->argv, uap->envv); | uap->argv, uap->envv); | ||||
if (error == 0) | if (error == 0) | ||||
error = kern_execve(td, &args, uap->mac_p); | error = kern_execve(td, &args, uap->mac_p, oldvmspace); | ||||
post_execve(td, error, oldvmspace); | post_execve(td, error, oldvmspace); | ||||
return (error); | return (error); | ||||
#else | #else | ||||
return (ENOSYS); | return (ENOSYS); | ||||
#endif | #endif | ||||
} | } | ||||
int | int | ||||
Show All 31 Lines | if ((p->p_flag & P_HADTHREADS) != 0) { | ||||
* force other threads to suicide. | * force other threads to suicide. | ||||
*/ | */ | ||||
if (error == EJUSTRETURN) | if (error == EJUSTRETURN) | ||||
thread_single(p, SINGLE_EXIT); | thread_single(p, SINGLE_EXIT); | ||||
else | else | ||||
thread_single_end(p, SINGLE_BOUNDARY); | thread_single_end(p, SINGLE_BOUNDARY); | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
} | } | ||||
if ((td->td_pflags & TDP_EXECVMSPC) != 0) { | exec_cleanup(td, oldvmspace); | ||||
KASSERT(p->p_vmspace != oldvmspace, | |||||
("oldvmspace still used")); | |||||
vmspace_free(oldvmspace); | |||||
td->td_pflags &= ~TDP_EXECVMSPC; | |||||
} | } | ||||
} | |||||
/* | /* | ||||
* XXX: kern_execve has the astonishing property of not always returning to | * kern_execve() has the astonishing property of not always returning to | ||||
* the caller. If sufficiently bad things happen during the call to | * the caller. If sufficiently bad things happen during the call to | ||||
* do_execve(), it can end up calling exit1(); as a result, callers must | * do_execve(), it can end up calling exit1(); as a result, callers must | ||||
* avoid doing anything which they might need to undo (e.g., allocating | * avoid doing anything which they might need to undo (e.g., allocating | ||||
* memory). | * memory). | ||||
*/ | */ | ||||
int | int | ||||
kern_execve(struct thread *td, struct image_args *args, struct mac *mac_p) | kern_execve(struct thread *td, struct image_args *args, struct mac *mac_p, | ||||
struct vmspace *oldvmspace) | |||||
{ | { | ||||
AUDIT_ARG_ARGV(args->begin_argv, args->argc, | AUDIT_ARG_ARGV(args->begin_argv, args->argc, | ||||
exec_args_get_begin_envv(args) - args->begin_argv); | exec_args_get_begin_envv(args) - args->begin_argv); | ||||
AUDIT_ARG_ENVV(exec_args_get_begin_envv(args), args->envc, | AUDIT_ARG_ENVV(exec_args_get_begin_envv(args), args->envc, | ||||
args->endp - exec_args_get_begin_envv(args)); | args->endp - exec_args_get_begin_envv(args)); | ||||
return (do_execve(td, args, mac_p)); | return (do_execve(td, args, mac_p, oldvmspace)); | ||||
} | } | ||||
/* | /* | ||||
* In-kernel implementation of execve(). All arguments are assumed to be | * In-kernel implementation of execve(). All arguments are assumed to be | ||||
* userspace pointers from the passed thread. | * userspace pointers from the passed thread. | ||||
*/ | */ | ||||
static int | static int | ||||
do_execve(struct thread *td, struct image_args *args, struct mac *mac_p) | do_execve(struct thread *td, struct image_args *args, struct mac *mac_p, | ||||
struct vmspace *oldvmspace) | |||||
{ | { | ||||
struct proc *p = td->td_proc; | struct proc *p = td->td_proc; | ||||
struct nameidata nd; | struct nameidata nd; | ||||
struct ucred *oldcred; | struct ucred *oldcred; | ||||
struct uidinfo *euip = NULL; | struct uidinfo *euip = NULL; | ||||
uintptr_t stack_base; | uintptr_t stack_base; | ||||
struct image_params image_params, *imgp; | struct image_params image_params, *imgp; | ||||
struct vattr attr; | struct vattr attr; | ||||
▲ Show 20 Lines • Show All 575 Lines • ▼ Show 20 Lines | #endif | ||||
pargs_drop(newargs); | pargs_drop(newargs); | ||||
if (oldsigacts != NULL) | if (oldsigacts != NULL) | ||||
sigacts_free(oldsigacts); | sigacts_free(oldsigacts); | ||||
if (euip != NULL) | if (euip != NULL) | ||||
uifree(euip); | uifree(euip); | ||||
if (error && imgp->vmspace_destroyed) { | if (error && imgp->vmspace_destroyed) { | ||||
/* sorry, no more process anymore. exit gracefully */ | /* sorry, no more process anymore. exit gracefully */ | ||||
exec_cleanup(td, oldvmspace); | |||||
exit1(td, 0, SIGABRT); | exit1(td, 0, SIGABRT); | ||||
/* NOT REACHED */ | /* NOT REACHED */ | ||||
} | } | ||||
#ifdef KTRACE | #ifdef KTRACE | ||||
if (error == 0) | if (error == 0) | ||||
ktrprocctor(p); | ktrprocctor(p); | ||||
#endif | #endif | ||||
/* | /* | ||||
* We don't want cpu_set_syscall_retval() to overwrite any of | * We don't want cpu_set_syscall_retval() to overwrite any of | ||||
* the register values put in place by exec_setregs(). | * the register values put in place by exec_setregs(). | ||||
* Implementations of cpu_set_syscall_retval() will leave | * Implementations of cpu_set_syscall_retval() will leave | ||||
* registers unmodified when returning EJUSTRETURN. | * registers unmodified when returning EJUSTRETURN. | ||||
*/ | */ | ||||
return (error == 0 ? EJUSTRETURN : error); | return (error == 0 ? EJUSTRETURN : error); | ||||
} | |||||
void | |||||
exec_cleanup(struct thread *td, struct vmspace *oldvmspace) | |||||
{ | |||||
struct proc *p; | |||||
p = td->td_proc; | |||||
if ((td->td_pflags & TDP_EXECVMSPC) != 0) { | |||||
KASSERT(p->p_vmspace != oldvmspace, | |||||
("oldvmspace still used")); | |||||
vmspace_free(oldvmspace); | |||||
td->td_pflags &= ~TDP_EXECVMSPC; | |||||
} | |||||
} | } | ||||
int | int | ||||
exec_map_first_page(struct image_params *imgp) | exec_map_first_page(struct image_params *imgp) | ||||
{ | { | ||||
vm_object_t object; | vm_object_t object; | ||||
vm_page_t m; | vm_page_t m; | ||||
int error; | int error; | ||||
▲ Show 20 Lines • Show All 854 Lines • Show Last 20 Lines |