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