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