|
@@ -28,7 +28,19 @@
|
|
|
#include <sys/stat.h>
|
|
|
#include <sys/wait.h>
|
|
|
|
|
|
-#define TEST_ROOT "/tmp/test-container-executor"
|
|
|
+#ifdef __APPLE__
|
|
|
+#include <CoreFoundation/CFString.h>
|
|
|
+#include <CoreFoundation/CFPreferences.h>
|
|
|
+
|
|
|
+#define TMPDIR "/private/tmp"
|
|
|
+#define RELTMPDIR "../.."
|
|
|
+#else
|
|
|
+#define RELTMPDIR ".."
|
|
|
+#define TMPDIR "/tmp"
|
|
|
+#endif
|
|
|
+
|
|
|
+#define TEST_ROOT TMPDIR "/test-container-executor"
|
|
|
+
|
|
|
#define DONT_TOUCH_FILE "dont-touch-me"
|
|
|
#define NM_LOCAL_DIRS TEST_ROOT "/local-1," TEST_ROOT "/local-2," \
|
|
|
TEST_ROOT "/local-3," TEST_ROOT "/local-4," TEST_ROOT "/local-5"
|
|
@@ -153,8 +165,8 @@ void check_pid_file(const char* pid_file, pid_t mypid) {
|
|
|
}
|
|
|
|
|
|
void test_get_user_directory() {
|
|
|
- char *user_dir = get_user_directory("/tmp", "user");
|
|
|
- char *expected = "/tmp/usercache/user";
|
|
|
+ char *user_dir = get_user_directory(TMPDIR, "user");
|
|
|
+ char *expected = TMPDIR "/usercache/user";
|
|
|
if (strcmp(user_dir, expected) != 0) {
|
|
|
printf("test_get_user_directory expected %s got %s\n", expected, user_dir);
|
|
|
exit(1);
|
|
@@ -163,8 +175,8 @@ void test_get_user_directory() {
|
|
|
}
|
|
|
|
|
|
void test_get_app_directory() {
|
|
|
- char *expected = "/tmp/usercache/user/appcache/app_200906101234_0001";
|
|
|
- char *app_dir = (char *) get_app_directory("/tmp", "user",
|
|
|
+ char *expected = TMPDIR "/usercache/user/appcache/app_200906101234_0001";
|
|
|
+ char *app_dir = (char *) get_app_directory(TMPDIR, "user",
|
|
|
"app_200906101234_0001");
|
|
|
if (strcmp(app_dir, expected) != 0) {
|
|
|
printf("test_get_app_directory expected %s got %s\n", expected, app_dir);
|
|
@@ -174,9 +186,9 @@ void test_get_app_directory() {
|
|
|
}
|
|
|
|
|
|
void test_get_container_directory() {
|
|
|
- char *container_dir = get_container_work_directory("/tmp", "owen", "app_1",
|
|
|
+ char *container_dir = get_container_work_directory(TMPDIR, "owen", "app_1",
|
|
|
"container_1");
|
|
|
- char *expected = "/tmp/usercache/owen/appcache/app_1/container_1";
|
|
|
+ char *expected = TMPDIR"/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);
|
|
@@ -186,9 +198,9 @@ void test_get_container_directory() {
|
|
|
}
|
|
|
|
|
|
void test_get_container_launcher_file() {
|
|
|
- char *expected_file = ("/tmp/usercache/user/appcache/app_200906101234_0001"
|
|
|
+ char *expected_file = (TMPDIR"/usercache/user/appcache/app_200906101234_0001"
|
|
|
"/launch_container.sh");
|
|
|
- char *app_dir = get_app_directory("/tmp", "user",
|
|
|
+ char *app_dir = get_app_directory(TMPDIR, "user",
|
|
|
"app_200906101234_0001");
|
|
|
char *container_file = get_container_launcher_file(app_dir);
|
|
|
if (strcmp(container_file, expected_file) != 0) {
|
|
@@ -210,15 +222,15 @@ void test_get_app_log_dir() {
|
|
|
free(logdir);
|
|
|
}
|
|
|
|
|
|
-void test_check_user() {
|
|
|
+void test_check_user(int expectedFailure) {
|
|
|
printf("\nTesting test_check_user\n");
|
|
|
struct passwd *user = check_user(username);
|
|
|
- if (user == NULL) {
|
|
|
+ if (user == NULL && !expectedFailure) {
|
|
|
printf("FAIL: failed check for user %s\n", username);
|
|
|
exit(1);
|
|
|
}
|
|
|
free(user);
|
|
|
- if (check_user("lp") != NULL) {
|
|
|
+ if (check_user("lp") != NULL && !expectedFailure) {
|
|
|
printf("FAIL: failed check for system user lp\n");
|
|
|
exit(1);
|
|
|
}
|
|
@@ -226,7 +238,7 @@ void test_check_user() {
|
|
|
printf("FAIL: failed check for system user root\n");
|
|
|
exit(1);
|
|
|
}
|
|
|
- if (check_user("daemon") == NULL) {
|
|
|
+ if (check_user("daemon") == NULL && !expectedFailure) {
|
|
|
printf("FAIL: failed check for whitelisted system user daemon\n");
|
|
|
exit(1);
|
|
|
}
|
|
@@ -238,8 +250,9 @@ void test_resolve_config_path() {
|
|
|
printf("FAIL: failed to resolve config_name on an absolute path name: /bin/ls\n");
|
|
|
exit(1);
|
|
|
}
|
|
|
- if (strcmp(resolve_config_path("../bin/ls", "/bin/ls"), "/bin/ls") != 0) {
|
|
|
- printf("FAIL: failed to resolve config_name on a relative path name: ../bin/ls (relative to /bin/ls)");
|
|
|
+ if (strcmp(resolve_config_path(RELTMPDIR TEST_ROOT, TEST_ROOT), TEST_ROOT) != 0) {
|
|
|
+ printf("FAIL: failed to resolve config_name on a relative path name: "
|
|
|
+ RELTMPDIR TEST_ROOT " (relative to " TEST_ROOT ")");
|
|
|
exit(1);
|
|
|
}
|
|
|
}
|
|
@@ -262,9 +275,9 @@ void test_delete_container() {
|
|
|
exit(1);
|
|
|
}
|
|
|
char* app_dir = get_app_directory(TEST_ROOT "/local-2", yarn_username, "app_1");
|
|
|
- char* dont_touch = get_app_directory(TEST_ROOT "/local-2", yarn_username,
|
|
|
+ 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",
|
|
|
+ char* container_dir = get_container_work_directory(TEST_ROOT "/local-2",
|
|
|
yarn_username, "app_1", "container_1");
|
|
|
char buffer[100000];
|
|
|
sprintf(buffer, "mkdir -p %s/who/let/the/dogs/out/who/who", container_dir);
|
|
@@ -324,9 +337,9 @@ void test_delete_container() {
|
|
|
|
|
|
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,
|
|
|
+ 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",
|
|
|
+ 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);
|
|
@@ -484,7 +497,7 @@ void test_signal_container_group() {
|
|
|
exit(0);
|
|
|
}
|
|
|
printf("Child container launched as %d\n", child);
|
|
|
- // there's a race condition for child calling change_user and us
|
|
|
+ // there's a race condition for child calling change_user and us
|
|
|
// calling signal_container_as_user, hence sleeping
|
|
|
sleep(3);
|
|
|
if (signal_container_as_user(yarn_username, child, SIGKILL) != 0) {
|
|
@@ -500,7 +513,7 @@ void test_signal_container_group() {
|
|
|
exit(1);
|
|
|
}
|
|
|
if (WTERMSIG(status) != SIGKILL) {
|
|
|
- printf("FAIL: child was killed with %d instead of %d\n",
|
|
|
+ printf("FAIL: child was killed with %d instead of %d\n",
|
|
|
WTERMSIG(status), SIGKILL);
|
|
|
exit(1);
|
|
|
}
|
|
@@ -546,7 +559,7 @@ void test_init_app() {
|
|
|
fflush(stderr);
|
|
|
pid_t child = fork();
|
|
|
if (child == -1) {
|
|
|
- printf("FAIL: failed to fork process for init_app - %s\n",
|
|
|
+ printf("FAIL: failed to fork process for init_app - %s\n",
|
|
|
strerror(errno));
|
|
|
exit(1);
|
|
|
} else if (child == 0) {
|
|
@@ -628,7 +641,7 @@ void test_run_container() {
|
|
|
printf("FAIL: failed to seteuid back to user - %s\n", strerror(errno));
|
|
|
exit(1);
|
|
|
}
|
|
|
- if (fprintf(script, "#!/bin/bash\n"
|
|
|
+ if (fprintf(script, "#!/usr/bin/env bash\n"
|
|
|
"touch foobar\n"
|
|
|
"exit 0") < 0) {
|
|
|
printf("FAIL: fprintf failed - %s\n", strerror(errno));
|
|
@@ -640,17 +653,17 @@ void test_run_container() {
|
|
|
}
|
|
|
fflush(stdout);
|
|
|
fflush(stderr);
|
|
|
- char* container_dir = get_container_work_directory(TEST_ROOT "/local-1",
|
|
|
+ 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",
|
|
|
+ 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",
|
|
|
+ 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) {
|
|
@@ -704,7 +717,7 @@ void test_run_container() {
|
|
|
// effective user id. If executed by a super-user everything
|
|
|
// gets tested. Here are different ways of execing the test binary:
|
|
|
// 1. regular user assuming user == yarn user
|
|
|
-// $ test-container-executor
|
|
|
+// $ test-container-executor
|
|
|
// 2. regular user with a given yarn user
|
|
|
// $ test-container-executor yarn_user
|
|
|
// 3. super user with a given user and assuming user == yarn user
|
|
@@ -712,6 +725,7 @@ void test_run_container() {
|
|
|
// 4. super user with a given user and a given yarn user
|
|
|
// # test-container-executor user yarn_user
|
|
|
int main(int argc, char **argv) {
|
|
|
+ int ret;
|
|
|
LOGFILE = stdout;
|
|
|
ERRORFILE = stderr;
|
|
|
|
|
@@ -719,7 +733,7 @@ int main(int argc, char **argv) {
|
|
|
if (system("chmod -R u=rwx " TEST_ROOT "; rm -fr " TEST_ROOT)) {
|
|
|
exit(1);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
if (mkdirs(TEST_ROOT "/logs/userlogs", 0755) != 0) {
|
|
|
exit(1);
|
|
|
}
|
|
@@ -778,12 +792,38 @@ int main(int argc, char **argv) {
|
|
|
printf("\nTesting delete_app()\n");
|
|
|
test_delete_app();
|
|
|
|
|
|
- test_check_user();
|
|
|
+ test_check_user(0);
|
|
|
+
|
|
|
+#ifdef __APPLE__
|
|
|
+ printf("OS X: disabling CrashReporter\n");
|
|
|
+ /*
|
|
|
+ * disable the "unexpectedly quit" dialog box
|
|
|
+ * because we know we're going to make our container
|
|
|
+ * do exactly that.
|
|
|
+ */
|
|
|
+ CFStringRef crashType = CFSTR("DialogType");
|
|
|
+ CFStringRef crashModeNone = CFSTR("None");
|
|
|
+ CFStringRef crashAppID = CFSTR("com.apple.CrashReporter");
|
|
|
+ CFStringRef crashOldMode = CFPreferencesCopyAppValue(CFSTR("DialogType"), CFSTR("com.apple.CrashReporter"));
|
|
|
+
|
|
|
+ CFPreferencesSetAppValue(crashType, crashModeNone, crashAppID);
|
|
|
+ CFPreferencesAppSynchronize(crashAppID);
|
|
|
+#endif
|
|
|
|
|
|
// the tests that change user need to be run in a subshell, so that
|
|
|
// when they change user they don't give up our privs
|
|
|
run_test_in_child("test_signal_container_group", test_signal_container_group);
|
|
|
|
|
|
+#ifdef __APPLE__
|
|
|
+ /*
|
|
|
+ * put the "unexpectedly quit" dialog back
|
|
|
+ */
|
|
|
+
|
|
|
+ CFPreferencesSetAppValue(crashType, crashOldMode, crashAppID);
|
|
|
+ CFPreferencesAppSynchronize(crashAppID);
|
|
|
+ printf("OS X: CrashReporter re-enabled\n");
|
|
|
+#endif
|
|
|
+
|
|
|
// init app and run container can't be run if you aren't testing as root
|
|
|
if (getuid() == 0) {
|
|
|
// these tests do internal forks so that the change_owner and execs
|
|
@@ -792,7 +832,13 @@ int main(int argc, char **argv) {
|
|
|
test_run_container();
|
|
|
}
|
|
|
|
|
|
- seteuid(0);
|
|
|
+ /*
|
|
|
+ * try to seteuid(0). if it doesn't work, carry on anyway.
|
|
|
+ * we're going to capture the return value to get rid of a
|
|
|
+ * compiler warning.
|
|
|
+ */
|
|
|
+ ret=seteuid(0);
|
|
|
+ ret++;
|
|
|
// test_delete_user must run as root since that's how we use the delete_as_user
|
|
|
test_delete_user();
|
|
|
free_configurations();
|
|
@@ -803,8 +849,19 @@ int main(int argc, char **argv) {
|
|
|
}
|
|
|
|
|
|
read_config(TEST_ROOT "/test.cfg");
|
|
|
+#ifdef __APPLE__
|
|
|
+ username = "_uucp";
|
|
|
+ test_check_user(1);
|
|
|
+
|
|
|
+ username = "_networkd";
|
|
|
+ test_check_user(1);
|
|
|
+#else
|
|
|
username = "bin";
|
|
|
- test_check_user();
|
|
|
+ test_check_user(1);
|
|
|
+
|
|
|
+ username = "sys";
|
|
|
+ test_check_user(1);
|
|
|
+#endif
|
|
|
|
|
|
run("rm -fr " TEST_ROOT);
|
|
|
printf("\nFinished tests\n");
|