]> git.ipfire.org Git - pakfire.git/blobdiff - tests/libpakfire/jail.c
jail: Remove callbacks from command calls
[pakfire.git] / tests / libpakfire / jail.c
index 008e05ef7352e575458785775a2ea3d6a4ba6eab..0848f02f8e543f641b4d2362d1dd87445b9cc100 100644 (file)
@@ -18,6 +18,8 @@
 #                                                                             #
 #############################################################################*/
 
+#include <sys/mount.h>
+
 #include <pakfire/cgroup.h>
 #include <pakfire/jail.h>
 
@@ -43,28 +45,70 @@ static int test_create(const struct test* t) {
        struct pakfire_jail* jail = NULL;
 
        // Create a new jail
-       ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire, 0));
+       ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire));
 
        // Destroy it
        ASSERT_NULL(pakfire_jail_unref(jail));
 
-       // Create an interactive jail
-       ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire, PAKFIRE_JAIL_INTERACTIVE));
-
-       // Destroy it again
-       ASSERT_NULL(pakfire_jail_unref(jail));
-
        return EXIT_SUCCESS;
 
 FAIL:
        return EXIT_FAILURE;
 }
 
+static int test_exit_code(const struct test* t) {
+       struct pakfire_jail* jail = NULL;
+       int r = EXIT_FAILURE;
+
+       const char* argv[] = {
+               "/command", "exit-with-code", "123", NULL,
+       };
+
+       // Create a new jail
+       ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire));
+
+       // Check if we receive the correct exit code
+       ASSERT(pakfire_jail_exec(jail, argv, 0) == 123);
+
+       // Success
+       r = EXIT_SUCCESS;
+
+FAIL:
+       if (jail)
+               pakfire_jail_unref(jail);
+
+       return r;
+}
+
+static int test_segv(const struct test* t) {
+       struct pakfire_jail* jail = NULL;
+       int r = EXIT_FAILURE;
+
+       const char* argv[] = {
+               "/command", "segv", NULL,
+       };
+
+       // Create a new jail
+       ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire));
+
+       // Check if we receive the correct exit code
+       ASSERT(pakfire_jail_exec(jail, argv, 0) == 139);
+
+       // Success
+       r = EXIT_SUCCESS;
+
+FAIL:
+       if (jail)
+               pakfire_jail_unref(jail);
+
+       return r;
+}
+
 static int test_env(const struct test* t) {
        struct pakfire_jail* jail = NULL;
 
        // Create a new jail
-       ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire, 0));
+       ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire));
 
        // Check if the default variables are set
        ASSERT(pakfire_jail_get_env(jail, "LANG"));
@@ -92,10 +136,10 @@ static int test_exec(const struct test* t) {
        struct pakfire_jail* jail = NULL;
 
        // Create a new jail
-       ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire, 0));
+       ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire));
 
        // Try to execute something
-       ASSERT_SUCCESS(pakfire_jail_exec(jail, cmd_hello_world, NULL));
+       ASSERT_SUCCESS(pakfire_jail_exec(jail, cmd_hello_world, 0));
 
        // Destroy it
        ASSERT_NULL(pakfire_jail_unref(jail));
@@ -112,16 +156,16 @@ static int test_launch_into_cgroup(const struct test* t) {
        int r = EXIT_FAILURE;
 
        // Create a new cgroup
-       ASSERT_SUCCESS(pakfire_cgroup_open(&cgroup, t->pakfire, "pakfire-test", 0));
+       ASSERT_SUCCESS(pakfire_cgroup_open(&cgroup, t->ctx, "pakfire-test", 0));
 
        // Create a new jail
-       ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire, 0));
+       ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire));
 
        // Connect jail to the cgroup
        ASSERT_SUCCESS(pakfire_jail_set_cgroup(jail, cgroup));
 
        // Run command
-       ASSERT(pakfire_jail_exec(jail, cmd_hello_world, NULL) == 0);
+       ASSERT(pakfire_jail_exec(jail, cmd_hello_world, 0) == 0);
 
        r = EXIT_SUCCESS;
 
@@ -146,7 +190,7 @@ static int test_nice(const struct test* t) {
        };
 
        // Create a new jail
-       ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire, 0));
+       ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire));
 
        // Set invalid nice levels
        ASSERT_ERRNO(pakfire_jail_nice(jail,  100), EINVAL);
