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