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