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"
37 int bus_kernel_parse_unique_name(const char *s, uint64_t *id) {
43 if (!startswith(s, ":1."))
46 r = safe_atou64(s + 3, id);
53 static void append_payload_vec(struct kdbus_item **d, const void *p, size_t sz) {
59 /* Note that p can be NULL, which encodes a region full of
60 * zeroes, which is useful to optimize certain padding
63 (*d)->size = offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec);
64 (*d)->type = KDBUS_MSG_PAYLOAD_VEC;
65 (*d)->vec.address = PTR_TO_UINT64(p);
68 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
71 static void append_payload_memfd(struct kdbus_item **d, int memfd, size_t sz) {
77 (*d)->size = offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd);
78 (*d)->type = KDBUS_MSG_PAYLOAD_MEMFD;
79 (*d)->memfd.fd = memfd;
80 (*d)->memfd.size = sz;
82 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
85 static void append_destination(struct kdbus_item **d, const char *s, size_t length) {
91 (*d)->size = offsetof(struct kdbus_item, str) + length + 1;
92 (*d)->type = KDBUS_MSG_DST_NAME;
93 memcpy((*d)->str, s, length + 1);
95 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
98 static void* append_bloom(struct kdbus_item **d, size_t length) {
105 (*d)->size = offsetof(struct kdbus_item, data) + length;
106 (*d)->type = KDBUS_MSG_BLOOM;
109 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
114 static void append_fds(struct kdbus_item **d, const int fds[], unsigned n_fds) {
120 (*d)->size = offsetof(struct kdbus_item, fds) + sizeof(int) * n_fds;
121 (*d)->type = KDBUS_MSG_FDS;
122 memcpy((*d)->fds, fds, sizeof(int) * n_fds);
124 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
127 static int bus_message_setup_bloom(sd_bus_message *m, void *bloom) {
134 memset(bloom, 0, BLOOM_SIZE);
136 bloom_add_pair(bloom, "message-type", bus_message_type_to_string(m->header->type));
139 bloom_add_pair(bloom, "interface", m->interface);
141 bloom_add_pair(bloom, "member", m->member);
143 bloom_add_pair(bloom, "path", m->path);
144 bloom_add_pair(bloom, "path-slash-prefix", m->path);
145 bloom_add_prefixes(bloom, "path-slash-prefix", m->path, '/');
148 r = sd_bus_message_rewind(m, true);
152 for (i = 0; i < 64; i++) {
155 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
158 r = sd_bus_message_peek_type(m, &type, NULL);
162 if (type != SD_BUS_TYPE_STRING &&
163 type != SD_BUS_TYPE_OBJECT_PATH &&
164 type != SD_BUS_TYPE_SIGNATURE)
167 r = sd_bus_message_read_basic(m, type, &t);
171 e = stpcpy(buf, "arg");
175 *(e++) = '0' + (i / 10);
176 *(e++) = '0' + (i % 10);
180 bloom_add_pair(bloom, buf, t);
182 strcpy(e, "-dot-prefix");
183 bloom_add_prefixes(bloom, buf, t, '.');
184 strcpy(e, "-slash-prefix");
185 bloom_add_prefixes(bloom, buf, t, '/');
191 static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
192 struct bus_body_part *part;
193 struct kdbus_item *d;
207 if (m->destination) {
208 r = bus_kernel_parse_unique_name(m->destination, &unique);
216 sz = offsetof(struct kdbus_msg, items);
218 assert_cc(ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec)) ==
219 ALIGN8(offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd)));
221 /* Add in fixed header, fields header and payload */
222 sz += (1 + m->n_body_parts) *
223 ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec));
225 /* Add space for bloom filter */
226 sz += ALIGN8(offsetof(struct kdbus_item, data) + BLOOM_SIZE);
228 /* Add in well-known destination header */
230 dl = strlen(m->destination);
231 sz += ALIGN8(offsetof(struct kdbus_item, str) + dl + 1);
234 /* Add space for unix fds */
236 sz += ALIGN8(offsetof(struct kdbus_item, fds) + sizeof(int)*m->n_fds);
238 m->kdbus = memalign(8, sz);
244 m->free_kdbus = true;
245 memset(m->kdbus, 0, sz);
248 ((m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_FLAGS_EXPECT_REPLY) |
249 ((m->header->flags & SD_BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_FLAGS_NO_AUTO_START : 0);
252 m->destination ? unique : KDBUS_DST_ID_BROADCAST;
253 m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS1;
254 m->kdbus->cookie = m->header->serial;
256 m->kdbus->timeout_ns = m->timeout * NSEC_PER_USEC;
261 append_destination(&d, m->destination, dl);
263 append_payload_vec(&d, m->header, BUS_MESSAGE_BODY_BEGIN(m));
265 MESSAGE_FOREACH_PART(part, i, m) {
267 /* If this is padding then simply send a
268 * vector with a NULL data pointer which the
269 * kernel will just pass through. This is the
270 * most efficient way to encode zeroes */
272 append_payload_vec(&d, NULL, part->size);
276 if (part->memfd >= 0 && part->sealed && m->destination) {
277 /* Try to send a memfd, if the part is
278 * sealed and this is not a broadcast. Since we can only */
280 append_payload_memfd(&d, part->memfd, part->size);
284 /* Otherwise let's send a vector to the actual data,
285 * for that we need to map it first. */
286 r = bus_body_part_map(part);
290 append_payload_vec(&d, part->data, part->size);
293 if (m->kdbus->dst_id == KDBUS_DST_ID_BROADCAST) {
296 p = append_bloom(&d, BLOOM_SIZE);
297 r = bus_message_setup_bloom(m, p);
303 append_fds(&d, m->fds, m->n_fds);
305 m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus;
306 assert(m->kdbus->size <= sz);
315 int bus_kernel_take_fd(sd_bus *b) {
316 struct kdbus_cmd_hello hello;
327 hello.size = sizeof(hello);
328 hello.conn_flags = b->hello_flags;
329 hello.pool_size = KDBUS_POOL_SIZE;
331 r = ioctl(b->input_fd, KDBUS_CMD_HELLO, &hello);
335 if (!b->kdbus_buffer) {
336 b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, b->input_fd, 0);
337 if (b->kdbus_buffer == MAP_FAILED) {
338 b->kdbus_buffer = NULL;
343 /* The higher 32bit of both flags fields are considered
344 * 'incompatible flags'. Refuse them all for now. */
345 if (hello.bus_flags > 0xFFFFFFFFULL ||
346 hello.conn_flags > 0xFFFFFFFFULL)
349 if (hello.bloom_size != BLOOM_SIZE)
352 if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello.id) < 0)
356 b->bus_client = true;
357 b->can_fds = !!(hello.conn_flags & KDBUS_HELLO_ACCEPT_FD);
359 r = bus_start_running(b);
366 int bus_kernel_connect(sd_bus *b) {
368 assert(b->input_fd < 0);
369 assert(b->output_fd < 0);
375 b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
379 b->output_fd = b->input_fd;
381 return bus_kernel_take_fd(b);
384 int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
389 assert(bus->state == BUS_RUNNING);
391 r = bus_message_setup_kmsg(bus, m);
395 r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
397 return errno == EAGAIN ? 0 : -errno;
402 static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
404 struct kdbus_item *d;
409 off = (uint8_t *)k - (uint8_t *)bus->kdbus_buffer;
410 ioctl(bus->input_fd, KDBUS_CMD_MSG_RELEASE, &off);
412 KDBUS_PART_FOREACH(d, k, items) {
414 if (d->type == KDBUS_MSG_FDS)
415 close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
416 else if (d->type == KDBUS_MSG_PAYLOAD_MEMFD)
417 close_nointr_nofail(d->memfd.fd);
421 static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_message **ret) {
422 sd_bus_message *m = NULL;
423 struct kdbus_item *d;
425 _cleanup_free_ int *fds = NULL;
426 struct bus_header *h = NULL;
427 size_t total, n_bytes = 0, idx = 0;
428 const char *destination = NULL, *seclabel = NULL;
435 if (k->payload_type != KDBUS_PAYLOAD_DBUS1)
438 KDBUS_PART_FOREACH(d, k, items) {
441 l = d->size - offsetof(struct kdbus_item, data);
443 if (d->type == KDBUS_MSG_PAYLOAD_OFF) {
446 h = (struct bus_header *)((uint8_t *)bus->kdbus_buffer + d->vec.offset);
448 if (!bus_header_is_complete(h, d->vec.size))
452 n_bytes += d->vec.size;
454 } else if (d->type == KDBUS_MSG_PAYLOAD_MEMFD) {
459 n_bytes += d->memfd.size;
461 } else if (d->type == KDBUS_MSG_FDS) {
466 f = realloc(fds, sizeof(int) * (n_fds + j));
471 memcpy(fds + n_fds, d->fds, sizeof(int) * j);
474 } else if (d->type == KDBUS_MSG_SRC_SECLABEL)
481 r = bus_header_message_size(h, &total);
485 if (n_bytes != total)
488 r = bus_message_from_header(bus, h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m);
492 KDBUS_PART_FOREACH(d, k, items) {
495 l = d->size - offsetof(struct kdbus_item, data);
497 if (d->type == KDBUS_MSG_PAYLOAD_OFF) {
500 begin_body = BUS_MESSAGE_BODY_BEGIN(m);
502 if (idx + d->vec.size > begin_body) {
503 struct bus_body_part *part;
505 /* Contains body material */
507 part = message_append_part(m);
513 /* A -1 offset is NUL padding. */
514 part->is_zero = d->vec.offset == ~0ULL;
516 if (idx >= begin_body) {
518 part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset;
519 part->size = d->vec.size;
522 part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset + (begin_body - idx);
523 part->size = d->vec.size - (begin_body - idx);
530 } else if (d->type == KDBUS_MSG_PAYLOAD_MEMFD) {
531 struct bus_body_part *part;
533 if (idx < BUS_MESSAGE_BODY_BEGIN(m)) {
538 part = message_append_part(m);
544 part->memfd = d->memfd.fd;
545 part->size = d->memfd.size;
548 idx += d->memfd.size;
550 } else if (d->type == KDBUS_MSG_SRC_CREDS) {
551 m->creds.pid_starttime = d->creds.starttime / NSEC_PER_USEC;
552 m->creds.uid = d->creds.uid;
553 m->creds.gid = d->creds.gid;
554 m->creds.pid = d->creds.pid;
555 m->creds.tid = d->creds.tid;
556 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;
558 } else if (d->type == KDBUS_MSG_TIMESTAMP) {
559 m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC;
560 m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC;
562 } else if (d->type == KDBUS_MSG_SRC_PID_COMM) {
563 m->creds.comm = d->str;
564 m->creds.mask |= SD_BUS_CREDS_COMM & bus->creds_mask;
566 } else if (d->type == KDBUS_MSG_SRC_TID_COMM) {
567 m->creds.tid_comm = d->str;
568 m->creds.mask |= SD_BUS_CREDS_TID_COMM & bus->creds_mask;
570 } else if (d->type == KDBUS_MSG_SRC_EXE) {
571 m->creds.exe = d->str;
572 m->creds.mask |= SD_BUS_CREDS_EXE & bus->creds_mask;
574 } else if (d->type == KDBUS_MSG_SRC_CMDLINE) {
575 m->creds.cmdline = d->str;
576 m->creds.cmdline_length = l;
577 m->creds.mask |= SD_BUS_CREDS_CMDLINE & bus->creds_mask;
579 } else if (d->type == KDBUS_MSG_SRC_CGROUP) {
580 m->creds.cgroup = d->str;
581 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;
583 } else if (d->type == KDBUS_MSG_SRC_AUDIT) {
584 m->creds.audit_session_id = d->audit.sessionid;
585 m->creds.audit_login_uid = d->audit.loginuid;
586 m->creds.mask |= (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID) & bus->creds_mask;
588 } else if (d->type == KDBUS_MSG_SRC_CAPS) {
589 m->creds.capability = d->data;
590 m->creds.capability_size = l;
591 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;
593 } else if (d->type == KDBUS_MSG_DST_NAME)
594 destination = d->str;
595 else if (d->type != KDBUS_MSG_FDS &&
596 d->type != KDBUS_MSG_SRC_SECLABEL &&
597 d->type != KDBUS_MSG_SRC_NAMES)
598 log_debug("Got unknown field from kernel %llu", d->type);
601 r = bus_message_parse_fields(m);
605 if (k->src_id == KDBUS_SRC_ID_KERNEL)
606 m->sender = "org.freedesktop.DBus";
608 snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
609 m->sender = m->sender_buffer;
612 if (!m->destination) {
614 m->destination = destination;
615 else if (k->dst_id != KDBUS_DST_ID_WELL_KNOWN_NAME &&
616 k->dst_id != KDBUS_DST_ID_BROADCAST) {
617 snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
618 m->destination = m->destination_buffer;
622 /* We take possession of the kmsg struct now */
624 m->release_kdbus = true;
634 struct bus_body_part *part;
637 /* Make sure the memfds are not freed twice */
638 MESSAGE_FOREACH_PART(part, i, m)
639 if (part->memfd >= 0)
642 sd_bus_message_unref(m);
648 int bus_kernel_read_message(sd_bus *bus, sd_bus_message **m) {
656 r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, &off);
663 k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + off);
665 r = bus_kernel_make_message(bus, k, m);
667 close_kdbus_msg(bus, k);
669 return r < 0 ? r : 1;
672 int bus_kernel_create(const char *name, char **s) {
673 struct kdbus_cmd_bus_make *make;
674 struct kdbus_item *n;
682 fd = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
687 make = alloca0(offsetof(struct kdbus_cmd_bus_make, items) +
688 KDBUS_PART_HEADER_SIZE + sizeof(uint64_t) +
689 KDBUS_PART_HEADER_SIZE + DECIMAL_STR_MAX(uid_t) + 1 + l + 1);
692 n->type = KDBUS_MAKE_NAME;
693 sprintf(n->str, "%lu-%s", (unsigned long) getuid(), name);
694 n->size = KDBUS_PART_HEADER_SIZE + strlen(n->str) + 1;
696 make->size = offsetof(struct kdbus_cmd_bus_make, items) + n->size;
697 make->flags = KDBUS_MAKE_POLICY_OPEN;
699 make->bloom_size = BLOOM_SIZE;
700 assert_cc(BLOOM_SIZE % 8 == 0);
702 p = strjoin("/dev/kdbus/", n->str, "/bus", NULL);
706 if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
707 close_nointr_nofail(fd);
718 int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *size) {
719 struct memfd_cache *c;
725 if (!bus || !bus->is_kernel)
728 assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
730 if (bus->n_memfd_cache <= 0) {
733 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
735 r = ioctl(bus->input_fd, KDBUS_CMD_MEMFD_NEW, &fd);
744 c = &bus->memfd_cache[--bus->n_memfd_cache];
747 assert(c->size == 0 || c->address);
749 *address = c->address;
753 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
758 static void close_and_munmap(int fd, void *address, size_t size) {
760 assert_se(munmap(address, PAGE_ALIGN(size)) >= 0);
762 close_nointr_nofail(fd);
765 void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t size) {
766 struct memfd_cache *c;
767 uint64_t max_sz = PAGE_ALIGN(MEMFD_CACHE_ITEM_SIZE_MAX);
770 assert(size == 0 || address);
772 if (!bus || !bus->is_kernel) {
773 close_and_munmap(fd, address, size);
777 assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
779 if (bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
780 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
782 close_and_munmap(fd, address, size);
786 c = &bus->memfd_cache[bus->n_memfd_cache++];
788 c->address = address;
790 /* If overly long, let's return a bit to the OS */
792 assert_se(ioctl(fd, KDBUS_CMD_MEMFD_SIZE_SET, &max_sz) >= 0);
793 assert_se(munmap((uint8_t*) address + max_sz, PAGE_ALIGN(size - max_sz)) >= 0);
798 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
801 void bus_kernel_flush_memfd(sd_bus *b) {
806 for (i = 0; i < b->n_memfd_cache; i++)
807 close_and_munmap(b->memfd_cache[i].fd, b->memfd_cache[i].address, b->memfd_cache[i].size);