2 * Test metadata and policies in new namespaces. Even if our tests
3 * can run in a namespaced setup, this test is necessary so we can
4 * inspect policies on the same kdbusfs but between multiple
7 * Copyright (C) 2014-2015 Djalal Harouni
9 * kdbus is free software; you can redistribute it and/or modify it under
10 * the terms of the GNU Lesser General Public License as published by the
11 * Free Software Foundation; either version 2.1 of the License, or (at
12 * your option) any later version.
28 #include <sys/prctl.h>
29 #include <sys/eventfd.h>
30 #include <sys/syscall.h>
31 #include <sys/capability.h>
32 #include <linux/sched.h>
34 #include "kdbus-test.h"
35 #include "kdbus-util.h"
36 #include "kdbus-enum.h"
39 #define POLICY_NAME "foo.test.policy-test"
41 #define KDBUS_CONN_MAX_MSGS_PER_USER 16
44 * Note: this test can be used to inspect policy_db->talk_access_hash
46 * The purpose of these tests:
47 * 1) Check KDBUS_POLICY_TALK
48 * 2) Check the cache state: kdbus_policy_db->talk_access_hash
53 * Check a list of connections against conn_db[0]
54 * conn_db[0] will own the name "foo.test.policy-test" and the
55 * policy holder connection for this name will update the policy
56 * entries, so different use cases can be tested.
58 static struct kdbus_conn **conn_db;
60 static void *kdbus_recv_echo(void *ptr)
63 struct kdbus_conn *conn = ptr;
65 ret = kdbus_msg_recv_poll(conn, 200, NULL, NULL);
67 return (void *)(long)ret;
70 /* Trigger kdbus_policy_set() */
71 static int kdbus_set_policy_talk(struct kdbus_conn *conn,
73 uid_t id, unsigned int type)
76 struct kdbus_policy_access access = {
79 .access = KDBUS_POLICY_TALK,
82 ret = kdbus_conn_update_policy(conn, name, &access, 1);
83 ASSERT_RETURN(ret == 0);
88 /* return TEST_OK or TEST_ERR on failure */
89 static int kdbus_register_same_activator(char *bus, const char *name,
90 struct kdbus_conn **c)
93 struct kdbus_conn *activator;
95 activator = kdbus_hello_activator(bus, name, NULL, 0);
98 fprintf(stderr, "--- error was able to register name twice '%s'.\n",
104 /* -EEXIST means test succeeded */
111 /* return TEST_OK or TEST_ERR on failure */
112 static int kdbus_register_policy_holder(char *bus, const char *name,
113 struct kdbus_conn **conn)
115 struct kdbus_conn *c;
116 struct kdbus_policy_access access[2];
118 access[0].type = KDBUS_POLICY_ACCESS_USER;
119 access[0].access = KDBUS_POLICY_OWN;
120 access[0].id = geteuid();
122 access[1].type = KDBUS_POLICY_ACCESS_WORLD;
123 access[1].access = KDBUS_POLICY_TALK;
124 access[1].id = geteuid();
126 c = kdbus_hello_registrar(bus, name, access, 2,
127 KDBUS_HELLO_POLICY_HOLDER);
136 * Create new threads for receiving from multiple senders,
137 * The 'conn_db' will be populated by newly created connections.
138 * Caller should free all allocated connections.
140 * return 0 on success, negative errno on failure.
142 static int kdbus_recv_in_threads(const char *bus, const char *name,
143 struct kdbus_conn **conn_db)
146 bool pool_full = false;
147 unsigned int sent_packets = 0;
148 unsigned int lost_packets = 0;
150 unsigned long dst_id;
151 unsigned long cookie = 1;
152 unsigned int thread_nr = MAX_CONN - 1;
153 pthread_t thread_id[MAX_CONN - 1] = {'\0'};
155 dst_id = name ? KDBUS_DST_ID_NAME : conn_db[0]->id;
157 for (tid = 0, i = 1; tid < thread_nr; tid++, i++) {
158 ret = pthread_create(&thread_id[tid], NULL,
159 kdbus_recv_echo, (void *)conn_db[0]);
162 kdbus_printf("error pthread_create: %d (%m)\n",
167 /* just free before re-using */
168 kdbus_conn_free(conn_db[i]);
171 /* We need to create connections here */
172 conn_db[i] = kdbus_hello(bus, 0, NULL, 0);
178 ret = kdbus_add_match_empty(conn_db[i]);
182 ret = kdbus_msg_send(conn_db[i], name, cookie++,
183 0, 0, 0, dst_id, 0, NULL);
186 * Receivers are not reading their messages,
189 * So set the pool full here, perhaps the
190 * connection pool or queue was full, later
191 * recheck receivers errors
193 if (ret == -ENOBUFS || ret == -EXFULL)
201 for (tid = 0; tid < thread_nr; tid++) {
204 if (thread_id[tid]) {
205 pthread_join(thread_id[tid], (void *)&thread_ret);
206 if (thread_ret < 0) {
207 /* Update only if send did not fail */
217 * When sending if we did fail with -ENOBUFS or -EXFULL
218 * then we should have set lost_packet and we should at
219 * least have sent_packets set to KDBUS_CONN_MAX_MSGS_PER_USER
222 ASSERT_RETURN(lost_packets > 0);
225 * We should at least send KDBUS_CONN_MAX_MSGS_PER_USER
227 * For every send operation we create a thread to
228 * recv the packet, so we keep the queue clean
230 ASSERT_RETURN(sent_packets >= KDBUS_CONN_MAX_MSGS_PER_USER);
233 * Set ret to zero since we only failed due to
234 * the receiving threads that have not been
243 /* Return: TEST_OK or TEST_ERR on failure */
244 static int kdbus_normal_test(const char *bus, const char *name,
245 struct kdbus_conn **conn_db)
249 ret = kdbus_recv_in_threads(bus, name, conn_db);
250 ASSERT_RETURN(ret >= 0);
255 static int kdbus_fork_test_by_id(const char *bus,
256 struct kdbus_conn **conn_db,
257 int parent_status, int child_status)
261 uint64_t cookie = 0x9876ecba;
262 struct kdbus_msg *msg = NULL;
267 * If the child_status is not EXIT_SUCCESS, then we expect
268 * that sending from the child will fail, thus receiving
269 * from parent must error with -ETIMEDOUT, and vice versa.
271 bool parent_timedout = !!child_status;
272 bool child_timedout = !!parent_status;
275 ASSERT_RETURN_VAL(pid >= 0, pid);
278 struct kdbus_conn *conn_src;
280 ret = prctl(PR_SET_PDEATHSIG, SIGKILL);
281 ASSERT_EXIT(ret == 0);
283 ret = drop_privileges(65534, 65534);
284 ASSERT_EXIT(ret == 0);
286 conn_src = kdbus_hello(bus, 0, NULL, 0);
287 ASSERT_EXIT(conn_src);
289 ret = kdbus_add_match_empty(conn_src);
290 ASSERT_EXIT(ret == 0);
293 * child_status is always checked against send
294 * operations, in case it fails always return
297 ret = kdbus_msg_send(conn_src, NULL, cookie,
298 0, 0, 0, conn_db[0]->id, 0, NULL);
299 ASSERT_EXIT(ret == child_status);
301 ret = kdbus_msg_recv_poll(conn_src, 100, NULL, NULL);
303 kdbus_conn_free(conn_src);
306 * Child kdbus_msg_recv_poll() should timeout since
307 * the parent_status was set to a non EXIT_SUCCESS
311 _exit(ret == -ETIMEDOUT ? EXIT_SUCCESS : EXIT_FAILURE);
313 _exit(ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
316 ret = kdbus_msg_recv_poll(conn_db[0], 100, &msg, &offset);
318 * If parent_timedout is set then this should fail with
319 * -ETIMEDOUT since the child_status was set to a non
320 * EXIT_SUCCESS value. Otherwise, assume
321 * that kdbus_msg_recv_poll() has succeeded.
323 if (parent_timedout) {
324 ASSERT_RETURN_VAL(ret == -ETIMEDOUT, TEST_ERR);
326 /* timedout no need to continue, we don't have the
327 * child connection ID, so just terminate. */
330 ASSERT_RETURN_VAL(ret == 0, ret);
333 ret = kdbus_msg_send(conn_db[0], NULL, ++cookie,
334 0, 0, 0, msg->src_id, 0, NULL);
336 * parent_status is checked against send operations,
337 * on failures always return TEST_ERR.
339 ASSERT_RETURN_VAL(ret == parent_status, TEST_ERR);
342 kdbus_free(conn_db[0], offset);
345 ret = waitpid(pid, &status, 0);
346 ASSERT_RETURN_VAL(ret >= 0, ret);
348 return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR;
352 * Return: TEST_OK, TEST_ERR or TEST_SKIP
353 * we return TEST_OK only if the children return with the expected
354 * 'expected_status' that is specified as an argument.
356 static int kdbus_fork_test(const char *bus, const char *name,
357 struct kdbus_conn **conn_db, int expected_status)
364 ASSERT_RETURN_VAL(pid >= 0, pid);
367 ret = prctl(PR_SET_PDEATHSIG, SIGKILL);
368 ASSERT_EXIT(ret == 0);
370 ret = drop_privileges(65534, 65534);
371 ASSERT_EXIT(ret == 0);
373 ret = kdbus_recv_in_threads(bus, name, conn_db);
374 _exit(ret == expected_status ? EXIT_SUCCESS : EXIT_FAILURE);
377 ret = waitpid(pid, &status, 0);
378 ASSERT_RETURN(ret >= 0);
380 return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR;
383 /* Return EXIT_SUCCESS, EXIT_FAILURE or negative errno */
384 static int __kdbus_clone_userns_test(const char *bus,
386 struct kdbus_conn **conn_db,
392 unsigned int uid = 65534;
395 ret = drop_privileges(uid, uid);
396 ASSERT_RETURN_VAL(ret == 0, ret);
399 * Since we just dropped privileges, the dumpable flag was just
400 * cleared which makes the /proc/$clone_child/uid_map to be
401 * owned by root, hence any userns uid mapping will fail with
402 * -EPERM since the mapping will be done by uid 65534.
404 * To avoid this set the dumpable flag again which makes procfs
405 * update the /proc/$clone_child/ inodes owner to 65534.
407 * Using this we will be able write to /proc/$clone_child/uid_map
408 * as uid 65534 and map the uid 65534 to 0 inside the user
411 ret = prctl(PR_SET_DUMPABLE, SUID_DUMP_USER);
412 ASSERT_RETURN_VAL(ret == 0, ret);
414 /* sync parent/child */
415 efd = eventfd(0, EFD_CLOEXEC);
416 ASSERT_RETURN_VAL(efd >= 0, efd);
418 pid = syscall(__NR_clone, SIGCHLD|CLONE_NEWUSER, NULL);
421 kdbus_printf("error clone: %d (%m)\n", ret);
423 * Normal user not allowed to create userns,
424 * so nothing to worry about ?
427 kdbus_printf("-- CLONE_NEWUSER TEST Failed for uid: %u\n"
428 "-- Make sure that your kernel do not allow "
429 "CLONE_NEWUSER for unprivileged users\n"
430 "-- Upstream Commit: "
431 "https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=5eaf563e\n",
440 struct kdbus_conn *conn_src;
441 eventfd_t event_status = 0;
443 ret = prctl(PR_SET_PDEATHSIG, SIGKILL);
444 ASSERT_EXIT(ret == 0);
446 ret = eventfd_read(efd, &event_status);
447 ASSERT_EXIT(ret >= 0 && event_status == 1);
449 /* ping connection from the new user namespace */
450 conn_src = kdbus_hello(bus, 0, NULL, 0);
451 ASSERT_EXIT(conn_src);
453 ret = kdbus_add_match_empty(conn_src);
454 ASSERT_EXIT(ret == 0);
456 ret = kdbus_msg_send(conn_src, name, 0xabcd1234,
457 0, 0, 0, KDBUS_DST_ID_NAME, 0, NULL);
458 kdbus_conn_free(conn_src);
460 _exit(ret == expected_status ? EXIT_SUCCESS : EXIT_FAILURE);
463 ret = userns_map_uid_gid(pid, "0 65534 1", "0 65534 1");
464 ASSERT_RETURN_VAL(ret == 0, ret);
466 /* Tell child we are ready */
467 ret = eventfd_write(efd, 1);
468 ASSERT_RETURN_VAL(ret == 0, ret);
470 ret = waitpid(pid, &status, 0);
471 ASSERT_RETURN_VAL(ret >= 0, ret);
475 return status == EXIT_SUCCESS ? TEST_OK : TEST_ERR;
478 static int kdbus_clone_userns_test(const char *bus,
480 struct kdbus_conn **conn_db,
488 ASSERT_RETURN_VAL(pid >= 0, -errno);
491 ret = prctl(PR_SET_PDEATHSIG, SIGKILL);
495 ret = __kdbus_clone_userns_test(bus, name, conn_db,
501 * Receive in the original (root privileged) user namespace,
502 * must fail with -ETIMEDOUT.
504 ret = kdbus_msg_recv_poll(conn_db[0], 100, NULL, NULL);
505 ASSERT_RETURN_VAL(ret == -ETIMEDOUT, ret);
507 ret = waitpid(pid, &status, 0);
508 ASSERT_RETURN_VAL(ret >= 0, ret);
510 return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR;
513 int kdbus_test_policy_ns(struct kdbus_test_env *env)
517 struct kdbus_conn *activator = NULL;
518 struct kdbus_conn *policy_holder = NULL;
519 char *bus = env->buspath;
521 ret = test_is_capable(CAP_SETUID, CAP_SETGID, -1);
522 ASSERT_RETURN(ret >= 0);
524 /* no enough privileges, SKIP test */
528 /* we require user-namespaces */
529 if (access("/proc/self/uid_map", F_OK) != 0)
532 /* uids/gids must be mapped */
533 if (!all_uids_gids_are_mapped())
536 conn_db = calloc(MAX_CONN, sizeof(struct kdbus_conn *));
537 ASSERT_RETURN(conn_db);
539 memset(conn_db, 0, MAX_CONN * sizeof(struct kdbus_conn *));
541 conn_db[0] = kdbus_hello(bus, 0, NULL, 0);
542 ASSERT_RETURN(conn_db[0]);
544 ret = kdbus_add_match_empty(conn_db[0]);
545 ASSERT_RETURN(ret == 0);
547 ret = kdbus_fork_test_by_id(bus, conn_db, -EPERM, -EPERM);
548 ASSERT_EXIT(ret == 0);
550 ret = kdbus_register_policy_holder(bus, POLICY_NAME,
552 ASSERT_RETURN(ret == 0);
554 /* Try to register the same name with an activator */
555 ret = kdbus_register_same_activator(bus, POLICY_NAME,
557 ASSERT_RETURN(ret == 0);
559 /* Acquire POLICY_NAME */
560 ret = kdbus_name_acquire(conn_db[0], POLICY_NAME, NULL);
561 ASSERT_RETURN(ret == 0);
563 ret = kdbus_normal_test(bus, POLICY_NAME, conn_db);
564 ASSERT_RETURN(ret == 0);
566 ret = kdbus_list(conn_db[0], KDBUS_LIST_NAMES |
568 KDBUS_LIST_ACTIVATORS |
570 ASSERT_RETURN(ret == 0);
572 ret = kdbus_fork_test(bus, POLICY_NAME, conn_db, EXIT_SUCCESS);
573 ASSERT_RETURN(ret == 0);
576 * children connections are able to talk to conn_db[0] since
577 * current POLICY_NAME TALK type is KDBUS_POLICY_ACCESS_WORLD,
578 * so expect EXIT_SUCCESS when sending from child. However,
579 * since the child's connection does not own any well-known
580 * name, The parent connection conn_db[0] should fail with
581 * -EPERM but since it is a privileged bus user the TALK is
584 ret = kdbus_fork_test_by_id(bus, conn_db,
585 EXIT_SUCCESS, EXIT_SUCCESS);
586 ASSERT_EXIT(ret == 0);
589 * Connections that can talk are perhaps being destroyed now.
590 * Restrict the policy and purge cache entries where the
591 * conn_db[0] is the destination.
593 * Now only connections with uid == 0 are allowed to talk.
595 ret = kdbus_set_policy_talk(policy_holder, POLICY_NAME,
596 geteuid(), KDBUS_POLICY_ACCESS_USER);
597 ASSERT_RETURN(ret == 0);
600 * Testing connections (FORK+DROP) again:
601 * After setting the policy re-check connections
602 * we expect the children to fail with -EPERM
604 ret = kdbus_fork_test(bus, POLICY_NAME, conn_db, -EPERM);
605 ASSERT_RETURN(ret == 0);
608 * Now expect that both parent and child to fail.
610 * Child should fail with -EPERM since we just restricted
611 * the POLICY_NAME TALK to uid 0 and its uid is 65534.
613 * Since the parent's connection will timeout when receiving
614 * from the child, we never continue. FWIW just put -EPERM.
616 ret = kdbus_fork_test_by_id(bus, conn_db, -EPERM, -EPERM);
617 ASSERT_EXIT(ret == 0);
619 /* Check if the name can be reached in a new userns */
620 ret = kdbus_clone_userns_test(bus, POLICY_NAME, conn_db, -EPERM);
621 ASSERT_RETURN(ret == 0);
623 for (i = 0; i < MAX_CONN; i++)
624 kdbus_conn_free(conn_db[i]);
626 kdbus_conn_free(activator);
627 kdbus_conn_free(policy_holder);