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