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