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>
30 #include "bus-internal.h"
31 #include "bus-message.h"
32 #include "bus-kernel.h"
34 #define KDBUS_MSG_FOREACH_DATA(d, k) \
35 for ((d) = (k)->data; \
36 (uint8_t*) (d) < (uint8_t*) (k) + (k)->size; \
37 (d) = (struct kdbus_msg_data*) ((uint8_t*) (d) + ALIGN8((d)->size)))
39 static int parse_unique_name(const char *s, uint64_t *id) {
45 if (!startswith(s, ":1."))
48 r = safe_atou64(s + 3, id);
55 static void append_payload_vec(struct kdbus_msg_data **d, const void *p, size_t sz) {
60 (*d)->size = offsetof(struct kdbus_msg_data, vec) + sizeof(struct kdbus_vec);
61 (*d)->type = KDBUS_MSG_PAYLOAD_VEC;
62 (*d)->vec.address = (uint64_t) p;
65 *d = (struct kdbus_msg_data*) ((uint8_t*) *d + ALIGN8((*d)->size));
68 static void append_destination(struct kdbus_msg_data **d, const char *s, size_t length) {
72 (*d)->size = offsetof(struct kdbus_msg_data, data) + length + 1;
73 (*d)->type = KDBUS_MSG_DST_NAME;
74 memcpy((*d)->data, s, length + 1);
76 *d = (struct kdbus_msg_data*) ((uint8_t*) *d + ALIGN8((*d)->size));
79 static int bus_message_setup_kmsg(sd_bus_message *m) {
80 struct kdbus_msg_data *d;
93 r = parse_unique_name(m->destination, &unique);
101 sz = offsetof(struct kdbus_msg, data);
103 /* Add in fixed header, fields header, fields header padding and payload */
104 sz += 4 * ALIGN8(offsetof(struct kdbus_msg_data, vec) + sizeof(struct kdbus_vec));
106 /* Add in well-known destination header */
108 dl = strlen(m->destination);
109 sz += ALIGN8(offsetof(struct kdbus_msg, data) + dl + 1);
112 m->kdbus = malloc0(sz);
117 ((m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_FLAGS_EXPECT_REPLY) |
118 ((m->header->flags & SD_BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_FLAGS_NO_AUTO_START : 0);
121 m->destination ? unique : (uint64_t) -1;
122 m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS1;
123 m->kdbus->cookie = m->header->serial;
125 m->kdbus->timeout_ns = m->timeout * NSEC_PER_USEC;
130 append_destination(&d, m->destination, dl);
132 append_payload_vec(&d, m->header, sizeof(*m->header));
135 append_payload_vec(&d, m->fields, m->header->fields_size);
137 if (m->header->fields_size % 8 != 0) {
138 static const uint8_t padding[7] = {};
140 append_payload_vec(&d, padding, 8 - (m->header->fields_size % 8));
145 append_payload_vec(&d, m->body, m->header->body_size);
147 m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus;
148 assert(m->kdbus->size <= sz);
150 m->free_kdbus = true;
155 int bus_kernel_take_fd(sd_bus *b) {
156 struct kdbus_cmd_hello hello = {};
164 r = ioctl(b->input_fd, KDBUS_CMD_HELLO, &hello);
168 if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello.id) < 0)
172 b->bus_client = true;
174 r = bus_start_running(b);
181 int bus_kernel_connect(sd_bus *b) {
183 assert(b->input_fd < 0);
184 assert(b->output_fd < 0);
190 b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
194 b->output_fd = b->input_fd;
196 return bus_kernel_take_fd(b);
199 int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
204 assert(bus->state == BUS_RUNNING);
206 r = bus_message_setup_kmsg(m);
210 r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
212 return errno == EAGAIN ? 0 : -errno;
217 static void close_kdbus_msg(struct kdbus_msg *k) {
218 struct kdbus_msg_data *d;
220 KDBUS_MSG_FOREACH_DATA(d, k) {
222 if (d->type != KDBUS_MSG_UNIX_FDS)
225 close_many(d->fds, (d->size - offsetof(struct kdbus_msg_data, fds)) / sizeof(int));
229 static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_message **ret) {
230 sd_bus_message *m = NULL;
231 struct kdbus_msg_data *d;
232 unsigned n_payload = 0, n_fds = 0;
233 _cleanup_free_ int *fds = NULL;
234 struct bus_header *h = NULL;
235 size_t total, n_bytes = 0, idx = 0;
236 struct kdbus_creds *creds = NULL;
244 if (k->payload_type != KDBUS_PAYLOAD_DBUS1)
247 KDBUS_MSG_FOREACH_DATA(d, k) {
250 l = d->size - offsetof(struct kdbus_msg_data, data);
252 if (d->type == KDBUS_MSG_PAYLOAD) {
255 if (l < sizeof(struct bus_header))
258 h = (struct bus_header*) d->data;
264 } else if (d->type == KDBUS_MSG_UNIX_FDS) {
269 f = realloc(fds, sizeof(int) * (n_fds + j));
274 memcpy(fds + n_fds, d->fds, j);
277 } else if (d->type == KDBUS_MSG_SRC_CREDS)
279 else if (d->type == KDBUS_MSG_TIMESTAMP)
286 r = bus_header_size(h, &total);
290 if (n_bytes != total)
293 r = bus_message_from_header(h, sizeof(struct bus_header), fds, n_fds, NULL, NULL, 0, &m);
297 KDBUS_MSG_FOREACH_DATA(d, k) {
300 if (d->type != KDBUS_MSG_PAYLOAD)
303 l = d->size - offsetof(struct kdbus_msg_data, data);
304 if (idx == sizeof(struct bus_header) &&
305 l == BUS_MESSAGE_FIELDS_SIZE(m))
307 else if (idx == sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m)) &&
308 l == BUS_MESSAGE_BODY_SIZE(m))
310 else if (!(idx == 0 && l == sizeof(struct bus_header)) &&
311 !(idx == sizeof(struct bus_header) + BUS_MESSAGE_FIELDS_SIZE(m))) {
312 sd_bus_message_unref(m);
320 m->pid_starttime = creds->starttime / NSEC_PER_USEC;
325 m->uid_valid = m->gid_valid = true;
328 m->timestamp = nsec / NSEC_PER_USEC;
330 r = bus_message_parse_fields(m);
332 sd_bus_message_unref(m);
336 /* We take possession of the kmsg struct now */
338 m->free_kdbus = true;
347 int bus_kernel_read_message(sd_bus *bus, sd_bus_message **m) {
358 q = realloc(bus->rbuffer, sz);
362 k = bus->rbuffer = q;
365 /* Let's tell valgrind that there's really no need to
366 * initialize this fully. This should be removed again
367 * when valgrind learned the kdbus ioctls natively. */
368 #ifdef HAVE_VALGRIND_MEMCHECK_H
369 VALGRIND_MAKE_MEM_DEFINED(k, sz);
372 r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, bus->rbuffer);
379 if (errno != ENOBUFS)
385 r = bus_kernel_make_message(bus, k, m);
394 int bus_kernel_create(const char *name, char **s) {
395 struct kdbus_cmd_fname *fname;
403 fd = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
408 fname = alloca(offsetof(struct kdbus_cmd_fname, name) + DECIMAL_STR_MAX(uid_t) + 1 + l + 1);
409 sprintf(fname->name, "%lu-%s", (unsigned long) getuid(), name);
410 fname->size = offsetof(struct kdbus_cmd_fname, name) + strlen(fname->name) + 1;
411 fname->kernel_flags = KDBUS_CMD_FNAME_ACCESS_WORLD;
412 fname->user_flags = 0;
414 p = strjoin("/dev/kdbus/", fname->name, "/bus", NULL);
418 if (ioctl(fd, KDBUS_CMD_BUS_MAKE, fname) < 0) {
419 close_nointr_nofail(fd);