]> git.proxmox.com Git - systemd.git/blame - src/libsystemd/sd-bus/bus-kernel.c
Imported Upstream version 218
[systemd.git] / src / libsystemd / sd-bus / bus-kernel.c
CommitLineData
60f067b4
JS
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>
5eef597e 28#include <libgen.h>
60f067b4
JS
29#include <sys/mman.h>
30#include <sys/prctl.h>
31
32#include "util.h"
33#include "strv.h"
f47781d8
MP
34#include "memfd-util.h"
35#include "cgroup-util.h"
36#include "fileio.h"
60f067b4
JS
37
38#include "bus-internal.h"
39#include "bus-message.h"
40#include "bus-kernel.h"
41#include "bus-bloom.h"
42#include "bus-util.h"
43#include "bus-label.h"
60f067b4
JS
44
45#define UNIQUE_NAME_MAX (3+DECIMAL_STR_MAX(uint64_t))
46
47int bus_kernel_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
63static void append_payload_vec(struct kdbus_item **d, const void *p, size_t sz) {
64 assert(d);
65 assert(sz > 0);
66
67 *d = ALIGN8_PTR(*d);
68
69 /* Note that p can be NULL, which encodes a region full of
70 * zeroes, which is useful to optimize certain padding
71 * conditions */
72
73 (*d)->size = offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec);
74 (*d)->type = KDBUS_ITEM_PAYLOAD_VEC;
75 (*d)->vec.address = PTR_TO_UINT64(p);
76 (*d)->vec.size = sz;
77
78 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
79}
80
f47781d8 81static void append_payload_memfd(struct kdbus_item **d, int memfd, size_t start, size_t sz) {
60f067b4
JS
82 assert(d);
83 assert(memfd >= 0);
84 assert(sz > 0);
85
86 *d = ALIGN8_PTR(*d);
87 (*d)->size = offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd);
88 (*d)->type = KDBUS_ITEM_PAYLOAD_MEMFD;
89 (*d)->memfd.fd = memfd;
f47781d8 90 (*d)->memfd.start = start;
60f067b4
JS
91 (*d)->memfd.size = sz;
92
93 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
94}
95
96static void append_destination(struct kdbus_item **d, const char *s, size_t length) {
97 assert(d);
98 assert(s);
99
100 *d = ALIGN8_PTR(*d);
101
102 (*d)->size = offsetof(struct kdbus_item, str) + length + 1;
103 (*d)->type = KDBUS_ITEM_DST_NAME;
104 memcpy((*d)->str, s, length + 1);
105
106 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
107}
108
109static struct kdbus_bloom_filter *append_bloom(struct kdbus_item **d, size_t length) {
110 struct kdbus_item *i;
111
112 assert(d);
113
114 i = ALIGN8_PTR(*d);
115
116 i->size = offsetof(struct kdbus_item, bloom_filter) +
117 offsetof(struct kdbus_bloom_filter, data) +
118 length;
119 i->type = KDBUS_ITEM_BLOOM_FILTER;
120
121 *d = (struct kdbus_item *) ((uint8_t*) i + i->size);
122
123 return &i->bloom_filter;
124}
125
126static void append_fds(struct kdbus_item **d, const int fds[], unsigned n_fds) {
127 assert(d);
128 assert(fds);
129 assert(n_fds > 0);
130
131 *d = ALIGN8_PTR(*d);
132 (*d)->size = offsetof(struct kdbus_item, fds) + sizeof(int) * n_fds;
133 (*d)->type = KDBUS_ITEM_FDS;
134 memcpy((*d)->fds, fds, sizeof(int) * n_fds);
135
136 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
137}
138
f47781d8
MP
139static void add_bloom_arg(void *data, size_t size, unsigned n_hash, unsigned i, const char *t) {
140 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
141 char *e;
142
143 assert(data);
144 assert(size > 0);
145 assert(i < 64);
146 assert(t);
147
148 e = stpcpy(buf, "arg");
149 if (i < 10)
150 *(e++) = '0' + (char) i;
151 else {
152 *(e++) = '0' + (char) (i / 10);
153 *(e++) = '0' + (char) (i % 10);
154 }
155
156 *e = 0;
157 bloom_add_pair(data, size, n_hash, buf, t);
158
159 strcpy(e, "-dot-prefix");
160 bloom_add_prefixes(data, size, n_hash, buf, t, '.');
161 strcpy(e, "-slash-prefix");
162 bloom_add_prefixes(data, size, n_hash, buf, t, '/');
163}
164
60f067b4
JS
165static int bus_message_setup_bloom(sd_bus_message *m, struct kdbus_bloom_filter *bloom) {
166 void *data;
167 unsigned i;
168 int r;
169
170 assert(m);
171 assert(bloom);
172
173 data = bloom->data;
174 memzero(data, m->bus->bloom_size);
175 bloom->generation = 0;
176
177 bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "message-type", bus_message_type_to_string(m->header->type));
178
179 if (m->interface)
180 bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "interface", m->interface);
181 if (m->member)
182 bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "member", m->member);
183 if (m->path) {
184 bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path", m->path);
185 bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path-slash-prefix", m->path);
186 bloom_add_prefixes(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path-slash-prefix", m->path, '/');
187 }
188
189 r = sd_bus_message_rewind(m, true);
190 if (r < 0)
191 return r;
192
193 for (i = 0; i < 64; i++) {
f47781d8 194 const char *t, *contents;
60f067b4 195 char type;
60f067b4 196
f47781d8 197 r = sd_bus_message_peek_type(m, &type, &contents);
60f067b4
JS
198 if (r < 0)
199 return r;
200
f47781d8 201 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
60f067b4 202
f47781d8
MP
203 /* The bloom filter includes simple strings of any kind */
204 r = sd_bus_message_read_basic(m, type, &t);
205 if (r < 0)
206 return r;
60f067b4 207
f47781d8
MP
208 add_bloom_arg(data, m->bus->bloom_size, m->bus->bloom_n_hash, i, t);
209 } if (type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")) {
60f067b4 210
f47781d8
MP
211 /* As well as array of simple strings of any kinds */
212 r = sd_bus_message_enter_container(m, type, contents);
213 if (r < 0)
214 return r;
215
216 while ((r = sd_bus_message_read_basic(m, contents[0], &t)) > 0)
217 add_bloom_arg(data, m->bus->bloom_size, m->bus->bloom_n_hash, i, t);
218 if (r < 0)
219 return r;
220
221 r = sd_bus_message_exit_container(m);
222 if (r < 0)
223 return r;
60f067b4 224
f47781d8
MP
225 } else
226 /* Stop adding to bloom filter as soon as we
227 * run into the first argument we cannot add
228 * to it. */
229 break;
60f067b4
JS
230 }
231
232 return 0;
233}
234
235static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
236 struct bus_body_part *part;
237 struct kdbus_item *d;
f47781d8 238 const char *destination;
60f067b4
JS
239 bool well_known;
240 uint64_t unique;
241 size_t sz, dl;
242 unsigned i;
243 int r;
244
245 assert(b);
246 assert(m);
247 assert(m->sealed);
248
249 /* We put this together only once, if this message is reused
250 * we reuse the earlier-built version */
251 if (m->kdbus)
252 return 0;
253
f47781d8
MP
254 destination = m->destination ?: m->destination_ptr;
255
256 if (destination) {
257 r = bus_kernel_parse_unique_name(destination, &unique);
60f067b4
JS
258 if (r < 0)
259 return r;
260
261 well_known = r == 0;
262 } else
263 well_known = false;
264
265 sz = offsetof(struct kdbus_msg, items);
266
60f067b4 267 /* Add in fixed header, fields header and payload */
f47781d8
MP
268 sz += (1 + m->n_body_parts) * ALIGN8(offsetof(struct kdbus_item, vec) +
269 MAX(sizeof(struct kdbus_vec),
270 sizeof(struct kdbus_memfd)));
60f067b4
JS
271
272 /* Add space for bloom filter */
273 sz += ALIGN8(offsetof(struct kdbus_item, bloom_filter) +
274 offsetof(struct kdbus_bloom_filter, data) +
275 m->bus->bloom_size);
276
277 /* Add in well-known destination header */
278 if (well_known) {
f47781d8 279 dl = strlen(destination);
60f067b4
JS
280 sz += ALIGN8(offsetof(struct kdbus_item, str) + dl + 1);
281 }
282
283 /* Add space for unix fds */
284 if (m->n_fds > 0)
285 sz += ALIGN8(offsetof(struct kdbus_item, fds) + sizeof(int)*m->n_fds);
286
287 m->kdbus = memalign(8, sz);
288 if (!m->kdbus) {
289 r = -ENOMEM;
290 goto fail;
291 }
292
293 m->free_kdbus = true;
294 memzero(m->kdbus, sz);
295
296 m->kdbus->flags =
297 ((m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_FLAGS_EXPECT_REPLY) |
298 ((m->header->flags & BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_FLAGS_NO_AUTO_START : 0);
f47781d8
MP
299
300 if (well_known)
301 /* verify_destination_id will usually be 0, which makes the kernel driver only look
302 * at the provided well-known name. Otherwise, the kernel will make sure the provided
303 * destination id matches the owner of the provided weel-known-name, and fail if they
304 * differ. Currently, this is only needed for bus-proxyd. */
305 m->kdbus->dst_id = m->verify_destination_id;
306 else
307 m->kdbus->dst_id = destination ? unique : KDBUS_DST_ID_BROADCAST;
308
60f067b4
JS
309 m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS;
310 m->kdbus->cookie = (uint64_t) m->header->serial;
311 m->kdbus->priority = m->priority;
312
f47781d8 313 if (m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
60f067b4 314 m->kdbus->cookie_reply = m->reply_cookie;
f47781d8 315 else {
5eef597e
MP
316 struct timespec now;
317
318 assert_se(clock_gettime(CLOCK_MONOTONIC_COARSE, &now) == 0);
319 m->kdbus->timeout_ns = now.tv_sec * NSEC_PER_SEC + now.tv_nsec +
320 m->timeout * NSEC_PER_USEC;
321 }
60f067b4
JS
322
323 d = m->kdbus->items;
324
325 if (well_known)
f47781d8 326 append_destination(&d, destination, dl);
60f067b4
JS
327
328 append_payload_vec(&d, m->header, BUS_MESSAGE_BODY_BEGIN(m));
329
330 MESSAGE_FOREACH_PART(part, i, m) {
331 if (part->is_zero) {
332 /* If this is padding then simply send a
333 * vector with a NULL data pointer which the
334 * kernel will just pass through. This is the
335 * most efficient way to encode zeroes */
336
337 append_payload_vec(&d, NULL, part->size);
338 continue;
339 }
340
f47781d8 341 if (part->memfd >= 0 && part->sealed && destination) {
60f067b4
JS
342 /* Try to send a memfd, if the part is
343 * sealed and this is not a broadcast. Since we can only */
344
f47781d8 345 append_payload_memfd(&d, part->memfd, part->memfd_offset, part->size);
60f067b4
JS
346 continue;
347 }
348
349 /* Otherwise, let's send a vector to the actual data.
350 * For that, we need to map it first. */
351 r = bus_body_part_map(part);
352 if (r < 0)
353 goto fail;
354
355 append_payload_vec(&d, part->data, part->size);
356 }
357
358 if (m->kdbus->dst_id == KDBUS_DST_ID_BROADCAST) {
359 struct kdbus_bloom_filter *bloom;
360
361 bloom = append_bloom(&d, m->bus->bloom_size);
362 r = bus_message_setup_bloom(m, bloom);
363 if (r < 0)
364 goto fail;
365 }
366
367 if (m->n_fds > 0)
368 append_fds(&d, m->fds, m->n_fds);
369
370 m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus;
371 assert(m->kdbus->size <= sz);
372
373 return 0;
374
375fail:
376 m->poisoned = true;
377 return r;
378}
379
f47781d8
MP
380static void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
381 assert(bus);
382 assert(m);
383
384 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
385 m->creds.well_known_names_driver = true;
386 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
387}
388
5eef597e
MP
389static void unset_memfds(struct sd_bus_message *m) {
390 struct bus_body_part *part;
391 unsigned i;
392
393 assert(m);
394
395 /* Make sure the memfds are not freed twice */
396 MESSAGE_FOREACH_PART(part, i, m)
397 if (part->memfd >= 0)
398 part->memfd = -1;
399}
400
60f067b4
JS
401static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
402 sd_bus_message *m = NULL;
403 struct kdbus_item *d;
404 unsigned n_fds = 0;
405 _cleanup_free_ int *fds = NULL;
406 struct bus_header *h = NULL;
407 size_t total, n_bytes = 0, idx = 0;
408 const char *destination = NULL, *seclabel = NULL;
409 int r;
410
411 assert(bus);
412 assert(k);
413 assert(k->payload_type == KDBUS_PAYLOAD_DBUS);
414
415 KDBUS_ITEM_FOREACH(d, k, items) {
416 size_t l;
417
418 l = d->size - offsetof(struct kdbus_item, data);
419
420 switch (d->type) {
421
422 case KDBUS_ITEM_PAYLOAD_OFF:
423 if (!h) {
f47781d8 424 h = (struct bus_header *)((uint8_t *)bus->kdbus_buffer + d->vec.offset);
60f067b4
JS
425
426 if (!bus_header_is_complete(h, d->vec.size))
427 return -EBADMSG;
428 }
429
430 n_bytes += d->vec.size;
431 break;
432
433 case KDBUS_ITEM_PAYLOAD_MEMFD:
434 if (!h)
435 return -EBADMSG;
436
437 n_bytes += d->memfd.size;
438 break;
439
440 case KDBUS_ITEM_FDS: {
441 int *f;
442 unsigned j;
443
444 j = l / sizeof(int);
445 f = realloc(fds, sizeof(int) * (n_fds + j));
446 if (!f)
447 return -ENOMEM;
448
449 fds = f;
450 memcpy(fds + n_fds, d->fds, sizeof(int) * j);
451 n_fds += j;
452 break;
453 }
454
455 case KDBUS_ITEM_SECLABEL:
456 seclabel = d->str;
457 break;
458 }
459 }
460
461 if (!h)
462 return -EBADMSG;
463
464 r = bus_header_message_size(h, &total);
465 if (r < 0)
466 return r;
467
468 if (n_bytes != total)
469 return -EBADMSG;
470
471 /* on kdbus we only speak native endian gvariant, never dbus1
472 * marshalling or reverse endian */
473 if (h->version != 2 ||
474 h->endian != BUS_NATIVE_ENDIAN)
475 return -EPROTOTYPE;
476
477 r = bus_message_from_header(bus, h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m);
478 if (r < 0)
479 return r;
480
481 /* The well-known names list is different from the other
482 credentials. If we asked for it, but nothing is there, this
483 means that the list of well-known names is simply empty, not
484 that we lack any data */
485
486 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
487
488 KDBUS_ITEM_FOREACH(d, k, items) {
489 size_t l;
490
491 l = d->size - offsetof(struct kdbus_item, data);
492
493 switch (d->type) {
494
495 case KDBUS_ITEM_PAYLOAD_OFF: {
496 size_t begin_body;
497
498 begin_body = BUS_MESSAGE_BODY_BEGIN(m);
499
500 if (idx + d->vec.size > begin_body) {
501 struct bus_body_part *part;
502
503 /* Contains body material */
504
505 part = message_append_part(m);
506 if (!part) {
507 r = -ENOMEM;
508 goto fail;
509 }
510
511 /* A -1 offset is NUL padding. */
512 part->is_zero = d->vec.offset == ~0ULL;
513
514 if (idx >= begin_body) {
515 if (!part->is_zero)
f47781d8 516 part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset;
60f067b4
JS
517 part->size = d->vec.size;
518 } else {
519 if (!part->is_zero)
f47781d8 520 part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset + (begin_body - idx);
60f067b4
JS
521 part->size = d->vec.size - (begin_body - idx);
522 }
523
524 part->sealed = true;
525 }
526
527 idx += d->vec.size;
528 break;
529 }
530
531 case KDBUS_ITEM_PAYLOAD_MEMFD: {
532 struct bus_body_part *part;
533
534 if (idx < BUS_MESSAGE_BODY_BEGIN(m)) {
535 r = -EBADMSG;
536 goto fail;
537 }
538
539 part = message_append_part(m);
540 if (!part) {
541 r = -ENOMEM;
542 goto fail;
543 }
544
545 part->memfd = d->memfd.fd;
f47781d8 546 part->memfd_offset = d->memfd.start;
60f067b4
JS
547 part->size = d->memfd.size;
548 part->sealed = true;
549
550 idx += d->memfd.size;
551 break;
552 }
553
f47781d8
MP
554 case KDBUS_ITEM_PIDS:
555
556 /* The PID/TID might be missing, when the data
557 * is faked by some data bus proxy and it
558 * lacks that information about the real
559 * client since SO_PEERCRED is used for
560 * that. */
561
562 if (d->pids.pid > 0) {
563 m->creds.pid = (pid_t) d->pids.pid;
564 m->creds.mask |= SD_BUS_CREDS_PID & bus->creds_mask;
60f067b4
JS
565 }
566
f47781d8
MP
567 if (d->pids.tid > 0) {
568 m->creds.tid = (pid_t) d->pids.tid;
60f067b4
JS
569 m->creds.mask |= SD_BUS_CREDS_TID & bus->creds_mask;
570 }
f47781d8
MP
571
572 break;
573
574 case KDBUS_ITEM_CREDS:
575
576 /* EUID/SUID/FSUID/EGID/SGID/FSGID might be missing too (see above). */
577
578 if ((uid_t) d->creds.uid != UID_INVALID) {
579 m->creds.uid = (uid_t) d->creds.uid;
580 m->creds.mask |= SD_BUS_CREDS_UID & bus->creds_mask;
581 }
582
583 if ((uid_t) d->creds.euid != UID_INVALID) {
584 m->creds.euid = (uid_t) d->creds.euid;
585 m->creds.mask |= SD_BUS_CREDS_EUID & bus->creds_mask;
586 }
587
588 if ((uid_t) d->creds.suid != UID_INVALID) {
589 m->creds.suid = (uid_t) d->creds.suid;
590 m->creds.mask |= SD_BUS_CREDS_SUID & bus->creds_mask;
591 }
592
593 if ((uid_t) d->creds.fsuid != UID_INVALID) {
594 m->creds.fsuid = (uid_t) d->creds.fsuid;
595 m->creds.mask |= SD_BUS_CREDS_FSUID & bus->creds_mask;
596 }
597
598 if ((gid_t) d->creds.gid != GID_INVALID) {
599 m->creds.gid = (gid_t) d->creds.gid;
600 m->creds.mask |= SD_BUS_CREDS_GID & bus->creds_mask;
601 }
602
603 if ((gid_t) d->creds.egid != GID_INVALID) {
604 m->creds.egid = (gid_t) d->creds.egid;
605 m->creds.mask |= SD_BUS_CREDS_EGID & bus->creds_mask;
606 }
607
608 if ((gid_t) d->creds.sgid != GID_INVALID) {
609 m->creds.sgid = (gid_t) d->creds.sgid;
610 m->creds.mask |= SD_BUS_CREDS_SGID & bus->creds_mask;
611 }
612
613 if ((gid_t) d->creds.fsgid != GID_INVALID) {
614 m->creds.fsgid = (gid_t) d->creds.fsgid;
615 m->creds.mask |= SD_BUS_CREDS_FSGID & bus->creds_mask;
616 }
617
60f067b4
JS
618 break;
619
620 case KDBUS_ITEM_TIMESTAMP:
621
622 if (bus->attach_flags & KDBUS_ATTACH_TIMESTAMP) {
623 m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC;
624 m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC;
625 m->seqnum = d->timestamp.seqnum;
626 }
627
628 break;
629
630 case KDBUS_ITEM_PID_COMM:
631 m->creds.comm = d->str;
632 m->creds.mask |= SD_BUS_CREDS_COMM & bus->creds_mask;
633 break;
634
635 case KDBUS_ITEM_TID_COMM:
636 m->creds.tid_comm = d->str;
637 m->creds.mask |= SD_BUS_CREDS_TID_COMM & bus->creds_mask;
638 break;
639
640 case KDBUS_ITEM_EXE:
641 m->creds.exe = d->str;
642 m->creds.mask |= SD_BUS_CREDS_EXE & bus->creds_mask;
643 break;
644
645 case KDBUS_ITEM_CMDLINE:
646 m->creds.cmdline = d->str;
647 m->creds.cmdline_size = l;
648 m->creds.mask |= SD_BUS_CREDS_CMDLINE & bus->creds_mask;
649 break;
650
651 case KDBUS_ITEM_CGROUP:
652 m->creds.cgroup = d->str;
653 m->creds.mask |= (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID) & bus->creds_mask;
654
5eef597e
MP
655 r = bus_get_root_path(bus);
656 if (r < 0)
657 goto fail;
60f067b4
JS
658
659 m->creds.cgroup_root = bus->cgroup_root;
660
661 break;
662
663 case KDBUS_ITEM_AUDIT:
f47781d8
MP
664 if ((uint32_t) d->audit.sessionid != (uint32_t) -1) {
665 m->creds.audit_session_id = (uint32_t) d->audit.sessionid;
666 m->creds.mask |= SD_BUS_CREDS_AUDIT_SESSION_ID & bus->creds_mask;
667 }
668
669 if ((uid_t) d->audit.loginuid != UID_INVALID) {
670 m->creds.audit_login_uid = (uid_t) d->audit.loginuid;
671 m->creds.mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID & bus->creds_mask;
672 }
60f067b4
JS
673 break;
674
675 case KDBUS_ITEM_CAPS:
5eef597e
MP
676 m->creds.capability = (uint8_t *) d->caps.caps;
677 m->creds.capability_size = d->size - offsetof(struct kdbus_item, caps.caps);
60f067b4
JS
678 m->creds.mask |= (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS) & bus->creds_mask;
679 break;
680
681 case KDBUS_ITEM_DST_NAME:
f47781d8
MP
682 if (!service_name_is_valid(d->str)) {
683 r = -EBADMSG;
684 goto fail;
685 }
60f067b4
JS
686
687 destination = d->str;
688 break;
689
f47781d8
MP
690 case KDBUS_ITEM_OWNED_NAME:
691 if (!service_name_is_valid(d->name.name)) {
692 r = -EBADMSG;
60f067b4 693 goto fail;
f47781d8
MP
694 }
695
696 if (bus->creds_mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
697 char **wkn;
698 size_t n;
699
700 /* We just extend the array here, but
701 * do not allocate the strings inside
702 * of it, instead we just point to our
703 * buffer directly. */
704 n = strv_length(m->creds.well_known_names);
705 wkn = realloc(m->creds.well_known_names, (n + 2) * sizeof(char*));
706 if (!wkn) {
707 r = -ENOMEM;
708 goto fail;
709 }
710
711 wkn[n] = d->name.name;
712 wkn[n+1] = NULL;
713 m->creds.well_known_names = wkn;
714
715 m->creds.mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
716 }
60f067b4
JS
717 break;
718
f47781d8
MP
719 case KDBUS_ITEM_CONN_DESCRIPTION:
720 m->creds.description = d->str;
721 m->creds.mask |= SD_BUS_CREDS_DESCRIPTION & bus->creds_mask;
722 break;
723
724 case KDBUS_ITEM_AUXGROUPS:
725
726 if (bus->creds_mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
727 assert_cc(sizeof(gid_t) == sizeof(uint32_t));
728
729 m->creds.n_supplementary_gids = (d->size - offsetof(struct kdbus_item, data32)) / sizeof(uint32_t);
730 m->creds.supplementary_gids = (gid_t*) d->data32;
731 m->creds.mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
732 }
733
60f067b4
JS
734 break;
735
736 case KDBUS_ITEM_FDS:
737 case KDBUS_ITEM_SECLABEL:
738 break;
739
740 default:
741 log_debug("Got unknown field from kernel %llu", d->type);
742 }
743 }
744
f47781d8
MP
745 /* If we requested the list of well-known names to be appended
746 * and the sender had none no item for it will be
747 * attached. However, this does *not* mean that we the kernel
748 * didn't want to provide this information to us. Hence, let's
749 * explicitly mark this information as available if it was
750 * requested. */
751 m->creds.mask |= bus->creds_mask & SD_BUS_CREDS_WELL_KNOWN_NAMES;
752
60f067b4
JS
753 r = bus_message_parse_fields(m);
754 if (r < 0)
755 goto fail;
756
f47781d8
MP
757 /* Refuse messages if kdbus and dbus1 cookie doesn't match up */
758 if ((uint64_t) m->header->serial != k->cookie) {
759 r = -EBADMSG;
760 goto fail;
761 }
762
763 /* Refuse messages where the reply flag doesn't match up */
764 if (!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) != !!(k->flags & KDBUS_MSG_FLAGS_EXPECT_REPLY)) {
765 r = -EBADMSG;
766 goto fail;
767 }
768
769 /* Refuse reply messages where the reply cookie doesn't match up */
770 if ((m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) && m->reply_cookie != k->cookie_reply) {
771 r = -EBADMSG;
772 goto fail;
773 }
774
775 /* Refuse messages where the autostart flag doesn't match up */
776 if (!(m->header->flags & BUS_MESSAGE_NO_AUTO_START) != !(k->flags & KDBUS_MSG_FLAGS_NO_AUTO_START)) {
777 r = -EBADMSG;
778 goto fail;
779 }
780
60f067b4
JS
781 /* Override information from the user header with data from the kernel */
782 if (k->src_id == KDBUS_SRC_ID_KERNEL)
f47781d8 783 bus_message_set_sender_driver(bus, m);
60f067b4
JS
784 else {
785 snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
786 m->sender = m->creds.unique_name = m->sender_buffer;
787 }
788
789 if (destination)
790 m->destination = destination;
791 else if (k->dst_id == KDBUS_DST_ID_BROADCAST)
792 m->destination = NULL;
793 else if (k->dst_id == KDBUS_DST_ID_NAME)
794 m->destination = bus->unique_name; /* fill in unique name if the well-known name is missing */
795 else {
796 snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
797 m->destination = m->destination_buffer;
798 }
799
800 /* We take possession of the kmsg struct now */
801 m->kdbus = k;
802 m->release_kdbus = true;
803 m->free_fds = true;
804 fds = NULL;
805
806 bus->rqueue[bus->rqueue_size++] = m;
807
808 return 1;
809
810fail:
5eef597e
MP
811 unset_memfds(m);
812 sd_bus_message_unref(m);
60f067b4
JS
813
814 return r;
815}
816
817int bus_kernel_take_fd(sd_bus *b) {
818 struct kdbus_cmd_hello *hello;
819 struct kdbus_item *item;
820 _cleanup_free_ char *g = NULL;
821 const char *name;
822 size_t l = 0, m = 0, sz;
823 int r;
824
825 assert(b);
826
827 if (b->is_server)
828 return -EINVAL;
829
830 b->use_memfd = 1;
831
f47781d8
MP
832 if (b->description) {
833 g = bus_label_escape(b->description);
60f067b4
JS
834 if (!g)
835 return -ENOMEM;
836
837 name = g;
838 } else {
839 char pr[17] = {};
840
841 /* If no name is explicitly set, we'll include a hint
842 * indicating the library implementation, a hint which
843 * kind of bus this is and the thread name */
844
845 assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0);
846
847 if (isempty(pr)) {
848 name = b->is_system ? "sd-system" :
849 b->is_user ? "sd-user" : "sd";
850 } else {
851 _cleanup_free_ char *e = NULL;
852
853 e = bus_label_escape(pr);
854 if (!e)
855 return -ENOMEM;
856
857 g = strappend(b->is_system ? "sd-system-" :
858 b->is_user ? "sd-user-" : "sd-",
859 e);
860 if (!g)
861 return -ENOMEM;
862
863 name = g;
864 }
865
f47781d8
MP
866 b->description = bus_label_unescape(name);
867 if (!b->description)
60f067b4
JS
868 return -ENOMEM;
869 }
870
871 m = strlen(name);
872
873 sz = ALIGN8(offsetof(struct kdbus_cmd_hello, items)) +
874 ALIGN8(offsetof(struct kdbus_item, str) + m + 1);
875
876 if (b->fake_creds_valid)
877 sz += ALIGN8(offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds));
878
f47781d8
MP
879 if (b->fake_pids_valid)
880 sz += ALIGN8(offsetof(struct kdbus_item, pids) + sizeof(struct kdbus_pids));
881
60f067b4
JS
882 if (b->fake_label) {
883 l = strlen(b->fake_label);
884 sz += ALIGN8(offsetof(struct kdbus_item, str) + l + 1);
885 }
886
5eef597e 887 hello = alloca0_align(sz, 8);
60f067b4 888 hello->size = sz;
5eef597e 889 hello->flags = b->hello_flags;
f47781d8
MP
890 hello->attach_flags_send = _KDBUS_ATTACH_ANY;
891 hello->attach_flags_recv = b->attach_flags;
60f067b4
JS
892 hello->pool_size = KDBUS_POOL_SIZE;
893
894 item = hello->items;
895
896 item->size = offsetof(struct kdbus_item, str) + m + 1;
f47781d8 897 item->type = KDBUS_ITEM_CONN_DESCRIPTION;
60f067b4
JS
898 memcpy(item->str, name, m + 1);
899 item = KDBUS_ITEM_NEXT(item);
900
901 if (b->fake_creds_valid) {
902 item->size = offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds);
903 item->type = KDBUS_ITEM_CREDS;
904 item->creds = b->fake_creds;
905
906 item = KDBUS_ITEM_NEXT(item);
907 }
908
f47781d8
MP
909 if (b->fake_pids_valid) {
910 item->size = offsetof(struct kdbus_item, pids) + sizeof(struct kdbus_pids);
911 item->type = KDBUS_ITEM_PIDS;
912 item->pids = b->fake_pids;
913
914 item = KDBUS_ITEM_NEXT(item);
915 }
916
60f067b4
JS
917 if (b->fake_label) {
918 item->size = offsetof(struct kdbus_item, str) + l + 1;
919 item->type = KDBUS_ITEM_SECLABEL;
920 memcpy(item->str, b->fake_label, l+1);
921 }
922
923 r = ioctl(b->input_fd, KDBUS_CMD_HELLO, hello);
924 if (r < 0)
925 return -errno;
926
927 if (!b->kdbus_buffer) {
928 b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, b->input_fd, 0);
929 if (b->kdbus_buffer == MAP_FAILED) {
930 b->kdbus_buffer = NULL;
931 return -errno;
932 }
933 }
934
5eef597e 935 /* The higher 32bit of the bus_flags fields are considered
60f067b4 936 * 'incompatible flags'. Refuse them all for now. */
5eef597e 937 if (hello->bus_flags > 0xFFFFFFFFULL)
60f067b4
JS
938 return -ENOTSUP;
939
940 if (!bloom_validate_parameters((size_t) hello->bloom.size, (unsigned) hello->bloom.n_hash))
941 return -ENOTSUP;
942
943 b->bloom_size = (size_t) hello->bloom.size;
944 b->bloom_n_hash = (unsigned) hello->bloom.n_hash;
945
946 if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello->id) < 0)
947 return -ENOMEM;
948
949 b->unique_id = hello->id;
950
951 b->is_kernel = true;
952 b->bus_client = true;
5eef597e 953 b->can_fds = !!(hello->flags & KDBUS_HELLO_ACCEPT_FD);
60f067b4
JS
954 b->message_version = 2;
955 b->message_endian = BUS_NATIVE_ENDIAN;
956
957 /* the kernel told us the UUID of the underlying bus */
958 memcpy(b->server_id.bytes, hello->id128, sizeof(b->server_id.bytes));
959
960 return bus_start_running(b);
961}
962
963int bus_kernel_connect(sd_bus *b) {
964 assert(b);
965 assert(b->input_fd < 0);
966 assert(b->output_fd < 0);
967 assert(b->kernel);
968
969 if (b->is_server)
970 return -EINVAL;
971
972 b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
973 if (b->input_fd < 0)
974 return -errno;
975
976 b->output_fd = b->input_fd;
977
978 return bus_kernel_take_fd(b);
979}
980
f47781d8
MP
981int bus_kernel_cmd_free(sd_bus *bus, uint64_t offset) {
982 struct kdbus_cmd_free cmd = {
983 .flags = 0,
984 .offset = offset,
985 };
986 int r;
987
988 assert(bus);
989 assert(bus->is_kernel);
990
991 r = ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd);
992 if (r < 0)
993 return -errno;
994
995 return 0;
996}
997
60f067b4 998static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
60f067b4
JS
999 struct kdbus_item *d;
1000
1001 assert(bus);
1002 assert(k);
1003
60f067b4 1004 KDBUS_ITEM_FOREACH(d, k, items) {
60f067b4
JS
1005 if (d->type == KDBUS_ITEM_FDS)
1006 close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
1007 else if (d->type == KDBUS_ITEM_PAYLOAD_MEMFD)
1008 safe_close(d->memfd.fd);
1009 }
5eef597e 1010
f47781d8 1011 bus_kernel_cmd_free(bus, (uint8_t*) k - (uint8_t*) bus->kdbus_buffer);
60f067b4
JS
1012}
1013
1014int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call) {
1015 int r;
1016
1017 assert(bus);
1018 assert(m);
1019 assert(bus->state == BUS_RUNNING);
1020
1021 /* If we can't deliver, we want room for the error message */
1022 r = bus_rqueue_make_room(bus);
1023 if (r < 0)
1024 return r;
1025
1026 r = bus_message_setup_kmsg(bus, m);
1027 if (r < 0)
1028 return r;
1029
1030 /* If this is a synchronous method call, then let's tell the
1031 * kernel, so that it can pass CPU time/scheduling to the
1032 * destination for the time, if it wants to. If we
1033 * synchronously wait for the result anyway, we won't need CPU
1034 * anyway. */
1035 if (hint_sync_call)
1036 m->kdbus->flags |= KDBUS_MSG_FLAGS_EXPECT_REPLY|KDBUS_MSG_FLAGS_SYNC_REPLY;
1037
1038 r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
1039 if (r < 0) {
1040 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1041 sd_bus_message *reply;
1042
1043 if (errno == EAGAIN || errno == EINTR)
1044 return 0;
1045 else if (errno == ENXIO || errno == ESRCH) {
1046
1047 /* ENXIO: unique name not known
1048 * ESRCH: well-known name not known */
1049
1050 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1051 sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Destination %s not known", m->destination);
1052 else {
1053 log_debug("Could not deliver message to %s as destination is not known. Ignoring.", m->destination);
1054 return 0;
1055 }
1056
1057 } else if (errno == EADDRNOTAVAIL) {
1058
1059 /* EADDRNOTAVAIL: activation is possible, but turned off in request flags */
1060
1061 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1062 sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Activation of %s not requested", m->destination);
1063 else {
1064 log_debug("Could not deliver message to %s as destination is not activated. Ignoring.", m->destination);
1065 return 0;
1066 }
1067 } else
1068 return -errno;
1069
1070 r = bus_message_new_synthetic_error(
1071 bus,
1072 BUS_MESSAGE_COOKIE(m),
1073 &error,
1074 &reply);
1075
1076 if (r < 0)
1077 return r;
1078
1079 r = bus_seal_synthetic_message(bus, reply);
1080 if (r < 0)
1081 return r;
1082
1083 bus->rqueue[bus->rqueue_size++] = reply;
1084
1085 } else if (hint_sync_call) {
1086 struct kdbus_msg *k;
1087
1088 k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + m->kdbus->offset_reply);
1089 assert(k);
1090
1091 if (k->payload_type == KDBUS_PAYLOAD_DBUS) {
1092
1093 r = bus_kernel_make_message(bus, k);
1094 if (r < 0) {
1095 close_kdbus_msg(bus, k);
1096
1097 /* Anybody can send us invalid messages, let's just drop them. */
1098 if (r == -EBADMSG || r == -EPROTOTYPE)
f47781d8 1099 log_debug_errno(r, "Ignoring invalid message: %m");
60f067b4
JS
1100 else
1101 return r;
1102 }
1103 } else {
1104 log_debug("Ignoring message with unknown payload type %llu.", (unsigned long long) k->payload_type);
1105 close_kdbus_msg(bus, k);
1106 }
1107 }
1108
1109 return 1;
1110}
1111
1112static int push_name_owner_changed(sd_bus *bus, const char *name, const char *old_owner, const char *new_owner) {
1113 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1114 int r;
1115
1116 assert(bus);
1117
1118 r = sd_bus_message_new_signal(
1119 bus,
1120 &m,
1121 "/org/freedesktop/DBus",
1122 "org.freedesktop.DBus",
1123 "NameOwnerChanged");
1124 if (r < 0)
1125 return r;
1126
1127 r = sd_bus_message_append(m, "sss", name, old_owner, new_owner);
1128 if (r < 0)
1129 return r;
1130
f47781d8 1131 bus_message_set_sender_driver(bus, m);
60f067b4
JS
1132
1133 r = bus_seal_synthetic_message(bus, m);
1134 if (r < 0)
1135 return r;
1136
1137 bus->rqueue[bus->rqueue_size++] = m;
1138 m = NULL;
1139
1140 return 1;
1141}
1142
1143static int translate_name_change(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d) {
1144 char new_owner[UNIQUE_NAME_MAX], old_owner[UNIQUE_NAME_MAX];
1145
1146 assert(bus);
1147 assert(k);
1148 assert(d);
1149
5eef597e 1150 if (d->type == KDBUS_ITEM_NAME_ADD || (d->name_change.old_id.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR)))
60f067b4
JS
1151 old_owner[0] = 0;
1152 else
5eef597e 1153 sprintf(old_owner, ":1.%llu", (unsigned long long) d->name_change.old_id.id);
60f067b4 1154
5eef597e 1155 if (d->type == KDBUS_ITEM_NAME_REMOVE || (d->name_change.new_id.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR))) {
60f067b4
JS
1156
1157 if (isempty(old_owner))
1158 return 0;
1159
1160 new_owner[0] = 0;
1161 } else
5eef597e 1162 sprintf(new_owner, ":1.%llu", (unsigned long long) d->name_change.new_id.id);
60f067b4
JS
1163
1164 return push_name_owner_changed(bus, d->name_change.name, old_owner, new_owner);
1165}
1166
1167static int translate_id_change(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d) {
1168 char owner[UNIQUE_NAME_MAX];
1169
1170 assert(bus);
1171 assert(k);
1172 assert(d);
1173
1174 sprintf(owner, ":1.%llu", d->id_change.id);
1175
1176 return push_name_owner_changed(
1177 bus, owner,
1178 d->type == KDBUS_ITEM_ID_ADD ? NULL : owner,
1179 d->type == KDBUS_ITEM_ID_ADD ? owner : NULL);
1180}
1181
1182static int translate_reply(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d) {
1183 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1184 int r;
1185
1186 assert(bus);
1187 assert(k);
1188 assert(d);
1189
1190 r = bus_message_new_synthetic_error(
1191 bus,
1192 k->cookie_reply,
1193 d->type == KDBUS_ITEM_REPLY_TIMEOUT ?
1194 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call timed out") :
1195 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call peer died"),
1196 &m);
1197 if (r < 0)
1198 return r;
1199
f47781d8 1200 bus_message_set_sender_driver(bus, m);
60f067b4
JS
1201
1202 r = bus_seal_synthetic_message(bus, m);
1203 if (r < 0)
1204 return r;
1205
1206 bus->rqueue[bus->rqueue_size++] = m;
1207 m = NULL;
1208
1209 return 1;
1210}
1211
1212static int bus_kernel_translate_message(sd_bus *bus, struct kdbus_msg *k) {
1213 struct kdbus_item *d, *found = NULL;
1214
1215 static int (* const translate[])(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d) = {
1216 [KDBUS_ITEM_NAME_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
1217 [KDBUS_ITEM_NAME_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
1218 [KDBUS_ITEM_NAME_CHANGE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
1219
1220 [KDBUS_ITEM_ID_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
1221 [KDBUS_ITEM_ID_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
1222
1223 [KDBUS_ITEM_REPLY_TIMEOUT - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
1224 [KDBUS_ITEM_REPLY_DEAD - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
1225 };
1226
1227 assert(bus);
1228 assert(k);
1229 assert(k->payload_type == KDBUS_PAYLOAD_KERNEL);
1230
1231 KDBUS_ITEM_FOREACH(d, k, items) {
1232 if (d->type >= _KDBUS_ITEM_KERNEL_BASE && d->type < _KDBUS_ITEM_KERNEL_BASE + ELEMENTSOF(translate)) {
1233 if (found)
1234 return -EBADMSG;
1235 found = d;
1236 } else
1237 log_debug("Got unknown field from kernel %llu", d->type);
1238 }
1239
1240 if (!found) {
1241 log_debug("Didn't find a kernel message to translate.");
1242 return 0;
1243 }
1244
1245 return translate[found->type - _KDBUS_ITEM_KERNEL_BASE](bus, k, found);
1246}
1247
1248int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority) {
1249 struct kdbus_cmd_recv recv = {};
1250 struct kdbus_msg *k;
1251 int r;
1252
1253 assert(bus);
1254
1255 r = bus_rqueue_make_room(bus);
1256 if (r < 0)
1257 return r;
1258
1259 if (hint_priority) {
1260 recv.flags |= KDBUS_RECV_USE_PRIORITY;
1261 recv.priority = priority;
1262 }
1263
1264 r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, &recv);
1265 if (r < 0) {
1266 if (errno == EAGAIN)
1267 return 0;
1268
f47781d8
MP
1269 if (errno == EOVERFLOW) {
1270 log_debug("%s: kdbus reports %" PRIu64 " dropped broadcast messages, ignoring.", strna(bus->description), (uint64_t) recv.dropped_msgs);
1271 return 0;
1272 }
1273
60f067b4
JS
1274 return -errno;
1275 }
1276
1277 k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + recv.offset);
1278 if (k->payload_type == KDBUS_PAYLOAD_DBUS) {
1279 r = bus_kernel_make_message(bus, k);
1280
1281 /* Anybody can send us invalid messages, let's just drop them. */
1282 if (r == -EBADMSG || r == -EPROTOTYPE) {
f47781d8 1283 log_debug_errno(r, "Ignoring invalid message: %m");
60f067b4
JS
1284 r = 0;
1285 }
1286
1287 } else if (k->payload_type == KDBUS_PAYLOAD_KERNEL)
1288 r = bus_kernel_translate_message(bus, k);
1289 else {
1290 log_debug("Ignoring message with unknown payload type %llu.", (unsigned long long) k->payload_type);
1291 r = 0;
1292 }
1293
1294 if (r <= 0)
1295 close_kdbus_msg(bus, k);
1296
1297 return r < 0 ? r : 1;
1298}
1299
1300int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *allocated) {
1301 struct memfd_cache *c;
1302 int fd;
1303
1304 assert(address);
1305 assert(mapped);
1306 assert(allocated);
1307
1308 if (!bus || !bus->is_kernel)
1309 return -ENOTSUP;
1310
1311 assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
1312
1313 if (bus->n_memfd_cache <= 0) {
60f067b4
JS
1314 int r;
1315
1316 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
1317
f47781d8 1318 r = memfd_new(bus->description);
60f067b4 1319 if (r < 0)
f47781d8 1320 return r;
60f067b4
JS
1321
1322 *address = NULL;
1323 *mapped = 0;
1324 *allocated = 0;
5eef597e 1325 return r;
60f067b4
JS
1326 }
1327
1328 c = &bus->memfd_cache[--bus->n_memfd_cache];
1329
1330 assert(c->fd >= 0);
1331 assert(c->mapped == 0 || c->address);
1332
1333 *address = c->address;
1334 *mapped = c->mapped;
1335 *allocated = c->allocated;
1336 fd = c->fd;
1337
1338 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
1339
1340 return fd;
1341}
1342
1343static void close_and_munmap(int fd, void *address, size_t size) {
1344 if (size > 0)
1345 assert_se(munmap(address, PAGE_ALIGN(size)) >= 0);
1346
1347 safe_close(fd);
1348}
1349
1350void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t mapped, size_t allocated) {
1351 struct memfd_cache *c;
1352 uint64_t max_mapped = PAGE_ALIGN(MEMFD_CACHE_ITEM_SIZE_MAX);
1353
1354 assert(fd >= 0);
1355 assert(mapped == 0 || address);
1356
1357 if (!bus || !bus->is_kernel) {
1358 close_and_munmap(fd, address, mapped);
1359 return;
1360 }
1361
1362 assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
1363
1364 if (bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
1365 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
1366
1367 close_and_munmap(fd, address, mapped);
1368 return;
1369 }
1370
1371 c = &bus->memfd_cache[bus->n_memfd_cache++];
1372 c->fd = fd;
1373 c->address = address;
1374
1375 /* If overly long, let's return a bit to the OS */
1376 if (mapped > max_mapped) {
f47781d8 1377 assert_se(memfd_set_size(fd, max_mapped) >= 0);
60f067b4
JS
1378 assert_se(munmap((uint8_t*) address + max_mapped, PAGE_ALIGN(mapped - max_mapped)) >= 0);
1379 c->mapped = c->allocated = max_mapped;
1380 } else {
1381 c->mapped = mapped;
1382 c->allocated = allocated;
1383 }
1384
1385 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
1386}
1387
1388void bus_kernel_flush_memfd(sd_bus *b) {
1389 unsigned i;
1390
1391 assert(b);
1392
1393 for (i = 0; i < b->n_memfd_cache; i++)
1394 close_and_munmap(b->memfd_cache[i].fd, b->memfd_cache[i].address, b->memfd_cache[i].mapped);
1395}
1396
f47781d8 1397uint64_t request_name_flags_to_kdbus(uint64_t flags) {
60f067b4
JS
1398 uint64_t f = 0;
1399
60f067b4
JS
1400 if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
1401 f |= KDBUS_NAME_ALLOW_REPLACEMENT;
1402
1403 if (flags & SD_BUS_NAME_REPLACE_EXISTING)
1404 f |= KDBUS_NAME_REPLACE_EXISTING;
1405
1406 if (flags & SD_BUS_NAME_QUEUE)
1407 f |= KDBUS_NAME_QUEUE;
1408
f47781d8 1409 return f;
60f067b4
JS
1410}
1411
f47781d8 1412uint64_t attach_flags_to_kdbus(uint64_t mask) {
60f067b4
JS
1413 uint64_t m = 0;
1414
f47781d8
MP
1415 if (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
1416 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID))
60f067b4
JS
1417 m |= KDBUS_ATTACH_CREDS;
1418
f47781d8
MP
1419 if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_TID))
1420 m |= KDBUS_ATTACH_PIDS;
1421
5eef597e
MP
1422 if (mask & SD_BUS_CREDS_COMM)
1423 m |= KDBUS_ATTACH_PID_COMM;
1424
1425 if (mask & SD_BUS_CREDS_TID_COMM)
1426 m |= KDBUS_ATTACH_TID_COMM;
60f067b4
JS
1427
1428 if (mask & SD_BUS_CREDS_EXE)
1429 m |= KDBUS_ATTACH_EXE;
1430
1431 if (mask & SD_BUS_CREDS_CMDLINE)
1432 m |= KDBUS_ATTACH_CMDLINE;
1433
1434 if (mask & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID))
1435 m |= KDBUS_ATTACH_CGROUP;
1436
1437 if (mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS))
1438 m |= KDBUS_ATTACH_CAPS;
1439
1440 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT)
1441 m |= KDBUS_ATTACH_SECLABEL;
1442
1443 if (mask & (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID))
1444 m |= KDBUS_ATTACH_AUDIT;
1445
1446 if (mask & SD_BUS_CREDS_WELL_KNOWN_NAMES)
1447 m |= KDBUS_ATTACH_NAMES;
1448
f47781d8
MP
1449 if (mask & SD_BUS_CREDS_DESCRIPTION)
1450 m |= KDBUS_ATTACH_CONN_DESCRIPTION;
60f067b4 1451
f47781d8
MP
1452 if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS)
1453 m |= KDBUS_ATTACH_AUXGROUPS;
1454
1455 return m;
60f067b4
JS
1456}
1457
1458int bus_kernel_create_bus(const char *name, bool world, char **s) {
1459 struct kdbus_cmd_make *make;
1460 struct kdbus_item *n;
f47781d8 1461 size_t l;
60f067b4
JS
1462 int fd;
1463
1464 assert(name);
1465 assert(s);
1466
f47781d8 1467 fd = open("/sys/fs/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
60f067b4
JS
1468 if (fd < 0)
1469 return -errno;
1470
f47781d8
MP
1471 l = strlen(name);
1472 make = alloca0_align(offsetof(struct kdbus_cmd_make, items) +
1473 ALIGN8(offsetof(struct kdbus_item, bloom_parameter) + sizeof(struct kdbus_bloom_parameter)) +
1474 ALIGN8(offsetof(struct kdbus_item, data64) + sizeof(uint64_t)) +
1475 ALIGN8(offsetof(struct kdbus_item, str) + DECIMAL_STR_MAX(uid_t) + 1 + l + 1),
5eef597e 1476 8);
60f067b4
JS
1477
1478 make->size = offsetof(struct kdbus_cmd_make, items);
1479
f47781d8 1480 /* Set the bloom parameters */
60f067b4
JS
1481 n = make->items;
1482 n->size = offsetof(struct kdbus_item, bloom_parameter) +
1483 sizeof(struct kdbus_bloom_parameter);
1484 n->type = KDBUS_ITEM_BLOOM_PARAMETER;
60f067b4
JS
1485 n->bloom_parameter.size = DEFAULT_BLOOM_SIZE;
1486 n->bloom_parameter.n_hash = DEFAULT_BLOOM_N_HASH;
1487
1488 assert_cc(DEFAULT_BLOOM_SIZE > 0);
1489 assert_cc(DEFAULT_BLOOM_N_HASH > 0);
1490
1491 make->size += ALIGN8(n->size);
1492
f47781d8
MP
1493 /* The busses we create make no restrictions on what metadata
1494 * peers can read from incoming messages. */
1495 n = KDBUS_ITEM_NEXT(n);
1496 n->type = KDBUS_ITEM_ATTACH_FLAGS_RECV;
1497 n->size = offsetof(struct kdbus_item, data64) + sizeof(uint64_t);
1498 n->data64[0] = _KDBUS_ATTACH_ANY;
1499 make->size += ALIGN8(n->size);
1500
1501 /* Set the a good name */
60f067b4
JS
1502 n = KDBUS_ITEM_NEXT(n);
1503 sprintf(n->str, UID_FMT "-%s", getuid(), name);
1504 n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
1505 n->type = KDBUS_ITEM_MAKE_NAME;
1506 make->size += ALIGN8(n->size);
1507
1508 make->flags = world ? KDBUS_MAKE_ACCESS_WORLD : 0;
1509
1510 if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
1511 safe_close(fd);
1512 return -errno;
1513 }
1514
60f067b4
JS
1515 if (s) {
1516 char *p;
1517
f47781d8 1518 p = strjoin("/sys/fs/kdbus/", n->str, "/bus", NULL);
60f067b4
JS
1519 if (!p) {
1520 safe_close(fd);
1521 return -ENOMEM;
1522 }
1523
1524 *s = p;
1525 }
1526
1527 return fd;
1528}
1529
5eef597e 1530static int bus_kernel_translate_access(BusPolicyAccess access) {
60f067b4 1531 assert(access >= 0);
5eef597e 1532 assert(access < _BUS_POLICY_ACCESS_MAX);
60f067b4
JS
1533
1534 switch (access) {
1535
5eef597e 1536 case BUS_POLICY_ACCESS_SEE:
60f067b4
JS
1537 return KDBUS_POLICY_SEE;
1538
5eef597e 1539 case BUS_POLICY_ACCESS_TALK:
60f067b4
JS
1540 return KDBUS_POLICY_TALK;
1541
5eef597e 1542 case BUS_POLICY_ACCESS_OWN:
60f067b4
JS
1543 return KDBUS_POLICY_OWN;
1544
1545 default:
1546 assert_not_reached("Unknown policy access");
1547 }
1548}
1549
1550static int bus_kernel_translate_policy(const BusNamePolicy *policy, struct kdbus_item *item) {
1551 int r;
1552
1553 assert(policy);
1554 assert(item);
1555
1556 switch (policy->type) {
1557
1558 case BUSNAME_POLICY_TYPE_USER: {
1559 const char *user = policy->name;
1560 uid_t uid;
1561
1562 r = get_user_creds(&user, &uid, NULL, NULL, NULL);
1563 if (r < 0)
1564 return r;
1565
1566 item->policy_access.type = KDBUS_POLICY_ACCESS_USER;
1567 item->policy_access.id = uid;
1568 break;
1569 }
1570
1571 case BUSNAME_POLICY_TYPE_GROUP: {
1572 const char *group = policy->name;
1573 gid_t gid;
1574
1575 r = get_group_creds(&group, &gid);
1576 if (r < 0)
1577 return r;
1578
1579 item->policy_access.type = KDBUS_POLICY_ACCESS_GROUP;
1580 item->policy_access.id = gid;
1581 break;
1582 }
1583
1584 default:
1585 assert_not_reached("Unknown policy type");
1586 }
1587
1588 item->policy_access.access = bus_kernel_translate_access(policy->access);
1589
1590 return 0;
1591}
1592
5eef597e 1593int bus_kernel_open_bus_fd(const char *bus, char **path) {
60f067b4
JS
1594 char *p;
1595 int fd;
5eef597e 1596 size_t len;
60f067b4 1597
f47781d8
MP
1598 assert(bus);
1599
1600 len = strlen("/sys/fs/kdbus/") + DECIMAL_STR_MAX(uid_t) + 1 + strlen(bus) + strlen("/bus") + 1;
5eef597e
MP
1601
1602 if (path) {
f47781d8 1603 p = new(char, len);
5eef597e
MP
1604 if (!p)
1605 return -ENOMEM;
5eef597e 1606 } else
f47781d8
MP
1607 p = newa(char, len);
1608
1609 sprintf(p, "/sys/fs/kdbus/" UID_FMT "-%s/bus", getuid(), bus);
60f067b4
JS
1610
1611 fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC);
f47781d8
MP
1612 if (fd < 0) {
1613 if (path)
1614 free(p);
1615
60f067b4 1616 return -errno;
f47781d8
MP
1617 }
1618
1619 if (path)
1620 *path = p;
60f067b4
JS
1621
1622 return fd;
1623}
1624
5eef597e
MP
1625int bus_kernel_create_endpoint(const char *bus_name, const char *ep_name, char **ep_path) {
1626 _cleanup_free_ char *path = NULL;
1627 struct kdbus_cmd_make *make;
1628 struct kdbus_item *n;
f47781d8 1629 const char *name;
5eef597e
MP
1630 int fd;
1631
1632 fd = bus_kernel_open_bus_fd(bus_name, &path);
1633 if (fd < 0)
1634 return fd;
1635
f47781d8
MP
1636 make = alloca0_align(ALIGN8(offsetof(struct kdbus_cmd_make, items)) +
1637 ALIGN8(offsetof(struct kdbus_item, str) + DECIMAL_STR_MAX(uid_t) + 1 + strlen(ep_name) + 1),
1638 8);
1639 make->size = ALIGN8(offsetof(struct kdbus_cmd_make, items));
5eef597e
MP
1640 make->flags = KDBUS_MAKE_ACCESS_WORLD;
1641
1642 n = make->items;
f47781d8
MP
1643 sprintf(n->str, UID_FMT "-%s", getuid(), ep_name);
1644 n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
5eef597e 1645 n->type = KDBUS_ITEM_MAKE_NAME;
f47781d8
MP
1646 make->size += ALIGN8(n->size);
1647 name = n->str;
5eef597e
MP
1648
1649 if (ioctl(fd, KDBUS_CMD_ENDPOINT_MAKE, make) < 0) {
1650 safe_close(fd);
1651 return -errno;
1652 }
1653
1654 if (ep_path) {
1655 char *p;
1656
f47781d8 1657 p = strjoin(dirname(path), "/", name, NULL);
5eef597e
MP
1658 if (!p) {
1659 safe_close(fd);
1660 return -ENOMEM;
1661 }
1662
1663 *ep_path = p;
1664 }
1665
1666 return fd;
1667}
1668
1669int bus_kernel_set_endpoint_policy(int fd, uid_t uid, BusEndpoint *ep) {
1670
1671 struct kdbus_cmd_update *update;
1672 struct kdbus_item *n;
1673 BusEndpointPolicy *po;
1674 Iterator i;
1675 size_t size;
1676 int r;
1677
1678 size = ALIGN8(offsetof(struct kdbus_cmd_update, items));
1679
1680 HASHMAP_FOREACH(po, ep->policy_hash, i) {
1681 size += ALIGN8(offsetof(struct kdbus_item, str) + strlen(po->name) + 1);
1682 size += ALIGN8(offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access));
1683 }
1684
1685 update = alloca0_align(size, 8);
1686 update->size = size;
1687
1688 n = update->items;
1689
1690 HASHMAP_FOREACH(po, ep->policy_hash, i) {
1691 n->type = KDBUS_ITEM_NAME;
1692 n->size = offsetof(struct kdbus_item, str) + strlen(po->name) + 1;
1693 strcpy(n->str, po->name);
1694 n = KDBUS_ITEM_NEXT(n);
1695
1696 n->type = KDBUS_ITEM_POLICY_ACCESS;
1697 n->size = offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access);
1698
1699 n->policy_access.type = KDBUS_POLICY_ACCESS_USER;
1700 n->policy_access.access = bus_kernel_translate_access(po->access);
1701 n->policy_access.id = uid;
1702
1703 n = KDBUS_ITEM_NEXT(n);
1704 }
1705
1706 r = ioctl(fd, KDBUS_CMD_ENDPOINT_UPDATE, update);
1707 if (r < 0)
1708 return -errno;
1709
1710 return 0;
1711}
1712
60f067b4
JS
1713int bus_kernel_make_starter(
1714 int fd,
1715 const char *name,
1716 bool activating,
1717 bool accept_fd,
1718 BusNamePolicy *policy,
5eef597e 1719 BusPolicyAccess world_policy) {
60f067b4
JS
1720
1721 struct kdbus_cmd_hello *hello;
1722 struct kdbus_item *n;
1723 size_t policy_cnt = 0;
1724 BusNamePolicy *po;
1725 size_t size;
1726 int r;
1727
1728 assert(fd >= 0);
1729 assert(name);
1730
1731 LIST_FOREACH(policy, po, policy)
1732 policy_cnt++;
1733
1734 if (world_policy >= 0)
1735 policy_cnt++;
1736
f47781d8 1737 size = offsetof(struct kdbus_cmd_hello, items) +
60f067b4
JS
1738 ALIGN8(offsetof(struct kdbus_item, str) + strlen(name) + 1) +
1739 policy_cnt * ALIGN8(offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access));
1740
5eef597e 1741 hello = alloca0_align(size, 8);
60f067b4
JS
1742
1743 n = hello->items;
1744 strcpy(n->str, name);
1745 n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
1746 n->type = KDBUS_ITEM_NAME;
1747 n = KDBUS_ITEM_NEXT(n);
1748
1749 LIST_FOREACH(policy, po, policy) {
1750 n->type = KDBUS_ITEM_POLICY_ACCESS;
1751 n->size = offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access);
1752
1753 r = bus_kernel_translate_policy(po, n);
1754 if (r < 0)
1755 return r;
1756
1757 n = KDBUS_ITEM_NEXT(n);
1758 }
1759
1760 if (world_policy >= 0) {
1761 n->type = KDBUS_ITEM_POLICY_ACCESS;
1762 n->size = offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access);
1763 n->policy_access.type = KDBUS_POLICY_ACCESS_WORLD;
1764 n->policy_access.access = bus_kernel_translate_access(world_policy);
1765 }
1766
1767 hello->size = size;
5eef597e 1768 hello->flags =
60f067b4
JS
1769 (activating ? KDBUS_HELLO_ACTIVATOR : KDBUS_HELLO_POLICY_HOLDER) |
1770 (accept_fd ? KDBUS_HELLO_ACCEPT_FD : 0);
1771 hello->pool_size = KDBUS_POOL_SIZE;
f47781d8
MP
1772 hello->attach_flags_send = _KDBUS_ATTACH_ANY;
1773 hello->attach_flags_recv = _KDBUS_ATTACH_ANY;
60f067b4
JS
1774
1775 if (ioctl(fd, KDBUS_CMD_HELLO, hello) < 0)
1776 return -errno;
1777
5eef597e 1778 /* The higher 32bit of the bus_flags fields are considered
60f067b4 1779 * 'incompatible flags'. Refuse them all for now. */
5eef597e 1780 if (hello->bus_flags > 0xFFFFFFFFULL)
60f067b4
JS
1781 return -ENOTSUP;
1782
1783 if (!bloom_validate_parameters((size_t) hello->bloom.size, (unsigned) hello->bloom.n_hash))
1784 return -ENOTSUP;
1785
1786 return fd;
1787}
1788
f47781d8
MP
1789int bus_kernel_try_close(sd_bus *bus) {
1790 assert(bus);
1791 assert(bus->is_kernel);
60f067b4 1792
f47781d8
MP
1793 if (ioctl(bus->input_fd, KDBUS_CMD_BYEBYE) < 0)
1794 return -errno;
60f067b4 1795
f47781d8
MP
1796 return 0;
1797}
1798
1799int bus_kernel_drop_one(int fd) {
1800 struct kdbus_cmd_recv recv = {
1801 .flags = KDBUS_RECV_DROP
1802 };
1803
1804 assert(fd >= 0);
1805
1806 if (ioctl(fd, KDBUS_CMD_MSG_RECV, &recv) < 0)
60f067b4
JS
1807 return -errno;
1808
f47781d8
MP
1809 return 0;
1810}
60f067b4 1811
f47781d8
MP
1812int bus_kernel_realize_attach_flags(sd_bus *bus) {
1813 struct kdbus_cmd_update *update;
1814 struct kdbus_item *n;
60f067b4 1815
f47781d8
MP
1816 assert(bus);
1817 assert(bus->is_kernel);
60f067b4 1818
f47781d8
MP
1819 update = alloca0_align(offsetof(struct kdbus_cmd_update, items) +
1820 ALIGN8(offsetof(struct kdbus_item, data64) + sizeof(uint64_t)),
1821 8);
1822
1823 n = update->items;
1824 n->type = KDBUS_ITEM_ATTACH_FLAGS_RECV;
1825 n->size = offsetof(struct kdbus_item, data64) + sizeof(uint64_t);
1826 n->data64[0] = bus->attach_flags;
1827
1828 update->size =
1829 offsetof(struct kdbus_cmd_update, items) +
1830 ALIGN8(n->size);
1831
1832 if (ioctl(bus->input_fd, KDBUS_CMD_CONN_UPDATE, update) < 0)
60f067b4 1833 return -errno;
60f067b4 1834
f47781d8
MP
1835 return 0;
1836}
60f067b4 1837
f47781d8
MP
1838int bus_kernel_fix_attach_mask(void) {
1839 _cleanup_free_ char *mask = NULL;
1840 uint64_t m = (uint64_t) -1;
1841 char buf[2+16+2];
1842 int r;
60f067b4 1843
f47781d8
MP
1844 /* By default we don't want any kdbus metadata fields to be
1845 * suppressed, hence we reset the kernel mask for it to
1846 * (uint64_t) -1. This is overridable via a kernel command
1847 * line option, however. */
60f067b4 1848
f47781d8
MP
1849 r = get_proc_cmdline_key("systemd.kdbus_attach_flags_mask=", &mask);
1850 if (r < 0)
1851 return log_warning_errno(r, "Failed to read kernel command line: %m");
1852
1853 if (mask) {
1854 const char *p = mask;
1855
1856 if (startswith(p, "0x"))
1857 p += 2;
1858
1859 if (sscanf(p, "%" PRIx64, &m) != 1)
1860 log_warning("Couldn't parse systemd.kdbus_attach_flags_mask= kernel command line parameter.");
60f067b4
JS
1861 }
1862
f47781d8
MP
1863 sprintf(buf, "0x%" PRIx64 "\n", m);
1864 r = write_string_file("/sys/module/kdbus/parameters/attach_flags_mask", buf);
1865 if (r < 0)
1866 return log_full_errno(
1867 IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r,
1868 "Failed to write kdbus attach mask: %m");
1869
1870 return 0;
60f067b4
JS
1871}
1872
f47781d8
MP
1873int bus_kernel_get_bus_name(sd_bus *bus, char **name) {
1874 struct kdbus_cmd_info cmd = {
1875 .size = sizeof(struct kdbus_cmd_info),
1876 };
1877 struct kdbus_info *info;
1878 struct kdbus_item *item;
1879 char *n = NULL;
1880 int r;
1881
60f067b4 1882 assert(bus);
f47781d8 1883 assert(name);
60f067b4
JS
1884 assert(bus->is_kernel);
1885
f47781d8
MP
1886 r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
1887 if (r < 0)
60f067b4
JS
1888 return -errno;
1889
f47781d8 1890 info = (struct kdbus_info*) ((uint8_t*) bus->kdbus_buffer + cmd.offset);
60f067b4 1891
f47781d8
MP
1892 KDBUS_ITEM_FOREACH(item, info, items)
1893 if (item->type == KDBUS_ITEM_MAKE_NAME) {
1894 r = free_and_strdup(&n, item->str);
1895 break;
1896 }
60f067b4 1897
f47781d8 1898 bus_kernel_cmd_free(bus, cmd.offset);
60f067b4 1899
f47781d8
MP
1900 if (r < 0)
1901 return r;
1902 if (!n)
1903 return -EIO;
60f067b4 1904
f47781d8 1905 *name = n;
60f067b4
JS
1906 return 0;
1907}