@@ -155,8 +199,11 @@ static int test_nice(const struct test* t) {
        // Set something sane
        ASSERT_SUCCESS(pakfire_jail_nice(jail, 5));
 
+       // Capture the output of the next execution
+       pakfire_jail_set_stdout_callback(jail, pakfire_jail_capture_stdout, &output);
+
        // Check if the nice level has been set
-       ASSERT_SUCCESS(pakfire_jail_exec(jail, argv, &output));
+       ASSERT_SUCCESS(pakfire_jail_exec(jail, argv, 0));
        ASSERT_STRING_EQUALS(output, "5\n");
 
        // Success
@@ -178,10 +225,10 @@ static int test_memory_limit(const struct test* t) {
 
 
        // Create cgroup
-       ASSERT_SUCCESS(pakfire_cgroup_open(&cgroup, t->pakfire, "pakfire-test", 0));
+       ASSERT_SUCCESS(pakfire_cgroup_open(&cgroup, t->ctx, "pakfire-test", 0));
 
        // Create jail
-       ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire, 0));
+       ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire));
 
        // Connect jail to the cgroup
        ASSERT_SUCCESS(pakfire_jail_set_cgroup(jail, cgroup));
@@ -190,10 +237,10 @@ static int test_memory_limit(const struct test* t) {
        ASSERT_SUCCESS(pakfire_cgroup_set_memory_limit(cgroup, 100 * 1024 * 1024));
 
        // Try to exhaust all memory
-       ASSERT_FAILURE(pakfire_jail_exec(jail, cmd_exhaust_memory, NULL));
+       ASSERT_FAILURE(pakfire_jail_exec(jail, cmd_exhaust_memory, 0));
 
        // A fork bomb should also exhaust all memory
-       ASSERT_FAILURE(pakfire_jail_exec(jail, cmd_fork_bomb, NULL));
+       ASSERT_FAILURE(pakfire_jail_exec(jail, cmd_fork_bomb, 0));
 
        // Success
        r = EXIT_SUCCESS;
@@ -215,10 +262,10 @@ static int test_pid_limit(const struct test* t) {
        int r = EXIT_FAILURE;
 
        // Create cgroup
-       ASSERT_SUCCESS(pakfire_cgroup_open(&cgroup, t->pakfire, "pakfire-test", 0));
+       ASSERT_SUCCESS(pakfire_cgroup_open(&cgroup, t->ctx, "pakfire-test", 0));
 
        // Create jail
-       ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire, 0));
+       ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire));
 
        // Connect jail to the cgroup
        ASSERT_SUCCESS(pakfire_jail_set_cgroup(jail, cgroup));
@@ -227,7 +274,7 @@ static int test_pid_limit(const struct test* t) {
        ASSERT_SUCCESS(pakfire_cgroup_set_pid_limit(cgroup, 100));
 
        // Try to fork as many processes as possible
-       ASSERT_FAILURE(pakfire_jail_exec(jail, cmd_fork_bomb, NULL));
+       ASSERT_FAILURE(pakfire_jail_exec(jail, cmd_fork_bomb, 0));
 
        // Success
        r = EXIT_SUCCESS;
@@ -263,15 +310,174 @@ FAIL:
        return r;
 }
 
