d9b8fbddb1da821750de3ffccf5b19375227e1c1
[platform/kernel/linux-rpi.git] / tools / testing / selftests / kdbus / test-message.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <fcntl.h>
4 #include <stdlib.h>
5 #include <stddef.h>
6 #include <unistd.h>
7 #include <stdint.h>
8 #include <errno.h>
9 #include <assert.h>
10 #include <time.h>
11 #include <stdbool.h>
12 #include <sys/eventfd.h>
13 #include <sys/types.h>
14 #include <sys/wait.h>
15
16 #include "kdbus-api.h"
17 #include "kdbus-util.h"
18 #include "kdbus-enum.h"
19 #include "kdbus-test.h"
20
21 /* maximum number of queued messages from the same individual user */
22 #define KDBUS_CONN_MAX_MSGS                     256
23
24 /* maximum number of queued requests waiting for a reply */
25 #define KDBUS_CONN_MAX_REQUESTS_PENDING         128
26
27 /* maximum message payload size */
28 #define KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE          (2 * 1024UL * 1024UL)
29
30 int kdbus_test_message_basic(struct kdbus_test_env *env)
31 {
32         struct kdbus_conn *conn;
33         struct kdbus_conn *sender;
34         struct kdbus_msg *msg;
35         uint64_t cookie = 0x1234abcd5678eeff;
36         uint64_t offset;
37         int ret;
38
39         sender = kdbus_hello(env->buspath, 0, NULL, 0);
40         ASSERT_RETURN(sender != NULL);
41
42         /* create a 2nd connection */
43         conn = kdbus_hello(env->buspath, 0, NULL, 0);
44         ASSERT_RETURN(conn != NULL);
45
46         ret = kdbus_add_match_empty(conn);
47         ASSERT_RETURN(ret == 0);
48
49         ret = kdbus_add_match_empty(sender);
50         ASSERT_RETURN(ret == 0);
51
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);
56
57         /* Make sure that we do not get our own broadcasts */
58         ret = kdbus_msg_recv(sender, NULL, NULL);
59         ASSERT_RETURN(ret == -EAGAIN);
60
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);
65
66         kdbus_msg_free(msg);
67
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);
72
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);
76
77         ret = kdbus_free(conn, offset);
78         ASSERT_RETURN(ret == 0);
79
80         kdbus_conn_free(sender);
81         kdbus_conn_free(conn);
82
83         return TEST_OK;
84 }
85
86 static int msg_recv_prio(struct kdbus_conn *conn,
87                          int64_t requested_prio,
88                          int64_t expected_prio)
89 {
90         struct kdbus_cmd_recv recv = {
91                 .size = sizeof(recv),
92                 .flags = KDBUS_RECV_USE_PRIORITY,
93                 .priority = requested_prio,
94         };
95         struct kdbus_msg *msg;
96         int ret;
97
98         ret = kdbus_cmd_recv(conn->fd, &recv);
99         if (ret < 0) {
100                 kdbus_printf("error receiving message: %d (%m)\n", -errno);
101                 return ret;
102         }
103
104         msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset);
105         kdbus_msg_dump(conn, msg);
106
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);
111                 return -EINVAL;
112         }
113
114         kdbus_msg_free(msg);
115         ret = kdbus_free(conn, recv.msg.offset);
116         if (ret < 0)
117                 return ret;
118
119         return 0;
120 }
121
122 int kdbus_test_message_prio(struct kdbus_test_env *env)
123 {
124         struct kdbus_conn *a, *b;
125         uint64_t cookie = 0;
126         int ret;
127
128         a = kdbus_hello(env->buspath, 0, NULL, 0);
129         b = kdbus_hello(env->buspath, 0, NULL, 0);
130         ASSERT_RETURN(a && b);
131
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);
156
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);
163
164         kdbus_printf("--- get priority (all)\n");
165         ASSERT_RETURN(kdbus_msg_recv(a, NULL, NULL) == 0);
166
167         kdbus_conn_free(a);
168         kdbus_conn_free(b);
169
170         return TEST_OK;
171 }
172
173 static int kdbus_test_notify_kernel_quota(struct kdbus_test_env *env)
174 {
175         int ret;
176         unsigned int i;
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) };
181
182         reader = kdbus_hello(env->buspath, 0, NULL, 0);
183         ASSERT_RETURN(reader);
184
185         conn = kdbus_hello(env->buspath, 0, NULL, 0);
186         ASSERT_RETURN(conn);
187
188         /* Register for ID signals */
189         ret = kdbus_add_match_id(reader, 0x1, KDBUS_ITEM_ID_ADD,
190                                  KDBUS_MATCH_ID_ANY);
191         ASSERT_RETURN(ret == 0);
192
193         ret = kdbus_add_match_id(reader, 0x2, KDBUS_ITEM_ID_REMOVE,
194                                  KDBUS_MATCH_ID_ANY);
195         ASSERT_RETURN(ret == 0);
196
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;
200
201                 notifier = kdbus_hello(env->buspath, 0, NULL, 0);
202                 ASSERT_RETURN(notifier);
203
204                 kdbus_conn_free(notifier);
205         }
206
207         /*
208          * Now the reader queue is full with kernel notfications,
209          * but as a user we still have room to push our messages.
210          */
211         ret = kdbus_msg_send(conn, NULL, 0xdeadbeef, 0, 0, 0, reader->id,
212                              0, NULL);
213         ASSERT_RETURN(ret == 0);
214
215         /* More ID kernel notifications that will be lost */
216         kdbus_conn_free(conn);
217
218         conn = kdbus_hello(env->buspath, 0, NULL, 0);
219         ASSERT_RETURN(conn);
220
221         kdbus_conn_free(conn);
222
223         /*
224          * We lost only 3 packets since only signal msgs are
225          * accounted. The connection ID add/remove notification
226          */
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);
231
232         msg = (struct kdbus_msg *)(reader->buf + recv.msg.offset);
233         kdbus_msg_free(msg);
234
235         /* Read our queue */
236         for (i = 0; i < KDBUS_CONN_MAX_MSGS - 1; i++) {
237                 memset(&recv, 0, sizeof(recv));
238                 recv.size = sizeof(recv);
239
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));
244
245                 msg = (struct kdbus_msg *)(reader->buf + recv.msg.offset);
246                 kdbus_msg_free(msg);
247         }
248
249         ret = kdbus_msg_recv(reader, NULL, NULL);
250         ASSERT_RETURN(ret == 0);
251
252         ret = kdbus_msg_recv(reader, NULL, NULL);
253         ASSERT_RETURN(ret == -EAGAIN);
254
255         kdbus_conn_free(reader);
256
257         return 0;
258 }
259
260 /* Return the number of message successfully sent */
261 static int kdbus_fill_conn_queue(struct kdbus_conn *conn_src,
262                                  uint64_t dst_id,
263                                  unsigned int max_msgs)
264 {
265         unsigned int i;
266         uint64_t cookie = 0;
267         size_t size;
268         struct kdbus_cmd_send cmd = {};
269         struct kdbus_msg *msg;
270         int ret;
271
272         size = sizeof(struct kdbus_msg);
273         msg = malloc(size);
274         ASSERT_RETURN_VAL(msg, -ENOMEM);
275
276         memset(msg, 0, size);
277         msg->size = size;
278         msg->src_id = conn_src->id;
279         msg->dst_id = dst_id;
280         msg->payload_type = KDBUS_PAYLOAD_DBUS;
281
282         cmd.size = sizeof(cmd);
283         cmd.msg_address = (uintptr_t)msg;
284
285         for (i = 0; i < max_msgs; i++) {
286                 msg->cookie = cookie++;
287                 ret = kdbus_cmd_send(conn_src->fd, &cmd);
288                 if (ret < 0)
289                         break;
290         }
291
292         free(msg);
293
294         return i;
295 }
296
297 static int kdbus_test_activator_quota(struct kdbus_test_env *env)
298 {
299         int ret;
300         unsigned int i;
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,
311                 .id = geteuid(),
312                 .access = KDBUS_POLICY_OWN,
313         };
314
315         activator = kdbus_hello_activator(env->buspath, "foo.test.activator",
316                                           &access, 1);
317         ASSERT_RETURN(activator);
318
319         conn = kdbus_hello(env->buspath, 0, NULL, 0);
320         sender = kdbus_hello(env->buspath, 0, NULL, 0);
321         ASSERT_RETURN(conn || sender);
322
323         ret = kdbus_list(sender, KDBUS_LIST_NAMES |
324                                  KDBUS_LIST_UNIQUE |
325                                  KDBUS_LIST_ACTIVATORS |
326                                  KDBUS_LIST_QUEUED);
327         ASSERT_RETURN(ret == 0);
328
329         for (i = 0; i < KDBUS_CONN_MAX_MSGS; i++) {
330                 ret = kdbus_msg_send(sender, "foo.test.activator",
331                                      cookie++, 0, 0, 0,
332                                      KDBUS_DST_ID_NAME,
333                                      0, NULL);
334                 if (ret < 0)
335                         break;
336                 activator_msgs_count++;
337         }
338
339         /* we must have at least sent one message */
340         ASSERT_RETURN_VAL(i > 0, -errno);
341         ASSERT_RETURN(ret == -ENOBUFS);
342
343         /* Good, activator queue is full now */
344
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,
347                              0, NULL);
348         ASSERT_RETURN(ret == -ENXIO);
349
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);
354
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);
359
360         /* Check activator queue */
361         ret = kdbus_cmd_recv(activator->fd, &recv);
362         ASSERT_RETURN(ret == 0);
363         ASSERT_RETURN(recv.dropped_msgs == 0);
364
365         activator_msgs_count--;
366
367         msg = (struct kdbus_msg *)(activator->buf + recv.msg.offset);
368         kdbus_msg_free(msg);
369
370
371         /* Stage 1) of test check the pool memory quota */
372
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);
377                 if (ret < 0)
378                         break;
379         }
380
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);
388         kdbus_msg_free(msg);
389
390         /* Try to acquire the name now */
391         ret = kdbus_name_acquire(conn, "foo.test.activator", &flags);
392         ASSERT_RETURN(ret == 0);
393
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);
400
401         /* number of dropped msgs < received ones (at least one was moved) */
402         ASSERT_RETURN(recv.dropped_msgs < activator_msgs_count);
403
404         /* Deduct the number of dropped msgs from the activator msgs */
405         activator_msgs_count -= recv.dropped_msgs;
406
407         msg = (struct kdbus_msg *)(activator->buf + recv.msg.offset);
408         kdbus_msg_free(msg);
409
410         /*
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
414          */
415         ret = kdbus_name_release(conn, "foo.test.activator");
416         ASSERT_RETURN(ret == 0);
417
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);
422
423         activator_msgs_count--;
424
425         kdbus_msg_free(msg);
426
427
428         /* Stage 2) of test check max message quota */
429
430         /* Empty conn queue */
431         for (i = 0; i < KDBUS_CONN_MAX_MSGS; i++) {
432                 ret = kdbus_msg_recv(conn, NULL, NULL);
433                 if (ret == -EAGAIN)
434                         break;
435         }
436
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);
440
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);
445
446         /* Acquire the name again */
447         ret = kdbus_name_acquire(conn, "foo.test.activator", &flags);
448         ASSERT_RETURN(ret == 0);
449
450         memset(&recv, 0, sizeof(recv));
451         recv.size = sizeof(recv);
452
453         /*
454          * Try to read messages and make sure that we have lost all
455          * the activator messages due to quota checks. Our queue is
456          * already full.
457          */
458         ret = kdbus_cmd_recv(conn->fd, &recv);
459         ASSERT_RETURN(ret == 0);
460         ASSERT_RETURN(recv.dropped_msgs == activator_msgs_count);
461
462         msg = (struct kdbus_msg *)(activator->buf + recv.msg.offset);
463         kdbus_msg_free(msg);
464
465         kdbus_conn_free(sender);
466         kdbus_conn_free(conn);
467         kdbus_conn_free(activator);
468
469         return 0;
470 }
471
472 static int kdbus_test_expected_reply_quota(struct kdbus_test_env *env)
473 {
474         int ret;
475         unsigned int i, n;
476         unsigned int count;
477         uint64_t cookie = 0x1234abcd5678eeff;
478         struct kdbus_conn *conn;
479         struct kdbus_conn *connections[9];
480
481         conn = kdbus_hello(env->buspath, 0, NULL, 0);
482         ASSERT_RETURN(conn);
483
484         for (i = 0; i < 9; i++) {
485                 connections[i] = kdbus_hello(env->buspath, 0, NULL, 0);
486                 ASSERT_RETURN(connections[i]);
487         }
488
489         count = 0;
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,
495                                              100000000ULL, 0,
496                                              connections[i]->id,
497                                              0, NULL);
498                         if (ret < 0)
499                                 break;
500
501                         count++;
502                 }
503         }
504
505         /*
506          * We should have queued at least
507          * KDBUS_CONN_MAX_REQUESTS_PENDING method call
508          */
509         ASSERT_RETURN(count == KDBUS_CONN_MAX_REQUESTS_PENDING);
510
511         /*
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
515          */
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);
519
520         for (i = 0; i < 9; i++)
521                 kdbus_conn_free(connections[i]);
522
523         kdbus_conn_free(conn);
524
525         return 0;
526 }
527
528 int kdbus_test_pool_quota(struct kdbus_test_env *env)
529 {
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);
536         uint64_t size;
537         unsigned int i;
538         char *payload;
539         int ret;
540
541         /* just a guard */
542         if (POOL_SIZE <= KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE ||
543             POOL_SIZE % KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE != 0)
544                 return 0;
545
546         payload = calloc(KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE, sizeof(char));
547         ASSERT_RETURN_VAL(payload, -ENOMEM);
548
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);
553
554         size = sizeof(struct kdbus_msg);
555         size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
556
557         msg = malloc(size);
558         ASSERT_RETURN_VAL(msg, -ENOMEM);
559
560         memset(msg, 0, size);
561         msg->size = size;
562         msg->src_id = a->id;
563         msg->dst_id = c->id;
564         msg->payload_type = KDBUS_PAYLOAD_DBUS;
565
566         item = msg->items;
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);
572
573         cmd.size = sizeof(cmd);
574         cmd.msg_address = (uintptr_t)msg;
575
576         /*
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
580          */
581         size += KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE;
582         for (i = size; i < (POOL_SIZE / 2 / 3); i += size) {
583                 msg->cookie = cookie++;
584
585                 ret = kdbus_cmd_send(a->fd, &cmd);
586                 ASSERT_RETURN_VAL(ret == 0, ret);
587         }
588
589         /* Try to get more than 33% */
590         msg->cookie = cookie++;
591         ret = kdbus_cmd_send(a->fd, &cmd);
592         ASSERT_RETURN(ret == -ENOBUFS);
593
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);
597
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);
602
603                 kdbus_msg_free(recv_msg);
604         }
605
606         ret = kdbus_msg_recv(c, &recv_msg, NULL);
607         ASSERT_RETURN(ret == 0);
608         ASSERT_RETURN(recv_msg->src_id == b->id);
609
610         kdbus_msg_free(recv_msg);
611
612         ret = kdbus_msg_recv(c, NULL, NULL);
613         ASSERT_RETURN(ret == -EAGAIN);
614
615         free(msg);
616         free(payload);
617
618         kdbus_conn_free(c);
619         kdbus_conn_free(b);
620         kdbus_conn_free(a);
621
622         return 0;
623 }
624
625 int kdbus_test_message_quota(struct kdbus_test_env *env)
626 {
627         struct kdbus_conn *a, *b;
628         uint64_t cookie = 0;
629         int ret;
630         int i;
631
632         ret = kdbus_test_activator_quota(env);
633         ASSERT_RETURN(ret == 0);
634
635         ret = kdbus_test_notify_kernel_quota(env);
636         ASSERT_RETURN(ret == 0);
637
638         ret = kdbus_test_pool_quota(env);
639         ASSERT_RETURN(ret == 0);
640
641         ret = kdbus_test_expected_reply_quota(env);
642         ASSERT_RETURN(ret == 0);
643
644         a = kdbus_hello(env->buspath, 0, NULL, 0);
645         b = kdbus_hello(env->buspath, 0, NULL, 0);
646
647         ret = kdbus_fill_conn_queue(b, a->id, KDBUS_CONN_MAX_MSGS);
648         ASSERT_RETURN(ret == KDBUS_CONN_MAX_MSGS);
649
650         ret = kdbus_msg_send(b, NULL, ++cookie, 0, 0, 0, a->id, 0, NULL);
651         ASSERT_RETURN(ret == -ENOBUFS);
652
653         for (i = 0; i < KDBUS_CONN_MAX_MSGS; ++i) {
654                 ret = kdbus_msg_recv(a, NULL, NULL);
655                 ASSERT_RETURN(ret == 0);
656         }
657
658         ret = kdbus_msg_recv(a, NULL, NULL);
659         ASSERT_RETURN(ret == -EAGAIN);
660
661         ret = kdbus_fill_conn_queue(b, a->id, KDBUS_CONN_MAX_MSGS + 1);
662         ASSERT_RETURN(ret == KDBUS_CONN_MAX_MSGS);
663
664         ret = kdbus_msg_send(b, NULL, ++cookie, 0, 0, 0, a->id, 0, NULL);
665         ASSERT_RETURN(ret == -ENOBUFS);
666
667         kdbus_conn_free(a);
668         kdbus_conn_free(b);
669
670         return TEST_OK;
671 }
672
673 int kdbus_test_memory_access(struct kdbus_test_env *env)
674 {
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;
680         char line[256];
681         uint64_t size;
682         FILE *f;
683         int ret;
684
685         /*
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.
689          */
690
691         f = fopen("/proc/kallsyms", "r");
692         if (!f)
693                 return TEST_SKIP;
694
695         while (fgets(line, sizeof(line), f)) {
696                 char *s = line;
697
698                 if (!strsep(&s, " "))
699                         continue;
700
701                 if (!strsep(&s, " "))
702                         continue;
703
704                 if (!strncmp(s, "mutex_lock", 10)) {
705                         test_addr = strtoull(line, NULL, 16);
706                         break;
707                 }
708         }
709
710         fclose(f);
711
712         if (!test_addr)
713                 return TEST_SKIP;
714
715         a = kdbus_hello(env->buspath, 0, NULL, 0);
716         b = kdbus_hello(env->buspath, 0, NULL, 0);
717         ASSERT_RETURN(a && b);
718
719         size = sizeof(struct kdbus_msg);
720         size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
721
722         msg = alloca(size);
723         ASSERT_RETURN_VAL(msg, -ENOMEM);
724
725         memset(msg, 0, size);
726         msg->size = size;
727         msg->src_id = a->id;
728         msg->dst_id = b->id;
729         msg->payload_type = KDBUS_PAYLOAD_DBUS;
730
731         item = msg->items;
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);
737
738         cmd.size = sizeof(cmd);
739         cmd.msg_address = (uintptr_t)msg;
740
741         ret = kdbus_cmd_send(a->fd, &cmd);
742         ASSERT_RETURN(ret == -EFAULT);
743
744         kdbus_conn_free(b);
745         kdbus_conn_free(a);
746
747         return 0;
748 }