14 #include <sys/mount.h>
15 #include <sys/prctl.h>
17 #include <sys/syscall.h>
18 #include <sys/eventfd.h>
19 #include <linux/sched.h>
21 #include "kdbus-util.h"
22 #include "kdbus-enum.h"
23 #include "kdbus-test.h"
26 TEST_CREATE_BUS = 1 << 0,
27 TEST_CREATE_CONN = 1 << 1,
33 int (*func)(struct kdbus_test_env *env);
38 struct kdbus_test_args {
50 char const * const *tests;
56 pthread_mutex_t global_print_lock = PTHREAD_MUTEX_INITIALIZER;
58 static const struct kdbus_test tests[] = {
61 .desc = "bus make functions",
62 .func = kdbus_test_bus_make,
68 .desc = "the HELLO command",
69 .func = kdbus_test_hello,
70 .flags = TEST_CREATE_BUS,
75 .desc = "the BYEBYE command",
76 .func = kdbus_test_byebye,
77 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
82 .desc = "a chat pattern",
83 .func = kdbus_test_chat,
84 .flags = TEST_CREATE_BUS,
89 .desc = "a simple daemon",
90 .func = kdbus_test_daemon,
91 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
96 .desc = "file descriptor passing",
97 .func = kdbus_test_fd_passing,
98 .flags = TEST_CREATE_BUS,
103 .desc = "custom endpoint",
104 .func = kdbus_test_custom_endpoint,
105 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
110 .desc = "monitor functionality",
111 .func = kdbus_test_monitor,
112 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
116 .name = "name-basics",
117 .desc = "basic name registry functions",
118 .func = kdbus_test_name_basic,
119 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
123 .name = "name-conflict",
124 .desc = "name registry conflict details",
125 .func = kdbus_test_name_conflict,
126 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
130 .name = "name-queue",
131 .desc = "queuing of names",
132 .func = kdbus_test_name_queue,
133 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
137 .name = "name-takeover",
138 .desc = "takeover of names",
139 .func = kdbus_test_name_takeover,
140 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
144 .name = "message-basic",
145 .desc = "basic message handling",
146 .func = kdbus_test_message_basic,
147 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
151 .name = "message-prio",
152 .desc = "handling of messages with priority",
153 .func = kdbus_test_message_prio,
154 .flags = TEST_CREATE_BUS,
158 .name = "activator-quota",
159 .desc = "activator message quotas are enforced",
160 .func = kdbus_test_activator_quota,
161 .flags = TEST_CREATE_BUS,
165 .name = "message-quota",
166 .desc = "message quotas are enforced",
167 .func = kdbus_test_message_quota,
168 .flags = TEST_CREATE_BUS,
172 .name = "memory-access",
173 .desc = "memory access",
174 .func = kdbus_test_memory_access,
175 .flags = TEST_CREATE_BUS,
181 .func = kdbus_test_timeout,
182 .flags = TEST_CREATE_BUS,
186 .name = "sync-byebye",
187 .desc = "synchronous replies vs. BYEBYE",
188 .func = kdbus_test_sync_byebye,
189 .flags = TEST_CREATE_BUS,
193 .name = "sync-reply",
194 .desc = "synchronous replies",
195 .func = kdbus_test_sync_reply,
196 .flags = TEST_CREATE_BUS,
201 .desc = "big metadata",
202 .func = kdbus_test_big_metadata,
203 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
207 .name = "message-free",
208 .desc = "freeing of memory",
209 .func = kdbus_test_free,
210 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
214 .name = "connection-info",
215 .desc = "retrieving connection information",
216 .func = kdbus_test_conn_info,
217 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
221 .name = "connection-update",
222 .desc = "updating connection information",
223 .func = kdbus_test_conn_update,
224 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
228 .name = "writable-pool",
229 .desc = "verifying pools are never writable",
230 .func = kdbus_test_writable_pool,
231 .flags = TEST_CREATE_BUS,
237 .func = kdbus_test_policy,
238 .flags = TEST_CREATE_BUS,
242 .name = "policy-priv",
243 .desc = "unprivileged bus access",
244 .func = kdbus_test_policy_priv,
245 .flags = TEST_CREATE_BUS,
250 .desc = "policy in user namespaces",
251 .func = kdbus_test_policy_ns,
252 .flags = TEST_CREATE_BUS,
258 .func = kdbus_test_metadata,
259 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
263 .name = "metadata-conn-info",
264 .desc = "metadata in connection-info",
265 .func = kdbus_test_metadata_conn_info,
266 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
270 .name = "metadata-ns",
271 .desc = "metadata in different namespaces",
272 .func = kdbus_test_metadata_ns,
273 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
277 .name = "match-id-add",
278 .desc = "adding of matches by id",
279 .func = kdbus_test_match_id_add,
280 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
284 .name = "match-id-remove",
285 .desc = "removing of matches by id",
286 .func = kdbus_test_match_id_remove,
287 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
291 .name = "match-replace",
292 .desc = "replace of matches with the same cookie",
293 .func = kdbus_test_match_replace,
294 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
298 .name = "match-name-add",
299 .desc = "adding of matches by name",
300 .func = kdbus_test_match_name_add,
301 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
305 .name = "match-name-remove",
306 .desc = "removing of matches by name",
307 .func = kdbus_test_match_name_remove,
308 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
312 .name = "match-name-change",
313 .desc = "matching for name changes",
314 .func = kdbus_test_match_name_change,
315 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
319 .name = "match-bloom",
320 .desc = "matching with bloom filters",
321 .func = kdbus_test_match_bloom,
322 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
327 .desc = "itemless catch-all matching",
328 .func = kdbus_test_match_itemless,
329 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
334 .desc = "activator connections",
335 .func = kdbus_test_activator,
336 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
342 .func = kdbus_test_benchmark,
343 .flags = TEST_CREATE_BUS,
347 .name = "benchmark-nomemfds",
348 .desc = "benchmark without using memfds",
349 .func = kdbus_test_benchmark_nomemfds,
350 .flags = TEST_CREATE_BUS,
354 .name = "benchmark-uds",
355 .desc = "benchmark comparison to UDS",
356 .func = kdbus_test_benchmark_uds,
357 .flags = TEST_CREATE_BUS,
362 #define N_TESTS ((int) (sizeof(tests) / sizeof(tests[0])))
364 static wur int test_prepare_env(const struct kdbus_test *t,
365 const struct kdbus_test_args *args,
366 struct kdbus_test_env *env)
368 if (t->flags & TEST_CREATE_BUS) {
373 if (0 >= asprintf(&s, "%s/control", args->root))
376 env->control_fd = open(s, O_RDWR);
378 ASSERT_RETURN(env->control_fd,>=,0);
381 ASSERT_NONZERO(n = unique_name("test-bus"));
383 ret = kdbus_create_bus(env->control_fd,
385 _KDBUS_ATTACH_ALL, &s);
389 if (0 >= asprintf(&env->buspath, "%s/%s/bus", args->root, s))
394 if (t->flags & TEST_CREATE_CONN)
395 ASSERT_NONZERO(env->conn = kdbus_hello(env->buspath, 0, NULL, 0));
397 env->root = args->root;
398 env->module = args->module;
403 static void test_unprepare_env(struct kdbus_test_env *env)
406 kdbus_conn_free(env->conn);
410 if (env->control_fd >= 0) {
411 CLOSE(env->control_fd);
412 env->control_fd = -1;
421 static wur int test_run(const struct kdbus_test *t,
422 const struct kdbus_test_args *kdbus_args,
426 struct kdbus_test_env env = {};
428 ret = test_prepare_env(t, kdbus_args, &env);
433 print("Sleeping %d seconds before running test ...\n", wait);
438 test_unprepare_env(&env);
442 static wur int test_run_forked(const struct kdbus_test *t,
443 const struct kdbus_test_args *kdbus_args,
447 pid_t pid, timer_pid = 0;
452 } else if (pid == 0) {
453 ret = test_run(t, kdbus_args, _wait);
457 if (!kdbus_args->no_timeout) {
461 } else if (timer_pid == 0) {
469 pid_t wpid = wait(&ret);
474 result = !WIFEXITED(ret) || WEXITSTATUS(ret) ? TEST_ERR + (timer_pid==wpid) : TEST_OK;
475 if (kdbus_args->no_timeout)
477 kill(wpid ^ pid ^ timer_pid, SIGKILL);
483 static void print_test_result(int ret)
498 static void print_res(struct kdbus_test const *t, int ret) {
499 printf("%s;%s\n", t->name, !ret ? "PASS" : TEST_TIME==ret ? "FAIL;TIMEOUT" : "FAIL");
502 static wur int start_all_tests(struct kdbus_test_args const *kdbus_args)
505 unsigned int fail_cnt = 0;
506 unsigned int skip_cnt = 0;
507 unsigned int ok_cnt = 0;
510 if (kdbus_args->tap_output) {
511 print("1..%d\n", N_TESTS);
515 kdbus_util_verbose = false;
517 for (i = 0; i < N_TESTS; i++) {
518 const struct kdbus_test *t = tests + i;
520 if (!kdbus_args->tap_output) {
523 print("Testing %s (%s) ", t->desc, t->name);
524 for (n = 0; n < 60 - strlen(t->desc) - strlen(t->name); n++)
529 ret = test_run_forked(t, kdbus_args, 0);
543 if (kdbus_args->tap_output) {
544 print("%sok %d - %s%s (%s)\n",
545 (ret >= TEST_ERR) ? "not " : "", i + 1,
546 (ret == TEST_SKIP) ? "# SKIP " : "",
550 print_test_result(ret);
556 if (kdbus_args->tap_output)
557 print("Failed %d/%d tests, %.2f%% okay\n", fail_cnt, N_TESTS,
558 100.0 - (fail_cnt * 100.0) / ((float) N_TESTS));
560 print("\nSUMMARY: %u tests passed, %u skipped, %u failed\n",
561 ok_cnt, skip_cnt, fail_cnt);
563 return fail_cnt > 0 ? TEST_ERR : TEST_OK;
566 static wur int start_some_tests(struct kdbus_test_args const *kdbus_args)
568 int i, ret = TEST_ERR;
569 bool test_found = false;
570 unsigned j=0, nTests = kdbus_args->nTests;
573 char const *tName = kdbus_args->tests[j];
574 for (i = 0; i < N_TESTS; i++) {
575 const struct kdbus_test *t = tests + i;
577 if (strcmp(t->name, tName))
582 if (kdbus_args->fork)
583 ret = test_run_forked(t, kdbus_args,
586 ret = test_run(t, kdbus_args,
589 print("Testing %s: ", t->desc);
590 print_test_result(ret);
596 } while (kdbus_args->loop);
600 print("%s;UNKNOWN\n", tName);
602 } while (++j < nTests);
607 static void usage(const char *argv0)
611 print("Usage: %s [options]\n"
613 "\t-a, --tap Output test results in TAP format\n"
614 "\t-m, --module <module> Kdbus module name\n"
615 "\t-x, --loop Run in a loop\n"
616 "\t-f, --fork Fork before running a test\n"
617 "\t-h, --help Print this help\n"
618 "\t-R, --root <root> Toplevel of the kdbus hierarchy\n"
619 "\t-t, --test <test-id> Run one specific test only, in verbose mode\n"
620 "\t-b, --bus <busname> Instead of generating a random bus name, take <busname>.\n"
621 "\t-w, --wait <secs> Wait <secs> before actually starting test\n"
622 "\t --mntns New mount namespace\n"
623 "\t --pidns New PID namespace\n"
624 "\t --userns New user namespace\n"
625 "\t --uidmap uid_map UID map for user namespace\n"
626 "\t --gidmap gid_map GID map for user namespace\n"
629 print("By default, all test are run once, and a summary is printed.\n"
630 "Available tests for --test:\n\n");
632 for (i = 0; i < N_TESTS; i++) {
633 const struct kdbus_test *t = tests + i;
635 print("\t%s", t->name);
637 for (j = 0; j < 24 - strlen(t->name); j++)
640 print("Test %s\n", t->desc);
644 print("Note that some tests may, if run specifically by --test, "
645 "behave differently, and not terminate by themselves.\n");
650 void print_kdbus_test_args(struct kdbus_test_args const *args)
652 if (args->userns || args->pidns || args->mntns)
653 print("# Starting tests in new %s%s%s namespaces%s\n",
654 args->mntns ? "MOUNT " : "",
655 args->pidns ? "PID " : "",
656 args->userns ? "USER " : "",
657 args->mntns ? ", kdbusfs will be remounted" : "");
659 print("# Starting tests in the same namespaces\n");
662 void print_metadata_support(void)
664 bool no_meta_audit, no_meta_cgroups, no_meta_seclabel;
667 * KDBUS_ATTACH_CGROUP, KDBUS_ATTACH_AUDIT and
668 * KDBUS_ATTACH_SECLABEL
670 no_meta_audit = !config_auditsyscall_is_enabled();
671 no_meta_cgroups = !config_cgroups_is_enabled();
672 no_meta_seclabel = !config_security_is_enabled();
674 if (no_meta_audit | no_meta_cgroups | no_meta_seclabel)
675 print("# Starting tests without %s%s%s metadata support\n",
676 no_meta_audit ? "AUDIT " : "",
677 no_meta_cgroups ? "CGROUP " : "",
678 no_meta_seclabel ? "SECLABEL " : "");
680 print("# Starting tests with full metadata support\n");
683 wur int run_tests(struct kdbus_test_args const *kdbus_args)
686 static char control[4096];
688 snprintf(control, sizeof(control), "%s/control", kdbus_args->root);
690 if (access(control, W_OK) < 0) {
691 print("Unable to locate control node at '%s'.\n",
696 if (kdbus_args->nTests) {
697 ret = start_some_tests(kdbus_args);
700 ret = start_all_tests(kdbus_args);
703 } while (kdbus_args->loop);
709 static void nop_handler(int sig) { UNUSED(sig); }
711 static wur int test_prepare_mounts(struct kdbus_test_args const *kdbus_args)
714 char kdbusfs[64] = {'\0'};
716 snprintf(kdbusfs, sizeof(kdbusfs), "%sfs", kdbus_args->module);
718 /* make current mount slave */
719 ret = mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL);
722 print("error mount() root: %d (%m)\n", ret);
726 /* Remount procfs since we need it in our tests */
727 if (kdbus_args->pidns) {
728 ret = mount("proc", "/proc", "proc",
729 MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL);
732 print("error mount() /proc : %d (%m)\n", ret);
737 /* Remount kdbusfs */
738 ret = mount(kdbusfs, kdbus_args->root, kdbusfs,
739 MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL);
742 print("error mount() %s :%d (%m)\n", kdbusfs, ret);
749 wur int run_tests_in_namespaces(struct kdbus_test_args const *kdbus_args)
755 struct sigaction oldsa;
756 struct sigaction sa = {
757 .sa_handler = nop_handler,
758 .sa_flags = SA_NOCLDSTOP,
761 efd = eventfd(0, EFD_CLOEXEC);
764 print("eventfd() failed: %d (%m)\n", ret);
768 ret = sigaction(SIGCHLD, &sa, &oldsa);
771 print("sigaction() failed: %d (%m)\n", ret);
775 /* setup namespaces */
776 pid = syscall(__NR_clone, SIGCHLD|
777 (kdbus_args->userns ? CLONE_NEWUSER : 0) |
778 (kdbus_args->mntns ? CLONE_NEWNS : 0) |
779 (kdbus_args->pidns ? CLONE_NEWPID : 0), NULL);
781 print("clone() failed: %d (%m)\n", -errno);
786 eventfd_t event_status = 0;
788 ret = prctl(PR_SET_PDEATHSIG, SIGKILL);
791 print("error prctl(): %d (%m)\n", ret);
795 /* reset sighandlers of childs */
796 ret = sigaction(SIGCHLD, &oldsa, NULL);
799 print("sigaction() failed: %d (%m)\n", ret);
803 ret = eventfd_read(efd, &event_status);
804 if (ret < 0 || event_status != 1) {
805 print("error eventfd_read()\n");
809 if (kdbus_args->mntns) {
810 ret = test_prepare_mounts(kdbus_args);
812 print("error preparing mounts\n");
817 ret = run_tests(kdbus_args);
821 /* Setup userns mapping */
822 if (kdbus_args->userns) {
823 ret = userns_map_uid_gid(pid, kdbus_args->uid_map,
824 kdbus_args->gid_map);
826 print("error mapping uid and gid in userns\n");
827 eventfd_write(efd, 2);
832 ret = eventfd_write(efd, 1);
835 print("error eventfd_write(): %d (%m)\n", ret);
839 rpid = waitpid(pid, &status, 0);
840 ASSERT_RETURN_VAL(rpid,==,pid, TEST_ERR);
844 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
850 wur int start_tests(struct kdbus_test_args const *kdbus_args)
855 namespaces = (kdbus_args->mntns || kdbus_args->pidns ||
858 /* for pidns we need mntns set */
859 if (kdbus_args->pidns && !kdbus_args->mntns) {
860 print("Failed: please set both pid and mnt namesapces\n");
864 if (kdbus_args->userns) {
865 if (!config_user_ns_is_enabled()) {
866 print("User namespace not supported\n");
870 if (!kdbus_args->uid_map || !kdbus_args->gid_map) {
871 print("Failed: please specify uid or gid mapping\n");
876 print_kdbus_test_args(kdbus_args);
877 print_metadata_support();
881 ret = run_tests_in_namespaces(kdbus_args);
883 ret = run_tests(kdbus_args);
888 wur int main(int argc, char *argv[])
891 struct kdbus_test_args kdbus_args;
892 static char fspath[4096];
901 memset(&kdbus_args, 0, sizeof(kdbus_args));
902 kdbus_args.module = "kdbus";
904 static const struct option options[] = {
905 { "loop", no_argument, NULL, 'x' },
906 { "help", no_argument, NULL, 'h' },
907 { "root", required_argument, NULL, 'R' },
908 { "test", no_argument, NULL, 't' },
909 { "bus", required_argument, NULL, 'b' },
910 { "wait", required_argument, NULL, 'w' },
911 { "fork", no_argument, NULL, 'f' },
912 { "list", no_argument, NULL, 'l' },
913 { "module", required_argument, NULL, 'm' },
914 { "tap", no_argument, NULL, 'a' },
915 { "notimeout", no_argument, NULL, 'n' },
916 { "mntns", no_argument, NULL, ARG_MNTNS },
917 { "pidns", no_argument, NULL, ARG_PIDNS },
918 { "userns", no_argument, NULL, ARG_USERNS },
919 { "uidmap", required_argument, NULL, ARG_UIDMAP },
920 { "gidmap", required_argument, NULL, ARG_GIDMAP },
928 while ((t = getopt_long(argc, argv, "xhtflnm:R:b:w:a:", options, NULL)) >= 0) {
935 kdbus_args.module = optarg;
939 kdbus_args.root = optarg;
947 kdbus_args.busname = optarg;
951 kdbus_args.wait = strtol(optarg, NULL, 10);
959 kdbus_args.tap_output = 1;
963 kdbus_args.no_timeout = 1;
970 const struct kdbus_test *t = &tests[i];
971 printf("%s;%s\n", t->name, t->desc);
972 } while (++i < TABSIZE(tests)-1);
977 kdbus_args.mntns = true;
981 kdbus_args.pidns = true;
985 kdbus_args.userns = true;
989 kdbus_args.uid_map = optarg;
993 kdbus_args.gid_map = optarg;
1003 if ((kdbus_args.nTests = argc-optind)) {
1004 kdbus_args.tests = (char const * const *)&argv[optind];
1005 if (1 < kdbus_args.nTests || !gotT)
1006 kdbus_args.fork = 1;
1009 if (!kdbus_args.root) {
1010 snprintf(fspath, sizeof(fspath), "/sys/fs/%s",
1012 kdbus_args.root = fspath;
1015 ret = start_tests(&kdbus_args);
1016 if (ret == TEST_ERR)
1017 return EXIT_FAILURE;