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) {
62 (*d)->size = offsetof(struct kdbus_msg_data, vec) + sizeof(struct kdbus_vec);
63 (*d)->type = KDBUS_MSG_PAYLOAD_VEC;
64 (*d)->vec.address = (uint64_t) p;
67 *d = (struct kdbus_msg_data*) ((uint8_t*) *d + (*d)->size);
70 static void append_destination(struct kdbus_msg_data **d, const char *s, size_t length) {
76 (*d)->size = offsetof(struct kdbus_msg_data, str) + length + 1;
77 (*d)->type = KDBUS_MSG_DST_NAME;
78 memcpy((*d)->str, s, length + 1);
80 *d = (struct kdbus_msg_data*) ((uint8_t*) *d + (*d)->size);
83 static void append_bloom(struct kdbus_msg_data **d, const void *p, size_t length) {
89 (*d)->size = offsetof(struct kdbus_msg_data, data) + length;
90 (*d)->type = KDBUS_MSG_BLOOM;
91 memcpy((*d)->data, p, length);
93 *d = (struct kdbus_msg_data*) ((uint8_t*) *d + (*d)->size);
96 static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
97 struct kdbus_msg_data *d;
110 if (m->destination) {
111 r = parse_unique_name(m->destination, &unique);
119 sz = offsetof(struct kdbus_msg, data);
121 /* Add in fixed header, fields header and payload */
122 sz += 3 * ALIGN8(offsetof(struct kdbus_msg_data, vec) + sizeof(struct kdbus_vec));
124 /* Add space for bloom filter */
125 sz += ALIGN8(offsetof(struct kdbus_msg_data, data) + b->bloom_size);
127 /* Add in well-known destination header */
129 dl = strlen(m->destination);
130 sz += ALIGN8(offsetof(struct kdbus_msg_data, str) + dl + 1);
133 m->kdbus = aligned_alloc(8, sz);
137 memset(m->kdbus, 0, sz);
140 ((m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_FLAGS_EXPECT_REPLY) |
141 ((m->header->flags & SD_BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_FLAGS_NO_AUTO_START : 0);
144 m->destination ? unique : KDBUS_DST_ID_BROADCAST;
145 m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS1;
146 m->kdbus->cookie = m->header->serial;
148 m->kdbus->timeout_ns = m->timeout * NSEC_PER_USEC;
153 append_destination(&d, m->destination, dl);
155 append_payload_vec(&d, m->header, sizeof(*m->header));
158 append_payload_vec(&d, m->fields, ALIGN8(m->header->fields_size));
161 append_payload_vec(&d, m->body, m->header->body_size);
163 if (m->kdbus->dst_id == KDBUS_DST_ID_BROADCAST) {
166 /* For now, let's add a mask all bloom filter */
167 p = alloca(b->bloom_size);
168 memset(p, 0xFF, b->bloom_size);
169 append_bloom(&d, p, b->bloom_size);
172 m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus;
173 assert(m->kdbus->size <= sz);
175 m->free_kdbus = true;
180 int bus_kernel_take_fd(sd_bus *b) {
181 struct kdbus_cmd_hello hello = {
183 KDBUS_CMD_HELLO_ACCEPT_FD|
184 KDBUS_CMD_HELLO_ACCEPT_MMAP|
185 KDBUS_CMD_HELLO_ATTACH_COMM|
186 KDBUS_CMD_HELLO_ATTACH_EXE|
187 KDBUS_CMD_HELLO_ATTACH_CMDLINE|
188 KDBUS_CMD_HELLO_ATTACH_CGROUP|
189 KDBUS_CMD_HELLO_ATTACH_CAPS|
190 KDBUS_CMD_HELLO_ATTACH_SECLABEL|
191 KDBUS_CMD_HELLO_ATTACH_AUDIT
200 r = ioctl(b->input_fd, KDBUS_CMD_HELLO, &hello);
204 /* The higher 32bit of both flags fields are considered
205 * 'incompatible flags'. Refuse them all for now. */
206 if (hello.bus_flags > 0xFFFFFFFFULL ||
207 hello.conn_flags > 0xFFFFFFFFULL)
210 if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello.id) < 0)
213 b->bloom_size = hello.bloom_size;
215 b->bus_client = true;
217 r = bus_start_running(b);
224 int bus_kernel_connect(sd_bus *b) {
226 assert(b->input_fd < 0);
227 assert(b->output_fd < 0);
233 b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
237 b->output_fd = b->input_fd;
239 return bus_kernel_take_fd(b);
242 int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
247 assert(bus->state == BUS_RUNNING);
249 r = bus_message_setup_kmsg(bus, m);
253 r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
255 return errno == EAGAIN ? 0 : -errno;
260 static void close_kdbus_msg(struct kdbus_msg *k) {
261 struct kdbus_msg_data *d;
263 KDBUS_MSG_FOREACH_DATA(d, k) {
265 if (d->type != KDBUS_MSG_UNIX_FDS)
268 close_many(d->fds, (d->size - offsetof(struct kdbus_msg_data, fds)) / sizeof(int));
272 static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_message **ret) {
273 sd_bus_message *m = NULL;
274 struct kdbus_msg_data *d;
275 unsigned n_payload = 0, n_fds = 0;
276 _cleanup_free_ int *fds = NULL;
277 struct bus_header *h = NULL;
278 size_t total, n_bytes = 0, idx = 0;
279 const char *destination = NULL, *seclabel = NULL;
286 if (k->payload_type != KDBUS_PAYLOAD_DBUS1)
289 KDBUS_MSG_FOREACH_DATA(d, k) {
292 l = d->size - offsetof(struct kdbus_msg_data, data);
294 if (d->type == KDBUS_MSG_PAYLOAD) {
297 if (l < sizeof(struct bus_header))
300 h = (struct bus_header*) d->data;
306 } else if (d->type == KDBUS_MSG_UNIX_FDS) {
311 f = realloc(fds, sizeof(int) * (n_fds + j));
316 memcpy(fds + n_fds, d->fds, j);
319 } else if (d->type == KDBUS_MSG_DST_NAME)
320 destination = d->str;
321 else if (d->type == KDBUS_MSG_SRC_SECLABEL)
328 r = bus_header_size(h, &total);
332 if (n_bytes != total)
335 r = bus_message_from_header(h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m);
339 KDBUS_MSG_FOREACH_DATA(d, k) {
342 l = d->size - offsetof(struct kdbus_msg_data, data);
344 if (d->type == KDBUS_MSG_PAYLOAD) {
346 if (idx == sizeof(struct bus_header) &&
347 l == ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m)))
349 else if (idx == sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m)) &&
350 l == BUS_MESSAGE_BODY_SIZE(m))
352 else if (!(idx == 0 && l == sizeof(struct bus_header))) {
353 sd_bus_message_unref(m);
358 } else if (d->type == KDBUS_MSG_SRC_CREDS) {
359 m->pid_starttime = d->creds.starttime / NSEC_PER_USEC;
360 m->uid = d->creds.uid;
361 m->gid = d->creds.gid;
362 m->pid = d->creds.pid;
363 m->tid = d->creds.tid;
364 m->uid_valid = m->gid_valid = true;
365 } else if (d->type == KDBUS_MSG_TIMESTAMP) {
366 m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC;
367 m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC;
368 } else if (d->type == KDBUS_MSG_SRC_PID_COMM)
370 else if (d->type == KDBUS_MSG_SRC_TID_COMM)
371 m->tid_comm = d->str;
372 else if (d->type == KDBUS_MSG_SRC_EXE)
376 r = bus_message_parse_fields(m);
378 sd_bus_message_unref(m);
382 if (k->src_id == KDBUS_SRC_ID_KERNEL)
383 m->sender = "org.freedesktop.DBus";
385 snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
386 m->sender = m->sender_buffer;
389 if (!m->destination) {
391 m->destination = destination;
392 else if (k->dst_id != KDBUS_DST_ID_WELL_KNOWN_NAME &&
393 k->dst_id != KDBUS_DST_ID_BROADCAST) {
394 snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
395 m->destination = m->destination_buffer;
399 /* We take possession of the kmsg struct now */
401 m->free_kdbus = true;
410 int bus_kernel_read_message(sd_bus *bus, sd_bus_message **m) {
421 q = aligned_alloc(8, sz);
426 k = bus->rbuffer = q;
429 /* Let's tell valgrind that there's really no need to
430 * initialize this fully. This should be removed again
431 * when valgrind learned the kdbus ioctls natively. */
432 #ifdef HAVE_VALGRIND_MEMCHECK_H
433 VALGRIND_MAKE_MEM_DEFINED(k, sz);
436 r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, bus->rbuffer);
443 if (errno != ENOBUFS)
449 r = bus_kernel_make_message(bus, k, m);
455 return r < 0 ? r : 1;
458 int bus_kernel_create(const char *name, char **s) {
459 struct kdbus_cmd_bus_make *make;
467 fd = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
472 make = alloca(offsetof(struct kdbus_cmd_bus_make, name) + DECIMAL_STR_MAX(uid_t) + 1 + l + 1);
473 sprintf(make->name, "%lu-%s", (unsigned long) getuid(), name);
474 make->size = offsetof(struct kdbus_cmd_bus_make, name) + strlen(make->name) + 1;
475 make->flags = KDBUS_ACCESS_WORLD | KDBUS_POLICY_OPEN;
477 make->bloom_size = 16;
479 p = strjoin("/dev/kdbus/", make->name, "/bus", NULL);
483 if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
484 close_nointr_nofail(fd);