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>
31 #include "bus-internal.h"
32 #include "bus-message.h"
33 #include "bus-kernel.h"
34 #include "bus-bloom.h"
36 #define KDBUS_ITEM_NEXT(item) \
37 (typeof(item))(((uint8_t *)item) + ALIGN8((item)->size))
39 #define KDBUS_ITEM_FOREACH(item, head) \
40 for (item = (head)->items; \
41 (uint8_t *)(item) < (uint8_t *)(head) + (head)->size; \
42 item = KDBUS_ITEM_NEXT(item))
44 static int parse_unique_name(const char *s, uint64_t *id) {
50 if (!startswith(s, ":1."))
53 r = safe_atou64(s + 3, id);
60 static void append_payload_vec(struct kdbus_msg_item **d, const void *p, size_t sz) {
67 (*d)->size = offsetof(struct kdbus_msg_item, vec) + sizeof(struct kdbus_vec);
68 (*d)->type = KDBUS_MSG_PAYLOAD_VEC;
69 (*d)->vec.address = (uint64_t) p;
72 *d = (struct kdbus_msg_item *) ((uint8_t*) *d + (*d)->size);
75 static void append_destination(struct kdbus_msg_item **d, const char *s, size_t length) {
81 (*d)->size = offsetof(struct kdbus_msg_item, str) + length + 1;
82 (*d)->type = KDBUS_MSG_DST_NAME;
83 memcpy((*d)->str, s, length + 1);
85 *d = (struct kdbus_msg_item *) ((uint8_t*) *d + (*d)->size);
88 static void* append_bloom(struct kdbus_msg_item **d, size_t length) {
95 (*d)->size = offsetof(struct kdbus_msg_item, data) + length;
96 (*d)->type = KDBUS_MSG_BLOOM;
99 *d = (struct kdbus_msg_item *) ((uint8_t*) *d + (*d)->size);
104 static void append_fds(struct kdbus_msg_item **d, const int fds[], unsigned n_fds) {
110 (*d)->size = offsetof(struct kdbus_msg_item, fds) + sizeof(int) * n_fds;
111 (*d)->type = KDBUS_MSG_UNIX_FDS;
112 memcpy((*d)->fds, fds, sizeof(int) * n_fds);
114 *d = (struct kdbus_msg_item *) ((uint8_t*) *d + (*d)->size);
117 static int bus_message_setup_bloom(sd_bus_message *m, void *bloom) {
124 memset(bloom, 0, BLOOM_SIZE);
126 bloom_add_pair(bloom, "message-type", bus_message_type_to_string(m->header->type));
129 bloom_add_pair(bloom, "interface", m->interface);
131 bloom_add_pair(bloom, "member", m->member);
133 bloom_add_pair(bloom, "path", m->path);
134 bloom_add_prefixes(bloom, "path-slash-prefix", m->path, '/');
137 r = sd_bus_message_rewind(m, true);
141 for (i = 0; i < 64; i++) {
144 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
147 r = sd_bus_message_peek_type(m, &type, NULL);
151 if (type != SD_BUS_TYPE_STRING &&
152 type != SD_BUS_TYPE_OBJECT_PATH &&
153 type != SD_BUS_TYPE_SIGNATURE)
156 r = sd_bus_message_read_basic(m, type, &t);
160 e = stpcpy(buf, "arg");
164 *(e++) = '0' + (i / 10);
165 *(e++) = '0' + (i % 10);
169 bloom_add_pair(bloom, buf, t);
171 strcpy(e, "-dot-prefix");
172 bloom_add_prefixes(bloom, buf, t, '.');
173 strcpy(e, "-slash-prefix");
174 bloom_add_prefixes(bloom, buf, t, '/');
180 static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
181 struct kdbus_msg_item *d;
194 if (m->destination) {
195 r = parse_unique_name(m->destination, &unique);
203 sz = offsetof(struct kdbus_msg, items);
205 /* Add in fixed header, fields header and payload */
206 sz += 3 * ALIGN8(offsetof(struct kdbus_msg_item, vec) + sizeof(struct kdbus_vec));
208 /* Add space for bloom filter */
209 sz += ALIGN8(offsetof(struct kdbus_msg_item, data) + BLOOM_SIZE);
211 /* Add in well-known destination header */
213 dl = strlen(m->destination);
214 sz += ALIGN8(offsetof(struct kdbus_msg_item, str) + dl + 1);
217 /* Add space for unix fds */
219 sz += ALIGN8(offsetof(struct kdbus_msg_item, fds) + sizeof(int)*m->n_fds);
221 m->kdbus = memalign(8, sz);
225 memset(m->kdbus, 0, sz);
228 ((m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_FLAGS_EXPECT_REPLY) |
229 ((m->header->flags & SD_BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_FLAGS_NO_AUTO_START : 0);
232 m->destination ? unique : KDBUS_DST_ID_BROADCAST;
233 m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS1;
234 m->kdbus->cookie = m->header->serial;
236 m->kdbus->timeout_ns = m->timeout * NSEC_PER_USEC;
241 append_destination(&d, m->destination, dl);
243 append_payload_vec(&d, m->header, sizeof(*m->header));
246 append_payload_vec(&d, m->fields, ALIGN8(m->header->fields_size));
249 append_payload_vec(&d, m->body, m->header->body_size);
251 if (m->kdbus->dst_id == KDBUS_DST_ID_BROADCAST) {
254 p = append_bloom(&d, BLOOM_SIZE);
255 r = bus_message_setup_bloom(m, p);
264 append_fds(&d, m->fds, m->n_fds);
266 m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus;
267 assert(m->kdbus->size <= sz);
269 m->free_kdbus = true;
274 int bus_kernel_take_fd(sd_bus *b) {
275 struct kdbus_cmd_hello hello = {
277 KDBUS_CMD_HELLO_ACCEPT_FD|
278 KDBUS_CMD_HELLO_ACCEPT_MMAP|
279 KDBUS_CMD_HELLO_ATTACH_COMM|
280 KDBUS_CMD_HELLO_ATTACH_EXE|
281 KDBUS_CMD_HELLO_ATTACH_CMDLINE|
282 KDBUS_CMD_HELLO_ATTACH_CGROUP|
283 KDBUS_CMD_HELLO_ATTACH_CAPS|
284 KDBUS_CMD_HELLO_ATTACH_SECLABEL|
285 KDBUS_CMD_HELLO_ATTACH_AUDIT
294 r = ioctl(b->input_fd, KDBUS_CMD_HELLO, &hello);
298 /* The higher 32bit of both flags fields are considered
299 * 'incompatible flags'. Refuse them all for now. */
300 if (hello.bus_flags > 0xFFFFFFFFULL ||
301 hello.conn_flags > 0xFFFFFFFFULL)
304 if (hello.bloom_size != BLOOM_SIZE)
307 if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello.id) < 0)
311 b->bus_client = true;
314 r = bus_start_running(b);
321 int bus_kernel_connect(sd_bus *b) {
323 assert(b->input_fd < 0);
324 assert(b->output_fd < 0);
330 b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
334 b->output_fd = b->input_fd;
336 return bus_kernel_take_fd(b);
339 int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
344 assert(bus->state == BUS_RUNNING);
346 r = bus_message_setup_kmsg(bus, m);
350 r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
352 return errno == EAGAIN ? 0 : -errno;
357 static void close_kdbus_msg(struct kdbus_msg *k) {
358 struct kdbus_msg_item *d;
360 KDBUS_ITEM_FOREACH(d, k) {
362 if (d->type != KDBUS_MSG_UNIX_FDS)
365 close_many(d->fds, (d->size - offsetof(struct kdbus_msg_item, fds)) / sizeof(int));
369 static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_message **ret) {
370 sd_bus_message *m = NULL;
371 struct kdbus_msg_item *d;
372 unsigned n_payload = 0, n_fds = 0;
373 _cleanup_free_ int *fds = NULL;
374 struct bus_header *h = NULL;
375 size_t total, n_bytes = 0, idx = 0;
376 const char *destination = NULL, *seclabel = NULL;
383 if (k->payload_type != KDBUS_PAYLOAD_DBUS1)
386 KDBUS_ITEM_FOREACH(d, k) {
389 l = d->size - offsetof(struct kdbus_msg_item, data);
391 if (d->type == KDBUS_MSG_PAYLOAD) {
394 if (l < sizeof(struct bus_header))
397 h = (struct bus_header*) d->data;
403 } else if (d->type == KDBUS_MSG_UNIX_FDS) {
408 f = realloc(fds, sizeof(int) * (n_fds + j));
413 memcpy(fds + n_fds, d->fds, sizeof(int) * j);
416 } else if (d->type == KDBUS_MSG_DST_NAME)
417 destination = d->str;
418 else if (d->type == KDBUS_MSG_SRC_SECLABEL)
425 r = bus_header_size(h, &total);
429 if (n_bytes != total)
432 r = bus_message_from_header(h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m);
436 KDBUS_ITEM_FOREACH(d, k) {
439 l = d->size - offsetof(struct kdbus_msg_item, data);
441 if (d->type == KDBUS_MSG_PAYLOAD) {
443 if (idx == sizeof(struct bus_header) &&
444 l == ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m)))
446 else if (idx == sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m)) &&
447 l == BUS_MESSAGE_BODY_SIZE(m))
449 else if (!(idx == 0 && l == sizeof(struct bus_header))) {
450 sd_bus_message_unref(m);
455 } else if (d->type == KDBUS_MSG_SRC_CREDS) {
456 m->pid_starttime = d->creds.starttime / NSEC_PER_USEC;
457 m->uid = d->creds.uid;
458 m->gid = d->creds.gid;
459 m->pid = d->creds.pid;
460 m->tid = d->creds.tid;
461 m->uid_valid = m->gid_valid = true;
462 } else if (d->type == KDBUS_MSG_TIMESTAMP) {
463 m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC;
464 m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC;
465 } else if (d->type == KDBUS_MSG_SRC_PID_COMM)
467 else if (d->type == KDBUS_MSG_SRC_TID_COMM)
468 m->tid_comm = d->str;
469 else if (d->type == KDBUS_MSG_SRC_EXE)
471 else if (d->type == KDBUS_MSG_SRC_CMDLINE) {
473 m->cmdline_length = l;
474 } else if (d->type == KDBUS_MSG_SRC_CGROUP)
476 else if (d->type == KDBUS_MSG_SRC_AUDIT)
477 m->audit = &d->audit;
478 else if (d->type == KDBUS_MSG_SRC_CAPS) {
479 m->capability = d->data;
480 m->capability_size = l;
482 log_debug("Got unknown field from kernel %llu", d->type);
485 r = bus_message_parse_fields(m);
487 sd_bus_message_unref(m);
491 if (k->src_id == KDBUS_SRC_ID_KERNEL)
492 m->sender = "org.freedesktop.DBus";
494 snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
495 m->sender = m->sender_buffer;
498 if (!m->destination) {
500 m->destination = destination;
501 else if (k->dst_id != KDBUS_DST_ID_WELL_KNOWN_NAME &&
502 k->dst_id != KDBUS_DST_ID_BROADCAST) {
503 snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
504 m->destination = m->destination_buffer;
508 /* We take possession of the kmsg struct now */
510 m->free_kdbus = true;
519 int bus_kernel_read_message(sd_bus *bus, sd_bus_message **m) {
535 k = bus->rbuffer = q;
538 /* Let's tell valgrind that there's really no need to
539 * initialize this fully. This should be removed again
540 * when valgrind learned the kdbus ioctls natively. */
541 #ifdef HAVE_VALGRIND_MEMCHECK_H
542 VALGRIND_MAKE_MEM_DEFINED(k, sz);
545 r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, bus->rbuffer);
552 if (errno != ENOBUFS)
558 r = bus_kernel_make_message(bus, k, m);
564 return r < 0 ? r : 1;
567 int bus_kernel_create(const char *name, char **s) {
568 struct kdbus_cmd_bus_make *make;
569 struct kdbus_cmd_make_item *n, *cg;
577 fd = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
582 make = alloca0(offsetof(struct kdbus_cmd_bus_make, items) +
583 sizeof(struct kdbus_cmd_make_item) + sizeof(uint64_t) +
584 sizeof(struct kdbus_cmd_make_item) + DECIMAL_STR_MAX(uid_t) + 1 + l + 1);
587 cg->type = KDBUS_CMD_MAKE_CGROUP;
589 cg->size = sizeof(struct kdbus_cmd_make_item) + sizeof(uint64_t);
591 n = KDBUS_ITEM_NEXT(cg);
592 n->type = KDBUS_CMD_MAKE_NAME;
593 sprintf(n->str, "%lu-%s", (unsigned long) getuid(), name);
594 n->size = sizeof(struct kdbus_cmd_make_item) + strlen(n->str) + 1;
596 make->size = offsetof(struct kdbus_cmd_bus_make, items) + cg->size + n->size;
597 make->flags = KDBUS_ACCESS_WORLD | KDBUS_POLICY_OPEN;
599 make->bloom_size = BLOOM_SIZE;
600 assert_cc(BLOOM_SIZE % 8 == 0);
602 p = strjoin("/dev/kdbus/", n->str, "/bus", NULL);
606 if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
607 close_nointr_nofail(fd);