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>
33 #ifndef __NR_memfd_create
35 #define __NR_memfd_create 319
37 #define __NR_memfd_create 385
39 #define __NR_memfd_create 356
43 #include "kdbus-api.h"
44 #include "kdbus-util.h"
45 #include "kdbus-enum.h"
46 #include "kdbus-test.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 /* maximum number of well-known names per connection */
60 #define KDBUS_CONN_MAX_NAMES 256
62 int kdbus_util_verbose = true;
64 wur int kdbus_sysfs_get_parameter_mask(const char *path, uint64_t *mask)
68 unsigned long long value;
70 file = fopen(path, "r");
73 kdbus_printf("--- error fopen(): %d (%m)\n", ret);
77 ret = fscanf(file, "%llu", &value);
84 kdbus_printf("--- error fscanf(): %d\n", ret);
89 *mask = (uint64_t)value;
96 wur int kdbus_sysfs_set_parameter_mask(const char *path, uint64_t mask)
101 file = fopen(path, "w");
104 kdbus_printf("--- error open(): %d (%m)\n", ret);
108 ret = fprintf(file, "%llu", (unsigned long long)mask);
111 kdbus_printf("--- error fprintf(): %d\n", ret);
116 return ret > 0 ? 0 : ret;
119 wur int kdbus_create_bus(int control_fd, const char *name,
120 uint64_t owner_meta, char **path)
123 struct kdbus_cmd cmd;
125 /* bloom size item */
129 struct kdbus_bloom_parameter bloom;
132 /* owner metadata items */
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;
154 snprintf(bus_make.name.str, sizeof(bus_make.name.str),
155 "%u-%s", getuid(), name);
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;
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;
165 bus_make.cmd.flags = KDBUS_MAKE_ACCESS_WORLD;
166 bus_make.cmd.size = sizeof(bus_make.cmd) +
168 bus_make.attach.size +
171 kdbus_printf("Creating bus with name >%s< on control fd %d ...\n",
174 ret = kdbus_cmd_bus_make(control_fd, &bus_make.cmd);
176 kdbus_printf("--- error when making bus: %d (%m)\n", ret);
180 if (ret == 0 && path)
181 *path = strdup(bus_make.name.str);
186 wur struct kdbus_conn *
187 kdbus_hello(const char *path, uint64_t flags,
188 const struct kdbus_item *item, size_t item_size)
190 struct kdbus_cmd_free cmd_free = {};
193 struct kdbus_cmd_hello hello;
201 uint8_t extra_items[item_size];
203 struct kdbus_conn *conn;
205 memset(&h, 0, sizeof(h));
208 memcpy(h.extra_items, item, item_size);
210 kdbus_printf("-- opening bus connection %s\n", path);
211 fd = open(path, O_RDWR|O_CLOEXEC);
213 kdbus_printf("--- error %d (%m)\n", fd);
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;
224 h.hello.size = sizeof(h);
225 h.hello.pool_size = POOL_SIZE;
227 ret = kdbus_cmd_hello(fd, (struct kdbus_cmd_hello *) &h.hello);
229 kdbus_printf("--- error when saying hello: %d (%m)\n", ret);
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],
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);
249 conn = alloc(sizeof(*conn));
251 kdbus_printf("unable to alloc()!?\n");
255 conn->buf = mmap(NULL, POOL_SIZE, PROT_READ, MAP_SHARED, fd, 0);
256 if (conn->buf == MAP_FAILED) {
259 kdbus_printf("--- error mmap (%m)\n");
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;
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)
275 struct kdbus_item *item, *items;
278 size = KDBUS_ITEM_SIZE(strlen(name) + 1) +
279 num_access * KDBUS_ITEM_SIZE(sizeof(*access));
281 items = alloca(size);
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);
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;
294 item->policy_access.type = access[i].type;
295 item->policy_access.access = access[i].access;
296 item->policy_access.id = access[i].id;
298 item = KDBUS_ITEM_NEXT(item);
301 return kdbus_hello(path, flags, items, size);
304 wur struct kdbus_conn *kdbus_hello_activator(const char *path, const char *name,
305 const struct kdbus_policy_access *access,
308 return kdbus_hello_registrar(path, name, access, num_access,
309 KDBUS_HELLO_ACTIVATOR);
312 wur bool kdbus_item_in_message(struct kdbus_msg *msg, uint64_t type)
314 const struct kdbus_item *item;
316 KDBUS_ITEM_FOREACH(item, msg, items)
317 if (item->type == type)
323 wur int kdbus_bus_creator_info(struct kdbus_conn *conn,
327 struct kdbus_cmd_info *cmd;
328 size_t size = sizeof(*cmd);
332 memset(cmd, 0, size);
334 cmd->attach_flags = flags;
336 ret = kdbus_cmd_bus_creator_info(conn->fd, cmd);
338 kdbus_printf("--- error when requesting info: %d (%m)\n", ret);
343 *offset = cmd->offset;
345 ret = kdbus_free(conn, cmd->offset);
350 wur static int kdbus_info_verify(struct kdbus_info *info, unsigned attach_flags);
352 wur int kdbus_conn_info(struct kdbus_conn *conn, uint64_t id,
353 const char *name, uint64_t flags,
356 struct kdbus_cmd_info *cmd;
357 size_t size = sizeof(*cmd);
359 struct kdbus_info *info;
362 /*print("call prepared 0\n");*/
365 size += KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1;
367 /*print("call prepared 1\n");*/
369 full_size = KDBUS_ALIGN8(size) + 1000;
371 /*print("call prepared 2\n");*/
373 cmd = malloc(full_size);
376 /*print("call prepared 3\n");*/
377 memset(cmd, 0, full_size);
378 /*print("call prepared 4\n");*/
380 /*print("call prepared 5\n");*/
381 cmd->attach_flags = flags;
382 /*print("call prepared 6\n");*/
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);*/
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);*/
395 /*print("call prepared 10\n");*/
399 /*print("call prepared 11\n");*/
401 ret = kdbus_cmd_conn_info(conn->fd, cmd);
403 kdbus_printf("--- error when requesting info: %d (%m)\n", ret);
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);
417 *offset = cmd->offset;
418 ASSERT_ZERO(kdbus_info_verify(info, flags));
420 ret = kdbus_free(conn, cmd->offset);
426 void kdbus_conn_free(struct kdbus_conn *conn)
431 if (conn->buf && munmap(conn->buf, POOL_SIZE))
432 fail("munmap(%p) err(%d)", conn->buf, errno);
434 if (conn->fd >= 0 && close(conn->fd))
435 fail("close(%d) err(%d)", conn->fd, errno);
440 wur int sys_memfd_create(const char *name, __u64 size)
444 fd = syscall(__NR_memfd_create, name, 2/*MFD_ALLOW_SEALING*/);
448 ret = ftruncate(fd, size);
457 wur int sys_memfd_seal_set(int fd)
459 return fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK |
460 F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL);
463 wur off_t sys_memfd_get_size(int fd, off_t *size)
468 ret = fstat(fd, &stat);
470 kdbus_printf("stat() failed: %m\n");
474 *size = stat.st_size;
478 static wur int __kdbus_msg_send(const struct kdbus_conn *conn,
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;
498 size = sizeof(*msg) + 3 * KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
500 if (dst_id == KDBUS_DST_ID_BROADCAST)
501 size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64;
503 memfd = sys_memfd_create("my-name-is-nice", 1024 * 1024);
505 kdbus_printf("failed to create memfd: %m\n");
509 if (write(memfd, "kdbus memfd 1234567", 19) != 19) {
511 kdbus_printf("writing to memfd failed: %m\n");
515 ret = sys_memfd_seal_set(memfd);
518 kdbus_printf("memfd sealing failed: %m\n");
522 size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_memfd));
526 size += KDBUS_ITEM_SIZE(strlen(name) + 1);
531 kdbus_printf("unable to alloc()!?\n");
535 if (dst_id == KDBUS_DST_ID_BROADCAST)
536 flags |= KDBUS_MSG_SIGNAL;
538 memset(msg, 0, size);
540 msg->priority = priority;
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;
548 ret = clock_gettime(CLOCK_MONOTONIC_COARSE, &now);
552 msg->timeout_ns = now.tv_sec * 1000000000ULL +
553 now.tv_nsec + timeout;
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);
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);
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);
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);
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;
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;
594 item = KDBUS_ITEM_NEXT(item);
598 size += KDBUS_ITEM_SIZE(sizeof(cancel_fd));
603 kdbus_printf("unable to alloc()!?\n");
608 cmd->flags = cmd_flags;
609 cmd->msg_address = (uintptr_t)msg;
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);
620 ret = kdbus_cmd_send(conn->fd, cmd);
622 kdbus_printf("error sending message: %d (%m)\n", ret);
626 if (cmd_flags & KDBUS_SEND_SYNC_REPLY) {
627 struct kdbus_msg *reply;
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);
634 kdbus_msg_free(reply);
636 ret = kdbus_free(conn, cmd->reply.offset);
648 return ret < 0 ? ret : 0;
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)
655 return __kdbus_msg_send(conn, name, cookie, flags, timeout, priority,
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)
663 return __kdbus_msg_send(conn, name, cookie, flags, timeout, priority,
664 dst_id, KDBUS_SEND_SYNC_REPLY, cancel_fd);
667 wur int kdbus_msg_send_reply(const struct kdbus_conn *conn,
668 uint64_t reply_cookie,
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;
678 size = sizeof(struct kdbus_msg);
679 size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
683 kdbus_printf("unable to alloc()!?\n");
687 memset(msg, 0, 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;
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);
702 cmd.size = sizeof(cmd);
703 cmd.msg_address = (uintptr_t)msg;
705 ret = kdbus_cmd_send(conn->fd, &cmd);
707 kdbus_printf("error sending message: %d (%m)\n", ret);
714 static wur char *msg_id(uint64_t id, char *buf)
720 sprintf(buf, "%llu", (unsigned long long)id);
724 wur int kdbus_msg_dump(const struct kdbus_msg *msg) {
725 const struct kdbus_item *item = msg->items;
728 uint64_t timeout = 0;
729 uint64_t cookie_reply = 0;
732 if (msg->flags & KDBUS_MSG_EXPECT_REPLY)
733 timeout = msg->timeout_ns;
735 cookie_reply = msg->cookie_reply;
737 kdbus_printf("MESSAGE(%p): %s (%llu bytes) flags=0x%08llx, %s → %s, "
738 "cookie=%llu, timeout=%llu cookie_reply=%llu priority=%lli\n",
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);
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);
753 switch (item->type) {
754 case KDBUS_ITEM_PAYLOAD_OFF: {
757 if (item->vec.offset == ~0ULL)
760 s = (char *)msg + item->vec.offset;
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);
769 case KDBUS_ITEM_FDS: {
770 int i, n = (item->size - KDBUS_ITEM_HEADER_SIZE) /
773 kdbus_printf(" +%s (%llu bytes, %d fds)\n",
774 enum_MSG(item->type), item->size, n);
776 for (i = 0; i < n; i++)
777 kdbus_printf(" fd[%d] = %d\n",
783 case KDBUS_ITEM_PAYLOAD_MEMFD: {
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);
795 if (sys_memfd_get_size(item->memfd.fd, &size) < 0) {
796 kdbus_printf("KDBUS_CMD_MEMFD_SIZE_GET failed: %m\n");
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);
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);
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,
825 case KDBUS_ITEM_AUXGROUPS: {
828 kdbus_printf(" +%s (%llu bytes)\n",
829 enum_MSG(item->type), item->size);
830 n = (item->size - KDBUS_ITEM_HEADER_SIZE) /
833 for (i = 0; i < n; i++)
834 kdbus_printf(" gid[%d] = %lld\n",
839 case KDBUS_ITEM_NAME:
840 case KDBUS_ITEM_PID_COMM:
841 case KDBUS_ITEM_TID_COMM:
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));
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),
860 case KDBUS_ITEM_CMDLINE: {
861 size_t size = item->size - KDBUS_ITEM_HEADER_SIZE;
862 const char *str = item->str;
865 kdbus_printf(" +%s (%llu bytes) ",
866 enum_MSG(item->type), item->size);
868 kdbus_printf("'%s' ", str);
869 size -= strlen(str) + 1;
870 str += strlen(str) + 1;
874 kdbus_printf("(%d string%s)\n",
875 count, (count == 1) ? "" : "s");
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);
885 case KDBUS_ITEM_CAPS: {
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);
895 cap = item->caps.caps;
896 n = (item->size - offsetof(struct kdbus_item, caps.caps))
897 / 4 / sizeof(uint32_t);
899 kdbus_printf(" CapInh=");
900 for (i = 0; i < n; i++)
901 kdbus_printf("%08x", cap[(0 * n) + (n - i - 1)]);
903 kdbus_printf(" CapPrm=");
904 for (i = 0; i < n; i++)
905 kdbus_printf("%08x", cap[(1 * n) + (n - i - 1)]);
907 kdbus_printf(" CapEff=");
908 for (i = 0; i < n; i++)
909 kdbus_printf("%08x", cap[(2 * n) + (n - i - 1)]);
911 kdbus_printf(" CapBnd=");
912 for (i = 0; i < n; i++)
913 kdbus_printf("%08x", cap[(3 * n) + (n - i - 1)]);
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);
926 case KDBUS_ITEM_REPLY_TIMEOUT:
927 kdbus_printf(" +%s (%llu bytes) cookie=%llu\n",
928 enum_MSG(item->type), item->size,
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);
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);
955 kdbus_printf(" +%s (%llu bytes)\n",
956 enum_MSG(item->type), item->size);
961 if ((char *)item - ((char *)msg + msg->size) >= 8) {
962 kdbus_printf("invalid padding at end of message\n");
971 void kdbus_msg_free(struct kdbus_msg *msg)
973 const struct kdbus_item *item;
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);
987 nfds = (item->size - KDBUS_ITEM_HEADER_SIZE) /
990 for (i = 0; i < nfds; i++)
991 if (-1 != item->fds[i])
999 wur static int verify_padding(char const *b, unsigned off)
1002 ASSERT_ZERO((unsigned)b[off]);
1008 wur static int verify_string(unsigned size, char const *s)
1011 ASSERT_NONZERO(size);
1013 ASSERT_RETURN(len,==,size);
1014 ASSERT_ZERO(verify_padding(s, len));
1017 wur static int verify_string_array(unsigned size, char const *s)
1020 ASSERT_NONZERO(size);
1022 unsigned len = strlen(s+off);
1026 ASSERT_RETURN(len,<=,size);
1030 ASSERT_ZERO(verify_padding(s, off));
1034 #define VERIFY_DECL\
1035 const struct kdbus_item *item;\
1036 unsigned item_count[14];\
1038 memset(item_count, 0, sizeof(item_count));
1039 #define VERIFY_DECL_INLOOP\
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\
1047 case KDBUS_ITEM_CREDS:\
1048 ASSERT_RETURN(size,==,sizeof(struct kdbus_creds));\
1050 case KDBUS_ITEM_PIDS:\
1051 ASSERT_RETURN(size,==,sizeof(struct kdbus_pids));\
1053 case KDBUS_ITEM_AUDIT:\
1054 ASSERT_RETURN(size,==,sizeof(struct kdbus_audit));\
1056 case KDBUS_ITEM_AUXGROUPS:\
1057 case KDBUS_ITEM_CAPS:\
1058 ASSERT_ZERO(size%sizeof(uint32_t));\
1060 case KDBUS_ITEM_OWNED_NAME:\
1061 ASSERT_ZERO(verify_string(size-offsetof(typeof(item->name), name), item->name.name));\
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));\
1071 case KDBUS_ITEM_CMDLINE:\
1072 ASSERT_ZERO(verify_string_array(size, item->str));\
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]);\
1082 ASSERT_RETURN(item_count[idx],<,(uint64_t)KDBUS_CONN_MAX_NAMES);\
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*/\
1096 wur static int kdbus_info_verify(struct kdbus_info *info, unsigned attach_flags)
1100 KDBUS_ITEM_FOREACH(item, info, items) {
1102 switch(item->type) {
1104 default: ASSERT_ZERO(item->type ?: (uint64_t)-1);
1109 VERIFY_FINAL_ASSERT;
1114 wur static int kdbus_msg_verify(struct kdbus_msg *msg, unsigned attach_flags)
1120 if (msg->payload_type != KDBUS_PAYLOAD_KERNEL) {
1121 ASSERT_RETURN(msg->payload_type,==,KDBUS_PAYLOAD_DBUS);
1125 KDBUS_ITEM_FOREACH(item, msg, items) {
1128 switch(item->type) {
1129 case KDBUS_ITEM_TIMESTAMP:
1130 ASSERT_RETURN(size,==,sizeof(struct kdbus_timestamp));
1135 case KDBUS_ITEM_PAYLOAD_OFF:
1136 ASSERT_NONZERO(user);
1137 ASSERT_RETURN(size,==,sizeof(struct kdbus_vec));
1139 case KDBUS_ITEM_PAYLOAD_MEMFD:
1140 ASSERT_NONZERO(user);
1141 ASSERT_RETURN(size,==,sizeof(struct kdbus_memfd));
1143 case KDBUS_ITEM_FDS:
1144 ASSERT_NONZERO(user);
1145 ASSERT_ZERO(size%sizeof(int));
1147 case KDBUS_ITEM_DST_NAME:
1148 ASSERT_NONZERO(user);
1149 ASSERT_ZERO(verify_string(size, item->str));
1153 case KDBUS_ITEM_NAME_ADD:
1154 case KDBUS_ITEM_NAME_REMOVE:
1155 case KDBUS_ITEM_NAME_CHANGE:
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));
1160 case KDBUS_ITEM_ID_ADD:
1161 case KDBUS_ITEM_ID_REMOVE:
1163 ASSERT_RETURN(size,==,sizeof(struct kdbus_notify_id_change));
1165 case KDBUS_ITEM_REPLY_TIMEOUT:
1166 case KDBUS_ITEM_REPLY_DEAD:
1171 case KDBUS_ITEM_BLOOM_FILTER:
1172 kdbus_printf("WARNING! KDBUS_ITEM_BLOOM_FILTER passed from the kernel\n");
1176 ASSERT_ZERO(item->type ?: (uint64_t)-1);
1178 if (KDBUS_ITEM_TIMESTAMP != item->type)
1179 ASSERT_NONZERO(user);
1183 /* we're requesting all metadata and that's what we mandate */
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]);
1194 wur int kdbus_msg_recv(struct kdbus_conn *conn,
1195 struct kdbus_msg **msg_out,
1198 struct kdbus_cmd_recv recv = { .size = sizeof(recv) };
1199 struct kdbus_msg *msg;
1202 ret = kdbus_cmd_recv(conn->fd, &recv);
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));
1210 kdbus_msg_free(msg);
1218 *offset = recv.msg.offset;
1220 kdbus_msg_free(msg);
1222 ret = kdbus_free(conn, recv.msg.offset);
1231 * Returns: 0 on success, negative errno on failure.
1233 * We must return -ETIMEDOUT, -ECONNREST, -EAGAIN and other errors.
1234 * We must return the result of kdbus_msg_recv()
1236 wur int kdbus_msg_recv_poll(struct kdbus_conn *conn,
1238 struct kdbus_msg **msg_out,
1244 struct timeval before, after, diff;
1248 fd.events = POLLIN | POLLPRI | POLLHUP;
1251 gettimeofday(&before, NULL);
1252 ret = poll(&fd, 1, timeout_ms);
1253 gettimeofday(&after, NULL);
1261 if (fd.revents & POLLIN)
1262 ret = kdbus_msg_recv(conn, msg_out, offset);
1264 if (fd.revents & (POLLHUP | POLLERR))
1268 if (ret == 0 || ret != -EAGAIN)
1271 timersub(&after, &before, &diff);
1272 timeout_ms -= diff.tv_sec * 1000UL +
1273 diff.tv_usec / 1000UL;
1274 } while (timeout_ms > 0);
1279 wur int kdbus_free(const struct kdbus_conn *conn, uint64_t offset)
1281 struct kdbus_cmd_free cmd_free = {};
1284 cmd_free.size = sizeof(cmd_free);
1285 cmd_free.offset = offset;
1288 ret = kdbus_cmd_free(conn->fd, &cmd_free);
1290 kdbus_printf("KDBUS_CMD_FREE failed: %d (%m)\n", ret);
1297 wur int kdbus_free_msg(struct kdbus_conn const *conn, struct kdbus_msg *msg)
1299 return kdbus_free(conn, (uintptr_t)msg - (uintptr_t)conn->buf);
1302 wur int kdbus_name_acquire(struct kdbus_conn *conn,
1303 const char *name, uint64_t *flags)
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;
1311 cmd_name = alloca(size);
1313 memset(cmd_name, 0, size);
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);
1320 cmd_name->size = size;
1322 cmd_name->flags = *flags;
1324 ret = kdbus_cmd_name_acquire(conn->fd, cmd_name);
1326 kdbus_printf("error acquiring name: %s\n", strerror(-ret));
1330 kdbus_printf("%s(): flags after call: 0x%llx\n", __func__,
1331 cmd_name->return_flags);
1334 *flags = cmd_name->return_flags;
1339 wur int kdbus_name_release(struct kdbus_conn *conn, const char *name)
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;
1347 cmd_name = alloca(size);
1349 memset(cmd_name, 0, size);
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);
1356 cmd_name->size = size;
1358 kdbus_printf("conn %lld giving up name '%s'\n",
1359 (unsigned long long) conn->id, name);
1361 ret = kdbus_cmd_name_release(conn->fd, cmd_name);
1363 kdbus_printf("error releasing name: %s\n", strerror(-ret));
1370 wur int kdbus_list(struct kdbus_conn *conn, uint64_t flags)
1372 struct kdbus_cmd_list cmd_list = {};
1373 struct kdbus_info *list, *name;
1376 cmd_list.size = sizeof(cmd_list);
1377 cmd_list.flags = flags;
1379 ret = kdbus_cmd_list(conn->fd, &cmd_list);
1381 kdbus_printf("error listing names: %d (%m)\n", ret);
1385 kdbus_printf("REGISTRY:\n");
1386 list = (struct kdbus_info *)(conn->buf + cmd_list.offset);
1388 KDBUS_FOREACH(name, list, cmd_list.list_size) {
1390 struct kdbus_item *item;
1391 const char *n = "MISSING-NAME";
1393 if (name->size == sizeof(struct kdbus_cmd))
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;
1401 kdbus_printf("%8llu flags=0x%08llx conn=0x%08llx '%s'\n",
1403 (unsigned long long) flags,
1409 ret = kdbus_free(conn, cmd_list.offset);
1414 wur int kdbus_conn_update_attach_flags(struct kdbus_conn *conn,
1415 uint64_t attach_flags_send,
1416 uint64_t attach_flags_recv)
1420 struct kdbus_cmd *update;
1421 struct kdbus_item *item;
1423 size = sizeof(struct kdbus_cmd);
1424 size += KDBUS_ITEM_SIZE(sizeof(uint64_t)) * 2;
1426 update = alloc(size);
1428 kdbus_printf("error alloc: %m\n");
1432 memset(update, 0, size);
1433 update->size = size;
1435 item = update->items;
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);
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);
1447 ret = kdbus_cmd_update(conn->fd, update);
1449 kdbus_printf("error conn update: %d (%m)\n", ret);
1452 conn->attach_flags_recv = attach_flags_recv;
1457 wur int kdbus_conn_update_policy(struct kdbus_conn *conn, const char *name,
1458 const struct kdbus_policy_access *access,
1461 struct kdbus_cmd *update;
1462 struct kdbus_item *item;
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));
1470 update = alloc(size);
1472 kdbus_printf("error alloc: %m\n");
1476 memset(update, 0, size);
1477 update->size = size;
1479 item = update->items;
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);
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;
1491 item->policy_access.type = access[i].type;
1492 item->policy_access.access = access[i].access;
1493 item->policy_access.id = access[i].id;
1495 item = KDBUS_ITEM_NEXT(item);
1498 ret = kdbus_cmd_update(conn->fd, update);
1500 kdbus_printf("error conn update: %d (%m)\n", ret);
1507 wur int kdbus_add_match_id(struct kdbus_conn *conn, uint64_t cookie,
1508 uint64_t type, uint64_t id)
1511 struct kdbus_cmd_match cmd;
1515 struct kdbus_notify_id_change chg;
1520 memset(&buf, 0, sizeof(buf));
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;
1528 ret = kdbus_cmd_match_add(conn->fd, &buf.cmd);
1530 kdbus_printf("--- error adding conn match: %d (%m)\n", ret);
1535 wur int kdbus_add_match_empty(struct kdbus_conn *conn)
1538 struct kdbus_cmd_match cmd;
1539 struct kdbus_item item;
1543 memset(&buf, 0, sizeof(buf));
1545 buf.item.size = sizeof(uint64_t) * 3;
1546 buf.item.type = KDBUS_ITEM_ID;
1547 buf.item.id = KDBUS_MATCH_ID_ANY;
1549 buf.cmd.size = sizeof(buf.cmd) + buf.item.size;
1551 ret = kdbus_cmd_match_add(conn->fd, &buf.cmd);
1553 kdbus_printf("--- error adding conn match: %d (%m)\n", ret);
1558 static wur int all_ids_are_mapped(const char *path)
1562 uint32_t inside_id, length;
1564 file = fopen(path, "r");
1567 kdbus_printf("error fopen() %s: %d (%m)\n",
1572 ret = fscanf(file, "%u\t%*u\t%u", &inside_id, &length);
1579 kdbus_printf("--- error fscanf(): %d\n", ret);
1587 * If length is 4294967295 which means the invalid uid
1588 * (uid_t) -1 then we are able to map all uid/gids
1590 if (inside_id == 0 && length == (uid_t) -1)
1596 wur int all_uids_gids_are_mapped(void)
1600 ret = all_ids_are_mapped("/proc/self/uid_map");
1602 kdbus_printf("--- error not all uids are mapped\n");
1606 ret = all_ids_are_mapped("/proc/self/gid_map");
1608 kdbus_printf("--- error not all gids are mapped\n");
1615 wur int drop_privileges(uid_t uid, gid_t gid)
1619 ret = setgroups(0, NULL);
1622 kdbus_printf("error setgroups: %d (%m)\n", ret);
1626 ret = setresgid(gid, gid, gid);
1629 kdbus_printf("error setresgid: %d (%m)\n", ret);
1633 ret = setresuid(uid, uid, uid);
1636 kdbus_printf("error setresuid: %d (%m)\n", ret);
1643 wur uint64_t now(clockid_t clock)
1645 struct timespec spec;
1647 clock_gettime(clock, &spec);
1648 return spec.tv_sec * 1000ULL * 1000ULL * 1000ULL + spec.tv_nsec;
1651 wur char *unique_name(const char *prefix)
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>
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
1669 * The <random> part makes the string always look vastly different,
1670 * the <time> part makes sure no two calls return the same string.
1673 u_now = now(CLOCK_MONOTONIC);
1675 for (i = 0; i < sizeof(n) - 1; ++i)
1676 n[i] = 'a' + (rand() % ('z' - 'a'));
1677 n[sizeof(n) - 1] = 0;
1679 r = asprintf(&str, "%s-%s-%" PRIu64, prefix, n, u_now);
1686 static wur int do_userns_map_id(const char *map_file,
1694 map = strndupa(map_id, strlen(map_id));
1697 kdbus_printf("error strndupa %s: %d (%m)\n",
1702 for (i = 0; i < strlen(map); i++)
1706 fd = open(map_file, O_RDWR);
1709 kdbus_printf("error open %s: %d (%m)\n",
1714 ret = write(fd, map, strlen(map));
1717 kdbus_printf("error write to %s: %d (%m)\n",
1729 wur int userns_map_uid_gid(pid_t pid,
1730 const char *map_uid,
1731 const char *map_gid)
1734 char file_id[128] = {'\0'};
1736 snprintf(file_id, sizeof(file_id), "/proc/%ld/uid_map",
1739 ret = do_userns_map_id(file_id, map_uid);
1743 snprintf(file_id, sizeof(file_id), "/proc/%ld/setgroups",
1746 fd = open(file_id, O_WRONLY);
1748 ret = write(fd, "deny\n", 5);
1751 return ret<0 ? ret : -EIO;
1754 snprintf(file_id, sizeof(file_id), "/proc/%ld/gid_map",
1757 return do_userns_map_id(file_id, map_gid);
1760 static wur int do_cap_get_flag(cap_t caps, cap_value_t cap)
1763 cap_flag_value_t flag_set;
1765 ret = cap_get_flag(caps, cap, CAP_EFFECTIVE, &flag_set);
1768 kdbus_printf("error cap_get_flag(): %d (%m)\n", ret);
1772 return (flag_set == CAP_SET);
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.
1782 * Terminate args with a negative value.
1784 wur int test_is_capable(int cap, ...)
1790 caps = cap_get_proc();
1793 kdbus_printf("error cap_get_proc(): %d (%m)\n", ret);
1797 ret = do_cap_get_flag(caps, (cap_value_t)cap);
1802 while ((cap = va_arg(ap, int)) > 0) {
1803 ret = do_cap_get_flag(caps, (cap_value_t)cap);
1814 wur int config_user_ns_is_enabled(void)
1816 return (access("/proc/self/uid_map", F_OK) == 0);
1819 wur int config_auditsyscall_is_enabled(void)
1821 return (access("/proc/self/loginuid", F_OK) == 0);
1824 wur int config_cgroups_is_enabled(void)
1826 return (access("/proc/self/cgroup", F_OK) == 0);
1829 wur int config_security_is_enabled(void)
1835 /* CONFIG_SECURITY is disabled */
1836 if (access("/proc/self/attr/current", F_OK) != 0)
1840 * Now only if read() fails with -EINVAL then we assume
1841 * that SECLABEL and LSM are disabled
1843 fd = open("/proc/self/attr/current", O_RDONLY|O_CLOEXEC);
1847 ret = read(fd, buf, sizeof(buf));
1848 if (ret == -1 && errno == EINVAL)