]> git.proxmox.com Git - systemd.git/blob - src/libsystemd-bus/bus-kernel.c
Imported Upstream version 204
[systemd.git] / src / libsystemd-bus / bus-kernel.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2013 Lennart Poettering
7
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.
12
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.
17
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/>.
20 ***/
21
22 #ifdef HAVE_VALGRIND_MEMCHECK_H
23 #include <valgrind/memcheck.h>
24 #endif
25
26 #include <fcntl.h>
27 #include <malloc.h>
28
29 #include "util.h"
30
31 #include "bus-internal.h"
32 #include "bus-message.h"
33 #include "bus-kernel.h"
34 #include "bus-bloom.h"
35
36 #define KDBUS_ITEM_NEXT(item) \
37 (typeof(item))(((uint8_t *)item) + ALIGN8((item)->size))
38
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))
43
44 #define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data)
45 #define KDBUS_ITEM_SIZE(s) ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE)
46
47 static int parse_unique_name(const char *s, uint64_t *id) {
48 int r;
49
50 assert(s);
51 assert(id);
52
53 if (!startswith(s, ":1."))
54 return 0;
55
56 r = safe_atou64(s + 3, id);
57 if (r < 0)
58 return r;
59
60 return 1;
61 }
62
63 static void append_payload_vec(struct kdbus_item **d, const void *p, size_t sz) {
64 assert(d);
65 assert(p);
66 assert(sz > 0);
67
68 *d = ALIGN8_PTR(*d);
69
70 (*d)->size = offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec);
71 (*d)->type = KDBUS_MSG_PAYLOAD_VEC;
72 (*d)->vec.address = (intptr_t) p;
73 (*d)->vec.size = sz;
74
75 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
76 }
77
78 static void append_destination(struct kdbus_item **d, const char *s, size_t length) {
79 assert(d);
80 assert(s);
81
82 *d = ALIGN8_PTR(*d);
83
84 (*d)->size = offsetof(struct kdbus_item, str) + length + 1;
85 (*d)->type = KDBUS_MSG_DST_NAME;
86 memcpy((*d)->str, s, length + 1);
87
88 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
89 }
90
91 static void* append_bloom(struct kdbus_item **d, size_t length) {
92 void *r;
93
94 assert(d);
95
96 *d = ALIGN8_PTR(*d);
97
98 (*d)->size = offsetof(struct kdbus_item, data) + length;
99 (*d)->type = KDBUS_MSG_BLOOM;
100 r = (*d)->data;
101
102 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
103
104 return r;
105 }
106
107 static void append_fds(struct kdbus_item **d, const int fds[], unsigned n_fds) {
108 assert(d);
109 assert(fds);
110 assert(n_fds > 0);
111
112 *d = ALIGN8_PTR(*d);
113 (*d)->size = offsetof(struct kdbus_item, fds) + sizeof(int) * n_fds;
114 (*d)->type = KDBUS_MSG_UNIX_FDS;
115 memcpy((*d)->fds, fds, sizeof(int) * n_fds);
116
117 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
118 }
119
120 static int bus_message_setup_bloom(sd_bus_message *m, void *bloom) {
121 unsigned i;
122 int r;
123
124 assert(m);
125 assert(bloom);
126
127 memset(bloom, 0, BLOOM_SIZE);
128
129 bloom_add_pair(bloom, "message-type", bus_message_type_to_string(m->header->type));
130
131 if (m->interface)
132 bloom_add_pair(bloom, "interface", m->interface);
133 if (m->member)
134 bloom_add_pair(bloom, "member", m->member);
135 if (m->path) {
136 bloom_add_pair(bloom, "path", m->path);
137 bloom_add_prefixes(bloom, "path-slash-prefix", m->path, '/');
138 }
139
140 r = sd_bus_message_rewind(m, true);
141 if (r < 0)
142 return r;
143
144 for (i = 0; i < 64; i++) {
145 char type;
146 const char *t;
147 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
148 char *e;
149
150 r = sd_bus_message_peek_type(m, &type, NULL);
151 if (r < 0)
152 return r;
153
154 if (type != SD_BUS_TYPE_STRING &&
155 type != SD_BUS_TYPE_OBJECT_PATH &&
156 type != SD_BUS_TYPE_SIGNATURE)
157 break;
158
159 r = sd_bus_message_read_basic(m, type, &t);
160 if (r < 0)
161 return r;
162
163 e = stpcpy(buf, "arg");
164 if (i < 10)
165 *(e++) = '0' + i;
166 else {
167 *(e++) = '0' + (i / 10);
168 *(e++) = '0' + (i % 10);
169 }
170
171 *e = 0;
172 bloom_add_pair(bloom, buf, t);
173
174 strcpy(e, "-dot-prefix");
175 bloom_add_prefixes(bloom, buf, t, '.');
176 strcpy(e, "-slash-prefix");
177 bloom_add_prefixes(bloom, buf, t, '/');
178 }
179
180 return 0;
181 }
182
183 static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
184 struct kdbus_item *d;
185 bool well_known;
186 uint64_t unique;
187 size_t sz, dl;
188 int r;
189
190 assert(b);
191 assert(m);
192 assert(m->sealed);
193
194 if (m->kdbus)
195 return 0;
196
197 if (m->destination) {
198 r = parse_unique_name(m->destination, &unique);
199 if (r < 0)
200 return r;
201
202 well_known = r == 0;
203 } else
204 well_known = false;
205
206 sz = offsetof(struct kdbus_msg, items);
207
208 /* Add in fixed header, fields header and payload */
209 sz += 3 * ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec));
210
211 /* Add space for bloom filter */
212 sz += ALIGN8(offsetof(struct kdbus_item, data) + BLOOM_SIZE);
213
214 /* Add in well-known destination header */
215 if (well_known) {
216 dl = strlen(m->destination);
217 sz += ALIGN8(offsetof(struct kdbus_item, str) + dl + 1);
218 }
219
220 /* Add space for unix fds */
221 if (m->n_fds > 0)
222 sz += ALIGN8(offsetof(struct kdbus_item, fds) + sizeof(int)*m->n_fds);
223
224 m->kdbus = memalign(8, sz);
225 if (!m->kdbus)
226 return -ENOMEM;
227
228 memset(m->kdbus, 0, sz);
229
230 m->kdbus->flags =
231 ((m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_FLAGS_EXPECT_REPLY) |
232 ((m->header->flags & SD_BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_FLAGS_NO_AUTO_START : 0);
233 m->kdbus->dst_id =
234 well_known ? 0 :
235 m->destination ? unique : KDBUS_DST_ID_BROADCAST;
236 m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS1;
237 m->kdbus->cookie = m->header->serial;
238
239 m->kdbus->timeout_ns = m->timeout * NSEC_PER_USEC;
240
241 d = m->kdbus->items;
242
243 if (well_known)
244 append_destination(&d, m->destination, dl);
245
246 append_payload_vec(&d, m->header, sizeof(*m->header));
247
248 if (m->fields)
249 append_payload_vec(&d, m->fields, ALIGN8(m->header->fields_size));
250
251 if (m->body)
252 append_payload_vec(&d, m->body, m->header->body_size);
253
254 if (m->kdbus->dst_id == KDBUS_DST_ID_BROADCAST) {
255 void *p;
256
257 p = append_bloom(&d, BLOOM_SIZE);
258 r = bus_message_setup_bloom(m, p);
259 if (r < 0) {
260 free(m->kdbus);
261 m->kdbus = NULL;
262 return -r;
263 }
264 }
265
266 if (m->n_fds > 0)
267 append_fds(&d, m->fds, m->n_fds);
268
269 m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus;
270 assert(m->kdbus->size <= sz);
271
272 m->free_kdbus = true;
273
274 return 0;
275 }
276
277 int bus_kernel_take_fd(sd_bus *b) {
278 struct kdbus_cmd_hello hello = {
279 .conn_flags =
280 KDBUS_HELLO_ACCEPT_FD|
281 KDBUS_HELLO_ATTACH_COMM|
282 KDBUS_HELLO_ATTACH_EXE|
283 KDBUS_HELLO_ATTACH_CMDLINE|
284 KDBUS_HELLO_ATTACH_CGROUP|
285 KDBUS_HELLO_ATTACH_CAPS|
286 KDBUS_HELLO_ATTACH_SECLABEL|
287 KDBUS_HELLO_ATTACH_AUDIT
288 };
289 int r;
290
291 assert(b);
292
293 if (b->is_server)
294 return -EINVAL;
295
296 r = ioctl(b->input_fd, KDBUS_CMD_HELLO, &hello);
297 if (r < 0)
298 return -errno;
299
300 /* The higher 32bit of both flags fields are considered
301 * 'incompatible flags'. Refuse them all for now. */
302 if (hello.bus_flags > 0xFFFFFFFFULL ||
303 hello.conn_flags > 0xFFFFFFFFULL)
304 return -ENOTSUP;
305
306 if (hello.bloom_size != BLOOM_SIZE)
307 return -ENOTSUP;
308
309 if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello.id) < 0)
310 return -ENOMEM;
311
312 b->is_kernel = true;
313 b->bus_client = true;
314 b->can_fds = true;
315
316 r = bus_start_running(b);
317 if (r < 0)
318 return r;
319
320 return 1;
321 }
322
323 int bus_kernel_connect(sd_bus *b) {
324 assert(b);
325 assert(b->input_fd < 0);
326 assert(b->output_fd < 0);
327 assert(b->kernel);
328
329 if (b->is_server)
330 return -EINVAL;
331
332 b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
333 if (b->input_fd < 0)
334 return -errno;
335
336 b->output_fd = b->input_fd;
337
338 return bus_kernel_take_fd(b);
339 }
340
341 int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
342 int r;
343
344 assert(bus);
345 assert(m);
346 assert(bus->state == BUS_RUNNING);
347
348 r = bus_message_setup_kmsg(bus, m);
349 if (r < 0)
350 return r;
351
352 r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
353 if (r < 0)
354 return errno == EAGAIN ? 0 : -errno;
355
356 return 1;
357 }
358
359 static void close_kdbus_msg(struct kdbus_msg *k) {
360 struct kdbus_item *d;
361
362 KDBUS_ITEM_FOREACH(d, k) {
363
364 if (d->type != KDBUS_MSG_UNIX_FDS)
365 continue;
366
367 close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
368 }
369 }
370
371 static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_message **ret) {
372 sd_bus_message *m = NULL;
373 struct kdbus_item *d;
374 unsigned n_payload = 0, n_fds = 0;
375 _cleanup_free_ int *fds = NULL;
376 struct bus_header *h = NULL;
377 size_t total, n_bytes = 0, idx = 0;
378 const char *destination = NULL, *seclabel = NULL;
379 int r;
380
381 assert(bus);
382 assert(k);
383 assert(ret);
384
385 if (k->payload_type != KDBUS_PAYLOAD_DBUS1)
386 return 0;
387
388 KDBUS_ITEM_FOREACH(d, k) {
389 size_t l;
390
391 l = d->size - offsetof(struct kdbus_item, data);
392
393 if (d->type == KDBUS_MSG_PAYLOAD) {
394
395 if (!h) {
396 if (l < sizeof(struct bus_header))
397 return -EBADMSG;
398
399 h = (struct bus_header*) d->data;
400 }
401
402 n_payload++;
403 n_bytes += l;
404
405 } else if (d->type == KDBUS_MSG_UNIX_FDS) {
406 int *f;
407 unsigned j;
408
409 j = l / sizeof(int);
410 f = realloc(fds, sizeof(int) * (n_fds + j));
411 if (!f)
412 return -ENOMEM;
413
414 fds = f;
415 memcpy(fds + n_fds, d->fds, sizeof(int) * j);
416 n_fds += j;
417
418 } else if (d->type == KDBUS_MSG_DST_NAME)
419 destination = d->str;
420 else if (d->type == KDBUS_MSG_SRC_SECLABEL)
421 seclabel = d->str;
422 }
423
424 if (!h)
425 return -EBADMSG;
426
427 r = bus_header_size(h, &total);
428 if (r < 0)
429 return r;
430
431 if (n_bytes != total)
432 return -EBADMSG;
433
434 r = bus_message_from_header(h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m);
435 if (r < 0)
436 return r;
437
438 KDBUS_ITEM_FOREACH(d, k) {
439 size_t l;
440
441 l = d->size - offsetof(struct kdbus_item, data);
442
443 if (d->type == KDBUS_MSG_PAYLOAD) {
444
445 if (idx == sizeof(struct bus_header) &&
446 l == ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m)))
447 m->fields = d->data;
448 else if (idx == sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m)) &&
449 l == BUS_MESSAGE_BODY_SIZE(m))
450 m->body = d->data;
451 else if (!(idx == 0 && l == sizeof(struct bus_header))) {
452 sd_bus_message_unref(m);
453 return -EBADMSG;
454 }
455
456 idx += l;
457 } else if (d->type == KDBUS_MSG_SRC_CREDS) {
458 m->pid_starttime = d->creds.starttime / NSEC_PER_USEC;
459 m->uid = d->creds.uid;
460 m->gid = d->creds.gid;
461 m->pid = d->creds.pid;
462 m->tid = d->creds.tid;
463 m->uid_valid = m->gid_valid = true;
464 } else if (d->type == KDBUS_MSG_TIMESTAMP) {
465 m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC;
466 m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC;
467 } else if (d->type == KDBUS_MSG_SRC_PID_COMM)
468 m->comm = d->str;
469 else if (d->type == KDBUS_MSG_SRC_TID_COMM)
470 m->tid_comm = d->str;
471 else if (d->type == KDBUS_MSG_SRC_EXE)
472 m->exe = d->str;
473 else if (d->type == KDBUS_MSG_SRC_CMDLINE) {
474 m->cmdline = d->str;
475 m->cmdline_length = l;
476 } else if (d->type == KDBUS_MSG_SRC_CGROUP)
477 m->cgroup = d->str;
478 else if (d->type == KDBUS_MSG_SRC_AUDIT)
479 m->audit = &d->audit;
480 else if (d->type == KDBUS_MSG_SRC_CAPS) {
481 m->capability = d->data;
482 m->capability_size = l;
483 } else
484 log_debug("Got unknown field from kernel %llu", d->type);
485 }
486
487 r = bus_message_parse_fields(m);
488 if (r < 0) {
489 sd_bus_message_unref(m);
490 return r;
491 }
492
493 if (k->src_id == KDBUS_SRC_ID_KERNEL)
494 m->sender = "org.freedesktop.DBus";
495 else {
496 snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
497 m->sender = m->sender_buffer;
498 }
499
500 if (!m->destination) {
501 if (destination)
502 m->destination = destination;
503 else if (k->dst_id != KDBUS_DST_ID_WELL_KNOWN_NAME &&
504 k->dst_id != KDBUS_DST_ID_BROADCAST) {
505 snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
506 m->destination = m->destination_buffer;
507 }
508 }
509
510 /* We take possession of the kmsg struct now */
511 m->kdbus = k;
512 m->free_kdbus = true;
513 m->free_fds = true;
514
515 fds = NULL;
516
517 *ret = m;
518 return 1;
519 }
520
521 int bus_kernel_read_message(sd_bus *bus, sd_bus_message **m) {
522 struct kdbus_msg *k;
523 size_t sz = 1024;
524 int r;
525
526 assert(bus);
527 assert(m);
528
529 for (;;) {
530 void *q;
531
532 q = memalign(8, sz);
533 if (!q)
534 return -errno;
535
536 free(bus->rbuffer);
537 k = bus->rbuffer = q;
538 k->size = sz;
539
540 /* Let's tell valgrind that there's really no need to
541 * initialize this fully. This should be removed again
542 * when valgrind learned the kdbus ioctls natively. */
543 #ifdef HAVE_VALGRIND_MEMCHECK_H
544 VALGRIND_MAKE_MEM_DEFINED(k, sz);
545 #endif
546
547 r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, bus->rbuffer);
548 if (r >= 0)
549 break;
550
551 if (errno == EAGAIN)
552 return 0;
553
554 if (errno != ENOBUFS)
555 return -errno;
556
557 sz *= 2;
558 }
559
560 r = bus_kernel_make_message(bus, k, m);
561 if (r > 0)
562 bus->rbuffer = NULL;
563 else
564 close_kdbus_msg(k);
565
566 return r < 0 ? r : 1;
567 }
568
569 int bus_kernel_create(const char *name, char **s) {
570 struct kdbus_cmd_bus_make *make;
571 struct kdbus_item *n, *cg;
572 size_t l;
573 int fd;
574 char *p;
575
576 assert(name);
577 assert(s);
578
579 fd = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
580 if (fd < 0)
581 return -errno;
582
583 l = strlen(name);
584 make = alloca0(offsetof(struct kdbus_cmd_bus_make, items) +
585 KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t) +
586 KDBUS_ITEM_HEADER_SIZE + DECIMAL_STR_MAX(uid_t) + 1 + l + 1);
587
588 cg = make->items;
589 cg->type = KDBUS_MAKE_CGROUP;
590 cg->data64[0] = 1;
591 cg->size = KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t);
592
593 n = KDBUS_ITEM_NEXT(cg);
594 n->type = KDBUS_MAKE_NAME;
595 sprintf(n->str, "%lu-%s", (unsigned long) getuid(), name);
596 n->size = KDBUS_ITEM_HEADER_SIZE + strlen(n->str) + 1;
597
598 make->size = offsetof(struct kdbus_cmd_bus_make, items) + cg->size + n->size;
599 make->flags = KDBUS_MAKE_ACCESS_WORLD | KDBUS_MAKE_POLICY_OPEN;
600 make->bus_flags = 0;
601 make->bloom_size = BLOOM_SIZE;
602 assert_cc(BLOOM_SIZE % 8 == 0);
603
604 p = strjoin("/dev/kdbus/", n->str, "/bus", NULL);
605 if (!p)
606 return -ENOMEM;
607
608 if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
609 close_nointr_nofail(fd);
610 free(p);
611 return -errno;
612 }
613
614 if (s)
615 *s = p;
616
617 return fd;
618 }