Renamed struct cleanup to struct launch_ctx
This commit is contained in:
@@ -44,7 +44,7 @@
|
||||
|
||||
static char g_launch_error[1024] = {};
|
||||
|
||||
struct cleanup {
|
||||
struct launch_ctx {
|
||||
/* list of handles that were opened by launch() that should be closed if an error occurs */
|
||||
mx_handle_t *auto_handles;
|
||||
size_t auto_handle_count;
|
||||
@@ -153,26 +153,26 @@ static int validate_argv(int argc, const char **argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int validate_fds(const struct launch_info *info, struct cleanup *cleanup)
|
||||
static int validate_fds(const struct launch_info *info, struct launch_ctx *ctx)
|
||||
{
|
||||
cleanup->fd = calloc(LAUNCH_MAX_FDS, sizeof(int));
|
||||
ctx->fd = calloc(LAUNCH_MAX_FDS, sizeof(int));
|
||||
bool auto_stdio = true;
|
||||
|
||||
if (info->flags & LAUNCH_SET_FD) {
|
||||
memcpy(cleanup->fd, info->fd, sizeof info->fd);
|
||||
memcpy(ctx->fd, info->fd, sizeof info->fd);
|
||||
auto_stdio = false;
|
||||
} else {
|
||||
for (int i = 0; i < LAUNCH_MAX_FDS; i++) {
|
||||
cleanup->fd[i] = i;
|
||||
ctx->fd[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < LAUNCH_MAX_FDS; i++) {
|
||||
int fd = cleanup->fd[i];
|
||||
int fd = ctx->fd[i];
|
||||
bool inherited = false;
|
||||
|
||||
if (fd == FD_INHERIT) {
|
||||
fd = cleanup->fd[i] = i;
|
||||
fd = ctx->fd[i] = i;
|
||||
inherited = true;
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ static int validate_fds(const struct launch_info *info, struct cleanup *cleanup)
|
||||
}
|
||||
|
||||
if (inherited || auto_stdio) {
|
||||
cleanup->fd[i] = FD_NONE;
|
||||
ctx->fd[i] = FD_NONE;
|
||||
} else {
|
||||
set_error_msg("file descriptor %d (launch_info.fd[%zu]) is invalid", fd, i);
|
||||
return EBADF;
|
||||
@@ -233,14 +233,14 @@ static int validate_ns(int flags, const struct namespace_entry *ns, size_t count
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int collect_names(const struct launch_info *info, struct cleanup *cleanup)
|
||||
static int collect_names(const struct launch_info *info, struct launch_ctx *ctx)
|
||||
{
|
||||
size_t ns_count = info->ns_count;
|
||||
const struct namespace_entry *ns = info->ns;
|
||||
|
||||
if (info->flags & LAUNCH_INHERIT_NS) {
|
||||
ns_count = cleanup->inherited_ns_len;
|
||||
ns = cleanup->inherited_ns;
|
||||
ns_count = ctx->inherited_ns_len;
|
||||
ns = ctx->inherited_ns;
|
||||
}
|
||||
|
||||
size_t name_count = ns_count;
|
||||
@@ -259,16 +259,16 @@ static int collect_names(const struct launch_info *info, struct cleanup *cleanup
|
||||
names[name_count - 1] = info->cwd.path;
|
||||
}
|
||||
|
||||
cleanup->names = names;
|
||||
cleanup->name_count = name_count;
|
||||
ctx->names = names;
|
||||
ctx->name_count = name_count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int count_handles(const struct launch_info *info, struct cleanup *cleanup)
|
||||
static int count_handles(const struct launch_info *info, struct launch_ctx *ctx)
|
||||
{
|
||||
size_t all_handles = 0, auto_handles = 0;
|
||||
for (size_t i = 0; i < LAUNCH_MAX_FDS; i++) {
|
||||
if (cleanup->fd[i] != FD_NONE) {
|
||||
if (ctx->fd[i] != FD_NONE) {
|
||||
all_handles++;
|
||||
auto_handles++;
|
||||
}
|
||||
@@ -279,8 +279,8 @@ static int count_handles(const struct launch_info *info, struct cleanup *cleanup
|
||||
bool auto_ns = false;
|
||||
|
||||
if (info->flags & LAUNCH_INHERIT_NS) {
|
||||
ns_len = cleanup->inherited_ns_len;
|
||||
ns = cleanup->inherited_ns;
|
||||
ns_len = ctx->inherited_ns_len;
|
||||
ns = ctx->inherited_ns;
|
||||
auto_ns = true;
|
||||
}
|
||||
|
||||
@@ -326,23 +326,23 @@ static int count_handles(const struct launch_info *info, struct cleanup *cleanup
|
||||
|
||||
all_handles += info->handle_count;
|
||||
|
||||
cleanup->auto_handle_count = auto_handles;
|
||||
cleanup->b_handle_count = all_handles;
|
||||
ctx->auto_handle_count = auto_handles;
|
||||
ctx->b_handle_count = all_handles;
|
||||
|
||||
cleanup->auto_handles = calloc(cleanup->auto_handle_count, sizeof *cleanup->auto_handles);
|
||||
cleanup->b_handles = calloc(cleanup->b_handle_count, sizeof *cleanup->b_handles);
|
||||
ctx->auto_handles = calloc(ctx->auto_handle_count, sizeof *ctx->auto_handles);
|
||||
ctx->b_handles = calloc(ctx->b_handle_count, sizeof *ctx->b_handles);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int collect_handles(const struct launch_info *info, struct cleanup *cleanup)
|
||||
static int collect_handles(const struct launch_info *info, struct launch_ctx *ctx)
|
||||
{
|
||||
memcpy(cleanup->b_handles, info->handles, info->handle_count * sizeof *info->handles);
|
||||
memcpy(ctx->b_handles, info->handles, info->handle_count * sizeof *info->handles);
|
||||
size_t b_idx = info->handle_count;
|
||||
size_t auto_idx = 0;
|
||||
|
||||
for (int i = 0; i < LAUNCH_MAX_FDS; i++) {
|
||||
int fd = cleanup->fd[i];
|
||||
int fd = ctx->fd[i];
|
||||
if (fd == FD_NONE) {
|
||||
continue;
|
||||
}
|
||||
@@ -365,23 +365,23 @@ static int collect_handles(const struct launch_info *info, struct cleanup *clean
|
||||
return EBADF;
|
||||
}
|
||||
|
||||
cleanup->b_handles[b_idx].info = MX_B_HND(MX_B_FD, i);
|
||||
cleanup->b_handles[b_idx].handle = fd_handle;
|
||||
ctx->b_handles[b_idx].info = MX_B_HND(MX_B_FD, i);
|
||||
ctx->b_handles[b_idx].handle = fd_handle;
|
||||
b_idx++;
|
||||
|
||||
cleanup->auto_handles[auto_idx++] = fd_handle;
|
||||
cleanup->stdio[i] = fd_handle;
|
||||
ctx->auto_handles[auto_idx++] = fd_handle;
|
||||
ctx->stdio[i] = fd_handle;
|
||||
}
|
||||
|
||||
if (info->flags & LAUNCH_INHERIT_NS) {
|
||||
for (size_t i = 0; i < cleanup->inherited_ns_len; i++) {
|
||||
const struct namespace_entry *ent = &cleanup->inherited_ns[i];
|
||||
for (size_t i = 0; i < ctx->inherited_ns_len; i++) {
|
||||
const struct namespace_entry *ent = &ctx->inherited_ns[i];
|
||||
|
||||
cleanup->b_handles[b_idx].info = MX_B_HND(MX_B_NS_DIR, i);
|
||||
cleanup->b_handles[b_idx].handle = ent->handle;
|
||||
ctx->b_handles[b_idx].info = MX_B_HND(MX_B_NS_DIR, i);
|
||||
ctx->b_handles[b_idx].handle = ent->handle;
|
||||
b_idx++;
|
||||
|
||||
cleanup->auto_handles[auto_idx++] = ent->handle;
|
||||
ctx->auto_handles[auto_idx++] = ent->handle;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -421,196 +421,196 @@ static int collect_handles(const struct launch_info *info, struct cleanup *clean
|
||||
return EBADF;
|
||||
}
|
||||
|
||||
cleanup->b_handles[b_idx].info = MX_B_HND(MX_B_NS_DIR, i);
|
||||
cleanup->b_handles[b_idx].handle = ns_handle;
|
||||
ctx->b_handles[b_idx].info = MX_B_HND(MX_B_NS_DIR, i);
|
||||
ctx->b_handles[b_idx].handle = ns_handle;
|
||||
b_idx++;
|
||||
|
||||
if (is_auto) {
|
||||
cleanup->auto_handles[auto_idx++] = ns_handle;
|
||||
ctx->auto_handles[auto_idx++] = ns_handle;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fail_cleanup(struct cleanup *cleanup)
|
||||
static void fail_cleanup(struct launch_ctx *ctx)
|
||||
{
|
||||
if (cleanup->exec_vmo) {
|
||||
mx_handle_close(cleanup->exec_vmo);
|
||||
if (ctx->exec_vmo) {
|
||||
mx_handle_close(ctx->exec_vmo);
|
||||
}
|
||||
|
||||
if (cleanup->auto_handles) {
|
||||
for (size_t i = 0; i < cleanup->auto_handle_count; i++) {
|
||||
if (cleanup->auto_handles[i]) {
|
||||
mx_handle_close(cleanup->auto_handles[i]);
|
||||
if (ctx->auto_handles) {
|
||||
for (size_t i = 0; i < ctx->auto_handle_count; i++) {
|
||||
if (ctx->auto_handles[i]) {
|
||||
mx_handle_close(ctx->auto_handles[i]);
|
||||
}
|
||||
}
|
||||
|
||||
free(cleanup->auto_handles);
|
||||
free(ctx->auto_handles);
|
||||
}
|
||||
|
||||
if (cleanup->inherited_ns) {
|
||||
for (size_t i = 0; i < cleanup->inherited_ns_len; i++) {
|
||||
struct namespace_entry *ent = &cleanup->inherited_ns[i];
|
||||
if (ctx->inherited_ns) {
|
||||
for (size_t i = 0; i < ctx->inherited_ns_len; i++) {
|
||||
struct namespace_entry *ent = &ctx->inherited_ns[i];
|
||||
free((char *)ent->path);
|
||||
mx_handle_close(ent->handle);
|
||||
}
|
||||
|
||||
free(cleanup->inherited_ns);
|
||||
cleanup->inherited_ns = NULL;
|
||||
cleanup->inherited_ns_len = 0;
|
||||
free(ctx->inherited_ns);
|
||||
ctx->inherited_ns = NULL;
|
||||
ctx->inherited_ns_len = 0;
|
||||
}
|
||||
|
||||
if (cleanup->names) {
|
||||
free(cleanup->names);
|
||||
cleanup->names = NULL;
|
||||
cleanup->name_count = 0;
|
||||
if (ctx->names) {
|
||||
free(ctx->names);
|
||||
ctx->names = NULL;
|
||||
ctx->name_count = 0;
|
||||
}
|
||||
|
||||
if (cleanup->b_handles) {
|
||||
free(cleanup->b_handles);
|
||||
if (ctx->b_handles) {
|
||||
free(ctx->b_handles);
|
||||
}
|
||||
|
||||
__elf_image_cleanup(&cleanup->exec);
|
||||
__elf_image_cleanup(&cleanup->vdso);
|
||||
__elf_image_cleanup(&ctx->exec);
|
||||
__elf_image_cleanup(&ctx->vdso);
|
||||
|
||||
if (cleanup->interp_vmo) {
|
||||
mx_handle_close(cleanup->interp_vmo);
|
||||
cleanup->interp_vmo = MX_NULL_HANDLE;
|
||||
if (ctx->interp_vmo) {
|
||||
mx_handle_close(ctx->interp_vmo);
|
||||
ctx->interp_vmo = MX_NULL_HANDLE;
|
||||
}
|
||||
|
||||
if (cleanup->interp_path) {
|
||||
free(cleanup->interp_path);
|
||||
cleanup->interp_path = NULL;
|
||||
if (ctx->interp_path) {
|
||||
free(ctx->interp_path);
|
||||
ctx->interp_path = NULL;
|
||||
}
|
||||
|
||||
if (cleanup->new_vmar) {
|
||||
mx_handle_close(cleanup->new_vmar);
|
||||
cleanup->new_vmar = MX_NULL_HANDLE;
|
||||
if (ctx->new_vmar) {
|
||||
mx_handle_close(ctx->new_vmar);
|
||||
ctx->new_vmar = MX_NULL_HANDLE;
|
||||
}
|
||||
|
||||
if (cleanup->stack_vmo) {
|
||||
mx_handle_close(cleanup->stack_vmo);
|
||||
cleanup->stack_vmo = MX_NULL_HANDLE;
|
||||
if (ctx->stack_vmo) {
|
||||
mx_handle_close(ctx->stack_vmo);
|
||||
ctx->stack_vmo = MX_NULL_HANDLE;
|
||||
}
|
||||
|
||||
if (cleanup->new_task) {
|
||||
mx_handle_close(cleanup->new_task);
|
||||
cleanup->new_task = MX_NULL_HANDLE;
|
||||
if (ctx->new_task) {
|
||||
mx_handle_close(ctx->new_task);
|
||||
ctx->new_task = MX_NULL_HANDLE;
|
||||
}
|
||||
|
||||
if (cleanup->bootstrap_local) {
|
||||
mx_handle_close(cleanup->bootstrap_local);
|
||||
cleanup->bootstrap_local = MX_NULL_HANDLE;
|
||||
if (ctx->bootstrap_local) {
|
||||
mx_handle_close(ctx->bootstrap_local);
|
||||
ctx->bootstrap_local = MX_NULL_HANDLE;
|
||||
}
|
||||
|
||||
if (cleanup->bootstrap_remote) {
|
||||
mx_handle_close(cleanup->bootstrap_remote);
|
||||
cleanup->bootstrap_remote = MX_NULL_HANDLE;
|
||||
if (ctx->bootstrap_remote) {
|
||||
mx_handle_close(ctx->bootstrap_remote);
|
||||
ctx->bootstrap_remote = MX_NULL_HANDLE;
|
||||
}
|
||||
|
||||
if (cleanup->fd) {
|
||||
free(cleanup->fd);
|
||||
cleanup->fd = NULL;
|
||||
if (ctx->fd) {
|
||||
free(ctx->fd);
|
||||
ctx->fd = NULL;
|
||||
}
|
||||
|
||||
if (cleanup->ldsvc_version == LDV1_VERSION && cleanup->ldsvc.handle) {
|
||||
mx_handle_close(cleanup->ldsvc.handle);
|
||||
cleanup->ldsvc.handle = MX_NULL_HANDLE;
|
||||
} else if (cleanup->ldsvc_version == LDV2_VERSION && cleanup->ldsvc.sock) {
|
||||
xpc_socket_destroy(cleanup->ldsvc.sock);
|
||||
cleanup->ldsvc.sock = NULL;
|
||||
if (ctx->ldsvc_version == LDV1_VERSION && ctx->ldsvc.handle) {
|
||||
mx_handle_close(ctx->ldsvc.handle);
|
||||
ctx->ldsvc.handle = MX_NULL_HANDLE;
|
||||
} else if (ctx->ldsvc_version == LDV2_VERSION && ctx->ldsvc.sock) {
|
||||
xpc_socket_destroy(ctx->ldsvc.sock);
|
||||
ctx->ldsvc.sock = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void success_cleanup(struct cleanup *cleanup)
|
||||
static void success_cleanup(struct launch_ctx *ctx)
|
||||
{
|
||||
if (cleanup->exec_vmo) {
|
||||
mx_handle_close(cleanup->exec_vmo);
|
||||
if (ctx->exec_vmo) {
|
||||
mx_handle_close(ctx->exec_vmo);
|
||||
}
|
||||
|
||||
if (cleanup->auto_handles) {
|
||||
for (size_t i = 0; i < cleanup->auto_handle_count; i++) {
|
||||
if (cleanup->auto_handles[i]) {
|
||||
mx_handle_close(cleanup->auto_handles[i]);
|
||||
if (ctx->auto_handles) {
|
||||
for (size_t i = 0; i < ctx->auto_handle_count; i++) {
|
||||
if (ctx->auto_handles[i]) {
|
||||
mx_handle_close(ctx->auto_handles[i]);
|
||||
}
|
||||
}
|
||||
|
||||
free(cleanup->auto_handles);
|
||||
free(ctx->auto_handles);
|
||||
}
|
||||
|
||||
if (cleanup->inherited_ns) {
|
||||
for (size_t i = 0; i < cleanup->inherited_ns_len; i++) {
|
||||
struct namespace_entry *ent = &cleanup->inherited_ns[i];
|
||||
if (ctx->inherited_ns) {
|
||||
for (size_t i = 0; i < ctx->inherited_ns_len; i++) {
|
||||
struct namespace_entry *ent = &ctx->inherited_ns[i];
|
||||
free((char *)ent->path);
|
||||
mx_handle_close(ent->handle);
|
||||
}
|
||||
|
||||
free(cleanup->inherited_ns);
|
||||
cleanup->inherited_ns = NULL;
|
||||
cleanup->inherited_ns_len = 0;
|
||||
free(ctx->inherited_ns);
|
||||
ctx->inherited_ns = NULL;
|
||||
ctx->inherited_ns_len = 0;
|
||||
}
|
||||
|
||||
if (cleanup->names) {
|
||||
free(cleanup->names);
|
||||
cleanup->names = NULL;
|
||||
cleanup->name_count = 0;
|
||||
if (ctx->names) {
|
||||
free(ctx->names);
|
||||
ctx->names = NULL;
|
||||
ctx->name_count = 0;
|
||||
}
|
||||
|
||||
if (cleanup->b_handles) {
|
||||
free(cleanup->b_handles);
|
||||
if (ctx->b_handles) {
|
||||
free(ctx->b_handles);
|
||||
}
|
||||
|
||||
__elf_image_cleanup(&cleanup->exec);
|
||||
__elf_image_cleanup(&cleanup->vdso);
|
||||
__elf_image_cleanup(&ctx->exec);
|
||||
__elf_image_cleanup(&ctx->vdso);
|
||||
|
||||
if (cleanup->interp_vmo) {
|
||||
mx_handle_close(cleanup->interp_vmo);
|
||||
cleanup->interp_vmo = MX_NULL_HANDLE;
|
||||
if (ctx->interp_vmo) {
|
||||
mx_handle_close(ctx->interp_vmo);
|
||||
ctx->interp_vmo = MX_NULL_HANDLE;
|
||||
}
|
||||
|
||||
if (cleanup->interp_path) {
|
||||
free(cleanup->interp_path);
|
||||
cleanup->interp_path = NULL;
|
||||
if (ctx->interp_path) {
|
||||
free(ctx->interp_path);
|
||||
ctx->interp_path = NULL;
|
||||
}
|
||||
|
||||
if (cleanup->stack_vmo) {
|
||||
mx_handle_close(cleanup->stack_vmo);
|
||||
cleanup->stack_vmo = MX_NULL_HANDLE;
|
||||
if (ctx->stack_vmo) {
|
||||
mx_handle_close(ctx->stack_vmo);
|
||||
ctx->stack_vmo = MX_NULL_HANDLE;
|
||||
}
|
||||
|
||||
if (cleanup->new_vmar) {
|
||||
mx_handle_close(cleanup->new_vmar);
|
||||
cleanup->new_vmar = MX_NULL_HANDLE;
|
||||
if (ctx->new_vmar) {
|
||||
mx_handle_close(ctx->new_vmar);
|
||||
ctx->new_vmar = MX_NULL_HANDLE;
|
||||
}
|
||||
|
||||
if (cleanup->bootstrap_local) {
|
||||
mx_handle_close(cleanup->bootstrap_local);
|
||||
cleanup->bootstrap_local = MX_NULL_HANDLE;
|
||||
if (ctx->bootstrap_local) {
|
||||
mx_handle_close(ctx->bootstrap_local);
|
||||
ctx->bootstrap_local = MX_NULL_HANDLE;
|
||||
}
|
||||
|
||||
if (cleanup->fd) {
|
||||
free(cleanup->fd);
|
||||
cleanup->fd = NULL;
|
||||
if (ctx->fd) {
|
||||
free(ctx->fd);
|
||||
ctx->fd = NULL;
|
||||
}
|
||||
|
||||
if (cleanup->ldsvc_version == LDV1_VERSION && cleanup->ldsvc.handle) {
|
||||
mx_handle_close(cleanup->ldsvc.handle);
|
||||
cleanup->ldsvc.handle = MX_NULL_HANDLE;
|
||||
} else if (cleanup->ldsvc_version == LDV2_VERSION && cleanup->ldsvc.sock) {
|
||||
xpc_socket_destroy(cleanup->ldsvc.sock);
|
||||
cleanup->ldsvc.sock = NULL;
|
||||
if (ctx->ldsvc_version == LDV1_VERSION && ctx->ldsvc.handle) {
|
||||
mx_handle_close(ctx->ldsvc.handle);
|
||||
ctx->ldsvc.handle = MX_NULL_HANDLE;
|
||||
} else if (ctx->ldsvc_version == LDV2_VERSION && ctx->ldsvc.sock) {
|
||||
xpc_socket_destroy(ctx->ldsvc.sock);
|
||||
ctx->ldsvc.sock = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int inherit_namespace(const struct launch_info *info, struct cleanup *cleanup)
|
||||
static int inherit_namespace(const struct launch_info *info, struct launch_ctx *ctx)
|
||||
{
|
||||
if (!(info->flags & LAUNCH_INHERIT_NS)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
cleanup->inherited_ns = mio_namespace_export(mio_global_namespace(), &cleanup->inherited_ns_len);
|
||||
return cleanup->inherited_ns ? 0 : -1;
|
||||
ctx->inherited_ns = mio_namespace_export(mio_global_namespace(), &ctx->inherited_ns_len);
|
||||
return ctx->inherited_ns ? 0 : -1;
|
||||
}
|
||||
|
||||
static mx_handle_t request_v1(mx_handle_t ldsvc, const char *name)
|
||||
@@ -684,13 +684,13 @@ static mx_handle_t request_v2(xpc_socket ldsvc, const char *name)
|
||||
return vmo;
|
||||
}
|
||||
|
||||
static mx_handle_t request_image(struct cleanup *cleanup, const char *name)
|
||||
static mx_handle_t request_image(struct launch_ctx *ctx, const char *name)
|
||||
{
|
||||
switch (cleanup->ldsvc_version) {
|
||||
switch (ctx->ldsvc_version) {
|
||||
case 0:
|
||||
return request_v1(cleanup->ldsvc.handle, name);
|
||||
return request_v1(ctx->ldsvc.handle, name);
|
||||
case 1:
|
||||
return request_v2(cleanup->ldsvc.sock, name);
|
||||
return request_v2(ctx->ldsvc.sock, name);
|
||||
default:
|
||||
return MX_NULL_HANDLE;
|
||||
}
|
||||
@@ -714,7 +714,7 @@ static const char *get_name_from_path(const struct launch_info *info)
|
||||
return e;
|
||||
}
|
||||
|
||||
static int load_exec(const struct launch_info *info, struct cleanup *cleanup)
|
||||
static int load_exec(const struct launch_info *info, struct launch_ctx *ctx)
|
||||
{
|
||||
mx_handle_t local_vmar = mx_bootstrap_handle_get(MX_B_VMAR_ROOT);
|
||||
mx_handle_t self_task = mx_bootstrap_handle_get(MX_B_TASK_SELF);
|
||||
@@ -727,74 +727,74 @@ static int load_exec(const struct launch_info *info, struct cleanup *cleanup)
|
||||
char interp_path[1024];
|
||||
interp_path[0] = '\0';
|
||||
|
||||
__elf_get_interp_path(cleanup->exec_vmo, interp_path, sizeof interp_path);
|
||||
__elf_get_interp_path(ctx->exec_vmo, interp_path, sizeof interp_path);
|
||||
|
||||
mx_handle_t real_exec = cleanup->exec_vmo;
|
||||
mx_handle_t real_exec = ctx->exec_vmo;
|
||||
|
||||
if (*interp_path != '\0') {
|
||||
real_exec = request_image(cleanup, interp_path);
|
||||
real_exec = request_image(ctx, interp_path);
|
||||
|
||||
if (real_exec == MX_NULL_HANDLE) {
|
||||
set_error_msg("cannot open program interpreter '%s'", interp_path);
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
cleanup->interp_vmo = real_exec;
|
||||
cleanup->interp_path = strdup(interp_path);
|
||||
ctx->interp_vmo = real_exec;
|
||||
ctx->interp_path = strdup(interp_path);
|
||||
}
|
||||
|
||||
const char *new_task_name = get_name_from_path(info);
|
||||
mx_status_t status = mx_task_create(self_task,
|
||||
new_task_name, strlen(new_task_name),
|
||||
0, &cleanup->new_task, &cleanup->new_vmar);
|
||||
0, &ctx->new_task, &ctx->new_vmar);
|
||||
|
||||
if (status != MX_OK) {
|
||||
return mio_errno_from_mx_status(status);
|
||||
}
|
||||
|
||||
__elf_image_init(local_vmar, cleanup->new_vmar, &cleanup->exec);
|
||||
if (__elf_image_load_image(&cleanup->exec, real_exec)) {
|
||||
set_error_msg("cannot load %s image", cleanup->interp_vmo ? "interpreter" : "executable");
|
||||
__elf_image_init(local_vmar, ctx->new_vmar, &ctx->exec);
|
||||
if (__elf_image_load_image(&ctx->exec, real_exec)) {
|
||||
set_error_msg("cannot load %s image", ctx->interp_vmo ? "interpreter" : "executable");
|
||||
return ENOEXEC;
|
||||
}
|
||||
|
||||
__elf_image_init(local_vmar, cleanup->new_vmar, &cleanup->vdso);
|
||||
if (__elf_image_load_image(&cleanup->vdso, vdso_vmo)) {
|
||||
__elf_image_init(local_vmar, ctx->new_vmar, &ctx->vdso);
|
||||
if (__elf_image_load_image(&ctx->vdso, vdso_vmo)) {
|
||||
set_error_msg("cannot load vDSO image");
|
||||
return ENOEXEC;
|
||||
}
|
||||
|
||||
if (__elf_image_link(&cleanup->exec, &cleanup->vdso)) {
|
||||
set_error_msg("cannot link %s image", cleanup->interp_vmo ? "interpreter" : "executable");
|
||||
if (__elf_image_link(&ctx->exec, &ctx->vdso)) {
|
||||
set_error_msg("cannot link %s image", ctx->interp_vmo ? "interpreter" : "executable");
|
||||
return ENOEXEC;
|
||||
}
|
||||
|
||||
cleanup->entry_point = __elf_image_entry_point(&cleanup->exec);
|
||||
ctx->entry_point = __elf_image_entry_point(&ctx->exec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int allocate_stack(struct cleanup *cleanup)
|
||||
static int allocate_stack(struct launch_ctx *ctx)
|
||||
{
|
||||
mx_status_t status = mx_vmo_create(DEFAULT_STACK_SZ, 0, &cleanup->stack_vmo);
|
||||
mx_status_t status = mx_vmo_create(DEFAULT_STACK_SZ, 0, &ctx->stack_vmo);
|
||||
if (status != MX_OK) {
|
||||
set_error_msg("cannot allocate stack for new process: %s", mx_status_to_string(status));
|
||||
return mio_errno_from_mx_status(status);
|
||||
}
|
||||
|
||||
mx_vaddr_t stack_buf;
|
||||
status = mx_vmar_map(cleanup->new_vmar, MX_VM_PERM_READ | MX_VM_PERM_WRITE,
|
||||
0, cleanup->stack_vmo, 0, DEFAULT_STACK_SZ, &stack_buf);
|
||||
status = mx_vmar_map(ctx->new_vmar, MX_VM_PERM_READ | MX_VM_PERM_WRITE,
|
||||
0, ctx->stack_vmo, 0, DEFAULT_STACK_SZ, &stack_buf);
|
||||
|
||||
if (status != MX_OK) {
|
||||
set_error_msg("cannot map stack for new process: %s", mx_status_to_string(status));
|
||||
return mio_errno_from_mx_status(status);
|
||||
}
|
||||
|
||||
cleanup->stack_ptr = stack_buf + DEFAULT_STACK_SZ;
|
||||
ctx->stack_ptr = stack_buf + DEFAULT_STACK_SZ;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_ldv1_handle(mx_handle_t handle, struct cleanup *cleanup)
|
||||
static int get_ldv1_handle(mx_handle_t handle, struct launch_ctx *ctx)
|
||||
{
|
||||
mx_handle_t t0, t1;
|
||||
mx_tunnel_create(&t0, &t1);
|
||||
@@ -823,12 +823,12 @@ static int get_ldv1_handle(mx_handle_t handle, struct cleanup *cleanup)
|
||||
return ENOLINK;
|
||||
}
|
||||
|
||||
cleanup->ldsvc_version = LDV1_VERSION;
|
||||
cleanup->ldsvc.handle = t1;
|
||||
ctx->ldsvc_version = LDV1_VERSION;
|
||||
ctx->ldsvc.handle = t1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_ldv2_handle(mx_handle_t handle, struct cleanup *cleanup)
|
||||
static int get_ldv2_handle(mx_handle_t handle, struct launch_ctx *ctx)
|
||||
{
|
||||
xpc_socket sock = xpc_socket_create(XPC_SOCKET_REQUESTER);
|
||||
xpc_socket_connect_tunnel(sock, handle);
|
||||
@@ -857,12 +857,12 @@ static int get_ldv2_handle(mx_handle_t handle, struct cleanup *cleanup)
|
||||
xpc_socket_release_tunnel(sock, NULL);
|
||||
xpc_socket_connect_tunnel(sock, t0);
|
||||
|
||||
cleanup->ldsvc_version = LDV2_VERSION;
|
||||
cleanup->ldsvc.sock = sock;
|
||||
ctx->ldsvc_version = LDV2_VERSION;
|
||||
ctx->ldsvc.sock = sock;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int open_ldv2_handle(struct cleanup *cleanup)
|
||||
static int open_ldv2_handle(struct launch_ctx *ctx)
|
||||
{
|
||||
int ldsvc_fd = open("/svc/horizon.sys.LoaderService/0", O_RDWR);
|
||||
if (ldsvc_fd == -1) {
|
||||
@@ -876,13 +876,13 @@ static int open_ldv2_handle(struct cleanup *cleanup)
|
||||
xpc_socket sock = xpc_socket_create(XPC_SOCKET_REQUESTER);
|
||||
xpc_socket_connect_tunnel(sock, handle);
|
||||
|
||||
cleanup->ldsvc_version = LDV2_VERSION;
|
||||
cleanup->ldsvc.sock = sock;
|
||||
ctx->ldsvc_version = LDV2_VERSION;
|
||||
ctx->ldsvc.sock = sock;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_ldsvc_handle(struct cleanup *cleanup)
|
||||
static int get_ldsvc_handle(struct launch_ctx *ctx)
|
||||
{
|
||||
size_t nr_handles;
|
||||
const mx_bootstrap_handle_t *handles = mx_bootstrap_handle_get_all(&nr_handles);
|
||||
@@ -905,11 +905,11 @@ static int get_ldsvc_handle(struct cleanup *cleanup)
|
||||
|
||||
int err = 0;
|
||||
if (handle == MX_NULL_HANDLE) {
|
||||
err = open_ldv2_handle(cleanup);
|
||||
err = open_ldv2_handle(ctx);
|
||||
} else if (version == LDV1_VERSION) {
|
||||
err = get_ldv1_handle(handle, cleanup);
|
||||
err = get_ldv1_handle(handle, ctx);
|
||||
} else if (version == LDV2_VERSION) {
|
||||
err = get_ldv2_handle(handle, cleanup);
|
||||
err = get_ldv2_handle(handle, ctx);
|
||||
} else {
|
||||
set_error_msg("no connection to loader service");
|
||||
return ENOLINK;
|
||||
@@ -1010,18 +1010,18 @@ static mx_handle_t *raw_handles(mx_bootstrap_handle_t *handles, size_t count)
|
||||
return out;
|
||||
}
|
||||
|
||||
static int send_interp_bootstrap_message(const struct launch_info *args, struct cleanup *cleanup)
|
||||
static int send_interp_bootstrap_message(const struct launch_info *args, struct launch_ctx *ctx)
|
||||
{
|
||||
mx_handle_t vdso_vmo = mx_bootstrap_handle_get(MX_B_VMO_VDSO);
|
||||
mx_handle_t ldsvc = MX_NULL_HANDLE;
|
||||
|
||||
if (cleanup->ldsvc_version == 0) {
|
||||
ldsvc = cleanup->ldsvc.handle;
|
||||
cleanup->ldsvc.handle = MX_NULL_HANDLE;
|
||||
if (ctx->ldsvc_version == 0) {
|
||||
ldsvc = ctx->ldsvc.handle;
|
||||
ctx->ldsvc.handle = MX_NULL_HANDLE;
|
||||
} else {
|
||||
xpc_socket_release_tunnel(cleanup->ldsvc.sock, &ldsvc);
|
||||
xpc_socket_destroy(cleanup->ldsvc.sock);
|
||||
cleanup->ldsvc.sock = NULL;
|
||||
xpc_socket_release_tunnel(ctx->ldsvc.sock, &ldsvc);
|
||||
xpc_socket_destroy(ctx->ldsvc.sock);
|
||||
ctx->ldsvc.sock = NULL;
|
||||
}
|
||||
|
||||
/* required handles for interpreter:
|
||||
@@ -1033,21 +1033,21 @@ static int send_interp_bootstrap_message(const struct launch_info *args, struct
|
||||
* exec vmar
|
||||
*/
|
||||
mx_bootstrap_handle_t handles[] = {
|
||||
ARG_HANDLE(cleanup->new_task, MX_B_HND(MX_B_TASK_SELF, 0)),
|
||||
ARG_HANDLE(cleanup->exec_vmo, MX_B_HND(MX_B_VMO_EXEC, 0)),
|
||||
ARG_HANDLE(cleanup->new_vmar, MX_B_HND(MX_B_VMAR_ROOT, 0)),
|
||||
ARG_HANDLE(cleanup->exec.remote_exec_vmar, MX_B_HND(MX_B_VMAR_EXEC, 0)),
|
||||
ARG_HANDLE(ctx->new_task, MX_B_HND(MX_B_TASK_SELF, 0)),
|
||||
ARG_HANDLE(ctx->exec_vmo, MX_B_HND(MX_B_VMO_EXEC, 0)),
|
||||
ARG_HANDLE(ctx->new_vmar, MX_B_HND(MX_B_VMAR_ROOT, 0)),
|
||||
ARG_HANDLE(ctx->exec.remote_exec_vmar, MX_B_HND(MX_B_VMAR_EXEC, 0)),
|
||||
ARG_HANDLE(vdso_vmo, MX_B_HND(MX_B_VMO_VDSO, 0)),
|
||||
ARG_HANDLE(ldsvc, MX_B_HND(MX_B_TUNNEL_LDSVC, cleanup->ldsvc_version)),
|
||||
ARG_HANDLE(cleanup->stdio[0], MX_B_HND(MX_B_FD, 0)),
|
||||
ARG_HANDLE(cleanup->stdio[1], MX_B_HND(MX_B_FD, 1)),
|
||||
ARG_HANDLE(cleanup->stdio[2], MX_B_HND(MX_B_FD, 2)),
|
||||
ARG_HANDLE(ldsvc, MX_B_HND(MX_B_TUNNEL_LDSVC, ctx->ldsvc_version)),
|
||||
ARG_HANDLE(ctx->stdio[0], MX_B_HND(MX_B_FD, 0)),
|
||||
ARG_HANDLE(ctx->stdio[1], MX_B_HND(MX_B_FD, 1)),
|
||||
ARG_HANDLE(ctx->stdio[2], MX_B_HND(MX_B_FD, 2)),
|
||||
};
|
||||
|
||||
static size_t handle_count = sizeof handles / sizeof handles[0];
|
||||
|
||||
const char *argv[] = {
|
||||
cleanup->interp_path,
|
||||
ctx->interp_path,
|
||||
args->path,
|
||||
};
|
||||
const int argc = sizeof argv / sizeof *argv;
|
||||
@@ -1062,7 +1062,7 @@ static int send_interp_bootstrap_message(const struct launch_info *args, struct
|
||||
handle_count, handles,
|
||||
&msg_len, &raw_handles);
|
||||
|
||||
mx_tunnel_write_etc(cleanup->bootstrap_local,
|
||||
mx_tunnel_write_etc(ctx->bootstrap_local,
|
||||
MX_TUNNEL_DUPLICATE_HANDLES,
|
||||
msg, msg_len,
|
||||
raw_handles, handle_count);
|
||||
@@ -1072,11 +1072,11 @@ static int send_interp_bootstrap_message(const struct launch_info *args, struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int send_exec_bootstrap_message(const struct launch_info *args, struct cleanup *cleanup)
|
||||
static int send_exec_bootstrap_message(const struct launch_info *args, struct launch_ctx *ctx)
|
||||
{
|
||||
mx_bootstrap_handle_t *default_handles =
|
||||
cleanup->b_handles
|
||||
+ cleanup->b_handle_count
|
||||
ctx->b_handles
|
||||
+ ctx->b_handle_count
|
||||
- NR_DEFAULT_HANDLES;
|
||||
|
||||
mx_handle_t vdso_vmo = mx_bootstrap_handle_get(MX_B_VMO_VDSO);
|
||||
@@ -1090,12 +1090,12 @@ static int send_exec_bootstrap_message(const struct launch_info *args, struct cl
|
||||
* MX_B_TUNNEL_BTSTP
|
||||
*/
|
||||
int tmp = 0;
|
||||
default_handles[tmp++] = ARG_HANDLE(cleanup->new_task, MX_B_HND(MX_B_TASK_SELF, 0));
|
||||
default_handles[tmp++] = ARG_HANDLE(ctx->new_task, MX_B_HND(MX_B_TASK_SELF, 0));
|
||||
default_handles[tmp++] = ARG_HANDLE(vdso_vmo, MX_B_HND(MX_B_VMO_VDSO, 0));
|
||||
default_handles[tmp++] = ARG_HANDLE(cleanup->exec_vmo, MX_B_HND(MX_B_VMO_EXEC, 0));
|
||||
default_handles[tmp++] = ARG_HANDLE(cleanup->new_vmar, MX_B_HND(MX_B_VMAR_ROOT, 0));
|
||||
default_handles[tmp++] = ARG_HANDLE(cleanup->exec.remote_exec_vmar, MX_B_HND(MX_B_VMAR_EXEC, 0));
|
||||
default_handles[tmp++] = ARG_HANDLE(cleanup->bootstrap_remote, MX_B_HND(MX_B_TUNNEL_BTSTP, 0));
|
||||
default_handles[tmp++] = ARG_HANDLE(ctx->exec_vmo, MX_B_HND(MX_B_VMO_EXEC, 0));
|
||||
default_handles[tmp++] = ARG_HANDLE(ctx->new_vmar, MX_B_HND(MX_B_VMAR_ROOT, 0));
|
||||
default_handles[tmp++] = ARG_HANDLE(ctx->exec.remote_exec_vmar, MX_B_HND(MX_B_VMAR_EXEC, 0));
|
||||
default_handles[tmp++] = ARG_HANDLE(ctx->bootstrap_remote, MX_B_HND(MX_B_TUNNEL_BTSTP, 0));
|
||||
|
||||
mx_handle_t *raw_handles;
|
||||
|
||||
@@ -1103,130 +1103,130 @@ static int send_exec_bootstrap_message(const struct launch_info *args, struct cl
|
||||
mx_bootstrap_msg_t *msg = build_bootstrap_message(
|
||||
args->argc, args->argv,
|
||||
0, NULL,
|
||||
cleanup->name_count, cleanup->names,
|
||||
cleanup->b_handle_count, cleanup->b_handles,
|
||||
ctx->name_count, ctx->names,
|
||||
ctx->b_handle_count, ctx->b_handles,
|
||||
&msg_len, &raw_handles);
|
||||
|
||||
mx_tunnel_write_etc(cleanup->bootstrap_local,
|
||||
mx_tunnel_write_etc(ctx->bootstrap_local,
|
||||
MX_TUNNEL_DUPLICATE_HANDLES,
|
||||
msg, msg_len,
|
||||
raw_handles, cleanup->b_handle_count);
|
||||
raw_handles, ctx->b_handle_count);
|
||||
|
||||
free(raw_handles);
|
||||
free(msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int send_bootstrap_messages(const struct launch_info *args, struct cleanup *cleanup)
|
||||
static int send_bootstrap_messages(const struct launch_info *args, struct launch_ctx *ctx)
|
||||
{
|
||||
if (cleanup->interp_vmo) {
|
||||
send_interp_bootstrap_message(args, cleanup);
|
||||
if (ctx->interp_vmo) {
|
||||
send_interp_bootstrap_message(args, ctx);
|
||||
}
|
||||
|
||||
send_exec_bootstrap_message(args, cleanup);
|
||||
send_exec_bootstrap_message(args, ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int launch(const struct launch_info *args, mx_handle_t *out_task)
|
||||
{
|
||||
struct cleanup cleanup = {};
|
||||
struct launch_ctx ctx = {};
|
||||
|
||||
int err = get_ldsvc_handle(&cleanup);
|
||||
int err = get_ldsvc_handle(&ctx);
|
||||
if (err != 0) {
|
||||
fail_cleanup(&cleanup);
|
||||
RET_ERR(err);
|
||||
fail_cleanup(&ctx);
|
||||
RET_ERR(err);
|
||||
}
|
||||
|
||||
if (!args->path) {
|
||||
fail_cleanup(&cleanup);
|
||||
fail_cleanup(&ctx);
|
||||
RET_ERR(EFAULT);
|
||||
}
|
||||
|
||||
err = validate_argv(args->argc, args->argv);
|
||||
if (err != 0) {
|
||||
fail_cleanup(&cleanup);
|
||||
fail_cleanup(&ctx);
|
||||
RET_ERR(err);
|
||||
}
|
||||
|
||||
err = validate_fds(args, &cleanup);
|
||||
err = validate_fds(args, &ctx);
|
||||
if (err != 0) {
|
||||
fail_cleanup(&cleanup);
|
||||
fail_cleanup(&ctx);
|
||||
RET_ERR(err);
|
||||
}
|
||||
|
||||
err = validate_ns(args->flags, args->ns, args->ns_count);
|
||||
if (err != 0) {
|
||||
fail_cleanup(&cleanup);
|
||||
fail_cleanup(&ctx);
|
||||
RET_ERR(err);
|
||||
}
|
||||
|
||||
err = inherit_namespace(args, &cleanup);
|
||||
err = inherit_namespace(args, &ctx);
|
||||
if (err != 0) {
|
||||
fail_cleanup(&cleanup);
|
||||
fail_cleanup(&ctx);
|
||||
RET_ERR(err);
|
||||
}
|
||||
|
||||
err = count_handles(args, &cleanup);
|
||||
err = count_handles(args, &ctx);
|
||||
if (err != 0) {
|
||||
fail_cleanup(&cleanup);
|
||||
fail_cleanup(&ctx);
|
||||
RET_ERR(err);
|
||||
}
|
||||
|
||||
err = collect_handles(args, &cleanup);
|
||||
err = collect_handles(args, &ctx);
|
||||
if (err != 0) {
|
||||
fail_cleanup(&cleanup);
|
||||
fail_cleanup(&ctx);
|
||||
RET_ERR(err);
|
||||
}
|
||||
|
||||
err = collect_names(args, &cleanup);
|
||||
err = collect_names(args, &ctx);
|
||||
if (err != 0) {
|
||||
fail_cleanup(&cleanup);
|
||||
fail_cleanup(&ctx);
|
||||
RET_ERR(err);
|
||||
}
|
||||
|
||||
int exec_fd = open(args->path, O_RDONLY);
|
||||
if (exec_fd == -1) {
|
||||
int error = errno;
|
||||
fail_cleanup(&cleanup);
|
||||
fail_cleanup(&ctx);
|
||||
set_error_msg("cannot open file '%s': %s", args->path, strerror(error));
|
||||
RET_ERR(error);
|
||||
}
|
||||
|
||||
err = mio_map_file(exec_fd, &cleanup.exec_vmo);
|
||||
err = mio_map_file(exec_fd, &ctx.exec_vmo);
|
||||
close(exec_fd);
|
||||
|
||||
if (err != 0) {
|
||||
fail_cleanup(&cleanup);
|
||||
fail_cleanup(&ctx);
|
||||
set_error_msg("cannot map file '%s': %s", args->path, strerror(-err));
|
||||
RET_ERR(-err);
|
||||
}
|
||||
|
||||
err = load_exec(args, &cleanup);
|
||||
err = load_exec(args, &ctx);
|
||||
if (err != 0) {
|
||||
fail_cleanup(&cleanup);
|
||||
fail_cleanup(&ctx);
|
||||
RET_ERR(err);
|
||||
}
|
||||
|
||||
err = allocate_stack(&cleanup);
|
||||
err = allocate_stack(&ctx);
|
||||
if (err != 0) {
|
||||
fail_cleanup(&cleanup);
|
||||
fail_cleanup(&ctx);
|
||||
RET_ERR(err);
|
||||
}
|
||||
|
||||
mx_tunnel_create(&cleanup.bootstrap_local, &cleanup.bootstrap_remote);
|
||||
mx_tunnel_create(&ctx.bootstrap_local, &ctx.bootstrap_remote);
|
||||
|
||||
err = send_bootstrap_messages(args, &cleanup);
|
||||
err = send_bootstrap_messages(args, &ctx);
|
||||
if (err != 0) {
|
||||
fail_cleanup(&cleanup);
|
||||
fail_cleanup(&ctx);
|
||||
RET_ERR(err);
|
||||
}
|
||||
|
||||
success_cleanup(&cleanup);
|
||||
success_cleanup(&ctx);
|
||||
set_error_msg("success");
|
||||
mx_task_start(cleanup.new_task, cleanup.entry_point, cleanup.stack_ptr, cleanup.bootstrap_remote, 0);
|
||||
mx_handle_close(cleanup.bootstrap_remote);
|
||||
mx_task_start(ctx.new_task, ctx.entry_point, ctx.stack_ptr, ctx.bootstrap_remote, 0);
|
||||
mx_handle_close(ctx.bootstrap_remote);
|
||||
|
||||
*out_task = cleanup.new_task;
|
||||
*out_task = ctx.new_task;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user