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>
33 #include "bus-internal.h"
34 #include "bus-message.h"
35 #include "bus-kernel.h"
36 #include "bus-bloom.h"
39 #define UNIQUE_NAME_MAX (3+DECIMAL_STR_MAX(uint64_t))
41 int bus_kernel_parse_unique_name(const char *s, uint64_t *id) {
47 if (!startswith(s, ":1."))
50 r = safe_atou64(s + 3, id);
57 static void append_payload_vec(struct kdbus_item **d, const void *p, size_t sz) {
63 /* Note that p can be NULL, which encodes a region full of
64 * zeroes, which is useful to optimize certain padding
67 (*d)->size = offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec);
68 (*d)->type = KDBUS_ITEM_PAYLOAD_VEC;
69 (*d)->vec.address = PTR_TO_UINT64(p);
72 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
75 static void append_payload_memfd(struct kdbus_item **d, int memfd, size_t sz) {
81 (*d)->size = offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd);
82 (*d)->type = KDBUS_ITEM_PAYLOAD_MEMFD;
83 (*d)->memfd.fd = memfd;
84 (*d)->memfd.size = sz;
86 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
89 static void append_destination(struct kdbus_item **d, const char *s, size_t length) {
95 (*d)->size = offsetof(struct kdbus_item, str) + length + 1;
96 (*d)->type = KDBUS_ITEM_DST_NAME;
97 memcpy((*d)->str, s, length + 1);
99 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
102 static void* append_bloom(struct kdbus_item **d, size_t length) {
109 (*d)->size = offsetof(struct kdbus_item, data) + length;
110 (*d)->type = KDBUS_ITEM_BLOOM;
113 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
118 static void append_fds(struct kdbus_item **d, const int fds[], unsigned n_fds) {
124 (*d)->size = offsetof(struct kdbus_item, fds) + sizeof(int) * n_fds;
125 (*d)->type = KDBUS_ITEM_FDS;
126 memcpy((*d)->fds, fds, sizeof(int) * n_fds);
128 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
131 static int bus_message_setup_bloom(sd_bus_message *m, void *bloom) {
138 memset(bloom, 0, BLOOM_SIZE);
140 bloom_add_pair(bloom, "message-type", bus_message_type_to_string(m->header->type));
143 bloom_add_pair(bloom, "interface", m->interface);
145 bloom_add_pair(bloom, "member", m->member);
147 bloom_add_pair(bloom, "path", m->path);
148 bloom_add_pair(bloom, "path-slash-prefix", m->path);
149 bloom_add_prefixes(bloom, "path-slash-prefix", m->path, '/');
152 r = sd_bus_message_rewind(m, true);
156 for (i = 0; i < 64; i++) {
159 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
162 r = sd_bus_message_peek_type(m, &type, NULL);
166 if (type != SD_BUS_TYPE_STRING &&
167 type != SD_BUS_TYPE_OBJECT_PATH &&
168 type != SD_BUS_TYPE_SIGNATURE)
171 r = sd_bus_message_read_basic(m, type, &t);
175 e = stpcpy(buf, "arg");
179 *(e++) = '0' + (i / 10);
180 *(e++) = '0' + (i % 10);
184 bloom_add_pair(bloom, buf, t);
186 strcpy(e, "-dot-prefix");
187 bloom_add_prefixes(bloom, buf, t, '.');
188 strcpy(e, "-slash-prefix");
189 bloom_add_prefixes(bloom, buf, t, '/');
195 static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
196 struct bus_body_part *part;
197 struct kdbus_item *d;
211 if (m->destination) {
212 r = bus_kernel_parse_unique_name(m->destination, &unique);
220 sz = offsetof(struct kdbus_msg, items);
222 assert_cc(ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec)) ==
223 ALIGN8(offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd)));
225 /* Add in fixed header, fields header and payload */
226 sz += (1 + m->n_body_parts) *
227 ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec));
229 /* Add space for bloom filter */
230 sz += ALIGN8(offsetof(struct kdbus_item, data) + BLOOM_SIZE);
232 /* Add in well-known destination header */
234 dl = strlen(m->destination);
235 sz += ALIGN8(offsetof(struct kdbus_item, str) + dl + 1);
238 /* Add space for unix fds */
240 sz += ALIGN8(offsetof(struct kdbus_item, fds) + sizeof(int)*m->n_fds);
242 m->kdbus = memalign(8, sz);
248 m->free_kdbus = true;
249 memset(m->kdbus, 0, sz);
252 ((m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_FLAGS_EXPECT_REPLY) |
253 ((m->header->flags & BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_FLAGS_NO_AUTO_START : 0);
256 m->destination ? unique : KDBUS_DST_ID_BROADCAST;
257 m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS;
258 m->kdbus->cookie = m->header->serial;
260 m->kdbus->timeout_ns = m->timeout * NSEC_PER_USEC;
265 append_destination(&d, m->destination, dl);
267 append_payload_vec(&d, m->header, BUS_MESSAGE_BODY_BEGIN(m));
269 MESSAGE_FOREACH_PART(part, i, m) {
271 /* If this is padding then simply send a
272 * vector with a NULL data pointer which the
273 * kernel will just pass through. This is the
274 * most efficient way to encode zeroes */
276 append_payload_vec(&d, NULL, part->size);
280 if (part->memfd >= 0 && part->sealed && m->destination) {
281 /* Try to send a memfd, if the part is
282 * sealed and this is not a broadcast. Since we can only */
284 append_payload_memfd(&d, part->memfd, part->size);
288 /* Otherwise let's send a vector to the actual data,
289 * for that we need to map it first. */
290 r = bus_body_part_map(part);
294 append_payload_vec(&d, part->data, part->size);
297 if (m->kdbus->dst_id == KDBUS_DST_ID_BROADCAST) {
300 p = append_bloom(&d, BLOOM_SIZE);
301 r = bus_message_setup_bloom(m, p);
307 append_fds(&d, m->fds, m->n_fds);
309 m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus;
310 assert(m->kdbus->size <= sz);
319 int bus_kernel_take_fd(sd_bus *b) {
320 struct kdbus_cmd_hello hello;
324 assert_return(!b->is_server, -EINVAL);
329 hello.size = sizeof(hello);
330 hello.conn_flags = b->hello_flags;
331 hello.attach_flags = b->attach_flags;
332 hello.pool_size = KDBUS_POOL_SIZE;
334 r = ioctl(b->input_fd, KDBUS_CMD_HELLO, &hello);
338 if (!b->kdbus_buffer) {
339 b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, b->input_fd, 0);
340 if (b->kdbus_buffer == MAP_FAILED) {
341 b->kdbus_buffer = NULL;
346 /* The higher 32bit of both flags fields are considered
347 * 'incompatible flags'. Refuse them all for now. */
348 if (hello.bus_flags > 0xFFFFFFFFULL ||
349 hello.conn_flags > 0xFFFFFFFFULL)
352 if (hello.bloom_size != BLOOM_SIZE)
355 if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello.id) < 0)
358 b->unique_id = hello.id;
361 b->bus_client = true;
362 b->can_fds = !!(hello.conn_flags & KDBUS_HELLO_ACCEPT_FD);
363 b->message_version = 2;
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);
376 assert_return(!b->is_server, -EINVAL);
378 b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
382 b->output_fd = b->input_fd;
384 return bus_kernel_take_fd(b);
387 int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
392 assert(bus->state == BUS_RUNNING);
394 /* If we can't deliver, we want room for the error message */
395 r = bus_rqueue_make_room(bus);
399 r = bus_message_setup_kmsg(bus, m);
403 r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
405 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
406 sd_bus_message *reply;
408 if (errno == EAGAIN || errno == EINTR)
410 else if (errno == ENXIO || errno == ESRCH) {
412 /* ENXIO: unique name not known
413 * ESRCH: well-known name not known */
415 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
416 sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Destination %s not known", m->destination);
420 } else if (errno == EADDRNOTAVAIL) {
422 /* EADDRNOTAVAIL: activation is possible, but turned off in request flags */
424 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
425 sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Activation of %s not requested", m->destination);
431 r = bus_message_new_synthetic_error(
433 BUS_MESSAGE_SERIAL(m),
440 r = bus_seal_synthetic_message(bus, reply);
444 bus->rqueue[bus->rqueue_size++] = reply;
452 static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
454 struct kdbus_item *d;
459 off = (uint8_t *)k - (uint8_t *)bus->kdbus_buffer;
460 ioctl(bus->input_fd, KDBUS_CMD_FREE, &off);
462 KDBUS_ITEM_FOREACH(d, k, items) {
464 if (d->type == KDBUS_ITEM_FDS)
465 close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
466 else if (d->type == KDBUS_ITEM_PAYLOAD_MEMFD)
467 close_nointr_nofail(d->memfd.fd);
471 static int push_name_owner_changed(sd_bus *bus, const char *name, const char *old_owner, const char *new_owner) {
472 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
477 r = sd_bus_message_new_signal(
479 "/org/freedesktop/DBus",
480 "org.freedesktop.DBus",
486 r = sd_bus_message_append(m, "sss", name, old_owner, new_owner);
490 m->sender = "org.freedesktop.DBus";
492 r = bus_seal_synthetic_message(bus, m);
496 bus->rqueue[bus->rqueue_size++] = m;
502 static int translate_name_change(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d) {
503 char new_owner[UNIQUE_NAME_MAX], old_owner[UNIQUE_NAME_MAX];
509 if (d->name_change.flags != 0)
512 if (d->type == KDBUS_ITEM_NAME_ADD)
515 sprintf(old_owner, ":1.%llu", (unsigned long long) d->name_change.old_id);
517 if (d->type == KDBUS_ITEM_NAME_REMOVE)
520 sprintf(new_owner, ":1.%llu", (unsigned long long) d->name_change.new_id);
522 return push_name_owner_changed(bus, d->name_change.name, old_owner, new_owner);
525 static int translate_id_change(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d) {
526 char owner[UNIQUE_NAME_MAX];
532 sprintf(owner, ":1.%llu", d->id_change.id);
534 return push_name_owner_changed(
536 d->type == KDBUS_ITEM_ID_ADD ? NULL : owner,
537 d->type == KDBUS_ITEM_ID_ADD ? owner : NULL);
540 static int translate_reply(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d) {
541 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
548 r = bus_message_new_synthetic_error(
551 d->type == KDBUS_ITEM_REPLY_TIMEOUT ?
552 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call timed out") :
553 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call peer died"),
558 m->sender = "org.freedesktop.DBus";
560 r = bus_seal_synthetic_message(bus, m);
564 bus->rqueue[bus->rqueue_size++] = m;
570 static int bus_kernel_translate_message(sd_bus *bus, struct kdbus_msg *k) {
571 struct kdbus_item *d, *found = NULL;
573 static int (* const translate[])(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d) = {
574 [KDBUS_ITEM_NAME_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
575 [KDBUS_ITEM_NAME_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
576 [KDBUS_ITEM_NAME_CHANGE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
578 [KDBUS_ITEM_ID_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
579 [KDBUS_ITEM_ID_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
581 [KDBUS_ITEM_REPLY_TIMEOUT - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
582 [KDBUS_ITEM_REPLY_DEAD - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
587 assert(k->payload_type == KDBUS_PAYLOAD_KERNEL);
589 KDBUS_ITEM_FOREACH(d, k, items) {
590 if (d->type >= _KDBUS_ITEM_KERNEL_BASE && d->type < _KDBUS_ITEM_KERNEL_BASE + ELEMENTSOF(translate)) {
595 log_debug("Got unknown field from kernel %llu", d->type);
599 log_debug("Didn't find a kernel message to translate.");
603 return translate[found->type - _KDBUS_ITEM_KERNEL_BASE](bus, k, found);
606 static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
607 sd_bus_message *m = NULL;
608 struct kdbus_item *d;
610 _cleanup_free_ int *fds = NULL;
611 struct bus_header *h = NULL;
612 size_t total, n_bytes = 0, idx = 0;
613 const char *destination = NULL, *seclabel = NULL;
618 assert(k->payload_type == KDBUS_PAYLOAD_DBUS);
620 KDBUS_ITEM_FOREACH(d, k, items) {
623 l = d->size - offsetof(struct kdbus_item, data);
627 case KDBUS_ITEM_PAYLOAD_OFF:
629 h = (struct bus_header *)((uint8_t *)bus->kdbus_buffer + d->vec.offset);
631 if (!bus_header_is_complete(h, d->vec.size))
635 n_bytes += d->vec.size;
638 case KDBUS_ITEM_PAYLOAD_MEMFD:
642 n_bytes += d->memfd.size;
645 case KDBUS_ITEM_FDS: {
650 f = realloc(fds, sizeof(int) * (n_fds + j));
655 memcpy(fds + n_fds, d->fds, sizeof(int) * j);
660 case KDBUS_ITEM_SECLABEL:
669 r = bus_header_message_size(h, &total);
673 if (n_bytes != total)
676 /* on kdbus we only speak native endian gvariant, never dbus1
677 * marshalling or reverse endian */
678 if (h->version != 2 ||
679 h->endian != BUS_NATIVE_ENDIAN)
682 r = bus_message_from_header(bus, h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m);
686 KDBUS_ITEM_FOREACH(d, k, items) {
689 l = d->size - offsetof(struct kdbus_item, data);
693 case KDBUS_ITEM_PAYLOAD_OFF: {
696 begin_body = BUS_MESSAGE_BODY_BEGIN(m);
698 if (idx + d->vec.size > begin_body) {
699 struct bus_body_part *part;
701 /* Contains body material */
703 part = message_append_part(m);
709 /* A -1 offset is NUL padding. */
710 part->is_zero = d->vec.offset == ~0ULL;
712 if (idx >= begin_body) {
714 part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset;
715 part->size = d->vec.size;
718 part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset + (begin_body - idx);
719 part->size = d->vec.size - (begin_body - idx);
729 case KDBUS_ITEM_PAYLOAD_MEMFD: {
730 struct bus_body_part *part;
732 if (idx < BUS_MESSAGE_BODY_BEGIN(m)) {
737 part = message_append_part(m);
743 part->memfd = d->memfd.fd;
744 part->size = d->memfd.size;
747 idx += d->memfd.size;
751 case KDBUS_ITEM_CREDS:
752 m->creds.pid_starttime = d->creds.starttime / NSEC_PER_USEC;
753 m->creds.uid = d->creds.uid;
754 m->creds.gid = d->creds.gid;
755 m->creds.pid = d->creds.pid;
756 m->creds.tid = d->creds.tid;
757 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;
760 case KDBUS_ITEM_TIMESTAMP:
761 m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC;
762 m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC;
765 case KDBUS_ITEM_PID_COMM:
766 m->creds.comm = d->str;
767 m->creds.mask |= SD_BUS_CREDS_COMM & bus->creds_mask;
770 case KDBUS_ITEM_TID_COMM:
771 m->creds.tid_comm = d->str;
772 m->creds.mask |= SD_BUS_CREDS_TID_COMM & bus->creds_mask;
776 m->creds.exe = d->str;
777 m->creds.mask |= SD_BUS_CREDS_EXE & bus->creds_mask;
780 case KDBUS_ITEM_CMDLINE:
781 m->creds.cmdline = d->str;
782 m->creds.cmdline_size = l;
783 m->creds.mask |= SD_BUS_CREDS_CMDLINE & bus->creds_mask;
786 case KDBUS_ITEM_CGROUP:
787 m->creds.cgroup = d->str;
788 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;
791 case KDBUS_ITEM_AUDIT:
792 m->creds.audit_session_id = d->audit.sessionid;
793 m->creds.audit_login_uid = d->audit.loginuid;
794 m->creds.mask |= (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID) & bus->creds_mask;
797 case KDBUS_ITEM_CAPS:
798 m->creds.capability = d->data;
799 m->creds.capability_size = l;
800 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;
803 case KDBUS_ITEM_DST_NAME:
804 destination = d->str;
807 case KDBUS_ITEM_NAME:
808 r = strv_extend(&m->creds.well_known_names, d->name.name);
811 m->creds.mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES & bus->creds_mask;
815 case KDBUS_ITEM_SECLABEL:
819 log_debug("Got unknown field from kernel %llu", d->type);
823 r = bus_message_parse_fields(m);
827 if (k->src_id == KDBUS_SRC_ID_KERNEL)
828 m->sender = "org.freedesktop.DBus";
830 snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
831 m->sender = m->creds.unique_name = m->sender_buffer;
832 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & bus->creds_mask;
835 if (!m->destination) {
837 m->destination = destination;
838 else if (k->dst_id != KDBUS_DST_ID_NAME &&
839 k->dst_id != KDBUS_DST_ID_BROADCAST) {
840 snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
841 m->destination = m->destination_buffer;
845 /* We take possession of the kmsg struct now */
847 m->release_kdbus = true;
851 bus->rqueue[bus->rqueue_size++] = m;
857 struct bus_body_part *part;
860 /* Make sure the memfds are not freed twice */
861 MESSAGE_FOREACH_PART(part, i, m)
862 if (part->memfd >= 0)
865 sd_bus_message_unref(m);
871 int bus_kernel_read_message(sd_bus *bus) {
878 r = bus_rqueue_make_room(bus);
882 r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, &off);
889 k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + off);
891 if (k->payload_type == KDBUS_PAYLOAD_DBUS) {
892 r = bus_kernel_make_message(bus, k);
894 /* Anybody can send us invalid messages, let's just drop them. */
895 if (r == -EBADMSG || r == -EPROTOTYPE) {
896 log_error("Ignoring invalid message: %s", strerror(-r));
900 } else if (k->payload_type == KDBUS_PAYLOAD_KERNEL)
901 r = bus_kernel_translate_message(bus, k);
906 close_kdbus_msg(bus, k);
908 return r < 0 ? r : 1;
911 int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *size) {
912 struct memfd_cache *c;
917 assert_return(bus && bus->is_kernel, -ENOTSUP);
919 assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
921 if (bus->n_memfd_cache <= 0) {
924 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
926 r = ioctl(bus->input_fd, KDBUS_CMD_MEMFD_NEW, &fd);
935 c = &bus->memfd_cache[--bus->n_memfd_cache];
938 assert(c->size == 0 || c->address);
940 *address = c->address;
944 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
949 static void close_and_munmap(int fd, void *address, size_t size) {
951 assert_se(munmap(address, PAGE_ALIGN(size)) >= 0);
953 close_nointr_nofail(fd);
956 void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t size) {
957 struct memfd_cache *c;
958 uint64_t max_sz = PAGE_ALIGN(MEMFD_CACHE_ITEM_SIZE_MAX);
961 assert(size == 0 || address);
963 if (!bus || !bus->is_kernel) {
964 close_and_munmap(fd, address, size);
968 assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
970 if (bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
971 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
973 close_and_munmap(fd, address, size);
977 c = &bus->memfd_cache[bus->n_memfd_cache++];
979 c->address = address;
981 /* If overly long, let's return a bit to the OS */
983 assert_se(ioctl(fd, KDBUS_CMD_MEMFD_SIZE_SET, &max_sz) >= 0);
984 assert_se(munmap((uint8_t*) address + max_sz, PAGE_ALIGN(size - max_sz)) >= 0);
989 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
992 void bus_kernel_flush_memfd(sd_bus *b) {
997 for (i = 0; i < b->n_memfd_cache; i++)
998 close_and_munmap(b->memfd_cache[i].fd, b->memfd_cache[i].address, b->memfd_cache[i].size);
1001 int kdbus_translate_request_name_flags(uint64_t flags, uint64_t *kdbus_flags) {
1004 assert(kdbus_flags);
1006 if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
1007 f |= KDBUS_NAME_ALLOW_REPLACEMENT;
1009 if (flags & SD_BUS_NAME_REPLACE_EXISTING)
1010 f |= KDBUS_NAME_REPLACE_EXISTING;
1012 if (!(flags & SD_BUS_NAME_DO_NOT_QUEUE))
1013 f |= KDBUS_NAME_QUEUE;
1019 int kdbus_translate_attach_flags(uint64_t mask, uint64_t *kdbus_mask) {
1024 if (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID))
1025 m |= KDBUS_ATTACH_CREDS;
1027 if (mask & (SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM))
1028 m |= KDBUS_ATTACH_COMM;
1030 if (mask & SD_BUS_CREDS_EXE)
1031 m |= KDBUS_ATTACH_EXE;
1033 if (mask & SD_BUS_CREDS_CMDLINE)
1034 m |= KDBUS_ATTACH_CMDLINE;
1036 if (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))
1037 m |= KDBUS_ATTACH_CGROUP;
1039 if (mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS))
1040 m |= KDBUS_ATTACH_CAPS;
1042 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT)
1043 m |= KDBUS_ATTACH_SECLABEL;
1045 if (mask & (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID))
1046 m |= KDBUS_ATTACH_AUDIT;
1048 if (mask & SD_BUS_CREDS_WELL_KNOWN_NAMES)
1049 m |= KDBUS_ATTACH_NAMES;
1055 int bus_kernel_create_bus(const char *name, char **s) {
1056 struct kdbus_cmd_bus_make *make;
1057 struct kdbus_item *n;
1063 fd = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
1067 make = alloca0(ALIGN8(offsetof(struct kdbus_cmd_bus_make, items) +
1068 offsetof(struct kdbus_item, str) +
1069 DECIMAL_STR_MAX(uid_t) + 1 + strlen(name) + 1));
1072 sprintf(n->str, "%lu-%s", (unsigned long) getuid(), name);
1073 n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
1074 n->type = KDBUS_ITEM_MAKE_NAME;
1076 make->size = ALIGN8(offsetof(struct kdbus_cmd_bus_make, items) + n->size);
1077 make->flags = KDBUS_MAKE_POLICY_OPEN;
1078 make->bloom_size = BLOOM_SIZE;
1079 assert_cc(BLOOM_SIZE % 8 == 0);
1081 if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
1082 close_nointr_nofail(fd);
1086 /* The higher 32bit of the flags field are considered
1087 * 'incompatible flags'. Refuse them all for now. */
1088 if (make->flags > 0xFFFFFFFFULL) {
1089 close_nointr_nofail(fd);
1096 p = strjoin("/dev/kdbus/", n->str, "/bus", NULL);
1098 close_nointr_nofail(fd);
1108 int bus_kernel_create_starter(const char *bus, const char *name) {
1109 struct kdbus_cmd_hello *hello;
1110 struct kdbus_item *n;
1117 p = alloca(sizeof("/dev/kdbus/") - 1 + DECIMAL_STR_MAX(uid_t) + 1 + strlen(bus) + sizeof("/bus"));
1118 sprintf(p, "/dev/kdbus/%lu-%s/bus", (unsigned long) getuid(), bus);
1120 fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC);
1124 hello = alloca0(ALIGN8(offsetof(struct kdbus_cmd_hello, items) +
1125 offsetof(struct kdbus_item, str) +
1129 strcpy(n->str, name);
1130 n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
1131 n->type = KDBUS_ITEM_STARTER_NAME;
1133 hello->size = ALIGN8(offsetof(struct kdbus_cmd_hello, items) + n->size);
1134 hello->conn_flags = KDBUS_HELLO_STARTER;
1135 hello->pool_size = KDBUS_POOL_SIZE;
1137 if (ioctl(fd, KDBUS_CMD_HELLO, hello) < 0) {
1138 close_nointr_nofail(fd);
1142 /* The higher 32bit of both flags fields are considered
1143 * 'incompatible flags'. Refuse them all for now. */
1144 if (hello->bus_flags > 0xFFFFFFFFULL ||
1145 hello->conn_flags > 0xFFFFFFFFULL) {
1146 close_nointr_nofail(fd);
1150 if (hello->bloom_size != BLOOM_SIZE) {
1151 close_nointr_nofail(fd);
1158 int bus_kernel_create_namespace(const char *name, char **s) {
1159 struct kdbus_cmd_ns_make *make;
1160 struct kdbus_item *n;
1166 fd = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
1170 make = alloca0(ALIGN8(offsetof(struct kdbus_cmd_ns_make, items) +
1171 offsetof(struct kdbus_item, str) +
1175 strcpy(n->str, name);
1176 n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
1177 n->type = KDBUS_ITEM_MAKE_NAME;
1179 make->size = ALIGN8(offsetof(struct kdbus_cmd_ns_make, items) + n->size);
1180 make->flags = KDBUS_MAKE_POLICY_OPEN | KDBUS_MAKE_ACCESS_WORLD;
1182 if (ioctl(fd, KDBUS_CMD_NS_MAKE, make) < 0) {
1183 close_nointr_nofail(fd);
1187 /* The higher 32bit of the flags field are considered
1188 * 'incompatible flags'. Refuse them all for now. */
1189 if (make->flags > 0xFFFFFFFFULL) {
1190 close_nointr_nofail(fd);
1197 p = strappend("/dev/kdbus/ns/", name);
1199 close_nointr_nofail(fd);