2 * Copyright (C) 2013-2015 Daniel Mack
3 * Copyright (C) 2013-2015 Kay Sievers
4 * Copyright (C) 2014-2015 Djalal Harouni
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.
27 #include <sys/capability.h>
31 #include <linux/unistd.h>
32 #include <linux/memfd.h>
34 #ifndef __NR_memfd_create
36 #define __NR_memfd_create 319
38 #define __NR_memfd_create 385
40 #define __NR_memfd_create 356
44 #include "kdbus-api.h"
45 #include "kdbus-util.h"
46 #include "kdbus-enum.h"
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)
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 */
59 int kdbus_util_verbose = true;
61 int kdbus_sysfs_get_parameter_mask(const char *path, uint64_t *mask)
65 unsigned long long value;
67 file = fopen(path, "r");
70 kdbus_printf("--- error fopen(): %d (%m)\n", ret);
74 ret = fscanf(file, "%llu", &value);
81 kdbus_printf("--- error fscanf(): %d\n", ret);
86 *mask = (uint64_t)value;
93 int kdbus_sysfs_set_parameter_mask(const char *path, uint64_t mask)
98 file = fopen(path, "w");
101 kdbus_printf("--- error open(): %d (%m)\n", ret);
105 ret = fprintf(file, "%llu", (unsigned long long)mask);
108 kdbus_printf("--- error fprintf(): %d\n", ret);
113 return ret > 0 ? 0 : ret;
116 int kdbus_create_bus(int control_fd, const char *name,
117 uint64_t req_meta, uint64_t owner_meta,
121 struct kdbus_cmd cmd;
123 /* bloom size item */
127 struct kdbus_bloom_parameter bloom;
130 /* required and owner metadata items */
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;
152 snprintf(bus_make.name.str, sizeof(bus_make.name.str),
153 "%u-%s", getuid(), name);
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;
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;
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;
167 bus_make.cmd.flags = KDBUS_MAKE_ACCESS_WORLD;
168 bus_make.cmd.size = sizeof(bus_make.cmd) +
170 bus_make.attach[0].size +
171 bus_make.attach[1].size +
174 if (control_fd != -1) {
176 "Creating bus with name >%s< on control fd %d ...\n",
179 ret = kdbus_cmd_bus_make(control_fd, &bus_make.cmd);
181 kdbus_printf("--- error when making bus: %d (%m)\n",
187 if (ret == 0 && path)
188 *path = strdup(bus_make.name.str);
194 kdbus_hello(const char *path, uint64_t flags,
195 const struct kdbus_item *item, size_t item_size)
197 struct kdbus_cmd_free cmd_free = {};
200 struct kdbus_cmd_hello hello;
208 uint8_t extra_items[item_size];
210 struct kdbus_conn *conn;
212 memset(&h, 0, sizeof(h));
215 memcpy(h.extra_items, item, item_size);
217 kdbus_printf("-- opening bus connection %s\n", path);
218 fd = open(path, O_RDWR|O_CLOEXEC);
220 kdbus_printf("--- error %d (%m)\n", fd);
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;
231 h.hello.size = sizeof(h);
232 h.hello.pool_size = POOL_SIZE;
234 ret = kdbus_cmd_hello(fd, (struct kdbus_cmd_hello *) &h.hello);
236 kdbus_printf("--- error when saying hello: %d (%m)\n", ret);
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],
248 cmd_free.size = sizeof(cmd_free);
249 cmd_free.offset = h.hello.offset;
250 kdbus_cmd_free(fd, &cmd_free);
252 conn = malloc(sizeof(*conn));
254 kdbus_printf("unable to malloc()!?\n");
258 conn->buf = mmap(NULL, POOL_SIZE, PROT_READ, MAP_SHARED, fd, 0);
259 if (conn->buf == MAP_FAILED) {
262 kdbus_printf("--- error mmap (%m)\n");
267 conn->id = h.hello.id;
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)
276 struct kdbus_item *item, *items;
279 size = KDBUS_ITEM_SIZE(strlen(name) + 1) +
280 num_access * KDBUS_ITEM_SIZE(sizeof(*access));
282 items = alloca(size);
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);
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;
295 item->policy_access.type = access[i].type;
296 item->policy_access.access = access[i].access;
297 item->policy_access.id = access[i].id;
299 item = KDBUS_ITEM_NEXT(item);
302 return kdbus_hello(path, flags, items, size);
305 struct kdbus_conn *kdbus_hello_activator(const char *path, const char *name,
306 const struct kdbus_policy_access *access,
309 return kdbus_hello_registrar(path, name, access, num_access,
310 KDBUS_HELLO_ACTIVATOR);
313 bool kdbus_item_in_message(struct kdbus_msg *msg, uint64_t type)
315 const struct kdbus_item *item;
317 KDBUS_ITEM_FOREACH(item, msg, items)
318 if (item->type == type)
324 int kdbus_bus_creator_info(struct kdbus_conn *conn,
328 struct kdbus_cmd_info *cmd;
329 size_t size = sizeof(*cmd);
333 memset(cmd, 0, size);
335 cmd->attach_flags = flags;
337 ret = kdbus_cmd_bus_creator_info(conn->fd, cmd);
339 kdbus_printf("--- error when requesting info: %d (%m)\n", ret);
344 *offset = cmd->offset;
346 kdbus_free(conn, cmd->offset);
351 int kdbus_conn_info(struct kdbus_conn *conn, uint64_t id,
352 const char *name, uint64_t flags,
355 struct kdbus_cmd_info *cmd;
356 size_t size = sizeof(*cmd);
357 struct kdbus_info *info;
361 size += KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1;
364 memset(cmd, 0, size);
366 cmd->attach_flags = flags;
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);
376 ret = kdbus_cmd_conn_info(conn->fd, cmd);
378 kdbus_printf("--- error when requesting info: %d (%m)\n", ret);
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);
390 *offset = cmd->offset;
392 kdbus_free(conn, cmd->offset);
397 void kdbus_conn_free(struct kdbus_conn *conn)
403 munmap(conn->buf, POOL_SIZE);
411 int sys_memfd_create(const char *name, __u64 size)
415 ret = syscall(__NR_memfd_create, name, MFD_ALLOW_SEALING);
421 ret = ftruncate(fd, size);
430 int sys_memfd_seal_set(int fd)
432 return fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK |
433 F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL);
436 off_t sys_memfd_get_size(int fd, off_t *size)
441 ret = fstat(fd, &stat);
443 kdbus_printf("stat() failed: %m\n");
447 *size = stat.st_size;
451 static int __kdbus_msg_send(const struct kdbus_conn *conn,
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;
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;
479 if (dst_id == KDBUS_DST_ID_BROADCAST)
480 size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64;
482 memfd = sys_memfd_create("my-name-is-nice", 1024 * 1024);
484 kdbus_printf("failed to create memfd: %m\n");
488 if (write(memfd, "kdbus memfd 1234567", 19) != 19) {
490 kdbus_printf("writing to memfd failed: %m\n");
494 ret = sys_memfd_seal_set(memfd);
497 kdbus_printf("memfd sealing failed: %m\n");
501 size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_memfd));
505 size += KDBUS_ITEM_SIZE(strlen(name) + 1);
510 kdbus_printf("unable to malloc()!?\n");
514 if (dst_id == KDBUS_DST_ID_BROADCAST)
515 flags |= KDBUS_MSG_SIGNAL;
517 memset(msg, 0, size);
519 msg->priority = priority;
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;
527 ret = clock_gettime(CLOCK_MONOTONIC_COARSE, &now);
531 msg->timeout_ns = now.tv_sec * 1000000000ULL +
532 now.tv_nsec + timeout;
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);
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);
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);
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);
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;
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;
573 item = KDBUS_ITEM_NEXT(item);
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);
584 size += KDBUS_ITEM_SIZE(sizeof(cancel_fd));
589 kdbus_printf("unable to malloc(%ld)!?\n", (long)size);
593 cmd->flags = cmd_flags;
594 cmd->msg_address = (uintptr_t)msg;
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);
606 ret = kdbus_cmd_send(conn->fd, cmd);
611 kdbus_printf("error sending message: %d (%m)\n", ret);
615 if (cmd_flags & KDBUS_SEND_SYNC_REPLY) {
616 struct kdbus_msg *reply;
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);
622 kdbus_msg_free(reply);
624 ret = kdbus_free(conn, cmd->reply.offset);
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[])
639 return __kdbus_msg_send(conn, name, cookie, flags, timeout, priority,
640 dst_id, 0, -1, fds_count, fds);
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)
647 return __kdbus_msg_send(conn, name, cookie, flags, timeout, priority,
648 dst_id, KDBUS_SEND_SYNC_REPLY, cancel_fd,
652 int kdbus_msg_send_reply(const struct kdbus_conn *conn,
653 uint64_t reply_cookie,
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;
663 size = sizeof(struct kdbus_msg);
664 size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
668 kdbus_printf("unable to malloc()!?\n");
672 memset(msg, 0, 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;
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);
687 cmd.size = sizeof(cmd);
688 cmd.msg_address = (uintptr_t)msg;
690 ret = kdbus_cmd_send(conn->fd, &cmd);
692 kdbus_printf("error sending message: %d (%m)\n", ret);
699 static char *msg_id(uint64_t id, char *buf)
705 sprintf(buf, "%llu", (unsigned long long)id);
709 int kdbus_msg_dump(const struct kdbus_conn *conn, const struct kdbus_msg *msg)
711 const struct kdbus_item *item = msg->items;
714 uint64_t timeout = 0;
715 uint64_t cookie_reply = 0;
718 if (msg->flags & KDBUS_MSG_EXPECT_REPLY)
719 timeout = msg->timeout_ns;
721 cookie_reply = msg->cookie_reply;
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);
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);
739 switch (item->type) {
740 case KDBUS_ITEM_PAYLOAD_OFF: {
743 if (item->vec.offset == ~0ULL)
746 s = (char *)msg + item->vec.offset;
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);
755 case KDBUS_ITEM_FDS: {
756 int i, n = (item->size - KDBUS_ITEM_HEADER_SIZE) /
759 kdbus_printf(" +%s (%llu bytes, %d fds)\n",
760 enum_MSG(item->type), item->size, n);
762 for (i = 0; i < n; i++)
763 kdbus_printf(" fd[%d] = %d\n",
769 case KDBUS_ITEM_PAYLOAD_MEMFD: {
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);
781 if (sys_memfd_get_size(item->memfd.fd, &size) < 0) {
782 kdbus_printf("KDBUS_CMD_MEMFD_SIZE_GET failed: %m\n");
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);
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);
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,
811 case KDBUS_ITEM_AUXGROUPS: {
814 kdbus_printf(" +%s (%llu bytes)\n",
815 enum_MSG(item->type), item->size);
816 n = (item->size - KDBUS_ITEM_HEADER_SIZE) /
819 for (i = 0; i < n; i++)
820 kdbus_printf(" gid[%d] = %lld\n",
825 case KDBUS_ITEM_NAME:
826 case KDBUS_ITEM_PID_COMM:
827 case KDBUS_ITEM_TID_COMM:
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));
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),
846 case KDBUS_ITEM_CMDLINE: {
847 size_t size = item->size - KDBUS_ITEM_HEADER_SIZE;
848 const char *str = item->str;
851 kdbus_printf(" +%s (%llu bytes) ",
852 enum_MSG(item->type), item->size);
854 kdbus_printf("'%s' ", str);
855 size -= strlen(str) + 1;
856 str += strlen(str) + 1;
860 kdbus_printf("(%d string%s)\n",
861 count, (count == 1) ? "" : "s");
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);
871 case KDBUS_ITEM_CAPS: {
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);
881 cap = item->caps.caps;
882 n = (item->size - offsetof(struct kdbus_item, caps.caps))
883 / 4 / sizeof(uint32_t);
885 kdbus_printf(" CapInh=");
886 for (i = 0; i < n; i++)
887 kdbus_printf("%08x", cap[(0 * n) + (n - i - 1)]);
889 kdbus_printf(" CapPrm=");
890 for (i = 0; i < n; i++)
891 kdbus_printf("%08x", cap[(1 * n) + (n - i - 1)]);
893 kdbus_printf(" CapEff=");
894 for (i = 0; i < n; i++)
895 kdbus_printf("%08x", cap[(2 * n) + (n - i - 1)]);
897 kdbus_printf(" CapBnd=");
898 for (i = 0; i < n; i++)
899 kdbus_printf("%08x", cap[(3 * n) + (n - i - 1)]);
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);
912 case KDBUS_ITEM_REPLY_TIMEOUT:
913 kdbus_printf(" +%s (%llu bytes) cookie=%llu\n",
914 enum_MSG(item->type), item->size,
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);
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);
941 kdbus_printf(" +%s (%llu bytes)\n",
942 enum_MSG(item->type), item->size);
947 if ((char *)item - ((char *)msg + msg->size) >= 8) {
948 kdbus_printf("invalid padding at end of message\n");
957 void kdbus_msg_free(struct kdbus_msg *msg)
959 const struct kdbus_item *item;
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);
972 nfds = (item->size - KDBUS_ITEM_HEADER_SIZE) /
975 for (i = 0; i < nfds; i++)
983 int kdbus_msg_recv(struct kdbus_conn *conn,
984 struct kdbus_msg **msg_out,
987 struct kdbus_cmd_recv recv = { .size = sizeof(recv) };
988 struct kdbus_msg *msg;
991 ret = kdbus_cmd_recv(conn->fd, &recv);
995 msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset);
996 ret = kdbus_msg_dump(conn, msg);
1006 *offset = recv.msg.offset;
1008 kdbus_msg_free(msg);
1010 ret = kdbus_free(conn, recv.msg.offset);
1019 * Returns: 0 on success, negative errno on failure.
1021 * We must return -ETIMEDOUT, -ECONNREST, -EAGAIN and other errors.
1022 * We must return the result of kdbus_msg_recv()
1024 int kdbus_msg_recv_poll(struct kdbus_conn *conn,
1026 struct kdbus_msg **msg_out,
1032 struct timeval before, after, diff;
1036 fd.events = POLLIN | POLLPRI | POLLHUP;
1039 gettimeofday(&before, NULL);
1040 ret = poll(&fd, 1, timeout_ms);
1041 gettimeofday(&after, NULL);
1049 if (fd.revents & POLLIN)
1050 ret = kdbus_msg_recv(conn, msg_out, offset);
1052 if (fd.revents & (POLLHUP | POLLERR))
1056 if (ret == 0 || ret != -EAGAIN)
1059 timersub(&after, &before, &diff);
1060 timeout_ms -= diff.tv_sec * 1000UL +
1061 diff.tv_usec / 1000UL;
1062 } while (timeout_ms > 0);
1067 int kdbus_free(const struct kdbus_conn *conn, uint64_t offset)
1069 struct kdbus_cmd_free cmd_free = {};
1072 cmd_free.size = sizeof(cmd_free);
1073 cmd_free.offset = offset;
1076 ret = kdbus_cmd_free(conn->fd, &cmd_free);
1078 kdbus_printf("KDBUS_CMD_FREE failed: %d (%m)\n", ret);
1085 int kdbus_name_acquire(struct kdbus_conn *conn,
1086 const char *name, uint64_t *flags)
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;
1094 cmd_name = alloca(size);
1096 memset(cmd_name, 0, size);
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);
1103 cmd_name->size = size;
1105 cmd_name->flags = *flags;
1107 ret = kdbus_cmd_name_acquire(conn->fd, cmd_name);
1109 kdbus_printf("error aquiring name: %s\n", strerror(-ret));
1113 kdbus_printf("%s(): flags after call: 0x%llx\n", __func__,
1114 cmd_name->return_flags);
1117 *flags = cmd_name->return_flags;
1122 int kdbus_name_release(struct kdbus_conn *conn, const char *name)
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;
1130 cmd_name = alloca(size);
1132 memset(cmd_name, 0, size);
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);
1139 cmd_name->size = size;
1141 kdbus_printf("conn %lld giving up name '%s'\n",
1142 (unsigned long long) conn->id, name);
1144 ret = kdbus_cmd_name_release(conn->fd, cmd_name);
1146 kdbus_printf("error releasing name: %s\n", strerror(-ret));
1153 int kdbus_list(struct kdbus_conn *conn, uint64_t flags)
1155 struct kdbus_cmd_list cmd_list = {};
1156 struct kdbus_info *list, *name;
1159 cmd_list.size = sizeof(cmd_list);
1160 cmd_list.flags = flags;
1162 ret = kdbus_cmd_list(conn->fd, &cmd_list);
1164 kdbus_printf("error listing names: %d (%m)\n", ret);
1168 kdbus_printf("REGISTRY:\n");
1169 list = (struct kdbus_info *)(conn->buf + cmd_list.offset);
1171 KDBUS_FOREACH(name, list, cmd_list.list_size) {
1173 struct kdbus_item *item;
1174 const char *n = "MISSING-NAME";
1176 if (name->size == sizeof(struct kdbus_cmd))
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;
1185 kdbus_printf("%8llu flags=0x%08llx conn=0x%08llx '%s'\n",
1186 name->id, (unsigned long long) flags,
1191 ret = kdbus_free(conn, cmd_list.offset);
1196 int kdbus_conn_update_attach_flags(struct kdbus_conn *conn,
1197 uint64_t attach_flags_send,
1198 uint64_t attach_flags_recv)
1202 struct kdbus_cmd *update;
1203 struct kdbus_item *item;
1205 size = sizeof(struct kdbus_cmd);
1206 size += KDBUS_ITEM_SIZE(sizeof(uint64_t)) * 2;
1208 update = malloc(size);
1210 kdbus_printf("error malloc: %m\n");
1214 memset(update, 0, size);
1215 update->size = size;
1217 item = update->items;
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);
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);
1229 ret = kdbus_cmd_update(conn->fd, update);
1231 kdbus_printf("error conn update: %d (%m)\n", ret);
1238 int kdbus_conn_update_policy(struct kdbus_conn *conn, const char *name,
1239 const struct kdbus_policy_access *access,
1242 struct kdbus_cmd *update;
1243 struct kdbus_item *item;
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));
1251 update = malloc(size);
1253 kdbus_printf("error malloc: %m\n");
1257 memset(update, 0, size);
1258 update->size = size;
1260 item = update->items;
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);
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;
1272 item->policy_access.type = access[i].type;
1273 item->policy_access.access = access[i].access;
1274 item->policy_access.id = access[i].id;
1276 item = KDBUS_ITEM_NEXT(item);
1279 ret = kdbus_cmd_update(conn->fd, update);
1281 kdbus_printf("error conn update: %d (%m)\n", ret);
1288 int kdbus_add_match_id(struct kdbus_conn *conn, uint64_t cookie,
1289 uint64_t type, uint64_t id)
1292 struct kdbus_cmd_match cmd;
1296 struct kdbus_notify_id_change chg;
1301 memset(&buf, 0, sizeof(buf));
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;
1309 ret = kdbus_cmd_match_add(conn->fd, &buf.cmd);
1311 kdbus_printf("--- error adding conn match: %d (%m)\n", ret);
1316 int kdbus_add_match_empty(struct kdbus_conn *conn)
1319 struct kdbus_cmd_match cmd;
1320 struct kdbus_item item;
1324 memset(&buf, 0, sizeof(buf));
1326 buf.item.size = sizeof(uint64_t) * 3;
1327 buf.item.type = KDBUS_ITEM_ID;
1328 buf.item.id = KDBUS_MATCH_ID_ANY;
1330 buf.cmd.size = sizeof(buf.cmd) + buf.item.size;
1332 ret = kdbus_cmd_match_add(conn->fd, &buf.cmd);
1334 kdbus_printf("--- error adding conn match: %d (%m)\n", ret);
1339 static int all_ids_are_mapped(const char *path)
1343 uint32_t inside_id, length;
1345 file = fopen(path, "r");
1348 kdbus_printf("error fopen() %s: %d (%m)\n",
1353 ret = fscanf(file, "%u\t%*u\t%u", &inside_id, &length);
1360 kdbus_printf("--- error fscanf(): %d\n", ret);
1368 * If length is 4294967295 which means the invalid uid
1369 * (uid_t) -1 then we are able to map all uid/gids
1371 if (inside_id == 0 && length == (uid_t) -1)
1377 int all_uids_gids_are_mapped()
1381 ret = all_ids_are_mapped("/proc/self/uid_map");
1383 kdbus_printf("--- error not all uids are mapped\n");
1387 ret = all_ids_are_mapped("/proc/self/gid_map");
1389 kdbus_printf("--- error not all gids are mapped\n");
1396 int drop_privileges(uid_t uid, gid_t gid)
1400 ret = setgroups(0, NULL);
1403 kdbus_printf("error setgroups: %d (%m)\n", ret);
1407 ret = setresgid(gid, gid, gid);
1410 kdbus_printf("error setresgid: %d (%m)\n", ret);
1414 ret = setresuid(uid, uid, uid);
1417 kdbus_printf("error setresuid: %d (%m)\n", ret);
1424 uint64_t now(clockid_t clock)
1426 struct timespec spec;
1428 clock_gettime(clock, &spec);
1429 return spec.tv_sec * 1000ULL * 1000ULL * 1000ULL + spec.tv_nsec;
1432 char *unique_name(const char *prefix)
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>
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
1450 * The <random> part makes the string always look vastly different,
1451 * the <time> part makes sure no two calls return the same string.
1454 u_now = now(CLOCK_MONOTONIC);
1456 for (i = 0; i < sizeof(n) - 1; ++i)
1457 n[i] = 'a' + (rand() % ('z' - 'a'));
1458 n[sizeof(n) - 1] = 0;
1460 r = asprintf(&str, "%s-%s-%" PRIu64, prefix, n, u_now);
1467 static int do_userns_map_id(pid_t pid,
1468 const char *map_file,
1476 map = strndupa(map_id, strlen(map_id));
1479 kdbus_printf("error strndupa %s: %d (%m)\n",
1484 for (i = 0; i < strlen(map); i++)
1488 fd = open(map_file, O_RDWR);
1491 kdbus_printf("error open %s: %d (%m)\n",
1496 ret = write(fd, map, strlen(map));
1499 kdbus_printf("error write to %s: %d (%m)\n",
1511 int userns_map_uid_gid(pid_t pid,
1512 const char *map_uid,
1513 const char *map_gid)
1516 char file_id[128] = {'\0'};
1518 snprintf(file_id, sizeof(file_id), "/proc/%ld/uid_map",
1521 ret = do_userns_map_id(pid, file_id, map_uid);
1525 snprintf(file_id, sizeof(file_id), "/proc/%ld/setgroups",
1528 fd = open(file_id, O_WRONLY);
1530 write(fd, "deny\n", 5);
1534 snprintf(file_id, sizeof(file_id), "/proc/%ld/gid_map",
1537 return do_userns_map_id(pid, file_id, map_gid);
1540 static int do_cap_get_flag(cap_t caps, cap_value_t cap)
1543 cap_flag_value_t flag_set;
1545 ret = cap_get_flag(caps, cap, CAP_EFFECTIVE, &flag_set);
1548 kdbus_printf("error cap_get_flag(): %d (%m)\n", ret);
1552 return (flag_set == CAP_SET);
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.
1562 * Terminate args with a negative value.
1564 int test_is_capable(int cap, ...)
1570 caps = cap_get_proc();
1573 kdbus_printf("error cap_get_proc(): %d (%m)\n", ret);
1577 ret = do_cap_get_flag(caps, (cap_value_t)cap);
1582 while ((cap = va_arg(ap, int)) > 0) {
1583 ret = do_cap_get_flag(caps, (cap_value_t)cap);
1594 int config_user_ns_is_enabled(void)
1596 return (access("/proc/self/uid_map", F_OK) == 0);
1599 int config_auditsyscall_is_enabled(void)
1601 return (access("/proc/self/loginuid", F_OK) == 0);
1604 int config_cgroups_is_enabled(void)
1606 return (access("/proc/self/cgroup", F_OK) == 0);
1609 int config_security_is_enabled(void)
1615 /* CONFIG_SECURITY is disabled */
1616 if (access("/proc/self/attr/current", F_OK) != 0)
1620 * Now only if read() fails with -EINVAL then we assume
1621 * that SECLABEL and LSM are disabled
1623 fd = open("/proc/self/attr/current", O_RDONLY|O_CLOEXEC);
1627 ret = read(fd, buf, sizeof(buf));
1628 if (ret == -1 && errno == EINVAL)