kdbus: test suite changed to common format
[platform/kernel/linux-rpi.git] / tools / testing / selftests / kdbus / kdbus-util.c
1 /*
2  * Copyright (C) 2013-2015 Daniel Mack
3  * Copyright (C) 2013-2015 Kay Sievers
4  * Copyright (C) 2014-2015 Djalal Harouni
5  *
6  * kdbus is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU Lesser General Public License as published by the
8  * Free Software Foundation; either version 2.1 of the License, or (at
9  * your option) any later version.
10  */
11
12 #include <stdio.h>
13 #include <stdarg.h>
14 #include <string.h>
15 #include <time.h>
16 #include <inttypes.h>
17 #include <fcntl.h>
18 #include <stdlib.h>
19 #include <stddef.h>
20 #include <unistd.h>
21 #include <stdint.h>
22 #include <stdbool.h>
23 #include <errno.h>
24 #include <assert.h>
25 #include <poll.h>
26 #include <grp.h>
27 #include <sys/capability.h>
28 #include <sys/mman.h>
29 #include <sys/stat.h>
30 #include <sys/time.h>
31 #include <linux/unistd.h>
32
33 #ifndef __NR_memfd_create
34   #ifdef __x86_64__
35     #define __NR_memfd_create 319
36   #elif defined __arm__
37     #define __NR_memfd_create 385
38   #else
39     #define __NR_memfd_create 356
40   #endif
41 #endif
42
43 #include "kdbus-api.h"
44 #include "kdbus-util.h"
45 #include "kdbus-enum.h"
46 #include "kdbus-test.h"
47
48 #ifndef F_ADD_SEALS
49 #define F_LINUX_SPECIFIC_BASE   1024
50 #define F_ADD_SEALS     (F_LINUX_SPECIFIC_BASE + 9)
51 #define F_GET_SEALS     (F_LINUX_SPECIFIC_BASE + 10)
52
53 #define F_SEAL_SEAL     0x0001  /* prevent further seals from being set */
54 #define F_SEAL_SHRINK   0x0002  /* prevent file from shrinking */
55 #define F_SEAL_GROW     0x0004  /* prevent file from growing */
56 #define F_SEAL_WRITE    0x0008  /* prevent writes */
57 #endif
58
59 /* maximum number of well-known names per connection */
60 #define KDBUS_CONN_MAX_NAMES                    256
61
62 int kdbus_util_verbose = true;
63
64 wur int kdbus_sysfs_get_parameter_mask(const char *path, uint64_t *mask)
65 {
66         int ret;
67         FILE *file;
68         unsigned long long value;
69
70         file = fopen(path, "r");
71         if (!file) {
72                 ret = -errno;
73                 kdbus_printf("--- error fopen(): %d (%m)\n", ret);
74                 return ret;
75         }
76
77         ret = fscanf(file, "%llu", &value);
78         if (ret != 1) {
79                 if (ferror(file))
80                         ret = -errno;
81                 else
82                         ret = -EIO;
83
84                 kdbus_printf("--- error fscanf(): %d\n", ret);
85                 fclose(file);
86                 return ret;
87         }
88
89         *mask = (uint64_t)value;
90
91         fclose(file);
92
93         return 0;
94 }
95
96 wur int kdbus_sysfs_set_parameter_mask(const char *path, uint64_t mask)
97 {
98         int ret;
99         FILE *file;
100
101         file = fopen(path, "w");
102         if (!file) {
103                 ret = -errno;
104                 kdbus_printf("--- error open(): %d (%m)\n", ret);
105                 return ret;
106         }
107
108         ret = fprintf(file, "%llu", (unsigned long long)mask);
109         if (ret <= 0) {
110                 ret = -EIO;
111                 kdbus_printf("--- error fprintf(): %d\n", ret);
112         }
113
114         fclose(file);
115
116         return ret > 0 ? 0 : ret;
117 }
118
119 wur int kdbus_create_bus(int control_fd, const char *name,
120                      uint64_t owner_meta, char **path)
121 {
122         struct {
123                 struct kdbus_cmd cmd;
124
125                 /* bloom size item */
126                 struct {
127                         uint64_t size;
128                         uint64_t type;
129                         struct kdbus_bloom_parameter bloom;
130                 } bp;
131
132                 /* owner metadata items */
133                 struct {
134                         uint64_t size;
135                         uint64_t type;
136                         uint64_t flags;
137                 } attach;
138
139                 /* name item */
140                 struct {
141                         uint64_t size;
142                         uint64_t type;
143                         char str[64];
144                 } name;
145         } bus_make;
146         int ret;
147
148         memset(&bus_make, 0, sizeof(bus_make));
149         bus_make.bp.size = sizeof(bus_make.bp);
150         bus_make.bp.type = KDBUS_ITEM_BLOOM_PARAMETER;
151         bus_make.bp.bloom.size = 64;
152         bus_make.bp.bloom.n_hash = 1;
153
154         snprintf(bus_make.name.str, sizeof(bus_make.name.str),
155                  "%u-%s", getuid(), name);
156
157         bus_make.attach.type = KDBUS_ITEM_ATTACH_FLAGS_SEND;
158         bus_make.attach.size = sizeof(bus_make.attach);
159         bus_make.attach.flags = owner_meta;
160
161         bus_make.name.type = KDBUS_ITEM_MAKE_NAME;
162         bus_make.name.size = KDBUS_ITEM_HEADER_SIZE +
163                              strlen(bus_make.name.str) + 1;
164
165         bus_make.cmd.flags = KDBUS_MAKE_ACCESS_WORLD;
166         bus_make.cmd.size = sizeof(bus_make.cmd) +
167                              bus_make.bp.size +
168                              bus_make.attach.size +
169                              bus_make.name.size;
170
171         kdbus_printf("Creating bus with name >%s< on control fd %d ...\n",
172                      name, control_fd);
173
174         ret = kdbus_cmd_bus_make(control_fd, &bus_make.cmd);
175         if (ret < 0) {
176                 kdbus_printf("--- error when making bus: %d (%m)\n", ret);
177                 return ret;
178         }
179
180         if (ret == 0 && path)
181                 *path = strdup(bus_make.name.str);
182
183         return ret;
184 }
185
186 wur struct kdbus_conn *
187 kdbus_hello(const char *path, uint64_t flags,
188             const struct kdbus_item *item, size_t item_size)
189 {
190         struct kdbus_cmd_free cmd_free = {};
191         int fd, ret;
192         struct {
193                 struct kdbus_cmd_hello hello;
194
195                 struct {
196                         uint64_t size;
197                         uint64_t type;
198                         char str[16];
199                 } conn_name;
200
201                 uint8_t extra_items[item_size];
202         } h;
203         struct kdbus_conn *conn;
204
205         memset(&h, 0, sizeof(h));
206
207         if (item_size > 0)
208                 memcpy(h.extra_items, item, item_size);
209
210         kdbus_printf("-- opening bus connection %s\n", path);
211         fd = open(path, O_RDWR|O_CLOEXEC);
212         if (fd < 0) {
213                 kdbus_printf("--- error %d (%m)\n", fd);
214                 return NULL;
215         }
216
217         h.hello.flags = flags | KDBUS_HELLO_ACCEPT_FD;
218         h.hello.attach_flags_send = _KDBUS_ATTACH_ALL;
219         h.hello.attach_flags_recv = _KDBUS_ATTACH_ALL;
220         h.conn_name.type = KDBUS_ITEM_CONN_DESCRIPTION;
221         strcpy(h.conn_name.str, "this-is-my-name");
222         h.conn_name.size = KDBUS_ITEM_HEADER_SIZE + strlen(h.conn_name.str) + 1;
223
224         h.hello.size = sizeof(h);
225         h.hello.pool_size = POOL_SIZE;
226
227         ret = kdbus_cmd_hello(fd, (struct kdbus_cmd_hello *) &h.hello);
228         if (ret < 0) {
229                 kdbus_printf("--- error when saying hello: %d (%m)\n", ret);
230                 return NULL;
231         }
232         kdbus_printf("-- Our peer ID for %s: %llu -- bus uuid: '%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x'\n",
233                      path, (unsigned long long)h.hello.id,
234                      h.hello.id128[0],  h.hello.id128[1],  h.hello.id128[2],
235                      h.hello.id128[3],  h.hello.id128[4],  h.hello.id128[5],
236                      h.hello.id128[6],  h.hello.id128[7],  h.hello.id128[8],
237                      h.hello.id128[9],  h.hello.id128[10], h.hello.id128[11],
238                      h.hello.id128[12], h.hello.id128[13], h.hello.id128[14],
239                      h.hello.id128[15]);
240
241         cmd_free.size = sizeof(cmd_free);
242         cmd_free.offset = h.hello.offset;
243         ret = kdbus_cmd_free(fd, &cmd_free);
244         if (ret < 0 && !(flags & KDBUS_HELLO_POLICY_HOLDER && -EOPNOTSUPP == ret)) { /* free not supported for policy holders */
245                 print("hello: KDBUS_CMD_FREE err(%d)\n", ret);
246                 return NULL;
247         }
248
249         conn = alloc(sizeof(*conn));
250         if (!conn) {
251                 kdbus_printf("unable to alloc()!?\n");
252                 return NULL;
253         }
254
255         conn->buf = mmap(NULL, POOL_SIZE, PROT_READ, MAP_SHARED, fd, 0);
256         if (conn->buf == MAP_FAILED) {
257                 free(conn);
258                 CLOSE(fd);
259                 kdbus_printf("--- error mmap (%m)\n");
260                 return NULL;
261         }
262
263         conn->fd = fd;
264         conn->id = h.hello.id;
265         _Static_assert((typeof(conn->attach_flags_recv))_KDBUS_ATTACH_ALL == _KDBUS_ATTACH_ALL, "kdbus_conn::attach_flags_recv too narrow for _KDBUS_ATTACH_ALL");
266         conn->attach_flags_recv = _KDBUS_ATTACH_ALL;
267         return conn;
268 }
269
270 wur struct kdbus_conn *
271 kdbus_hello_registrar(const char *path, const char *name,
272                       const struct kdbus_policy_access *access,
273                       size_t num_access, uint64_t flags)
274 {
275         struct kdbus_item *item, *items;
276         size_t i, size;
277
278         size = KDBUS_ITEM_SIZE(strlen(name) + 1) +
279                 num_access * KDBUS_ITEM_SIZE(sizeof(*access));
280
281         items = alloca(size);
282
283         item = items;
284         item->size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1;
285         item->type = KDBUS_ITEM_NAME;
286         strcpy(item->str, name);
287         item = KDBUS_ITEM_NEXT(item);
288
289         for (i = 0; i < num_access; i++) {
290                 item->size = KDBUS_ITEM_HEADER_SIZE +
291                              sizeof(struct kdbus_policy_access);
292                 item->type = KDBUS_ITEM_POLICY_ACCESS;
293
294                 item->policy_access.type = access[i].type;
295                 item->policy_access.access = access[i].access;
296                 item->policy_access.id = access[i].id;
297
298                 item = KDBUS_ITEM_NEXT(item);
299         }
300
301         return kdbus_hello(path, flags, items, size);
302 }
303
304 wur struct kdbus_conn *kdbus_hello_activator(const char *path, const char *name,
305                                    const struct kdbus_policy_access *access,
306                                    size_t num_access)
307 {
308         return kdbus_hello_registrar(path, name, access, num_access,
309                                      KDBUS_HELLO_ACTIVATOR);
310 }
311
312 wur bool kdbus_item_in_message(struct kdbus_msg *msg, uint64_t type)
313 {
314         const struct kdbus_item *item;
315
316         KDBUS_ITEM_FOREACH(item, msg, items)
317                 if (item->type == type)
318                         return true;
319
320         return false;
321 }
322
323 wur int kdbus_bus_creator_info(struct kdbus_conn *conn,
324                            uint64_t flags,
325                            uint64_t *offset)
326 {
327         struct kdbus_cmd_info *cmd;
328         size_t size = sizeof(*cmd);
329         int ret;
330
331         cmd = alloca(size);
332         memset(cmd, 0, size);
333         cmd->size = size;
334         cmd->attach_flags = flags;
335
336         ret = kdbus_cmd_bus_creator_info(conn->fd, cmd);
337         if (ret < 0) {
338                 kdbus_printf("--- error when requesting info: %d (%m)\n", ret);
339                 return ret;
340         }
341
342         if (offset)
343                 *offset = cmd->offset;
344         else
345                 ret = kdbus_free(conn, cmd->offset);
346
347         return ret;
348 }
349
350 wur static int kdbus_info_verify(struct kdbus_info *info, unsigned attach_flags);
351
352 wur int kdbus_conn_info(struct kdbus_conn *conn, uint64_t id,
353                     const char *name, uint64_t flags,
354                     uint64_t *offset)
355 {
356         struct kdbus_cmd_info *cmd;
357         size_t size = sizeof(*cmd);
358         size_t full_size;
359         struct kdbus_info *info;
360         int ret;
361
362         /*print("call prepared 0\n");*/
363
364         if (name)
365                 size += KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1;
366
367         /*print("call prepared 1\n");*/
368
369         full_size = KDBUS_ALIGN8(size) + 1000;
370
371         /*print("call prepared 2\n");*/
372
373         cmd = malloc(full_size);
374         if (!cmd)
375                 return -ENOMEM;
376         /*print("call prepared 3\n");*/
377         memset(cmd, 0, full_size);
378         /*print("call prepared 4\n");*/
379         cmd->size = size;
380         /*print("call prepared 5\n");*/
381         cmd->attach_flags = flags;
382         /*print("call prepared 6\n");*/
383
384         if (name) {
385                 /*print("call prepared 7\n");*/
386                 cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1;
387                 /*print("call prepared 8\n");*/
388                 cmd->items[0].type = KDBUS_ITEM_NAME;
389                 /*print("call prepared 9 cmd(%p) cmd->items[0].str(%p) full_size(%u) len(%u) name(%s)\n", cmd, cmd->items[0].str, (unsigned)full_size, (unsigned)strlen(name), name);*/
390
391                 /* tizen 3.0 strcpy reports buffer overflow for no apparent reason - memcpy doesn't */
392                 memcpy(cmd->items[0].str, name, strlen(name));
393                 /*strcpy(cmd->items[0].str, name);*/
394         } else {
395                 /*print("call prepared 10\n");*/
396                 cmd->id = id;
397         }
398
399         /*print("call prepared 11\n");*/
400
401         ret = kdbus_cmd_conn_info(conn->fd, cmd);
402         if (ret < 0) {
403                 kdbus_printf("--- error when requesting info: %d (%m)\n", ret);
404                 free(cmd);
405                 return ret;
406         }
407
408         info = (struct kdbus_info *) (conn->buf + cmd->offset);
409         if (KDBUS_ALIGN8(info->size) != cmd->info_size) {
410                 kdbus_printf("%s(): size mismatch: %d != %d\n", __func__,
411                                 (int) info->size, (int) cmd->info_size);
412                 free(cmd);
413                 return -EIO;
414         }
415
416         if (offset) {
417                 *offset = cmd->offset;
418                 ASSERT_ZERO(kdbus_info_verify(info, flags));
419         } else
420                 ret = kdbus_free(conn, cmd->offset);
421
422         free(cmd);
423         return ret;
424 }
425
426 void kdbus_conn_free(struct kdbus_conn *conn)
427 {
428         if (!conn)
429                 return;
430
431         if (conn->buf && munmap(conn->buf, POOL_SIZE))
432                 fail("munmap(%p) err(%d)", conn->buf, errno);
433
434         if (conn->fd >= 0 && close(conn->fd))
435                 fail("close(%d) err(%d)", conn->fd, errno);
436
437         free(conn);
438 }
439
440 wur int sys_memfd_create(const char *name, __u64 size)
441 {
442         int ret, fd;
443
444         fd = syscall(__NR_memfd_create, name, 2/*MFD_ALLOW_SEALING*/);
445         if (fd < 0)
446                 return fd;
447
448         ret = ftruncate(fd, size);
449         if (ret < 0) {
450                 CLOSE(fd);
451                 return ret;
452         }
453
454         return fd;
455 }
456
457 wur int sys_memfd_seal_set(int fd)
458 {
459         return fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK |
460                          F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL);
461 }
462
463 wur off_t sys_memfd_get_size(int fd, off_t *size)
464 {
465         struct stat stat;
466         int ret;
467
468         ret = fstat(fd, &stat);
469         if (ret < 0) {
470                 kdbus_printf("stat() failed: %m\n");
471                 return ret;
472         }
473
474         *size = stat.st_size;
475         return 0;
476 }
477
478 static wur int __kdbus_msg_send(const struct kdbus_conn *conn,
479                             const char *name,
480                             uint64_t cookie,
481                             uint64_t flags,
482                             uint64_t timeout,
483                             int64_t priority,
484                             uint64_t dst_id,
485                             uint64_t cmd_flags,
486                             int cancel_fd)
487 {
488         struct kdbus_cmd_send *cmd = NULL;
489         struct kdbus_msg *msg = NULL;
490         const char ref1[1024 * 128 + 3] = "0123456789_0";
491         const char ref2[] = "0123456789_1";
492         struct kdbus_item *item;
493         struct timespec now;
494         uint64_t size;
495         int memfd = -1;
496         int ret;
497
498         size = sizeof(*msg) + 3 * KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
499
500         if (dst_id == KDBUS_DST_ID_BROADCAST)
501                 size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64;
502         else {
503                 memfd = sys_memfd_create("my-name-is-nice", 1024 * 1024);
504                 if (memfd < 0) {
505                         kdbus_printf("failed to create memfd: %m\n");
506                         return memfd;
507                 }
508
509                 if (write(memfd, "kdbus memfd 1234567", 19) != 19) {
510                         ret = -errno;
511                         kdbus_printf("writing to memfd failed: %m\n");
512                         goto out;
513                 }
514
515                 ret = sys_memfd_seal_set(memfd);
516                 if (ret < 0) {
517                         ret = -errno;
518                         kdbus_printf("memfd sealing failed: %m\n");
519                         goto out;
520                 }
521
522                 size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_memfd));
523         }
524
525         if (name)
526                 size += KDBUS_ITEM_SIZE(strlen(name) + 1);
527
528         msg = alloc(size);
529         if (!msg) {
530                 ret = -errno;
531                 kdbus_printf("unable to alloc()!?\n");
532                 goto out;
533         }
534
535         if (dst_id == KDBUS_DST_ID_BROADCAST)
536                 flags |= KDBUS_MSG_SIGNAL;
537
538         memset(msg, 0, size);
539         msg->flags = flags;
540         msg->priority = priority;
541         msg->size = size;
542         msg->src_id = conn->id;
543         msg->dst_id = name ? 0 : dst_id;
544         msg->cookie = cookie;
545         msg->payload_type = KDBUS_PAYLOAD_DBUS;
546
547         if (timeout) {
548                 ret = clock_gettime(CLOCK_MONOTONIC_COARSE, &now);
549                 if (ret < 0)
550                         goto out;
551
552                 msg->timeout_ns = now.tv_sec * 1000000000ULL +
553                                   now.tv_nsec + timeout;
554         }
555
556         item = msg->items;
557
558         if (name) {
559                 item->type = KDBUS_ITEM_DST_NAME;
560                 item->size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1;
561                 strcpy(item->str, name);
562                 item = KDBUS_ITEM_NEXT(item);
563         }
564
565         item->type = KDBUS_ITEM_PAYLOAD_VEC;
566         item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
567         item->vec.address = (uintptr_t)&ref1;
568         item->vec.size = sizeof(ref1);
569         item = KDBUS_ITEM_NEXT(item);
570
571         /* data padding for ref1 */
572         item->type = KDBUS_ITEM_PAYLOAD_VEC;
573         item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
574         item->vec.address = (uintptr_t)NULL;
575         item->vec.size =  KDBUS_ALIGN8(sizeof(ref1)) - sizeof(ref1);
576         item = KDBUS_ITEM_NEXT(item);
577
578         item->type = KDBUS_ITEM_PAYLOAD_VEC;
579         item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
580         item->vec.address = (uintptr_t)&ref2;
581         item->vec.size = sizeof(ref2);
582         item = KDBUS_ITEM_NEXT(item);
583
584         if (dst_id == KDBUS_DST_ID_BROADCAST) {
585                 item->type = KDBUS_ITEM_BLOOM_FILTER;
586                 item->size = KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64;
587                 item->bloom_filter.generation = 0;
588         } else {
589                 item->type = KDBUS_ITEM_PAYLOAD_MEMFD;
590                 item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_memfd);
591                 item->memfd.size = 16;
592                 item->memfd.fd = memfd;
593         }
594         item = KDBUS_ITEM_NEXT(item);
595
596         size = sizeof(*cmd);
597         if (cancel_fd != -1)
598                 size += KDBUS_ITEM_SIZE(sizeof(cancel_fd));
599
600         cmd = alloc(size);
601         if (!cmd) {
602                 ret = -errno;
603                 kdbus_printf("unable to alloc()!?\n");
604                 goto out;
605         }
606
607         cmd->size = size;
608         cmd->flags = cmd_flags;
609         cmd->msg_address = (uintptr_t)msg;
610
611         item = cmd->items;
612
613         if (cancel_fd != -1) {
614                 item->type = KDBUS_ITEM_CANCEL_FD;
615                 item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(cancel_fd);
616                 item->fds[0] = cancel_fd;
617                 item = KDBUS_ITEM_NEXT(item);
618         }
619
620         ret = kdbus_cmd_send(conn->fd, cmd);
621         if (ret < 0) {
622                 kdbus_printf("error sending message: %d (%m)\n", ret);
623                 goto out;
624         }
625
626         if (cmd_flags & KDBUS_SEND_SYNC_REPLY) {
627                 struct kdbus_msg *reply;
628                 int dumpret;
629
630                 kdbus_printf("SYNC REPLY @offset %llu:\n", cmd->reply.offset);
631                 reply = (struct kdbus_msg *)(conn->buf + cmd->reply.offset);
632                 dumpret = kdbus_msg_dump(reply);
633
634                 kdbus_msg_free(reply);
635
636                 ret = kdbus_free(conn, cmd->reply.offset);
637                 if (!ret)
638                         ret = dumpret;
639         }
640
641 out:
642         free(msg);
643         free(cmd);
644
645         if (memfd >= 0)
646                 CLOSE(memfd);
647
648         return ret < 0 ? ret : 0;
649 }
650
651 wur int kdbus_msg_send(const struct kdbus_conn *conn, const char *name,
652                    uint64_t cookie, uint64_t flags, uint64_t timeout,
653                    int64_t priority, uint64_t dst_id)
654 {
655         return __kdbus_msg_send(conn, name, cookie, flags, timeout, priority,
656                                 dst_id, 0, -1);
657 }
658
659 wur int kdbus_msg_send_sync(const struct kdbus_conn *conn, const char *name,
660                         uint64_t cookie, uint64_t flags, uint64_t timeout,
661                         int64_t priority, uint64_t dst_id, int cancel_fd)
662 {
663         return __kdbus_msg_send(conn, name, cookie, flags, timeout, priority,
664                                 dst_id, KDBUS_SEND_SYNC_REPLY, cancel_fd);
665 }
666
667 wur int kdbus_msg_send_reply(const struct kdbus_conn *conn,
668                          uint64_t reply_cookie,
669                          uint64_t dst_id)
670 {
671         struct kdbus_cmd_send cmd = {};
672         struct kdbus_msg *msg;
673         const char ref1[1024 * 128 + 3] = "0123456789_0";
674         struct kdbus_item *item;
675         uint64_t size;
676         int ret;
677
678         size = sizeof(struct kdbus_msg);
679         size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
680
681         msg = alloc(size);
682         if (!msg) {
683                 kdbus_printf("unable to alloc()!?\n");
684                 return -ENOMEM;
685         }
686
687         memset(msg, 0, size);
688         msg->size = size;
689         msg->src_id = conn->id;
690         msg->dst_id = dst_id;
691         msg->cookie_reply = reply_cookie;
692         msg->payload_type = KDBUS_PAYLOAD_DBUS;
693
694         item = msg->items;
695
696         item->type = KDBUS_ITEM_PAYLOAD_VEC;
697         item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
698         item->vec.address = (uintptr_t)&ref1;
699         item->vec.size = sizeof(ref1);
700         item = KDBUS_ITEM_NEXT(item);
701
702         cmd.size = sizeof(cmd);
703         cmd.msg_address = (uintptr_t)msg;
704
705         ret = kdbus_cmd_send(conn->fd, &cmd);
706         if (ret < 0)
707                 kdbus_printf("error sending message: %d (%m)\n", ret);
708
709         free(msg);
710
711         return ret;
712 }
713
714 static wur char *msg_id(uint64_t id, char *buf)
715 {
716         if (id == 0)
717                 return "KERNEL";
718         if (id == ~0ULL)
719                 return "BROADCAST";
720         sprintf(buf, "%llu", (unsigned long long)id);
721         return buf;
722 }
723
724 wur int kdbus_msg_dump(const struct kdbus_msg *msg) {
725         const struct kdbus_item *item = msg->items;
726         char buf_src[32];
727         char buf_dst[32];
728         uint64_t timeout = 0;
729         uint64_t cookie_reply = 0;
730         int ret = 0;
731
732         if (msg->flags & KDBUS_MSG_EXPECT_REPLY)
733                 timeout = msg->timeout_ns;
734         else
735                 cookie_reply = msg->cookie_reply;
736
737         kdbus_printf("MESSAGE(%p): %s (%llu bytes) flags=0x%08llx, %s â†’ %s, "
738                      "cookie=%llu, timeout=%llu cookie_reply=%llu priority=%lli\n",
739                 msg,
740                 enum_PAYLOAD(msg->payload_type), (unsigned long long)msg->size,
741                 (unsigned long long)msg->flags,
742                 msg_id(msg->src_id, buf_src), msg_id(msg->dst_id, buf_dst),
743                 (unsigned long long)msg->cookie, (unsigned long long)timeout,
744                 (unsigned long long)cookie_reply, (long long)msg->priority);
745
746         KDBUS_ITEM_FOREACH(item, msg, items) {
747                 if (item->size < KDBUS_ITEM_HEADER_SIZE) {
748                         kdbus_printf("  +%s (%llu bytes) invalid data record\n",
749                                      enum_MSG(item->type), item->size);
750                         return -EINVAL;
751                 }
752
753                 switch (item->type) {
754                 case KDBUS_ITEM_PAYLOAD_OFF: {
755                         char *s;
756
757                         if (item->vec.offset == ~0ULL)
758                                 s = "[\\0-bytes]";
759                         else
760                                 s = (char *)msg + item->vec.offset;
761
762                         kdbus_printf("  +%s (%llu bytes) off=%llu size=%llu '%s'\n",
763                                enum_MSG(item->type), item->size,
764                                (unsigned long long)item->vec.offset,
765                                (unsigned long long)item->vec.size, s);
766                         break;
767                 }
768
769                 case KDBUS_ITEM_FDS: {
770                         int i, n = (item->size - KDBUS_ITEM_HEADER_SIZE) /
771                                         sizeof(int);
772
773                         kdbus_printf("  +%s (%llu bytes, %d fds)\n",
774                                enum_MSG(item->type), item->size, n);
775
776                         for (i = 0; i < n; i++)
777                                 kdbus_printf("    fd[%d] = %d\n",
778                                              i, item->fds[i]);
779
780                         break;
781                 }
782
783                 case KDBUS_ITEM_PAYLOAD_MEMFD: {
784                         char *buf;
785                         off_t size;
786
787                         buf = mmap(NULL, item->memfd.size, PROT_READ,
788                                    MAP_PRIVATE, item->memfd.fd, 0);
789                         if (buf == MAP_FAILED) {
790                                 kdbus_printf("mmap() fd=%i size=%llu failed: %m\n",
791                                              item->memfd.fd, item->memfd.size);
792                                 break;
793                         }
794
795                         if (sys_memfd_get_size(item->memfd.fd, &size) < 0) {
796                                 kdbus_printf("KDBUS_CMD_MEMFD_SIZE_GET failed: %m\n");
797                                 break;
798                         }
799
800                         kdbus_printf("  +%s (%llu bytes) fd=%i size=%llu filesize=%llu '0x%llx'\n",
801                                enum_MSG(item->type), item->size, item->memfd.fd,
802                                (unsigned long long)item->memfd.size,
803                                (unsigned long long)size, (unsigned long long)(size >= 8 ? *(unsigned long long *)buf : size >= 4 ? *(unsigned *)buf : *buf));
804                         munmap(buf, item->memfd.size);
805                         break;
806                 }
807
808                 case KDBUS_ITEM_CREDS:
809                         kdbus_printf("  +%s (%llu bytes) uid=%lld, euid=%lld, suid=%lld, fsuid=%lld, "
810                                                         "gid=%lld, egid=%lld, sgid=%lld, fsgid=%lld\n",
811                                 enum_MSG(item->type), item->size,
812                                 item->creds.uid, item->creds.euid,
813                                 item->creds.suid, item->creds.fsuid,
814                                 item->creds.gid, item->creds.egid,
815                                 item->creds.sgid, item->creds.fsgid);
816                         break;
817
818                 case KDBUS_ITEM_PIDS:
819                         kdbus_printf("  +%s (%llu bytes) pid=%lld, tid=%lld, ppid=%lld\n",
820                                 enum_MSG(item->type), item->size,
821                                 item->pids.pid, item->pids.tid,
822                                 item->pids.ppid);
823                         break;
824
825                 case KDBUS_ITEM_AUXGROUPS: {
826                         int i, n;
827
828                         kdbus_printf("  +%s (%llu bytes)\n",
829                                      enum_MSG(item->type), item->size);
830                         n = (item->size - KDBUS_ITEM_HEADER_SIZE) /
831                                 sizeof(uint64_t);
832
833                         for (i = 0; i < n; i++)
834                                 kdbus_printf("    gid[%d] = %lld\n",
835                                              i, item->data64[i]);
836                         break;
837                 }
838
839                 case KDBUS_ITEM_NAME:
840                 case KDBUS_ITEM_PID_COMM:
841                 case KDBUS_ITEM_TID_COMM:
842                 case KDBUS_ITEM_EXE:
843                 case KDBUS_ITEM_CGROUP:
844                 case KDBUS_ITEM_SECLABEL:
845                 case KDBUS_ITEM_DST_NAME:
846                 case KDBUS_ITEM_CONN_DESCRIPTION:
847                         kdbus_printf("  +%s (%llu bytes) '%s' (%zu)\n",
848                                      enum_MSG(item->type), item->size,
849                                      item->str, strlen(item->str));
850                         break;
851
852                 case KDBUS_ITEM_OWNED_NAME: {
853                         kdbus_printf("  +%s (%llu bytes) '%s' (%zu) flags=0x%08llx\n",
854                                      enum_MSG(item->type), item->size,
855                                      item->name.name, strlen(item->name.name),
856                                      item->name.flags);
857                         break;
858                 }
859
860                 case KDBUS_ITEM_CMDLINE: {
861                         size_t size = item->size - KDBUS_ITEM_HEADER_SIZE;
862                         const char *str = item->str;
863                         int count = 0;
864
865                         kdbus_printf("  +%s (%llu bytes) ",
866                                      enum_MSG(item->type), item->size);
867                         while (size) {
868                                 kdbus_printf("'%s' ", str);
869                                 size -= strlen(str) + 1;
870                                 str += strlen(str) + 1;
871                                 count++;
872                         }
873
874                         kdbus_printf("(%d string%s)\n",
875                                      count, (count == 1) ? "" : "s");
876                         break;
877                 }
878
879                 case KDBUS_ITEM_AUDIT:
880                         kdbus_printf("  +%s (%llu bytes) loginuid=%u sessionid=%u\n",
881                                enum_MSG(item->type), item->size,
882                                item->audit.loginuid, item->audit.sessionid);
883                         break;
884
885                 case KDBUS_ITEM_CAPS: {
886                         const uint32_t *cap;
887                         int n, i;
888
889                         kdbus_printf("  +%s (%llu bytes) len=%llu bytes, last_cap %d\n",
890                                      enum_MSG(item->type), item->size,
891                                      (unsigned long long)item->size -
892                                         KDBUS_ITEM_HEADER_SIZE,
893                                      (int) item->caps.last_cap);
894
895                         cap = item->caps.caps;
896                         n = (item->size - offsetof(struct kdbus_item, caps.caps))
897                                 / 4 / sizeof(uint32_t);
898
899                         kdbus_printf("    CapInh=");
900                         for (i = 0; i < n; i++)
901                                 kdbus_printf("%08x", cap[(0 * n) + (n - i - 1)]);
902
903                         kdbus_printf(" CapPrm=");
904                         for (i = 0; i < n; i++)
905                                 kdbus_printf("%08x", cap[(1 * n) + (n - i - 1)]);
906
907                         kdbus_printf(" CapEff=");
908                         for (i = 0; i < n; i++)
909                                 kdbus_printf("%08x", cap[(2 * n) + (n - i - 1)]);
910
911                         kdbus_printf(" CapBnd=");
912                         for (i = 0; i < n; i++)
913                                 kdbus_printf("%08x", cap[(3 * n) + (n - i - 1)]);
914                         kdbus_printf("\n");
915                         break;
916                 }
917
918                 case KDBUS_ITEM_TIMESTAMP:
919                         kdbus_printf("  +%s (%llu bytes) seq=%llu realtime=%lluns monotonic=%lluns\n",
920                                enum_MSG(item->type), item->size,
921                                (unsigned long long)item->timestamp.seqnum,
922                                (unsigned long long)item->timestamp.realtime_ns,
923                                (unsigned long long)item->timestamp.monotonic_ns);
924                         break;
925
926                 case KDBUS_ITEM_REPLY_TIMEOUT:
927                         kdbus_printf("  +%s (%llu bytes) cookie=%llu\n",
928                                enum_MSG(item->type), item->size,
929                                msg->cookie_reply);
930                         break;
931
932                 case KDBUS_ITEM_NAME_ADD:
933                 case KDBUS_ITEM_NAME_REMOVE:
934                 case KDBUS_ITEM_NAME_CHANGE:
935                         kdbus_printf("  +%s (%llu bytes) '%s', old id=%lld, now id=%lld, old_flags=0x%llx new_flags=0x%llx\n",
936                                 enum_MSG(item->type),
937                                 (unsigned long long) item->size,
938                                 item->name_change.name,
939                                 item->name_change.old_id.id,
940                                 item->name_change.new_id.id,
941                                 item->name_change.old_id.flags,
942                                 item->name_change.new_id.flags);
943                         break;
944
945                 case KDBUS_ITEM_ID_ADD:
946                 case KDBUS_ITEM_ID_REMOVE:
947                         kdbus_printf("  +%s (%llu bytes) id=%llu flags=%llu\n",
948                                enum_MSG(item->type),
949                                (unsigned long long) item->size,
950                                (unsigned long long) item->id_change.id,
951                                (unsigned long long) item->id_change.flags);
952                         break;
953
954                 default:
955                         kdbus_printf("  +%s (%llu bytes)\n",
956                                      enum_MSG(item->type), item->size);
957                         break;
958                 }
959         }
960
961         if ((char *)item - ((char *)msg + msg->size) >= 8) {
962                 kdbus_printf("invalid padding at end of message\n");
963                 ret = -EINVAL;
964         }
965
966         kdbus_printf("\n");
967
968         return ret;
969 }
970
971 void kdbus_msg_free(struct kdbus_msg *msg)
972 {
973         const struct kdbus_item *item;
974         int nfds, i;
975
976         if (!msg)
977                 return;
978
979         KDBUS_ITEM_FOREACH(item, msg, items) {
980                 switch (item->type) {
981                 /* close all memfds */
982                 case KDBUS_ITEM_PAYLOAD_MEMFD:
983                         if (-1 != item->memfd.fd)
984                                 CLOSE(item->memfd.fd);
985                         break;
986                 case KDBUS_ITEM_FDS:
987                         nfds = (item->size - KDBUS_ITEM_HEADER_SIZE) /
988                                 sizeof(int);
989
990                         for (i = 0; i < nfds; i++)
991                                 if (-1 != item->fds[i])
992                                         CLOSE(item->fds[i]);
993
994                         break;
995                 }
996         }
997 }
998
999 wur static int verify_padding(char const *b, unsigned off)
1000 {
1001         while (off%8) {
1002                 ASSERT_ZERO((unsigned)b[off]);
1003                 ++off;
1004         }
1005         return 0;
1006 }
1007
1008 wur static int verify_string(unsigned size, char const *s)
1009 {
1010         unsigned len;
1011         ASSERT_NONZERO(size);
1012         len = strlen(s)+1;
1013         ASSERT_RETURN(len,==,size);
1014         ASSERT_ZERO(verify_padding(s, len));
1015         return 0;
1016 }
1017 wur static int verify_string_array(unsigned size, char const *s)
1018 {
1019         unsigned off=0;
1020         ASSERT_NONZERO(size);
1021         while (size) {
1022                 unsigned len = strlen(s+off);
1023                 if (!len)
1024                         break;
1025                 ++len;
1026                 ASSERT_RETURN(len,<=,size);
1027                 size -= len;
1028                 off += len;
1029         }
1030         ASSERT_ZERO(verify_padding(s, off));
1031         return 0;
1032 }
1033
1034 #define VERIFY_DECL\
1035         const struct kdbus_item *item;\
1036         unsigned item_count[14];\
1037         unsigned i;\
1038         memset(item_count, 0, sizeof(item_count));
1039 #define VERIFY_DECL_INLOOP\
1040         unsigned idx;\
1041         unsigned size;\
1042         ASSERT_RETURN(item->size,>=,2*sizeof(uint64_t));\
1043         ASSERT_RETURN((unsigned)item->size,==,item->size);\
1044         size = item->size - 2*sizeof(uint64_t);
1045 #define VERIFY_META_CASES\
1046         /* metadata */\
1047         case KDBUS_ITEM_CREDS:\
1048                 ASSERT_RETURN(size,==,sizeof(struct kdbus_creds));\
1049                 break;\
1050         case KDBUS_ITEM_PIDS:\
1051                 ASSERT_RETURN(size,==,sizeof(struct kdbus_pids));\
1052                 break;\
1053         case KDBUS_ITEM_AUDIT:\
1054                 ASSERT_RETURN(size,==,sizeof(struct kdbus_audit));\
1055                 break;\
1056         case KDBUS_ITEM_AUXGROUPS:\
1057         case KDBUS_ITEM_CAPS:\
1058                 ASSERT_ZERO(size%sizeof(uint32_t));\
1059                 break;\
1060         case KDBUS_ITEM_OWNED_NAME:\
1061                 ASSERT_ZERO(verify_string(size-offsetof(typeof(item->name), name), item->name.name));\
1062                 break;\
1063         case KDBUS_ITEM_TID_COMM:\
1064         case KDBUS_ITEM_PID_COMM:\
1065         case KDBUS_ITEM_EXE:\
1066         case KDBUS_ITEM_CGROUP:\
1067         case KDBUS_ITEM_SECLABEL:\
1068         case KDBUS_ITEM_CONN_DESCRIPTION:\
1069                 ASSERT_ZERO(verify_string(size, item->str));\
1070                 break;\
1071         case KDBUS_ITEM_CMDLINE:\
1072                 ASSERT_ZERO(verify_string_array(size, item->str));\
1073                 break;
1074 #define VERIFY_META do {\
1075         ASSERT_RETURN(item->type,>=,(uint64_t)_KDBUS_ITEM_ATTACH_BASE);\
1076         idx = item->type - _KDBUS_ITEM_ATTACH_BASE;\
1077         ASSERT_RETURN(idx,<,sizeof(item_count)/sizeof(*item_count));\
1078         ASSERT_NONZERO(attach_flags & 1<<idx);\
1079         if (KDBUS_ITEM_OWNED_NAME != item->type)\
1080                 ASSERT_ZERO(item_count[idx]);\
1081         else\
1082                 ASSERT_RETURN(item_count[idx],<,(uint64_t)KDBUS_CONN_MAX_NAMES);\
1083         ++item_count[idx];\
1084 } while (0)
1085 #define VERIFY_FINAL_ASSERT do {\
1086         for (i=0; i<TABSIZE(item_count); ++i) {\
1087                 if (attach_flags & 1<<i &&\
1088                         KDBUS_ITEM_TIMESTAMP-_KDBUS_ITEM_ATTACH_BASE != i && /* nameless connections happen */\
1089                         KDBUS_ITEM_OWNED_NAME-_KDBUS_ITEM_ATTACH_BASE != i && /* nameless connections happen */\
1090                         KDBUS_ITEM_CONN_DESCRIPTION-_KDBUS_ITEM_ATTACH_BASE != i && /* defining a connection description is optional */\
1091                         KDBUS_ITEM_AUDIT-_KDBUS_ITEM_ATTACH_BASE != i) /* missing if CONFIG_AUDITSYSCALL not defined */\
1092                         if (!item_count[i]) ASSERT_ZERO(i+1); /*hack to make i visible*/\
1093         }\
1094 } while (0)
1095
1096 wur static int kdbus_info_verify(struct kdbus_info *info, unsigned attach_flags)
1097 {
1098         VERIFY_DECL;
1099
1100         KDBUS_ITEM_FOREACH(item, info, items) {
1101                 VERIFY_DECL_INLOOP;
1102                 switch(item->type) {
1103                         VERIFY_META_CASES;
1104                         default: ASSERT_ZERO(item->type ?: (uint64_t)-1);
1105                 }
1106                 VERIFY_META;
1107         }
1108
1109         VERIFY_FINAL_ASSERT;
1110
1111         return 0;
1112 }
1113
1114 wur static int kdbus_msg_verify(struct kdbus_msg *msg, unsigned attach_flags)
1115 {
1116         bool user = false;
1117
1118         VERIFY_DECL;
1119
1120         if (msg->payload_type != KDBUS_PAYLOAD_KERNEL) {
1121                 ASSERT_RETURN(msg->payload_type,==,KDBUS_PAYLOAD_DBUS);
1122                 user = true;
1123         }
1124
1125         KDBUS_ITEM_FOREACH(item, msg, items) {
1126                 VERIFY_DECL_INLOOP;
1127
1128                 switch(item->type) {
1129                         case KDBUS_ITEM_TIMESTAMP:
1130                                 ASSERT_RETURN(size,==,sizeof(struct kdbus_timestamp));
1131                                 break;
1132                         VERIFY_META_CASES;
1133
1134                         /* user items */
1135                         case KDBUS_ITEM_PAYLOAD_OFF:
1136                                 ASSERT_NONZERO(user);
1137                                 ASSERT_RETURN(size,==,sizeof(struct kdbus_vec));
1138                                 continue;
1139                         case KDBUS_ITEM_PAYLOAD_MEMFD:
1140                                 ASSERT_NONZERO(user);
1141                                 ASSERT_RETURN(size,==,sizeof(struct kdbus_memfd));
1142                                 continue;
1143                         case KDBUS_ITEM_FDS:
1144                                 ASSERT_NONZERO(user);
1145                                 ASSERT_ZERO(size%sizeof(int));
1146                                 continue;
1147                         case KDBUS_ITEM_DST_NAME:
1148                                 ASSERT_NONZERO(user);
1149                                 ASSERT_ZERO(verify_string(size, item->str));
1150                                 continue;
1151
1152                         /* kernel items */
1153                         case KDBUS_ITEM_NAME_ADD:
1154                         case KDBUS_ITEM_NAME_REMOVE:
1155                         case KDBUS_ITEM_NAME_CHANGE:
1156                                 ASSERT_ZERO(user);
1157                                 ASSERT_RETURN(size,>=,sizeof(struct kdbus_notify_name_change));
1158                                 ASSERT_ZERO(verify_string(size-sizeof(struct kdbus_notify_name_change), item->name_change.name));
1159                                 continue;
1160                         case KDBUS_ITEM_ID_ADD:
1161                         case KDBUS_ITEM_ID_REMOVE:
1162                                 ASSERT_ZERO(user);
1163                                 ASSERT_RETURN(size,==,sizeof(struct kdbus_notify_id_change));
1164                                 continue;
1165                         case KDBUS_ITEM_REPLY_TIMEOUT:
1166                         case KDBUS_ITEM_REPLY_DEAD:
1167                                 ASSERT_ZERO(user);
1168                                 ASSERT_ZERO(size);
1169                                 continue;
1170
1171                         case KDBUS_ITEM_BLOOM_FILTER:
1172                                 kdbus_printf("WARNING! KDBUS_ITEM_BLOOM_FILTER passed from the kernel\n");
1173                                 continue;
1174
1175                         default:
1176                                 ASSERT_ZERO(item->type ?: (uint64_t)-1);
1177                 }
1178                 if (KDBUS_ITEM_TIMESTAMP != item->type)
1179                         ASSERT_NONZERO(user);
1180                 VERIFY_META;
1181         }
1182
1183         /* we're requesting all metadata and that's what we mandate */
1184         if (user) {
1185                 VERIFY_FINAL_ASSERT;
1186                 if (attach_flags & 1 << (KDBUS_ITEM_TIMESTAMP-_KDBUS_ITEM_ATTACH_BASE))
1187                         ASSERT_NONZERO(item_count[KDBUS_ITEM_TIMESTAMP-_KDBUS_ITEM_ATTACH_BASE]);
1188         } else if (attach_flags & 1 << (KDBUS_ITEM_TIMESTAMP-_KDBUS_ITEM_ATTACH_BASE))
1189                 ASSERT_NONZERO(item_count[KDBUS_ITEM_TIMESTAMP-_KDBUS_ITEM_ATTACH_BASE]);
1190
1191         return 0;
1192 }
1193
1194 wur int kdbus_msg_recv(struct kdbus_conn *conn,
1195                    struct kdbus_msg **msg_out,
1196                    uint64_t *offset)
1197 {
1198         struct kdbus_cmd_recv recv = { .size = sizeof(recv) };
1199         struct kdbus_msg *msg;
1200         int ret;
1201
1202         ret = kdbus_cmd_recv(conn->fd, &recv);
1203         if (ret < 0)
1204                 return ret;
1205
1206         msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset);
1207         ret = kdbus_msg_dump(msg);
1208         ASSERT_ZERO(kdbus_msg_verify(msg, conn->attach_flags_recv));
1209         if (ret < 0) {
1210                 kdbus_msg_free(msg);
1211                 return ret;
1212         }
1213
1214         if (msg_out) {
1215                 *msg_out = msg;
1216
1217                 if (offset)
1218                         *offset = recv.msg.offset;
1219         } else {
1220                 kdbus_msg_free(msg);
1221
1222                 ret = kdbus_free(conn, recv.msg.offset);
1223                 if (ret < 0)
1224                         return ret;
1225         }
1226
1227         return 0;
1228 }
1229
1230 /*
1231  * Returns: 0 on success, negative errno on failure.
1232  *
1233  * We must return -ETIMEDOUT, -ECONNREST, -EAGAIN and other errors.
1234  * We must return the result of kdbus_msg_recv()
1235  */
1236 wur int kdbus_msg_recv_poll(struct kdbus_conn *conn,
1237                         int timeout_ms,
1238                         struct kdbus_msg **msg_out,
1239                         uint64_t *offset)
1240 {
1241         int ret;
1242
1243         do {
1244                 struct timeval before, after, diff;
1245                 struct pollfd fd;
1246
1247                 fd.fd = conn->fd;
1248                 fd.events = POLLIN | POLLPRI | POLLHUP;
1249                 fd.revents = 0;
1250
1251                 gettimeofday(&before, NULL);
1252                 ret = poll(&fd, 1, timeout_ms);
1253                 gettimeofday(&after, NULL);
1254
1255                 if (ret == 0) {
1256                         ret = -ETIMEDOUT;
1257                         break;
1258                 }
1259
1260                 if (ret > 0) {
1261                         if (fd.revents & POLLIN)
1262                                 ret = kdbus_msg_recv(conn, msg_out, offset);
1263
1264                         if (fd.revents & (POLLHUP | POLLERR))
1265                                 ret = -ECONNRESET;
1266                 }
1267
1268                 if (ret == 0 || ret != -EAGAIN)
1269                         break;
1270
1271                 timersub(&after, &before, &diff);
1272                 timeout_ms -= diff.tv_sec * 1000UL +
1273                               diff.tv_usec / 1000UL;
1274         } while (timeout_ms > 0);
1275
1276         return ret;
1277 }
1278
1279 wur int kdbus_free(const struct kdbus_conn *conn, uint64_t offset)
1280 {
1281         struct kdbus_cmd_free cmd_free = {};
1282         int ret;
1283
1284         cmd_free.size = sizeof(cmd_free);
1285         cmd_free.offset = offset;
1286         cmd_free.flags = 0;
1287
1288         ret = kdbus_cmd_free(conn->fd, &cmd_free);
1289         if (ret < 0) {
1290                 kdbus_printf("KDBUS_CMD_FREE failed: %d (%m)\n", ret);
1291                 return ret;
1292         }
1293
1294         return 0;
1295 }
1296
1297 wur int kdbus_free_msg(struct kdbus_conn const *conn, struct kdbus_msg *msg)
1298 {
1299         return kdbus_free(conn, (uintptr_t)msg - (uintptr_t)conn->buf);
1300 }
1301
1302 wur int kdbus_name_acquire(struct kdbus_conn *conn,
1303                        const char *name, uint64_t *flags)
1304 {
1305         struct kdbus_cmd *cmd_name;
1306         size_t name_len = strlen(name) + 1;
1307         uint64_t size = sizeof(*cmd_name) + KDBUS_ITEM_SIZE(name_len);
1308         struct kdbus_item *item;
1309         int ret;
1310
1311         cmd_name = alloca(size);
1312
1313         memset(cmd_name, 0, size);
1314
1315         item = cmd_name->items;
1316         item->size = KDBUS_ITEM_HEADER_SIZE + name_len;
1317         item->type = KDBUS_ITEM_NAME;
1318         strcpy(item->str, name);
1319
1320         cmd_name->size = size;
1321         if (flags)
1322                 cmd_name->flags = *flags;
1323
1324         ret = kdbus_cmd_name_acquire(conn->fd, cmd_name);
1325         if (ret < 0) {
1326                 kdbus_printf("error acquiring name: %s\n", strerror(-ret));
1327                 return ret;
1328         }
1329
1330         kdbus_printf("%s(): flags after call: 0x%llx\n", __func__,
1331                      cmd_name->return_flags);
1332
1333         if (flags)
1334                 *flags = cmd_name->return_flags;
1335
1336         return 0;
1337 }
1338
1339 wur int kdbus_name_release(struct kdbus_conn *conn, const char *name)
1340 {
1341         struct kdbus_cmd *cmd_name;
1342         size_t name_len = strlen(name) + 1;
1343         uint64_t size = sizeof(*cmd_name) + KDBUS_ITEM_SIZE(name_len);
1344         struct kdbus_item *item;
1345         int ret;
1346
1347         cmd_name = alloca(size);
1348
1349         memset(cmd_name, 0, size);
1350
1351         item = cmd_name->items;
1352         item->size = KDBUS_ITEM_HEADER_SIZE + name_len;
1353         item->type = KDBUS_ITEM_NAME;
1354         strcpy(item->str, name);
1355
1356         cmd_name->size = size;
1357
1358         kdbus_printf("conn %lld giving up name '%s'\n",
1359                      (unsigned long long) conn->id, name);
1360
1361         ret = kdbus_cmd_name_release(conn->fd, cmd_name);
1362         if (ret < 0) {
1363                 kdbus_printf("error releasing name: %s\n", strerror(-ret));
1364                 return ret;
1365         }
1366
1367         return 0;
1368 }
1369
1370 wur int kdbus_list(struct kdbus_conn *conn, uint64_t flags)
1371 {
1372         struct kdbus_cmd_list cmd_list = {};
1373         struct kdbus_info *list, *name;
1374         int ret;
1375
1376         cmd_list.size = sizeof(cmd_list);
1377         cmd_list.flags = flags;
1378
1379         ret = kdbus_cmd_list(conn->fd, &cmd_list);
1380         if (ret < 0) {
1381                 kdbus_printf("error listing names: %d (%m)\n", ret);
1382                 return ret;
1383         }
1384
1385         kdbus_printf("REGISTRY:\n");
1386         list = (struct kdbus_info *)(conn->buf + cmd_list.offset);
1387
1388         KDBUS_FOREACH(name, list, cmd_list.list_size) {
1389                 uint64_t flags = 0;
1390                 struct kdbus_item *item;
1391                 const char *n = "MISSING-NAME";
1392
1393                 if (name->size == sizeof(struct kdbus_cmd))
1394                         continue;
1395
1396                 KDBUS_ITEM_FOREACH(item, name, items)
1397                         if (item->type == KDBUS_ITEM_OWNED_NAME) {
1398                                 n = item->name.name;
1399                                 flags = item->name.flags;
1400
1401                                 kdbus_printf("%8llu flags=0x%08llx conn=0x%08llx '%s'\n",
1402                                              name->id,
1403                                              (unsigned long long) flags,
1404                                              name->flags, n);
1405                         }
1406         }
1407         kdbus_printf("\n");
1408
1409         ret = kdbus_free(conn, cmd_list.offset);
1410
1411         return ret;
1412 }
1413
1414 wur int kdbus_conn_update_attach_flags(struct kdbus_conn *conn,
1415                                    uint64_t attach_flags_send,
1416                                    uint64_t attach_flags_recv)
1417 {
1418         int ret;
1419         size_t size;
1420         struct kdbus_cmd *update;
1421         struct kdbus_item *item;
1422
1423         size = sizeof(struct kdbus_cmd);
1424         size += KDBUS_ITEM_SIZE(sizeof(uint64_t)) * 2;
1425
1426         update = alloc(size);
1427         if (!update) {
1428                 kdbus_printf("error alloc: %m\n");
1429                 return -ENOMEM;
1430         }
1431
1432         memset(update, 0, size);
1433         update->size = size;
1434
1435         item = update->items;
1436
1437         item->type = KDBUS_ITEM_ATTACH_FLAGS_SEND;
1438         item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t);
1439         item->data64[0] = attach_flags_send;
1440         item = KDBUS_ITEM_NEXT(item);
1441
1442         item->type = KDBUS_ITEM_ATTACH_FLAGS_RECV;
1443         item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t);
1444         item->data64[0] = attach_flags_recv;
1445         item = KDBUS_ITEM_NEXT(item);
1446
1447         ret = kdbus_cmd_update(conn->fd, update);
1448         if (ret < 0)
1449                 kdbus_printf("error conn update: %d (%m)\n", ret);
1450
1451         free(update);
1452         conn->attach_flags_recv = attach_flags_recv;
1453
1454         return ret;
1455 }
1456
1457 wur int kdbus_conn_update_policy(struct kdbus_conn *conn, const char *name,
1458                              const struct kdbus_policy_access *access,
1459                              size_t num_access)
1460 {
1461         struct kdbus_cmd *update;
1462         struct kdbus_item *item;
1463         size_t i, size;
1464         int ret;
1465
1466         size = sizeof(struct kdbus_cmd);
1467         size += KDBUS_ITEM_SIZE(strlen(name) + 1);
1468         size += num_access * KDBUS_ITEM_SIZE(sizeof(struct kdbus_policy_access));
1469
1470         update = alloc(size);
1471         if (!update) {
1472                 kdbus_printf("error alloc: %m\n");
1473                 return -ENOMEM;
1474         }
1475
1476         memset(update, 0, size);
1477         update->size = size;
1478
1479         item = update->items;
1480
1481         item->type = KDBUS_ITEM_NAME;
1482         item->size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1;
1483         strcpy(item->str, name);
1484         item = KDBUS_ITEM_NEXT(item);
1485
1486         for (i = 0; i < num_access; i++) {
1487                 item->size = KDBUS_ITEM_HEADER_SIZE +
1488                              sizeof(struct kdbus_policy_access);
1489                 item->type = KDBUS_ITEM_POLICY_ACCESS;
1490
1491                 item->policy_access.type = access[i].type;
1492                 item->policy_access.access = access[i].access;
1493                 item->policy_access.id = access[i].id;
1494
1495                 item = KDBUS_ITEM_NEXT(item);
1496         }
1497
1498         ret = kdbus_cmd_update(conn->fd, update);
1499         if (ret < 0)
1500                 kdbus_printf("error conn update: %d (%m)\n", ret);
1501
1502         free(update);
1503
1504         return ret;
1505 }
1506
1507 wur int kdbus_add_match_id(struct kdbus_conn *conn, uint64_t cookie,
1508                        uint64_t type, uint64_t id)
1509 {
1510         struct {
1511                 struct kdbus_cmd_match cmd;
1512                 struct {
1513                         uint64_t size;
1514                         uint64_t type;
1515                         struct kdbus_notify_id_change chg;
1516                 } item;
1517         } buf;
1518         int ret;
1519
1520         memset(&buf, 0, sizeof(buf));
1521
1522         buf.cmd.size = sizeof(buf);
1523         buf.cmd.cookie = cookie;
1524         buf.item.size = sizeof(buf.item);
1525         buf.item.type = type;
1526         buf.item.chg.id = id;
1527
1528         ret = kdbus_cmd_match_add(conn->fd, &buf.cmd);
1529         if (ret < 0)
1530                 kdbus_printf("--- error adding conn match: %d (%m)\n", ret);
1531
1532         return ret;
1533 }
1534
1535 wur int kdbus_add_match_empty(struct kdbus_conn *conn)
1536 {
1537         struct {
1538                 struct kdbus_cmd_match cmd;
1539                 struct kdbus_item item;
1540         } buf;
1541         int ret;
1542
1543         memset(&buf, 0, sizeof(buf));
1544
1545         buf.item.size = sizeof(uint64_t) * 3;
1546         buf.item.type = KDBUS_ITEM_ID;
1547         buf.item.id = KDBUS_MATCH_ID_ANY;
1548
1549         buf.cmd.size = sizeof(buf.cmd) + buf.item.size;
1550
1551         ret = kdbus_cmd_match_add(conn->fd, &buf.cmd);
1552         if (ret < 0)
1553                 kdbus_printf("--- error adding conn match: %d (%m)\n", ret);
1554
1555         return ret;
1556 }
1557
1558 static wur int all_ids_are_mapped(const char *path)
1559 {
1560         int ret;
1561         FILE *file;
1562         uint32_t inside_id, length;
1563
1564         file = fopen(path, "r");
1565         if (!file) {
1566                 ret = -errno;
1567                 kdbus_printf("error fopen() %s: %d (%m)\n",
1568                              path, ret);
1569                 return ret;
1570         }
1571
1572         ret = fscanf(file, "%u\t%*u\t%u", &inside_id, &length);
1573         if (ret != 2) {
1574                 if (ferror(file))
1575                         ret = -errno;
1576                 else
1577                         ret = -EIO;
1578
1579                 kdbus_printf("--- error fscanf(): %d\n", ret);
1580                 fclose(file);
1581                 return ret;
1582         }
1583
1584         fclose(file);
1585
1586         /*
1587          * If length is 4294967295 which means the invalid uid
1588          * (uid_t) -1 then we are able to map all uid/gids
1589          */
1590         if (inside_id == 0 && length == (uid_t) -1)
1591                 return 1;
1592
1593         return 0;
1594 }
1595
1596 wur int all_uids_gids_are_mapped(void)
1597 {
1598         int ret;
1599
1600         ret = all_ids_are_mapped("/proc/self/uid_map");
1601         if (ret <= 0) {
1602                 kdbus_printf("--- error not all uids are mapped\n");
1603                 return 0;
1604         }
1605
1606         ret = all_ids_are_mapped("/proc/self/gid_map");
1607         if (ret <= 0) {
1608                 kdbus_printf("--- error not all gids are mapped\n");
1609                 return 0;
1610         }
1611
1612         return 1;
1613 }
1614
1615 wur int drop_privileges(uid_t uid, gid_t gid)
1616 {
1617         int ret;
1618
1619         ret = setgroups(0, NULL);
1620         if (ret < 0) {
1621                 ret = -errno;
1622                 kdbus_printf("error setgroups: %d (%m)\n", ret);
1623                 return ret;
1624         }
1625
1626         ret = setresgid(gid, gid, gid);
1627         if (ret < 0) {
1628                 ret = -errno;
1629                 kdbus_printf("error setresgid: %d (%m)\n", ret);
1630                 return ret;
1631         }
1632
1633         ret = setresuid(uid, uid, uid);
1634         if (ret < 0) {
1635                 ret = -errno;
1636                 kdbus_printf("error setresuid: %d (%m)\n", ret);
1637                 return ret;
1638         }
1639
1640         return ret;
1641 }
1642
1643 wur uint64_t now(clockid_t clock)
1644 {
1645         struct timespec spec;
1646
1647         clock_gettime(clock, &spec);
1648         return spec.tv_sec * 1000ULL * 1000ULL * 1000ULL + spec.tv_nsec;
1649 }
1650
1651 wur char *unique_name(const char *prefix)
1652 {
1653         unsigned int i;
1654         uint64_t u_now;
1655         char n[17];
1656         char *str;
1657         int r;
1658
1659         /*
1660          * This returns a random string which is guaranteed to be
1661          * globally unique across all calls to unique_name(). We
1662          * compose the string as:
1663          *   <prefix>-<random>-<time>
1664          * With:
1665          *   <prefix>: string provided by the caller
1666          *   <random>: a random alpha string of 16 characters
1667          *   <time>: the current time in micro-seconds since last boot
1668          *
1669          * The <random> part makes the string always look vastly different,
1670          * the <time> part makes sure no two calls return the same string.
1671          */
1672
1673         u_now = now(CLOCK_MONOTONIC);
1674
1675         for (i = 0; i < sizeof(n) - 1; ++i)
1676                 n[i] = 'a' + (rand() % ('z' - 'a'));
1677         n[sizeof(n) - 1] = 0;
1678
1679         r = asprintf(&str, "%s-%s-%" PRIu64, prefix, n, u_now);
1680         if (r < 0)
1681                 return NULL;
1682
1683         return str;
1684 }
1685
1686 static wur int do_userns_map_id(const char *map_file,
1687                             const char *map_id)
1688 {
1689         int ret;
1690         int fd;
1691         char *map;
1692         unsigned int i;
1693
1694         map = strndupa(map_id, strlen(map_id));
1695         if (!map) {
1696                 ret = -errno;
1697                 kdbus_printf("error strndupa %s: %d (%m)\n",
1698                         map_file, ret);
1699                 return ret;
1700         }
1701
1702         for (i = 0; i < strlen(map); i++)
1703                 if (map[i] == ',')
1704                         map[i] = '\n';
1705
1706         fd = open(map_file, O_RDWR);
1707         if (fd < 0) {
1708                 ret = -errno;
1709                 kdbus_printf("error open %s: %d (%m)\n",
1710                         map_file, ret);
1711                 return ret;
1712         }
1713
1714         ret = write(fd, map, strlen(map));
1715         if (ret < 0) {
1716                 ret = -errno;
1717                 kdbus_printf("error write to %s: %d (%m)\n",
1718                              map_file, ret);
1719                 goto out;
1720         }
1721
1722         ret = 0;
1723
1724 out:
1725         CLOSE(fd);
1726         return ret;
1727 }
1728
1729 wur int userns_map_uid_gid(pid_t pid,
1730                        const char *map_uid,
1731                        const char *map_gid)
1732 {
1733         int fd, ret;
1734         char file_id[128] = {'\0'};
1735
1736         snprintf(file_id, sizeof(file_id), "/proc/%ld/uid_map",
1737                  (long) pid);
1738
1739         ret = do_userns_map_id(file_id, map_uid);
1740         if (ret < 0)
1741                 return ret;
1742
1743         snprintf(file_id, sizeof(file_id), "/proc/%ld/setgroups",
1744                  (long) pid);
1745
1746         fd = open(file_id, O_WRONLY);
1747         if (fd >= 0) {
1748                 ret = write(fd, "deny\n", 5);
1749                 CLOSE(fd);
1750                 if (ret != 5)
1751                         return ret<0 ? ret : -EIO;
1752         }
1753
1754         snprintf(file_id, sizeof(file_id), "/proc/%ld/gid_map",
1755                  (long) pid);
1756
1757         return do_userns_map_id(file_id, map_gid);
1758 }
1759
1760 static wur int do_cap_get_flag(cap_t caps, cap_value_t cap)
1761 {
1762         int ret;
1763         cap_flag_value_t flag_set;
1764
1765         ret = cap_get_flag(caps, cap, CAP_EFFECTIVE, &flag_set);
1766         if (ret < 0) {
1767                 ret = -errno;
1768                 kdbus_printf("error cap_get_flag(): %d (%m)\n", ret);
1769                 return ret;
1770         }
1771
1772         return (flag_set == CAP_SET);
1773 }
1774
1775 /*
1776  * Returns:
1777  *  1 in case all the requested effective capabilities are set.
1778  *  0 in case we do not have the requested capabilities. This value
1779  *    will be used to abort tests with TEST_SKIP
1780  *  Negative errno on failure.
1781  *
1782  *  Terminate args with a negative value.
1783  */
1784 wur int test_is_capable(int cap, ...)
1785 {
1786         int ret;
1787         va_list ap;
1788         cap_t caps;
1789
1790         caps = cap_get_proc();
1791         if (!caps) {
1792                 ret = -errno;
1793                 kdbus_printf("error cap_get_proc(): %d (%m)\n", ret);
1794                 return ret;
1795         }
1796
1797         ret = do_cap_get_flag(caps, (cap_value_t)cap);
1798         if (ret <= 0)
1799                 goto out;
1800
1801         va_start(ap, cap);
1802         while ((cap = va_arg(ap, int)) > 0) {
1803                 ret = do_cap_get_flag(caps, (cap_value_t)cap);
1804                 if (ret <= 0)
1805                         break;
1806         }
1807         va_end(ap);
1808
1809 out:
1810         cap_free(caps);
1811         return ret;
1812 }
1813
1814 wur int config_user_ns_is_enabled(void)
1815 {
1816         return (access("/proc/self/uid_map", F_OK) == 0);
1817 }
1818
1819 wur int config_auditsyscall_is_enabled(void)
1820 {
1821         return (access("/proc/self/loginuid", F_OK) == 0);
1822 }
1823
1824 wur int config_cgroups_is_enabled(void)
1825 {
1826         return (access("/proc/self/cgroup", F_OK) == 0);
1827 }
1828
1829 wur int config_security_is_enabled(void)
1830 {
1831         int fd;
1832         int ret;
1833         char buf[128];
1834
1835         /* CONFIG_SECURITY is disabled */
1836         if (access("/proc/self/attr/current", F_OK) != 0)
1837                 return 0;
1838
1839         /*
1840          * Now only if read() fails with -EINVAL then we assume
1841          * that SECLABEL and LSM are disabled
1842          */
1843         fd = open("/proc/self/attr/current", O_RDONLY|O_CLOEXEC);
1844         if (fd < 0)
1845                 return 1;
1846
1847         ret = read(fd, buf, sizeof(buf));
1848         if (ret == -1 && errno == EINVAL)
1849                 ret = 0;
1850         else
1851                 ret = 1;
1852
1853         CLOSE(fd);
1854
1855         return ret;
1856 }