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,
28 TEST_CREATE_CAN_FAIL = 1 << 2,
34 int (*func)(struct kdbus_test_env *env);
38 struct kdbus_test_args {
52 char *mask_param_path;
55 static const struct kdbus_test tests[] = {
58 .desc = "bus make functions",
59 .func = kdbus_test_bus_make,
64 .desc = "the HELLO command",
65 .func = kdbus_test_hello,
66 .flags = TEST_CREATE_BUS,
70 .desc = "the BYEBYE command",
71 .func = kdbus_test_byebye,
72 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
76 .desc = "a chat pattern",
77 .func = kdbus_test_chat,
78 .flags = TEST_CREATE_BUS,
82 .desc = "a simple daemon",
83 .func = kdbus_test_daemon,
84 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
88 .desc = "file descriptor passing",
89 .func = kdbus_test_fd_passing,
90 .flags = TEST_CREATE_BUS,
94 .desc = "custom endpoint",
95 .func = kdbus_test_custom_endpoint,
96 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
100 .desc = "monitor functionality",
101 .func = kdbus_test_monitor,
102 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
105 .name = "name-basics",
106 .desc = "basic name registry functions",
107 .func = kdbus_test_name_basic,
108 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
111 .name = "name-conflict",
112 .desc = "name registry conflict details",
113 .func = kdbus_test_name_conflict,
114 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
117 .name = "name-queue",
118 .desc = "queuing of names",
119 .func = kdbus_test_name_queue,
120 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
123 .name = "message-basic",
124 .desc = "basic message handling",
125 .func = kdbus_test_message_basic,
126 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
129 .name = "message-prio",
130 .desc = "handling of messages with priority",
131 .func = kdbus_test_message_prio,
132 .flags = TEST_CREATE_BUS,
135 .name = "message-quota",
136 .desc = "message quotas are enforced",
137 .func = kdbus_test_message_quota,
138 .flags = TEST_CREATE_BUS,
141 .name = "memory-access",
142 .desc = "memory access",
143 .func = kdbus_test_memory_access,
144 .flags = TEST_CREATE_BUS,
149 .func = kdbus_test_timeout,
150 .flags = TEST_CREATE_BUS,
155 .func = kdbus_test_send,
156 .flags = TEST_CREATE_CONN | TEST_CREATE_CAN_FAIL,
159 .name = "sync-byebye",
160 .desc = "synchronous replies vs. BYEBYE",
161 .func = kdbus_test_sync_byebye,
162 .flags = TEST_CREATE_BUS,
165 .name = "sync-reply",
166 .desc = "synchronous replies",
167 .func = kdbus_test_sync_reply,
168 .flags = TEST_CREATE_BUS,
171 .name = "message-free",
172 .desc = "freeing of memory",
173 .func = kdbus_test_free,
174 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
177 .name = "connection-info",
178 .desc = "retrieving connection information",
179 .func = kdbus_test_conn_info,
180 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
183 .name = "connection-update",
184 .desc = "updating connection information",
185 .func = kdbus_test_conn_update,
186 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
189 .name = "writable-pool",
190 .desc = "verifying pools are never writable",
191 .func = kdbus_test_writable_pool,
192 .flags = TEST_CREATE_BUS,
197 .func = kdbus_test_policy,
198 .flags = TEST_CREATE_BUS,
201 .name = "policy-priv",
202 .desc = "unprivileged bus access",
203 .func = kdbus_test_policy_priv,
204 .flags = TEST_CREATE_BUS,
208 .desc = "policy in user namespaces",
209 .func = kdbus_test_policy_ns,
210 .flags = TEST_CREATE_BUS,
213 .name = "metadata-ns",
214 .desc = "metadata in different namespaces",
215 .func = kdbus_test_metadata_ns,
216 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
219 .name = "match-id-add",
220 .desc = "adding of matches by id",
221 .func = kdbus_test_match_id_add,
222 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
225 .name = "match-id-remove",
226 .desc = "removing of matches by id",
227 .func = kdbus_test_match_id_remove,
228 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
231 .name = "match-replace",
232 .desc = "replace of matches with the same cookie",
233 .func = kdbus_test_match_replace,
234 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
237 .name = "match-name-add",
238 .desc = "adding of matches by name",
239 .func = kdbus_test_match_name_add,
240 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
243 .name = "match-name-remove",
244 .desc = "removing of matches by name",
245 .func = kdbus_test_match_name_remove,
246 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
249 .name = "match-name-change",
250 .desc = "matching for name changes",
251 .func = kdbus_test_match_name_change,
252 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
255 .name = "match-bloom",
256 .desc = "matching with bloom filters",
257 .func = kdbus_test_match_bloom,
258 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
262 .desc = "activator connections",
263 .func = kdbus_test_activator,
264 .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
269 .func = kdbus_test_benchmark,
270 .flags = TEST_CREATE_BUS,
273 .name = "benchmark-nomemfds",
274 .desc = "benchmark without using memfds",
275 .func = kdbus_test_benchmark_nomemfds,
276 .flags = TEST_CREATE_BUS,
279 .name = "benchmark-uds",
280 .desc = "benchmark comparison to UDS",
281 .func = kdbus_test_benchmark_uds,
282 .flags = TEST_CREATE_BUS,
286 .name = "attach-flags",
287 .desc = "attach flags mask",
288 .func = kdbus_test_attach_flags,
293 #define N_TESTS ((int) (sizeof(tests) / sizeof(tests[0])))
295 static int test_prepare_env(const struct kdbus_test *t,
296 const struct kdbus_test_args *args,
297 struct kdbus_test_env *env)
299 if (t->flags & TEST_CREATE_BUS) {
304 asprintf(&s, "%s/control", args->root);
306 env->control_fd = open(s, O_RDWR);
308 ASSERT_RETURN(env->control_fd >= 0);
310 if (!args->busname) {
311 n = unique_name("test-bus");
315 ret = kdbus_create_bus(env->control_fd,
318 _KDBUS_ATTACH_ALL, &s);
320 ASSERT_RETURN((ret == 0) || (t->flags & TEST_CREATE_CAN_FAIL));
322 asprintf(&env->buspath, "%s/%s/bus", args->root, s);
326 if (t->flags & TEST_CREATE_CONN) {
332 if (!args->busname) {
333 n = unique_name("test-bus");
337 ret = kdbus_create_bus(-1,
342 ASSERT_RETURN(ret == 0);
344 asprintf(&env->buspath, "%s/%s/bus", args->root, s);
347 ASSERT_RETURN(env->buspath);
348 env->conn = kdbus_hello(env->buspath, 0, NULL, 0);
349 ASSERT_RETURN(env->conn || (t->flags & TEST_CREATE_CAN_FAIL));
352 env->root = args->root;
353 env->module = args->module;
354 env->mask_param_path = args->mask_param_path;
359 void test_unprepare_env(const struct kdbus_test *t, struct kdbus_test_env *env)
362 kdbus_conn_free(env->conn);
366 if (env->control_fd >= 0) {
367 close(env->control_fd);
368 env->control_fd = -1;
377 static int test_run(const struct kdbus_test *t,
378 const struct kdbus_test_args *kdbus_args,
382 struct kdbus_test_env env = {};
384 ret = test_prepare_env(t, kdbus_args, &env);
389 printf("Sleeping %d seconds before running test ...\n", wait);
394 test_unprepare_env(t, &env);
398 static int test_run_forked(const struct kdbus_test *t,
399 const struct kdbus_test_args *kdbus_args,
408 } else if (pid == 0) {
409 ret = test_run(t, kdbus_args, wait);
413 pid = waitpid(pid, &ret, 0);
416 else if (!WIFEXITED(ret))
419 return WEXITSTATUS(ret);
422 static void print_test_result(int ret)
437 static int start_all_tests(struct kdbus_test_args *kdbus_args)
440 unsigned int fail_cnt = 0;
441 unsigned int skip_cnt = 0;
442 unsigned int ok_cnt = 0;
445 if (kdbus_args->tap_output) {
446 printf("1..%d\n", N_TESTS);
450 kdbus_util_verbose = false;
452 for (i = 0; i < N_TESTS; i++) {
453 const struct kdbus_test *t = tests + i;
455 if (!kdbus_args->tap_output) {
458 printf("Testing %s (%s) ", t->desc, t->name);
459 for (n = 0; n < 60 - strlen(t->desc) - strlen(t->name); n++)
464 ret = test_run_forked(t, kdbus_args, 0);
477 if (kdbus_args->tap_output) {
478 printf("%sok %d - %s%s (%s)\n",
479 (ret == TEST_ERR) ? "not " : "", i + 1,
480 (ret == TEST_SKIP) ? "# SKIP " : "",
484 print_test_result(ret);
489 if (kdbus_args->tap_output)
490 printf("Failed %d/%d tests, %.2f%% okay\n", fail_cnt, N_TESTS,
491 100.0 - (fail_cnt * 100.0) / ((float) N_TESTS));
493 printf("\nSUMMARY: %u tests passed, %u skipped, %u failed\n",
494 ok_cnt, skip_cnt, fail_cnt);
496 return fail_cnt > 0 ? TEST_ERR : TEST_OK;
499 static int start_one_test(struct kdbus_test_args *kdbus_args)
502 bool test_found = false;
504 for (i = 0; i < N_TESTS; i++) {
505 const struct kdbus_test *t = tests + i;
507 if (strcmp(t->name, kdbus_args->test))
512 if (kdbus_args->fork)
513 ret = test_run_forked(t, kdbus_args,
516 ret = test_run(t, kdbus_args,
519 printf("Testing %s: ", t->desc);
520 print_test_result(ret);
525 } while (kdbus_args->loop);
531 printf("Unknown test-id '%s'\n", kdbus_args->test);
538 static void usage(const char *argv0)
542 printf("Usage: %s [options]\n"
544 "\t-a, --tap Output test results in TAP format\n"
545 "\t-m, --module <module> Kdbus module name\n"
546 "\t-x, --loop Run in a loop\n"
547 "\t-f, --fork Fork before running a test\n"
548 "\t-h, --help Print this help\n"
549 "\t-r, --root <root> Toplevel of the kdbus hierarchy\n"
550 "\t-t, --test <test-id> Run one specific test only, in verbose mode\n"
551 "\t-b, --bus <busname> Instead of generating a random bus name, take <busname>.\n"
552 "\t-w, --wait <secs> Wait <secs> before actually starting test\n"
553 "\t --mntns New mount namespace\n"
554 "\t --pidns New PID namespace\n"
555 "\t --userns New user namespace\n"
556 "\t --uidmap uid_map UID map for user namespace\n"
557 "\t --gidmap gid_map GID map for user namespace\n"
560 printf("By default, all test are run once, and a summary is printed.\n"
561 "Available tests for --test:\n\n");
563 for (i = 0; i < N_TESTS; i++) {
564 const struct kdbus_test *t = tests + i;
566 printf("\t%s", t->name);
568 for (j = 0; j < 24 - strlen(t->name); j++)
571 printf("Test %s\n", t->desc);
575 printf("Note that some tests may, if run specifically by --test, "
576 "behave differently, and not terminate by themselves.\n");
581 void print_kdbus_test_args(struct kdbus_test_args *args)
583 if (args->userns || args->pidns || args->mntns)
584 printf("# Starting tests in new %s%s%s namespaces%s\n",
585 args->mntns ? "MOUNT " : "",
586 args->pidns ? "PID " : "",
587 args->userns ? "USER " : "",
588 args->mntns ? ", kdbusfs will be remounted" : "");
590 printf("# Starting tests in the same namespaces\n");
593 void print_metadata_support(void)
595 bool no_meta_audit, no_meta_cgroups, no_meta_seclabel;
598 * KDBUS_ATTACH_CGROUP, KDBUS_ATTACH_AUDIT and
599 * KDBUS_ATTACH_SECLABEL
601 no_meta_audit = !config_auditsyscall_is_enabled();
602 no_meta_cgroups = !config_cgroups_is_enabled();
603 no_meta_seclabel = !config_security_is_enabled();
605 if (no_meta_audit | no_meta_cgroups | no_meta_seclabel)
606 printf("# Starting tests without %s%s%s metadata support\n",
607 no_meta_audit ? "AUDIT " : "",
608 no_meta_cgroups ? "CGROUP " : "",
609 no_meta_seclabel ? "SECLABEL " : "");
611 printf("# Starting tests with full metadata support\n");
614 int run_tests(struct kdbus_test_args *kdbus_args)
617 static char control[4096];
619 snprintf(control, sizeof(control), "%s/control", kdbus_args->root);
621 if (access(control, W_OK) < 0) {
622 printf("Unable to locate control node at '%s'.\n",
627 if (kdbus_args->test) {
628 ret = start_one_test(kdbus_args);
631 ret = start_all_tests(kdbus_args);
634 } while (kdbus_args->loop);
640 static void nop_handler(int sig) {}
642 static int test_prepare_mounts(struct kdbus_test_args *kdbus_args)
645 char kdbusfs[64] = {'\0'};
647 snprintf(kdbusfs, sizeof(kdbusfs), "%sfs", kdbus_args->module);
649 /* make current mount slave */
650 ret = mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL);
653 printf("error mount() root: %d (%m)\n", ret);
657 /* Remount procfs since we need it in our tests */
658 if (kdbus_args->pidns) {
659 ret = mount("proc", "/proc", "proc",
660 MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL);
663 printf("error mount() /proc : %d (%m)\n", ret);
668 /* Remount kdbusfs */
669 ret = mount(kdbusfs, kdbus_args->root, kdbusfs,
670 MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL);
673 printf("error mount() %s :%d (%m)\n", kdbusfs, ret);
680 int run_tests_in_namespaces(struct kdbus_test_args *kdbus_args)
686 struct sigaction oldsa;
687 struct sigaction sa = {
688 .sa_handler = nop_handler,
689 .sa_flags = SA_NOCLDSTOP,
692 efd = eventfd(0, EFD_CLOEXEC);
695 printf("eventfd() failed: %d (%m)\n", ret);
699 ret = sigaction(SIGCHLD, &sa, &oldsa);
702 printf("sigaction() failed: %d (%m)\n", ret);
706 /* setup namespaces */
707 pid = syscall(__NR_clone, SIGCHLD|
708 (kdbus_args->userns ? CLONE_NEWUSER : 0) |
709 (kdbus_args->mntns ? CLONE_NEWNS : 0) |
710 (kdbus_args->pidns ? CLONE_NEWPID : 0), NULL);
712 printf("clone() failed: %d (%m)\n", -errno);
717 eventfd_t event_status = 0;
719 ret = prctl(PR_SET_PDEATHSIG, SIGKILL);
722 printf("error prctl(): %d (%m)\n", ret);
726 /* reset sighandlers of childs */
727 ret = sigaction(SIGCHLD, &oldsa, NULL);
730 printf("sigaction() failed: %d (%m)\n", ret);
734 ret = eventfd_read(efd, &event_status);
735 if (ret < 0 || event_status != 1) {
736 printf("error eventfd_read()\n");
740 if (kdbus_args->mntns) {
741 ret = test_prepare_mounts(kdbus_args);
743 printf("error preparing mounts\n");
748 ret = run_tests(kdbus_args);
752 /* Setup userns mapping */
753 if (kdbus_args->userns) {
754 ret = userns_map_uid_gid(pid, kdbus_args->uid_map,
755 kdbus_args->gid_map);
757 printf("error mapping uid and gid in userns\n");
758 eventfd_write(efd, 2);
763 ret = eventfd_write(efd, 1);
766 printf("error eventfd_write(): %d (%m)\n", ret);
770 rpid = waitpid(pid, &status, 0);
771 ASSERT_RETURN_VAL(rpid == pid, TEST_ERR);
775 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
781 int start_tests(struct kdbus_test_args *kdbus_args)
785 uint64_t kdbus_param_mask;
786 static char fspath[4096], parampath[4096];
788 namespaces = (kdbus_args->mntns || kdbus_args->pidns ||
791 /* for pidns we need mntns set */
792 if (kdbus_args->pidns && !kdbus_args->mntns) {
793 printf("Failed: please set both pid and mnt namesapces\n");
797 if (kdbus_args->userns) {
798 if (!config_user_ns_is_enabled()) {
799 printf("User namespace not supported\n");
803 if (!kdbus_args->uid_map || !kdbus_args->gid_map) {
804 printf("Failed: please specify uid or gid mapping\n");
809 print_kdbus_test_args(kdbus_args);
810 print_metadata_support();
812 /* setup kdbus paths */
813 if (!kdbus_args->module)
814 kdbus_args->module = "kdbus";
816 if (!kdbus_args->root) {
817 snprintf(fspath, sizeof(fspath), "/sys/fs/%s",
819 kdbus_args->root = fspath;
822 snprintf(parampath, sizeof(parampath),
823 "/sys/module/%s/parameters/attach_flags_mask",
825 kdbus_args->mask_param_path = parampath;
827 ret = kdbus_sysfs_get_parameter_mask(kdbus_args->mask_param_path,
832 printf("# Starting tests with an attach_flags_mask=0x%llx\n",
833 (unsigned long long)kdbus_param_mask);
837 ret = run_tests_in_namespaces(kdbus_args);
839 ret = run_tests(kdbus_args);
844 int main(int argc, char *argv[])
847 struct kdbus_test_args *kdbus_args;
855 char *exec = basename(argv[0]);
857 kdbus_args = malloc(sizeof(*kdbus_args));
859 printf("unable to malloc() kdbus_args\n");
863 memset(kdbus_args, 0, sizeof(*kdbus_args));
865 static const struct option options[] = {
866 { "loop", no_argument, NULL, 'x' },
867 { "help", no_argument, NULL, 'h' },
868 { "root", required_argument, NULL, 'r' },
869 { "test", required_argument, NULL, 't' },
870 { "bus", required_argument, NULL, 'b' },
871 { "wait", required_argument, NULL, 'w' },
872 { "fork", no_argument, NULL, 'f' },
873 { "module", required_argument, NULL, 'm' },
874 { "tap", no_argument, NULL, 'a' },
875 { "mntns", no_argument, NULL, ARG_MNTNS },
876 { "pidns", no_argument, NULL, ARG_PIDNS },
877 { "userns", no_argument, NULL, ARG_USERNS },
878 { "uidmap", required_argument, NULL, ARG_UIDMAP },
879 { "gidmap", required_argument, NULL, ARG_GIDMAP },
885 if (strcmp(exec, "kdbus-test") != 0) {
886 kdbus_args->test = exec;
889 while ((t = getopt_long(argc, argv, "hxfm:r:t:b:w:a", options, NULL)) >= 0) {
892 kdbus_args->loop = 1;
896 kdbus_args->module = optarg;
900 kdbus_args->root = optarg;
904 kdbus_args->test = optarg;
908 kdbus_args->busname = optarg;
912 kdbus_args->wait = strtol(optarg, NULL, 10);
916 kdbus_args->fork = 1;
920 kdbus_args->tap_output = 1;
924 kdbus_args->mntns = true;
928 kdbus_args->pidns = true;
932 kdbus_args->userns = true;
936 kdbus_args->uid_map = optarg;
940 kdbus_args->gid_map = optarg;
949 ret = start_tests(kdbus_args);