]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/bus-kernel.c
Revert "Revert "sd-bus: change serialization of kdbus messages to qualify in their...
[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
LP
31/* When we include libgen.h because we need dirname() we immediately
32 * undefine basename() since libgen.h defines it as a macro to the XDG
33 * version which is really broken. */
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
LP
41#include "cgroup-util.h"
42#include "fileio.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,
501 NULL,
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
LP
597
598 break;
599
600 case KDBUS_ITEM_CREDS:
601
2ac7c17f
LP
602 /* EUID/SUID/FSUID/EGID/SGID/FSGID might be
603 * missing too (see above). */
705a415f 604
fed1e721 605 if ((uid_t) d->creds.uid != UID_INVALID) {
705a415f
LP
606 m->creds.uid = (uid_t) d->creds.uid;
607 m->creds.mask |= SD_BUS_CREDS_UID & bus->creds_mask;
608 }
609
fed1e721 610 if ((uid_t) d->creds.euid != UID_INVALID) {
705a415f
LP
611 m->creds.euid = (uid_t) d->creds.euid;
612 m->creds.mask |= SD_BUS_CREDS_EUID & bus->creds_mask;
613 }
614
fed1e721 615 if ((uid_t) d->creds.suid != UID_INVALID) {
705a415f
LP
616 m->creds.suid = (uid_t) d->creds.suid;
617 m->creds.mask |= SD_BUS_CREDS_SUID & bus->creds_mask;
618 }
619
fed1e721 620 if ((uid_t) d->creds.fsuid != UID_INVALID) {
705a415f
LP
621 m->creds.fsuid = (uid_t) d->creds.fsuid;
622 m->creds.mask |= SD_BUS_CREDS_FSUID & bus->creds_mask;
623 }
624
fed1e721 625 if ((gid_t) d->creds.gid != GID_INVALID) {
705a415f
LP
626 m->creds.gid = (gid_t) d->creds.gid;
627 m->creds.mask |= SD_BUS_CREDS_GID & bus->creds_mask;
628 }
629
fed1e721 630 if ((gid_t) d->creds.egid != GID_INVALID) {
705a415f
LP
631 m->creds.egid = (gid_t) d->creds.egid;
632 m->creds.mask |= SD_BUS_CREDS_EGID & bus->creds_mask;
633 }
634
fed1e721 635 if ((gid_t) d->creds.sgid != GID_INVALID) {
705a415f
LP
636 m->creds.sgid = (gid_t) d->creds.sgid;
637 m->creds.mask |= SD_BUS_CREDS_SGID & bus->creds_mask;
638 }
639
fed1e721 640 if ((gid_t) d->creds.fsgid != GID_INVALID) {
705a415f
LP
641 m->creds.fsgid = (gid_t) d->creds.fsgid;
642 m->creds.mask |= SD_BUS_CREDS_FSGID & bus->creds_mask;
643 }
644
cb67f718 645 break;
6629161f 646
cb67f718 647 case KDBUS_ITEM_TIMESTAMP:
76877fb9 648 message_set_timestamp(bus, m, &d->timestamp);
cb67f718 649 break;
fd8d62d9 650
cb67f718
DM
651 case KDBUS_ITEM_PID_COMM:
652 m->creds.comm = d->str;
653 m->creds.mask |= SD_BUS_CREDS_COMM & bus->creds_mask;
654 break;
fd8d62d9 655
cb67f718
DM
656 case KDBUS_ITEM_TID_COMM:
657 m->creds.tid_comm = d->str;
658 m->creds.mask |= SD_BUS_CREDS_TID_COMM & bus->creds_mask;
659 break;
6629161f 660
cb67f718
DM
661 case KDBUS_ITEM_EXE:
662 m->creds.exe = d->str;
663 m->creds.mask |= SD_BUS_CREDS_EXE & bus->creds_mask;
664 break;
6629161f 665
cb67f718
DM
666 case KDBUS_ITEM_CMDLINE:
667 m->creds.cmdline = d->str;
668 m->creds.cmdline_size = l;
669 m->creds.mask |= SD_BUS_CREDS_CMDLINE & bus->creds_mask;
670 break;
777d7a61 671
cb67f718
DM
672 case KDBUS_ITEM_CGROUP:
673 m->creds.cgroup = d->str;
674 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 675
fe3f22d1
DK
676 r = bus_get_root_path(bus);
677 if (r < 0)
678 goto fail;
777d7a61 679
cb67f718 680 m->creds.cgroup_root = bus->cgroup_root;
cb67f718 681 break;
777d7a61 682
cb67f718 683 case KDBUS_ITEM_AUDIT:
6dfcc64b
LP
684 if ((uint32_t) d->audit.sessionid != (uint32_t) -1) {
685 m->creds.audit_session_id = (uint32_t) d->audit.sessionid;
686 m->creds.mask |= SD_BUS_CREDS_AUDIT_SESSION_ID & bus->creds_mask;
687 }
688
fed1e721 689 if ((uid_t) d->audit.loginuid != UID_INVALID) {
6dfcc64b
LP
690 m->creds.audit_login_uid = (uid_t) d->audit.loginuid;
691 m->creds.mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID & bus->creds_mask;
692 }
cb67f718 693 break;
777d7a61 694
cb67f718 695 case KDBUS_ITEM_CAPS:
34a5d5e5
DH
696 if (d->caps.last_cap != cap_last_cap() ||
697 d->size - offsetof(struct kdbus_item, caps.caps) < DIV_ROUND_UP(d->caps.last_cap, 32U) * 4 * 4) {
698 r = -EBADMSG;
699 goto fail;
700 }
701
7d9fcc2b 702 m->creds.capability = d->caps.caps;
cb67f718
DM
703 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;
704 break;
219728b3 705
cb67f718 706 case KDBUS_ITEM_DST_NAME:
9f6dfd06
LP
707 if (!service_name_is_valid(d->str)) {
708 r = -EBADMSG;
709 goto fail;
710 }
219728b3 711
cb67f718
DM
712 destination = d->str;
713 break;
777d7a61 714
635f9f0d 715 case KDBUS_ITEM_OWNED_NAME:
9f6dfd06
LP
716 if (!service_name_is_valid(d->name.name)) {
717 r = -EBADMSG;
cb67f718 718 goto fail;
9f6dfd06
LP
719 }
720
721 if (bus->creds_mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
50c45216
LP
722 char **wkn;
723 size_t n;
724
725 /* We just extend the array here, but
726 * do not allocate the strings inside
727 * of it, instead we just point to our
728 * buffer directly. */
729 n = strv_length(m->creds.well_known_names);
730 wkn = realloc(m->creds.well_known_names, (n + 2) * sizeof(char*));
731 if (!wkn) {
732 r = -ENOMEM;
9f6dfd06 733 goto fail;
50c45216
LP
734 }
735
736 wkn[n] = d->name.name;
737 wkn[n+1] = NULL;
738 m->creds.well_known_names = wkn;
9f6dfd06
LP
739
740 m->creds.mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
741 }
cb67f718 742 break;
777d7a61 743
635f9f0d 744 case KDBUS_ITEM_CONN_DESCRIPTION:
455971c1
LP
745 m->creds.description = d->str;
746 m->creds.mask |= SD_BUS_CREDS_DESCRIPTION & bus->creds_mask;
cccb0b2c
LP
747 break;
748
02581590
LP
749 case KDBUS_ITEM_AUXGROUPS:
750
751 if (bus->creds_mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
e12d81ae 752 assert_cc(sizeof(gid_t) == sizeof(uint32_t));
02581590 753
e12d81ae
LP
754 m->creds.n_supplementary_gids = (d->size - offsetof(struct kdbus_item, data32)) / sizeof(uint32_t);
755 m->creds.supplementary_gids = (gid_t*) d->data32;
02581590
LP
756 m->creds.mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
757 }
758
759 break;
760
cb67f718
DM
761 case KDBUS_ITEM_FDS:
762 case KDBUS_ITEM_SECLABEL:
763 break;
d78bf250 764
cb67f718
DM
765 default:
766 log_debug("Got unknown field from kernel %llu", d->type);
767 }
768 }
d78bf250 769
38ce47e2
LP
770 /* If we requested the list of well-known names to be appended
771 * and the sender had none no item for it will be
315a73d9 772 * attached. However, this does *not* mean that the kernel
38ce47e2
LP
773 * didn't want to provide this information to us. Hence, let's
774 * explicitly mark this information as available if it was
775 * requested. */
776 m->creds.mask |= bus->creds_mask & SD_BUS_CREDS_WELL_KNOWN_NAMES;
777
cb67f718
DM
778 r = bus_message_parse_fields(m);
779 if (r < 0)
780 goto fail;
777d7a61 781
7fa934b0 782 /* Refuse messages if kdbus and dbus1 cookie doesn't match up */
2ac7c17f 783 if ((uint64_t) m->header->dbus2.cookie != k->cookie) {
7fa934b0
LP
784 r = -EBADMSG;
785 goto fail;
786 }
787
788 /* Refuse messages where the reply flag doesn't match up */
94e15fdc 789 if (!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) != !!(k->flags & KDBUS_MSG_EXPECT_REPLY)) {
7fa934b0
LP
790 r = -EBADMSG;
791 goto fail;
792 }
793
794 /* Refuse reply messages where the reply cookie doesn't match up */
795 if ((m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) && m->reply_cookie != k->cookie_reply) {
796 r = -EBADMSG;
797 goto fail;
798 }
799
800 /* Refuse messages where the autostart flag doesn't match up */
94e15fdc 801 if (!(m->header->flags & BUS_MESSAGE_NO_AUTO_START) != !(k->flags & KDBUS_MSG_NO_AUTO_START)) {
7fa934b0
LP
802 r = -EBADMSG;
803 goto fail;
804 }
805
cb67f718 806 /* Override information from the user header with data from the kernel */
7d31d924
LP
807 if (k->src_id == KDBUS_SRC_ID_KERNEL)
808 bus_message_set_sender_driver(bus, m);
809 else {
cb67f718
DM
810 snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
811 m->sender = m->creds.unique_name = m->sender_buffer;
812 }
777d7a61 813
cb67f718
DM
814 if (destination)
815 m->destination = destination;
816 else if (k->dst_id == KDBUS_DST_ID_BROADCAST)
817 m->destination = NULL;
818 else if (k->dst_id == KDBUS_DST_ID_NAME)
819 m->destination = bus->unique_name; /* fill in unique name if the well-known name is missing */
820 else {
821 snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
822 m->destination = m->destination_buffer;
823 }
777d7a61 824
cb67f718
DM
825 /* We take possession of the kmsg struct now */
826 m->kdbus = k;
827 m->release_kdbus = true;
828 m->free_fds = true;
829 fds = NULL;
777d7a61 830
cb67f718 831 bus->rqueue[bus->rqueue_size++] = m;
777d7a61 832
cb67f718 833 return 1;
777d7a61 834
cb67f718 835fail:
125dd074
ZJS
836 unset_memfds(m);
837 sd_bus_message_unref(m);
777d7a61 838
cb67f718
DM
839 return r;
840}
777d7a61 841
cb67f718 842int bus_kernel_take_fd(sd_bus *b) {
d31f486b 843 struct kdbus_bloom_parameter *bloom = NULL;
cb67f718 844 struct kdbus_cmd_hello *hello;
d31f486b 845 struct kdbus_item_list *items;
cb67f718 846 struct kdbus_item *item;
5972fe95
LP
847 _cleanup_free_ char *g = NULL;
848 const char *name;
849 size_t l = 0, m = 0, sz;
cb67f718 850 int r;
777d7a61 851
cb67f718 852 assert(b);
7adc46fc 853
cb67f718
DM
854 if (b->is_server)
855 return -EINVAL;
777d7a61 856
cb67f718 857 b->use_memfd = 1;
777d7a61 858
455971c1
LP
859 if (b->description) {
860 g = bus_label_escape(b->description);
5972fe95
LP
861 if (!g)
862 return -ENOMEM;
863
864 name = g;
865 } else {
866 char pr[17] = {};
867
868 /* If no name is explicitly set, we'll include a hint
869 * indicating the library implementation, a hint which
870 * kind of bus this is and the thread name */
871
872 assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0);
873
874 if (isempty(pr)) {
875 name = b->is_system ? "sd-system" :
876 b->is_user ? "sd-user" : "sd";
877 } else {
878 _cleanup_free_ char *e = NULL;
879
a6278b88 880 e = bus_label_escape(pr);
5972fe95
LP
881 if (!e)
882 return -ENOMEM;
883
884 g = strappend(b->is_system ? "sd-system-" :
885 b->is_user ? "sd-user-" : "sd-",
886 e);
887 if (!g)
888 return -ENOMEM;
889
890 name = g;
891 }
892
455971c1
LP
893 b->description = bus_label_unescape(name);
894 if (!b->description)
5972fe95
LP
895 return -ENOMEM;
896 }
897
898 m = strlen(name);
899
900 sz = ALIGN8(offsetof(struct kdbus_cmd_hello, items)) +
901 ALIGN8(offsetof(struct kdbus_item, str) + m + 1);
777d7a61 902
cb67f718 903 if (b->fake_creds_valid)
5972fe95 904 sz += ALIGN8(offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds));
777d7a61 905
705a415f
LP
906 if (b->fake_pids_valid)
907 sz += ALIGN8(offsetof(struct kdbus_item, pids) + sizeof(struct kdbus_pids));
908
cb67f718
DM
909 if (b->fake_label) {
910 l = strlen(b->fake_label);
911 sz += ALIGN8(offsetof(struct kdbus_item, str) + l + 1);
912 }
777d7a61 913
7f3d3ba1 914 hello = alloca0_align(sz, 8);
cb67f718 915 hello->size = sz;
bc75205c 916 hello->flags = b->hello_flags;
6f5c810a 917 hello->attach_flags_send = _KDBUS_ATTACH_ANY;
d704fda9 918 hello->attach_flags_recv = b->attach_flags;
cb67f718 919 hello->pool_size = KDBUS_POOL_SIZE;
777d7a61 920
cb67f718
DM
921 item = hello->items;
922
5972fe95 923 item->size = offsetof(struct kdbus_item, str) + m + 1;
635f9f0d 924 item->type = KDBUS_ITEM_CONN_DESCRIPTION;
5972fe95
LP
925 memcpy(item->str, name, m + 1);
926 item = KDBUS_ITEM_NEXT(item);
927
cb67f718
DM
928 if (b->fake_creds_valid) {
929 item->size = offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds);
930 item->type = KDBUS_ITEM_CREDS;
931 item->creds = b->fake_creds;
932
933 item = KDBUS_ITEM_NEXT(item);
777d7a61
LP
934 }
935
705a415f
LP
936 if (b->fake_pids_valid) {
937 item->size = offsetof(struct kdbus_item, pids) + sizeof(struct kdbus_pids);
938 item->type = KDBUS_ITEM_PIDS;
939 item->pids = b->fake_pids;
940
941 item = KDBUS_ITEM_NEXT(item);
942 }
943
cb67f718
DM
944 if (b->fake_label) {
945 item->size = offsetof(struct kdbus_item, str) + l + 1;
5972fe95 946 item->type = KDBUS_ITEM_SECLABEL;
cb67f718 947 memcpy(item->str, b->fake_label, l+1);
777d7a61
LP
948 }
949
cb67f718
DM
950 r = ioctl(b->input_fd, KDBUS_CMD_HELLO, hello);
951 if (r < 0)
952 return -errno;
777d7a61 953
cb67f718
DM
954 if (!b->kdbus_buffer) {
955 b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, b->input_fd, 0);
956 if (b->kdbus_buffer == MAP_FAILED) {
957 b->kdbus_buffer = NULL;
d31f486b
DH
958 r = -errno;
959 goto fail;
cb67f718
DM
960 }
961 }
6629161f 962
4a3e79e1 963 /* The higher 32bit of the bus_flags fields are considered
cb67f718 964 * 'incompatible flags'. Refuse them all for now. */
d31f486b
DH
965 if (hello->bus_flags > 0xFFFFFFFFULL) {
966 r = -ENOTSUP;
967 goto fail;
968 }
6629161f 969
d31f486b
DH
970 /* extract bloom parameters from items */
971 items = (void*)((uint8_t*)b->kdbus_buffer + hello->offset);
972 KDBUS_ITEM_FOREACH(item, items, items) {
973 switch (item->type) {
974 case KDBUS_ITEM_BLOOM_PARAMETER:
975 bloom = &item->bloom_parameter;
976 break;
977 }
978 }
6629161f 979
d31f486b
DH
980 if (!bloom || !bloom_validate_parameters((size_t) bloom->size, (unsigned) bloom->n_hash)) {
981 r = -ENOTSUP;
982 goto fail;
983 }
b28ff39f 984
d31f486b
DH
985 b->bloom_size = (size_t) bloom->size;
986 b->bloom_n_hash = (unsigned) bloom->n_hash;
987
988 if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello->id) < 0) {
989 r = -ENOMEM;
990 goto fail;
991 }
6629161f 992
cb67f718 993 b->unique_id = hello->id;
6629161f 994
cb67f718
DM
995 b->is_kernel = true;
996 b->bus_client = true;
bc75205c 997 b->can_fds = !!(hello->flags & KDBUS_HELLO_ACCEPT_FD);
cb67f718
DM
998 b->message_version = 2;
999 b->message_endian = BUS_NATIVE_ENDIAN;
c91cb83c 1000
cb67f718
DM
1001 /* the kernel told us the UUID of the underlying bus */
1002 memcpy(b->server_id.bytes, hello->id128, sizeof(b->server_id.bytes));
6629161f 1003
d31f486b
DH
1004 /* free returned items */
1005 (void) bus_kernel_cmd_free(b, hello->offset);
cb67f718 1006 return bus_start_running(b);
d31f486b
DH
1007
1008fail:
72e61104 1009 (void) bus_kernel_cmd_free(b, hello->offset);
d31f486b 1010 return r;
cb67f718 1011}
6629161f 1012
cb67f718
DM
1013int bus_kernel_connect(sd_bus *b) {
1014 assert(b);
1015 assert(b->input_fd < 0);
1016 assert(b->output_fd < 0);
1017 assert(b->kernel);
1307c3ff 1018
cb67f718
DM
1019 if (b->is_server)
1020 return -EINVAL;
1307c3ff 1021
cb67f718
DM
1022 b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
1023 if (b->input_fd < 0)
1024 return -errno;
6629161f 1025
cb67f718 1026 b->output_fd = b->input_fd;
6629161f 1027
cb67f718
DM
1028 return bus_kernel_take_fd(b);
1029}
f9be01f3 1030
52cfc037
LP
1031int bus_kernel_cmd_free(sd_bus *bus, uint64_t offset) {
1032 struct kdbus_cmd_free cmd = {
d31f486b 1033 .size = sizeof(cmd),
52cfc037
LP
1034 .offset = offset,
1035 };
1036 int r;
1037
1038 assert(bus);
1039 assert(bus->is_kernel);
1040
1041 r = ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd);
1042 if (r < 0)
1043 return -errno;
1044
1045 return 0;
1046}
1047
069f5e61 1048static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
069f5e61
LP
1049 struct kdbus_item *d;
1050
1051 assert(bus);
1052 assert(k);
1053
069f5e61 1054 KDBUS_ITEM_FOREACH(d, k, items) {
069f5e61
LP
1055 if (d->type == KDBUS_ITEM_FDS)
1056 close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
1057 else if (d->type == KDBUS_ITEM_PAYLOAD_MEMFD)
03e334a1 1058 safe_close(d->memfd.fd);
069f5e61 1059 }
ca794c8e 1060
52cfc037 1061 bus_kernel_cmd_free(bus, (uint8_t*) k - (uint8_t*) bus->kdbus_buffer);
069f5e61
LP
1062}
1063
1064int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call) {
94e15fdc 1065 struct kdbus_cmd_send cmd = { };
cb67f718 1066 int r;
6629161f 1067
cb67f718
DM
1068 assert(bus);
1069 assert(m);
1070 assert(bus->state == BUS_RUNNING);
6629161f 1071
cb67f718
DM
1072 /* If we can't deliver, we want room for the error message */
1073 r = bus_rqueue_make_room(bus);
6629161f
LP
1074 if (r < 0)
1075 return r;
1076
cb67f718 1077 r = bus_message_setup_kmsg(bus, m);
6629161f
LP
1078 if (r < 0)
1079 return r;
1080
94e15fdc
DH
1081 cmd.size = sizeof(cmd);
1082 cmd.msg_address = (uintptr_t)m->kdbus;
1083
069f5e61
LP
1084 /* If this is a synchronous method call, then let's tell the
1085 * kernel, so that it can pass CPU time/scheduling to the
1086 * destination for the time, if it wants to. If we
1087 * synchronously wait for the result anyway, we won't need CPU
1088 * anyway. */
94e15fdc
DH
1089 if (hint_sync_call) {
1090 m->kdbus->flags |= KDBUS_MSG_EXPECT_REPLY;
1091 cmd.flags |= KDBUS_SEND_SYNC_REPLY;
1092 }
069f5e61 1093
94e15fdc 1094 r = ioctl(bus->output_fd, KDBUS_CMD_SEND, &cmd);
cb67f718
DM
1095 if (r < 0) {
1096 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1097 sd_bus_message *reply;
253ce82b 1098
cb67f718
DM
1099 if (errno == EAGAIN || errno == EINTR)
1100 return 0;
1101 else if (errno == ENXIO || errno == ESRCH) {
6629161f 1102
cb67f718
DM
1103 /* ENXIO: unique name not known
1104 * ESRCH: well-known name not known */
6629161f 1105
cb67f718
DM
1106 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1107 sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Destination %s not known", m->destination);
1108 else {
1109 log_debug("Could not deliver message to %s as destination is not known. Ignoring.", m->destination);
1110 return 0;
1111 }
777d7a61 1112
cb67f718 1113 } else if (errno == EADDRNOTAVAIL) {
fd8d62d9 1114
cb67f718 1115 /* EADDRNOTAVAIL: activation is possible, but turned off in request flags */
bc7fd8cd 1116
cb67f718
DM
1117 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1118 sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Activation of %s not requested", m->destination);
1119 else {
1120 log_debug("Could not deliver message to %s as destination is not activated. Ignoring.", m->destination);
1121 return 0;
1122 }
1123 } else
1124 return -errno;
bc7fd8cd 1125
cb67f718
DM
1126 r = bus_message_new_synthetic_error(
1127 bus,
1128 BUS_MESSAGE_COOKIE(m),
1129 &error,
1130 &reply);
bc7fd8cd 1131
cb67f718
DM
1132 if (r < 0)
1133 return r;
bc7fd8cd 1134
cb67f718
DM
1135 r = bus_seal_synthetic_message(bus, reply);
1136 if (r < 0)
1137 return r;
62b3e928 1138
cb67f718 1139 bus->rqueue[bus->rqueue_size++] = reply;
bc7fd8cd 1140
069f5e61
LP
1141 } else if (hint_sync_call) {
1142 struct kdbus_msg *k;
fd8d62d9 1143
94e15fdc 1144 k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + cmd.reply.offset);
069f5e61 1145 assert(k);
777d7a61 1146
069f5e61 1147 if (k->payload_type == KDBUS_PAYLOAD_DBUS) {
1307c3ff 1148
069f5e61
LP
1149 r = bus_kernel_make_message(bus, k);
1150 if (r < 0) {
1151 close_kdbus_msg(bus, k);
1307c3ff 1152
069f5e61
LP
1153 /* Anybody can send us invalid messages, let's just drop them. */
1154 if (r == -EBADMSG || r == -EPROTOTYPE)
da927ba9 1155 log_debug_errno(r, "Ignoring invalid message: %m");
069f5e61
LP
1156 else
1157 return r;
1158 }
1159 } else {
1160 log_debug("Ignoring message with unknown payload type %llu.", (unsigned long long) k->payload_type);
1161 close_kdbus_msg(bus, k);
1162 }
cb67f718 1163 }
069f5e61
LP
1164
1165 return 1;
cb67f718 1166}
69aec65c 1167
76877fb9
LP
1168static int push_name_owner_changed(
1169 sd_bus *bus,
1170 const char *name,
1171 const char *old_owner,
1172 const char *new_owner,
1173 const struct kdbus_timestamp *ts) {
1174
cb67f718
DM
1175 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1176 int r;
2dc9970b 1177
cb67f718 1178 assert(bus);
2dc9970b 1179
cb67f718
DM
1180 r = sd_bus_message_new_signal(
1181 bus,
151b9b96 1182 &m,
cb67f718
DM
1183 "/org/freedesktop/DBus",
1184 "org.freedesktop.DBus",
151b9b96 1185 "NameOwnerChanged");
cb67f718
DM
1186 if (r < 0)
1187 return r;
2dc9970b 1188
cb67f718
DM
1189 r = sd_bus_message_append(m, "sss", name, old_owner, new_owner);
1190 if (r < 0)
1191 return r;
5b12334d 1192
7d31d924 1193 bus_message_set_sender_driver(bus, m);
76877fb9 1194 message_set_timestamp(bus, m, ts);
5b12334d 1195
cb67f718
DM
1196 r = bus_seal_synthetic_message(bus, m);
1197 if (r < 0)
1198 return r;
5b12334d 1199
cb67f718
DM
1200 bus->rqueue[bus->rqueue_size++] = m;
1201 m = NULL;
5b12334d 1202
cb67f718
DM
1203 return 1;
1204}
5b12334d 1205
76877fb9
LP
1206static int translate_name_change(
1207 sd_bus *bus,
1208 const struct kdbus_msg *k,
1209 const struct kdbus_item *d,
1210 const struct kdbus_timestamp *ts) {
1211
cb67f718 1212 char new_owner[UNIQUE_NAME_MAX], old_owner[UNIQUE_NAME_MAX];
5b12334d 1213
cb67f718
DM
1214 assert(bus);
1215 assert(k);
1216 assert(d);
751bc6ac 1217
619d7a03 1218 if (d->type == KDBUS_ITEM_NAME_ADD || (d->name_change.old_id.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR)))
cb67f718
DM
1219 old_owner[0] = 0;
1220 else
619d7a03 1221 sprintf(old_owner, ":1.%llu", (unsigned long long) d->name_change.old_id.id);
751bc6ac 1222
619d7a03 1223 if (d->type == KDBUS_ITEM_NAME_REMOVE || (d->name_change.new_id.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR))) {
751bc6ac 1224
cb67f718
DM
1225 if (isempty(old_owner))
1226 return 0;
5b12334d 1227
cb67f718
DM
1228 new_owner[0] = 0;
1229 } else
619d7a03 1230 sprintf(new_owner, ":1.%llu", (unsigned long long) d->name_change.new_id.id);
5b12334d 1231
76877fb9 1232 return push_name_owner_changed(bus, d->name_change.name, old_owner, new_owner, ts);
cb67f718 1233}
5b12334d 1234
76877fb9
LP
1235static int translate_id_change(
1236 sd_bus *bus,
1237 const struct kdbus_msg *k,
1238 const struct kdbus_item *d,
1239 const struct kdbus_timestamp *ts) {
1240
cb67f718 1241 char owner[UNIQUE_NAME_MAX];
2e2ec0ea 1242
cb67f718
DM
1243 assert(bus);
1244 assert(k);
1245 assert(d);
777d7a61 1246
cb67f718 1247 sprintf(owner, ":1.%llu", d->id_change.id);
2e2ec0ea 1248
cb67f718
DM
1249 return push_name_owner_changed(
1250 bus, owner,
1251 d->type == KDBUS_ITEM_ID_ADD ? NULL : owner,
76877fb9
LP
1252 d->type == KDBUS_ITEM_ID_ADD ? owner : NULL,
1253 ts);
cb67f718 1254}
49b832c5 1255
76877fb9
LP
1256static int translate_reply(
1257 sd_bus *bus,
1258 const struct kdbus_msg *k,
1259 const struct kdbus_item *d,
1260 const struct kdbus_timestamp *ts) {
1261
cb67f718
DM
1262 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1263 int r;
777d7a61 1264
cb67f718
DM
1265 assert(bus);
1266 assert(k);
1267 assert(d);
acb5a3cb 1268
cb67f718
DM
1269 r = bus_message_new_synthetic_error(
1270 bus,
1271 k->cookie_reply,
1272 d->type == KDBUS_ITEM_REPLY_TIMEOUT ?
1273 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call timed out") :
1274 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call peer died"),
1275 &m);
1307c3ff 1276 if (r < 0)
cb67f718 1277 return r;
51038c03 1278
76877fb9 1279 message_set_timestamp(bus, m, ts);
51038c03 1280
cb67f718
DM
1281 r = bus_seal_synthetic_message(bus, m);
1282 if (r < 0)
1283 return r;
6629161f 1284
7adc46fc 1285 bus->rqueue[bus->rqueue_size++] = m;
cb67f718 1286 m = NULL;
7d22c717 1287
6629161f 1288 return 1;
cb67f718 1289}
1307c3ff 1290
cb67f718 1291static int bus_kernel_translate_message(sd_bus *bus, struct kdbus_msg *k) {
76877fb9 1292 static int (* const translate[])(sd_bus *bus, const struct kdbus_msg *k, const struct kdbus_item *d, const struct kdbus_timestamp *ts) = {
cb67f718
DM
1293 [KDBUS_ITEM_NAME_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
1294 [KDBUS_ITEM_NAME_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
1295 [KDBUS_ITEM_NAME_CHANGE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
1307c3ff 1296
cb67f718
DM
1297 [KDBUS_ITEM_ID_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
1298 [KDBUS_ITEM_ID_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
1299
1300 [KDBUS_ITEM_REPLY_TIMEOUT - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
1301 [KDBUS_ITEM_REPLY_DEAD - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
1302 };
1303
76877fb9
LP
1304 struct kdbus_item *d, *found = NULL;
1305 struct kdbus_timestamp *ts = NULL;
1306
cb67f718
DM
1307 assert(bus);
1308 assert(k);
1309 assert(k->payload_type == KDBUS_PAYLOAD_KERNEL);
1310
1311 KDBUS_ITEM_FOREACH(d, k, items) {
856d6e09 1312 if (d->type == KDBUS_ITEM_TIMESTAMP)
76877fb9 1313 ts = &d->timestamp;
856d6e09 1314
cb67f718
DM
1315 if (d->type >= _KDBUS_ITEM_KERNEL_BASE && d->type < _KDBUS_ITEM_KERNEL_BASE + ELEMENTSOF(translate)) {
1316 if (found)
1317 return -EBADMSG;
1318 found = d;
1319 } else
1320 log_debug("Got unknown field from kernel %llu", d->type);
1307c3ff
LP
1321 }
1322
cb67f718
DM
1323 if (!found) {
1324 log_debug("Didn't find a kernel message to translate.");
1325 return 0;
1326 }
1327
76877fb9 1328 return translate[found->type - _KDBUS_ITEM_KERNEL_BASE](bus, k, found, ts);
6629161f
LP
1329}
1330
766c5809 1331int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority) {
94e15fdc 1332 struct kdbus_cmd_recv recv = { .size = sizeof(recv) };
6629161f 1333 struct kdbus_msg *k;
6629161f
LP
1334 int r;
1335
1336 assert(bus);
7d22c717 1337
7adc46fc 1338 r = bus_rqueue_make_room(bus);
7d22c717
LP
1339 if (r < 0)
1340 return r;
6629161f 1341
766c5809
LP
1342 if (hint_priority) {
1343 recv.flags |= KDBUS_RECV_USE_PRIORITY;
1344 recv.priority = priority;
1345 }
1346
94e15fdc 1347 r = ioctl(bus->input_fd, KDBUS_CMD_RECV, &recv);
fd8d62d9 1348 if (r < 0) {
6629161f
LP
1349 if (errno == EAGAIN)
1350 return 0;
1351
f9a458c6
LP
1352 if (errno == EOVERFLOW) {
1353 log_debug("%s: kdbus reports %" PRIu64 " dropped broadcast messages, ignoring.", strna(bus->description), (uint64_t) recv.dropped_msgs);
1354 return 0;
1355 }
1356
fd8d62d9 1357 return -errno;
6629161f
LP
1358 }
1359
a9c8343e 1360 k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + recv.msg.offset);
e1d337d4 1361 if (k->payload_type == KDBUS_PAYLOAD_DBUS) {
7d22c717 1362 r = bus_kernel_make_message(bus, k);
e1d337d4
LP
1363
1364 /* Anybody can send us invalid messages, let's just drop them. */
1365 if (r == -EBADMSG || r == -EPROTOTYPE) {
da927ba9 1366 log_debug_errno(r, "Ignoring invalid message: %m");
e1d337d4
LP
1367 r = 0;
1368 }
1369
1370 } else if (k->payload_type == KDBUS_PAYLOAD_KERNEL)
7d22c717 1371 r = bus_kernel_translate_message(bus, k);
069f5e61
LP
1372 else {
1373 log_debug("Ignoring message with unknown payload type %llu.", (unsigned long long) k->payload_type);
777d7a61 1374 r = 0;
069f5e61 1375 }
777d7a61 1376
fd8d62d9
LP
1377 if (r <= 0)
1378 close_kdbus_msg(bus, k);
6629161f 1379
51038c03 1380 return r < 0 ? r : 1;
6629161f
LP
1381}
1382
8e959fbf 1383int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *allocated) {
bc7fd8cd 1384 struct memfd_cache *c;
45fbe937 1385 int fd;
bc7fd8cd
LP
1386
1387 assert(address);
8e959fbf
LP
1388 assert(mapped);
1389 assert(allocated);
35460afc
LP
1390
1391 if (!bus || !bus->is_kernel)
1392 return -ENOTSUP;
bc7fd8cd 1393
76b7742c 1394 assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
45fbe937 1395
bc7fd8cd 1396 if (bus->n_memfd_cache <= 0) {
45fbe937
LP
1397 int r;
1398
76b7742c 1399 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
bc7fd8cd 1400
455971c1 1401 r = memfd_new(bus->description);
9b05bc48 1402 if (r < 0)
73843b52 1403 return r;
bc7fd8cd
LP
1404
1405 *address = NULL;
8e959fbf
LP
1406 *mapped = 0;
1407 *allocated = 0;
a6082d77 1408 return r;
bc7fd8cd
LP
1409 }
1410
bf30e48f 1411 c = &bus->memfd_cache[--bus->n_memfd_cache];
bc7fd8cd
LP
1412
1413 assert(c->fd >= 0);
8e959fbf 1414 assert(c->mapped == 0 || c->address);
bc7fd8cd
LP
1415
1416 *address = c->address;
8e959fbf
LP
1417 *mapped = c->mapped;
1418 *allocated = c->allocated;
45fbe937
LP
1419 fd = c->fd;
1420
76b7742c 1421 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
bc7fd8cd 1422
45fbe937
LP
1423 return fd;
1424}
1425
1426static void close_and_munmap(int fd, void *address, size_t size) {
1427 if (size > 0)
76b7742c 1428 assert_se(munmap(address, PAGE_ALIGN(size)) >= 0);
45fbe937 1429
03e334a1 1430 safe_close(fd);
bc7fd8cd
LP
1431}
1432
8e959fbf 1433void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t mapped, size_t allocated) {
bc7fd8cd 1434 struct memfd_cache *c;
8e959fbf 1435 uint64_t max_mapped = PAGE_ALIGN(MEMFD_CACHE_ITEM_SIZE_MAX);
bc7fd8cd
LP
1436
1437 assert(fd >= 0);
8e959fbf 1438 assert(mapped == 0 || address);
bc7fd8cd 1439
45fbe937 1440 if (!bus || !bus->is_kernel) {
8e959fbf 1441 close_and_munmap(fd, address, mapped);
45fbe937
LP
1442 return;
1443 }
1444
76b7742c 1445 assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
bc7fd8cd 1446
45fbe937 1447 if (bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
76b7742c 1448 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
bc7fd8cd 1449
8e959fbf 1450 close_and_munmap(fd, address, mapped);
bc7fd8cd
LP
1451 return;
1452 }
1453
1454 c = &bus->memfd_cache[bus->n_memfd_cache++];
1455 c->fd = fd;
1456 c->address = address;
1457
1458 /* If overly long, let's return a bit to the OS */
8e959fbf 1459 if (mapped > max_mapped) {
73843b52 1460 assert_se(memfd_set_size(fd, max_mapped) >= 0);
8e959fbf
LP
1461 assert_se(munmap((uint8_t*) address + max_mapped, PAGE_ALIGN(mapped - max_mapped)) >= 0);
1462 c->mapped = c->allocated = max_mapped;
1463 } else {
1464 c->mapped = mapped;
1465 c->allocated = allocated;
1466 }
45fbe937 1467
76b7742c 1468 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
bc7fd8cd
LP
1469}
1470
1471void bus_kernel_flush_memfd(sd_bus *b) {
1472 unsigned i;
1473
1474 assert(b);
1475
76b7742c 1476 for (i = 0; i < b->n_memfd_cache; i++)
8e959fbf 1477 close_and_munmap(b->memfd_cache[i].fd, b->memfd_cache[i].address, b->memfd_cache[i].mapped);
bc7fd8cd 1478}
0253ddcc 1479
b5dae4c7 1480uint64_t request_name_flags_to_kdbus(uint64_t flags) {
e3dd987c 1481 uint64_t f = 0;
0253ddcc 1482
e3dd987c
LP
1483 if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
1484 f |= KDBUS_NAME_ALLOW_REPLACEMENT;
0253ddcc 1485
e3dd987c
LP
1486 if (flags & SD_BUS_NAME_REPLACE_EXISTING)
1487 f |= KDBUS_NAME_REPLACE_EXISTING;
0253ddcc 1488
d90bb669 1489 if (flags & SD_BUS_NAME_QUEUE)
e3dd987c 1490 f |= KDBUS_NAME_QUEUE;
0253ddcc 1491
b5dae4c7 1492 return f;
e3dd987c
LP
1493}
1494
b5dae4c7 1495uint64_t attach_flags_to_kdbus(uint64_t mask) {
e3dd987c
LP
1496 uint64_t m = 0;
1497
705a415f
LP
1498 if (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
1499 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID))
e3dd987c
LP
1500 m |= KDBUS_ATTACH_CREDS;
1501
32802361 1502 if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_TID))
705a415f
LP
1503 m |= KDBUS_ATTACH_PIDS;
1504
a2243d54
DM
1505 if (mask & SD_BUS_CREDS_COMM)
1506 m |= KDBUS_ATTACH_PID_COMM;
1507
1508 if (mask & SD_BUS_CREDS_TID_COMM)
1509 m |= KDBUS_ATTACH_TID_COMM;
e3dd987c
LP
1510
1511 if (mask & SD_BUS_CREDS_EXE)
1512 m |= KDBUS_ATTACH_EXE;
1513
1514 if (mask & SD_BUS_CREDS_CMDLINE)
1515 m |= KDBUS_ATTACH_CMDLINE;
1516
1517 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))
1518 m |= KDBUS_ATTACH_CGROUP;
1519
1520 if (mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS))
1521 m |= KDBUS_ATTACH_CAPS;
1522
1523 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT)
1524 m |= KDBUS_ATTACH_SECLABEL;
0253ddcc 1525
e3dd987c
LP
1526 if (mask & (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID))
1527 m |= KDBUS_ATTACH_AUDIT;
1528
49b832c5
LP
1529 if (mask & SD_BUS_CREDS_WELL_KNOWN_NAMES)
1530 m |= KDBUS_ATTACH_NAMES;
1531
455971c1 1532 if (mask & SD_BUS_CREDS_DESCRIPTION)
635f9f0d 1533 m |= KDBUS_ATTACH_CONN_DESCRIPTION;
cccb0b2c 1534
02581590
LP
1535 if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS)
1536 m |= KDBUS_ATTACH_AUXGROUPS;
1537
b5dae4c7 1538 return m;
0253ddcc 1539}
e3dd987c 1540
f2769777 1541int bus_kernel_create_bus(const char *name, bool world, char **s) {
b2086f60 1542 struct kdbus_cmd *make;
e3dd987c 1543 struct kdbus_item *n;
fa7796e9 1544 size_t l;
e3dd987c
LP
1545 int fd;
1546
1547 assert(name);
1548 assert(s);
1549
63cc4c31 1550 fd = open("/sys/fs/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
e3dd987c
LP
1551 if (fd < 0)
1552 return -errno;
1553
fa7796e9 1554 l = strlen(name);
b2086f60 1555 make = alloca0_align(offsetof(struct kdbus_cmd, items) +
fa7796e9
LP
1556 ALIGN8(offsetof(struct kdbus_item, bloom_parameter) + sizeof(struct kdbus_bloom_parameter)) +
1557 ALIGN8(offsetof(struct kdbus_item, data64) + sizeof(uint64_t)) +
19ee32dc 1558 ALIGN8(offsetof(struct kdbus_item, data64) + sizeof(uint64_t)) +
fa7796e9 1559 ALIGN8(offsetof(struct kdbus_item, str) + DECIMAL_STR_MAX(uid_t) + 1 + l + 1),
7f3d3ba1 1560 8);
e3dd987c 1561
b2086f60 1562 make->size = offsetof(struct kdbus_cmd, items);
816a3f9e 1563
fa7796e9 1564 /* Set the bloom parameters */
e3dd987c 1565 n = make->items;
18a28147
KS
1566 n->size = offsetof(struct kdbus_item, bloom_parameter) +
1567 sizeof(struct kdbus_bloom_parameter);
1568 n->type = KDBUS_ITEM_BLOOM_PARAMETER;
b28ff39f
LP
1569 n->bloom_parameter.size = DEFAULT_BLOOM_SIZE;
1570 n->bloom_parameter.n_hash = DEFAULT_BLOOM_N_HASH;
1571
1572 assert_cc(DEFAULT_BLOOM_SIZE > 0);
1573 assert_cc(DEFAULT_BLOOM_N_HASH > 0);
1574
816a3f9e
DM
1575 make->size += ALIGN8(n->size);
1576
fa7796e9
LP
1577 /* The busses we create make no restrictions on what metadata
1578 * peers can read from incoming messages. */
1579 n = KDBUS_ITEM_NEXT(n);
1580 n->type = KDBUS_ITEM_ATTACH_FLAGS_RECV;
1581 n->size = offsetof(struct kdbus_item, data64) + sizeof(uint64_t);
19ee32dc
DH
1582 n->data64[0] = _KDBUS_ATTACH_ANY;
1583 make->size += ALIGN8(n->size);
1584
1585 /* Provide all metadata via bus-owner queries */
1586 n = KDBUS_ITEM_NEXT(n);
1587 n->type = KDBUS_ITEM_ATTACH_FLAGS_SEND;
1588 n->size = offsetof(struct kdbus_item, data64) + sizeof(uint64_t);
fa7796e9
LP
1589 n->data64[0] = _KDBUS_ATTACH_ANY;
1590 make->size += ALIGN8(n->size);
1591
1592 /* Set the a good name */
816a3f9e 1593 n = KDBUS_ITEM_NEXT(n);
a4152e3f 1594 sprintf(n->str, UID_FMT "-%s", getuid(), name);
e3dd987c 1595 n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
5e16c257 1596 n->type = KDBUS_ITEM_MAKE_NAME;
816a3f9e 1597 make->size += ALIGN8(n->size);
e3dd987c 1598
f7c7cd03 1599 make->flags = world ? KDBUS_MAKE_ACCESS_WORLD : 0;
e3dd987c
LP
1600
1601 if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
03e334a1 1602 safe_close(fd);
e3dd987c
LP
1603 return -errno;
1604 }
1605
1606 if (s) {
1607 char *p;
1608
63cc4c31 1609 p = strjoin("/sys/fs/kdbus/", n->str, "/bus", NULL);
e3dd987c 1610 if (!p) {
03e334a1 1611 safe_close(fd);
e3dd987c
LP
1612 return -ENOMEM;
1613 }
1614
1615 *s = p;
1616 }
1617
1618 return fd;
1619}
9bd37b40 1620
8f077bf9 1621int bus_kernel_open_bus_fd(const char *bus, char **path) {
a4152e3f
LP
1622 char *p;
1623 int fd;
8f077bf9 1624 size_t len;
1683342a 1625
8aee3fc7
LP
1626 assert(bus);
1627
63cc4c31 1628 len = strlen("/sys/fs/kdbus/") + DECIMAL_STR_MAX(uid_t) + 1 + strlen(bus) + strlen("/bus") + 1;
8f077bf9
ZJS
1629
1630 if (path) {
8aee3fc7 1631 p = new(char, len);
8f077bf9
ZJS
1632 if (!p)
1633 return -ENOMEM;
8f077bf9 1634 } else
8aee3fc7
LP
1635 p = newa(char, len);
1636
63cc4c31 1637 sprintf(p, "/sys/fs/kdbus/" UID_FMT "-%s/bus", getuid(), bus);
1683342a 1638
a4152e3f 1639 fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC);
8aee3fc7
LP
1640 if (fd < 0) {
1641 if (path)
1642 free(p);
1643
a4152e3f 1644 return -errno;
8aee3fc7
LP
1645 }
1646
1647 if (path)
1648 *path = p;
a4152e3f
LP
1649
1650 return fd;
1683342a
DM
1651}
1652
e7d718af 1653int bus_kernel_create_endpoint(const char *bus_name, const char *ep_name, char **ep_path) {
8e00bfc2 1654 _cleanup_free_ char *path = NULL;
b2086f60 1655 struct kdbus_cmd *make;
e7d718af 1656 struct kdbus_item *n;
342f3005 1657 const char *name;
e7d718af
DM
1658 int fd;
1659
1660 fd = bus_kernel_open_bus_fd(bus_name, &path);
1661 if (fd < 0)
1662 return fd;
1663
b2086f60 1664 make = alloca0_align(ALIGN8(offsetof(struct kdbus_cmd, items)) +
342f3005
DH
1665 ALIGN8(offsetof(struct kdbus_item, str) + DECIMAL_STR_MAX(uid_t) + 1 + strlen(ep_name) + 1),
1666 8);
b2086f60 1667 make->size = ALIGN8(offsetof(struct kdbus_cmd, items));
e7d718af
DM
1668 make->flags = KDBUS_MAKE_ACCESS_WORLD;
1669
1670 n = make->items;
342f3005
DH
1671 sprintf(n->str, UID_FMT "-%s", getuid(), ep_name);
1672 n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
e7d718af 1673 n->type = KDBUS_ITEM_MAKE_NAME;
342f3005
DH
1674 make->size += ALIGN8(n->size);
1675 name = n->str;
e7d718af 1676
40885bb2 1677 if (ioctl(fd, KDBUS_CMD_ENDPOINT_MAKE, make) < 0) {
e7d718af
DM
1678 safe_close(fd);
1679 return -errno;
1680 }
1681
e7d718af 1682 if (ep_path) {
2c652b6b
LP
1683 char *p;
1684
342f3005 1685 p = strjoin(dirname(path), "/", name, NULL);
2c652b6b 1686 if (!p) {
4edf33d1 1687 safe_close(fd);
e7d718af 1688 return -ENOMEM;
4edf33d1 1689 }
2c652b6b
LP
1690
1691 *ep_path = p;
e7d718af
DM
1692 }
1693
1694 return fd;
1695}
1696
ae095f86 1697int bus_kernel_try_close(sd_bus *bus) {
b2086f60
DH
1698 struct kdbus_cmd byebye = { .size = sizeof(byebye) };
1699
ae095f86
LP
1700 assert(bus);
1701 assert(bus->is_kernel);
1702
b2086f60 1703 if (ioctl(bus->input_fd, KDBUS_CMD_BYEBYE, &byebye) < 0)
ae095f86
LP
1704 return -errno;
1705
1706 return 0;
1707}
ff975efb
LP
1708
1709int bus_kernel_drop_one(int fd) {
1710 struct kdbus_cmd_recv recv = {
94e15fdc
DH
1711 .size = sizeof(recv),
1712 .flags = KDBUS_RECV_DROP,
ff975efb
LP
1713 };
1714
1715 assert(fd >= 0);
1716
94e15fdc 1717 if (ioctl(fd, KDBUS_CMD_RECV, &recv) < 0)
ff975efb
LP
1718 return -errno;
1719
1720 return 0;
1721}
b5dae4c7
LP
1722
1723int bus_kernel_realize_attach_flags(sd_bus *bus) {
b2086f60 1724 struct kdbus_cmd *update;
b5dae4c7
LP
1725 struct kdbus_item *n;
1726
1727 assert(bus);
1728 assert(bus->is_kernel);
1729
b2086f60 1730 update = alloca0_align(offsetof(struct kdbus_cmd, items) +
fa7796e9
LP
1731 ALIGN8(offsetof(struct kdbus_item, data64) + sizeof(uint64_t)),
1732 8);
b5dae4c7
LP
1733
1734 n = update->items;
1735 n->type = KDBUS_ITEM_ATTACH_FLAGS_RECV;
1736 n->size = offsetof(struct kdbus_item, data64) + sizeof(uint64_t);
1737 n->data64[0] = bus->attach_flags;
1738
fa7796e9 1739 update->size =
b2086f60 1740 offsetof(struct kdbus_cmd, items) +
fa7796e9 1741 ALIGN8(n->size);
b5dae4c7 1742
b2086f60 1743 if (ioctl(bus->input_fd, KDBUS_CMD_UPDATE, update) < 0)
b5dae4c7
LP
1744 return -errno;
1745
1746 return 0;
1747}
1a299299
LP
1748
1749int bus_kernel_fix_attach_mask(void) {
1750 _cleanup_free_ char *mask = NULL;
412c18f1 1751 uint64_t m = (uint64_t) -1;
1a299299
LP
1752 char buf[2+16+2];
1753 int r;
1754
412c18f1
LP
1755 /* By default we don't want any kdbus metadata fields to be
1756 * suppressed, hence we reset the kernel mask for it to
314808ce
DH
1757 * (uint64_t) -1. If the module argument was overwritten by
1758 * the kernel cmdline, we leave it as is. */
412c18f1 1759
314808ce 1760 r = get_proc_cmdline_key("kdbus.attach_flags_mask=", &mask);
1214b53c
LP
1761 if (r < 0)
1762 return log_warning_errno(r, "Failed to read kernel command line: %m");
1a299299 1763
314808ce
DH
1764 if (r == 0) {
1765 sprintf(buf, "0x%" PRIx64 "\n", m);
1766 r = write_string_file("/sys/module/kdbus/parameters/attach_flags_mask", buf);
1767 if (r < 0)
1768 return log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r,
1769 "Failed to write kdbus attach mask: %m");
1a299299
LP
1770 }
1771
1a299299
LP
1772 return 0;
1773}
3acc1daf
LP
1774
1775int bus_kernel_get_bus_name(sd_bus *bus, char **name) {
1776 struct kdbus_cmd_info cmd = {
1777 .size = sizeof(struct kdbus_cmd_info),
1778 };
1779 struct kdbus_info *info;
1780 struct kdbus_item *item;
1781 char *n = NULL;
1782 int r;
1783
1784 assert(bus);
1785 assert(name);
1786 assert(bus->is_kernel);
1787
1788 r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
1789 if (r < 0)
1790 return -errno;
1791
1792 info = (struct kdbus_info*) ((uint8_t*) bus->kdbus_buffer + cmd.offset);
1793
1794 KDBUS_ITEM_FOREACH(item, info, items)
1795 if (item->type == KDBUS_ITEM_MAKE_NAME) {
1796 r = free_and_strdup(&n, item->str);
1797 break;
1798 }
1799
1800 bus_kernel_cmd_free(bus, cmd.offset);
1801
1802 if (r < 0)
1803 return r;
1804 if (!n)
1805 return -EIO;
1806
1807 *name = n;
1808 return 0;
1809}