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