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)
360 b->bus_client = true;
361 b->can_fds = !!(hello.conn_flags & KDBUS_HELLO_ACCEPT_FD);
363 /* the kernel told us the UUID of the underlying bus */
364 memcpy(b->server_id.bytes, hello.id128, sizeof(b->server_id.bytes));
366 r = bus_start_running(b);
373 int bus_kernel_connect(sd_bus *b) {
375 assert(b->input_fd < 0);
376 assert(b->output_fd < 0);
382 b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
386 b->output_fd = b->input_fd;
388 return bus_kernel_take_fd(b);
391 int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
396 assert(bus->state == BUS_RUNNING);
398 r = bus_message_setup_kmsg(bus, m);
402 r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
404 return errno == EAGAIN ? 0 : -errno;
409 static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
411 struct kdbus_item *d;
416 off = (uint8_t *)k - (uint8_t *)bus->kdbus_buffer;
417 ioctl(bus->input_fd, KDBUS_CMD_MSG_RELEASE, &off);
419 KDBUS_PART_FOREACH(d, k, items) {
421 if (d->type == KDBUS_ITEM_FDS)
422 close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
423 else if (d->type == KDBUS_ITEM_PAYLOAD_MEMFD)
424 close_nointr_nofail(d->memfd.fd);
428 static int return_name_owner_changed(sd_bus *bus, const char *name, const char *old_owner, const char *new_owner, sd_bus_message **ret) {
429 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
435 r = sd_bus_message_new_signal(
437 "/org/freedesktop/DBus",
438 "org.freedesktop.DBus",
444 r = sd_bus_message_append(m, "sss", name, old_owner, new_owner);
448 m->sender = "org.freedesktop.DBus";
450 r = bus_seal_message(bus, m);
460 static int translate_name_change(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d, sd_bus_message **ret) {
461 char new_owner[UNIQUE_NAME_MAX], old_owner[UNIQUE_NAME_MAX];
468 if (d->name_change.flags != 0)
471 if (d->type == KDBUS_ITEM_NAME_ADD)
474 sprintf(old_owner, ":1.%llu", (unsigned long long) d->name_change.old_id);
476 if (d->type == KDBUS_ITEM_NAME_REMOVE)
479 sprintf(new_owner, ":1.%llu", (unsigned long long) d->name_change.new_id);
481 return return_name_owner_changed(bus, d->name_change.name, old_owner, new_owner, ret);
484 static int translate_id_change(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d, sd_bus_message **ret) {
485 char owner[UNIQUE_NAME_MAX];
492 sprintf(owner, ":1.%llu", d->id_change.id);
494 return return_name_owner_changed(
496 d->type == KDBUS_ITEM_ID_ADD ? NULL : owner,
497 d->type == KDBUS_ITEM_ID_ADD ? owner : NULL,
501 static int translate_reply(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d, sd_bus_message **ret) {
502 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
510 r = bus_message_new_synthetic_error(
513 d->type == KDBUS_ITEM_REPLY_TIMEOUT ?
514 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call timed out") :
515 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call peer died"),
520 m->sender = "org.freedesktop.DBus";
522 r = bus_seal_message(bus, m);
532 static int bus_kernel_translate_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_message **ret) {
533 struct kdbus_item *d, *found = NULL;
535 static int (* const translate[])(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d, sd_bus_message **ret) = {
536 [KDBUS_ITEM_NAME_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
537 [KDBUS_ITEM_NAME_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
538 [KDBUS_ITEM_NAME_CHANGE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
540 [KDBUS_ITEM_ID_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
541 [KDBUS_ITEM_ID_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
543 [KDBUS_ITEM_REPLY_TIMEOUT - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
544 [KDBUS_ITEM_REPLY_DEAD - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
550 assert(k->payload_type == KDBUS_PAYLOAD_KERNEL);
552 KDBUS_PART_FOREACH(d, k, items) {
553 if (d->type >= _KDBUS_ITEM_KERNEL_BASE && d->type < _KDBUS_ITEM_KERNEL_BASE + ELEMENTSOF(translate)) {
558 log_debug("Got unknown field from kernel %llu", d->type);
562 log_debug("Didn't find a kernel message to translate.");
566 return translate[found->type](bus, k, d, ret);
569 int kdbus_translate_attach_flags(uint64_t mask, uint64_t *kdbus_mask) {
573 SET_FLAG(m, KDBUS_ATTACH_CREDS,
574 !!(mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID)));
576 SET_FLAG(m, KDBUS_ATTACH_COMM,
577 !!(mask & (SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM)));
579 SET_FLAG(m, KDBUS_ATTACH_EXE,
580 !!(mask & SD_BUS_CREDS_EXE));
582 SET_FLAG(m, KDBUS_ATTACH_CMDLINE,
583 !!(mask & SD_BUS_CREDS_CMDLINE));
585 SET_FLAG(m, KDBUS_ATTACH_CGROUP,
586 !!(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)));
588 SET_FLAG(m, KDBUS_ATTACH_CAPS,
589 !!(mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)));
591 SET_FLAG(m, KDBUS_ATTACH_SECLABEL,
592 !!(mask & SD_BUS_CREDS_SELINUX_CONTEXT));
594 SET_FLAG(m, KDBUS_ATTACH_AUDIT,
595 !!(mask & (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)));
602 static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_message **ret) {
603 sd_bus_message *m = NULL;
604 struct kdbus_item *d;
606 _cleanup_free_ int *fds = NULL;
607 struct bus_header *h = NULL;
608 size_t total, n_bytes = 0, idx = 0;
609 const char *destination = NULL, *seclabel = NULL;
615 assert(k->payload_type == KDBUS_PAYLOAD_DBUS1);
617 KDBUS_PART_FOREACH(d, k, items) {
620 l = d->size - offsetof(struct kdbus_item, data);
624 case KDBUS_ITEM_PAYLOAD_OFF:
626 h = (struct bus_header *)((uint8_t *)bus->kdbus_buffer + d->vec.offset);
628 if (!bus_header_is_complete(h, d->vec.size))
632 n_bytes += d->vec.size;
635 case KDBUS_ITEM_PAYLOAD_MEMFD:
639 n_bytes += d->memfd.size;
642 case KDBUS_ITEM_FDS: {
647 f = realloc(fds, sizeof(int) * (n_fds + j));
652 memcpy(fds + n_fds, d->fds, sizeof(int) * j);
657 case KDBUS_ITEM_SECLABEL:
666 r = bus_header_message_size(h, &total);
670 if (n_bytes != total)
673 r = bus_message_from_header(bus, h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m);
677 KDBUS_PART_FOREACH(d, k, items) {
680 l = d->size - offsetof(struct kdbus_item, data);
684 case KDBUS_ITEM_PAYLOAD_OFF: {
687 begin_body = BUS_MESSAGE_BODY_BEGIN(m);
689 if (idx + d->vec.size > begin_body) {
690 struct bus_body_part *part;
692 /* Contains body material */
694 part = message_append_part(m);
700 /* A -1 offset is NUL padding. */
701 part->is_zero = d->vec.offset == ~0ULL;
703 if (idx >= begin_body) {
705 part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset;
706 part->size = d->vec.size;
709 part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset + (begin_body - idx);
710 part->size = d->vec.size - (begin_body - idx);
720 case KDBUS_ITEM_PAYLOAD_MEMFD: {
721 struct bus_body_part *part;
723 if (idx < BUS_MESSAGE_BODY_BEGIN(m)) {
728 part = message_append_part(m);
734 part->memfd = d->memfd.fd;
735 part->size = d->memfd.size;
738 idx += d->memfd.size;
742 case KDBUS_ITEM_CREDS:
743 m->creds.pid_starttime = d->creds.starttime / NSEC_PER_USEC;
744 m->creds.uid = d->creds.uid;
745 m->creds.gid = d->creds.gid;
746 m->creds.pid = d->creds.pid;
747 m->creds.tid = d->creds.tid;
748 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;
751 case KDBUS_ITEM_TIMESTAMP:
752 m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC;
753 m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC;
756 case KDBUS_ITEM_PID_COMM:
757 m->creds.comm = d->str;
758 m->creds.mask |= SD_BUS_CREDS_COMM & bus->creds_mask;
761 case KDBUS_ITEM_TID_COMM:
762 m->creds.tid_comm = d->str;
763 m->creds.mask |= SD_BUS_CREDS_TID_COMM & bus->creds_mask;
767 m->creds.exe = d->str;
768 m->creds.mask |= SD_BUS_CREDS_EXE & bus->creds_mask;
771 case KDBUS_ITEM_CMDLINE:
772 m->creds.cmdline = d->str;
773 m->creds.cmdline_length = l;
774 m->creds.mask |= SD_BUS_CREDS_CMDLINE & bus->creds_mask;
777 case KDBUS_ITEM_CGROUP:
778 m->creds.cgroup = d->str;
779 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;
782 case KDBUS_ITEM_AUDIT:
783 m->creds.audit_session_id = d->audit.sessionid;
784 m->creds.audit_login_uid = d->audit.loginuid;
785 m->creds.mask |= (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID) & bus->creds_mask;
788 case KDBUS_ITEM_CAPS:
789 m->creds.capability = d->data;
790 m->creds.capability_size = l;
791 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;
794 case KDBUS_ITEM_DST_NAME:
795 destination = d->str;
799 case KDBUS_ITEM_SECLABEL:
800 case KDBUS_ITEM_NAMES:
804 log_debug("Got unknown field from kernel %llu", d->type);
808 r = bus_message_parse_fields(m);
812 if (k->src_id == KDBUS_SRC_ID_KERNEL)
813 m->sender = "org.freedesktop.DBus";
815 snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
816 m->sender = m->sender_buffer;
819 if (!m->destination) {
821 m->destination = destination;
822 else if (k->dst_id != KDBUS_DST_ID_WELL_KNOWN_NAME &&
823 k->dst_id != KDBUS_DST_ID_BROADCAST) {
824 snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
825 m->destination = m->destination_buffer;
829 /* We take possession of the kmsg struct now */
831 m->release_kdbus = true;
841 struct bus_body_part *part;
844 /* Make sure the memfds are not freed twice */
845 MESSAGE_FOREACH_PART(part, i, m)
846 if (part->memfd >= 0)
849 sd_bus_message_unref(m);
855 int bus_kernel_read_message(sd_bus *bus, sd_bus_message **m) {
863 r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, &off);
870 k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + off);
872 if (k->payload_type == KDBUS_PAYLOAD_DBUS1)
873 r = bus_kernel_make_message(bus, k, m);
874 else if (k->payload_type == KDBUS_PAYLOAD_KERNEL)
875 r = bus_kernel_translate_message(bus, k, m);
880 close_kdbus_msg(bus, k);
882 return r < 0 ? r : 1;
885 int bus_kernel_create(const char *name, char **s) {
886 struct kdbus_cmd_bus_make *make;
887 struct kdbus_item *n;
895 fd = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
900 make = alloca0(offsetof(struct kdbus_cmd_bus_make, items) +
901 KDBUS_PART_HEADER_SIZE + sizeof(uint64_t) +
902 KDBUS_PART_HEADER_SIZE + DECIMAL_STR_MAX(uid_t) + 1 + l + 1);
905 n->type = KDBUS_MAKE_NAME;
906 sprintf(n->str, "%lu-%s", (unsigned long) getuid(), name);
907 n->size = KDBUS_PART_HEADER_SIZE + strlen(n->str) + 1;
909 make->size = offsetof(struct kdbus_cmd_bus_make, items) + n->size;
910 make->flags = KDBUS_MAKE_POLICY_OPEN;
912 make->bloom_size = BLOOM_SIZE;
913 assert_cc(BLOOM_SIZE % 8 == 0);
915 p = strjoin("/dev/kdbus/", n->str, "/bus", NULL);
919 if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
920 close_nointr_nofail(fd);
931 int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *size) {
932 struct memfd_cache *c;
938 if (!bus || !bus->is_kernel)
941 assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
943 if (bus->n_memfd_cache <= 0) {
946 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
948 r = ioctl(bus->input_fd, KDBUS_CMD_MEMFD_NEW, &fd);
957 c = &bus->memfd_cache[--bus->n_memfd_cache];
960 assert(c->size == 0 || c->address);
962 *address = c->address;
966 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
971 static void close_and_munmap(int fd, void *address, size_t size) {
973 assert_se(munmap(address, PAGE_ALIGN(size)) >= 0);
975 close_nointr_nofail(fd);
978 void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t size) {
979 struct memfd_cache *c;
980 uint64_t max_sz = PAGE_ALIGN(MEMFD_CACHE_ITEM_SIZE_MAX);
983 assert(size == 0 || address);
985 if (!bus || !bus->is_kernel) {
986 close_and_munmap(fd, address, size);
990 assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
992 if (bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
993 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
995 close_and_munmap(fd, address, size);
999 c = &bus->memfd_cache[bus->n_memfd_cache++];
1001 c->address = address;
1003 /* If overly long, let's return a bit to the OS */
1004 if (size > max_sz) {
1005 assert_se(ioctl(fd, KDBUS_CMD_MEMFD_SIZE_SET, &max_sz) >= 0);
1006 assert_se(munmap((uint8_t*) address + max_sz, PAGE_ALIGN(size - max_sz)) >= 0);
1011 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
1014 void bus_kernel_flush_memfd(sd_bus *b) {
1019 for (i = 0; i < b->n_memfd_cache; i++)
1020 close_and_munmap(b->memfd_cache[i].fd, b->memfd_cache[i].address, b->memfd_cache[i].size);
1023 int kdbus_translate_request_name_flags(uint64_t sd_bus_flags, uint64_t *kdbus_flags) {
1025 assert_return(kdbus_flags != NULL, -EINVAL);
1029 if (sd_bus_flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
1030 *kdbus_flags |= KDBUS_NAME_ALLOW_REPLACEMENT;
1032 if (sd_bus_flags & SD_BUS_NAME_REPLACE_EXISTING)
1033 *kdbus_flags |= KDBUS_NAME_REPLACE_EXISTING;
1035 if (!(sd_bus_flags & SD_BUS_NAME_DO_NOT_QUEUE))
1036 *kdbus_flags |= KDBUS_NAME_QUEUE;