static int test_console_running_container(struct lxc_container *c) { int nrconsoles, i, ret = -1; int ttynum [MAXCONSOLES]; int ttyfd [MAXCONSOLES]; int masterfd[MAXCONSOLES]; for (i = 0; i < MAXCONSOLES; i++) ttynum[i] = ttyfd[i] = masterfd[i] = -1; ttynum[0] = 1; ret = c->console_getfd(c, &ttynum[0], &masterfd[0]); if (ret < 0) { TSTERR("console allocate failed"); goto err1; } ttyfd[0] = ret; if (ttynum[0] != 1) { TSTERR("console allocate got bad ttynum %d", ttynum[0]); goto err2; } /* attempt to alloc same ttynum */ ret = c->console_getfd(c, &ttynum[0], &masterfd[1]); if (ret != -1) { TSTERR("console allocate should fail for allocated ttynum %d", ttynum[0]); goto err2; } close(masterfd[0]); masterfd[0] = -1; close(ttyfd[0]); ttyfd[0] = -1; /* ensure we can allocate all consoles, we do this a few times to * show that the closes are freeing up the allocated slots */ for (i = 0; i < 10; i++) { for (nrconsoles = 0; nrconsoles < MAXCONSOLES; nrconsoles++) { ret = c->console_getfd(c, &ttynum[nrconsoles], &masterfd[nrconsoles]); if (ret < 0) break; ttyfd[nrconsoles] = ret; } if (nrconsoles != TTYCNT) { TSTERR("didn't allocate all consoles %d != %d", nrconsoles, TTYCNT); goto err2; } test_console_close_all(ttyfd, masterfd); } ret = 0; err2: test_console_close_all(ttyfd, masterfd); err1: return ret; }
static int test_attach_lsm_cmd(struct lxc_container *ct) { int ret; pid_t pid; int pipefd[2]; char result[1024]; char *space; char *argv[] = {"cat", "/proc/self/attr/current", NULL}; lxc_attach_command_t command = {"cat", argv}; lxc_attach_options_t attach_options = LXC_ATTACH_OPTIONS_DEFAULT; TSTOUT("Testing attach lsm label with cmd...\n"); ret = pipe(pipefd); if (ret < 0) { TSTERR("pipe failed %d", ret); return ret; } attach_options.stdout_fd = pipefd[1]; ret = ct->attach(ct, lxc_attach_run_command, &command, &attach_options, &pid); if (ret < 0) { TSTERR("attach failed"); goto err1; } ret = read(pipefd[0], result, sizeof(result)-1); if (ret < 0) { TSTERR("read failed %d", ret); goto err2; } result[ret] = '\0'; space = strchr(result, '\n'); if (space) *space = '\0'; space = strchr(result, ' '); if (space) *space = '\0'; ret = -1; if (strcmp(lsm_label, result)) { TSTERR("LSM label mismatch expected:%s got:%s", lsm_label, result); goto err2; } ret = 0; err2: wait_for_pid(pid); err1: close(pipefd[0]); close(pipefd[1]); return ret; }
static int test_attach_func(struct lxc_container *ct) { int ret; pid_t pid,nspid; int pipefd[2]; char result[1024]; lxc_attach_options_t attach_options = LXC_ATTACH_OPTIONS_DEFAULT; TSTOUT("Testing attach with func...\n"); /* XXX: We can't just use &nspid and have test_attach_func_func fill * it in because the function doesn't run in our process context but * in a fork()ed from us context. We read the result through a pipe. */ ret = pipe(pipefd); if (ret < 0) { TSTERR("pipe failed %d", ret); return ret; } attach_options.stdout_fd = pipefd[1]; ret = ct->attach(ct, test_attach_func_func, NULL, &attach_options, &pid); if (ret < 0) { TSTERR("attach failed"); goto err1; } ret = read(pipefd[0], result, sizeof(result)-1); if (ret < 0) { TSTERR("read failed %d", ret); goto err2; } result[ret] = '\0'; /* There is a small chance the pid is reused inside the NS, so we * just print it and don't actually do this check * * if (pid == nspid) TSTERR(...) */ nspid = atoi(result); TSTOUT("Pid:%d in NS:%d\n", pid, nspid); ret = 0; err2: wait_for_pid(pid); err1: close(pipefd[0]); close(pipefd[1]); return ret; }
static int test_attach_lsm_func(struct lxc_container *ct) { int ret; pid_t pid; int pipefd[2]; char result[1024]; lxc_attach_options_t attach_options = LXC_ATTACH_OPTIONS_DEFAULT; TSTOUT("Testing attach lsm label with func...\n"); ret = pipe(pipefd); if (ret < 0) { TSTERR("pipe failed %d", ret); return ret; } attach_options.stdout_fd = pipefd[1]; attach_options.attach_flags &= ~(LXC_ATTACH_LSM_EXEC|LXC_ATTACH_DROP_CAPABILITIES); attach_options.attach_flags |= LXC_ATTACH_LSM_NOW; ret = ct->attach(ct, test_attach_lsm_func_func, NULL, &attach_options, &pid); if (ret < 0) { TSTERR("attach failed"); goto err1; } ret = read(pipefd[0], result, sizeof(result)-1); if (ret < 0) { TSTERR("read failed %d", ret); goto err2; } result[ret] = '\0'; if (strcmp(lsm_label, result)) { TSTERR("LSM label mismatch expected:%s got:%s", lsm_label, result); ret = -1; goto err2; } ret = 0; err2: wait_for_pid(pid); err1: close(pipefd[0]); close(pipefd[1]); return ret; }
static int test_attach_cmd(struct lxc_container *ct) { int ret; pid_t pid; char *argv[] = {"cmp", "-s", "/sbin/init", "/bin/busybox", NULL}; lxc_attach_command_t command = {"cmp", argv}; lxc_attach_options_t attach_options = LXC_ATTACH_OPTIONS_DEFAULT; TSTOUT("Testing attach with success command...\n"); ret = ct->attach(ct, lxc_attach_run_command, &command, &attach_options, &pid); if (ret < 0) { TSTERR("attach failed"); return ret; } ret = wait_for_pid(pid); if (ret < 0) { TSTERR("attach success command got bad return %d", ret); return ret; } TSTOUT("Testing attach with failure command...\n"); argv[2] = "/etc/fstab"; ret = ct->attach(ct, lxc_attach_run_command, &command, &attach_options, &pid); if (ret < 0) { TSTERR("attach failed"); return ret; } ret = wait_for_pid(pid); if (ret == 0) { TSTERR("attach failure command got bad return %d", ret); return -1; } return 0; }
static void test_lsm_detect(void) { if (lsm_enabled()) { if (!strcmp(lsm_name(), "SELinux")) { lsm_config_key = "lxc.se_context"; lsm_label = "unconfined_u:unconfined_r:lxc_t:s0-s0:c0.c1023"; } else if (!strcmp(lsm_name(), "AppArmor")) { lsm_config_key = "lxc.aa_profile"; lsm_label = "lxc-container-default"; } else { TSTERR("unknown lsm %s enabled, add test code here", lsm_name()); exit(EXIT_FAILURE); } } }
int main() { struct lxc_container *c; const char *p1, *p2; int retval = -1; c = lxc_container_new(MYNAME, NULL); if (!c) { TSTERR("create using default path"); goto err; } p1 = c->get_config_path(c); p2 = c->config_file_name(c); if (!p1 || !p2 || strncmp(p1, p2, strlen(p1))) { TSTERR("Bad result for path names"); goto err; } #define CPATH "/boo" #define FPATH "/boo/lxctest1/config" if (!c->set_config_path(c, "/boo")) { TSTERR("Error setting custom path"); goto err; } p1 = c->get_config_path(c); p2 = c->config_file_name(c); if (strcmp(p1, CPATH) || strcmp(p2, FPATH)) { TSTERR("Bad result for path names after set_config_path()"); goto err; } lxc_container_put(c); c = lxc_container_new(MYNAME, CPATH); if (!c) { TSTERR("create using custom path"); goto err; } p1 = c->get_config_path(c); p2 = c->config_file_name(c); if (strcmp(p1, CPATH) || strcmp(p2, FPATH)) { TSTERR("Bad result for path names after create with custom path"); goto err; } retval = 0; err: lxc_container_put(c); return retval; }
/* * test_running_container: test cgroup functions against a running container * * @group : name of the container group or NULL for default "lxc" * @name : name of the container */ static int test_running_container(const char *lxcpath, const char *group, const char *name) { int ret = -1; struct lxc_container *c = NULL; char *cgrelpath; char relpath[PATH_MAX+1]; char value[NAME_MAX], value_save[NAME_MAX]; sprintf(relpath, "%s/%s", group ? group : "lxc", name); if ((c = lxc_container_new(name, lxcpath)) == NULL) { TSTERR("container %s couldn't instantiate", name); goto err1; } if (!c->is_defined(c)) { TSTERR("container %s does not exist", name); goto err2; } cgrelpath = lxc_cmd_get_cgroup_path(c->name, c->config_path, "freezer"); if (!cgrelpath) { TSTERR("lxc_cmd_get_cgroup_path returned NULL"); goto err2; } if (!strstr(cgrelpath, relpath)) { TSTERR("lxc_cmd_get_cgroup_path %s not in %s", relpath, cgrelpath); goto err3; } /* test get/set value using memory.soft_limit_in_bytes file */ ret = lxc_cgroup_get("memory.soft_limit_in_bytes", value, sizeof(value), c->name, c->config_path); if (ret < 0) { TSTERR("lxc_cgroup_get failed"); goto err3; } strcpy(value_save, value); ret = lxc_cgroup_set("memory.soft_limit_in_bytes", "512M", c->name, c->config_path); if (ret < 0) { TSTERR("lxc_cgroup_set failed %d %d", ret, errno); goto err3; } ret = lxc_cgroup_get("memory.soft_limit_in_bytes", value, sizeof(value), c->name, c->config_path); if (ret < 0) { TSTERR("lxc_cgroup_get failed"); goto err3; } if (strcmp(value, "536870912\n")) { TSTERR("lxc_cgroup_set_bypath failed to set value >%s<", value); goto err3; } /* restore original value */ ret = lxc_cgroup_set("memory.soft_limit_in_bytes", value_save, c->name, c->config_path); if (ret < 0) { TSTERR("lxc_cgroup_set failed"); goto err3; } ret = 0; err3: free(cgrelpath); err2: lxc_container_put(c); err1: return ret; }