コード例 #1
0
ファイル: test-message.c プロジェクト: archetipo/kdbus
static int kdbus_test_broadcast_quota(struct kdbus_test_env *env)
{
	int ret;
	uint64_t offset;
	unsigned int i;
	struct kdbus_msg *msg;
	struct kdbus_conn *privileged_a;
	struct kdbus_conn *privileged_b;
	struct kdbus_conn *holder;
	struct kdbus_policy_access access = {
		.type = KDBUS_POLICY_ACCESS_WORLD,
		.id = getuid(),
		.access = KDBUS_POLICY_TALK,
	};
	uint64_t expected_cookie = time(NULL) ^ 0xdeadbeef;

	holder = kdbus_hello_registrar(env->buspath, "com.example.a",
				       &access, 1,
				       KDBUS_HELLO_POLICY_HOLDER);
	ASSERT_RETURN(holder);

	privileged_a = kdbus_hello(env->buspath, 0, NULL, 0);
	ASSERT_RETURN(privileged_a);

	privileged_b = kdbus_hello(env->buspath, 0, NULL, 0);
	ASSERT_RETURN(privileged_b);

	/* Acquire name with access world so they can talk to us */
	ret = kdbus_name_acquire(privileged_a, "com.example.a", NULL);
	ASSERT_RETURN(ret >= 0);

	/* Broadcast matches for privileged connections */
	ret = kdbus_add_match_empty(privileged_a);
	ASSERT_RETURN(ret == 0);

	ret = kdbus_add_match_empty(privileged_b);
	ASSERT_RETURN(ret == 0);

	/*
	 * We start accouting after KDBUS_CONN_MAX_MSGS_UNACCOUNTED
	 * so the first sender will at least send
	 * KDBUS_CONN_MAX_MSGS_UNACCOUNTED + KDBUS_CONN_MAX_MSGS_PER_USER
	 */
	ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
		unsigned int cnt;

		cnt = kdbus_fill_conn_queue(unpriv, KDBUS_DST_ID_BROADCAST,
					    MAX_USER_TOTAL_MSGS);
		ASSERT_EXIT(cnt == MAX_USER_TOTAL_MSGS);

		/*
		 * Another message that will trigger the lost count
		 *
		 * Broadcasts always succeed
		 */
		ret = kdbus_msg_send(unpriv, NULL, 0xdeadbeef, 0, 0,
				     0, KDBUS_DST_ID_BROADCAST);
		ASSERT_EXIT(ret == 0);
	}));
コード例 #2
0
ファイル: test-message.c プロジェクト: archetipo/kdbus
int kdbus_test_message_basic(struct kdbus_test_env *env)
{
	struct kdbus_conn *conn;
	struct kdbus_conn *sender;
	struct kdbus_msg *msg;
	uint64_t cookie = 0x1234abcd5678eeff;
	uint64_t offset;
	int ret;

	sender = kdbus_hello(env->buspath, 0, NULL, 0);
	ASSERT_RETURN(sender != NULL);

	/* create a 2nd connection */
	conn = kdbus_hello(env->buspath, 0, NULL, 0);
	ASSERT_RETURN(conn != NULL);

	ret = kdbus_add_match_empty(conn);
	ASSERT_RETURN(ret == 0);

	ret = kdbus_add_match_empty(sender);
	ASSERT_RETURN(ret == 0);

	/* send over 1st connection */
	ret = kdbus_msg_send(sender, NULL, cookie, 0, 0, 0,
			     KDBUS_DST_ID_BROADCAST);
	ASSERT_RETURN(ret == 0);

	/* Make sure that we do not get our own broadcasts */
	ret = kdbus_msg_recv(sender, NULL, NULL);
	ASSERT_RETURN(ret == -EAGAIN);

	/* ... and receive on the 2nd */
	ret = kdbus_msg_recv_poll(conn, 100, &msg, &offset);
	ASSERT_RETURN(ret == 0);
	ASSERT_RETURN(msg->cookie == cookie);

	kdbus_msg_free(msg);

	ret = kdbus_free(conn, offset);
	ASSERT_RETURN(ret == 0);

	kdbus_conn_free(sender);
	kdbus_conn_free(conn);

	return TEST_OK;
}
コード例 #3
0
ファイル: test-connection.c プロジェクト: amigadave/kdbus
int kdbus_test_byebye(struct kdbus_test_env *env)
{
	struct kdbus_conn *conn;
	struct kdbus_cmd_recv recv = {};
	int ret;

	/* create a 2nd connection */
	conn = kdbus_hello(env->buspath, 0, NULL, 0);
	ASSERT_RETURN(conn != NULL);

	ret = kdbus_add_match_empty(conn);
	ASSERT_RETURN(ret == 0);

	ret = kdbus_add_match_empty(env->conn);
	ASSERT_RETURN(ret == 0);

	/* send over 1st connection */
	ret = kdbus_msg_send(env->conn, NULL, 0, 0, 0, 0,
			     KDBUS_DST_ID_BROADCAST);
	ASSERT_RETURN(ret == 0);

	/* say byebye on the 2nd, which must fail */
	ret = ioctl(conn->fd, KDBUS_CMD_BYEBYE, 0);
	ASSERT_RETURN(ret == -1 && errno == EBUSY);

	/* receive the message */
	ret = ioctl(conn->fd, KDBUS_CMD_MSG_RECV, &recv);
	ASSERT_RETURN(ret == 0);

	ret = kdbus_free(conn, recv.offset);
	ASSERT_RETURN(ret == 0);

	/* and try again */
	ret = ioctl(conn->fd, KDBUS_CMD_BYEBYE, 0);
	ASSERT_RETURN(ret == 0);

	/* a 2nd try should result in -EALREADY */
	ret = ioctl(conn->fd, KDBUS_CMD_BYEBYE, 0);
	ASSERT_RETURN(ret == -1 && errno == EOPNOTSUPP);

	kdbus_conn_free(conn);

	return TEST_OK;
}
コード例 #4
0
ファイル: test-policy-ns.c プロジェクト: 8l/kdbus
/**
 * Create new threads for receiving from multiple senders,
 * The 'conn_db' will be populated by newly created connections.
 * Caller should free all allocated connections.
 *
 * return 0 on success, negative errno on failure.
 */
