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