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