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) {
72 (*d)->size = offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec);
73 (*d)->type = KDBUS_MSG_PAYLOAD_VEC;
74 (*d)->vec.address = PTR_TO_UINT64(p);
77 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
80 static void append_payload_memfd(struct kdbus_item **d, int memfd, size_t sz) {
86 (*d)->size = offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd);
87 (*d)->type = KDBUS_MSG_PAYLOAD_MEMFD;
88 (*d)->memfd.fd = memfd;
89 (*d)->memfd.size = sz;
91 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
94 static void append_destination(struct kdbus_item **d, const char *s, size_t length) {
100 (*d)->size = offsetof(struct kdbus_item, str) + length + 1;
101 (*d)->type = KDBUS_MSG_DST_NAME;
102 memcpy((*d)->str, s, length + 1);
104 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
107 static void* append_bloom(struct kdbus_item **d, size_t length) {
114 (*d)->size = offsetof(struct kdbus_item, data) + length;
115 (*d)->type = KDBUS_MSG_BLOOM;
118 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
123 static void append_fds(struct kdbus_item **d, const int fds[], unsigned n_fds) {
129 (*d)->size = offsetof(struct kdbus_item, fds) + sizeof(int) * n_fds;
130 (*d)->type = KDBUS_MSG_FDS;
131 memcpy((*d)->fds, fds, sizeof(int) * n_fds);
133 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
136 static int bus_message_setup_bloom(sd_bus_message *m, void *bloom) {
143 memset(bloom, 0, BLOOM_SIZE);
145 bloom_add_pair(bloom, "message-type", bus_message_type_to_string(m->header->type));
148 bloom_add_pair(bloom, "interface", m->interface);
150 bloom_add_pair(bloom, "member", m->member);
152 bloom_add_pair(bloom, "path", m->path);
153 bloom_add_prefixes(bloom, "path-slash-prefix", m->path, '/');
156 r = sd_bus_message_rewind(m, true);
160 for (i = 0; i < 64; i++) {
163 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
166 r = sd_bus_message_peek_type(m, &type, NULL);
170 if (type != SD_BUS_TYPE_STRING &&
171 type != SD_BUS_TYPE_OBJECT_PATH &&
172 type != SD_BUS_TYPE_SIGNATURE)
175 r = sd_bus_message_read_basic(m, type, &t);
179 e = stpcpy(buf, "arg");
183 *(e++) = '0' + (i / 10);
184 *(e++) = '0' + (i % 10);
188 bloom_add_pair(bloom, buf, t);
190 strcpy(e, "-dot-prefix");
191 bloom_add_prefixes(bloom, buf, t, '.');
192 strcpy(e, "-slash-prefix");
193 bloom_add_prefixes(bloom, buf, t, '/');
199 static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
200 struct bus_body_part *part;
201 struct kdbus_item *d;
215 if (m->destination) {
216 r = parse_unique_name(m->destination, &unique);
224 sz = offsetof(struct kdbus_msg, items);
226 assert_cc(ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec)) ==
227 ALIGN8(offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd)));
229 /* Add in fixed header, fields header and payload */
230 sz += (1 + m->n_body_parts) *
231 ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec));
233 /* Add space for bloom filter */
234 sz += ALIGN8(offsetof(struct kdbus_item, data) + BLOOM_SIZE);
236 /* Add in well-known destination header */
238 dl = strlen(m->destination);
239 sz += ALIGN8(offsetof(struct kdbus_item, str) + dl + 1);
242 /* Add space for unix fds */
244 sz += ALIGN8(offsetof(struct kdbus_item, fds) + sizeof(int)*m->n_fds);
246 m->kdbus = memalign(8, sz);
250 memset(m->kdbus, 0, sz);
253 ((m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_FLAGS_EXPECT_REPLY) |
254 ((m->header->flags & SD_BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_FLAGS_NO_AUTO_START : 0);
257 m->destination ? unique : KDBUS_DST_ID_BROADCAST;
258 m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS1;
259 m->kdbus->cookie = m->header->serial;
261 m->kdbus->timeout_ns = m->timeout * NSEC_PER_USEC;
266 append_destination(&d, m->destination, dl);
268 append_payload_vec(&d, m->header, BUS_MESSAGE_BODY_BEGIN(m));
270 MESSAGE_FOREACH_PART(part, i, m) {
272 append_payload_vec(&d, NULL, part->size);
276 if (part->memfd >= 0 && part->sealed) {
277 bus_body_part_unmap(part);
280 append_payload_memfd(&d, part->memfd, part->size);
285 if (part->memfd >= 0) {
286 r = bus_body_part_map(part);
291 append_payload_vec(&d, part->data, part->size);
294 if (m->kdbus->dst_id == KDBUS_DST_ID_BROADCAST) {
297 p = append_bloom(&d, BLOOM_SIZE);
298 r = bus_message_setup_bloom(m, p);
304 append_fds(&d, m->fds, m->n_fds);
306 m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus;
307 assert(m->kdbus->size <= sz);
309 m->free_kdbus = true;
319 int bus_kernel_take_fd(sd_bus *b) {
320 uint8_t h[ALIGN8(sizeof(struct kdbus_cmd_hello)) +
321 ALIGN8(KDBUS_ITEM_HEADER_SIZE) +
322 ALIGN8(sizeof(struct kdbus_vec))] = {};
324 struct kdbus_cmd_hello *hello = (struct kdbus_cmd_hello*) h;
333 if (!b->kdbus_buffer) {
334 b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
335 if (b->kdbus_buffer == MAP_FAILED) {
336 b->kdbus_buffer = NULL;
341 hello->size = sizeof(h);
343 KDBUS_HELLO_ACCEPT_FD|
344 KDBUS_HELLO_ATTACH_COMM|
345 KDBUS_HELLO_ATTACH_EXE|
346 KDBUS_HELLO_ATTACH_CMDLINE|
347 KDBUS_HELLO_ATTACH_CGROUP|
348 KDBUS_HELLO_ATTACH_CAPS|
349 KDBUS_HELLO_ATTACH_SECLABEL|
350 KDBUS_HELLO_ATTACH_AUDIT;
352 hello->items[0].type = KDBUS_HELLO_POOL;
353 hello->items[0].size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
354 hello->items[0].vec.address = (uint64_t) b->kdbus_buffer;
355 hello->items[0].vec.size = KDBUS_POOL_SIZE;
357 r = ioctl(b->input_fd, KDBUS_CMD_HELLO, hello);
361 /* The higher 32bit of both flags fields are considered
362 * 'incompatible flags'. Refuse them all for now. */
363 if (hello->bus_flags > 0xFFFFFFFFULL ||
364 hello->conn_flags > 0xFFFFFFFFULL)
367 if (hello->bloom_size != BLOOM_SIZE)
370 if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello->id) < 0)
374 b->bus_client = true;
377 r = bus_start_running(b);
384 int bus_kernel_connect(sd_bus *b) {
386 assert(b->input_fd < 0);
387 assert(b->output_fd < 0);
393 b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
397 b->output_fd = b->input_fd;
399 return bus_kernel_take_fd(b);
402 int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
407 assert(bus->state == BUS_RUNNING);
409 r = bus_message_setup_kmsg(bus, m);
413 r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
415 return errno == EAGAIN ? 0 : -errno;
420 static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
421 struct kdbus_item *d;
426 ioctl(bus->input_fd, KDBUS_CMD_MSG_RELEASE, k);
428 KDBUS_ITEM_FOREACH(d, k) {
430 if (d->type == KDBUS_MSG_FDS)
431 close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
432 else if (d->type == KDBUS_MSG_PAYLOAD_MEMFD)
433 close_nointr_nofail(d->memfd.fd);
437 static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_message **ret) {
438 sd_bus_message *m = NULL;
439 struct kdbus_item *d;
441 _cleanup_free_ int *fds = NULL;
442 struct bus_header *h = NULL;
443 size_t total, n_bytes = 0, idx = 0;
444 const char *destination = NULL, *seclabel = NULL;
451 if (k->payload_type != KDBUS_PAYLOAD_DBUS1)
454 KDBUS_ITEM_FOREACH(d, k) {
457 l = d->size - offsetof(struct kdbus_item, data);
459 if (d->type == KDBUS_MSG_PAYLOAD_VEC) {
462 h = UINT64_TO_PTR(d->vec.address);
464 if (!bus_header_is_complete(h, d->vec.size))
468 n_bytes += d->vec.size;
470 } else if (d->type == KDBUS_MSG_PAYLOAD_MEMFD) {
475 n_bytes += d->memfd.size;
477 } else if (d->type == KDBUS_MSG_FDS) {
482 f = realloc(fds, sizeof(int) * (n_fds + j));
487 memcpy(fds + n_fds, d->fds, sizeof(int) * j);
490 } else if (d->type == KDBUS_MSG_SRC_SECLABEL)
497 r = bus_header_message_size(h, &total);
501 if (n_bytes != total)
504 r = bus_message_from_header(h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m);
508 KDBUS_ITEM_FOREACH(d, k) {
511 l = d->size - offsetof(struct kdbus_item, data);
513 if (d->type == KDBUS_MSG_PAYLOAD_VEC) {
516 begin_body = BUS_MESSAGE_BODY_BEGIN(m);
518 if (idx + d->vec.size > begin_body) {
519 struct bus_body_part *part;
521 /* Contains body material */
523 part = message_append_part(m);
529 if (idx >= begin_body) {
530 part->data = UINT64_TO_PTR(d->vec.address);
531 part->size = d->vec.size;
533 part->data = d->vec.address != 0 ? (uint8_t*) UINT64_TO_PTR(d->vec.address) + (begin_body - idx) : NULL;
534 part->size = d->vec.size - (begin_body - idx);
537 part->is_zero = d->vec.address == 0;
542 } else if (d->type == KDBUS_MSG_PAYLOAD_MEMFD) {
543 struct bus_body_part *part;
545 if (idx < BUS_MESSAGE_BODY_BEGIN(m)) {
550 part = message_append_part(m);
556 part->memfd = d->memfd.fd;
557 part->size = d->memfd.size;
560 idx += d->memfd.size;
562 } else if (d->type == KDBUS_MSG_SRC_CREDS) {
563 m->pid_starttime = d->creds.starttime / NSEC_PER_USEC;
564 m->uid = d->creds.uid;
565 m->gid = d->creds.gid;
566 m->pid = d->creds.pid;
567 m->tid = d->creds.tid;
568 m->uid_valid = m->gid_valid = true;
569 } else if (d->type == KDBUS_MSG_TIMESTAMP) {
570 m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC;
571 m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC;
572 } else if (d->type == KDBUS_MSG_SRC_PID_COMM)
574 else if (d->type == KDBUS_MSG_SRC_TID_COMM)
575 m->tid_comm = d->str;
576 else if (d->type == KDBUS_MSG_SRC_EXE)
578 else if (d->type == KDBUS_MSG_SRC_CMDLINE) {
580 m->cmdline_length = l;
581 } else if (d->type == KDBUS_MSG_SRC_CGROUP)
583 else if (d->type == KDBUS_MSG_SRC_AUDIT)
584 m->audit = &d->audit;
585 else if (d->type == KDBUS_MSG_SRC_CAPS) {
586 m->capability = d->data;
587 m->capability_size = l;
588 } else if (d->type == KDBUS_MSG_DST_NAME)
589 destination = d->str;
590 else if (d->type != KDBUS_MSG_FDS &&
591 d->type != KDBUS_MSG_SRC_SECLABEL)
592 log_debug("Got unknown field from kernel %llu", d->type);
595 r = bus_message_parse_fields(m);
599 if (k->src_id == KDBUS_SRC_ID_KERNEL)
600 m->sender = "org.freedesktop.DBus";
602 snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
603 m->sender = m->sender_buffer;
606 if (!m->destination) {
608 m->destination = destination;
609 else if (k->dst_id != KDBUS_DST_ID_WELL_KNOWN_NAME &&
610 k->dst_id != KDBUS_DST_ID_BROADCAST) {
611 snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
612 m->destination = m->destination_buffer;
616 /* We take possession of the kmsg struct now */
618 m->bus = sd_bus_ref(bus);
619 m->release_kdbus = true;
629 struct bus_body_part *part;
632 /* Make sure the memfds are not freed twice */
633 MESSAGE_FOREACH_PART(part, i, m)
634 if (part->memfd >= 0)
637 sd_bus_message_unref(m);
643 int bus_kernel_read_message(sd_bus *bus, sd_bus_message **m) {
650 r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, &k);
658 r = bus_kernel_make_message(bus, k, m);
660 close_kdbus_msg(bus, k);
662 return r < 0 ? r : 1;
665 int bus_kernel_create(const char *name, char **s) {
666 struct kdbus_cmd_bus_make *make;
667 struct kdbus_item *n, *cg;
675 fd = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
680 make = alloca0(offsetof(struct kdbus_cmd_bus_make, items) +
681 KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t) +
682 KDBUS_ITEM_HEADER_SIZE + DECIMAL_STR_MAX(uid_t) + 1 + l + 1);
685 cg->type = KDBUS_MAKE_CGROUP;
687 cg->size = KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t);
689 n = KDBUS_ITEM_NEXT(cg);
690 n->type = KDBUS_MAKE_NAME;
691 sprintf(n->str, "%lu-%s", (unsigned long) getuid(), name);
692 n->size = KDBUS_ITEM_HEADER_SIZE + strlen(n->str) + 1;
694 make->size = offsetof(struct kdbus_cmd_bus_make, items) + cg->size + n->size;
695 make->flags = KDBUS_MAKE_POLICY_OPEN;
697 make->bloom_size = BLOOM_SIZE;
698 assert_cc(BLOOM_SIZE % 8 == 0);
700 p = strjoin("/dev/kdbus/", n->str, "/bus", NULL);
704 if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
705 close_nointr_nofail(fd);
716 int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *size) {
717 struct memfd_cache *c;
722 if (!bus || !bus->is_kernel)
725 if (bus->n_memfd_cache <= 0) {
728 r = ioctl(bus->input_fd, KDBUS_CMD_MEMFD_NEW, &fd);
737 c = &bus->memfd_cache[-- bus->n_memfd_cache];
740 assert(c->size == 0 || c->address);
742 *address = c->address;
748 void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t size) {
749 struct memfd_cache *c;
752 assert(size == 0 || address);
754 if (!bus || !bus->is_kernel ||
755 bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
758 assert_se(munmap(address, PAGE_ALIGN(size)) == 0);
760 close_nointr_nofail(fd);
764 c = &bus->memfd_cache[bus->n_memfd_cache++];
766 c->address = address;
768 /* If overly long, let's return a bit to the OS */
769 if (size > MEMFD_CACHE_ITEM_SIZE_MAX) {
770 uint64_t sz = MEMFD_CACHE_ITEM_SIZE_MAX;
772 ioctl(bus->input_fd, KDBUS_CMD_MEMFD_SIZE_SET, &sz);
774 c->size = MEMFD_CACHE_ITEM_SIZE_MAX;
779 void bus_kernel_flush_memfd(sd_bus *b) {
784 for (i = 0; i < b->n_memfd_cache; i++) {
785 if (b->memfd_cache[i].size > 0)
786 assert_se(munmap(b->memfd_cache[i].address, PAGE_ALIGN(b->memfd_cache[i].size)) == 0);
788 close_nointr_nofail(b->memfd_cache[i].fd);