Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/kern_exec.c
Show First 20 Lines • Show All 574 Lines • ▼ Show 20 Lines | #endif | ||||
* let it do the stack setup. | * let it do the stack setup. | ||||
* Else stuff argument count as first item on stack | * Else stuff argument count as first item on stack | ||||
*/ | */ | ||||
if (p->p_sysent->sv_fixup != NULL) | if (p->p_sysent->sv_fixup != NULL) | ||||
(*p->p_sysent->sv_fixup)(&stack_base, imgp); | (*p->p_sysent->sv_fixup)(&stack_base, imgp); | ||||
else | else | ||||
suword(--stack_base, imgp->args->argc); | suword(--stack_base, imgp->args->argc); | ||||
if (args->fdp != NULL) { | |||||
/* Install a brand new file descriptor table. */ | |||||
fdinstall_remapped(td, args->fdp); | |||||
args->fdp = NULL; | |||||
} else { | |||||
/* | /* | ||||
* For security and other reasons, the file descriptor table cannot | * Keep on using the existing file descriptor table. For | ||||
* be shared after an exec. | * security and other reasons, the file descriptor table | ||||
* cannot be shared after an exec. | |||||
*/ | */ | ||||
fdunshare(td); | fdunshare(td); | ||||
/* close files on exec */ | /* close files on exec */ | ||||
fdcloseexec(td); | fdcloseexec(td); | ||||
} | |||||
/* | /* | ||||
* Malloc things before we need locks. | * Malloc things before we need locks. | ||||
*/ | */ | ||||
i = imgp->args->begin_envv - imgp->args->begin_argv; | i = imgp->args->begin_envv - imgp->args->begin_argv; | ||||
/* Cache arguments if they fit inside our allowance */ | /* Cache arguments if they fit inside our allowance */ | ||||
if (ps_arg_cache_limit >= i + sizeof(struct pargs)) { | if (ps_arg_cache_limit >= i + sizeof(struct pargs)) { | ||||
newargs = pargs_alloc(i); | newargs = pargs_alloc(i); | ||||
▲ Show 20 Lines • Show All 594 Lines • ▼ Show 20 Lines | exec_copyin_args(struct image_args *args, char *fname, | ||||
return (0); | return (0); | ||||
err_exit: | err_exit: | ||||
exec_free_args(args); | exec_free_args(args); | ||||
return (error); | return (error); | ||||
} | } | ||||
int | |||||
exec_copyin_data_fds(struct thread *td, struct image_args *args, | |||||
const void *data, size_t datalen, const int *fds, size_t fdslen) | |||||
{ | |||||
struct filedesc *ofdp; | |||||
const char *p; | |||||
int *kfds; | |||||
int error; | |||||
memset(args, '\0', sizeof(*args)); | |||||
ofdp = td->td_proc->p_fd; | |||||
if (datalen >= ARG_MAX || fdslen > ofdp->fd_lastfile + 1) | |||||
return (E2BIG); | |||||
error = exec_alloc_args(args); | |||||
if (error != 0) | |||||
return (error); | |||||
args->begin_argv = args->buf; | |||||
args->stringspace = ARG_MAX; | |||||
if (datalen > 0) { | |||||
/* | /* | ||||
* Argument buffer has been provided. Copy it into the | |||||
* kernel as a single string and add a terminating null | |||||
* byte. | |||||
*/ | |||||
error = copyin(data, args->begin_argv, datalen); | |||||
if (error != 0) | |||||
goto err_exit; | |||||
args->begin_argv[datalen] = '\0'; | |||||
args->endp = args->begin_argv + datalen + 1; | |||||
args->stringspace -= datalen + 1; | |||||
/* | |||||
* Traditional argument counting. Count the number of | |||||
* null bytes. | |||||
*/ | |||||
for (p = args->begin_argv; p < args->endp; ++p) | |||||
if (*p == '\0') | |||||
++args->argc; | |||||
} else { | |||||
/* No argument buffer provided. */ | |||||
args->endp = args->begin_argv; | |||||
} | |||||
/* There are no environment variables. */ | |||||
args->begin_envv = args->endp; | |||||
/* Create new file descriptor table. */ | |||||
kfds = malloc(fdslen * sizeof(int), M_TEMP, M_WAITOK); | |||||
error = copyin(fds, kfds, fdslen * sizeof(int)); | |||||
if (error != 0) { | |||||
free(kfds, M_TEMP); | |||||
goto err_exit; | |||||
} | |||||
error = fdcopy_remapped(ofdp, kfds, fdslen, &args->fdp); | |||||
free(kfds, M_TEMP); | |||||
if (error != 0) | |||||
goto err_exit; | |||||
return (0); | |||||
err_exit: | |||||
exec_free_args(args); | |||||
return (error); | |||||
} | |||||
/* | |||||
* Allocate temporary demand-paged, zero-filled memory for the file name, | * Allocate temporary demand-paged, zero-filled memory for the file name, | ||||
* argument, and environment strings. Returns zero if the allocation succeeds | * argument, and environment strings. Returns zero if the allocation succeeds | ||||
* and ENOMEM otherwise. | * and ENOMEM otherwise. | ||||
*/ | */ | ||||
int | int | ||||
exec_alloc_args(struct image_args *args) | exec_alloc_args(struct image_args *args) | ||||
{ | { | ||||
Show All 9 Lines | if (args->buf != NULL) { | ||||
kmap_free_wakeup(exec_map, (vm_offset_t)args->buf, | kmap_free_wakeup(exec_map, (vm_offset_t)args->buf, | ||||
PATH_MAX + ARG_MAX); | PATH_MAX + ARG_MAX); | ||||
args->buf = NULL; | args->buf = NULL; | ||||
} | } | ||||
if (args->fname_buf != NULL) { | if (args->fname_buf != NULL) { | ||||
free(args->fname_buf, M_TEMP); | free(args->fname_buf, M_TEMP); | ||||
args->fname_buf = NULL; | args->fname_buf = NULL; | ||||
} | } | ||||
if (args->fdp != NULL) | |||||
fdescfree_remapped(args->fdp); | |||||
} | } | ||||
/* | /* | ||||
* Copy strings out to the new process address space, constructing new arg | * Copy strings out to the new process address space, constructing new arg | ||||
* and env vector tables. Return a pointer to the base so that it can be used | * and env vector tables. Return a pointer to the base so that it can be used | ||||
* as the initial stack pointer. | * as the initial stack pointer. | ||||
*/ | */ | ||||
register_t * | register_t * | ||||
▲ Show 20 Lines • Show All 284 Lines • Show Last 20 Lines |