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 = {};
161 r = ioctl(b->input_fd, KDBUS_CMD_HELLO, &hello);
165 if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello.id) < 0)
170 r = bus_start_running(b);
177 int bus_kernel_connect(sd_bus *b) {
179 assert(b->input_fd < 0);
180 assert(b->output_fd < 0);
183 b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
187 b->output_fd = b->input_fd;
189 return bus_kernel_take_fd(b);
192 int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
197 assert(bus->state == BUS_RUNNING);
199 r = bus_message_setup_kmsg(m);
203 r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
205 return errno == EAGAIN ? 0 : -errno;
210 static void close_kdbus_msg(struct kdbus_msg *k) {
211 struct kdbus_msg_data *d;
213 KDBUS_MSG_FOREACH_DATA(d, k) {
215 if (d->type != KDBUS_MSG_UNIX_FDS)
218 close_many(d->fds, (d->size - offsetof(struct kdbus_msg_data, fds)) / sizeof(int));
222 static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_message **ret) {
223 sd_bus_message *m = NULL;
224 struct kdbus_msg_data *d;
225 unsigned n_payload = 0, n_fds = 0;
226 _cleanup_free_ int *fds = NULL;
227 struct bus_header *h = NULL;
228 size_t total, n_bytes = 0, idx = 0;
229 struct kdbus_creds *creds = NULL;
237 if (k->payload_type != KDBUS_PAYLOAD_DBUS1)
240 KDBUS_MSG_FOREACH_DATA(d, k) {
243 l = d->size - offsetof(struct kdbus_msg_data, data);
245 if (d->type == KDBUS_MSG_PAYLOAD) {
248 if (l < sizeof(struct bus_header))
251 h = (struct bus_header*) d->data;
257 } else if (d->type == KDBUS_MSG_UNIX_FDS) {
262 f = realloc(fds, sizeof(int) * (n_fds + j));
267 memcpy(fds + n_fds, d->fds, j);
270 } else if (d->type == KDBUS_MSG_SRC_CREDS)
272 else if (d->type == KDBUS_MSG_TIMESTAMP)
279 r = bus_header_size(h, &total);
283 if (n_bytes != total)
286 r = bus_message_from_header(h, sizeof(struct bus_header), fds, n_fds, NULL, NULL, 0, &m);
290 KDBUS_MSG_FOREACH_DATA(d, k) {
293 if (d->type != KDBUS_MSG_PAYLOAD)
296 l = d->size - offsetof(struct kdbus_msg_data, data);
297 if (idx == sizeof(struct bus_header) &&
298 l == BUS_MESSAGE_FIELDS_SIZE(m))
300 else if (idx == sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m)) &&
301 l == BUS_MESSAGE_BODY_SIZE(m))
303 else if (!(idx == 0 && l == sizeof(struct bus_header)) &&
304 !(idx == sizeof(struct bus_header) + BUS_MESSAGE_FIELDS_SIZE(m))) {
305 sd_bus_message_unref(m);
313 m->pid_starttime = creds->starttime / NSEC_PER_USEC;
318 m->uid_valid = m->gid_valid = true;
321 m->timestamp = nsec / NSEC_PER_USEC;
323 r = bus_message_parse_fields(m);
325 sd_bus_message_unref(m);
329 /* We take possession of the kmsg struct now */
331 m->free_kdbus = true;
340 int bus_kernel_read_message(sd_bus *bus, sd_bus_message **m) {
351 q = realloc(bus->rbuffer, sz);
355 k = bus->rbuffer = q;
358 /* Let's tell valgrind that there's really no need to
359 * initialize this fully. This should be removed again
360 * when valgrind learned the kdbus ioctls natively. */
361 VALGRIND_MAKE_MEM_DEFINED(k, sz);
363 r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, bus->rbuffer);
370 if (errno != ENOBUFS)
376 r = bus_kernel_make_message(bus, k, m);
385 int bus_kernel_create(const char *name, char **s) {
386 struct kdbus_cmd_fname *fname;
394 fd = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
399 fname = alloca(offsetof(struct kdbus_cmd_fname, name) + DECIMAL_STR_MAX(uid_t) + 1 + l + 1);
400 sprintf(fname->name, "%lu-%s", (unsigned long) getuid(), name);
401 fname->size = offsetof(struct kdbus_cmd_fname, name) + strlen(fname->name) + 1;
402 fname->kernel_flags = KDBUS_CMD_FNAME_ACCESS_WORLD;
403 fname->user_flags = 0;
405 p = strjoin("/dev/kdbus/", fname->name, "/bus", NULL);
409 if (ioctl(fd, KDBUS_CMD_BUS_MAKE, fname) < 0) {
410 close_nointr_nofail(fd);