void test_delete_app() { char* app_dir = get_app_directory(TEST_ROOT "/local-2", yarn_username, "app_2"); char* dont_touch = get_app_directory(TEST_ROOT "/local-2", yarn_username, DONT_TOUCH_FILE); char* container_dir = get_container_work_directory(TEST_ROOT "/local-2", yarn_username, "app_2", "container_1"); char buffer[100000]; sprintf(buffer, "mkdir -p %s/who/let/the/dogs/out/who/who", container_dir); run(buffer); sprintf(buffer, "touch %s", dont_touch); run(buffer); // soft link to the canary file from the container directory sprintf(buffer, "ln -s %s %s/who/softlink", dont_touch, container_dir); run(buffer); // hard link to the canary file from the container directory sprintf(buffer, "ln %s %s/who/hardlink", dont_touch, container_dir); run(buffer); // create a dot file in the container directory sprintf(buffer, "touch %s/who/let/.dotfile", container_dir); run(buffer); // create a no permission file sprintf(buffer, "touch %s/who/let/protect", container_dir); run(buffer); sprintf(buffer, "chmod 000 %s/who/let/protect", container_dir); run(buffer); // create a no permission directory sprintf(buffer, "chmod 000 %s/who/let", container_dir); run(buffer); // delete container directory int ret = delete_as_user(yarn_username, app_dir, NULL); if (ret != 0) { printf("FAIL: return code from delete_as_user is %d\n", ret); exit(1); } // check to make sure the container directory is gone if (access(container_dir, R_OK) == 0) { printf("FAIL: failed to delete the directory - %s\n", container_dir); exit(1); } // check to make sure the app directory is gone if (access(app_dir, R_OK) == 0) { printf("FAIL: didn't delete the directory - %s\n", app_dir); exit(1); } // but that the canary is not gone if (access(dont_touch, R_OK) != 0) { printf("FAIL: accidently deleted file %s\n", dont_touch); exit(1); } free(app_dir); free(container_dir); free(dont_touch); }
void test_get_container_directory() { char *container_dir = get_container_work_directory("/tmp", "owen", "app_1", "container_1"); char *expected = "/tmp/usercache/owen/appcache/app_1/container_1"; if (strcmp(container_dir, expected) != 0) { printf("Fail get_container_work_directory got %s expected %s\n", container_dir, expected); exit(1); } free(container_dir); }
/** * Function to prepare the container directories. * It creates the container work and log directories. */ static int create_container_directories(const char* user, const char *app_id, const char *container_id, char* const* local_dir, char* const* log_dir, const char *work_dir) { // create dirs as 0750 const mode_t perms = S_IRWXU | S_IRGRP | S_IXGRP; if (app_id == NULL || container_id == NULL || user == NULL) { fprintf(LOGFILE, "Either app_id, container_id or the user passed is null.\n"); return -1; } int result = -1; char* const* local_dir_ptr; for(local_dir_ptr = local_dir; *local_dir_ptr != NULL; ++local_dir_ptr) { char *container_dir = get_container_work_directory(*local_dir_ptr, user, app_id, container_id); if (container_dir == NULL) { return -1; } if (mkdirs(container_dir, perms) == 0) { result = 0; } // continue on to create other work directories free(container_dir); } if (result != 0) { return result; } result = -1; // also make the directory for the container logs char *combined_name = malloc(strlen(app_id) + strlen(container_id) + 2); if (combined_name == NULL) { fprintf(LOGFILE, "Malloc of combined name failed\n"); result = -1; } else { sprintf(combined_name, "%s/%s", app_id, container_id); char* const* log_dir_ptr; for(log_dir_ptr = log_dir; *log_dir_ptr != NULL; ++log_dir_ptr) { char *container_log_dir = get_app_log_directory(*log_dir_ptr, combined_name); if (container_log_dir == NULL) { free(combined_name); return -1; } else if (mkdirs(container_log_dir, perms) != 0) { free(container_log_dir); } else { result = 0; free(container_log_dir); } } free(combined_name); } if (result != 0) { return result; } result = -1; // also make the tmp directory char *tmp_dir = get_tmp_directory(work_dir); if (tmp_dir == NULL) { return -1; } if (mkdirs(tmp_dir, perms) == 0) { result = 0; } free(tmp_dir); return result; }
void test_run_container() { printf("\nTesting run container\n"); if (seteuid(0) != 0) { printf("FAIL: seteuid to root failed - %s\n", strerror(errno)); exit(1); } FILE* creds = fopen(TEST_ROOT "/creds.txt", "w"); if (creds == NULL) { printf("FAIL: failed to create credentials file - %s\n", strerror(errno)); exit(1); } if (fprintf(creds, "secret key\n") < 0) { printf("FAIL: fprintf failed - %s\n", strerror(errno)); exit(1); } if (fclose(creds) != 0) { printf("FAIL: fclose failed - %s\n", strerror(errno)); exit(1); } char * cgroups_pids[] = { TEST_ROOT "/cgroups-pid1.txt", TEST_ROOT "/cgroups-pid2.txt", 0 }; close(creat(cgroups_pids[0], O_RDWR)); close(creat(cgroups_pids[1], O_RDWR)); const char* script_name = TEST_ROOT "/container-script"; FILE* script = fopen(script_name, "w"); if (script == NULL) { printf("FAIL: failed to create script file - %s\n", strerror(errno)); exit(1); } if (seteuid(user_detail->pw_uid) != 0) { printf("FAIL: failed to seteuid back to user - %s\n", strerror(errno)); exit(1); } if (fprintf(script, "#!/bin/bash\n" "touch foobar\n" "exit 0") < 0) { printf("FAIL: fprintf failed - %s\n", strerror(errno)); exit(1); } if (fclose(script) != 0) { printf("FAIL: fclose failed - %s\n", strerror(errno)); exit(1); } fflush(stdout); fflush(stderr); char* container_dir = get_container_work_directory(TEST_ROOT "/local-1", yarn_username, "app_4", "container_1"); const char * pid_file = TEST_ROOT "/pid.txt"; pid_t child = fork(); if (child == -1) { printf("FAIL: failed to fork process for init_app - %s\n", strerror(errno)); exit(1); } else if (child == 0) { if (launch_container_as_user(yarn_username, "app_4", "container_1", container_dir, script_name, TEST_ROOT "/creds.txt", pid_file, local_dirs, log_dirs, "cgroups", cgroups_pids) != 0) { printf("FAIL: failed in child\n"); exit(42); } // should never return exit(1); } int status = 0; if (waitpid(child, &status, 0) <= 0) { printf("FAIL: failed waiting for process %" PRId64 " - %s\n", (int64_t)child, strerror(errno)); exit(1); } if (access(TEST_ROOT "/logs/userlogs/app_4/container_1", R_OK) != 0) { printf("FAIL: failed to create container log directory\n"); exit(1); } if (access(container_dir, R_OK) != 0) { printf("FAIL: failed to create container directory %s\n", container_dir); exit(1); } char buffer[100000]; sprintf(buffer, "%s/foobar", container_dir); if (access(buffer, R_OK) != 0) { printf("FAIL: failed to create touch file %s\n", buffer); exit(1); } free(container_dir); container_dir = get_app_log_directory(TEST_ROOT "/logs/userlogs", "app_4/container_1"); if (access(container_dir, R_OK) != 0) { printf("FAIL: failed to create app log directory %s\n", container_dir); exit(1); } free(container_dir); if (seteuid(0) != 0) { printf("FAIL: seteuid to root failed - %s\n", strerror(errno)); exit(1); } check_pid_file(pid_file, child); check_pid_file(cgroups_pids[0], child); check_pid_file(cgroups_pids[1], child); }
void test_run_container() { printf("\nTesting run container\n"); if (seteuid(0) != 0) { printf("FAIL: seteuid to root failed - %s\n", strerror(errno)); exit(1); } FILE* creds = fopen(TEST_ROOT "/creds.txt", "w"); if (creds == NULL) { printf("FAIL: failed to create credentials file - %s\n", strerror(errno)); exit(1); } if (fprintf(creds, "secret key\n") < 0) { printf("FAIL: fprintf failed - %s\n", strerror(errno)); exit(1); } if (fclose(creds) != 0) { printf("FAIL: fclose failed - %s\n", strerror(errno)); exit(1); } const char* script_name = TEST_ROOT "/container-script"; FILE* script = fopen(script_name, "w"); if (script == NULL) { printf("FAIL: failed to create script file - %s\n", strerror(errno)); exit(1); } if (seteuid(user_detail->pw_uid) != 0) { printf("FAIL: failed to seteuid back to user - %s\n", strerror(errno)); exit(1); } if (fprintf(script, "#!/bin/bash\n" "touch foobar\n" "exit 0") < 0) { printf("FAIL: fprintf failed - %s\n", strerror(errno)); exit(1); } if (fclose(script) != 0) { printf("FAIL: fclose failed - %s\n", strerror(errno)); exit(1); } fflush(stdout); fflush(stderr); char* container_dir = get_container_work_directory(TEST_ROOT "/local-1", username, "app_4", "container_1"); const char * pid_file = TEST_ROOT "/pid.txt"; pid_t child = fork(); if (child == -1) { printf("FAIL: failed to fork process for init_app - %s\n", strerror(errno)); exit(1); } else if (child == 0) { if (launch_container_as_user(username, "app_4", "container_1", container_dir, script_name, TEST_ROOT "/creds.txt", pid_file) != 0) { printf("FAIL: failed in child\n"); exit(42); } // should never return exit(1); } int status = 0; if (waitpid(child, &status, 0) <= 0) { printf("FAIL: failed waiting for process %d - %s\n", child, strerror(errno)); exit(1); } if (access(TEST_ROOT "/logs/userlogs/app_4/container_1", R_OK) != 0) { printf("FAIL: failed to create container log directory\n"); exit(1); } if (access(container_dir, R_OK) != 0) { printf("FAIL: failed to create container directory %s\n", container_dir); exit(1); } char buffer[100000]; sprintf(buffer, "%s/foobar", container_dir); if (access(buffer, R_OK) != 0) { printf("FAIL: failed to create touch file %s\n", buffer); exit(1); } free(container_dir); container_dir = get_app_log_directory("logs", "app_4/container_1"); if (access(container_dir, R_OK) != 0) { printf("FAIL: failed to create app log directory %s\n", container_dir); exit(1); } free(container_dir); if(access(pid_file, R_OK) != 0) { printf("FAIL: failed to create pid file %s\n", pid_file); exit(1); } int pidfd = open(pid_file, O_RDONLY); if (pidfd == -1) { printf("FAIL: failed to open pid file %s - %s\n", pid_file, strerror(errno)); exit(1); } char pidBuf[100]; ssize_t bytes = read(pidfd, pidBuf, 100); if (bytes == -1) { printf("FAIL: failed to read from pid file %s - %s\n", pid_file, strerror(errno)); exit(1); } pid_t mypid = child; char myPidBuf[33]; snprintf(myPidBuf, 33, "%d", mypid); if (strncmp(pidBuf, myPidBuf, strlen(myPidBuf)) != 0) { printf("FAIL: failed to find matching pid in pid file\n"); printf("FAIL: Expected pid %d : Got %.*s", mypid, (int)bytes, pidBuf); exit(1); } }