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