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