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_BUFFER_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 = (intptr_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;
200 if (m->destination) {
201 r = parse_unique_name(m->destination, &unique);
209 sz = offsetof(struct kdbus_msg, items);
211 /* Add in fixed header, fields header and payload */
212 sz += 3 * ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec));
214 /* Add space for bloom filter */
215 sz += ALIGN8(offsetof(struct kdbus_item, data) + BLOOM_SIZE);
217 /* Add in well-known destination header */
219 dl = strlen(m->destination);
220 sz += ALIGN8(offsetof(struct kdbus_item, str) + dl + 1);
223 /* Add space for unix fds */
225 sz += ALIGN8(offsetof(struct kdbus_item, fds) + sizeof(int)*m->n_fds);
227 m->kdbus = memalign(8, sz);
231 memset(m->kdbus, 0, sz);
234 ((m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_FLAGS_EXPECT_REPLY) |
235 ((m->header->flags & SD_BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_FLAGS_NO_AUTO_START : 0);
238 m->destination ? unique : KDBUS_DST_ID_BROADCAST;
239 m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS1;
240 m->kdbus->cookie = m->header->serial;
242 m->kdbus->timeout_ns = m->timeout * NSEC_PER_USEC;
247 append_destination(&d, m->destination, dl);
249 append_payload_vec(&d, m->header, sizeof(*m->header));
252 append_payload_vec(&d, m->fields, ALIGN8(m->header->fields_size));
255 append_payload_vec(&d, m->body, m->header->body_size);
257 if (m->kdbus->dst_id == KDBUS_DST_ID_BROADCAST) {
260 p = append_bloom(&d, BLOOM_SIZE);
261 r = bus_message_setup_bloom(m, p);
270 append_fds(&d, m->fds, m->n_fds);
272 m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus;
273 assert(m->kdbus->size <= sz);
275 m->free_kdbus = true;
280 int bus_kernel_take_fd(sd_bus *b) {
281 uint8_t h[ALIGN8(sizeof(struct kdbus_cmd_hello)) +
282 ALIGN8(KDBUS_ITEM_HEADER_SIZE) +
283 ALIGN8(sizeof(struct kdbus_vec))] = {};
285 struct kdbus_cmd_hello *hello = (struct kdbus_cmd_hello*) h;
294 if (!b->kdbus_buffer) {
295 b->kdbus_buffer = mmap(NULL, KDBUS_BUFFER_SIZE, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
296 if (b->kdbus_buffer == MAP_FAILED) {
297 b->kdbus_buffer = NULL;
302 hello->size = sizeof(h);
304 KDBUS_HELLO_ACCEPT_FD|
305 KDBUS_HELLO_ATTACH_COMM|
306 KDBUS_HELLO_ATTACH_EXE|
307 KDBUS_HELLO_ATTACH_CMDLINE|
308 KDBUS_HELLO_ATTACH_CGROUP|
309 KDBUS_HELLO_ATTACH_CAPS|
310 KDBUS_HELLO_ATTACH_SECLABEL|
311 KDBUS_HELLO_ATTACH_AUDIT;
313 hello->items[0].type = KDBUS_HELLO_BUFFER;
314 hello->items[0].size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
315 hello->items[0].vec.address = (uint64_t) b->kdbus_buffer;
316 hello->items[0].vec.size = KDBUS_BUFFER_SIZE;
318 r = ioctl(b->input_fd, KDBUS_CMD_HELLO, hello);
322 /* The higher 32bit of both flags fields are considered
323 * 'incompatible flags'. Refuse them all for now. */
324 if (hello->bus_flags > 0xFFFFFFFFULL ||
325 hello->conn_flags > 0xFFFFFFFFULL)
328 if (hello->bloom_size != BLOOM_SIZE)
331 if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello->id) < 0)
335 b->bus_client = true;
338 r = bus_start_running(b);
345 int bus_kernel_connect(sd_bus *b) {
347 assert(b->input_fd < 0);
348 assert(b->output_fd < 0);
354 b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
358 b->output_fd = b->input_fd;
360 return bus_kernel_take_fd(b);
363 int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
368 assert(bus->state == BUS_RUNNING);
370 r = bus_message_setup_kmsg(bus, m);
374 r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
376 return errno == EAGAIN ? 0 : -errno;
381 static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
382 struct kdbus_item *d;
387 ioctl(bus->input_fd, KDBUS_CMD_MSG_RELEASE, k);
389 KDBUS_ITEM_FOREACH(d, k) {
391 if (d->type != KDBUS_MSG_FDS)
394 close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
398 static bool range_contains(size_t astart, size_t asize, size_t bstart, size_t bsize, void *a, void **b) {
403 if (bstart + bsize > astart + asize)
406 *b = (uint8_t*) a + (bstart - astart);
411 static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_message **ret) {
412 sd_bus_message *m = NULL;
413 struct kdbus_item *d;
414 unsigned n_payload = 0, n_fds = 0;
415 _cleanup_free_ int *fds = NULL;
416 struct bus_header *h = NULL;
417 size_t total, n_bytes = 0, idx = 0;
418 const char *destination = NULL, *seclabel = NULL;
425 if (k->payload_type != KDBUS_PAYLOAD_DBUS1)
428 KDBUS_ITEM_FOREACH(d, k) {
431 l = d->size - offsetof(struct kdbus_item, data);
433 if (d->type == KDBUS_MSG_PAYLOAD_VEC) {
436 if (d->vec.size < sizeof(struct bus_header))
439 h = (struct bus_header*) d->vec.address;
443 n_bytes += d->vec.size;
445 } else if (d->type == KDBUS_MSG_FDS) {
450 f = realloc(fds, sizeof(int) * (n_fds + j));
455 memcpy(fds + n_fds, d->fds, sizeof(int) * j);
458 } else if (d->type == KDBUS_MSG_DST_NAME)
459 destination = d->str;
460 else if (d->type == KDBUS_MSG_SRC_SECLABEL)
467 r = bus_header_size(h, &total);
471 if (n_bytes != total)
477 r = bus_message_from_header(h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m);
481 KDBUS_ITEM_FOREACH(d, k) {
484 l = d->size - offsetof(struct kdbus_item, data);
486 if (d->type == KDBUS_MSG_PAYLOAD_VEC) {
488 range_contains(idx, d->vec.size, ALIGN8(sizeof(struct bus_header)), BUS_MESSAGE_FIELDS_SIZE(m), (void*) d->vec.address, &m->fields);
489 range_contains(idx, d->vec.size, ALIGN8(sizeof(struct bus_header)) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m)), BUS_MESSAGE_BODY_SIZE(m), (void*) d->vec.address, &m->body);
493 } else if (d->type == KDBUS_MSG_SRC_CREDS) {
494 m->pid_starttime = d->creds.starttime / NSEC_PER_USEC;
495 m->uid = d->creds.uid;
496 m->gid = d->creds.gid;
497 m->pid = d->creds.pid;
498 m->tid = d->creds.tid;
499 m->uid_valid = m->gid_valid = true;
500 } else if (d->type == KDBUS_MSG_TIMESTAMP) {
501 m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC;
502 m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC;
503 } else if (d->type == KDBUS_MSG_SRC_PID_COMM)
505 else if (d->type == KDBUS_MSG_SRC_TID_COMM)
506 m->tid_comm = d->str;
507 else if (d->type == KDBUS_MSG_SRC_EXE)
509 else if (d->type == KDBUS_MSG_SRC_CMDLINE) {
511 m->cmdline_length = l;
512 } else if (d->type == KDBUS_MSG_SRC_CGROUP)
514 else if (d->type == KDBUS_MSG_SRC_AUDIT)
515 m->audit = &d->audit;
516 else if (d->type == KDBUS_MSG_SRC_CAPS) {
517 m->capability = d->data;
518 m->capability_size = l;
519 } else if (d->type != KDBUS_MSG_FDS &&
520 d->type != KDBUS_MSG_DST_NAME &&
521 d->type != KDBUS_MSG_SRC_SECLABEL)
522 log_debug("Got unknown field from kernel %llu", d->type);
525 if ((BUS_MESSAGE_FIELDS_SIZE(m) > 0 && !m->fields) ||
526 (BUS_MESSAGE_BODY_SIZE(m) > 0 && !m->body)) {
527 sd_bus_message_unref(m);
531 r = bus_message_parse_fields(m);
533 sd_bus_message_unref(m);
537 if (k->src_id == KDBUS_SRC_ID_KERNEL)
538 m->sender = "org.freedesktop.DBus";
540 snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
541 m->sender = m->sender_buffer;
544 if (!m->destination) {
546 m->destination = destination;
547 else if (k->dst_id != KDBUS_DST_ID_WELL_KNOWN_NAME &&
548 k->dst_id != KDBUS_DST_ID_BROADCAST) {
549 snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
550 m->destination = m->destination_buffer;
554 /* We take possession of the kmsg struct now */
556 m->bus = sd_bus_ref(bus);
557 m->release_kdbus = true;
566 int bus_kernel_read_message(sd_bus *bus, sd_bus_message **m) {
573 r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, &k);
582 /* /\* Let's tell valgrind that there's really no need to */
583 /* * initialize this fully. This should be removed again */
584 /* * when valgrind learned the kdbus ioctls natively. *\/ */
585 /* #ifdef HAVE_VALGRIND_MEMCHECK_H */
586 /* VALGRIND_MAKE_MEM_DEFINED(k, sz); */
590 r = bus_kernel_make_message(bus, k, m);
592 close_kdbus_msg(bus, k);
594 return r < 0 ? r : 1;
597 int bus_kernel_create(const char *name, char **s) {
598 struct kdbus_cmd_bus_make *make;
599 struct kdbus_item *n, *cg;
607 fd = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
612 make = alloca0(offsetof(struct kdbus_cmd_bus_make, items) +
613 KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t) +
614 KDBUS_ITEM_HEADER_SIZE + DECIMAL_STR_MAX(uid_t) + 1 + l + 1);
617 cg->type = KDBUS_MAKE_CGROUP;
619 cg->size = KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t);
621 n = KDBUS_ITEM_NEXT(cg);
622 n->type = KDBUS_MAKE_NAME;
623 sprintf(n->str, "%lu-%s", (unsigned long) getuid(), name);
624 n->size = KDBUS_ITEM_HEADER_SIZE + strlen(n->str) + 1;
626 make->size = offsetof(struct kdbus_cmd_bus_make, items) + cg->size + n->size;
627 make->flags = KDBUS_MAKE_ACCESS_WORLD | KDBUS_MAKE_POLICY_OPEN;
629 make->bloom_size = BLOOM_SIZE;
630 assert_cc(BLOOM_SIZE % 8 == 0);
632 p = strjoin("/dev/kdbus/", n->str, "/bus", NULL);
636 if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
637 close_nointr_nofail(fd);