int main(int argc, char **argv) { struct ct_arg cta; int p[2], status; libct_session_t s; ct_handler_t ct; ct_process_desc_t pd; ct_process_t pr, epr; test_init(); if (pipe(p)) return tst_perr("Unable to create pipe"); cta.mark = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, 0, 0); cta.mark[0] = 0; cta.mark[1] = 0; cta.wait_fd = p[0]; s = libct_session_open_local(); ct = libct_container_create(s, "test"); libct_container_set_nsmask(ct, CLONE_NEWPID); pd = libct_process_desc_create(s); pr = libct_container_spawn_cb(ct, pd, set_ct_alive, &cta); if (libct_handle_is_err(pr)) { return fail("Unable to start CT"); } epr = libct_container_enter_cb(ct, pd, set_ct_enter, &cta); if (libct_handle_is_err(epr)) return fail("Unable to enter into CT"); if (kill(libct_process_get_pid(pr), SIGKILL)) return fail("Unable to send a signal to the init process"); if (libct_process_wait(epr, &status)) return fail("Unable to wait a process"); if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGKILL) return fail("Unexpected status %x\n", status); if (libct_process_wait(pr, &status)) return fail("Unable to wait a process"); if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGKILL) return fail("Unexpected status %x\n", status); libct_container_wait(ct); libct_container_destroy(ct); libct_process_desc_destroy(pd); libct_process_destroy(epr); libct_session_close(s); return pass("CT is created and entered"); }
int main(int argc, char **argv) { int fd, p[2], status; struct ct_arg cta; libct_session_t s; ct_handler_t ct; ct_process_desc_t pd; ct_process_t pr; pipe(p); mkdir(FS_ROOT, 0600); fd = open(FS_ROOT "/" FS_FILE, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (fd < 0) { tst_perr("Can't create file"); return 2; } write(fd, FS_DATA, sizeof(FS_DATA)); close(fd); cta.fs_data = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, 0, 0); cta.fs_data[0] = '\0'; cta.fs_data[ENTER_DOFF] = '\0'; cta.wait_fd = p[0]; s = libct_session_open_local(); ct = libct_container_create(s, "test"); pd = libct_process_desc_create(s); libct_fs_set_root(ct, FS_ROOT); libct_container_spawn_cb(ct, pd, ct_main_fn, &cta); pr = libct_container_enter_cb(ct, pd, ct_enter_fn, &cta); if (libct_handle_is_err(pr)) fail("Unable to enter into CT"); libct_process_wait(pr, &status); write(p[1], "a", 1); libct_container_wait(ct); libct_container_destroy(ct); libct_session_close(s); unlink(FS_ROOT "/" FS_FILE); rmdir(FS_ROOT); if (strcmp(cta.fs_data, FS_DATA)) return fail("FS not accessed"); if (strcmp(cta.fs_data + ENTER_DOFF, FS_DATA)) return fail("FS not entered"); return pass("FS is created and entered"); }
static int local_ct_wait(ct_handler_t h) { struct container *ct = cth2ct(h); int ret, status; if (ct->state != CT_RUNNING) return -LCTERR_BADCTSTATE; if (ct->p.pid > 0) { ret = libct_process_wait(&ct->p.h, &status); if (ret < 0) return -1; } fs_umount(ct); cgroups_destroy(ct); /* FIXME -- can be held accross restarts */ net_stop(ct); ct->state = CT_STOPPED; return 0; }
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); }