static int kdbus_recv_in_threads(const char *bus, const char *name,
				 struct kdbus_conn **conn_db)
{
	int ret;
	unsigned int i, tid;
	unsigned long dst_id;
	unsigned long cookie = 1;
	unsigned int thread_nr = MAX_CONN - 1;
	pthread_t thread_id[MAX_CONN - 1] = {'\0'};

	dst_id = name ? KDBUS_DST_ID_NAME : conn_db[0]->id;

	for (tid = 0, i = 1; tid < thread_nr; tid++, i++) {
		ret = pthread_create(&thread_id[tid], NULL,
				     kdbus_recv_echo, (void *)conn_db[0]);
		if (ret < 0) {
			ret = -errno;
			kdbus_printf("error pthread_create: %d err %d (%m)\n",
				      ret, errno);
			break;
		}

		/* just free before re-using */
		kdbus_conn_free(conn_db[i]);
		conn_db[i] = NULL;

		/* We need to create connections here */
		conn_db[i] = kdbus_hello(bus, 0, NULL, 0);
		if (!conn_db[i]) {
			ret = -errno;
			break;
		}

		ret = kdbus_add_match_empty(conn_db[i]);
		if (ret < 0)
			break;

		ret = kdbus_msg_send(conn_db[i], name, cookie++,
				     0, 0, 0, dst_id);
		if (ret < 0)
			break;
	}

	for (tid = 0; tid < thread_nr; tid++) {
		int thread_ret = 0;

		if (thread_id[tid]) {
			pthread_join(thread_id[tid], (void *)&thread_ret);
			if (thread_ret < 0 && ret == 0)
				ret = thread_ret;
		}
	}

