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