]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/bus-kernel.c
libsystemd-bus: make sd_bus_list_names return all connections, including unique names
[thirdparty/systemd.git] / src / libsystemd-bus / bus-kernel.c
CommitLineData
6629161f
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
7211f918
LP
22#ifdef HAVE_VALGRIND_MEMCHECK_H
23#include <valgrind/memcheck.h>
24#endif
25
6629161f 26#include <fcntl.h>
c556fe79 27#include <malloc.h>
fd8d62d9 28#include <sys/mman.h>
6629161f
LP
29
30#include "util.h"
31
32#include "bus-internal.h"
33#include "bus-message.h"
34#include "bus-kernel.h"
a56f19c4 35#include "bus-bloom.h"
6629161f 36
c7819669 37int bus_kernel_parse_unique_name(const char *s, uint64_t *id) {
6629161f
LP
38 int r;
39
40 assert(s);
41 assert(id);
42
43 if (!startswith(s, ":1."))
44 return 0;
45
46 r = safe_atou64(s + 3, id);
47 if (r < 0)
48 return r;
49
50 return 1;
51}
52
febfd508 53static void append_payload_vec(struct kdbus_item **d, const void *p, size_t sz) {
6629161f 54 assert(d);
6629161f
LP
55 assert(sz > 0);
56
e86b80b8
LP
57 *d = ALIGN8_PTR(*d);
58
66b26c5c
LP
59 /* Note that p can be NULL, which encodes a region full of
60 * zeroes, which is useful to optimize certain padding
61 * conditions */
62
febfd508 63 (*d)->size = offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec);
6629161f 64 (*d)->type = KDBUS_MSG_PAYLOAD_VEC;
a392d361 65 (*d)->vec.address = PTR_TO_UINT64(p);
6629161f
LP
66 (*d)->vec.size = sz;
67
febfd508 68 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
6629161f
LP
69}
70
a392d361
LP
71static void append_payload_memfd(struct kdbus_item **d, int memfd, size_t sz) {
72 assert(d);
73 assert(memfd >= 0);
74 assert(sz > 0);
75
76 *d = ALIGN8_PTR(*d);
77 (*d)->size = offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd);
78 (*d)->type = KDBUS_MSG_PAYLOAD_MEMFD;
79 (*d)->memfd.fd = memfd;
80 (*d)->memfd.size = sz;
81
82 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
83}
84
febfd508 85static void append_destination(struct kdbus_item **d, const char *s, size_t length) {
6629161f 86 assert(d);
b5baa8fe 87 assert(s);
6629161f 88
e86b80b8
LP
89 *d = ALIGN8_PTR(*d);
90
febfd508 91 (*d)->size = offsetof(struct kdbus_item, str) + length + 1;
6629161f 92 (*d)->type = KDBUS_MSG_DST_NAME;
51038c03 93 memcpy((*d)->str, s, length + 1);
6629161f 94
febfd508 95 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
6629161f
LP
96}
97
febfd508 98static void* append_bloom(struct kdbus_item **d, size_t length) {
a56f19c4
LP
99 void *r;
100
b5baa8fe 101 assert(d);
b5baa8fe
LP
102
103 *d = ALIGN8_PTR(*d);
104
febfd508 105 (*d)->size = offsetof(struct kdbus_item, data) + length;
b5baa8fe 106 (*d)->type = KDBUS_MSG_BLOOM;
a56f19c4 107 r = (*d)->data;
b5baa8fe 108
febfd508 109 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
a56f19c4
LP
110
111 return r;
112}
113
febfd508 114static void append_fds(struct kdbus_item **d, const int fds[], unsigned n_fds) {
9097fe29
LP
115 assert(d);
116 assert(fds);
117 assert(n_fds > 0);
118
119 *d = ALIGN8_PTR(*d);
febfd508 120 (*d)->size = offsetof(struct kdbus_item, fds) + sizeof(int) * n_fds;
fd8d62d9 121 (*d)->type = KDBUS_MSG_FDS;
9097fe29
LP
122 memcpy((*d)->fds, fds, sizeof(int) * n_fds);
123
febfd508 124 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
9097fe29
LP
125}
126
a56f19c4
LP
127static int bus_message_setup_bloom(sd_bus_message *m, void *bloom) {
128 unsigned i;
129 int r;
130
131 assert(m);
132 assert(bloom);
133
134 memset(bloom, 0, BLOOM_SIZE);
135
136 bloom_add_pair(bloom, "message-type", bus_message_type_to_string(m->header->type));
137
138 if (m->interface)
139 bloom_add_pair(bloom, "interface", m->interface);
140 if (m->member)
141 bloom_add_pair(bloom, "member", m->member);
142 if (m->path) {
143 bloom_add_pair(bloom, "path", m->path);
f11e11e3 144 bloom_add_pair(bloom, "path-slash-prefix", m->path);
a56f19c4
LP
145 bloom_add_prefixes(bloom, "path-slash-prefix", m->path, '/');
146 }
147
148 r = sd_bus_message_rewind(m, true);
149 if (r < 0)
150 return r;
151
152 for (i = 0; i < 64; i++) {
153 char type;
154 const char *t;
155 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
156 char *e;
157
158 r = sd_bus_message_peek_type(m, &type, NULL);
159 if (r < 0)
160 return r;
161
162 if (type != SD_BUS_TYPE_STRING &&
163 type != SD_BUS_TYPE_OBJECT_PATH &&
164 type != SD_BUS_TYPE_SIGNATURE)
165 break;
166
167 r = sd_bus_message_read_basic(m, type, &t);
168 if (r < 0)
169 return r;
170
171 e = stpcpy(buf, "arg");
172 if (i < 10)
173 *(e++) = '0' + i;
174 else {
175 *(e++) = '0' + (i / 10);
176 *(e++) = '0' + (i % 10);
177 }
178
179 *e = 0;
180 bloom_add_pair(bloom, buf, t);
181
182 strcpy(e, "-dot-prefix");
183 bloom_add_prefixes(bloom, buf, t, '.');
184 strcpy(e, "-slash-prefix");
185 bloom_add_prefixes(bloom, buf, t, '/');
186 }
187
188 return 0;
b5baa8fe
LP
189}
190
5b7d4c1c 191static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
9b29bb68 192 struct bus_body_part *part;
febfd508 193 struct kdbus_item *d;
6629161f
LP
194 bool well_known;
195 uint64_t unique;
196 size_t sz, dl;
9b29bb68 197 unsigned i;
6629161f
LP
198 int r;
199
5b7d4c1c 200 assert(b);
6629161f
LP
201 assert(m);
202 assert(m->sealed);
e9a967f9
LP
203
204 if (m->kdbus)
205 return 0;
6629161f
LP
206
207 if (m->destination) {
c7819669 208 r = bus_kernel_parse_unique_name(m->destination, &unique);
6629161f
LP
209 if (r < 0)
210 return r;
211
212 well_known = r == 0;
213 } else
214 well_known = false;
215
b1454bf0 216 sz = offsetof(struct kdbus_msg, items);
6629161f 217
a392d361
LP
218 assert_cc(ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec)) ==
219 ALIGN8(offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd)));
220
69aec65c 221 /* Add in fixed header, fields header and payload */
c91cb83c 222 sz += (1 + m->n_body_parts) *
bc7fd8cd 223 ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec));
6629161f 224
69aec65c 225 /* Add space for bloom filter */
febfd508 226 sz += ALIGN8(offsetof(struct kdbus_item, data) + BLOOM_SIZE);
b5baa8fe 227
6629161f
LP
228 /* Add in well-known destination header */
229 if (well_known) {
230 dl = strlen(m->destination);
febfd508 231 sz += ALIGN8(offsetof(struct kdbus_item, str) + dl + 1);
6629161f
LP
232 }
233
9097fe29
LP
234 /* Add space for unix fds */
235 if (m->n_fds > 0)
febfd508 236 sz += ALIGN8(offsetof(struct kdbus_item, fds) + sizeof(int)*m->n_fds);
9097fe29 237
c556fe79 238 m->kdbus = memalign(8, sz);
66b26c5c
LP
239 if (!m->kdbus) {
240 r = -ENOMEM;
241 goto fail;
242 }
6629161f 243
66b26c5c 244 m->free_kdbus = true;
d9115e18
LP
245 memset(m->kdbus, 0, sz);
246
6629161f
LP
247 m->kdbus->flags =
248 ((m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_FLAGS_EXPECT_REPLY) |
249 ((m->header->flags & SD_BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_FLAGS_NO_AUTO_START : 0);
250 m->kdbus->dst_id =
251 well_known ? 0 :
b5baa8fe 252 m->destination ? unique : KDBUS_DST_ID_BROADCAST;
6629161f
LP
253 m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS1;
254 m->kdbus->cookie = m->header->serial;
255
256 m->kdbus->timeout_ns = m->timeout * NSEC_PER_USEC;
257
b1454bf0 258 d = m->kdbus->items;
6629161f
LP
259
260 if (well_known)
261 append_destination(&d, m->destination, dl);
262
c91cb83c 263 append_payload_vec(&d, m->header, BUS_MESSAGE_BODY_BEGIN(m));
a392d361
LP
264
265 MESSAGE_FOREACH_PART(part, i, m) {
266 if (part->is_zero) {
66b26c5c
LP
267 /* If this is padding then simply send a
268 * vector with a NULL data pointer which the
269 * kernel will just pass through. This is the
270 * most efficient way to encode zeroes */
271
a392d361
LP
272 append_payload_vec(&d, NULL, part->size);
273 continue;
274 }
275
66b26c5c
LP
276 if (part->memfd >= 0 && part->sealed && m->destination) {
277 /* Try to send a memfd, if the part is
278 * sealed and this is not a broadcast. Since we can only */
a392d361 279
66b26c5c
LP
280 append_payload_memfd(&d, part->memfd, part->size);
281 continue;
a392d361
LP
282 }
283
66b26c5c
LP
284 /* Otherwise let's send a vector to the actual data,
285 * for that we need to map it first. */
286 r = bus_body_part_map(part);
287 if (r < 0)
288 goto fail;
a392d361 289
bc7fd8cd 290 append_payload_vec(&d, part->data, part->size);
a392d361 291 }
6629161f 292
5b7d4c1c
LP
293 if (m->kdbus->dst_id == KDBUS_DST_ID_BROADCAST) {
294 void *p;
295
a56f19c4
LP
296 p = append_bloom(&d, BLOOM_SIZE);
297 r = bus_message_setup_bloom(m, p);
a392d361
LP
298 if (r < 0)
299 goto fail;
5b7d4c1c 300 }
b5baa8fe 301
9097fe29
LP
302 if (m->n_fds > 0)
303 append_fds(&d, m->fds, m->n_fds);
304
e9a967f9 305 m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus;
6629161f
LP
306 assert(m->kdbus->size <= sz);
307
308 return 0;
a392d361
LP
309
310fail:
66b26c5c 311 m->poisoned = true;
a392d361 312 return r;
6629161f
LP
313}
314
315int bus_kernel_take_fd(sd_bus *b) {
62b3e928 316 struct kdbus_cmd_hello hello;
6629161f
LP
317 int r;
318
319 assert(b);
320
f08838da
LP
321 if (b->is_server)
322 return -EINVAL;
323
8f155917
LP
324 b->use_memfd = 1;
325
62b3e928
KS
326 zero(hello);
327 hello.size = sizeof(hello);
328 hello.conn_flags = b->hello_flags;
329 hello.pool_size = KDBUS_POOL_SIZE;
330
331 r = ioctl(b->input_fd, KDBUS_CMD_HELLO, &hello);
332 if (r < 0)
333 return -errno;
334
fd8d62d9 335 if (!b->kdbus_buffer) {
62b3e928 336 b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, b->input_fd, 0);
fd8d62d9
LP
337 if (b->kdbus_buffer == MAP_FAILED) {
338 b->kdbus_buffer = NULL;
339 return -errno;
340 }
341 }
342
5b7d4c1c
LP
343 /* The higher 32bit of both flags fields are considered
344 * 'incompatible flags'. Refuse them all for now. */
62b3e928
KS
345 if (hello.bus_flags > 0xFFFFFFFFULL ||
346 hello.conn_flags > 0xFFFFFFFFULL)
5b7d4c1c
LP
347 return -ENOTSUP;
348
62b3e928 349 if (hello.bloom_size != BLOOM_SIZE)
a56f19c4
LP
350 return -ENOTSUP;
351
62b3e928 352 if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello.id) < 0)
de297575
LP
353 return -ENOMEM;
354
6629161f 355 b->is_kernel = true;
f08838da 356 b->bus_client = true;
62b3e928 357 b->can_fds = !!(hello.conn_flags & KDBUS_HELLO_ACCEPT_FD);
6629161f
LP
358
359 r = bus_start_running(b);
360 if (r < 0)
361 return r;
362
363 return 1;
364}
365
366int bus_kernel_connect(sd_bus *b) {
367 assert(b);
368 assert(b->input_fd < 0);
369 assert(b->output_fd < 0);
370 assert(b->kernel);
371
f08838da
LP
372 if (b->is_server)
373 return -EINVAL;
374
6629161f 375 b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
c320885c 376 if (b->input_fd < 0)
6629161f
LP
377 return -errno;
378
379 b->output_fd = b->input_fd;
380
381 return bus_kernel_take_fd(b);
382}
383
384int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
385 int r;
386
387 assert(bus);
388 assert(m);
389 assert(bus->state == BUS_RUNNING);
390
5b7d4c1c 391 r = bus_message_setup_kmsg(bus, m);
6629161f
LP
392 if (r < 0)
393 return r;
394
395 r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
396 if (r < 0)
397 return errno == EAGAIN ? 0 : -errno;
398
51038c03 399 return 1;
6629161f
LP
400}
401
fd8d62d9 402static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
62b3e928 403 uint64_t off;
febfd508 404 struct kdbus_item *d;
6629161f 405
fd8d62d9
LP
406 assert(bus);
407 assert(k);
408
62b3e928
KS
409 off = (uint8_t *)k - (uint8_t *)bus->kdbus_buffer;
410 ioctl(bus->input_fd, KDBUS_CMD_MSG_RELEASE, &off);
fd8d62d9 411
9eb34e82 412 KDBUS_PART_FOREACH(d, k, items) {
6629161f 413
1307c3ff
LP
414 if (d->type == KDBUS_MSG_FDS)
415 close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
416 else if (d->type == KDBUS_MSG_PAYLOAD_MEMFD)
417 close_nointr_nofail(d->memfd.fd);
6629161f
LP
418 }
419}
420
421static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_message **ret) {
422 sd_bus_message *m = NULL;
febfd508 423 struct kdbus_item *d;
1307c3ff 424 unsigned n_fds = 0;
6629161f
LP
425 _cleanup_free_ int *fds = NULL;
426 struct bus_header *h = NULL;
427 size_t total, n_bytes = 0, idx = 0;
69aec65c 428 const char *destination = NULL, *seclabel = NULL;
6629161f
LP
429 int r;
430
431 assert(bus);
432 assert(k);
433 assert(ret);
434
435 if (k->payload_type != KDBUS_PAYLOAD_DBUS1)
436 return 0;
437
9eb34e82 438 KDBUS_PART_FOREACH(d, k, items) {
6629161f
LP
439 size_t l;
440
febfd508 441 l = d->size - offsetof(struct kdbus_item, data);
6629161f 442
62b3e928 443 if (d->type == KDBUS_MSG_PAYLOAD_OFF) {
6629161f
LP
444
445 if (!h) {
62b3e928 446 h = (struct bus_header *)((uint8_t *)bus->kdbus_buffer + d->vec.offset);
c91cb83c
LP
447
448 if (!bus_header_is_complete(h, d->vec.size))
449 return -EBADMSG;
6629161f
LP
450 }
451
fd8d62d9 452 n_bytes += d->vec.size;
6629161f 453
1307c3ff
LP
454 } else if (d->type == KDBUS_MSG_PAYLOAD_MEMFD) {
455
456 if (!h)
457 return -EBADMSG;
458
459 n_bytes += d->memfd.size;
460
fd8d62d9 461 } else if (d->type == KDBUS_MSG_FDS) {
6629161f
LP
462 int *f;
463 unsigned j;
464
465 j = l / sizeof(int);
466 f = realloc(fds, sizeof(int) * (n_fds + j));
467 if (!f)
468 return -ENOMEM;
469
470 fds = f;
9097fe29 471 memcpy(fds + n_fds, d->fds, sizeof(int) * j);
6629161f 472 n_fds += j;
f9be01f3 473
1307c3ff 474 } else if (d->type == KDBUS_MSG_SRC_SECLABEL)
69aec65c 475 seclabel = d->str;
6629161f
LP
476 }
477
478 if (!h)
479 return -EBADMSG;
480
c91cb83c 481 r = bus_header_message_size(h, &total);
6629161f
LP
482 if (r < 0)
483 return r;
484
485 if (n_bytes != total)
486 return -EBADMSG;
487
df2d202e 488 r = bus_message_from_header(bus, h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m);
6629161f
LP
489 if (r < 0)
490 return r;
491
9eb34e82 492 KDBUS_PART_FOREACH(d, k, items) {
6629161f
LP
493 size_t l;
494
febfd508 495 l = d->size - offsetof(struct kdbus_item, data);
6629161f 496
62b3e928 497 if (d->type == KDBUS_MSG_PAYLOAD_OFF) {
bc7fd8cd 498 size_t begin_body;
fd8d62d9 499
c91cb83c 500 begin_body = BUS_MESSAGE_BODY_BEGIN(m);
bc7fd8cd
LP
501
502 if (idx + d->vec.size > begin_body) {
503 struct bus_body_part *part;
504
505 /* Contains body material */
506
507 part = message_append_part(m);
508 if (!part) {
1307c3ff
LP
509 r = -ENOMEM;
510 goto fail;
bc7fd8cd
LP
511 }
512
62b3e928
KS
513 /* A -1 offset is NUL padding. */
514 part->is_zero = d->vec.offset == ~0ULL;
515
bc7fd8cd 516 if (idx >= begin_body) {
62b3e928
KS
517 if (!part->is_zero)
518 part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset;
bc7fd8cd
LP
519 part->size = d->vec.size;
520 } else {
62b3e928
KS
521 if (!part->is_zero)
522 part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset + (begin_body - idx);
bc7fd8cd
LP
523 part->size = d->vec.size - (begin_body - idx);
524 }
525
526 part->sealed = true;
527 }
fd8d62d9
LP
528
529 idx += d->vec.size;
1307c3ff
LP
530 } else if (d->type == KDBUS_MSG_PAYLOAD_MEMFD) {
531 struct bus_body_part *part;
532
533 if (idx < BUS_MESSAGE_BODY_BEGIN(m)) {
534 r = -EBADMSG;
535 goto fail;
536 }
537
538 part = message_append_part(m);
539 if (!part) {
540 r = -ENOMEM;
541 goto fail;
542 }
543
544 part->memfd = d->memfd.fd;
545 part->size = d->memfd.size;
546 part->sealed = true;
547
548 idx += d->memfd.size;
69aec65c 549
69aec65c 550 } else if (d->type == KDBUS_MSG_SRC_CREDS) {
5b12334d
LP
551 m->creds.pid_starttime = d->creds.starttime / NSEC_PER_USEC;
552 m->creds.uid = d->creds.uid;
553 m->creds.gid = d->creds.gid;
554 m->creds.pid = d->creds.pid;
555 m->creds.tid = d->creds.tid;
556 m->creds.mask |= (SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID) & bus->creds_mask;
557
69aec65c
LP
558 } else if (d->type == KDBUS_MSG_TIMESTAMP) {
559 m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC;
560 m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC;
5b12334d
LP
561
562 } else if (d->type == KDBUS_MSG_SRC_PID_COMM) {
563 m->creds.comm = d->str;
564 m->creds.mask |= SD_BUS_CREDS_COMM & bus->creds_mask;
565
566 } else if (d->type == KDBUS_MSG_SRC_TID_COMM) {
567 m->creds.tid_comm = d->str;
568 m->creds.mask |= SD_BUS_CREDS_TID_COMM & bus->creds_mask;
569
570 } else if (d->type == KDBUS_MSG_SRC_EXE) {
571 m->creds.exe = d->str;
572 m->creds.mask |= SD_BUS_CREDS_EXE & bus->creds_mask;
573
574 } else if (d->type == KDBUS_MSG_SRC_CMDLINE) {
575 m->creds.cmdline = d->str;
576 m->creds.cmdline_length = l;
577 m->creds.mask |= SD_BUS_CREDS_CMDLINE & bus->creds_mask;
578
579 } else if (d->type == KDBUS_MSG_SRC_CGROUP) {
580 m->creds.cgroup = d->str;
581 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;
582
583 } else if (d->type == KDBUS_MSG_SRC_AUDIT) {
584 m->creds.audit_session_id = d->audit.sessionid;
585 m->creds.audit_login_uid = d->audit.loginuid;
586 m->creds.mask |= (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID) & bus->creds_mask;
587
588 } else if (d->type == KDBUS_MSG_SRC_CAPS) {
589 m->creds.capability = d->data;
590 m->creds.capability_size = l;
591 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;
592
1307c3ff
LP
593 } else if (d->type == KDBUS_MSG_DST_NAME)
594 destination = d->str;
595 else if (d->type != KDBUS_MSG_FDS &&
27df44a2
LS
596 d->type != KDBUS_MSG_SRC_SECLABEL &&
597 d->type != KDBUS_MSG_SRC_NAMES)
77930f11 598 log_debug("Got unknown field from kernel %llu", d->type);
69aec65c 599 }
acb5a3cb 600
6629161f 601 r = bus_message_parse_fields(m);
1307c3ff
LP
602 if (r < 0)
603 goto fail;
6629161f 604
51038c03
LP
605 if (k->src_id == KDBUS_SRC_ID_KERNEL)
606 m->sender = "org.freedesktop.DBus";
607 else {
608 snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
609 m->sender = m->sender_buffer;
610 }
611
612 if (!m->destination) {
613 if (destination)
614 m->destination = destination;
615 else if (k->dst_id != KDBUS_DST_ID_WELL_KNOWN_NAME &&
616 k->dst_id != KDBUS_DST_ID_BROADCAST) {
617 snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
618 m->destination = m->destination_buffer;
619 }
620 }
621
6629161f
LP
622 /* We take possession of the kmsg struct now */
623 m->kdbus = k;
fd8d62d9 624 m->release_kdbus = true;
6629161f
LP
625 m->free_fds = true;
626
627 fds = NULL;
628
629 *ret = m;
630 return 1;
1307c3ff
LP
631
632fail:
633 if (m) {
634 struct bus_body_part *part;
635 unsigned i;
636
637 /* Make sure the memfds are not freed twice */
638 MESSAGE_FOREACH_PART(part, i, m)
639 if (part->memfd >= 0)
640 part->memfd = -1;
641
642 sd_bus_message_unref(m);
643 }
644
645 return r;
6629161f
LP
646}
647
648int bus_kernel_read_message(sd_bus *bus, sd_bus_message **m) {
62b3e928 649 uint64_t off;
6629161f 650 struct kdbus_msg *k;
6629161f
LP
651 int r;
652
653 assert(bus);
654 assert(m);
655
62b3e928 656 r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, &off);
fd8d62d9 657 if (r < 0) {
6629161f
LP
658 if (errno == EAGAIN)
659 return 0;
660
fd8d62d9 661 return -errno;
6629161f 662 }
62b3e928 663 k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + off);
6629161f
LP
664
665 r = bus_kernel_make_message(bus, k, m);
fd8d62d9
LP
666 if (r <= 0)
667 close_kdbus_msg(bus, k);
6629161f 668
51038c03 669 return r < 0 ? r : 1;
6629161f
LP
670}
671
672int bus_kernel_create(const char *name, char **s) {
5b7d4c1c 673 struct kdbus_cmd_bus_make *make;
efa3c0af 674 struct kdbus_item *n;
6629161f
LP
675 size_t l;
676 int fd;
677 char *p;
678
679 assert(name);
680 assert(s);
681
682 fd = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
683 if (fd < 0)
684 return -errno;
685
686 l = strlen(name);
a2cef833 687 make = alloca0(offsetof(struct kdbus_cmd_bus_make, items) +
9eb34e82
DM
688 KDBUS_PART_HEADER_SIZE + sizeof(uint64_t) +
689 KDBUS_PART_HEADER_SIZE + DECIMAL_STR_MAX(uid_t) + 1 + l + 1);
a2cef833 690
efa3c0af 691 n = make->items;
799e7ea8 692 n->type = KDBUS_MAKE_NAME;
a2cef833 693 sprintf(n->str, "%lu-%s", (unsigned long) getuid(), name);
9eb34e82 694 n->size = KDBUS_PART_HEADER_SIZE + strlen(n->str) + 1;
a2cef833 695
efa3c0af 696 make->size = offsetof(struct kdbus_cmd_bus_make, items) + n->size;
18cd014f 697 make->flags = KDBUS_MAKE_POLICY_OPEN;
5b7d4c1c 698 make->bus_flags = 0;
a56f19c4 699 make->bloom_size = BLOOM_SIZE;
a56f19c4 700 assert_cc(BLOOM_SIZE % 8 == 0);
5b7d4c1c 701
a2cef833 702 p = strjoin("/dev/kdbus/", n->str, "/bus", NULL);
6629161f
LP
703 if (!p)
704 return -ENOMEM;
705
5b7d4c1c 706 if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
6629161f
LP
707 close_nointr_nofail(fd);
708 free(p);
709 return -errno;
710 }
711
712 if (s)
713 *s = p;
714
715 return fd;
716}
bc7fd8cd
LP
717
718int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *size) {
719 struct memfd_cache *c;
45fbe937 720 int fd;
bc7fd8cd
LP
721
722 assert(address);
723 assert(size);
724
725 if (!bus || !bus->is_kernel)
726 return -ENOTSUP;
727
76b7742c 728 assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
45fbe937 729
bc7fd8cd 730 if (bus->n_memfd_cache <= 0) {
45fbe937
LP
731 int r;
732
76b7742c 733 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
bc7fd8cd 734
9b05bc48
LP
735 r = ioctl(bus->input_fd, KDBUS_CMD_MEMFD_NEW, &fd);
736 if (r < 0)
bc7fd8cd
LP
737 return -errno;
738
739 *address = NULL;
740 *size = 0;
741 return fd;
742 }
743
bf30e48f 744 c = &bus->memfd_cache[--bus->n_memfd_cache];
bc7fd8cd
LP
745
746 assert(c->fd >= 0);
747 assert(c->size == 0 || c->address);
748
749 *address = c->address;
750 *size = c->size;
45fbe937
LP
751 fd = c->fd;
752
76b7742c 753 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
bc7fd8cd 754
45fbe937
LP
755 return fd;
756}
757
758static void close_and_munmap(int fd, void *address, size_t size) {
759 if (size > 0)
76b7742c 760 assert_se(munmap(address, PAGE_ALIGN(size)) >= 0);
45fbe937
LP
761
762 close_nointr_nofail(fd);
bc7fd8cd
LP
763}
764
765void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t size) {
766 struct memfd_cache *c;
76b7742c 767 uint64_t max_sz = PAGE_ALIGN(MEMFD_CACHE_ITEM_SIZE_MAX);
bc7fd8cd
LP
768
769 assert(fd >= 0);
770 assert(size == 0 || address);
771
45fbe937
LP
772 if (!bus || !bus->is_kernel) {
773 close_and_munmap(fd, address, size);
774 return;
775 }
776
76b7742c 777 assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
bc7fd8cd 778
45fbe937 779 if (bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
76b7742c 780 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
bc7fd8cd 781
45fbe937 782 close_and_munmap(fd, address, size);
bc7fd8cd
LP
783 return;
784 }
785
786 c = &bus->memfd_cache[bus->n_memfd_cache++];
787 c->fd = fd;
788 c->address = address;
789
790 /* If overly long, let's return a bit to the OS */
76b7742c
LP
791 if (size > max_sz) {
792 assert_se(ioctl(fd, KDBUS_CMD_MEMFD_SIZE_SET, &max_sz) >= 0);
793 assert_se(munmap((uint8_t*) address + max_sz, PAGE_ALIGN(size - max_sz)) >= 0);
794 c->size = max_sz;
bc7fd8cd
LP
795 } else
796 c->size = size;
45fbe937 797
76b7742c 798 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
bc7fd8cd
LP
799}
800
801void bus_kernel_flush_memfd(sd_bus *b) {
802 unsigned i;
803
804 assert(b);
805
76b7742c
LP
806 for (i = 0; i < b->n_memfd_cache; i++)
807 close_and_munmap(b->memfd_cache[i].fd, b->memfd_cache[i].address, b->memfd_cache[i].size);
bc7fd8cd 808}