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