static uint8_t wait_domain_id(domainid_t domainid) { uint8_t exitcode; errval_t err = spawn_wait(domainid, &exitcode, false); if(err_is_fail(err)) { USER_PANIC_ERR(err, "spawn_wait"); } return exitcode; }
static ct_process_t __local_enter_cb(ct_handler_t h, ct_process_desc_t ph, int (*cb)(void *), void *arg, bool is_exec) { struct container *ct = cth2ct(h); struct process_desc *p = prh2pr(ph); struct process *pr; int aux = -1, pid; int wait_pipe[2]; if (ct->state != CT_RUNNING) return ERR_PTR(-LCTERR_BADCTSTATE); if (ct->nsmask & CLONE_NEWPID) { if (switch_ns(ct->p.pid, &pid_ns, &aux)) return ERR_PTR(-LCTERR_INVARG); } pr = xmalloc(sizeof(struct process)); if (pr == NULL) return ERR_PTR(-1); local_process_init(pr); if (pipe(wait_pipe)) { xfree(pr); return ERR_PTR(-1); } pid = fork(); if (pid == 0) { struct ns_desc *ns; close(wait_pipe[0]); if (p->fds) { p->fds[p->fdn] = wait_pipe[1]; if (setup_fds(p->fds, p->fdn + 1)) exit(-1); wait_pipe[1] = p->fdn; } for (aux = 0; namespaces[aux]; aux++) { ns = namespaces[aux]; if (ns->cflag == CLONE_NEWPID) continue; if (!(ns->cflag & ct->nsmask)) continue; if (switch_ns(ct->p.pid, ns, NULL)) exit(-1); } if (cgroups_attach(ct)) exit(-1); if (ct->root_path && !(ct->nsmask & CLONE_NEWNS)) { char nroot[128]; /* * Otherwise switched by setns() */ snprintf(nroot, sizeof(nroot), "/proc/%d/root", ct->p.pid); if (set_current_root(nroot)) exit(-1); } if (apply_creds(p)) exit(-1); if (is_exec) spawn_wake_and_cloexec(wait_pipe, 0); else spawn_wake_and_close(wait_pipe, 0); aux = cb(arg); if (is_exec) spawn_wake_and_close(wait_pipe, -1); exit(aux); } close(wait_pipe[1]); if (aux >= 0) restore_ns(aux, &pid_ns); if (spawn_wait(wait_pipe)) goto err; if (spawn_wait_and_close(wait_pipe) != INT_MIN) goto err; pr->pid = pid; return &pr->h; err: xfree(pr); close(wait_pipe[0]); waitpid(pid, NULL, 0); return ERR_PTR(-1); }
static ct_process_t __local_spawn_cb(ct_handler_t h, ct_process_desc_t ph, int (*cb)(void *), void *arg, bool is_exec) { struct container *ct = cth2ct(h); struct process_desc *p = prh2pr(ph); int ret = -1, pid, aux; struct ct_clone_arg ca; if (ct->state != CT_STOPPED) return ERR_PTR(-LCTERR_BADCTSTATE); ret = fs_mount(ct); if (ret) return ERR_PTR(ret); if ((ct->flags & CT_KILLABLE) && !(ct->nsmask & CLONE_NEWPID)) { if (add_service_controller(ct)) goto err_cg; } ret = cgroups_create(ct); if (ret) goto err_cg; ret = -1; if (pipe(ca.child_wait_pipe)) goto err_pipe; if (pipe(ca.parent_wait_pipe)) goto err_pipe2; ca.cb = cb; ca.arg = arg; ca.ct = ct; ca.p = p; ca.is_exec = is_exec; pid = clone(ct_clone, &ca.stack_ptr, ct->nsmask | SIGCHLD, &ca); if (pid < 0) goto err_clone; ct->p.pid = pid; close(ca.child_wait_pipe[0]); close(ca.parent_wait_pipe[1]); if (ct->nsmask & CLONE_NEWUSER) { if (write_id_mappings(pid, &ct->uid_map, "uid_map")) goto err_net; if (write_id_mappings(pid, &ct->gid_map, "gid_map")) goto err_net; } if (net_start(ct)) goto err_net; spawn_wake_and_close(ca.child_wait_pipe, 0); aux = spawn_wait(ca.parent_wait_pipe); if (aux != 0) { ret = aux; goto err_ch; } aux = spawn_wait_and_close(ca.parent_wait_pipe); if (aux != INT_MIN) { ret = -1; goto err_ch; } ct->state = CT_RUNNING; return &ct->p.h; err_ch: net_stop(ct); err_net: spawn_wake_and_close(ca.child_wait_pipe, -1); libct_process_wait(&ct->p.h, NULL); err_clone: close(ca.parent_wait_pipe[0]); close(ca.parent_wait_pipe[1]); err_pipe2: close(ca.child_wait_pipe[0]); close(ca.child_wait_pipe[1]); err_pipe: cgroups_destroy(ct); err_cg: fs_umount(ct); return ERR_PTR(ret); }