1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #ifdef HAVE_VALGRIND_MEMCHECK_H
23 #include <valgrind/memcheck.h>
32 #include "bus-internal.h"
33 #include "bus-message.h"
34 #include "bus-kernel.h"
35 #include "bus-bloom.h"
38 #define UNIQUE_NAME_MAX (3+DECIMAL_STR_MAX(uint64_t))
40 int bus_kernel_parse_unique_name(const char *s, uint64_t *id) {
46 if (!startswith(s, ":1."))
49 r = safe_atou64(s + 3, id);
56 static void append_payload_vec(struct kdbus_item **d, const void *p, size_t sz) {
62 /* Note that p can be NULL, which encodes a region full of
63 * zeroes, which is useful to optimize certain padding
66 (*d)->size = offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec);
67 (*d)->type = KDBUS_ITEM_PAYLOAD_VEC;
68 (*d)->vec.address = PTR_TO_UINT64(p);
71 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
74 static void append_payload_memfd(struct kdbus_item **d, int memfd, size_t sz) {
80 (*d)->size = offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd);
81 (*d)->type = KDBUS_ITEM_PAYLOAD_MEMFD;
82 (*d)->memfd.fd = memfd;
83 (*d)->memfd.size = sz;
85 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
88 static void append_destination(struct kdbus_item **d, const char *s, size_t length) {
94 (*d)->size = offsetof(struct kdbus_item, str) + length + 1;
95 (*d)->type = KDBUS_ITEM_DST_NAME;
96 memcpy((*d)->str, s, length + 1);
98 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
101 static void* append_bloom(struct kdbus_item **d, size_t length) {
108 (*d)->size = offsetof(struct kdbus_item, data) + length;
109 (*d)->type = KDBUS_ITEM_BLOOM;
112 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
117 static void append_fds(struct kdbus_item **d, const int fds[], unsigned n_fds) {
123 (*d)->size = offsetof(struct kdbus_item, fds) + sizeof(int) * n_fds;
124 (*d)->type = KDBUS_ITEM_FDS;
125 memcpy((*d)->fds, fds, sizeof(int) * n_fds);
127 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
130 static int bus_message_setup_bloom(sd_bus_message *m, void *bloom) {
137 memset(bloom, 0, BLOOM_SIZE);
139 bloom_add_pair(bloom, "message-type", bus_message_type_to_string(m->header->type));
142 bloom_add_pair(bloom, "interface", m->interface);
144 bloom_add_pair(bloom, "member", m->member);
146 bloom_add_pair(bloom, "path", m->path);
147 bloom_add_pair(bloom, "path-slash-prefix", m->path);
148 bloom_add_prefixes(bloom, "path-slash-prefix", m->path, '/');
151 r = sd_bus_message_rewind(m, true);
155 for (i = 0; i < 64; i++) {
158 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
161 r = sd_bus_message_peek_type(m, &type, NULL);
165 if (type != SD_BUS_TYPE_STRING &&
166 type != SD_BUS_TYPE_OBJECT_PATH &&
167 type != SD_BUS_TYPE_SIGNATURE)
170 r = sd_bus_message_read_basic(m, type, &t);
174 e = stpcpy(buf, "arg");
178 *(e++) = '0' + (i / 10);
179 *(e++) = '0' + (i % 10);
183 bloom_add_pair(bloom, buf, t);
185 strcpy(e, "-dot-prefix");
186 bloom_add_prefixes(bloom, buf, t, '.');
187 strcpy(e, "-slash-prefix");
188 bloom_add_prefixes(bloom, buf, t, '/');
194 static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
195 struct bus_body_part *part;
196 struct kdbus_item *d;
210 if (m->destination) {
211 r = bus_kernel_parse_unique_name(m->destination, &unique);
219 sz = offsetof(struct kdbus_msg, items);
221 assert_cc(ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec)) ==
222 ALIGN8(offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd)));
224 /* Add in fixed header, fields header and payload */
225 sz += (1 + m->n_body_parts) *
226 ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec));
228 /* Add space for bloom filter */
229 sz += ALIGN8(offsetof(struct kdbus_item, data) + BLOOM_SIZE);
231 /* Add in well-known destination header */
233 dl = strlen(m->destination);
234 sz += ALIGN8(offsetof(struct kdbus_item, str) + dl + 1);
237 /* Add space for unix fds */
239 sz += ALIGN8(offsetof(struct kdbus_item, fds) + sizeof(int)*m->n_fds);
241 m->kdbus = memalign(8, sz);
247 m->free_kdbus = true;
248 memset(m->kdbus, 0, sz);
251 ((m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_FLAGS_EXPECT_REPLY) |
252 ((m->header->flags & SD_BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_FLAGS_NO_AUTO_START : 0);
255 m->destination ? unique : KDBUS_DST_ID_BROADCAST;
256 m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS1;
257 m->kdbus->cookie = m->header->serial;
259 m->kdbus->timeout_ns = m->timeout * NSEC_PER_USEC;
264 append_destination(&d, m->destination, dl);
266 append_payload_vec(&d, m->header, BUS_MESSAGE_BODY_BEGIN(m));
268 MESSAGE_FOREACH_PART(part, i, m) {
270 /* If this is padding then simply send a
271 * vector with a NULL data pointer which the
272 * kernel will just pass through. This is the
273 * most efficient way to encode zeroes */
275 append_payload_vec(&d, NULL, part->size);
279 if (part->memfd >= 0 && part->sealed && m->destination) {
280 /* Try to send a memfd, if the part is
281 * sealed and this is not a broadcast. Since we can only */
283 append_payload_memfd(&d, part->memfd, part->size);
287 /* Otherwise let's send a vector to the actual data,
288 * for that we need to map it first. */
289 r = bus_body_part_map(part);
293 append_payload_vec(&d, part->data, part->size);
296 if (m->kdbus->dst_id == KDBUS_DST_ID_BROADCAST) {
299 p = append_bloom(&d, BLOOM_SIZE);
300 r = bus_message_setup_bloom(m, p);
306 append_fds(&d, m->fds, m->n_fds);
308 m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus;
309 assert(m->kdbus->size <= sz);
318 int bus_kernel_take_fd(sd_bus *b) {
319 struct kdbus_cmd_hello hello;
330 hello.size = sizeof(hello);
331 hello.conn_flags = b->hello_flags;
332 hello.attach_flags = b->attach_flags;
333 hello.pool_size = KDBUS_POOL_SIZE;
335 r = ioctl(b->input_fd, KDBUS_CMD_HELLO, &hello);
339 if (!b->kdbus_buffer) {
340 b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, b->input_fd, 0);
341 if (b->kdbus_buffer == MAP_FAILED) {
342 b->kdbus_buffer = NULL;
347 /* The higher 32bit of both flags fields are considered
348 * 'incompatible flags'. Refuse them all for now. */
349 if (hello.bus_flags > 0xFFFFFFFFULL ||
350 hello.conn_flags > 0xFFFFFFFFULL)
353 if (hello.bloom_size != BLOOM_SIZE)
356 if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello.id) < 0)
359 b->unique_id = hello.id;
362 b->bus_client = true;
363 b->can_fds = !!(hello.conn_flags & KDBUS_HELLO_ACCEPT_FD);
365 /* the kernel told us the UUID of the underlying bus */
366 memcpy(b->server_id.bytes, hello.id128, sizeof(b->server_id.bytes));
368 return bus_start_running(b);
371 int bus_kernel_connect(sd_bus *b) {
373 assert(b->input_fd < 0);
374 assert(b->output_fd < 0);
380 b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
384 b->output_fd = b->input_fd;
386 return bus_kernel_take_fd(b);
389 int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
394 assert(bus->state == BUS_RUNNING);
396 r = bus_message_setup_kmsg(bus, m);
400 r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
402 return errno == EAGAIN ? 0 : -errno;
407 static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
409 struct kdbus_item *d;
414 off = (uint8_t *)k - (uint8_t *)bus->kdbus_buffer;
415 ioctl(bus->input_fd, KDBUS_CMD_MSG_RELEASE, &off);
417 KDBUS_PART_FOREACH(d, k, items) {
419 if (d->type == KDBUS_ITEM_FDS)
420 close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
421 else if (d->type == KDBUS_ITEM_PAYLOAD_MEMFD)
422 close_nointr_nofail(d->memfd.fd);
426 static int push_name_owner_changed(sd_bus *bus, const char *name, const char *old_owner, const char *new_owner) {
427 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
432 r = sd_bus_message_new_signal(
434 "/org/freedesktop/DBus",
435 "org.freedesktop.DBus",
441 r = sd_bus_message_append(m, "sss", name, old_owner, new_owner);
445 m->sender = "org.freedesktop.DBus";
447 r = bus_seal_synthetic_message(bus, m);
451 bus->rqueue[bus->rqueue_size++] = m;
457 static int translate_name_change(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d) {
458 char new_owner[UNIQUE_NAME_MAX], old_owner[UNIQUE_NAME_MAX];
464 if (d->name_change.flags != 0)
467 if (d->type == KDBUS_ITEM_NAME_ADD)
470 sprintf(old_owner, ":1.%llu", (unsigned long long) d->name_change.old_id);
472 if (d->type == KDBUS_ITEM_NAME_REMOVE)
475 sprintf(new_owner, ":1.%llu", (unsigned long long) d->name_change.new_id);
477 return push_name_owner_changed(bus, d->name_change.name, old_owner, new_owner);
480 static int translate_id_change(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d) {
481 char owner[UNIQUE_NAME_MAX];
487 sprintf(owner, ":1.%llu", d->id_change.id);
489 return push_name_owner_changed(
491 d->type == KDBUS_ITEM_ID_ADD ? NULL : owner,
492 d->type == KDBUS_ITEM_ID_ADD ? owner : NULL);
495 static int translate_reply(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d) {
496 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
503 r = bus_message_new_synthetic_error(
506 d->type == KDBUS_ITEM_REPLY_TIMEOUT ?
507 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call timed out") :
508 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call peer died"),
513 m->sender = "org.freedesktop.DBus";
515 r = bus_seal_synthetic_message(bus, m);
519 bus->rqueue[bus->rqueue_size++] = m;
525 static int bus_kernel_translate_message(sd_bus *bus, struct kdbus_msg *k) {
526 struct kdbus_item *d, *found = NULL;
528 static int (* const translate[])(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d) = {
529 [KDBUS_ITEM_NAME_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
530 [KDBUS_ITEM_NAME_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
531 [KDBUS_ITEM_NAME_CHANGE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
533 [KDBUS_ITEM_ID_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
534 [KDBUS_ITEM_ID_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
536 [KDBUS_ITEM_REPLY_TIMEOUT - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
537 [KDBUS_ITEM_REPLY_DEAD - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
542 assert(k->payload_type == KDBUS_PAYLOAD_KERNEL);
544 KDBUS_PART_FOREACH(d, k, items) {
545 if (d->type >= _KDBUS_ITEM_KERNEL_BASE && d->type < _KDBUS_ITEM_KERNEL_BASE + ELEMENTSOF(translate)) {
550 log_debug("Got unknown field from kernel %llu", d->type);
554 log_debug("Didn't find a kernel message to translate.");
558 return translate[found->type - _KDBUS_ITEM_KERNEL_BASE](bus, k, found);
561 int kdbus_translate_attach_flags(uint64_t mask, uint64_t *kdbus_mask) {
565 SET_FLAG(m, KDBUS_ATTACH_CREDS,
566 !!(mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID)));
568 SET_FLAG(m, KDBUS_ATTACH_COMM,
569 !!(mask & (SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM)));
571 SET_FLAG(m, KDBUS_ATTACH_EXE,
572 !!(mask & SD_BUS_CREDS_EXE));
574 SET_FLAG(m, KDBUS_ATTACH_CMDLINE,
575 !!(mask & SD_BUS_CREDS_CMDLINE));
577 SET_FLAG(m, KDBUS_ATTACH_CGROUP,
578 !!(mask & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID)));
580 SET_FLAG(m, KDBUS_ATTACH_CAPS,
581 !!(mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)));
583 SET_FLAG(m, KDBUS_ATTACH_SECLABEL,
584 !!(mask & SD_BUS_CREDS_SELINUX_CONTEXT));
586 SET_FLAG(m, KDBUS_ATTACH_AUDIT,
587 !!(mask & (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)));
594 static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
595 sd_bus_message *m = NULL;
596 struct kdbus_item *d;
598 _cleanup_free_ int *fds = NULL;
599 struct bus_header *h = NULL;
600 size_t total, n_bytes = 0, idx = 0;
601 const char *destination = NULL, *seclabel = NULL;
606 assert(k->payload_type == KDBUS_PAYLOAD_DBUS1);
608 KDBUS_PART_FOREACH(d, k, items) {
611 l = d->size - offsetof(struct kdbus_item, data);
615 case KDBUS_ITEM_PAYLOAD_OFF:
617 h = (struct bus_header *)((uint8_t *)bus->kdbus_buffer + d->vec.offset);
619 if (!bus_header_is_complete(h, d->vec.size))
623 n_bytes += d->vec.size;
626 case KDBUS_ITEM_PAYLOAD_MEMFD:
630 n_bytes += d->memfd.size;
633 case KDBUS_ITEM_FDS: {
638 f = realloc(fds, sizeof(int) * (n_fds + j));
643 memcpy(fds + n_fds, d->fds, sizeof(int) * j);
648 case KDBUS_ITEM_SECLABEL:
657 r = bus_header_message_size(h, &total);
661 if (n_bytes != total)
664 r = bus_message_from_header(bus, h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m);
668 KDBUS_PART_FOREACH(d, k, items) {
671 l = d->size - offsetof(struct kdbus_item, data);
675 case KDBUS_ITEM_PAYLOAD_OFF: {
678 begin_body = BUS_MESSAGE_BODY_BEGIN(m);
680 if (idx + d->vec.size > begin_body) {
681 struct bus_body_part *part;
683 /* Contains body material */
685 part = message_append_part(m);
691 /* A -1 offset is NUL padding. */
692 part->is_zero = d->vec.offset == ~0ULL;
694 if (idx >= begin_body) {
696 part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset;
697 part->size = d->vec.size;
700 part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset + (begin_body - idx);
701 part->size = d->vec.size - (begin_body - idx);
711 case KDBUS_ITEM_PAYLOAD_MEMFD: {
712 struct bus_body_part *part;
714 if (idx < BUS_MESSAGE_BODY_BEGIN(m)) {
719 part = message_append_part(m);
725 part->memfd = d->memfd.fd;
726 part->size = d->memfd.size;
729 idx += d->memfd.size;
733 case KDBUS_ITEM_CREDS:
734 m->creds.pid_starttime = d->creds.starttime / NSEC_PER_USEC;
735 m->creds.uid = d->creds.uid;
736 m->creds.gid = d->creds.gid;
737 m->creds.pid = d->creds.pid;
738 m->creds.tid = d->creds.tid;
739 m->creds.mask |= (SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID) & bus->creds_mask;
742 case KDBUS_ITEM_TIMESTAMP:
743 m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC;
744 m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC;
747 case KDBUS_ITEM_PID_COMM:
748 m->creds.comm = d->str;
749 m->creds.mask |= SD_BUS_CREDS_COMM & bus->creds_mask;
752 case KDBUS_ITEM_TID_COMM:
753 m->creds.tid_comm = d->str;
754 m->creds.mask |= SD_BUS_CREDS_TID_COMM & bus->creds_mask;
758 m->creds.exe = d->str;
759 m->creds.mask |= SD_BUS_CREDS_EXE & bus->creds_mask;
762 case KDBUS_ITEM_CMDLINE:
763 m->creds.cmdline = d->str;
764 m->creds.cmdline_length = l;
765 m->creds.mask |= SD_BUS_CREDS_CMDLINE & bus->creds_mask;
768 case KDBUS_ITEM_CGROUP:
769 m->creds.cgroup = d->str;
770 m->creds.mask |= (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID) & bus->creds_mask;
773 case KDBUS_ITEM_AUDIT:
774 m->creds.audit_session_id = d->audit.sessionid;
775 m->creds.audit_login_uid = d->audit.loginuid;
776 m->creds.mask |= (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID) & bus->creds_mask;
779 case KDBUS_ITEM_CAPS:
780 m->creds.capability = d->data;
781 m->creds.capability_size = l;
782 m->creds.mask |= (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS) & bus->creds_mask;
785 case KDBUS_ITEM_DST_NAME:
786 destination = d->str;
790 case KDBUS_ITEM_SECLABEL:
791 case KDBUS_ITEM_NAMES:
795 log_debug("Got unknown field from kernel %llu", d->type);
799 r = bus_message_parse_fields(m);
803 if (k->src_id == KDBUS_SRC_ID_KERNEL)
804 m->sender = "org.freedesktop.DBus";
806 snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
807 m->sender = m->sender_buffer;
810 if (!m->destination) {
812 m->destination = destination;
813 else if (k->dst_id != KDBUS_DST_ID_WELL_KNOWN_NAME &&
814 k->dst_id != KDBUS_DST_ID_BROADCAST) {
815 snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
816 m->destination = m->destination_buffer;
820 /* We take possession of the kmsg struct now */
822 m->release_kdbus = true;
826 bus->rqueue[bus->rqueue_size++] = m;
832 struct bus_body_part *part;
835 /* Make sure the memfds are not freed twice */
836 MESSAGE_FOREACH_PART(part, i, m)
837 if (part->memfd >= 0)
840 sd_bus_message_unref(m);
846 int bus_kernel_read_message(sd_bus *bus) {
853 r = bus_rqueue_make_room(bus);
857 r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, &off);
864 k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + off);
866 if (k->payload_type == KDBUS_PAYLOAD_DBUS1)
867 r = bus_kernel_make_message(bus, k);
868 else if (k->payload_type == KDBUS_PAYLOAD_KERNEL)
869 r = bus_kernel_translate_message(bus, k);
874 close_kdbus_msg(bus, k);
876 return r < 0 ? r : 1;
879 int bus_kernel_create(const char *name, char **s) {
880 struct kdbus_cmd_bus_make *make;
881 struct kdbus_item *n;
889 fd = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
894 make = alloca0(offsetof(struct kdbus_cmd_bus_make, items) +
895 KDBUS_PART_HEADER_SIZE + sizeof(uint64_t) +
896 KDBUS_PART_HEADER_SIZE + DECIMAL_STR_MAX(uid_t) + 1 + l + 1);
899 n->type = KDBUS_MAKE_NAME;
900 sprintf(n->str, "%lu-%s", (unsigned long) getuid(), name);
901 n->size = KDBUS_PART_HEADER_SIZE + strlen(n->str) + 1;
903 make->size = offsetof(struct kdbus_cmd_bus_make, items) + n->size;
904 make->flags = KDBUS_MAKE_POLICY_OPEN;
906 make->bloom_size = BLOOM_SIZE;
907 assert_cc(BLOOM_SIZE % 8 == 0);
909 p = strjoin("/dev/kdbus/", n->str, "/bus", NULL);
913 if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
914 close_nointr_nofail(fd);
925 int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *size) {
926 struct memfd_cache *c;
932 if (!bus || !bus->is_kernel)
935 assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
937 if (bus->n_memfd_cache <= 0) {
940 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
942 r = ioctl(bus->input_fd, KDBUS_CMD_MEMFD_NEW, &fd);
951 c = &bus->memfd_cache[--bus->n_memfd_cache];
954 assert(c->size == 0 || c->address);
956 *address = c->address;
960 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
965 static void close_and_munmap(int fd, void *address, size_t size) {
967 assert_se(munmap(address, PAGE_ALIGN(size)) >= 0);
969 close_nointr_nofail(fd);
972 void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t size) {
973 struct memfd_cache *c;
974 uint64_t max_sz = PAGE_ALIGN(MEMFD_CACHE_ITEM_SIZE_MAX);
977 assert(size == 0 || address);
979 if (!bus || !bus->is_kernel) {
980 close_and_munmap(fd, address, size);
984 assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
986 if (bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
987 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
989 close_and_munmap(fd, address, size);
993 c = &bus->memfd_cache[bus->n_memfd_cache++];
995 c->address = address;
997 /* If overly long, let's return a bit to the OS */
999 assert_se(ioctl(fd, KDBUS_CMD_MEMFD_SIZE_SET, &max_sz) >= 0);
1000 assert_se(munmap((uint8_t*) address + max_sz, PAGE_ALIGN(size - max_sz)) >= 0);
1005 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
1008 void bus_kernel_flush_memfd(sd_bus *b) {
1013 for (i = 0; i < b->n_memfd_cache; i++)
1014 close_and_munmap(b->memfd_cache[i].fd, b->memfd_cache[i].address, b->memfd_cache[i].size);
1017 int kdbus_translate_request_name_flags(uint64_t sd_bus_flags, uint64_t *kdbus_flags) {
1019 assert_return(kdbus_flags != NULL, -EINVAL);
1023 if (sd_bus_flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
1024 *kdbus_flags |= KDBUS_NAME_ALLOW_REPLACEMENT;
1026 if (sd_bus_flags & SD_BUS_NAME_REPLACE_EXISTING)
1027 *kdbus_flags |= KDBUS_NAME_REPLACE_EXISTING;
1029 if (!(sd_bus_flags & SD_BUS_NAME_DO_NOT_QUEUE))
1030 *kdbus_flags |= KDBUS_NAME_QUEUE;