]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/bus-kernel.c
bus: properly unmap mapped area
[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) {
fd8d62d9
LP
316 uint8_t h[ALIGN8(sizeof(struct kdbus_cmd_hello)) +
317 ALIGN8(KDBUS_ITEM_HEADER_SIZE) +
318 ALIGN8(sizeof(struct kdbus_vec))] = {};
319
320 struct kdbus_cmd_hello *hello = (struct kdbus_cmd_hello*) h;
321
6629161f
LP
322 int r;
323
324 assert(b);
325
f08838da
LP
326 if (b->is_server)
327 return -EINVAL;
328
8f155917
LP
329 b->use_memfd = 1;
330
fd8d62d9 331 if (!b->kdbus_buffer) {
13019ef5 332 b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
fd8d62d9
LP
333 if (b->kdbus_buffer == MAP_FAILED) {
334 b->kdbus_buffer = NULL;
335 return -errno;
336 }
337 }
338
339 hello->size = sizeof(h);
264ad849 340 hello->conn_flags = b->hello_flags;
fd8d62d9 341
13019ef5 342 hello->items[0].type = KDBUS_HELLO_POOL;
fd8d62d9
LP
343 hello->items[0].size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
344 hello->items[0].vec.address = (uint64_t) b->kdbus_buffer;
13019ef5 345 hello->items[0].vec.size = KDBUS_POOL_SIZE;
fd8d62d9
LP
346
347 r = ioctl(b->input_fd, KDBUS_CMD_HELLO, hello);
6629161f
LP
348 if (r < 0)
349 return -errno;
350
5b7d4c1c
LP
351 /* The higher 32bit of both flags fields are considered
352 * 'incompatible flags'. Refuse them all for now. */
fd8d62d9
LP
353 if (hello->bus_flags > 0xFFFFFFFFULL ||
354 hello->conn_flags > 0xFFFFFFFFULL)
5b7d4c1c
LP
355 return -ENOTSUP;
356
fd8d62d9 357 if (hello->bloom_size != BLOOM_SIZE)
a56f19c4
LP
358 return -ENOTSUP;
359
fd8d62d9 360 if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello->id) < 0)
de297575
LP
361 return -ENOMEM;
362
6629161f 363 b->is_kernel = true;
f08838da 364 b->bus_client = true;
264ad849 365 b->can_fds = !!(hello->conn_flags & KDBUS_HELLO_ACCEPT_FD);
6629161f
LP
366
367 r = bus_start_running(b);
368 if (r < 0)
369 return r;
370
371 return 1;
372}
373
374int bus_kernel_connect(sd_bus *b) {
375 assert(b);
376 assert(b->input_fd < 0);
377 assert(b->output_fd < 0);
378 assert(b->kernel);
379
f08838da
LP
380 if (b->is_server)
381 return -EINVAL;
382
6629161f 383 b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
c320885c 384 if (b->input_fd < 0)
6629161f
LP
385 return -errno;
386
387 b->output_fd = b->input_fd;
388
389 return bus_kernel_take_fd(b);
390}
391
392int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
393 int r;
394
395 assert(bus);
396 assert(m);
397 assert(bus->state == BUS_RUNNING);
398
5b7d4c1c 399 r = bus_message_setup_kmsg(bus, m);
6629161f
LP
400 if (r < 0)
401 return r;
402
403 r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
404 if (r < 0)
405 return errno == EAGAIN ? 0 : -errno;
406
51038c03 407 return 1;
6629161f
LP
408}
409
fd8d62d9 410static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
febfd508 411 struct kdbus_item *d;
6629161f 412
fd8d62d9
LP
413 assert(bus);
414 assert(k);
415
416 ioctl(bus->input_fd, KDBUS_CMD_MSG_RELEASE, k);
417
6133cee2 418 KDBUS_ITEM_FOREACH(d, k) {
6629161f 419
1307c3ff
LP
420 if (d->type == KDBUS_MSG_FDS)
421 close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
422 else if (d->type == KDBUS_MSG_PAYLOAD_MEMFD)
423 close_nointr_nofail(d->memfd.fd);
6629161f
LP
424 }
425}
426
427static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_message **ret) {
428 sd_bus_message *m = NULL;
febfd508 429 struct kdbus_item *d;
1307c3ff 430 unsigned n_fds = 0;
6629161f
LP
431 _cleanup_free_ int *fds = NULL;
432 struct bus_header *h = NULL;
433 size_t total, n_bytes = 0, idx = 0;
69aec65c 434 const char *destination = NULL, *seclabel = NULL;
6629161f
LP
435 int r;
436
437 assert(bus);
438 assert(k);
439 assert(ret);
440
441 if (k->payload_type != KDBUS_PAYLOAD_DBUS1)
442 return 0;
443
6133cee2 444 KDBUS_ITEM_FOREACH(d, k) {
6629161f
LP
445 size_t l;
446
febfd508 447 l = d->size - offsetof(struct kdbus_item, data);
6629161f 448
fd8d62d9 449 if (d->type == KDBUS_MSG_PAYLOAD_VEC) {
6629161f
LP
450
451 if (!h) {
9b05bc48 452 h = UINT64_TO_PTR(d->vec.address);
c91cb83c
LP
453
454 if (!bus_header_is_complete(h, d->vec.size))
455 return -EBADMSG;
6629161f
LP
456 }
457
fd8d62d9 458 n_bytes += d->vec.size;
6629161f 459
1307c3ff
LP
460 } else if (d->type == KDBUS_MSG_PAYLOAD_MEMFD) {
461
462 if (!h)
463 return -EBADMSG;
464
465 n_bytes += d->memfd.size;
466
fd8d62d9 467 } else if (d->type == KDBUS_MSG_FDS) {
6629161f
LP
468 int *f;
469 unsigned j;
470
471 j = l / sizeof(int);
472 f = realloc(fds, sizeof(int) * (n_fds + j));
473 if (!f)
474 return -ENOMEM;
475
476 fds = f;
9097fe29 477 memcpy(fds + n_fds, d->fds, sizeof(int) * j);
6629161f 478 n_fds += j;
f9be01f3 479
1307c3ff 480 } else if (d->type == KDBUS_MSG_SRC_SECLABEL)
69aec65c 481 seclabel = d->str;
6629161f
LP
482 }
483
484 if (!h)
485 return -EBADMSG;
486
c91cb83c 487 r = bus_header_message_size(h, &total);
6629161f
LP
488 if (r < 0)
489 return r;
490
491 if (n_bytes != total)
492 return -EBADMSG;
493
69aec65c 494 r = bus_message_from_header(h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m);
6629161f
LP
495 if (r < 0)
496 return r;
497
6133cee2 498 KDBUS_ITEM_FOREACH(d, k) {
6629161f
LP
499 size_t l;
500
febfd508 501 l = d->size - offsetof(struct kdbus_item, data);
6629161f 502
fd8d62d9 503 if (d->type == KDBUS_MSG_PAYLOAD_VEC) {
bc7fd8cd 504 size_t begin_body;
fd8d62d9 505
c91cb83c 506 begin_body = BUS_MESSAGE_BODY_BEGIN(m);
bc7fd8cd
LP
507
508 if (idx + d->vec.size > begin_body) {
509 struct bus_body_part *part;
510
511 /* Contains body material */
512
513 part = message_append_part(m);
514 if (!part) {
1307c3ff
LP
515 r = -ENOMEM;
516 goto fail;
bc7fd8cd
LP
517 }
518
519 if (idx >= begin_body) {
c91cb83c 520 part->data = UINT64_TO_PTR(d->vec.address);
bc7fd8cd
LP
521 part->size = d->vec.size;
522 } else {
453a0c29 523 part->data = d->vec.address != 0 ? (uint8_t*) UINT64_TO_PTR(d->vec.address) + (begin_body - idx) : NULL;
bc7fd8cd
LP
524 part->size = d->vec.size - (begin_body - idx);
525 }
526
453a0c29 527 part->is_zero = d->vec.address == 0;
bc7fd8cd
LP
528 part->sealed = true;
529 }
fd8d62d9
LP
530
531 idx += d->vec.size;
1307c3ff
LP
532 } else if (d->type == KDBUS_MSG_PAYLOAD_MEMFD) {
533 struct bus_body_part *part;
534
535 if (idx < BUS_MESSAGE_BODY_BEGIN(m)) {
536 r = -EBADMSG;
537 goto fail;
538 }
539
540 part = message_append_part(m);
541 if (!part) {
542 r = -ENOMEM;
543 goto fail;
544 }
545
546 part->memfd = d->memfd.fd;
547 part->size = d->memfd.size;
548 part->sealed = true;
549
550 idx += d->memfd.size;
69aec65c 551
69aec65c
LP
552 } else if (d->type == KDBUS_MSG_SRC_CREDS) {
553 m->pid_starttime = d->creds.starttime / NSEC_PER_USEC;
554 m->uid = d->creds.uid;
555 m->gid = d->creds.gid;
556 m->pid = d->creds.pid;
557 m->tid = d->creds.tid;
558 m->uid_valid = m->gid_valid = true;
559 } else if (d->type == KDBUS_MSG_TIMESTAMP) {
560 m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC;
561 m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC;
562 } else if (d->type == KDBUS_MSG_SRC_PID_COMM)
563 m->comm = d->str;
564 else if (d->type == KDBUS_MSG_SRC_TID_COMM)
565 m->tid_comm = d->str;
566 else if (d->type == KDBUS_MSG_SRC_EXE)
567 m->exe = d->str;
77930f11
LP
568 else if (d->type == KDBUS_MSG_SRC_CMDLINE) {
569 m->cmdline = d->str;
570 m->cmdline_length = l;
4a875b61
LP
571 } else if (d->type == KDBUS_MSG_SRC_CGROUP)
572 m->cgroup = d->str;
120f919e
LP
573 else if (d->type == KDBUS_MSG_SRC_AUDIT)
574 m->audit = &d->audit;
102ea8e4
LP
575 else if (d->type == KDBUS_MSG_SRC_CAPS) {
576 m->capability = d->data;
577 m->capability_size = l;
1307c3ff
LP
578 } else if (d->type == KDBUS_MSG_DST_NAME)
579 destination = d->str;
580 else if (d->type != KDBUS_MSG_FDS &&
fd8d62d9 581 d->type != KDBUS_MSG_SRC_SECLABEL)
77930f11 582 log_debug("Got unknown field from kernel %llu", d->type);
69aec65c 583 }
acb5a3cb 584
6629161f 585 r = bus_message_parse_fields(m);
1307c3ff
LP
586 if (r < 0)
587 goto fail;
6629161f 588
51038c03
LP
589 if (k->src_id == KDBUS_SRC_ID_KERNEL)
590 m->sender = "org.freedesktop.DBus";
591 else {
592 snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
593 m->sender = m->sender_buffer;
594 }
595
596 if (!m->destination) {
597 if (destination)
598 m->destination = destination;
599 else if (k->dst_id != KDBUS_DST_ID_WELL_KNOWN_NAME &&
600 k->dst_id != KDBUS_DST_ID_BROADCAST) {
601 snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
602 m->destination = m->destination_buffer;
603 }
604 }
605
6629161f
LP
606 /* We take possession of the kmsg struct now */
607 m->kdbus = k;
fd8d62d9
LP
608 m->bus = sd_bus_ref(bus);
609 m->release_kdbus = true;
6629161f
LP
610 m->free_fds = true;
611
612 fds = NULL;
613
614 *ret = m;
615 return 1;
1307c3ff
LP
616
617fail:
618 if (m) {
619 struct bus_body_part *part;
620 unsigned i;
621
622 /* Make sure the memfds are not freed twice */
623 MESSAGE_FOREACH_PART(part, i, m)
624 if (part->memfd >= 0)
625 part->memfd = -1;
626
627 sd_bus_message_unref(m);
628 }
629
630 return r;
6629161f
LP
631}
632
633int bus_kernel_read_message(sd_bus *bus, sd_bus_message **m) {
16af1d39 634 uint64_t addr;
6629161f 635 struct kdbus_msg *k;
6629161f
LP
636 int r;
637
638 assert(bus);
639 assert(m);
640
16af1d39 641 r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, &addr);
fd8d62d9 642 if (r < 0) {
6629161f
LP
643 if (errno == EAGAIN)
644 return 0;
645
fd8d62d9 646 return -errno;
6629161f 647 }
16af1d39 648 k = UINT64_TO_PTR(addr);
6629161f
LP
649
650 r = bus_kernel_make_message(bus, k, m);
fd8d62d9
LP
651 if (r <= 0)
652 close_kdbus_msg(bus, k);
6629161f 653
51038c03 654 return r < 0 ? r : 1;
6629161f
LP
655}
656
657int bus_kernel_create(const char *name, char **s) {
5b7d4c1c 658 struct kdbus_cmd_bus_make *make;
febfd508 659 struct kdbus_item *n, *cg;
6629161f
LP
660 size_t l;
661 int fd;
662 char *p;
663
664 assert(name);
665 assert(s);
666
667 fd = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
668 if (fd < 0)
669 return -errno;
670
671 l = strlen(name);
a2cef833 672 make = alloca0(offsetof(struct kdbus_cmd_bus_make, items) +
febfd508
KS
673 KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t) +
674 KDBUS_ITEM_HEADER_SIZE + DECIMAL_STR_MAX(uid_t) + 1 + l + 1);
a2cef833
KS
675
676 cg = make->items;
799e7ea8 677 cg->type = KDBUS_MAKE_CGROUP;
a2cef833 678 cg->data64[0] = 1;
febfd508 679 cg->size = KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t);
a2cef833
KS
680
681 n = KDBUS_ITEM_NEXT(cg);
799e7ea8 682 n->type = KDBUS_MAKE_NAME;
a2cef833 683 sprintf(n->str, "%lu-%s", (unsigned long) getuid(), name);
febfd508 684 n->size = KDBUS_ITEM_HEADER_SIZE + strlen(n->str) + 1;
a2cef833
KS
685
686 make->size = offsetof(struct kdbus_cmd_bus_make, items) + cg->size + n->size;
18cd014f 687 make->flags = KDBUS_MAKE_POLICY_OPEN;
5b7d4c1c 688 make->bus_flags = 0;
a56f19c4 689 make->bloom_size = BLOOM_SIZE;
a56f19c4 690 assert_cc(BLOOM_SIZE % 8 == 0);
5b7d4c1c 691
a2cef833 692 p = strjoin("/dev/kdbus/", n->str, "/bus", NULL);
6629161f
LP
693 if (!p)
694 return -ENOMEM;
695
5b7d4c1c 696 if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
6629161f
LP
697 close_nointr_nofail(fd);
698 free(p);
699 return -errno;
700 }
701
702 if (s)
703 *s = p;
704
705 return fd;
706}
bc7fd8cd
LP
707
708int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *size) {
709 struct memfd_cache *c;
45fbe937 710 int fd;
bc7fd8cd
LP
711
712 assert(address);
713 assert(size);
714
715 if (!bus || !bus->is_kernel)
716 return -ENOTSUP;
717
45fbe937
LP
718 assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) == 0);
719
bc7fd8cd 720 if (bus->n_memfd_cache <= 0) {
45fbe937
LP
721 int r;
722
723 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0);
bc7fd8cd 724
9b05bc48
LP
725 r = ioctl(bus->input_fd, KDBUS_CMD_MEMFD_NEW, &fd);
726 if (r < 0)
bc7fd8cd
LP
727 return -errno;
728
729 *address = NULL;
730 *size = 0;
731 return fd;
732 }
733
734 c = &bus->memfd_cache[-- bus->n_memfd_cache];
735
736 assert(c->fd >= 0);
737 assert(c->size == 0 || c->address);
738
739 *address = c->address;
740 *size = c->size;
45fbe937
LP
741 fd = c->fd;
742
743 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0);
bc7fd8cd 744
45fbe937
LP
745 return fd;
746}
747
748static void close_and_munmap(int fd, void *address, size_t size) {
749 if (size > 0)
750 assert_se(munmap(address, PAGE_ALIGN(size)) == 0);
751
752 close_nointr_nofail(fd);
bc7fd8cd
LP
753}
754
755void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t size) {
756 struct memfd_cache *c;
757
758 assert(fd >= 0);
759 assert(size == 0 || address);
760
45fbe937
LP
761 if (!bus || !bus->is_kernel) {
762 close_and_munmap(fd, address, size);
763 return;
764 }
765
766 assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) == 0);
bc7fd8cd 767
45fbe937
LP
768 if (bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
769 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0);
bc7fd8cd 770
45fbe937 771 close_and_munmap(fd, address, size);
bc7fd8cd
LP
772 return;
773 }
774
775 c = &bus->memfd_cache[bus->n_memfd_cache++];
776 c->fd = fd;
777 c->address = address;
778
779 /* If overly long, let's return a bit to the OS */
780 if (size > MEMFD_CACHE_ITEM_SIZE_MAX) {
781 uint64_t sz = MEMFD_CACHE_ITEM_SIZE_MAX;
782
783 ioctl(bus->input_fd, KDBUS_CMD_MEMFD_SIZE_SET, &sz);
784
785 c->size = MEMFD_CACHE_ITEM_SIZE_MAX;
786 } else
787 c->size = size;
45fbe937
LP
788
789 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0);
bc7fd8cd
LP
790}
791
792void bus_kernel_flush_memfd(sd_bus *b) {
793 unsigned i;
794
795 assert(b);
796
797 for (i = 0; i < b->n_memfd_cache; i++) {
798 if (b->memfd_cache[i].size > 0)
799 assert_se(munmap(b->memfd_cache[i].address, PAGE_ALIGN(b->memfd_cache[i].size)) == 0);
800
801 close_nointr_nofail(b->memfd_cache[i].fd);
802 }
803}