kdbus: test suite changed to common format
[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                     256U
23
24 /* maximum number of queued requests waiting for a reply */
25 #define KDBUS_CONN_MAX_REQUESTS_PENDING         1024U
26
27 /* maximum message payload size */
28 #define KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE          (2 * 1024UL * 1024UL)
29
30 wur 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
38         ASSERT_NONZERO(sender = kdbus_hello(env->buspath, 0, NULL, 0));
39
40         /* create a 2nd connection */
41         ASSERT_NONZERO(conn = kdbus_hello(env->buspath, 0, NULL, 0));
42
43         ASSERT_ZERO(kdbus_add_match_empty(conn));
44
45         ASSERT_ZERO(kdbus_add_match_empty(sender));
46
47         /* send over 1st connection */
48         ASSERT_ZERO(kdbus_msg_send(sender, NULL, cookie, 0, 0, 0, KDBUS_DST_ID_BROADCAST));
49
50         /* Make sure that we do get our own broadcasts */
51         ASSERT_ZERO(kdbus_msg_recv(sender, &msg, &offset));
52         ASSERT_RETURN(msg->cookie,==,cookie);
53         kdbus_msg_free(msg);
54
55         /* ... and receive on the 2nd */
56         ASSERT_ZERO(kdbus_msg_recv_poll(conn, 100, &msg, &offset));
57         ASSERT_RETURN(msg->cookie,==,cookie);
58
59         kdbus_msg_free(msg);
60
61         /* Msgs that expect a reply must have timeout and cookie */
62         ASSERT_RETURN(-EINVAL,==,kdbus_msg_send(sender, NULL, 0, KDBUS_MSG_EXPECT_REPLY, 1000000000, 0, conn->id)); /* no cookie */
63         ASSERT_RETURN(-EINVAL,==,kdbus_msg_send(sender, NULL, 1, KDBUS_MSG_EXPECT_REPLY, 0, 0, conn->id)); /* no timeout */
64         ASSERT_RETURN(-EINVAL,==,kdbus_msg_send(sender, NULL, 0, KDBUS_MSG_EXPECT_REPLY, 0, 0, conn->id)); /* neither cookie nor timeout */
65
66         /* Faked replies with a valid reply cookie are rejected iff not TIZEN */
67         ASSERT_RETURN(ONTIZEN(0,-EBADSLT),==,kdbus_msg_send_reply(conn, time(NULL) ^ cookie, sender->id));
68
69         ASSERT_ZERO(kdbus_free(conn, offset));
70
71         kdbus_conn_free(sender);
72         kdbus_conn_free(conn);
73
74         return TEST_OK;
75 }
76
77 static wur int msg_recv_prio(struct kdbus_conn *conn,
78                          int64_t requested_prio,
79                          int64_t expected_prio)
80 {
81         struct kdbus_cmd_recv recv = {
82                 .size = sizeof(recv),
83                 .flags = KDBUS_RECV_USE_PRIORITY,
84                 .priority = requested_prio,
85         };
86         struct kdbus_msg *msg;
87         int ret, dumpret;
88
89         ret = kdbus_cmd_recv(conn->fd, &recv);
90         if (ret < 0) {
91                 kdbus_printf("error receiving message: %d (%m)\n", -errno);
92                 return ret;
93         }
94
95         msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset);
96         dumpret = kdbus_msg_dump(msg);
97
98         if (msg->priority != expected_prio) {
99                 kdbus_printf("expected message prio %lld, got %lld\n",
100                              (unsigned long long) expected_prio,
101                              (unsigned long long) msg->priority);
102                 return -EINVAL;
103         }
104
105         kdbus_msg_free(msg);
106         ret = kdbus_free(conn, recv.msg.offset);
107         if (ret < 0)
108                 return ret;
109         if (dumpret)
110                 return dumpret;
111
112         return 0;
113 }
114
115 wur int kdbus_test_message_prio(struct kdbus_test_env *env)
116 {
117         struct kdbus_conn *a, *b;
118         uint64_t cookie = 0;
119
120         ASSERT_NONZERO(a = kdbus_hello(env->buspath, 0, NULL, 0));
121         ASSERT_NONZERO(b = kdbus_hello(env->buspath, 0, NULL, 0));
122
123         ASSERT_ZERO(kdbus_msg_send(b, NULL, ++cookie, 0, 0,   25, a->id));
124         ASSERT_ZERO(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -600, a->id));
125         ASSERT_ZERO(kdbus_msg_send(b, NULL, ++cookie, 0, 0,   10, a->id));
126         ASSERT_ZERO(kdbus_msg_send(b, NULL, ++cookie, 0, 0,  -35, a->id));
127         ASSERT_ZERO(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -100, a->id));
128         ASSERT_ZERO(kdbus_msg_send(b, NULL, ++cookie, 0, 0,   20, a->id));
129         ASSERT_ZERO(kdbus_msg_send(b, NULL, ++cookie, 0, 0,  -15, a->id));
130         ASSERT_ZERO(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -800, a->id));
131         ASSERT_ZERO(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -150, a->id));
132         ASSERT_ZERO(kdbus_msg_send(b, NULL, ++cookie, 0, 0,   10, a->id));
133         ASSERT_ZERO(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -800, a->id));
134         ASSERT_ZERO(kdbus_msg_send(b, NULL, ++cookie, 0, 0,  -10, a->id));
135
136         ASSERT_ZERO(msg_recv_prio(a, -200, -800));
137         ASSERT_ZERO(msg_recv_prio(a, -100, -800));
138         ASSERT_ZERO(msg_recv_prio(a, -400, -600));
139         ASSERT_RETURN(msg_recv_prio(a, -400, -600),==,-EAGAIN);
140         ASSERT_ZERO(msg_recv_prio(a, 10, -150));
141         ASSERT_ZERO(msg_recv_prio(a, 10, -100));
142
143         kdbus_printf("--- get priority (all)\n");
144         ASSERT_ZERO(kdbus_msg_recv(a, NULL, NULL));
145
146         kdbus_conn_free(a);
147         kdbus_conn_free(b);
148
149         return TEST_OK;
150 }
151
152 static wur int kdbus_test_notify_kernel_quota(struct kdbus_test_env *env)
153 {
154         unsigned int i;
155         struct kdbus_conn *conn;
156         struct kdbus_conn *reader;
157         struct kdbus_msg *msg = NULL;
158         struct kdbus_cmd_recv recv = { .size = sizeof(recv) };
159
160         ASSERT_NONZERO(reader = kdbus_hello(env->buspath, 0, NULL, 0));
161         ASSERT_NONZERO(conn = kdbus_hello(env->buspath, 0, NULL, 0));
162
163         /* Register for ID signals */
164         ASSERT_ZERO(kdbus_add_match_id(reader, 0x1, KDBUS_ITEM_ID_ADD, KDBUS_MATCH_ID_ANY));
165
166         ASSERT_ZERO(kdbus_add_match_id(reader, 0x2, KDBUS_ITEM_ID_REMOVE, KDBUS_MATCH_ID_ANY));
167
168         /* Each iteration two notifications: add and remove ID */
169         for (i = 0; i < KDBUS_CONN_MAX_MSGS / 2; i++) {
170                 struct kdbus_conn *notifier;
171                 ASSERT_NONZERO(notifier = kdbus_hello(env->buspath, 0, NULL, 0));
172                 kdbus_conn_free(notifier);
173         }
174
175         /*
176          * Now the reader queue is full with kernel notfications,
177          * but as a user we still have room to push our messages.
178          */
179         ASSERT_ZERO(kdbus_msg_send(conn, NULL, 0xdeadbeef, 0, 0, 0, reader->id));
180
181         /* More ID kernel notifications that will be lost */
182         kdbus_conn_free(conn);
183
184         ASSERT_NONZERO(conn = kdbus_hello(env->buspath, 0, NULL, 0));
185
186         kdbus_conn_free(conn);
187
188         /*
189          * We lost only 3 packets since only signal msgs are
190          * accounted. The connection ID add/remove notification
191          */
192         ASSERT_ZERO(kdbus_cmd_recv(reader->fd, &recv));
193         ASSERT_NONZERO(recv.return_flags & KDBUS_RECV_RETURN_DROPPED_MSGS);
194         ASSERT_RETURN(recv.dropped_msgs,==,3U);
195
196         msg = (struct kdbus_msg *)(reader->buf + recv.msg.offset);
197         kdbus_msg_free(msg);
198
199         /* Read our queue */
200         for (i = 0; i < KDBUS_CONN_MAX_MSGS - 1; i++) {
201                 memset(&recv, 0, sizeof(recv));
202                 recv.size = sizeof(recv);
203
204                 ASSERT_ZERO(kdbus_cmd_recv(reader->fd, &recv));
205                 ASSERT_ZERO(recv.return_flags & KDBUS_RECV_RETURN_DROPPED_MSGS);
206
207                 msg = (struct kdbus_msg *)(reader->buf + recv.msg.offset);
208                 kdbus_msg_free(msg);
209         }
210
211         ASSERT_ZERO(kdbus_msg_recv(reader, NULL, NULL));
212
213         ASSERT_RETURN(-EAGAIN,==,kdbus_msg_recv(reader, NULL, NULL));
214
215         kdbus_conn_free(reader);
216
217         return 0;
218 }
219
220 /* Return the number of message successfully sent */
221 static wur int kdbus_fill_conn_queue(struct kdbus_conn *conn_src,
222                                  uint64_t dst_id,
223                                  unsigned int max_msgs)
224 {
225         unsigned int i;
226         uint64_t cookie = 0;
227         size_t size;
228         struct kdbus_cmd_send cmd = {};
229         struct kdbus_msg *msg;
230         int ret;
231
232         size = sizeof(struct kdbus_msg);
233         msg = malloc(size);
234         ASSERT_RETURN_VAL(msg,!=,NULL, -ENOMEM);
235
236         memset(msg, 0, size);
237         msg->size = size;
238         msg->src_id = conn_src->id;
239         msg->dst_id = dst_id;
240         msg->payload_type = KDBUS_PAYLOAD_DBUS;
241
242         cmd.size = sizeof(cmd);
243         cmd.msg_address = (uintptr_t)msg;
244
245         for (i = 0; i < max_msgs; i++) {
246                 msg->cookie = ++cookie;
247                 ret = kdbus_cmd_send(conn_src->fd, &cmd);
248                 if (ret < 0) {
249                         /*print("fill_conn_queue_senderr(%d)", ret);*/
250                         break;
251                 }
252         }
253
254         free(msg);
255
256         return i;
257 }
258
259 wur int kdbus_test_activator_quota(struct kdbus_test_env *env)
260 {
261         unsigned i, activator_msgs_count=0;
262         uint64_t cookie = time(NULL);
263         uint64_t flags = KDBUS_NAME_REPLACE_EXISTING;
264         struct kdbus_conn *conn;
265         struct kdbus_conn *sender;
266         struct kdbus_conn *activator;
267         struct kdbus_msg *msg;
268         struct kdbus_cmd_recv recv = { .size = sizeof(recv) };
269         struct kdbus_policy_access access = {
270                 .type = KDBUS_POLICY_ACCESS_USER,
271                 .id = geteuid(),
272                 .access = KDBUS_POLICY_OWN,
273         };
274
275         ASSERT_NONZERO(activator = kdbus_hello_activator(env->buspath, "foo.test.activator", &access, 1));
276
277         ASSERT_NONZERO(conn = kdbus_hello(env->buspath, 0, NULL, 0));
278         ASSERT_NONZERO(sender = kdbus_hello(env->buspath, 0, NULL, 0));
279
280         ASSERT_ZERO(kdbus_list(sender, KDBUS_LIST_NAMES | KDBUS_LIST_UNIQUE | KDBUS_LIST_ACTIVATORS | KDBUS_LIST_QUEUED));
281
282 #define EXHAUST(EXPECTERR,SENDOP) do {\
283         for (i = 0;; ++i) {\
284                 int ret = (SENDOP);\
285                 ASSERT_RETURN(i,<=,KDBUS_CONN_MAX_MSGS);\
286                 if (0 > ret) {\
287                         ASSERT_RETURN((EXPECTERR),==,ret);\
288                         ASSERT_RETURN(i,<,KDBUS_CONN_MAX_MSGS);\
289                         break;\
290                 }\
291         }\
292 } while (0)
293         EXHAUST(-ENOBUFS,kdbus_msg_send(sender, "foo.test.activator", ++cookie, 0, 0, 0, KDBUS_DST_ID_NAME));
294         activator_msgs_count = i;
295
296         /* we must have at least sent one message */
297         ASSERT_RETURN_VAL(i,>,0U, -errno);
298
299         /* Good, activator queue is full now */
300
301         /* ENXIO on direct send (activators can never be addressed by ID) */
302         ASSERT_RETURN(-ENXIO,==,kdbus_msg_send(conn, NULL, ++cookie, 0, 0, 0, activator->id));
303
304         /* can't queue more */
305         ASSERT_RETURN(-ENOBUFS,==,kdbus_msg_send(conn, "foo.test.activator", ++cookie, 0, 0, 0, KDBUS_DST_ID_NAME));
306
307         /* no match installed, so the broadcast will not inc dropped_msgs */
308         ASSERT_ZERO(kdbus_msg_send(conn, NULL, ++cookie, 0, 0, 0, KDBUS_DST_ID_BROADCAST));
309
310         /* Check activator queue */
311         ASSERT_ZERO(kdbus_cmd_recv(activator->fd, &recv));
312         ASSERT_ZERO(recv.dropped_msgs);
313
314         msg = (struct kdbus_msg *)(activator->buf + recv.msg.offset);
315         ASSERT_RETURN(msg->src_id,==,sender->id);
316         ASSERT_RETURN(msg->dst_id,==,(typeof(msg->dst_id))KDBUS_DST_ID_NAME);
317         --activator_msgs_count;
318         kdbus_msg_free(msg);
319
320
321         /* Stage 1) of test check the pool memory quota */
322
323         /* Consume the connection pool memory */
324         EXHAUST(-ENOBUFS,kdbus_msg_send(conn, NULL, ++cookie, 0, 0, 0, conn->id));
325
326         /* consume one message, so later at least one can be moved */
327         memset(&recv, 0, sizeof(recv));
328         recv.size = sizeof(recv);
329         ASSERT_ZERO(kdbus_cmd_recv(conn->fd, &recv));
330         ASSERT_ZERO(recv.dropped_msgs);
331         msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset);
332         kdbus_msg_free(msg);
333
334         /* Try to acquire the name now */
335         ASSERT_ZERO(kdbus_name_acquire(conn, "foo.test.activator", &flags));
336
337         /* try to read messages and see if we have lost some */
338         memset(&recv, 0, sizeof(recv));
339         recv.size = sizeof(recv);
340         ASSERT_ZERO(kdbus_cmd_recv(conn->fd, &recv));
341         ASSERT_NONZERO(recv.dropped_msgs);
342
343         /* number of dropped msgs < received ones (at least one was moved) */
344         ASSERT_RETURN(recv.dropped_msgs,<,activator_msgs_count);
345
346         /* Deduct the number of dropped msgs from the activator msgs */
347         activator_msgs_count -= recv.dropped_msgs;
348
349         msg = (struct kdbus_msg *)(activator->buf + recv.msg.offset);
350         kdbus_msg_free(msg);
351         /*
352          * Release the name and hand it back to activator, now
353          * we should have 'activator_msgs_count' msgs again in
354          * the activator queue
355          */
356         ASSERT_ZERO(kdbus_name_release(conn, "foo.test.activator"));
357
358         /* make sure that we got our previous activator msgs */
359         ASSERT_ZERO(kdbus_msg_recv(activator, &msg, NULL));
360         ASSERT_RETURN(msg->src_id,==,sender->id);
361         ASSERT_RETURN(msg->dst_id,==,(typeof(msg->dst_id))KDBUS_DST_ID_NAME);
362         --activator_msgs_count;
363         kdbus_msg_free(msg);
364
365
366         /* Stage 2) of test check max message quota */
367
368         /* Empty conn queue and refill it to the brink anew */
369         EXHAUST(-EAGAIN,kdbus_msg_recv(conn, NULL, NULL));
370         EXHAUST(-ENOBUFS,kdbus_msg_send(sender, NULL, ++cookie, 0, 0, 0, conn->id));
371 #undef EXHAUST
372
373         if (!activator_msgs_count)
374                 ASSERT_RETURN(-EAGAIN,==,kdbus_msg_recv(activator, NULL, NULL));
375
376         /* Acquire the name again */
377         flags = KDBUS_NAME_REPLACE_EXISTING;
378         ASSERT_ZERO(kdbus_name_acquire(conn, "foo.test.activator", &flags));
379
380         memset(&recv, 0, sizeof(recv));
381         recv.size = sizeof(recv);
382
383         /*
384          * Try to read messages and make sure that we have lost all
385          * the activator messages due to quota checks. Our queue is
386          * already full.
387          */
388         ASSERT_ZERO(kdbus_cmd_recv(conn->fd, &recv));
389         ASSERT_RETURN(recv.dropped_msgs,==,activator_msgs_count);
390
391         msg = (struct kdbus_msg *)(activator->buf + recv.msg.offset);
392         kdbus_msg_free(msg);
393
394         kdbus_conn_free(sender);
395         kdbus_conn_free(conn);
396         kdbus_conn_free(activator);
397
398         return TEST_OK;
399 }
400
401 #define TIMEOUT_CONNECTION_COUNT 8
402 #define TIMEOUTS_PER_CONNECTION (MIN(KDBUS_CONN_MAX_REQUESTS_PENDING,KDBUS_CONN_MAX_MSGS)/TIMEOUT_CONNECTION_COUNT)
403
404 static wur int kdbus_test_expected_reply_validate_timeouts(struct kdbus_conn *conn, uint64_t first_cookie, uint64_t type)
405 {
406         uint64_t cookie_reply, seqnum, monotonic_ns, realtime_ns, prev_seqnum=0, prev_monotonic_ns=0, prev_realtime_ns=0;
407         unsigned i, next_cookie[TIMEOUT_CONNECTION_COUNT];
408         memset(next_cookie, 0, sizeof(next_cookie));
409         for (i=0; i < MIN(KDBUS_CONN_MAX_REQUESTS_PENDING,KDBUS_CONN_MAX_MSGS); i++) {
410                 unsigned n, r;
411                 ASSERT_ZERO(timeout_msg_recv(conn, type, &cookie_reply, &seqnum, &monotonic_ns, &realtime_ns));
412                 #define A(W,R) do { ASSERT_RETURN(prev_##W,R,W); prev_##W = W; } while (0);
413                         A(seqnum,<)
414                         A(monotonic_ns,<=)
415                         A(realtime_ns,<=)
416                 #undef A
417                 ASSERT_RETURN(first_cookie,<=,cookie_reply);
418                 cookie_reply -= first_cookie;
419                 n = cookie_reply % TIMEOUT_CONNECTION_COUNT;
420                 r = cookie_reply / TIMEOUT_CONNECTION_COUNT;
421                 ASSERT_RETURN(r,==,next_cookie[n]);
422                 ++next_cookie[n];
423         }
424         ASSERT_NO_PENDING(conn);
425         return 0;
426 }
427
428 static wur int kdbus_test_expected_reply_timeouts_or_quota(struct kdbus_test_env *env)
429 {
430         unsigned i, n;
431         uint64_t first_cookie = 0x1234abcd5678eeff;
432         struct kdbus_conn *conn;
433         struct kdbus_conn *connections[1+TIMEOUT_CONNECTION_COUNT];
434
435         ASSERT_NONZERO(conn = kdbus_hello(env->buspath, 0, NULL, 0));
436
437         for (i = 0; i < 1+TIMEOUT_CONNECTION_COUNT; i++)
438                 ASSERT_NONZERO(connections[i] = kdbus_hello(env->buspath, 0, NULL, 0));
439
440         _Static_assert(!(KDBUS_CONN_MAX_REQUESTS_PENDING%TIMEOUT_CONNECTION_COUNT), "KDBUS_CONN_MAX_REQUESTS_PENDING) not a multitude of TIMEOUT_CONNECTION_COUNT - quota test needs to be modified to reflect that");
441
442         /* Send messages to TIMEOUT_CONNECTION_COUNT different connections */
443         for (i = 0; i < TIMEOUT_CONNECTION_COUNT; i++)
444                 for (n = 0; n < TIMEOUTS_PER_CONNECTION; n++) {
445                         ASSERT_ZERO(kdbus_msg_send(conn, NULL, first_cookie + i + n*TIMEOUT_CONNECTION_COUNT,
446                                              KDBUS_MSG_EXPECT_REPLY,
447                                              200000000ULL /* 0.2s */, 0,
448                                              connections[i]->id));
449                         /* drain queue to avoid hitting KDBUS_CONN_MAX_MSGS */
450                         ASSERT_ZERO(kdbus_msg_recv(connections[i], NULL, NULL));
451                 }
452
453         sleep(1); /* just to wait and see if timeout logic somehow destabilizes the system */
454
455         ASSERT_ZERO(kdbus_test_expected_reply_validate_timeouts(conn, first_cookie, KDBUS_ITEM_REPLY_TIMEOUT));
456
457         for (i = 0; i < 1+TIMEOUT_CONNECTION_COUNT; i++)
458                 kdbus_conn_free(connections[i]);
459
460         kdbus_conn_free(conn);
461
462         return 0;
463 }
464
465 static wur int kdbus_test_expected_reply_quota(struct kdbus_test_env *env)
466 {
467         unsigned i, n;
468         uint64_t first_cookie = 0x5678eeff1234abcd;
469         struct kdbus_conn *conn;
470         struct kdbus_conn *connections[1+TIMEOUT_CONNECTION_COUNT];
471
472         ASSERT_NONZERO(conn = kdbus_hello(env->buspath, 0, NULL, 0));
473
474         for (i = 0; i < 1+TIMEOUT_CONNECTION_COUNT; i++)
475                 ASSERT_NONZERO(connections[i] = kdbus_hello(env->buspath, 0, NULL, 0));
476
477         /* Send messages to TIMEOUT_CONNECTION_COUNT different connections */
478         for (i = 0; i < TIMEOUT_CONNECTION_COUNT; i++)
479                 for (n = 0; n < KDBUS_CONN_MAX_REQUESTS_PENDING/TIMEOUT_CONNECTION_COUNT; n++) {
480                         ASSERT_ZERO(kdbus_msg_send(conn, NULL, first_cookie + i + n*TIMEOUT_CONNECTION_COUNT,
481                                              KDBUS_MSG_EXPECT_REPLY,
482                                              KDBUS_TIMEOUT_INFINITE, 0, /* massive timeout to make sure all pending replies do not timeout before quota check below */
483                                              connections[i]->id));
484                         /* drain queue to avoid hitting KDBUS_CONN_MAX_MSGS */
485                         ASSERT_ZERO(kdbus_msg_recv(connections[i], NULL, NULL));
486                 }
487
488         /*
489          * Now try to send a message to the last connection,
490          * if we have reached KDBUS_CONN_MAX_REQUESTS_PENDING
491          * no further requests are allowed
492          */
493         ASSERT_RETURN(-EMLINK,==,kdbus_msg_send(conn, NULL, first_cookie + TIMEOUT_CONNECTION_COUNT*TIMEOUTS_PER_CONNECTION, KDBUS_MSG_EXPECT_REPLY, 1000000000ULL, 0, connections[TIMEOUT_CONNECTION_COUNT]->id));
494
495         for (i = 0; i < 1+TIMEOUT_CONNECTION_COUNT; i++)
496                 kdbus_conn_free(connections[i]);
497
498         ASSERT_ZERO(kdbus_test_expected_reply_validate_timeouts(conn, first_cookie, KDBUS_ITEM_REPLY_DEAD));
499
500         kdbus_conn_free(conn);
501
502         return 0;
503 }
504
505 wur int kdbus_test_pool_quota(struct kdbus_test_env *env)
506 {
507         struct kdbus_conn *a, *b, *c;
508         struct kdbus_cmd_send cmd = {};
509         struct kdbus_item *item;
510         struct kdbus_msg *recv_msg;
511         struct kdbus_msg *msg;
512         uint64_t cookie = time(NULL);
513         uint64_t size;
514         unsigned int i;
515         char *payload;
516         int ret;
517
518         /* just a guard */
519         if (POOL_SIZE <= KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE ||
520             POOL_SIZE % KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE != 0)
521                 return 0;
522
523         payload = calloc(KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE, sizeof(char));
524         ASSERT_RETURN_VAL(payload,!=,NULL, -ENOMEM);
525
526         ASSERT_NONZERO(a = kdbus_hello(env->buspath, 0, NULL, 0));
527         ASSERT_NONZERO(b = kdbus_hello(env->buspath, 0, NULL, 0));
528         ASSERT_NONZERO(c = kdbus_hello(env->buspath, 0, NULL, 0));
529
530         size = sizeof(struct kdbus_msg);
531         size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
532
533         msg = malloc(size);
534         ASSERT_RETURN_VAL(msg,!=,NULL, -ENOMEM);
535
536         memset(msg, 0, size);
537         msg->size = size;
538         msg->src_id = a->id;
539         msg->dst_id = c->id;
540         msg->payload_type = KDBUS_PAYLOAD_DBUS;
541
542         item = msg->items;
543         item->type = KDBUS_ITEM_PAYLOAD_VEC;
544         item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
545         item->vec.address = (uintptr_t)payload;
546         item->vec.size = KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE;
547         item = KDBUS_ITEM_NEXT(item);
548
549         cmd.size = sizeof(cmd);
550         cmd.msg_address = (uintptr_t)msg;
551
552         /*
553          * Send 2097248 bytes, a user is only allowed to get 33% of half of
554          * the free space of the pool, the already used space is
555          * accounted as free space
556          */
557         size += KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE;
558         for (i = size; i < (POOL_SIZE / 2 / 3); i += size) {
559                 msg->cookie = cookie++;
560
561                 ret = kdbus_cmd_send(a->fd, &cmd);
562                 ASSERT_RETURN_VAL(ret,==,0, ret);
563         }
564
565         /* Try to get more than 33% */
566         msg->cookie = cookie++;
567         ASSERT_RETURN(-ENOBUFS,==,kdbus_cmd_send(a->fd, &cmd));
568
569         /* We still can pass small messages */
570         ASSERT_ZERO(kdbus_msg_send(b, NULL, cookie++, 0, 0, 0, c->id));
571
572         for (i = size; i < (POOL_SIZE / 2 / 3); i += size) {
573                 ASSERT_ZERO(kdbus_msg_recv(c, &recv_msg, NULL));
574                 ASSERT_RETURN(recv_msg->src_id,==,a->id);
575
576                 kdbus_msg_free(recv_msg);
577         }
578
579         ASSERT_ZERO(kdbus_msg_recv(c, &recv_msg, NULL));
580         ASSERT_RETURN(recv_msg->src_id,==,b->id);
581
582         kdbus_msg_free(recv_msg);
583
584         ASSERT_RETURN(-EAGAIN,==,kdbus_msg_recv(c, NULL, NULL));
585
586         free(msg);
587         free(payload);
588
589         kdbus_conn_free(c);
590         kdbus_conn_free(b);
591         kdbus_conn_free(a);
592
593         return 0;
594 }
595
596 wur int kdbus_test_message_quota(struct kdbus_test_env *env)
597 {
598         struct kdbus_conn *a, *b;
599         uint64_t cookie = 0;
600         unsigned i;
601
602         ASSERT_ZERO(kdbus_test_notify_kernel_quota(env));
603
604         ASSERT_ZERO(kdbus_test_pool_quota(env));
605
606         ASSERT_ZERO(kdbus_test_expected_reply_timeouts_or_quota(env));
607
608         ASSERT_ZERO(kdbus_test_expected_reply_quota(env));
609
610         a = kdbus_hello(env->buspath, 0, NULL, 0);
611         b = kdbus_hello(env->buspath, 0, NULL, 0);
612
613         ASSERT_RETURN((typeof(kdbus_fill_conn_queue(b, a->id, KDBUS_CONN_MAX_MSGS)))KDBUS_CONN_MAX_MSGS,==,kdbus_fill_conn_queue(b, a->id, KDBUS_CONN_MAX_MSGS));
614
615         ASSERT_RETURN(-ENOBUFS,==,kdbus_msg_send(b, NULL, ++cookie, 0, 0, 0, a->id));
616
617         for (i = 0; i < KDBUS_CONN_MAX_MSGS; ++i)
618                 ASSERT_ZERO(kdbus_msg_recv(a, NULL, NULL));
619
620         ASSERT_RETURN(-EAGAIN,==,kdbus_msg_recv(a, NULL, NULL));
621
622         ASSERT_RETURN((typeof(kdbus_fill_conn_queue(b, a->id, KDBUS_CONN_MAX_MSGS + 1)))KDBUS_CONN_MAX_MSGS,==,kdbus_fill_conn_queue(b, a->id, KDBUS_CONN_MAX_MSGS + 1));
623
624         ASSERT_RETURN(-ENOBUFS,==,kdbus_msg_send(b, NULL, ++cookie, 0, 0, 0, a->id));
625
626         kdbus_conn_free(a);
627         kdbus_conn_free(b);
628
629         return TEST_OK;
630 }
631
632 wur int kdbus_test_memory_access(struct kdbus_test_env *env)
633 {
634         struct kdbus_conn *a, *b;
635         struct kdbus_cmd_send cmd = {};
636         struct kdbus_item *item;
637         struct kdbus_msg *msg;
638         uint64_t test_addr = 0;
639         char line[256];
640         uint64_t size;
641         FILE *f;
642
643         /*
644          * Search in /proc/kallsyms for the address of a kernel symbol that
645          * should always be there, regardless of the config. Use that address
646          * in a PAYLOAD_VEC item and make sure it's inaccessible.
647          */
648
649         f = fopen("/proc/kallsyms", "r");
650         if (!f)
651                 return TEST_SKIP;
652
653         while (fgets(line, sizeof(line), f)) {
654                 char *s = line;
655
656                 if (!strsep(&s, " "))
657                         continue;
658
659                 if (!strsep(&s, " "))
660                         continue;
661
662                 if (!strncmp(s, "mutex_lock", 10)) {
663                         test_addr = strtoull(line, NULL, 16);
664                         break;
665                 }
666         }
667
668         fclose(f);
669
670         if (!test_addr)
671                 return TEST_SKIP;
672
673         ASSERT_NONZERO(a = kdbus_hello(env->buspath, 0, NULL, 0));
674         ASSERT_NONZERO(b = kdbus_hello(env->buspath, 0, NULL, 0));
675
676         size = sizeof(struct kdbus_msg);
677         size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
678
679         msg = alloca(size);
680         ASSERT_RETURN_VAL(msg,!=,NULL, -ENOMEM);
681
682         memset(msg, 0, size);
683         msg->size = size;
684         msg->src_id = a->id;
685         msg->dst_id = b->id;
686         msg->payload_type = KDBUS_PAYLOAD_DBUS;
687
688         item = msg->items;
689         item->type = KDBUS_ITEM_PAYLOAD_VEC;
690         item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
691         item->vec.address = test_addr;
692         item->vec.size = sizeof(void*);
693         item = KDBUS_ITEM_NEXT(item);
694
695         cmd.size = sizeof(cmd);
696         cmd.msg_address = (uintptr_t)msg;
697
698         ASSERT_RETURN(-EFAULT,==,kdbus_cmd_send(a->fd, &cmd));
699
700         kdbus_conn_free(b);
701         kdbus_conn_free(a);
702
703         return 0;
704 }