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