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