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 = (struct bus_header*)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)
482 r = bus_message_from_header(h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m);
486 KDBUS_ITEM_FOREACH(d, k) {
489 l = d->size - offsetof(struct kdbus_item, data);
491 if (d->type == KDBUS_MSG_PAYLOAD_VEC) {
494 /* Fill in fields material */
495 range_contains(idx, d->vec.size, ALIGN8(sizeof(struct bus_header)), BUS_MESSAGE_FIELDS_SIZE(m),
496 UINT64_TO_PTR(d->vec.address), &m->fields);
498 begin_body = ALIGN8(sizeof(struct bus_header)) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
500 if (idx + d->vec.size > begin_body) {
501 struct bus_body_part *part;
503 /* Contains body material */
505 part = message_append_part(m);
507 sd_bus_message_unref(m);
511 if (idx >= begin_body) {
512 part->data = (void*) d->vec.address;
513 part->size = d->vec.size;
515 part->data = (uint8_t*) (uintptr_t) d->vec.address + (begin_body - idx);
516 part->size = d->vec.size - (begin_body - idx);
524 } else if (d->type == KDBUS_MSG_SRC_CREDS) {
525 m->pid_starttime = d->creds.starttime / NSEC_PER_USEC;
526 m->uid = d->creds.uid;
527 m->gid = d->creds.gid;
528 m->pid = d->creds.pid;
529 m->tid = d->creds.tid;
530 m->uid_valid = m->gid_valid = true;
531 } else if (d->type == KDBUS_MSG_TIMESTAMP) {
532 m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC;
533 m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC;
534 } else if (d->type == KDBUS_MSG_SRC_PID_COMM)
536 else if (d->type == KDBUS_MSG_SRC_TID_COMM)
537 m->tid_comm = d->str;
538 else if (d->type == KDBUS_MSG_SRC_EXE)
540 else if (d->type == KDBUS_MSG_SRC_CMDLINE) {
542 m->cmdline_length = l;
543 } else if (d->type == KDBUS_MSG_SRC_CGROUP)
545 else if (d->type == KDBUS_MSG_SRC_AUDIT)
546 m->audit = &d->audit;
547 else if (d->type == KDBUS_MSG_SRC_CAPS) {
548 m->capability = d->data;
549 m->capability_size = l;
550 } else if (d->type != KDBUS_MSG_FDS &&
551 d->type != KDBUS_MSG_DST_NAME &&
552 d->type != KDBUS_MSG_SRC_SECLABEL)
553 log_debug("Got unknown field from kernel %llu", d->type);
556 if ((BUS_MESSAGE_FIELDS_SIZE(m) > 0 && !m->fields) || BUS_MESSAGE_SIZE(m) != idx) {
557 sd_bus_message_unref(m);
561 r = bus_message_parse_fields(m);
563 sd_bus_message_unref(m);
567 if (k->src_id == KDBUS_SRC_ID_KERNEL)
568 m->sender = "org.freedesktop.DBus";
570 snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
571 m->sender = m->sender_buffer;
574 if (!m->destination) {
576 m->destination = destination;
577 else if (k->dst_id != KDBUS_DST_ID_WELL_KNOWN_NAME &&
578 k->dst_id != KDBUS_DST_ID_BROADCAST) {
579 snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
580 m->destination = m->destination_buffer;
584 /* We take possession of the kmsg struct now */
586 m->bus = sd_bus_ref(bus);
587 m->release_kdbus = true;
596 int bus_kernel_read_message(sd_bus *bus, sd_bus_message **m) {
603 r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, &k);
612 /* /\* Let's tell valgrind that there's really no need to */
613 /* * initialize this fully. This should be removed again */
614 /* * when valgrind learned the kdbus ioctls natively. *\/ */
615 /* #ifdef HAVE_VALGRIND_MEMCHECK_H */
616 /* VALGRIND_MAKE_MEM_DEFINED(k, sz); */
620 r = bus_kernel_make_message(bus, k, m);
622 close_kdbus_msg(bus, k);
624 return r < 0 ? r : 1;
627 int bus_kernel_create(const char *name, char **s) {
628 struct kdbus_cmd_bus_make *make;
629 struct kdbus_item *n, *cg;
637 fd = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
642 make = alloca0(offsetof(struct kdbus_cmd_bus_make, items) +
643 KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t) +
644 KDBUS_ITEM_HEADER_SIZE + DECIMAL_STR_MAX(uid_t) + 1 + l + 1);
647 cg->type = KDBUS_MAKE_CGROUP;
649 cg->size = KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t);
651 n = KDBUS_ITEM_NEXT(cg);
652 n->type = KDBUS_MAKE_NAME;
653 sprintf(n->str, "%lu-%s", (unsigned long) getuid(), name);
654 n->size = KDBUS_ITEM_HEADER_SIZE + strlen(n->str) + 1;
656 make->size = offsetof(struct kdbus_cmd_bus_make, items) + cg->size + n->size;
657 make->flags = KDBUS_MAKE_POLICY_OPEN;
659 make->bloom_size = BLOOM_SIZE;
660 assert_cc(BLOOM_SIZE % 8 == 0);
662 p = strjoin("/dev/kdbus/", n->str, "/bus", NULL);
666 if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
667 close_nointr_nofail(fd);
678 int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *size) {
679 struct memfd_cache *c;
684 if (!bus || !bus->is_kernel)
687 if (bus->n_memfd_cache <= 0) {
690 fd = ioctl(bus->input_fd, KDBUS_CMD_MEMFD_NEW, &fd);
699 c = &bus->memfd_cache[-- bus->n_memfd_cache];
702 assert(c->size == 0 || c->address);
704 *address = c->address;
710 void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t size) {
711 struct memfd_cache *c;
714 assert(size == 0 || address);
716 if (!bus || !bus->is_kernel ||
717 bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
720 assert_se(munmap(address, PAGE_ALIGN(size)) == 0);
722 close_nointr_nofail(fd);
726 c = &bus->memfd_cache[bus->n_memfd_cache++];
728 c->address = address;
730 /* If overly long, let's return a bit to the OS */
731 if (size > MEMFD_CACHE_ITEM_SIZE_MAX) {
732 uint64_t sz = MEMFD_CACHE_ITEM_SIZE_MAX;
734 ioctl(bus->input_fd, KDBUS_CMD_MEMFD_SIZE_SET, &sz);
736 c->size = MEMFD_CACHE_ITEM_SIZE_MAX;
741 void bus_kernel_flush_memfd(sd_bus *b) {
746 for (i = 0; i < b->n_memfd_cache; i++) {
747 if (b->memfd_cache[i].size > 0)
748 assert_se(munmap(b->memfd_cache[i].address, PAGE_ALIGN(b->memfd_cache[i].size)) == 0);
750 close_nointr_nofail(b->memfd_cache[i].fd);