	return ret;
}
コード例 #5
0
ファイル: test-metadata-ns.c プロジェクト: D-os/kdbus
static int __kdbus_clone_userns_test(const char *bus,
				     struct kdbus_conn *conn,
				     uint64_t grandpa_pid,
				     int signal_fd)
{
	int clone_ret;
	int ret;
	struct kdbus_msg *msg = NULL;
	const struct kdbus_item *item;
	uint64_t cookie = time(NULL) ^ 0xdeadbeef;
	struct kdbus_conn *unpriv_conn = NULL;
	struct kdbus_pids parent_pids = {
		.pid = getppid(),
		.tid = getppid(),
		.ppid = grandpa_pid,
	};

	ret = drop_privileges(UNPRIV_UID, UNPRIV_GID);
	ASSERT_EXIT(ret == 0);

	unpriv_conn = kdbus_hello(bus, 0, NULL, 0);
	ASSERT_EXIT(unpriv_conn);

	ret = kdbus_add_match_empty(unpriv_conn);
	ASSERT_EXIT(ret == 0);

	/*
	 * ping privileged connection from this new unprivileged
	 * one
	 */

	ret = kdbus_msg_send(unpriv_conn, NULL, cookie, 0, 0,
			     0, conn->id);
	ASSERT_EXIT(ret == 0);

	/*
	 * Since we just dropped privileges, the dumpable flag
	 * was just cleared which makes the /proc/$clone_child/uid_map
	 * to be owned by root, hence any userns uid mapping will fail
	 * with -EPERM since the mapping will be done by uid 65534.
	 *
	 * To avoid this set the dumpable flag again which makes
	 * procfs update the /proc/$clone_child/ inodes owner to 65534.
	 *
	 * Using this we will be able write to /proc/$clone_child/uid_map
	 * as uid 65534 and map the uid 65534 to 0 inside the user namespace.
	 */
	ret = prctl(PR_SET_DUMPABLE, SUID_DUMP_USER);
	ASSERT_EXIT(ret == 0);

	/* Make child privileged in its new userns and run tests */

	ret = RUN_CLONE_CHILD(&clone_ret,
			      SIGCHLD | CLONE_NEWUSER | CLONE_NEWPID,
	({ 0;  /* Clone setup, nothing */ }),
コード例 #6
0
ファイル: test-policy-ns.c プロジェクト: adhideguchi/kdbus
int kdbus_test_policy_ns(struct kdbus_test_env *env)
{
	int i;
	int ret;
	struct kdbus_conn *activator = NULL;
	struct kdbus_conn *policy_holder = NULL;
	char *bus = env->buspath;

	ret = test_is_capable(CAP_SETUID, CAP_SETGID, -1);
	ASSERT_RETURN(ret >= 0);

	/* no enough privileges, SKIP test */
	if (!ret)
		return TEST_SKIP;

	/* we require user-namespaces */
	if (access("/proc/self/uid_map", F_OK) != 0)
		return TEST_SKIP;

	/* uids/gids must be mapped */
	if (!all_uids_gids_are_mapped())
		return TEST_SKIP;

	conn_db = calloc(MAX_CONN, sizeof(struct kdbus_conn *));
	ASSERT_RETURN(conn_db);

	memset(conn_db, 0, MAX_CONN * sizeof(struct kdbus_conn *));

	conn_db[0] = kdbus_hello(bus, 0, NULL, 0);
	ASSERT_RETURN(conn_db[0]);

	ret = kdbus_add_match_empty(conn_db[0]);
	ASSERT_RETURN(ret == 0);

	ret = kdbus_fork_test_by_id(bus, conn_db, -EPERM, -EPERM);
	ASSERT_EXIT(ret == 0);

	ret = kdbus_register_policy_holder(bus, POLICY_NAME,
					   &policy_holder);
	ASSERT_RETURN(ret == 0);

	/* Try to register the same name with an activator */
	ret = kdbus_register_same_activator(bus, POLICY_NAME,
					    &activator);
	ASSERT_RETURN(ret == 0);

	/* Acquire POLICY_NAME */
	ret = kdbus_name_acquire(conn_db[0], POLICY_NAME, NULL);
	ASSERT_RETURN(ret == 0);

	ret = kdbus_normal_test(bus, POLICY_NAME, conn_db);
	ASSERT_RETURN(ret == 0);

	ret = kdbus_list(conn_db[0], KDBUS_LIST_NAMES |
				     KDBUS_LIST_UNIQUE |
				     KDBUS_LIST_ACTIVATORS |
				     KDBUS_LIST_QUEUED);
	ASSERT_RETURN(ret == 0);

	ret = kdbus_fork_test(bus, POLICY_NAME, conn_db, EXIT_SUCCESS);
	ASSERT_RETURN(ret == 0);

	/*
	 * children connections are able to talk to conn_db[0] since
	 * current POLICY_NAME TALK type is KDBUS_POLICY_ACCESS_WORLD,
	 * so expect EXIT_SUCCESS when sending from child. However,
	 * since the child's connection does not own any well-known
	 * name, The parent connection conn_db[0] should fail with
	 * -EPERM but since it is a privileged bus user the TALK is
	 *  allowed.
	 */
	ret = kdbus_fork_test_by_id(bus, conn_db,
				    EXIT_SUCCESS, EXIT_SUCCESS);
	ASSERT_EXIT(ret == 0);

	/*
	 * Connections that can talk are perhaps being destroyed now.
	 * Restrict the policy and purge cache entries where the
	 * conn_db[0] is the destination.
	 *
	 * Now only connections with uid == 0 are allowed to talk.
	 */
	ret = kdbus_set_policy_talk(policy_holder, POLICY_NAME,
				    geteuid(), KDBUS_POLICY_ACCESS_USER);
	ASSERT_RETURN(ret == 0);

	/*
	 * Testing connections (FORK+DROP) again:
	 * After setting the policy re-check connections
	 * we expect the children to fail with -EPERM
	 */
	ret = kdbus_fork_test(bus, POLICY_NAME, conn_db, -EPERM);
	ASSERT_RETURN(ret == 0);

	/*
	 * Now expect that both parent and child to fail.
	 *
	 * Child should fail with -EPERM since we just restricted
	 * the POLICY_NAME TALK to uid 0 and its uid is 65534.
	 *
	 * Since the parent's connection will timeout when receiving
	 * from the child, we never continue. FWIW just put -EPERM.
	 */
	ret = kdbus_fork_test_by_id(bus, conn_db, -EPERM, -EPERM);
	ASSERT_EXIT(ret == 0);

	/* Check if the name can be reached in a new userns */
	ret = kdbus_clone_userns_test(bus, POLICY_NAME, conn_db, -EPERM);
	ASSERT_RETURN(ret == 0);

	for (i = 0; i < MAX_CONN; i++)
		kdbus_conn_free(conn_db[i]);

	kdbus_conn_free(activator);
	kdbus_conn_free(policy_holder);

	free(conn_db);

	return ret;
}
コード例 #7
0
ファイル: test-policy-ns.c プロジェクト: adhideguchi/kdbus
/* Return EXIT_SUCCESS, EXIT_FAILURE or negative errno */
static int __kdbus_clone_userns_test(const char *bus,
				     const char *name,
				     struct kdbus_conn **conn_db,
				     int expected_status)
{
	int efd;
	pid_t pid;
	int ret = 0;
	unsigned int uid = 65534;
	int status;

	ret = drop_privileges(uid, uid);
	ASSERT_RETURN_VAL(ret == 0, ret);

	/*
	 * Since we just dropped privileges, the dumpable flag was just
	 * cleared which makes the /proc/$clone_child/uid_map to be
	 * owned by root, hence any userns uid mapping will fail with
	 * -EPERM since the mapping will be done by uid 65534.
	 *
	 * To avoid this set the dumpable flag again which makes procfs
	 * update the /proc/$clone_child/ inodes owner to 65534.
	 *
	 * Using this we will be able write to /proc/$clone_child/uid_map
	 * as uid 65534 and map the uid 65534 to 0 inside the user
	 * namespace.
	 */
	ret = prctl(PR_SET_DUMPABLE, SUID_DUMP_USER);
	ASSERT_RETURN_VAL(ret == 0, ret);

	/* sync parent/child */
	efd = eventfd(0, EFD_CLOEXEC);
	ASSERT_RETURN_VAL(efd >= 0, efd);

	pid = syscall(__NR_clone, SIGCHLD|CLONE_NEWUSER, NULL);
	if (pid < 0) {
		ret = -errno;
		kdbus_printf("error clone: %d (%m)\n", ret);
		/*
		 * Normal user not allowed to create userns,
		 * so nothing to worry about ?
		 */
		if (ret == -EPERM) {
			kdbus_printf("-- CLONE_NEWUSER TEST Failed for uid: %u\n"
				"-- Make sure that your kernel do not allow "
				"CLONE_NEWUSER for unprivileged users\n"
				"-- Upstream Commit: "
				"https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=5eaf563e\n",
				uid);
			ret = 0;
		}

		return ret;
	}

	if (pid == 0) {
		struct kdbus_conn *conn_src;
		eventfd_t event_status = 0;

		ret = prctl(PR_SET_PDEATHSIG, SIGKILL);
		ASSERT_EXIT(ret == 0);

		ret = eventfd_read(efd, &event_status);
		ASSERT_EXIT(ret >= 0 && event_status == 1);

		/* ping connection from the new user namespace */
		conn_src = kdbus_hello(bus, 0, NULL, 0);
		ASSERT_EXIT(conn_src);

		ret = kdbus_add_match_empty(conn_src);
		ASSERT_EXIT(ret == 0);

		ret = kdbus_msg_send(conn_src, name, 0xabcd1234,
				     0, 0, 0, KDBUS_DST_ID_NAME);
		kdbus_conn_free(conn_src);

		_exit(ret == expected_status ? EXIT_SUCCESS : EXIT_FAILURE);
	}

	ret = userns_map_uid_gid(pid, "0 65534 1", "0 65534 1");
	ASSERT_RETURN_VAL(ret == 0, ret);

	/* Tell child we are ready */
	ret = eventfd_write(efd, 1);
	ASSERT_RETURN_VAL(ret == 0, ret);

	ret = waitpid(pid, &status, 0);
	ASSERT_RETURN_VAL(ret >= 0, ret);

	close(efd);

	return status == EXIT_SUCCESS ? TEST_OK : TEST_ERR;
}
コード例 #8
0
ファイル: test-policy-ns.c プロジェクト: adhideguchi/kdbus
static int kdbus_fork_test_by_id(const char *bus,
				 struct kdbus_conn **conn_db,
				 int parent_status, int child_status)
{
	int ret;
	pid_t pid;
	uint64_t cookie = 0x9876ecba;
	struct kdbus_msg *msg = NULL;
	uint64_t offset = 0;
	int status = 0;

	/*
	 * If the child_status is not EXIT_SUCCESS, then we expect
	 * that sending from the child will fail, thus receiving
	 * from parent must error with -ETIMEDOUT, and vice versa.
	 */
	bool parent_timedout = !!child_status;
	bool child_timedout = !!parent_status;

	pid = fork();
	ASSERT_RETURN_VAL(pid >= 0, pid);

	if (pid == 0) {
		struct kdbus_conn *conn_src;

		ret = prctl(PR_SET_PDEATHSIG, SIGKILL);
		ASSERT_EXIT(ret == 0);

		ret = drop_privileges(65534, 65534);
		ASSERT_EXIT(ret == 0);

		conn_src = kdbus_hello(bus, 0, NULL, 0);
		ASSERT_EXIT(conn_src);

		ret = kdbus_add_match_empty(conn_src);
		ASSERT_EXIT(ret == 0);

		/*
		 * child_status is always checked against send
		 * operations, in case it fails always return
		 * EXIT_FAILURE.
		 */
		ret = kdbus_msg_send(conn_src, NULL, cookie,
				     0, 0, 0, conn_db[0]->id);
		ASSERT_EXIT(ret == child_status);

		ret = kdbus_msg_recv_poll(conn_src, 100, NULL, NULL);

		kdbus_conn_free(conn_src);

		/*
		 * Child kdbus_msg_recv_poll() should timeout since
		 * the parent_status was set to a non EXIT_SUCCESS
		 * value.
		 */
		if (child_timedout)
			_exit(ret == -ETIMEDOUT ? EXIT_SUCCESS : EXIT_FAILURE);

		_exit(ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
	}

	ret = kdbus_msg_recv_poll(conn_db[0], 100, &msg, &offset);
	/*
	 * If parent_timedout is set then this should fail with
	 * -ETIMEDOUT since the child_status was set to a non
	 * EXIT_SUCCESS value. Otherwise, assume
	 * that kdbus_msg_recv_poll() has succeeded.
	 */
	if (parent_timedout) {
		ASSERT_RETURN_VAL(ret == -ETIMEDOUT, TEST_ERR);

		/* timedout no need to continue, we don't have the
		 * child connection ID, so just terminate. */
		goto out;
	} else {
		ASSERT_RETURN_VAL(ret == 0, ret);
	}

	ret = kdbus_msg_send(conn_db[0], NULL, ++cookie,
			     0, 0, 0, msg->src_id);
	/*
	 * parent_status is checked against send operations,
	 * on failures always return TEST_ERR.
	 */
	ASSERT_RETURN_VAL(ret == parent_status, TEST_ERR);

	kdbus_msg_free(msg);
	kdbus_free(conn_db[0], offset);

out:
	ret = waitpid(pid, &status, 0);
	ASSERT_RETURN_VAL(ret >= 0, ret);

	return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR;
}
コード例 #9
0
ファイル: test-policy-ns.c プロジェクト: adhideguchi/kdbus
/**
 * Create new threads for receiving from multiple senders,
 * The 'conn_db' will be populated by newly created connections.
 * Caller should free all allocated connections.
 *
 * return 0 on success, negative errno on failure.
 */
static int kdbus_recv_in_threads(const char *bus, const char *name,
				 struct kdbus_conn **conn_db)
{
	int ret;
	bool pool_full = false;
	unsigned int sent_packets = 0;
	unsigned int lost_packets = 0;
	unsigned int i, tid;
	unsigned long dst_id;
	unsigned long cookie = 1;
	unsigned int thread_nr = MAX_CONN - 1;
	pthread_t thread_id[MAX_CONN - 1] = {'\0'};

	dst_id = name ? KDBUS_DST_ID_NAME : conn_db[0]->id;

	for (tid = 0, i = 1; tid < thread_nr; tid++, i++) {
		ret = pthread_create(&thread_id[tid], NULL,
				     kdbus_recv_echo, (void *)conn_db[0]);
		if (ret < 0) {
			ret = -errno;
			kdbus_printf("error pthread_create: %d (%m)\n",
				      ret);
			break;
		}

		/* just free before re-using */
		kdbus_conn_free(conn_db[i]);
		conn_db[i] = NULL;

		/* We need to create connections here */
		conn_db[i] = kdbus_hello(bus, 0, NULL, 0);
		if (!conn_db[i]) {
			ret = -errno;
			break;
		}

		ret = kdbus_add_match_empty(conn_db[i]);
		if (ret < 0)
			break;

		ret = kdbus_msg_send(conn_db[i], name, cookie++,
				     0, 0, 0, dst_id);
		if (ret < 0) {
			/*
			 * Receivers are not reading their messages,
			 * not scheduled ?!
			 *
			 * So set the pool full here, perhaps the
			 * connection pool or queue was full, later
			 * recheck receivers errors
			 */
			if (ret == -ENOBUFS || ret == -EXFULL)
				pool_full = true;
			break;
		}

		sent_packets++;
	}

	for (tid = 0; tid < thread_nr; tid++) {
		int thread_ret = 0;

		if (thread_id[tid]) {
			pthread_join(thread_id[tid], (void *)&thread_ret);
			if (thread_ret < 0) {
				/* Update only if send did not fail */
				if (ret == 0)
					ret = thread_ret;

				lost_packets++;
			}
		}
	}

	/*
	 * When sending if we did fail with -ENOBUFS or -EXFULL
	 * then we should have set lost_packet and we should at
	 * least have sent_packets set to KDBUS_CONN_MAX_MSGS_PER_USER
	 */
	if (pool_full) {
		ASSERT_RETURN(lost_packets > 0);

		/*
		 * We should at least send KDBUS_CONN_MAX_MSGS_PER_USER
		 *
		 * For every send operation we create a thread to
		 * recv the packet, so we keep the queue clean
		 */
		ASSERT_RETURN(sent_packets >= KDBUS_CONN_MAX_MSGS_PER_USER);

		/*
		 * Set ret to zero since we only failed due to
		 * the receiving threads that have not been
		 * scheduled
		 */
		ret = 0;
	}

	return ret;
}
コード例 #10
0
ファイル: test-activator.c プロジェクト: squiddle/kdbus
int kdbus_test_activator(struct kdbus_test_env *env)
{
	int ret;
	struct kdbus_conn *activator;
	struct pollfd fds[2];
	bool activator_done = false;
	struct kdbus_policy_access access[2];

	access[0].type = KDBUS_POLICY_ACCESS_USER;
	access[0].id = 1001;
	access[0].access = KDBUS_POLICY_OWN;

	access[1].type = KDBUS_POLICY_ACCESS_WORLD;
	access[1].access = KDBUS_POLICY_TALK;

	activator = kdbus_hello_activator(env->buspath, "foo.test.activator",
					  access, 2);
	ASSERT_RETURN(activator);

	ret = kdbus_add_match_empty(env->conn);
	ASSERT_RETURN(ret == 0);

	ret = kdbus_name_list(env->conn, KDBUS_NAME_LIST_NAMES |
					 KDBUS_NAME_LIST_UNIQUE |
					 KDBUS_NAME_LIST_ACTIVATORS |
					 KDBUS_NAME_LIST_QUEUED);
	ASSERT_RETURN(ret == 0);

	ret = kdbus_msg_send(env->conn, "foo.test.activator", 0xdeafbeef,
			     0, 0, 0, KDBUS_DST_ID_NAME);
	ASSERT_RETURN(ret == 0);

	fds[0].fd = activator->fd;
	fds[1].fd = env->conn->fd;

	kdbus_printf("-- entering poll loop ...\n");

	for (;;) {
		int i, nfds = sizeof(fds) / sizeof(fds[0]);

		for (i = 0; i < nfds; i++) {
			fds[i].events = POLLIN | POLLPRI;
			fds[i].revents = 0;
		}

		ret = poll(fds, nfds, 3000);
		ASSERT_RETURN(ret >= 0);

		ret = kdbus_name_list(env->conn, KDBUS_NAME_LIST_NAMES);
		ASSERT_RETURN(ret == 0);

		if ((fds[0].revents & POLLIN) && !activator_done) {
			kdbus_printf("Starter was called back!\n");

			ret = kdbus_name_acquire(env->conn,
						 "foo.test.activator",
						 KDBUS_NAME_REPLACE_EXISTING);
			ASSERT_RETURN(ret == 0);

			activator_done = true;
		}

		if (fds[1].revents & POLLIN) {
			kdbus_msg_recv(env->conn, NULL);
			break;
		}
	}

	kdbus_conn_free(activator);

	return TEST_OK;
}
コード例 #11
0
ファイル: test-metadata-ns.c プロジェクト: D-os/kdbus
	ASSERT_EXIT(ret == 0);

	/* Make child privileged in its new userns and run tests */

	ret = RUN_CLONE_CHILD(&clone_ret,
			      SIGCHLD | CLONE_NEWUSER | CLONE_NEWPID,
	({ 0;  /* Clone setup, nothing */ }),
	({
		eventfd_t event_status = 0;
		struct kdbus_conn *userns_conn;

		/* ping connection from the new user namespace */
		userns_conn = kdbus_hello(bus, 0, NULL, 0);
		ASSERT_EXIT(userns_conn);

		ret = kdbus_add_match_empty(userns_conn);
		ASSERT_EXIT(ret == 0);

		cookie++;
		ret = kdbus_msg_send(userns_conn, NULL, cookie,
				     0, 0, 0, conn->id);
		ASSERT_EXIT(ret == 0);

		/* Parent did send */
		ret = eventfd_read(signal_fd, &event_status);
		ASSERT_RETURN(ret >= 0 && event_status == 1);

		/*
		 * Receive from privileged connection
		 */
		kdbus_printf("Privileged → unprivileged/privileged "
コード例 #12
0
ファイル: test-sync.c プロジェクト: adhideguchi/kdbus
static int interrupt_sync(struct kdbus_conn *conn_src,
			  struct kdbus_conn *conn_dst)
{
	pid_t pid;
	int ret, status;
	struct kdbus_msg *msg = NULL;
	struct sigaction sa = {
		.sa_handler = nop_handler,
		.sa_flags = SA_NOCLDSTOP|SA_RESTART,
	};

	cookie++;
	pid = fork();
	ASSERT_RETURN_VAL(pid >= 0, pid);

	if (pid == 0) {
		ret = sigaction(SIGINT, &sa, NULL);
		ASSERT_EXIT(ret == 0);

		ret = kdbus_msg_send_sync(conn_dst, NULL, cookie,
					  KDBUS_MSG_EXPECT_REPLY,
					  100000000ULL, 0, conn_src->id, -1);
		ASSERT_EXIT(ret == -ETIMEDOUT);

		_exit(EXIT_SUCCESS);
	}

	ret = kdbus_msg_recv_poll(conn_src, 100, &msg, NULL);
	ASSERT_RETURN(ret == 0 && msg->cookie == cookie);

	kdbus_msg_free(msg);

	ret = kill(pid, SIGINT);
	ASSERT_RETURN_VAL(ret == 0, ret);

	ret = waitpid(pid, &status, 0);
	ASSERT_RETURN_VAL(ret >= 0, ret);

	if (WIFSIGNALED(status))
		return TEST_ERR;

	ret = kdbus_msg_recv_poll(conn_src, 100, NULL, NULL);
	ASSERT_RETURN(ret == -ETIMEDOUT);

	return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR;
}

static int close_epipe_sync(const char *bus)
{
	pid_t pid;
	int ret, status;
	struct kdbus_conn *conn_src;
	struct kdbus_conn *conn_dst;
	struct kdbus_msg *msg = NULL;

	conn_src = kdbus_hello(bus, 0, NULL, 0);
	ASSERT_RETURN(conn_src);

	ret = kdbus_add_match_empty(conn_src);
	ASSERT_RETURN(ret == 0);

	conn_dst = kdbus_hello(bus, 0, NULL, 0);
	ASSERT_RETURN(conn_dst);

	cookie++;
	pid = fork();
	ASSERT_RETURN_VAL(pid >= 0, pid);

	if (pid == 0) {
		uint64_t dst_id;

		/* close our reference */
		dst_id = conn_dst->id;
		kdbus_conn_free(conn_dst);

		ret = kdbus_msg_recv_poll(conn_src, 100, &msg, NULL);
		ASSERT_EXIT(ret == 0 && msg->cookie == cookie);
		ASSERT_EXIT(msg->src_id == dst_id);

		cookie++;
		ret = kdbus_msg_send_sync(conn_src, NULL, cookie,
					  KDBUS_MSG_EXPECT_REPLY,
					  100000000ULL, 0, dst_id, -1);
		ASSERT_EXIT(ret == -EPIPE);

		_exit(EXIT_SUCCESS);
	}

	ret = kdbus_msg_send(conn_dst, NULL, cookie, 0, 0, 0,
			     KDBUS_DST_ID_BROADCAST);
	ASSERT_RETURN(ret == 0);

	cookie++;
	ret = kdbus_msg_recv_poll(conn_dst, 100, &msg, NULL);
	ASSERT_RETURN(ret == 0 && msg->cookie == cookie);

	kdbus_msg_free(msg);

	/* destroy connection */
	kdbus_conn_free(conn_dst);
	kdbus_conn_free(conn_src);

	ret = waitpid(pid, &status, 0);
	ASSERT_RETURN_VAL(ret >= 0, ret);

	if (!WIFEXITED(status))
		return TEST_ERR;

	return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR;
}
コード例 #13
0
ファイル: test-chat.c プロジェクト: adhideguchi/kdbus
int kdbus_test_chat(struct kdbus_test_env *env)
{
	int ret, cookie;
	struct kdbus_conn *conn_a, *conn_b;
	struct pollfd fds[2];
	uint64_t flags;
	int count;

	conn_a = kdbus_hello(env->buspath, 0, NULL, 0);
	conn_b = kdbus_hello(env->buspath, 0, NULL, 0);
	ASSERT_RETURN(conn_a && conn_b);

	flags = KDBUS_NAME_ALLOW_REPLACEMENT;
	ret = kdbus_name_acquire(conn_a, "foo.bar.test", &flags);
	ASSERT_RETURN(ret == 0);

	ret = kdbus_name_acquire(conn_a, "foo.bar.baz", NULL);
	ASSERT_RETURN(ret == 0);

	flags = KDBUS_NAME_QUEUE;
	ret = kdbus_name_acquire(conn_b, "foo.bar.baz", &flags);
	ASSERT_RETURN(ret == 0);

	ret = kdbus_name_acquire(conn_a, "foo.bar.double", NULL);
	ASSERT_RETURN(ret == 0);

	ret = kdbus_name_acquire(conn_a, "foo.bar.double", NULL);
	ASSERT_RETURN(ret == -EALREADY);

	ret = kdbus_name_release(conn_a, "foo.bar.double");
	ASSERT_RETURN(ret == 0);

	ret = kdbus_name_release(conn_a, "foo.bar.double");
	ASSERT_RETURN(ret == -ESRCH);

	ret = kdbus_list(conn_b, KDBUS_LIST_UNIQUE |
				 KDBUS_LIST_NAMES  |
				 KDBUS_LIST_QUEUED |
				 KDBUS_LIST_ACTIVATORS);
	ASSERT_RETURN(ret == 0);

	ret = kdbus_add_match_empty(conn_a);
	ASSERT_RETURN(ret == 0);

	ret = kdbus_add_match_empty(conn_b);
	ASSERT_RETURN(ret == 0);

	cookie = 0;
	ret = kdbus_msg_send(conn_b, NULL, 0xc0000000 | cookie, 0, 0, 0,
			     KDBUS_DST_ID_BROADCAST);
	ASSERT_RETURN(ret == 0);

	fds[0].fd = conn_a->fd;
	fds[1].fd = conn_b->fd;

	kdbus_printf("-- entering poll loop ...\n");

	for (count = 0;; count++) {
		int i, nfds = sizeof(fds) / sizeof(fds[0]);

		for (i = 0; i < nfds; i++) {
			fds[i].events = POLLIN | POLLPRI | POLLHUP;
			fds[i].revents = 0;
		}

		ret = poll(fds, nfds, 3000);
		ASSERT_RETURN(ret >= 0);

		if (fds[0].revents & POLLIN) {
			if (count > 2)
				kdbus_name_release(conn_a, "foo.bar.baz");

			ret = kdbus_msg_recv(conn_a, NULL, NULL);
			ASSERT_RETURN(ret == 0);
			ret = kdbus_msg_send(conn_a, NULL,
					     0xc0000000 | cookie++,
					     0, 0, 0, conn_b->id);
			ASSERT_RETURN(ret == 0);
		}

		if (fds[1].revents & POLLIN) {
			ret = kdbus_msg_recv(conn_b, NULL, NULL);
			ASSERT_RETURN(ret == 0);
			ret = kdbus_msg_send(conn_b, NULL,
					     0xc0000000 | cookie++,
					     0, 0, 0, conn_a->id);
			ASSERT_RETURN(ret == 0);
		}

		ret = kdbus_list(conn_b, KDBUS_LIST_UNIQUE |
					 KDBUS_LIST_NAMES  |
					 KDBUS_LIST_QUEUED |
					 KDBUS_LIST_ACTIVATORS);
		ASSERT_RETURN(ret == 0);

		if (count > 10)
			break;
	}

	kdbus_printf("-- closing bus connections\n");
	kdbus_conn_free(conn_a);
	kdbus_conn_free(conn_b);

	return TEST_OK;
}