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 #define KDBUS_ITEM_NEXT(item) \
38 (typeof(item))(((uint8_t *)item) + ALIGN8((item)->size))
40 #define KDBUS_ITEM_FOREACH(item, head) \
41 for (item = (head)->items; \
42 (uint8_t *)(item) < (uint8_t *)(head) + (head)->size; \
43 item = KDBUS_ITEM_NEXT(item))
45 #define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data)
46 #define KDBUS_ITEM_SIZE(s) ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE)
48 #define KDBUS_POOL_SIZE (4*1024*1024)
50 static int parse_unique_name(const char *s, uint64_t *id) {
56 if (!startswith(s, ":1."))
59 r = safe_atou64(s + 3, id);
66 static void append_payload_vec(struct kdbus_item **d, const void *p, size_t sz) {
73 (*d)->size = offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec);
74 (*d)->type = KDBUS_MSG_PAYLOAD_VEC;
75 (*d)->vec.address = (uint64_t) p;
78 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
81 static void append_destination(struct kdbus_item **d, const char *s, size_t length) {
87 (*d)->size = offsetof(struct kdbus_item, str) + length + 1;
88 (*d)->type = KDBUS_MSG_DST_NAME;
89 memcpy((*d)->str, s, length + 1);
91 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
94 static void* append_bloom(struct kdbus_item **d, size_t length) {
101 (*d)->size = offsetof(struct kdbus_item, data) + length;
102 (*d)->type = KDBUS_MSG_BLOOM;
105 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
110 static void append_fds(struct kdbus_item **d, const int fds[], unsigned n_fds) {
116 (*d)->size = offsetof(struct kdbus_item, fds) + sizeof(int) * n_fds;
117 (*d)->type = KDBUS_MSG_FDS;
118 memcpy((*d)->fds, fds, sizeof(int) * n_fds);
120 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
123 static int bus_message_setup_bloom(sd_bus_message *m, void *bloom) {
130 memset(bloom, 0, BLOOM_SIZE);
132 bloom_add_pair(bloom, "message-type", bus_message_type_to_string(m->header->type));
135 bloom_add_pair(bloom, "interface", m->interface);
137 bloom_add_pair(bloom, "member", m->member);
139 bloom_add_pair(bloom, "path", m->path);
140 bloom_add_prefixes(bloom, "path-slash-prefix", m->path, '/');
143 r = sd_bus_message_rewind(m, true);
147 for (i = 0; i < 64; i++) {
150 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
153 r = sd_bus_message_peek_type(m, &type, NULL);
157 if (type != SD_BUS_TYPE_STRING &&
158 type != SD_BUS_TYPE_OBJECT_PATH &&
159 type != SD_BUS_TYPE_SIGNATURE)
162 r = sd_bus_message_read_basic(m, type, &t);
166 e = stpcpy(buf, "arg");
170 *(e++) = '0' + (i / 10);
171 *(e++) = '0' + (i % 10);
175 bloom_add_pair(bloom, buf, t);
177 strcpy(e, "-dot-prefix");
178 bloom_add_prefixes(bloom, buf, t, '.');
179 strcpy(e, "-slash-prefix");
180 bloom_add_prefixes(bloom, buf, t, '/');
186 static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
187 struct bus_body_part *part;
188 struct kdbus_item *d;
202 if (m->destination) {
203 r = parse_unique_name(m->destination, &unique);
211 sz = offsetof(struct kdbus_msg, items);
213 /* Add in fixed header, fields header and payload */
214 sz += (1 + !!m->fields + m->n_body_parts) *
215 ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec));
217 /* Add space for bloom filter */
218 sz += ALIGN8(offsetof(struct kdbus_item, data) + BLOOM_SIZE);
220 /* Add in well-known destination header */
222 dl = strlen(m->destination);
223 sz += ALIGN8(offsetof(struct kdbus_item, str) + dl + 1);
226 /* Add space for unix fds */
228 sz += ALIGN8(offsetof(struct kdbus_item, fds) + sizeof(int)*m->n_fds);
230 m->kdbus = memalign(8, sz);
234 memset(m->kdbus, 0, sz);
237 ((m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_FLAGS_EXPECT_REPLY) |
238 ((m->header->flags & SD_BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_FLAGS_NO_AUTO_START : 0);
241 m->destination ? unique : KDBUS_DST_ID_BROADCAST;
242 m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS1;
243 m->kdbus->cookie = m->header->serial;
245 m->kdbus->timeout_ns = m->timeout * NSEC_PER_USEC;
250 append_destination(&d, m->destination, dl);
252 append_payload_vec(&d, m->header, sizeof(*m->header));
255 append_payload_vec(&d, m->fields, ALIGN8(m->header->fields_size));
257 MESSAGE_FOREACH_PART(part, i, m)
258 append_payload_vec(&d, part->data, part->size);
260 if (m->kdbus->dst_id == KDBUS_DST_ID_BROADCAST) {
263 p = append_bloom(&d, BLOOM_SIZE);
264 r = bus_message_setup_bloom(m, p);
273 append_fds(&d, m->fds, m->n_fds);
275 m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus;
276 assert(m->kdbus->size <= sz);
278 m->free_kdbus = true;
283 int bus_kernel_take_fd(sd_bus *b) {
284 uint8_t h[ALIGN8(sizeof(struct kdbus_cmd_hello)) +
285 ALIGN8(KDBUS_ITEM_HEADER_SIZE) +
286 ALIGN8(sizeof(struct kdbus_vec))] = {};
288 struct kdbus_cmd_hello *hello = (struct kdbus_cmd_hello*) h;
297 if (!b->kdbus_buffer) {
298 b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
299 if (b->kdbus_buffer == MAP_FAILED) {
300 b->kdbus_buffer = NULL;
305 hello->size = sizeof(h);
307 KDBUS_HELLO_ACCEPT_FD|
308 KDBUS_HELLO_ATTACH_COMM|
309 KDBUS_HELLO_ATTACH_EXE|
310 KDBUS_HELLO_ATTACH_CMDLINE|
311 KDBUS_HELLO_ATTACH_CGROUP|
312 KDBUS_HELLO_ATTACH_CAPS|
313 KDBUS_HELLO_ATTACH_SECLABEL|
314 KDBUS_HELLO_ATTACH_AUDIT;
316 hello->items[0].type = KDBUS_HELLO_POOL;
317 hello->items[0].size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
318 hello->items[0].vec.address = (uint64_t) b->kdbus_buffer;
319 hello->items[0].vec.size = KDBUS_POOL_SIZE;
321 r = ioctl(b->input_fd, KDBUS_CMD_HELLO, hello);
325 /* The higher 32bit of both flags fields are considered
326 * 'incompatible flags'. Refuse them all for now. */
327 if (hello->bus_flags > 0xFFFFFFFFULL ||
328 hello->conn_flags > 0xFFFFFFFFULL)
331 if (hello->bloom_size != BLOOM_SIZE)
334 if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello->id) < 0)
338 b->bus_client = true;
341 r = bus_start_running(b);
348 int bus_kernel_connect(sd_bus *b) {
350 assert(b->input_fd < 0);
351 assert(b->output_fd < 0);
357 b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
361 b->output_fd = b->input_fd;
363 return bus_kernel_take_fd(b);
366 int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
371 assert(bus->state == BUS_RUNNING);
373 r = bus_message_setup_kmsg(bus, m);
377 r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
379 return errno == EAGAIN ? 0 : -errno;
384 static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
385 struct kdbus_item *d;
390 ioctl(bus->input_fd, KDBUS_CMD_MSG_RELEASE, k);
392 KDBUS_ITEM_FOREACH(d, k) {
394 if (d->type != KDBUS_MSG_FDS)
397 close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
401 static bool range_contains(
402 size_t astart, size_t asize,
403 size_t bstart, size_t bsize,
409 if (bstart + bsize > astart + asize)
412 *b = (uint8_t*) a + (bstart - astart);
417 static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_message **ret) {
418 sd_bus_message *m = NULL;
419 struct kdbus_item *d;
420 unsigned n_payload = 0, n_fds = 0;
421 _cleanup_free_ int *fds = NULL;
422 struct bus_header *h = NULL;
423 size_t total, n_bytes = 0, idx = 0;
424 const char *destination = NULL, *seclabel = NULL;
431 if (k->payload_type != KDBUS_PAYLOAD_DBUS1)
434 KDBUS_ITEM_FOREACH(d, k) {
437 l = d->size - offsetof(struct kdbus_item, data);
439 if (d->type == KDBUS_MSG_PAYLOAD_VEC) {
442 if (d->vec.size < sizeof(struct bus_header))
445 h = UINT64_TO_PTR(d->vec.address);
449 n_bytes += d->vec.size;
451 } else if (d->type == KDBUS_MSG_FDS) {
456 f = realloc(fds, sizeof(int) * (n_fds + j));
461 memcpy(fds + n_fds, d->fds, sizeof(int) * j);
464 } else if (d->type == KDBUS_MSG_DST_NAME)
465 destination = d->str;
466 else if (d->type == KDBUS_MSG_SRC_SECLABEL)
473 r = bus_header_size(h, &total);
477 if (n_bytes != total)
480 r = bus_message_from_header(h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m);
484 KDBUS_ITEM_FOREACH(d, k) {
487 l = d->size - offsetof(struct kdbus_item, data);
489 if (d->type == KDBUS_MSG_PAYLOAD_VEC) {
492 /* Fill in fields material */
493 range_contains(idx, d->vec.size, ALIGN8(sizeof(struct bus_header)), BUS_MESSAGE_FIELDS_SIZE(m),
494 UINT64_TO_PTR(d->vec.address), &m->fields);
496 begin_body = ALIGN8(sizeof(struct bus_header)) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
498 if (idx + d->vec.size > begin_body) {
499 struct bus_body_part *part;
501 /* Contains body material */
503 part = message_append_part(m);
505 sd_bus_message_unref(m);
509 if (idx >= begin_body) {
510 part->data = (void*) d->vec.address;
511 part->size = d->vec.size;
513 part->data = (uint8_t*) (uintptr_t) d->vec.address + (begin_body - idx);
514 part->size = d->vec.size - (begin_body - idx);
522 } else if (d->type == KDBUS_MSG_SRC_CREDS) {
523 m->pid_starttime = d->creds.starttime / NSEC_PER_USEC;
524 m->uid = d->creds.uid;
525 m->gid = d->creds.gid;
526 m->pid = d->creds.pid;
527 m->tid = d->creds.tid;
528 m->uid_valid = m->gid_valid = true;
529 } else if (d->type == KDBUS_MSG_TIMESTAMP) {
530 m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC;
531 m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC;
532 } else if (d->type == KDBUS_MSG_SRC_PID_COMM)
534 else if (d->type == KDBUS_MSG_SRC_TID_COMM)
535 m->tid_comm = d->str;
536 else if (d->type == KDBUS_MSG_SRC_EXE)
538 else if (d->type == KDBUS_MSG_SRC_CMDLINE) {
540 m->cmdline_length = l;
541 } else if (d->type == KDBUS_MSG_SRC_CGROUP)
543 else if (d->type == KDBUS_MSG_SRC_AUDIT)
544 m->audit = &d->audit;
545 else if (d->type == KDBUS_MSG_SRC_CAPS) {
546 m->capability = d->data;
547 m->capability_size = l;
548 } else if (d->type != KDBUS_MSG_FDS &&
549 d->type != KDBUS_MSG_DST_NAME &&
550 d->type != KDBUS_MSG_SRC_SECLABEL)
551 log_debug("Got unknown field from kernel %llu", d->type);
554 if ((BUS_MESSAGE_FIELDS_SIZE(m) > 0 && !m->fields)) {
555 sd_bus_message_unref(m);
559 r = bus_message_parse_fields(m);
561 sd_bus_message_unref(m);
565 if (k->src_id == KDBUS_SRC_ID_KERNEL)
566 m->sender = "org.freedesktop.DBus";
568 snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
569 m->sender = m->sender_buffer;
572 if (!m->destination) {
574 m->destination = destination;
575 else if (k->dst_id != KDBUS_DST_ID_WELL_KNOWN_NAME &&
576 k->dst_id != KDBUS_DST_ID_BROADCAST) {
577 snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
578 m->destination = m->destination_buffer;
582 /* We take possession of the kmsg struct now */
584 m->bus = sd_bus_ref(bus);
585 m->release_kdbus = true;
594 int bus_kernel_read_message(sd_bus *bus, sd_bus_message **m) {
601 r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, &k);
610 /* /\* Let's tell valgrind that there's really no need to */
611 /* * initialize this fully. This should be removed again */
612 /* * when valgrind learned the kdbus ioctls natively. *\/ */
613 /* #ifdef HAVE_VALGRIND_MEMCHECK_H */
614 /* VALGRIND_MAKE_MEM_DEFINED(k, sz); */
618 r = bus_kernel_make_message(bus, k, m);
620 close_kdbus_msg(bus, k);
622 return r < 0 ? r : 1;
625 int bus_kernel_create(const char *name, char **s) {
626 struct kdbus_cmd_bus_make *make;
627 struct kdbus_item *n, *cg;
635 fd = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
640 make = alloca0(offsetof(struct kdbus_cmd_bus_make, items) +
641 KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t) +
642 KDBUS_ITEM_HEADER_SIZE + DECIMAL_STR_MAX(uid_t) + 1 + l + 1);
645 cg->type = KDBUS_MAKE_CGROUP;
647 cg->size = KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t);
649 n = KDBUS_ITEM_NEXT(cg);
650 n->type = KDBUS_MAKE_NAME;
651 sprintf(n->str, "%lu-%s", (unsigned long) getuid(), name);
652 n->size = KDBUS_ITEM_HEADER_SIZE + strlen(n->str) + 1;
654 make->size = offsetof(struct kdbus_cmd_bus_make, items) + cg->size + n->size;
655 make->flags = KDBUS_MAKE_POLICY_OPEN;
657 make->bloom_size = BLOOM_SIZE;
658 assert_cc(BLOOM_SIZE % 8 == 0);
660 p = strjoin("/dev/kdbus/", n->str, "/bus", NULL);
664 if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
665 close_nointr_nofail(fd);
676 int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *size) {
677 struct memfd_cache *c;
682 if (!bus || !bus->is_kernel)
685 if (bus->n_memfd_cache <= 0) {
688 r = ioctl(bus->input_fd, KDBUS_CMD_MEMFD_NEW, &fd);
697 c = &bus->memfd_cache[-- bus->n_memfd_cache];
700 assert(c->size == 0 || c->address);
702 *address = c->address;
708 void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t size) {
709 struct memfd_cache *c;
712 assert(size == 0 || address);
714 if (!bus || !bus->is_kernel ||
715 bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
718 assert_se(munmap(address, PAGE_ALIGN(size)) == 0);
720 close_nointr_nofail(fd);
724 c = &bus->memfd_cache[bus->n_memfd_cache++];
726 c->address = address;
728 /* If overly long, let's return a bit to the OS */
729 if (size > MEMFD_CACHE_ITEM_SIZE_MAX) {
730 uint64_t sz = MEMFD_CACHE_ITEM_SIZE_MAX;
732 ioctl(bus->input_fd, KDBUS_CMD_MEMFD_SIZE_SET, &sz);
734 c->size = MEMFD_CACHE_ITEM_SIZE_MAX;
739 void bus_kernel_flush_memfd(sd_bus *b) {
744 for (i = 0; i < b->n_memfd_cache; i++) {
745 if (b->memfd_cache[i].size > 0)
746 assert_se(munmap(b->memfd_cache[i].address, PAGE_ALIGN(b->memfd_cache[i].size)) == 0);
748 close_nointr_nofail(b->memfd_cache[i].fd);