+static int test_bind(const struct test* t) {
+       struct pakfire_jail* jail = NULL;
+       char* output = NULL;
+       int r = EXIT_FAILURE;
+
+       const char* source = "/";
+       const char* target = "/oldroot";
+
+       const char* argv[] = {
+               "/command", "check-mountpoint", target, NULL,
+       };
+
+       // Create a new jail
+       ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire));
+
+       // Bind-mount nonsense
+       ASSERT_ERRNO(pakfire_jail_bind(jail, NULL, target, 0), EINVAL);
+       ASSERT_ERRNO(pakfire_jail_bind(jail, source, NULL, 0), EINVAL);
+
+       // Bind-mount something
+       ASSERT_SUCCESS(pakfire_jail_bind(jail, source, target, MS_RDONLY));
+
+       // Check if the mount actually works
+       ASSERT_SUCCESS(pakfire_jail_exec(jail, argv, 0));
+
+       // Success
+       r = EXIT_SUCCESS;
+
+FAIL:
+       if (jail)
+               pakfire_jail_unref(jail);
+
+       return r;
+}
+
+static int callback_stdin(struct pakfire_ctx* ctx, struct pakfire_jail* pakfire, void* data, int fd) {
+       int* lines = (int*)data;
+       int r;
+
+       while (*lines > 0) {
+               r = dprintf(fd, "LINE %d\n", *lines);
+               if (r < 0) {
+                       switch (errno) {
+                               case EAGAIN:
+                                       return 0;
+
+                               default:
+                                       LOG_ERROR("Could not write line (%u) to stdin: %m\n", *lines);
+                                       return -errno;
+                       }
+               }
+
+               // Decrement the lines counter
+               (*lines)--;
+       }
+
+       return EOF;
+}
+
+static int test_communicate(const struct test* t) {
+       struct pakfire_jail* jail = NULL;
+       int r = EXIT_FAILURE;
+
+       // How many lines to send?
+       int lines = 65535;
+
+       const char* argv[] = {
+               "/command", "pipe", NULL,
+       };
+
+       // Create a new jail
+       ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire));
+
+       pakfire_jail_set_stdin_callback(jail, callback_stdin, &lines);
+
+       // Check if the mount actually works
+       ASSERT_SUCCESS(pakfire_jail_exec(jail, argv, 0));
+
+       // Success
+       r = EXIT_SUCCESS;
+
+FAIL:
+       if (jail)
+               pakfire_jail_unref(jail);
+
+       return r;
+}
+
+static int test_send_one_signal(const struct test* t,
+               struct pakfire_jail* jail, const char* signal) {
+       const char* argv[] = {
+               "/command", "send-signal", signal, NULL,
+       };
+
+       // Perform the command
+       return pakfire_jail_exec(jail, argv, 0);
+}
+
+static int test_send_signal(const struct test* t) {
+       struct pakfire_jail* jail = NULL;
+       int r = EXIT_FAILURE;
+
+       // Create a new jail
+       ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire));
+
+       // Sending SIGTERM to ourselves
+       ASSERT(test_send_one_signal(t, jail, "15") == 0);
+
+       // Sending SIGKILL to ourselves
+       ASSERT(test_send_one_signal(t, jail, "9") == 0);
+
+       // Sending SIGSTOP to ourselves (this should be ignored by the jail)
+       ASSERT(test_send_one_signal(t, jail, "23") == 0);
+
+       // Success
+       r = EXIT_SUCCESS;
+
+FAIL:
+       if (jail)
+               pakfire_jail_unref(jail);
+
+       return r;
+}
+
+static int test_timeout(const struct test* t) {
+       struct pakfire_jail* jail = NULL;
+       int r = EXIT_FAILURE;
+
+       const char* argv[] = {
+               "/command", "sleep", "5", NULL,
+       };
+
+       // Create a new jail
+       ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire));
+
+       // Set a timeout of one second
+       ASSERT_SUCCESS(pakfire_jail_set_timeout(jail, 1));
+
+       // Check if we receive the correct exit code
+       ASSERT(pakfire_jail_exec(jail, argv, 0) == 139);
+
+       // Success
+       r = EXIT_SUCCESS;
+
+FAIL:
+       if (jail)
+               pakfire_jail_unref(jail);
+
+       return r;
+}
+
 int main(int argc, const char* argv[]) {
-       testsuite_add_test(test_create);
-       testsuite_add_test(test_env);
-       testsuite_add_test(test_exec);
-       testsuite_add_test(test_launch_into_cgroup);
-       testsuite_add_test(test_nice);
-       testsuite_add_test(test_memory_limit);
-       testsuite_add_test(test_pid_limit);
-       testsuite_add_test(test_file_ownership);
+       testsuite_add_test(test_create, TEST_WANTS_PAKFIRE);
+       testsuite_add_test(test_exit_code, TEST_WANTS_PAKFIRE);
+       testsuite_add_test(test_segv, TEST_WANTS_PAKFIRE);
+       testsuite_add_test(test_env, TEST_WANTS_PAKFIRE);
+       testsuite_add_test(test_exec, TEST_WANTS_PAKFIRE);
+       testsuite_add_test(test_launch_into_cgroup, TEST_WANTS_PAKFIRE);
+       testsuite_add_test(test_nice, TEST_WANTS_PAKFIRE);
+       testsuite_add_test(test_memory_limit, TEST_WANTS_PAKFIRE);
+       testsuite_add_test(test_pid_limit, TEST_WANTS_PAKFIRE);
+#if 0
+       testsuite_add_test(test_file_ownership, TEST_WANTS_PAKFIRE);
+#endif
+       testsuite_add_test(test_bind, TEST_WANTS_PAKFIRE);
+       testsuite_add_test(test_communicate, TEST_WANTS_PAKFIRE);
+       testsuite_add_test(test_send_signal, TEST_WANTS_PAKFIRE);
+       testsuite_add_test(test_timeout, TEST_WANTS_PAKFIRE);
 
        return testsuite_run(argc, argv);
 }