12 #include <sys/eventfd.h>
13 #include <sys/types.h>
16 #include "kdbus-api.h"
17 #include "kdbus-util.h"
18 #include "kdbus-enum.h"
19 #include "kdbus-test.h"
21 /* maximum number of queued messages from the same individual user */
22 #define KDBUS_CONN_MAX_MSGS 256
24 /* maximum number of queued requests waiting for a reply */
25 #define KDBUS_CONN_MAX_REQUESTS_PENDING 128
27 /* maximum message payload size */
28 #define KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE (2 * 1024UL * 1024UL)
30 int kdbus_test_message_basic(struct kdbus_test_env *env)
32 struct kdbus_conn *conn;
33 struct kdbus_conn *sender;
34 struct kdbus_msg *msg;
35 uint64_t cookie = 0x1234abcd5678eeff;
39 sender = kdbus_hello(env->buspath, 0, NULL, 0);
40 ASSERT_RETURN(sender != NULL);
42 /* create a 2nd connection */
43 conn = kdbus_hello(env->buspath, 0, NULL, 0);
44 ASSERT_RETURN(conn != NULL);
46 ret = kdbus_add_match_empty(conn);
47 ASSERT_RETURN(ret == 0);
49 ret = kdbus_add_match_empty(sender);
50 ASSERT_RETURN(ret == 0);
52 /* send over 1st connection */
53 ret = kdbus_msg_send(sender, NULL, cookie, 0, 0, 0,
54 KDBUS_DST_ID_BROADCAST, 0, NULL);
55 ASSERT_RETURN(ret == 0);
57 /* Make sure that we do not get our own broadcasts */
58 ret = kdbus_msg_recv(sender, NULL, NULL);
59 ASSERT_RETURN(ret == -EAGAIN);
61 /* ... and receive on the 2nd */
62 ret = kdbus_msg_recv_poll(conn, 100, &msg, &offset);
63 ASSERT_RETURN(ret == 0);
64 ASSERT_RETURN(msg->cookie == cookie);
68 /* Msgs that expect a reply must have timeout and cookie */
69 ret = kdbus_msg_send(sender, NULL, 0, KDBUS_MSG_EXPECT_REPLY,
70 0, 0, conn->id, 0, NULL);
71 ASSERT_RETURN(ret == -EINVAL);
73 /* Faked replies with a valid reply cookie are rejected */
74 ret = kdbus_msg_send_reply(conn, time(NULL) ^ cookie, sender->id);
75 ASSERT_RETURN(ret == -EPERM);
77 ret = kdbus_free(conn, offset);
78 ASSERT_RETURN(ret == 0);
80 kdbus_conn_free(sender);
81 kdbus_conn_free(conn);
86 static int msg_recv_prio(struct kdbus_conn *conn,
87 int64_t requested_prio,
88 int64_t expected_prio)
90 struct kdbus_cmd_recv recv = {
92 .flags = KDBUS_RECV_USE_PRIORITY,
93 .priority = requested_prio,
95 struct kdbus_msg *msg;
98 ret = kdbus_cmd_recv(conn->fd, &recv);
100 kdbus_printf("error receiving message: %d (%m)\n", -errno);
104 msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset);
105 kdbus_msg_dump(conn, msg);
107 if (msg->priority != expected_prio) {
108 kdbus_printf("expected message prio %lld, got %lld\n",
109 (unsigned long long) expected_prio,
110 (unsigned long long) msg->priority);
115 ret = kdbus_free(conn, recv.msg.offset);
122 int kdbus_test_message_prio(struct kdbus_test_env *env)
124 struct kdbus_conn *a, *b;
128 a = kdbus_hello(env->buspath, 0, NULL, 0);
129 b = kdbus_hello(env->buspath, 0, NULL, 0);
130 ASSERT_RETURN(a && b);
132 ret = kdbus_msg_send(b, NULL, ++cookie, 0, 0, 25, a->id, 0, NULL);
133 ASSERT_RETURN(ret == 0);
134 ret = kdbus_msg_send(b, NULL, ++cookie, 0, 0, -600, a->id, 0, NULL);
135 ASSERT_RETURN(ret == 0);
136 ret = kdbus_msg_send(b, NULL, ++cookie, 0, 0, 10, a->id, 0, NULL);
137 ASSERT_RETURN(ret == 0);
138 ret = kdbus_msg_send(b, NULL, ++cookie, 0, 0, -35, a->id, 0, NULL);
139 ASSERT_RETURN(ret == 0);
140 ret = kdbus_msg_send(b, NULL, ++cookie, 0, 0, -100, a->id, 0, NULL);
141 ASSERT_RETURN(ret == 0);
142 ret = kdbus_msg_send(b, NULL, ++cookie, 0, 0, 20, a->id, 0, NULL);
143 ASSERT_RETURN(ret == 0);
144 ret = kdbus_msg_send(b, NULL, ++cookie, 0, 0, -15, a->id, 0, NULL);
145 ASSERT_RETURN(ret == 0);
146 ret = kdbus_msg_send(b, NULL, ++cookie, 0, 0, -800, a->id, 0, NULL);
147 ASSERT_RETURN(ret == 0);
148 ret = kdbus_msg_send(b, NULL, ++cookie, 0, 0, -150, a->id, 0, NULL);
149 ASSERT_RETURN(ret == 0);
150 ret = kdbus_msg_send(b, NULL, ++cookie, 0, 0, 10, a->id, 0, NULL);
151 ASSERT_RETURN(ret == 0);
152 ret = kdbus_msg_send(b, NULL, ++cookie, 0, 0, -800, a->id, 0, NULL);
153 ASSERT_RETURN(ret == 0);
154 ret = kdbus_msg_send(b, NULL, ++cookie, 0, 0, -10, a->id, 0, NULL);
155 ASSERT_RETURN(ret == 0);
157 ASSERT_RETURN(msg_recv_prio(a, -200, -800) == 0);
158 ASSERT_RETURN(msg_recv_prio(a, -100, -800) == 0);
159 ASSERT_RETURN(msg_recv_prio(a, -400, -600) == 0);
160 ASSERT_RETURN(msg_recv_prio(a, -400, -600) == -EAGAIN);
161 ASSERT_RETURN(msg_recv_prio(a, 10, -150) == 0);
162 ASSERT_RETURN(msg_recv_prio(a, 10, -100) == 0);
164 kdbus_printf("--- get priority (all)\n");
165 ASSERT_RETURN(kdbus_msg_recv(a, NULL, NULL) == 0);
173 static int kdbus_test_notify_kernel_quota(struct kdbus_test_env *env)
177 struct kdbus_conn *conn;
178 struct kdbus_conn *reader;
179 struct kdbus_msg *msg = NULL;
180 struct kdbus_cmd_recv recv = { .size = sizeof(recv) };
182 reader = kdbus_hello(env->buspath, 0, NULL, 0);
183 ASSERT_RETURN(reader);
185 conn = kdbus_hello(env->buspath, 0, NULL, 0);
188 /* Register for ID signals */
189 ret = kdbus_add_match_id(reader, 0x1, KDBUS_ITEM_ID_ADD,
191 ASSERT_RETURN(ret == 0);
193 ret = kdbus_add_match_id(reader, 0x2, KDBUS_ITEM_ID_REMOVE,
195 ASSERT_RETURN(ret == 0);
197 /* Each iteration two notifications: add and remove ID */
198 for (i = 0; i < KDBUS_CONN_MAX_MSGS / 2; i++) {
199 struct kdbus_conn *notifier;
201 notifier = kdbus_hello(env->buspath, 0, NULL, 0);
202 ASSERT_RETURN(notifier);
204 kdbus_conn_free(notifier);
208 * Now the reader queue is full with kernel notfications,
209 * but as a user we still have room to push our messages.
211 ret = kdbus_msg_send(conn, NULL, 0xdeadbeef, 0, 0, 0, reader->id,
213 ASSERT_RETURN(ret == 0);
215 /* More ID kernel notifications that will be lost */
216 kdbus_conn_free(conn);
218 conn = kdbus_hello(env->buspath, 0, NULL, 0);
221 kdbus_conn_free(conn);
224 * We lost only 3 packets since only signal msgs are
225 * accounted. The connection ID add/remove notification
227 ret = kdbus_cmd_recv(reader->fd, &recv);
228 ASSERT_RETURN(ret == 0);
229 ASSERT_RETURN(recv.return_flags & KDBUS_RECV_RETURN_DROPPED_MSGS);
230 ASSERT_RETURN(recv.dropped_msgs == 3);
232 msg = (struct kdbus_msg *)(reader->buf + recv.msg.offset);
236 for (i = 0; i < KDBUS_CONN_MAX_MSGS - 1; i++) {
237 memset(&recv, 0, sizeof(recv));
238 recv.size = sizeof(recv);
240 ret = kdbus_cmd_recv(reader->fd, &recv);
241 ASSERT_RETURN(ret == 0);
242 ASSERT_RETURN(!(recv.return_flags &
243 KDBUS_RECV_RETURN_DROPPED_MSGS));
245 msg = (struct kdbus_msg *)(reader->buf + recv.msg.offset);
249 ret = kdbus_msg_recv(reader, NULL, NULL);
250 ASSERT_RETURN(ret == 0);
252 ret = kdbus_msg_recv(reader, NULL, NULL);
253 ASSERT_RETURN(ret == -EAGAIN);
255 kdbus_conn_free(reader);
260 /* Return the number of message successfully sent */
261 static int kdbus_fill_conn_queue(struct kdbus_conn *conn_src,
263 unsigned int max_msgs)
268 struct kdbus_cmd_send cmd = {};
269 struct kdbus_msg *msg;
272 size = sizeof(struct kdbus_msg);
274 ASSERT_RETURN_VAL(msg, -ENOMEM);
276 memset(msg, 0, size);
278 msg->src_id = conn_src->id;
279 msg->dst_id = dst_id;
280 msg->payload_type = KDBUS_PAYLOAD_DBUS;
282 cmd.size = sizeof(cmd);
283 cmd.msg_address = (uintptr_t)msg;
285 for (i = 0; i < max_msgs; i++) {
286 msg->cookie = cookie++;
287 ret = kdbus_cmd_send(conn_src->fd, &cmd);
297 static int kdbus_test_activator_quota(struct kdbus_test_env *env)
301 unsigned int activator_msgs_count = 0;
302 uint64_t cookie = time(NULL);
303 struct kdbus_conn *conn;
304 struct kdbus_conn *sender;
305 struct kdbus_conn *activator;
306 struct kdbus_msg *msg;
307 uint64_t flags = KDBUS_NAME_REPLACE_EXISTING;
308 struct kdbus_cmd_recv recv = { .size = sizeof(recv) };
309 struct kdbus_policy_access access = {
310 .type = KDBUS_POLICY_ACCESS_USER,
312 .access = KDBUS_POLICY_OWN,
315 activator = kdbus_hello_activator(env->buspath, "foo.test.activator",
317 ASSERT_RETURN(activator);
319 conn = kdbus_hello(env->buspath, 0, NULL, 0);
320 sender = kdbus_hello(env->buspath, 0, NULL, 0);
321 ASSERT_RETURN(conn || sender);
323 ret = kdbus_list(sender, KDBUS_LIST_NAMES |
325 KDBUS_LIST_ACTIVATORS |
327 ASSERT_RETURN(ret == 0);
329 for (i = 0; i < KDBUS_CONN_MAX_MSGS; i++) {
330 ret = kdbus_msg_send(sender, "foo.test.activator",
336 activator_msgs_count++;
339 /* we must have at least sent one message */
340 ASSERT_RETURN_VAL(i > 0, -errno);
341 ASSERT_RETURN(ret == -ENOBUFS);
343 /* Good, activator queue is full now */
345 /* ENXIO on direct send (activators can never be addressed by ID) */
346 ret = kdbus_msg_send(conn, NULL, cookie++, 0, 0, 0, activator->id,
348 ASSERT_RETURN(ret == -ENXIO);
350 /* can't queue more */
351 ret = kdbus_msg_send(conn, "foo.test.activator", cookie++,
352 0, 0, 0, KDBUS_DST_ID_NAME, 0, NULL);
353 ASSERT_RETURN(ret == -ENOBUFS);
355 /* no match installed, so the broadcast will not inc dropped_msgs */
356 ret = kdbus_msg_send(sender, NULL, cookie++, 0, 0, 0,
357 KDBUS_DST_ID_BROADCAST, 0, NULL);
358 ASSERT_RETURN(ret == 0);
360 /* Check activator queue */
361 ret = kdbus_cmd_recv(activator->fd, &recv);
362 ASSERT_RETURN(ret == 0);
363 ASSERT_RETURN(recv.dropped_msgs == 0);
365 activator_msgs_count--;
367 msg = (struct kdbus_msg *)(activator->buf + recv.msg.offset);
371 /* Stage 1) of test check the pool memory quota */
373 /* Consume the connection pool memory */
374 for (i = 0; i < KDBUS_CONN_MAX_MSGS; i++) {
375 ret = kdbus_msg_send(sender, NULL,
376 cookie++, 0, 0, 0, conn->id, 0, NULL);
381 /* consume one message, so later at least one can be moved */
382 memset(&recv, 0, sizeof(recv));
383 recv.size = sizeof(recv);
384 ret = kdbus_cmd_recv(conn->fd, &recv);
385 ASSERT_RETURN(ret == 0);
386 ASSERT_RETURN(recv.dropped_msgs == 0);
387 msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset);
390 /* Try to acquire the name now */
391 ret = kdbus_name_acquire(conn, "foo.test.activator", &flags);
392 ASSERT_RETURN(ret == 0);
394 /* try to read messages and see if we have lost some */
395 memset(&recv, 0, sizeof(recv));
396 recv.size = sizeof(recv);
397 ret = kdbus_cmd_recv(conn->fd, &recv);
398 ASSERT_RETURN(ret == 0);
399 ASSERT_RETURN(recv.dropped_msgs != 0);
401 /* number of dropped msgs < received ones (at least one was moved) */
402 ASSERT_RETURN(recv.dropped_msgs < activator_msgs_count);
404 /* Deduct the number of dropped msgs from the activator msgs */
405 activator_msgs_count -= recv.dropped_msgs;
407 msg = (struct kdbus_msg *)(activator->buf + recv.msg.offset);
411 * Release the name and hand it back to activator, now
412 * we should have 'activator_msgs_count' msgs again in
413 * the activator queue
415 ret = kdbus_name_release(conn, "foo.test.activator");
416 ASSERT_RETURN(ret == 0);
418 /* make sure that we got our previous activator msgs */
419 ret = kdbus_msg_recv(activator, &msg, NULL);
420 ASSERT_RETURN(ret == 0);
421 ASSERT_RETURN(msg->src_id == sender->id);
423 activator_msgs_count--;
428 /* Stage 2) of test check max message quota */
430 /* Empty conn queue */
431 for (i = 0; i < KDBUS_CONN_MAX_MSGS; i++) {
432 ret = kdbus_msg_recv(conn, NULL, NULL);
437 /* fill queue with max msgs quota */
438 ret = kdbus_fill_conn_queue(sender, conn->id, KDBUS_CONN_MAX_MSGS);
439 ASSERT_RETURN(ret == KDBUS_CONN_MAX_MSGS);
441 /* This one is lost but it is not accounted */
442 ret = kdbus_msg_send(sender, NULL,
443 cookie++, 0, 0, 0, conn->id, 0, NULL);
444 ASSERT_RETURN(ret == -ENOBUFS);
446 /* Acquire the name again */
447 ret = kdbus_name_acquire(conn, "foo.test.activator", &flags);
448 ASSERT_RETURN(ret == 0);
450 memset(&recv, 0, sizeof(recv));
451 recv.size = sizeof(recv);
454 * Try to read messages and make sure that we have lost all
455 * the activator messages due to quota checks. Our queue is
458 ret = kdbus_cmd_recv(conn->fd, &recv);
459 ASSERT_RETURN(ret == 0);
460 ASSERT_RETURN(recv.dropped_msgs == activator_msgs_count);
462 msg = (struct kdbus_msg *)(activator->buf + recv.msg.offset);
465 kdbus_conn_free(sender);
466 kdbus_conn_free(conn);
467 kdbus_conn_free(activator);
472 static int kdbus_test_expected_reply_quota(struct kdbus_test_env *env)
477 uint64_t cookie = 0x1234abcd5678eeff;
478 struct kdbus_conn *conn;
479 struct kdbus_conn *connections[9];
481 conn = kdbus_hello(env->buspath, 0, NULL, 0);
484 for (i = 0; i < 9; i++) {
485 connections[i] = kdbus_hello(env->buspath, 0, NULL, 0);
486 ASSERT_RETURN(connections[i]);
490 /* Send 16 messages to 8 different connections */
491 for (i = 0; i < 8; i++) {
492 for (n = 0; n < 16; n++) {
493 ret = kdbus_msg_send(conn, NULL, cookie++,
494 KDBUS_MSG_EXPECT_REPLY,
506 * We should have queued at least
507 * KDBUS_CONN_MAX_REQUESTS_PENDING method call
509 ASSERT_RETURN(count == KDBUS_CONN_MAX_REQUESTS_PENDING);
512 * Now try to send a message to the last connection,
513 * if we have reached KDBUS_CONN_MAX_REQUESTS_PENDING
514 * no further requests are allowed
516 ret = kdbus_msg_send(conn, NULL, cookie++, KDBUS_MSG_EXPECT_REPLY,
517 1000000000ULL, 0, connections[8]->id, 0, NULL);
518 ASSERT_RETURN(ret == -EMLINK);
520 for (i = 0; i < 9; i++)
521 kdbus_conn_free(connections[i]);
523 kdbus_conn_free(conn);
528 int kdbus_test_pool_quota(struct kdbus_test_env *env)
530 struct kdbus_conn *a, *b, *c;
531 struct kdbus_cmd_send cmd = {};
532 struct kdbus_item *item;
533 struct kdbus_msg *recv_msg;
534 struct kdbus_msg *msg;
535 uint64_t cookie = time(NULL);
542 if (POOL_SIZE <= KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE ||
543 POOL_SIZE % KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE != 0)
546 payload = calloc(KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE, sizeof(char));
547 ASSERT_RETURN_VAL(payload, -ENOMEM);
549 a = kdbus_hello(env->buspath, 0, NULL, 0);
550 b = kdbus_hello(env->buspath, 0, NULL, 0);
551 c = kdbus_hello(env->buspath, 0, NULL, 0);
552 ASSERT_RETURN(a && b && c);
554 size = sizeof(struct kdbus_msg);
555 size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
558 ASSERT_RETURN_VAL(msg, -ENOMEM);
560 memset(msg, 0, size);
564 msg->payload_type = KDBUS_PAYLOAD_DBUS;
567 item->type = KDBUS_ITEM_PAYLOAD_VEC;
568 item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
569 item->vec.address = (uintptr_t)payload;
570 item->vec.size = KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE;
571 item = KDBUS_ITEM_NEXT(item);
573 cmd.size = sizeof(cmd);
574 cmd.msg_address = (uintptr_t)msg;
577 * Send 2097248 bytes, a user is only allowed to get 33% of half of
578 * the free space of the pool, the already used space is
579 * accounted as free space
581 size += KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE;
582 for (i = size; i < (POOL_SIZE / 2 / 3); i += size) {
583 msg->cookie = cookie++;
585 ret = kdbus_cmd_send(a->fd, &cmd);
586 ASSERT_RETURN_VAL(ret == 0, ret);
589 /* Try to get more than 33% */
590 msg->cookie = cookie++;
591 ret = kdbus_cmd_send(a->fd, &cmd);
592 ASSERT_RETURN(ret == -ENOBUFS);
594 /* We still can pass small messages */
595 ret = kdbus_msg_send(b, NULL, cookie++, 0, 0, 0, c->id, 0, NULL);
596 ASSERT_RETURN(ret == 0);
598 for (i = size; i < (POOL_SIZE / 2 / 3); i += size) {
599 ret = kdbus_msg_recv(c, &recv_msg, NULL);
600 ASSERT_RETURN(ret == 0);
601 ASSERT_RETURN(recv_msg->src_id == a->id);
603 kdbus_msg_free(recv_msg);
606 ret = kdbus_msg_recv(c, &recv_msg, NULL);
607 ASSERT_RETURN(ret == 0);
608 ASSERT_RETURN(recv_msg->src_id == b->id);
610 kdbus_msg_free(recv_msg);
612 ret = kdbus_msg_recv(c, NULL, NULL);
613 ASSERT_RETURN(ret == -EAGAIN);
625 int kdbus_test_message_quota(struct kdbus_test_env *env)
627 struct kdbus_conn *a, *b;
632 ret = kdbus_test_activator_quota(env);
633 ASSERT_RETURN(ret == 0);
635 ret = kdbus_test_notify_kernel_quota(env);
636 ASSERT_RETURN(ret == 0);
638 ret = kdbus_test_pool_quota(env);
639 ASSERT_RETURN(ret == 0);
641 ret = kdbus_test_expected_reply_quota(env);
642 ASSERT_RETURN(ret == 0);
644 a = kdbus_hello(env->buspath, 0, NULL, 0);
645 b = kdbus_hello(env->buspath, 0, NULL, 0);
647 ret = kdbus_fill_conn_queue(b, a->id, KDBUS_CONN_MAX_MSGS);
648 ASSERT_RETURN(ret == KDBUS_CONN_MAX_MSGS);
650 ret = kdbus_msg_send(b, NULL, ++cookie, 0, 0, 0, a->id, 0, NULL);
651 ASSERT_RETURN(ret == -ENOBUFS);
653 for (i = 0; i < KDBUS_CONN_MAX_MSGS; ++i) {
654 ret = kdbus_msg_recv(a, NULL, NULL);
655 ASSERT_RETURN(ret == 0);
658 ret = kdbus_msg_recv(a, NULL, NULL);
659 ASSERT_RETURN(ret == -EAGAIN);
661 ret = kdbus_fill_conn_queue(b, a->id, KDBUS_CONN_MAX_MSGS + 1);
662 ASSERT_RETURN(ret == KDBUS_CONN_MAX_MSGS);
664 ret = kdbus_msg_send(b, NULL, ++cookie, 0, 0, 0, a->id, 0, NULL);
665 ASSERT_RETURN(ret == -ENOBUFS);
673 int kdbus_test_memory_access(struct kdbus_test_env *env)
675 struct kdbus_conn *a, *b;
676 struct kdbus_cmd_send cmd = {};
677 struct kdbus_item *item;
678 struct kdbus_msg *msg;
679 uint64_t test_addr = 0;
686 * Search in /proc/kallsyms for the address of a kernel symbol that
687 * should always be there, regardless of the config. Use that address
688 * in a PAYLOAD_VEC item and make sure it's inaccessible.
691 f = fopen("/proc/kallsyms", "r");
695 while (fgets(line, sizeof(line), f)) {
698 if (!strsep(&s, " "))
701 if (!strsep(&s, " "))
704 if (!strncmp(s, "mutex_lock", 10)) {
705 test_addr = strtoull(line, NULL, 16);
715 a = kdbus_hello(env->buspath, 0, NULL, 0);
716 b = kdbus_hello(env->buspath, 0, NULL, 0);
717 ASSERT_RETURN(a && b);
719 size = sizeof(struct kdbus_msg);
720 size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
723 ASSERT_RETURN_VAL(msg, -ENOMEM);
725 memset(msg, 0, size);
729 msg->payload_type = KDBUS_PAYLOAD_DBUS;
732 item->type = KDBUS_ITEM_PAYLOAD_VEC;
733 item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
734 item->vec.address = test_addr;
735 item->vec.size = sizeof(void*);
736 item = KDBUS_ITEM_NEXT(item);
738 cmd.size = sizeof(cmd);
739 cmd.msg_address = (uintptr_t)msg;
741 ret = kdbus_cmd_send(a->fd, &cmd);
742 ASSERT_RETURN(ret == -EFAULT);