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 kdbus_item *d;
192 struct bus_body_part *part;
201 if (m->destination) {
202 r = parse_unique_name(m->destination, &unique);
210 sz = offsetof(struct kdbus_msg, items);
212 /* Add in fixed header, fields header and payload */
213 sz += (1 + !!m->fields + m->n_body_parts) *
214 ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec));
216 /* Add space for bloom filter */
217 sz += ALIGN8(offsetof(struct kdbus_item, data) + BLOOM_SIZE);
219 /* Add in well-known destination header */
221 dl = strlen(m->destination);
222 sz += ALIGN8(offsetof(struct kdbus_item, str) + dl + 1);
225 /* Add space for unix fds */
227 sz += ALIGN8(offsetof(struct kdbus_item, fds) + sizeof(int)*m->n_fds);
229 m->kdbus = memalign(8, sz);
233 memset(m->kdbus, 0, sz);
236 ((m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_FLAGS_EXPECT_REPLY) |
237 ((m->header->flags & SD_BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_FLAGS_NO_AUTO_START : 0);
240 m->destination ? unique : KDBUS_DST_ID_BROADCAST;
241 m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS1;
242 m->kdbus->cookie = m->header->serial;
244 m->kdbus->timeout_ns = m->timeout * NSEC_PER_USEC;
249 append_destination(&d, m->destination, dl);
251 append_payload_vec(&d, m->header, sizeof(*m->header));
254 append_payload_vec(&d, m->fields, ALIGN8(m->header->fields_size));
256 for (part = &m->body; part && part->size > 0; part = part->next)
257 append_payload_vec(&d, part->data, part->size);
259 if (m->kdbus->dst_id == KDBUS_DST_ID_BROADCAST) {
262 p = append_bloom(&d, BLOOM_SIZE);
263 r = bus_message_setup_bloom(m, p);
272 append_fds(&d, m->fds, m->n_fds);
274 m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus;
275 assert(m->kdbus->size <= sz);
277 m->free_kdbus = true;
282 int bus_kernel_take_fd(sd_bus *b) {
283 uint8_t h[ALIGN8(sizeof(struct kdbus_cmd_hello)) +
284 ALIGN8(KDBUS_ITEM_HEADER_SIZE) +
285 ALIGN8(sizeof(struct kdbus_vec))] = {};
287 struct kdbus_cmd_hello *hello = (struct kdbus_cmd_hello*) h;
296 if (!b->kdbus_buffer) {
297 b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
298 if (b->kdbus_buffer == MAP_FAILED) {
299 b->kdbus_buffer = NULL;
304 hello->size = sizeof(h);
306 KDBUS_HELLO_ACCEPT_FD|
307 KDBUS_HELLO_ATTACH_COMM|
308 KDBUS_HELLO_ATTACH_EXE|
309 KDBUS_HELLO_ATTACH_CMDLINE|
310 KDBUS_HELLO_ATTACH_CGROUP|
311 KDBUS_HELLO_ATTACH_CAPS|
312 KDBUS_HELLO_ATTACH_SECLABEL|
313 KDBUS_HELLO_ATTACH_AUDIT;
315 hello->items[0].type = KDBUS_HELLO_POOL;
316 hello->items[0].size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
317 hello->items[0].vec.address = (uint64_t) b->kdbus_buffer;
318 hello->items[0].vec.size = KDBUS_POOL_SIZE;
320 r = ioctl(b->input_fd, KDBUS_CMD_HELLO, hello);
324 /* The higher 32bit of both flags fields are considered
325 * 'incompatible flags'. Refuse them all for now. */
326 if (hello->bus_flags > 0xFFFFFFFFULL ||
327 hello->conn_flags > 0xFFFFFFFFULL)
330 if (hello->bloom_size != BLOOM_SIZE)
333 if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello->id) < 0)
337 b->bus_client = true;
340 r = bus_start_running(b);
347 int bus_kernel_connect(sd_bus *b) {
349 assert(b->input_fd < 0);
350 assert(b->output_fd < 0);
356 b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
360 b->output_fd = b->input_fd;
362 return bus_kernel_take_fd(b);
365 int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
370 assert(bus->state == BUS_RUNNING);
372 r = bus_message_setup_kmsg(bus, m);
376 r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
378 return errno == EAGAIN ? 0 : -errno;
383 static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
384 struct kdbus_item *d;
389 ioctl(bus->input_fd, KDBUS_CMD_MSG_RELEASE, k);
391 KDBUS_ITEM_FOREACH(d, k) {
393 if (d->type != KDBUS_MSG_FDS)
396 close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
400 static bool range_contains(
401 size_t astart, size_t asize,
402 size_t bstart, size_t bsize,
408 if (bstart + bsize > astart + asize)
411 *b = (uint8_t*) a + (bstart - astart);
416 static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_message **ret) {
417 sd_bus_message *m = NULL;
418 struct kdbus_item *d;
419 unsigned n_payload = 0, n_fds = 0;
420 _cleanup_free_ int *fds = NULL;
421 struct bus_header *h = NULL;
422 size_t total, n_bytes = 0, idx = 0;
423 const char *destination = NULL, *seclabel = NULL;
430 if (k->payload_type != KDBUS_PAYLOAD_DBUS1)
433 KDBUS_ITEM_FOREACH(d, k) {
436 l = d->size - offsetof(struct kdbus_item, data);
438 if (d->type == KDBUS_MSG_PAYLOAD_VEC) {
441 if (d->vec.size < sizeof(struct bus_header))
444 h = UINT64_TO_PTR(d->vec.address);
448 n_bytes += d->vec.size;
450 } else if (d->type == KDBUS_MSG_FDS) {
455 f = realloc(fds, sizeof(int) * (n_fds + j));
460 memcpy(fds + n_fds, d->fds, sizeof(int) * j);
463 } else if (d->type == KDBUS_MSG_DST_NAME)
464 destination = d->str;
465 else if (d->type == KDBUS_MSG_SRC_SECLABEL)
472 r = bus_header_size(h, &total);
476 if (n_bytes != total)
479 r = bus_message_from_header(h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m);
483 KDBUS_ITEM_FOREACH(d, k) {
486 l = d->size - offsetof(struct kdbus_item, data);
488 if (d->type == KDBUS_MSG_PAYLOAD_VEC) {
491 /* Fill in fields material */
492 range_contains(idx, d->vec.size, ALIGN8(sizeof(struct bus_header)), BUS_MESSAGE_FIELDS_SIZE(m),
493 UINT64_TO_PTR(d->vec.address), &m->fields);
495 begin_body = ALIGN8(sizeof(struct bus_header)) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
497 if (idx + d->vec.size > begin_body) {
498 struct bus_body_part *part;
500 /* Contains body material */
502 part = message_append_part(m);
504 sd_bus_message_unref(m);
508 if (idx >= begin_body) {
509 part->data = (void*) d->vec.address;
510 part->size = d->vec.size;
512 part->data = (uint8_t*) (uintptr_t) d->vec.address + (begin_body - idx);
513 part->size = d->vec.size - (begin_body - idx);
521 } else if (d->type == KDBUS_MSG_SRC_CREDS) {
522 m->pid_starttime = d->creds.starttime / NSEC_PER_USEC;
523 m->uid = d->creds.uid;
524 m->gid = d->creds.gid;
525 m->pid = d->creds.pid;
526 m->tid = d->creds.tid;
527 m->uid_valid = m->gid_valid = true;
528 } else if (d->type == KDBUS_MSG_TIMESTAMP) {
529 m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC;
530 m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC;
531 } else if (d->type == KDBUS_MSG_SRC_PID_COMM)
533 else if (d->type == KDBUS_MSG_SRC_TID_COMM)
534 m->tid_comm = d->str;
535 else if (d->type == KDBUS_MSG_SRC_EXE)
537 else if (d->type == KDBUS_MSG_SRC_CMDLINE) {
539 m->cmdline_length = l;
540 } else if (d->type == KDBUS_MSG_SRC_CGROUP)
542 else if (d->type == KDBUS_MSG_SRC_AUDIT)
543 m->audit = &d->audit;
544 else if (d->type == KDBUS_MSG_SRC_CAPS) {
545 m->capability = d->data;
546 m->capability_size = l;
547 } else if (d->type != KDBUS_MSG_FDS &&
548 d->type != KDBUS_MSG_DST_NAME &&
549 d->type != KDBUS_MSG_SRC_SECLABEL)
550 log_debug("Got unknown field from kernel %llu", d->type);
553 if ((BUS_MESSAGE_FIELDS_SIZE(m) > 0 && !m->fields)) {
554 sd_bus_message_unref(m);
558 r = bus_message_parse_fields(m);
560 sd_bus_message_unref(m);
564 if (k->src_id == KDBUS_SRC_ID_KERNEL)
565 m->sender = "org.freedesktop.DBus";
567 snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
568 m->sender = m->sender_buffer;
571 if (!m->destination) {
573 m->destination = destination;
574 else if (k->dst_id != KDBUS_DST_ID_WELL_KNOWN_NAME &&
575 k->dst_id != KDBUS_DST_ID_BROADCAST) {
576 snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
577 m->destination = m->destination_buffer;
581 /* We take possession of the kmsg struct now */
583 m->bus = sd_bus_ref(bus);
584 m->release_kdbus = true;
593 int bus_kernel_read_message(sd_bus *bus, sd_bus_message **m) {
600 r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, &k);
609 /* /\* Let's tell valgrind that there's really no need to */
610 /* * initialize this fully. This should be removed again */
611 /* * when valgrind learned the kdbus ioctls natively. *\/ */
612 /* #ifdef HAVE_VALGRIND_MEMCHECK_H */
613 /* VALGRIND_MAKE_MEM_DEFINED(k, sz); */
617 r = bus_kernel_make_message(bus, k, m);
619 close_kdbus_msg(bus, k);
621 return r < 0 ? r : 1;
624 int bus_kernel_create(const char *name, char **s) {
625 struct kdbus_cmd_bus_make *make;
626 struct kdbus_item *n, *cg;
634 fd = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
639 make = alloca0(offsetof(struct kdbus_cmd_bus_make, items) +
640 KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t) +
641 KDBUS_ITEM_HEADER_SIZE + DECIMAL_STR_MAX(uid_t) + 1 + l + 1);
644 cg->type = KDBUS_MAKE_CGROUP;
646 cg->size = KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t);
648 n = KDBUS_ITEM_NEXT(cg);
649 n->type = KDBUS_MAKE_NAME;
650 sprintf(n->str, "%lu-%s", (unsigned long) getuid(), name);
651 n->size = KDBUS_ITEM_HEADER_SIZE + strlen(n->str) + 1;
653 make->size = offsetof(struct kdbus_cmd_bus_make, items) + cg->size + n->size;
654 make->flags = KDBUS_MAKE_POLICY_OPEN;
656 make->bloom_size = BLOOM_SIZE;
657 assert_cc(BLOOM_SIZE % 8 == 0);
659 p = strjoin("/dev/kdbus/", n->str, "/bus", NULL);
663 if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
664 close_nointr_nofail(fd);
675 int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *size) {
676 struct memfd_cache *c;
681 if (!bus || !bus->is_kernel)
684 if (bus->n_memfd_cache <= 0) {
687 r = ioctl(bus->input_fd, KDBUS_CMD_MEMFD_NEW, &fd);
696 c = &bus->memfd_cache[-- bus->n_memfd_cache];
699 assert(c->size == 0 || c->address);
701 *address = c->address;
707 void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t size) {
708 struct memfd_cache *c;
711 assert(size == 0 || address);
713 if (!bus || !bus->is_kernel ||
714 bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
717 assert_se(munmap(address, PAGE_ALIGN(size)) == 0);
719 close_nointr_nofail(fd);
723 c = &bus->memfd_cache[bus->n_memfd_cache++];
725 c->address = address;
727 /* If overly long, let's return a bit to the OS */
728 if (size > MEMFD_CACHE_ITEM_SIZE_MAX) {
729 uint64_t sz = MEMFD_CACHE_ITEM_SIZE_MAX;
731 ioctl(bus->input_fd, KDBUS_CMD_MEMFD_SIZE_SET, &sz);
733 c->size = MEMFD_CACHE_ITEM_SIZE_MAX;
738 void bus_kernel_flush_memfd(sd_bus *b) {
743 for (i = 0; i < b->n_memfd_cache; i++) {
744 if (b->memfd_cache[i].size > 0)
745 assert_se(munmap(b->memfd_cache[i].address, PAGE_ALIGN(b->memfd_cache[i].size)) == 0);
747 close_nointr_nofail(b->memfd_cache[i].fd);