]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/bus-kernel.c
core: remove unneeded <libgen.h> include
[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;
954871d8 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;
954871d8
KS
414 struct bus_header *h = NULL;
415 size_t total, n_bytes = 0, idx = 0;
cb67f718 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 430 case KDBUS_ITEM_PAYLOAD_OFF:
954871d8
KS
431 if (!h) {
432 h = (struct bus_header *)((uint8_t *)bus->kdbus_buffer + d->vec.offset);
8a0e0ed9 433
954871d8
KS
434 if (!bus_header_is_complete(h, d->vec.size))
435 return -EBADMSG;
436 }
b381de41 437
cb67f718
DM
438 n_bytes += d->vec.size;
439 break;
8a0e0ed9 440
cb67f718 441 case KDBUS_ITEM_PAYLOAD_MEMFD:
954871d8 442 if (!h)
cb67f718 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
954871d8 469 if (!h)
cb67f718 470 return -EBADMSG;
de297575 471
954871d8
KS
472 r = bus_header_message_size(h, &total);
473 if (r < 0)
474 return r;
219728b3 475
954871d8 476 if (n_bytes != total)
cb67f718 477 return -EBADMSG;
6629161f 478
cb67f718
DM
479 /* on kdbus we only speak native endian gvariant, never dbus1
480 * marshalling or reverse endian */
954871d8
KS
481 if (h->version != 2 ||
482 h->endian != BUS_NATIVE_ENDIAN)
cb67f718 483 return -EPROTOTYPE;
c58dea19 484
954871d8 485 r = bus_message_from_header(bus, h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m);
cb67f718
DM
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 564 /* The PID/TID might be missing, when the data
954871d8
KS
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
954871d8 584 /* EUID/SUID/FSUID/EGID/SGID/FSGID might be missing too (see above). */
705a415f 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;
954871d8 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 764 /* Refuse messages if kdbus and dbus1 cookie doesn't match up */
954871d8 765 if ((uint64_t) m->header->serial != k->cookie) {
7fa934b0
LP
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) {
d31f486b 825 struct kdbus_bloom_parameter *bloom = NULL;
cb67f718 826 struct kdbus_cmd_hello *hello;
d31f486b 827 struct kdbus_item_list *items;
cb67f718 828 struct kdbus_item *item;
5972fe95
LP
829 _cleanup_free_ char *g = NULL;
830 const char *name;
831 size_t l = 0, m = 0, sz;
cb67f718 832 int r;
777d7a61 833
cb67f718 834 assert(b);
7adc46fc 835
cb67f718
DM
836 if (b->is_server)
837 return -EINVAL;
777d7a61 838
cb67f718 839 b->use_memfd = 1;
777d7a61 840
455971c1
LP
841 if (b->description) {
842 g = bus_label_escape(b->description);
5972fe95
LP
843 if (!g)
844 return -ENOMEM;
845
846 name = g;
847 } else {
848 char pr[17] = {};
849
850 /* If no name is explicitly set, we'll include a hint
851 * indicating the library implementation, a hint which
852 * kind of bus this is and the thread name */
853
854 assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0);
855
856 if (isempty(pr)) {
857 name = b->is_system ? "sd-system" :
858 b->is_user ? "sd-user" : "sd";
859 } else {
860 _cleanup_free_ char *e = NULL;
861
a6278b88 862 e = bus_label_escape(pr);
5972fe95
LP
863 if (!e)
864 return -ENOMEM;
865
866 g = strappend(b->is_system ? "sd-system-" :
867 b->is_user ? "sd-user-" : "sd-",
868 e);
869 if (!g)
870 return -ENOMEM;
871
872 name = g;
873 }
874
455971c1
LP
875 b->description = bus_label_unescape(name);
876 if (!b->description)
5972fe95
LP
877 return -ENOMEM;
878 }
879
880 m = strlen(name);
881
882 sz = ALIGN8(offsetof(struct kdbus_cmd_hello, items)) +
883 ALIGN8(offsetof(struct kdbus_item, str) + m + 1);
777d7a61 884
cb67f718 885 if (b->fake_creds_valid)
5972fe95 886 sz += ALIGN8(offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds));
777d7a61 887
705a415f
LP
888 if (b->fake_pids_valid)
889 sz += ALIGN8(offsetof(struct kdbus_item, pids) + sizeof(struct kdbus_pids));
890
cb67f718
DM
891 if (b->fake_label) {
892 l = strlen(b->fake_label);
893 sz += ALIGN8(offsetof(struct kdbus_item, str) + l + 1);
894 }
777d7a61 895
7f3d3ba1 896 hello = alloca0_align(sz, 8);
cb67f718 897 hello->size = sz;
bc75205c 898 hello->flags = b->hello_flags;
6f5c810a 899 hello->attach_flags_send = _KDBUS_ATTACH_ANY;
d704fda9 900 hello->attach_flags_recv = b->attach_flags;
cb67f718 901 hello->pool_size = KDBUS_POOL_SIZE;
777d7a61 902
cb67f718
DM
903 item = hello->items;
904
5972fe95 905 item->size = offsetof(struct kdbus_item, str) + m + 1;
635f9f0d 906 item->type = KDBUS_ITEM_CONN_DESCRIPTION;
5972fe95
LP
907 memcpy(item->str, name, m + 1);
908 item = KDBUS_ITEM_NEXT(item);
909
cb67f718
DM
910 if (b->fake_creds_valid) {
911 item->size = offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds);
912 item->type = KDBUS_ITEM_CREDS;
913 item->creds = b->fake_creds;
914
915 item = KDBUS_ITEM_NEXT(item);
777d7a61
LP
916 }
917
705a415f
LP
918 if (b->fake_pids_valid) {
919 item->size = offsetof(struct kdbus_item, pids) + sizeof(struct kdbus_pids);
920 item->type = KDBUS_ITEM_PIDS;
921 item->pids = b->fake_pids;
922
923 item = KDBUS_ITEM_NEXT(item);
924 }
925
cb67f718
DM
926 if (b->fake_label) {
927 item->size = offsetof(struct kdbus_item, str) + l + 1;
5972fe95 928 item->type = KDBUS_ITEM_SECLABEL;
cb67f718 929 memcpy(item->str, b->fake_label, l+1);
777d7a61
LP
930 }
931
cb67f718
DM
932 r = ioctl(b->input_fd, KDBUS_CMD_HELLO, hello);
933 if (r < 0)
934 return -errno;
777d7a61 935
cb67f718
DM
936 if (!b->kdbus_buffer) {
937 b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, b->input_fd, 0);
938 if (b->kdbus_buffer == MAP_FAILED) {
939 b->kdbus_buffer = NULL;
d31f486b
DH
940 r = -errno;
941 goto fail;
cb67f718
DM
942 }
943 }
6629161f 944
4a3e79e1 945 /* The higher 32bit of the bus_flags fields are considered
cb67f718 946 * 'incompatible flags'. Refuse them all for now. */
d31f486b
DH
947 if (hello->bus_flags > 0xFFFFFFFFULL) {
948 r = -ENOTSUP;
949 goto fail;
950 }
6629161f 951
d31f486b
DH
952 /* extract bloom parameters from items */
953 items = (void*)((uint8_t*)b->kdbus_buffer + hello->offset);
954 KDBUS_ITEM_FOREACH(item, items, items) {
955 switch (item->type) {
956 case KDBUS_ITEM_BLOOM_PARAMETER:
957 bloom = &item->bloom_parameter;
958 break;
959 }
960 }
6629161f 961
d31f486b
DH
962 if (!bloom || !bloom_validate_parameters((size_t) bloom->size, (unsigned) bloom->n_hash)) {
963 r = -ENOTSUP;
964 goto fail;
965 }
b28ff39f 966
d31f486b
DH
967 b->bloom_size = (size_t) bloom->size;
968 b->bloom_n_hash = (unsigned) bloom->n_hash;
969
970 if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello->id) < 0) {
971 r = -ENOMEM;
972 goto fail;
973 }
6629161f 974
cb67f718 975 b->unique_id = hello->id;
6629161f 976
cb67f718
DM
977 b->is_kernel = true;
978 b->bus_client = true;
bc75205c 979 b->can_fds = !!(hello->flags & KDBUS_HELLO_ACCEPT_FD);
cb67f718
DM
980 b->message_version = 2;
981 b->message_endian = BUS_NATIVE_ENDIAN;
c91cb83c 982
cb67f718
DM
983 /* the kernel told us the UUID of the underlying bus */
984 memcpy(b->server_id.bytes, hello->id128, sizeof(b->server_id.bytes));
6629161f 985
d31f486b
DH
986 /* free returned items */
987 (void) bus_kernel_cmd_free(b, hello->offset);
cb67f718 988 return bus_start_running(b);
d31f486b
DH
989
990fail:
72e61104 991 (void) bus_kernel_cmd_free(b, hello->offset);
d31f486b 992 return r;
cb67f718 993}
6629161f 994
cb67f718
DM
995int bus_kernel_connect(sd_bus *b) {
996 assert(b);
997 assert(b->input_fd < 0);
998 assert(b->output_fd < 0);
999 assert(b->kernel);
1307c3ff 1000
cb67f718
DM
1001 if (b->is_server)
1002 return -EINVAL;
1307c3ff 1003
cb67f718
DM
1004 b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
1005 if (b->input_fd < 0)
1006 return -errno;
6629161f 1007
cb67f718 1008 b->output_fd = b->input_fd;
6629161f 1009
cb67f718
DM
1010 return bus_kernel_take_fd(b);
1011}
f9be01f3 1012
52cfc037
LP
1013int bus_kernel_cmd_free(sd_bus *bus, uint64_t offset) {
1014 struct kdbus_cmd_free cmd = {
d31f486b 1015 .size = sizeof(cmd),
52cfc037
LP
1016 .offset = offset,
1017 };
1018 int r;
1019
1020 assert(bus);
1021 assert(bus->is_kernel);
1022
1023 r = ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd);
1024 if (r < 0)
1025 return -errno;
1026
1027 return 0;
1028}
1029
069f5e61 1030static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
069f5e61
LP
1031 struct kdbus_item *d;
1032
1033 assert(bus);
1034 assert(k);
1035
069f5e61 1036 KDBUS_ITEM_FOREACH(d, k, items) {
069f5e61
LP
1037 if (d->type == KDBUS_ITEM_FDS)
1038 close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
1039 else if (d->type == KDBUS_ITEM_PAYLOAD_MEMFD)
03e334a1 1040 safe_close(d->memfd.fd);
069f5e61 1041 }
ca794c8e 1042
52cfc037 1043 bus_kernel_cmd_free(bus, (uint8_t*) k - (uint8_t*) bus->kdbus_buffer);
069f5e61
LP
1044}
1045
1046int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call) {
94e15fdc 1047 struct kdbus_cmd_send cmd = { };
cb67f718 1048 int r;
6629161f 1049
cb67f718
DM
1050 assert(bus);
1051 assert(m);
1052 assert(bus->state == BUS_RUNNING);
6629161f 1053
cb67f718
DM
1054 /* If we can't deliver, we want room for the error message */
1055 r = bus_rqueue_make_room(bus);
6629161f
LP
1056 if (r < 0)
1057 return r;
1058
cb67f718 1059 r = bus_message_setup_kmsg(bus, m);
6629161f
LP
1060 if (r < 0)
1061 return r;
1062
94e15fdc
DH
1063 cmd.size = sizeof(cmd);
1064 cmd.msg_address = (uintptr_t)m->kdbus;
1065
069f5e61
LP
1066 /* If this is a synchronous method call, then let's tell the
1067 * kernel, so that it can pass CPU time/scheduling to the
1068 * destination for the time, if it wants to. If we
1069 * synchronously wait for the result anyway, we won't need CPU
1070 * anyway. */
94e15fdc
DH
1071 if (hint_sync_call) {
1072 m->kdbus->flags |= KDBUS_MSG_EXPECT_REPLY;
1073 cmd.flags |= KDBUS_SEND_SYNC_REPLY;
1074 }
069f5e61 1075
94e15fdc 1076 r = ioctl(bus->output_fd, KDBUS_CMD_SEND, &cmd);
cb67f718
DM
1077 if (r < 0) {
1078 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1079 sd_bus_message *reply;
253ce82b 1080
cb67f718
DM
1081 if (errno == EAGAIN || errno == EINTR)
1082 return 0;
1083 else if (errno == ENXIO || errno == ESRCH) {
6629161f 1084
cb67f718
DM
1085 /* ENXIO: unique name not known
1086 * ESRCH: well-known name not known */
6629161f 1087
cb67f718
DM
1088 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1089 sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Destination %s not known", m->destination);
1090 else {
1091 log_debug("Could not deliver message to %s as destination is not known. Ignoring.", m->destination);
1092 return 0;
1093 }
777d7a61 1094
cb67f718 1095 } else if (errno == EADDRNOTAVAIL) {
fd8d62d9 1096
cb67f718 1097 /* EADDRNOTAVAIL: activation is possible, but turned off in request flags */
bc7fd8cd 1098
cb67f718
DM
1099 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1100 sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Activation of %s not requested", m->destination);
1101 else {
1102 log_debug("Could not deliver message to %s as destination is not activated. Ignoring.", m->destination);
1103 return 0;
1104 }
1105 } else
1106 return -errno;
bc7fd8cd 1107
cb67f718
DM
1108 r = bus_message_new_synthetic_error(
1109 bus,
1110 BUS_MESSAGE_COOKIE(m),
1111 &error,
1112 &reply);
bc7fd8cd 1113
cb67f718
DM
1114 if (r < 0)
1115 return r;
bc7fd8cd 1116
cb67f718
DM
1117 r = bus_seal_synthetic_message(bus, reply);
1118 if (r < 0)
1119 return r;
62b3e928 1120
cb67f718 1121 bus->rqueue[bus->rqueue_size++] = reply;
bc7fd8cd 1122
069f5e61
LP
1123 } else if (hint_sync_call) {
1124 struct kdbus_msg *k;
fd8d62d9 1125
94e15fdc 1126 k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + cmd.reply.offset);
069f5e61 1127 assert(k);
777d7a61 1128
069f5e61 1129 if (k->payload_type == KDBUS_PAYLOAD_DBUS) {
1307c3ff 1130
069f5e61
LP
1131 r = bus_kernel_make_message(bus, k);
1132 if (r < 0) {
1133 close_kdbus_msg(bus, k);
1307c3ff 1134
069f5e61
LP
1135 /* Anybody can send us invalid messages, let's just drop them. */
1136 if (r == -EBADMSG || r == -EPROTOTYPE)
da927ba9 1137 log_debug_errno(r, "Ignoring invalid message: %m");
069f5e61
LP
1138 else
1139 return r;
1140 }
1141 } else {
1142 log_debug("Ignoring message with unknown payload type %llu.", (unsigned long long) k->payload_type);
1143 close_kdbus_msg(bus, k);
1144 }
cb67f718 1145 }
069f5e61
LP
1146
1147 return 1;
cb67f718 1148}
69aec65c 1149
76877fb9
LP
1150static int push_name_owner_changed(
1151 sd_bus *bus,
1152 const char *name,
1153 const char *old_owner,
1154 const char *new_owner,
1155 const struct kdbus_timestamp *ts) {
1156
cb67f718
DM
1157 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1158 int r;
2dc9970b 1159
cb67f718 1160 assert(bus);
2dc9970b 1161
cb67f718
DM
1162 r = sd_bus_message_new_signal(
1163 bus,
151b9b96 1164 &m,
cb67f718
DM
1165 "/org/freedesktop/DBus",
1166 "org.freedesktop.DBus",
151b9b96 1167 "NameOwnerChanged");
cb67f718
DM
1168 if (r < 0)
1169 return r;
2dc9970b 1170
cb67f718
DM
1171 r = sd_bus_message_append(m, "sss", name, old_owner, new_owner);
1172 if (r < 0)
1173 return r;
5b12334d 1174
7d31d924 1175 bus_message_set_sender_driver(bus, m);
76877fb9 1176 message_set_timestamp(bus, m, ts);
5b12334d 1177
cb67f718
DM
1178 r = bus_seal_synthetic_message(bus, m);
1179 if (r < 0)
1180 return r;
5b12334d 1181
cb67f718
DM
1182 bus->rqueue[bus->rqueue_size++] = m;
1183 m = NULL;
5b12334d 1184
cb67f718
DM
1185 return 1;
1186}
5b12334d 1187
76877fb9
LP
1188static int translate_name_change(
1189 sd_bus *bus,
1190 const struct kdbus_msg *k,
1191 const struct kdbus_item *d,
1192 const struct kdbus_timestamp *ts) {
1193
cb67f718 1194 char new_owner[UNIQUE_NAME_MAX], old_owner[UNIQUE_NAME_MAX];
5b12334d 1195
cb67f718
DM
1196 assert(bus);
1197 assert(k);
1198 assert(d);
751bc6ac 1199
619d7a03 1200 if (d->type == KDBUS_ITEM_NAME_ADD || (d->name_change.old_id.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR)))
cb67f718
DM
1201 old_owner[0] = 0;
1202 else
619d7a03 1203 sprintf(old_owner, ":1.%llu", (unsigned long long) d->name_change.old_id.id);
751bc6ac 1204
619d7a03 1205 if (d->type == KDBUS_ITEM_NAME_REMOVE || (d->name_change.new_id.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR))) {
751bc6ac 1206
cb67f718
DM
1207 if (isempty(old_owner))
1208 return 0;
5b12334d 1209
cb67f718
DM
1210 new_owner[0] = 0;
1211 } else
619d7a03 1212 sprintf(new_owner, ":1.%llu", (unsigned long long) d->name_change.new_id.id);
5b12334d 1213
76877fb9 1214 return push_name_owner_changed(bus, d->name_change.name, old_owner, new_owner, ts);
cb67f718 1215}
5b12334d 1216
76877fb9
LP
1217static int translate_id_change(
1218 sd_bus *bus,
1219 const struct kdbus_msg *k,
1220 const struct kdbus_item *d,
1221 const struct kdbus_timestamp *ts) {
1222
cb67f718 1223 char owner[UNIQUE_NAME_MAX];
2e2ec0ea 1224
cb67f718
DM
1225 assert(bus);
1226 assert(k);
1227 assert(d);
777d7a61 1228
cb67f718 1229 sprintf(owner, ":1.%llu", d->id_change.id);
2e2ec0ea 1230
cb67f718
DM
1231 return push_name_owner_changed(
1232 bus, owner,
1233 d->type == KDBUS_ITEM_ID_ADD ? NULL : owner,
76877fb9
LP
1234 d->type == KDBUS_ITEM_ID_ADD ? owner : NULL,
1235 ts);
cb67f718 1236}
49b832c5 1237
76877fb9
LP
1238static int translate_reply(
1239 sd_bus *bus,
1240 const struct kdbus_msg *k,
1241 const struct kdbus_item *d,
1242 const struct kdbus_timestamp *ts) {
1243
cb67f718
DM
1244 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1245 int r;
777d7a61 1246
cb67f718
DM
1247 assert(bus);
1248 assert(k);
1249 assert(d);
acb5a3cb 1250
cb67f718
DM
1251 r = bus_message_new_synthetic_error(
1252 bus,
1253 k->cookie_reply,
1254 d->type == KDBUS_ITEM_REPLY_TIMEOUT ?
1255 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call timed out") :
1256 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call peer died"),
1257 &m);
1307c3ff 1258 if (r < 0)
cb67f718 1259 return r;
51038c03 1260
76877fb9 1261 message_set_timestamp(bus, m, ts);
51038c03 1262
cb67f718
DM
1263 r = bus_seal_synthetic_message(bus, m);
1264 if (r < 0)
1265 return r;
6629161f 1266
7adc46fc 1267 bus->rqueue[bus->rqueue_size++] = m;
cb67f718 1268 m = NULL;
7d22c717 1269
6629161f 1270 return 1;
cb67f718 1271}
1307c3ff 1272
cb67f718 1273static int bus_kernel_translate_message(sd_bus *bus, struct kdbus_msg *k) {
76877fb9 1274 static int (* const translate[])(sd_bus *bus, const struct kdbus_msg *k, const struct kdbus_item *d, const struct kdbus_timestamp *ts) = {
cb67f718
DM
1275 [KDBUS_ITEM_NAME_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
1276 [KDBUS_ITEM_NAME_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
1277 [KDBUS_ITEM_NAME_CHANGE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
1307c3ff 1278
cb67f718
DM
1279 [KDBUS_ITEM_ID_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
1280 [KDBUS_ITEM_ID_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
1281
1282 [KDBUS_ITEM_REPLY_TIMEOUT - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
1283 [KDBUS_ITEM_REPLY_DEAD - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
1284 };
1285
76877fb9
LP
1286 struct kdbus_item *d, *found = NULL;
1287 struct kdbus_timestamp *ts = NULL;
1288
cb67f718
DM
1289 assert(bus);
1290 assert(k);
1291 assert(k->payload_type == KDBUS_PAYLOAD_KERNEL);
1292
1293 KDBUS_ITEM_FOREACH(d, k, items) {
856d6e09 1294 if (d->type == KDBUS_ITEM_TIMESTAMP)
76877fb9 1295 ts = &d->timestamp;
856d6e09 1296
cb67f718
DM
1297 if (d->type >= _KDBUS_ITEM_KERNEL_BASE && d->type < _KDBUS_ITEM_KERNEL_BASE + ELEMENTSOF(translate)) {
1298 if (found)
1299 return -EBADMSG;
1300 found = d;
1301 } else
1302 log_debug("Got unknown field from kernel %llu", d->type);
1307c3ff
LP
1303 }
1304
cb67f718
DM
1305 if (!found) {
1306 log_debug("Didn't find a kernel message to translate.");
1307 return 0;
1308 }
1309
76877fb9 1310 return translate[found->type - _KDBUS_ITEM_KERNEL_BASE](bus, k, found, ts);
6629161f
LP
1311}
1312
766c5809 1313int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority) {
94e15fdc 1314 struct kdbus_cmd_recv recv = { .size = sizeof(recv) };
6629161f 1315 struct kdbus_msg *k;
6629161f
LP
1316 int r;
1317
1318 assert(bus);
7d22c717 1319
7adc46fc 1320 r = bus_rqueue_make_room(bus);
7d22c717
LP
1321 if (r < 0)
1322 return r;
6629161f 1323
766c5809
LP
1324 if (hint_priority) {
1325 recv.flags |= KDBUS_RECV_USE_PRIORITY;
1326 recv.priority = priority;
1327 }
1328
94e15fdc 1329 r = ioctl(bus->input_fd, KDBUS_CMD_RECV, &recv);
fd8d62d9 1330 if (r < 0) {
6629161f
LP
1331 if (errno == EAGAIN)
1332 return 0;
1333
f9a458c6
LP
1334 if (errno == EOVERFLOW) {
1335 log_debug("%s: kdbus reports %" PRIu64 " dropped broadcast messages, ignoring.", strna(bus->description), (uint64_t) recv.dropped_msgs);
1336 return 0;
1337 }
1338
fd8d62d9 1339 return -errno;
6629161f
LP
1340 }
1341
a9c8343e 1342 k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + recv.msg.offset);
e1d337d4 1343 if (k->payload_type == KDBUS_PAYLOAD_DBUS) {
7d22c717 1344 r = bus_kernel_make_message(bus, k);
e1d337d4
LP
1345
1346 /* Anybody can send us invalid messages, let's just drop them. */
1347 if (r == -EBADMSG || r == -EPROTOTYPE) {
da927ba9 1348 log_debug_errno(r, "Ignoring invalid message: %m");
e1d337d4
LP
1349 r = 0;
1350 }
1351
1352 } else if (k->payload_type == KDBUS_PAYLOAD_KERNEL)
7d22c717 1353 r = bus_kernel_translate_message(bus, k);
069f5e61
LP
1354 else {
1355 log_debug("Ignoring message with unknown payload type %llu.", (unsigned long long) k->payload_type);
777d7a61 1356 r = 0;
069f5e61 1357 }
777d7a61 1358
fd8d62d9
LP
1359 if (r <= 0)
1360 close_kdbus_msg(bus, k);
6629161f 1361
51038c03 1362 return r < 0 ? r : 1;
6629161f
LP
1363}
1364
8e959fbf 1365int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *allocated) {
bc7fd8cd 1366 struct memfd_cache *c;
45fbe937 1367 int fd;
bc7fd8cd
LP
1368
1369 assert(address);
8e959fbf
LP
1370 assert(mapped);
1371 assert(allocated);
35460afc
LP
1372
1373 if (!bus || !bus->is_kernel)
1374 return -ENOTSUP;
bc7fd8cd 1375
76b7742c 1376 assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
45fbe937 1377
bc7fd8cd 1378 if (bus->n_memfd_cache <= 0) {
45fbe937
LP
1379 int r;
1380
76b7742c 1381 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
bc7fd8cd 1382
455971c1 1383 r = memfd_new(bus->description);
9b05bc48 1384 if (r < 0)
73843b52 1385 return r;
bc7fd8cd
LP
1386
1387 *address = NULL;
8e959fbf
LP
1388 *mapped = 0;
1389 *allocated = 0;
a6082d77 1390 return r;
bc7fd8cd
LP
1391 }
1392
bf30e48f 1393 c = &bus->memfd_cache[--bus->n_memfd_cache];
bc7fd8cd
LP
1394
1395 assert(c->fd >= 0);
8e959fbf 1396 assert(c->mapped == 0 || c->address);
bc7fd8cd
LP
1397
1398 *address = c->address;
8e959fbf
LP
1399 *mapped = c->mapped;
1400 *allocated = c->allocated;
45fbe937
LP
1401 fd = c->fd;
1402
76b7742c 1403 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
bc7fd8cd 1404
45fbe937
LP
1405 return fd;
1406}
1407
1408static void close_and_munmap(int fd, void *address, size_t size) {
1409 if (size > 0)
76b7742c 1410 assert_se(munmap(address, PAGE_ALIGN(size)) >= 0);
45fbe937 1411
03e334a1 1412 safe_close(fd);
bc7fd8cd
LP
1413}
1414
8e959fbf 1415void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t mapped, size_t allocated) {
bc7fd8cd 1416 struct memfd_cache *c;
8e959fbf 1417 uint64_t max_mapped = PAGE_ALIGN(MEMFD_CACHE_ITEM_SIZE_MAX);
bc7fd8cd
LP
1418
1419 assert(fd >= 0);
8e959fbf 1420 assert(mapped == 0 || address);
bc7fd8cd 1421
45fbe937 1422 if (!bus || !bus->is_kernel) {
8e959fbf 1423 close_and_munmap(fd, address, mapped);
45fbe937
LP
1424 return;
1425 }
1426
76b7742c 1427 assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
bc7fd8cd 1428
45fbe937 1429 if (bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
76b7742c 1430 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
bc7fd8cd 1431
8e959fbf 1432 close_and_munmap(fd, address, mapped);
bc7fd8cd
LP
1433 return;
1434 }
1435
1436 c = &bus->memfd_cache[bus->n_memfd_cache++];
1437 c->fd = fd;
1438 c->address = address;
1439
1440 /* If overly long, let's return a bit to the OS */
8e959fbf 1441 if (mapped > max_mapped) {
73843b52 1442 assert_se(memfd_set_size(fd, max_mapped) >= 0);
8e959fbf
LP
1443 assert_se(munmap((uint8_t*) address + max_mapped, PAGE_ALIGN(mapped - max_mapped)) >= 0);
1444 c->mapped = c->allocated = max_mapped;
1445 } else {
1446 c->mapped = mapped;
1447 c->allocated = allocated;
1448 }
45fbe937 1449
76b7742c 1450 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
bc7fd8cd
LP
1451}
1452
1453void bus_kernel_flush_memfd(sd_bus *b) {
1454 unsigned i;
1455
1456 assert(b);
1457
76b7742c 1458 for (i = 0; i < b->n_memfd_cache; i++)
8e959fbf 1459 close_and_munmap(b->memfd_cache[i].fd, b->memfd_cache[i].address, b->memfd_cache[i].mapped);
bc7fd8cd 1460}
0253ddcc 1461
b5dae4c7 1462uint64_t request_name_flags_to_kdbus(uint64_t flags) {
e3dd987c 1463 uint64_t f = 0;
0253ddcc 1464
e3dd987c
LP
1465 if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
1466 f |= KDBUS_NAME_ALLOW_REPLACEMENT;
0253ddcc 1467
e3dd987c
LP
1468 if (flags & SD_BUS_NAME_REPLACE_EXISTING)
1469 f |= KDBUS_NAME_REPLACE_EXISTING;
0253ddcc 1470
d90bb669 1471 if (flags & SD_BUS_NAME_QUEUE)
e3dd987c 1472 f |= KDBUS_NAME_QUEUE;
0253ddcc 1473
b5dae4c7 1474 return f;
e3dd987c
LP
1475}
1476
b5dae4c7 1477uint64_t attach_flags_to_kdbus(uint64_t mask) {
e3dd987c
LP
1478 uint64_t m = 0;
1479
705a415f
LP
1480 if (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
1481 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID))
e3dd987c
LP
1482 m |= KDBUS_ATTACH_CREDS;
1483
32802361 1484 if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_TID))
705a415f
LP
1485 m |= KDBUS_ATTACH_PIDS;
1486
a2243d54
DM
1487 if (mask & SD_BUS_CREDS_COMM)
1488 m |= KDBUS_ATTACH_PID_COMM;
1489
1490 if (mask & SD_BUS_CREDS_TID_COMM)
1491 m |= KDBUS_ATTACH_TID_COMM;
e3dd987c
LP
1492
1493 if (mask & SD_BUS_CREDS_EXE)
1494 m |= KDBUS_ATTACH_EXE;
1495
1496 if (mask & SD_BUS_CREDS_CMDLINE)
1497 m |= KDBUS_ATTACH_CMDLINE;
1498
1499 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))
1500 m |= KDBUS_ATTACH_CGROUP;
1501
1502 if (mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS))
1503 m |= KDBUS_ATTACH_CAPS;
1504
1505 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT)
1506 m |= KDBUS_ATTACH_SECLABEL;
0253ddcc 1507
e3dd987c
LP
1508 if (mask & (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID))
1509 m |= KDBUS_ATTACH_AUDIT;
1510
49b832c5
LP
1511 if (mask & SD_BUS_CREDS_WELL_KNOWN_NAMES)
1512 m |= KDBUS_ATTACH_NAMES;
1513
455971c1 1514 if (mask & SD_BUS_CREDS_DESCRIPTION)
635f9f0d 1515 m |= KDBUS_ATTACH_CONN_DESCRIPTION;
cccb0b2c 1516
02581590
LP
1517 if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS)
1518 m |= KDBUS_ATTACH_AUXGROUPS;
1519
b5dae4c7 1520 return m;
0253ddcc 1521}
e3dd987c 1522
f2769777 1523int bus_kernel_create_bus(const char *name, bool world, char **s) {
b2086f60 1524 struct kdbus_cmd *make;
e3dd987c 1525 struct kdbus_item *n;
fa7796e9 1526 size_t l;
e3dd987c
LP
1527 int fd;
1528
1529 assert(name);
1530 assert(s);
1531
63cc4c31 1532 fd = open("/sys/fs/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
e3dd987c
LP
1533 if (fd < 0)
1534 return -errno;
1535
fa7796e9 1536 l = strlen(name);
b2086f60 1537 make = alloca0_align(offsetof(struct kdbus_cmd, items) +
fa7796e9
LP
1538 ALIGN8(offsetof(struct kdbus_item, bloom_parameter) + sizeof(struct kdbus_bloom_parameter)) +
1539 ALIGN8(offsetof(struct kdbus_item, data64) + sizeof(uint64_t)) +
19ee32dc 1540 ALIGN8(offsetof(struct kdbus_item, data64) + sizeof(uint64_t)) +
fa7796e9 1541 ALIGN8(offsetof(struct kdbus_item, str) + DECIMAL_STR_MAX(uid_t) + 1 + l + 1),
7f3d3ba1 1542 8);
e3dd987c 1543
b2086f60 1544 make->size = offsetof(struct kdbus_cmd, items);
816a3f9e 1545
fa7796e9 1546 /* Set the bloom parameters */
e3dd987c 1547 n = make->items;
18a28147
KS
1548 n->size = offsetof(struct kdbus_item, bloom_parameter) +
1549 sizeof(struct kdbus_bloom_parameter);
1550 n->type = KDBUS_ITEM_BLOOM_PARAMETER;
b28ff39f
LP
1551 n->bloom_parameter.size = DEFAULT_BLOOM_SIZE;
1552 n->bloom_parameter.n_hash = DEFAULT_BLOOM_N_HASH;
1553
1554 assert_cc(DEFAULT_BLOOM_SIZE > 0);
1555 assert_cc(DEFAULT_BLOOM_N_HASH > 0);
1556
816a3f9e
DM
1557 make->size += ALIGN8(n->size);
1558
fa7796e9
LP
1559 /* The busses we create make no restrictions on what metadata
1560 * peers can read from incoming messages. */
1561 n = KDBUS_ITEM_NEXT(n);
1562 n->type = KDBUS_ITEM_ATTACH_FLAGS_RECV;
1563 n->size = offsetof(struct kdbus_item, data64) + sizeof(uint64_t);
19ee32dc
DH
1564 n->data64[0] = _KDBUS_ATTACH_ANY;
1565 make->size += ALIGN8(n->size);
1566
1567 /* Provide all metadata via bus-owner queries */
1568 n = KDBUS_ITEM_NEXT(n);
1569 n->type = KDBUS_ITEM_ATTACH_FLAGS_SEND;
1570 n->size = offsetof(struct kdbus_item, data64) + sizeof(uint64_t);
fa7796e9
LP
1571 n->data64[0] = _KDBUS_ATTACH_ANY;
1572 make->size += ALIGN8(n->size);
1573
1574 /* Set the a good name */
816a3f9e 1575 n = KDBUS_ITEM_NEXT(n);
a4152e3f 1576 sprintf(n->str, UID_FMT "-%s", getuid(), name);
e3dd987c 1577 n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
5e16c257 1578 n->type = KDBUS_ITEM_MAKE_NAME;
816a3f9e 1579 make->size += ALIGN8(n->size);
e3dd987c 1580
f7c7cd03 1581 make->flags = world ? KDBUS_MAKE_ACCESS_WORLD : 0;
e3dd987c
LP
1582
1583 if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
03e334a1 1584 safe_close(fd);
e3dd987c
LP
1585 return -errno;
1586 }
1587
1588 if (s) {
1589 char *p;
1590
63cc4c31 1591 p = strjoin("/sys/fs/kdbus/", n->str, "/bus", NULL);
e3dd987c 1592 if (!p) {
03e334a1 1593 safe_close(fd);
e3dd987c
LP
1594 return -ENOMEM;
1595 }
1596
1597 *s = p;
1598 }
1599
1600 return fd;
1601}
9bd37b40 1602
8f077bf9 1603int bus_kernel_open_bus_fd(const char *bus, char **path) {
a4152e3f
LP
1604 char *p;
1605 int fd;
8f077bf9 1606 size_t len;
1683342a 1607
8aee3fc7
LP
1608 assert(bus);
1609
63cc4c31 1610 len = strlen("/sys/fs/kdbus/") + DECIMAL_STR_MAX(uid_t) + 1 + strlen(bus) + strlen("/bus") + 1;
8f077bf9
ZJS
1611
1612 if (path) {
8aee3fc7 1613 p = new(char, len);
8f077bf9
ZJS
1614 if (!p)
1615 return -ENOMEM;
8f077bf9 1616 } else
8aee3fc7
LP
1617 p = newa(char, len);
1618
63cc4c31 1619 sprintf(p, "/sys/fs/kdbus/" UID_FMT "-%s/bus", getuid(), bus);
1683342a 1620
a4152e3f 1621 fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC);
8aee3fc7
LP
1622 if (fd < 0) {
1623 if (path)
1624 free(p);
1625
a4152e3f 1626 return -errno;
8aee3fc7
LP
1627 }
1628
1629 if (path)
1630 *path = p;
a4152e3f
LP
1631
1632 return fd;
1683342a
DM
1633}
1634
e7d718af 1635int bus_kernel_create_endpoint(const char *bus_name, const char *ep_name, char **ep_path) {
8e00bfc2 1636 _cleanup_free_ char *path = NULL;
b2086f60 1637 struct kdbus_cmd *make;
e7d718af 1638 struct kdbus_item *n;
342f3005 1639 const char *name;
e7d718af
DM
1640 int fd;
1641
1642 fd = bus_kernel_open_bus_fd(bus_name, &path);
1643 if (fd < 0)
1644 return fd;
1645
b2086f60 1646 make = alloca0_align(ALIGN8(offsetof(struct kdbus_cmd, items)) +
342f3005
DH
1647 ALIGN8(offsetof(struct kdbus_item, str) + DECIMAL_STR_MAX(uid_t) + 1 + strlen(ep_name) + 1),
1648 8);
b2086f60 1649 make->size = ALIGN8(offsetof(struct kdbus_cmd, items));
e7d718af
DM
1650 make->flags = KDBUS_MAKE_ACCESS_WORLD;
1651
1652 n = make->items;
342f3005
DH
1653 sprintf(n->str, UID_FMT "-%s", getuid(), ep_name);
1654 n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
e7d718af 1655 n->type = KDBUS_ITEM_MAKE_NAME;
342f3005
DH
1656 make->size += ALIGN8(n->size);
1657 name = n->str;
e7d718af 1658
40885bb2 1659 if (ioctl(fd, KDBUS_CMD_ENDPOINT_MAKE, make) < 0) {
e7d718af
DM
1660 safe_close(fd);
1661 return -errno;
1662 }
1663
e7d718af 1664 if (ep_path) {
2c652b6b
LP
1665 char *p;
1666
342f3005 1667 p = strjoin(dirname(path), "/", name, NULL);
2c652b6b 1668 if (!p) {
4edf33d1 1669 safe_close(fd);
e7d718af 1670 return -ENOMEM;
4edf33d1 1671 }
2c652b6b
LP
1672
1673 *ep_path = p;
e7d718af
DM
1674 }
1675
1676 return fd;
1677}
1678
ae095f86 1679int bus_kernel_try_close(sd_bus *bus) {
b2086f60
DH
1680 struct kdbus_cmd byebye = { .size = sizeof(byebye) };
1681
ae095f86
LP
1682 assert(bus);
1683 assert(bus->is_kernel);
1684
b2086f60 1685 if (ioctl(bus->input_fd, KDBUS_CMD_BYEBYE, &byebye) < 0)
ae095f86
LP
1686 return -errno;
1687
1688 return 0;
1689}
ff975efb
LP
1690
1691int bus_kernel_drop_one(int fd) {
1692 struct kdbus_cmd_recv recv = {
94e15fdc
DH
1693 .size = sizeof(recv),
1694 .flags = KDBUS_RECV_DROP,
ff975efb
LP
1695 };
1696
1697 assert(fd >= 0);
1698
94e15fdc 1699 if (ioctl(fd, KDBUS_CMD_RECV, &recv) < 0)
ff975efb
LP
1700 return -errno;
1701
1702 return 0;
1703}
b5dae4c7
LP
1704
1705int bus_kernel_realize_attach_flags(sd_bus *bus) {
b2086f60 1706 struct kdbus_cmd *update;
b5dae4c7
LP
1707 struct kdbus_item *n;
1708
1709 assert(bus);
1710 assert(bus->is_kernel);
1711
b2086f60 1712 update = alloca0_align(offsetof(struct kdbus_cmd, items) +
fa7796e9
LP
1713 ALIGN8(offsetof(struct kdbus_item, data64) + sizeof(uint64_t)),
1714 8);
b5dae4c7
LP
1715
1716 n = update->items;
1717 n->type = KDBUS_ITEM_ATTACH_FLAGS_RECV;
1718 n->size = offsetof(struct kdbus_item, data64) + sizeof(uint64_t);
1719 n->data64[0] = bus->attach_flags;
1720
fa7796e9 1721 update->size =
b2086f60 1722 offsetof(struct kdbus_cmd, items) +
fa7796e9 1723 ALIGN8(n->size);
b5dae4c7 1724
b2086f60 1725 if (ioctl(bus->input_fd, KDBUS_CMD_UPDATE, update) < 0)
b5dae4c7
LP
1726 return -errno;
1727
1728 return 0;
1729}
1a299299
LP
1730
1731int bus_kernel_fix_attach_mask(void) {
1732 _cleanup_free_ char *mask = NULL;
412c18f1 1733 uint64_t m = (uint64_t) -1;
1a299299
LP
1734 char buf[2+16+2];
1735 int r;
1736
412c18f1
LP
1737 /* By default we don't want any kdbus metadata fields to be
1738 * suppressed, hence we reset the kernel mask for it to
314808ce
DH
1739 * (uint64_t) -1. If the module argument was overwritten by
1740 * the kernel cmdline, we leave it as is. */
412c18f1 1741
314808ce 1742 r = get_proc_cmdline_key("kdbus.attach_flags_mask=", &mask);
1214b53c
LP
1743 if (r < 0)
1744 return log_warning_errno(r, "Failed to read kernel command line: %m");
1a299299 1745
314808ce
DH
1746 if (r == 0) {
1747 sprintf(buf, "0x%" PRIx64 "\n", m);
1748 r = write_string_file("/sys/module/kdbus/parameters/attach_flags_mask", buf);
1749 if (r < 0)
1750 return log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r,
1751 "Failed to write kdbus attach mask: %m");
1a299299
LP
1752 }
1753
1a299299
LP
1754 return 0;
1755}
3acc1daf
LP
1756
1757int bus_kernel_get_bus_name(sd_bus *bus, char **name) {
1758 struct kdbus_cmd_info cmd = {
1759 .size = sizeof(struct kdbus_cmd_info),
1760 };
1761 struct kdbus_info *info;
1762 struct kdbus_item *item;
1763 char *n = NULL;
1764 int r;
1765
1766 assert(bus);
1767 assert(name);
1768 assert(bus->is_kernel);
1769
1770 r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
1771 if (r < 0)
1772 return -errno;
1773
1774 info = (struct kdbus_info*) ((uint8_t*) bus->kdbus_buffer + cmd.offset);
1775
1776 KDBUS_ITEM_FOREACH(item, info, items)
1777 if (item->type == KDBUS_ITEM_MAKE_NAME) {
1778 r = free_and_strdup(&n, item->str);
1779 break;
1780 }
1781
1782 bus_kernel_cmd_free(bus, cmd.offset);
1783
1784 if (r < 0)
1785 return r;
1786 if (!n)
1787 return -EIO;
1788
1789 *name = n;
1790 return 0;
1791}