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