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)
433 close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
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;
440 unsigned n_payload = 0, n_fds = 0;
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))
469 n_bytes += d->vec.size;
471 } else if (d->type == KDBUS_MSG_FDS) {
476 f = realloc(fds, sizeof(int) * (n_fds + j));
481 memcpy(fds + n_fds, d->fds, sizeof(int) * j);
484 } else if (d->type == KDBUS_MSG_DST_NAME)
485 destination = d->str;
486 else if (d->type == KDBUS_MSG_SRC_SECLABEL)
493 r = bus_header_message_size(h, &total);
497 if (n_bytes != total)
500 r = bus_message_from_header(h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m);
504 KDBUS_ITEM_FOREACH(d, k) {
507 l = d->size - offsetof(struct kdbus_item, data);
509 if (d->type == KDBUS_MSG_PAYLOAD_VEC) {
512 begin_body = BUS_MESSAGE_BODY_BEGIN(m);
514 if (idx + d->vec.size > begin_body) {
515 struct bus_body_part *part;
517 /* Contains body material */
519 part = message_append_part(m);
521 sd_bus_message_unref(m);
525 if (idx >= begin_body) {
526 part->data = UINT64_TO_PTR(d->vec.address);
527 part->size = d->vec.size;
529 part->data = d->vec.address != 0 ? (uint8_t*) UINT64_TO_PTR(d->vec.address) + (begin_body - idx) : NULL;
530 part->size = d->vec.size - (begin_body - idx);
533 part->is_zero = d->vec.address == 0;
539 } else if (d->type == KDBUS_MSG_SRC_CREDS) {
540 m->pid_starttime = d->creds.starttime / NSEC_PER_USEC;
541 m->uid = d->creds.uid;
542 m->gid = d->creds.gid;
543 m->pid = d->creds.pid;
544 m->tid = d->creds.tid;
545 m->uid_valid = m->gid_valid = true;
546 } else if (d->type == KDBUS_MSG_TIMESTAMP) {
547 m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC;
548 m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC;
549 } else if (d->type == KDBUS_MSG_SRC_PID_COMM)
551 else if (d->type == KDBUS_MSG_SRC_TID_COMM)
552 m->tid_comm = d->str;
553 else if (d->type == KDBUS_MSG_SRC_EXE)
555 else if (d->type == KDBUS_MSG_SRC_CMDLINE) {
557 m->cmdline_length = l;
558 } else if (d->type == KDBUS_MSG_SRC_CGROUP)
560 else if (d->type == KDBUS_MSG_SRC_AUDIT)
561 m->audit = &d->audit;
562 else if (d->type == KDBUS_MSG_SRC_CAPS) {
563 m->capability = d->data;
564 m->capability_size = l;
565 } else if (d->type != KDBUS_MSG_FDS &&
566 d->type != KDBUS_MSG_DST_NAME &&
567 d->type != KDBUS_MSG_SRC_SECLABEL)
568 log_debug("Got unknown field from kernel %llu", d->type);
571 r = bus_message_parse_fields(m);
573 sd_bus_message_unref(m);
577 if (k->src_id == KDBUS_SRC_ID_KERNEL)
578 m->sender = "org.freedesktop.DBus";
580 snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
581 m->sender = m->sender_buffer;
584 if (!m->destination) {
586 m->destination = destination;
587 else if (k->dst_id != KDBUS_DST_ID_WELL_KNOWN_NAME &&
588 k->dst_id != KDBUS_DST_ID_BROADCAST) {
589 snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
590 m->destination = m->destination_buffer;
594 /* We take possession of the kmsg struct now */
596 m->bus = sd_bus_ref(bus);
597 m->release_kdbus = true;
606 int bus_kernel_read_message(sd_bus *bus, sd_bus_message **m) {
613 r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, &k);
622 /* /\* Let's tell valgrind that there's really no need to */
623 /* * initialize this fully. This should be removed again */
624 /* * when valgrind learned the kdbus ioctls natively. *\/ */
625 /* #ifdef HAVE_VALGRIND_MEMCHECK_H */
626 /* VALGRIND_MAKE_MEM_DEFINED(k, sz); */
630 r = bus_kernel_make_message(bus, k, m);
632 close_kdbus_msg(bus, k);
634 return r < 0 ? r : 1;
637 int bus_kernel_create(const char *name, char **s) {
638 struct kdbus_cmd_bus_make *make;
639 struct kdbus_item *n, *cg;
647 fd = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
652 make = alloca0(offsetof(struct kdbus_cmd_bus_make, items) +
653 KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t) +
654 KDBUS_ITEM_HEADER_SIZE + DECIMAL_STR_MAX(uid_t) + 1 + l + 1);
657 cg->type = KDBUS_MAKE_CGROUP;
659 cg->size = KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t);
661 n = KDBUS_ITEM_NEXT(cg);
662 n->type = KDBUS_MAKE_NAME;
663 sprintf(n->str, "%lu-%s", (unsigned long) getuid(), name);
664 n->size = KDBUS_ITEM_HEADER_SIZE + strlen(n->str) + 1;
666 make->size = offsetof(struct kdbus_cmd_bus_make, items) + cg->size + n->size;
667 make->flags = KDBUS_MAKE_POLICY_OPEN;
669 make->bloom_size = BLOOM_SIZE;
670 assert_cc(BLOOM_SIZE % 8 == 0);
672 p = strjoin("/dev/kdbus/", n->str, "/bus", NULL);
676 if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
677 close_nointr_nofail(fd);
688 int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *size) {
689 struct memfd_cache *c;
694 if (!bus || !bus->is_kernel)
697 if (bus->n_memfd_cache <= 0) {
700 r = ioctl(bus->input_fd, KDBUS_CMD_MEMFD_NEW, &fd);
709 c = &bus->memfd_cache[-- bus->n_memfd_cache];
712 assert(c->size == 0 || c->address);
714 *address = c->address;
720 void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t size) {
721 struct memfd_cache *c;
724 assert(size == 0 || address);
726 if (!bus || !bus->is_kernel ||
727 bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
730 assert_se(munmap(address, PAGE_ALIGN(size)) == 0);
732 close_nointr_nofail(fd);
736 c = &bus->memfd_cache[bus->n_memfd_cache++];
738 c->address = address;
740 /* If overly long, let's return a bit to the OS */
741 if (size > MEMFD_CACHE_ITEM_SIZE_MAX) {
742 uint64_t sz = MEMFD_CACHE_ITEM_SIZE_MAX;
744 ioctl(bus->input_fd, KDBUS_CMD_MEMFD_SIZE_SET, &sz);
746 c->size = MEMFD_CACHE_ITEM_SIZE_MAX;
751 void bus_kernel_flush_memfd(sd_bus *b) {
756 for (i = 0; i < b->n_memfd_cache; i++) {
757 if (b->memfd_cache[i].size > 0)
758 assert_se(munmap(b->memfd_cache[i].address, PAGE_ALIGN(b->memfd_cache[i].size)) == 0);
760 close_nointr_nofail(b->memfd_cache[i].fd);