]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-bus/bus-kernel.c
libsystemd-bus: catch up with latest kdbus changes
[thirdparty/systemd.git] / src / libsystemd-bus / bus-kernel.c
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
22 #ifdef HAVE_VALGRIND_MEMCHECK_H
23 #include <valgrind/memcheck.h>
24 #endif
25
26 #include <fcntl.h>
27 #include <malloc.h>
28 #include <sys/mman.h>
29
30 #include "util.h"
31
32 #include "bus-internal.h"
33 #include "bus-message.h"
34 #include "bus-kernel.h"
35 #include "bus-bloom.h"
36
37 int bus_kernel_parse_unique_name(const char *s, uint64_t *id) {
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
53 static void append_payload_vec(struct kdbus_item **d, const void *p, size_t sz) {
54 assert(d);
55 assert(sz > 0);
56
57 *d = ALIGN8_PTR(*d);
58
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
63 (*d)->size = offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec);
64 (*d)->type = KDBUS_MSG_PAYLOAD_VEC;
65 (*d)->vec.address = PTR_TO_UINT64(p);
66 (*d)->vec.size = sz;
67
68 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
69 }
70
71 static 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
85 static void append_destination(struct kdbus_item **d, const char *s, size_t length) {
86 assert(d);
87 assert(s);
88
89 *d = ALIGN8_PTR(*d);
90
91 (*d)->size = offsetof(struct kdbus_item, str) + length + 1;
92 (*d)->type = KDBUS_MSG_DST_NAME;
93 memcpy((*d)->str, s, length + 1);
94
95 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
96 }
97
98 static void* append_bloom(struct kdbus_item **d, size_t length) {
99 void *r;
100
101 assert(d);
102
103 *d = ALIGN8_PTR(*d);
104
105 (*d)->size = offsetof(struct kdbus_item, data) + length;
106 (*d)->type = KDBUS_MSG_BLOOM;
107 r = (*d)->data;
108
109 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
110
111 return r;
112 }
113
114 static void append_fds(struct kdbus_item **d, const int fds[], unsigned n_fds) {
115 assert(d);
116 assert(fds);
117 assert(n_fds > 0);
118
119 *d = ALIGN8_PTR(*d);
120 (*d)->size = offsetof(struct kdbus_item, fds) + sizeof(int) * n_fds;
121 (*d)->type = KDBUS_MSG_FDS;
122 memcpy((*d)->fds, fds, sizeof(int) * n_fds);
123
124 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
125 }
126
127 static 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);
144 bloom_add_pair(bloom, "path-slash-prefix", m->path);
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;
189 }
190
191 static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
192 struct bus_body_part *part;
193 struct kdbus_item *d;
194 bool well_known;
195 uint64_t unique;
196 size_t sz, dl;
197 unsigned i;
198 int r;
199
200 assert(b);
201 assert(m);
202 assert(m->sealed);
203
204 if (m->kdbus)
205 return 0;
206
207 if (m->destination) {
208 r = bus_kernel_parse_unique_name(m->destination, &unique);
209 if (r < 0)
210 return r;
211
212 well_known = r == 0;
213 } else
214 well_known = false;
215
216 sz = offsetof(struct kdbus_msg, items);
217
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
221 /* Add in fixed header, fields header and payload */
222 sz += (1 + m->n_body_parts) *
223 ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec));
224
225 /* Add space for bloom filter */
226 sz += ALIGN8(offsetof(struct kdbus_item, data) + BLOOM_SIZE);
227
228 /* Add in well-known destination header */
229 if (well_known) {
230 dl = strlen(m->destination);
231 sz += ALIGN8(offsetof(struct kdbus_item, str) + dl + 1);
232 }
233
234 /* Add space for unix fds */
235 if (m->n_fds > 0)
236 sz += ALIGN8(offsetof(struct kdbus_item, fds) + sizeof(int)*m->n_fds);
237
238 m->kdbus = memalign(8, sz);
239 if (!m->kdbus) {
240 r = -ENOMEM;
241 goto fail;
242 }
243
244 m->free_kdbus = true;
245 memset(m->kdbus, 0, sz);
246
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 :
252 m->destination ? unique : KDBUS_DST_ID_BROADCAST;
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
258 d = m->kdbus->items;
259
260 if (well_known)
261 append_destination(&d, m->destination, dl);
262
263 append_payload_vec(&d, m->header, BUS_MESSAGE_BODY_BEGIN(m));
264
265 MESSAGE_FOREACH_PART(part, i, m) {
266 if (part->is_zero) {
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
272 append_payload_vec(&d, NULL, part->size);
273 continue;
274 }
275
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 */
279
280 append_payload_memfd(&d, part->memfd, part->size);
281 continue;
282 }
283
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;
289
290 append_payload_vec(&d, part->data, part->size);
291 }
292
293 if (m->kdbus->dst_id == KDBUS_DST_ID_BROADCAST) {
294 void *p;
295
296 p = append_bloom(&d, BLOOM_SIZE);
297 r = bus_message_setup_bloom(m, p);
298 if (r < 0)
299 goto fail;
300 }
301
302 if (m->n_fds > 0)
303 append_fds(&d, m->fds, m->n_fds);
304
305 m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus;
306 assert(m->kdbus->size <= sz);
307
308 return 0;
309
310 fail:
311 m->poisoned = true;
312 return r;
313 }
314
315 int bus_kernel_take_fd(sd_bus *b) {
316 struct kdbus_cmd_hello hello;
317 int r;
318
319 assert(b);
320
321 if (b->is_server)
322 return -EINVAL;
323
324 b->use_memfd = 1;
325
326 zero(hello);
327 hello.size = sizeof(hello);
328 hello.conn_flags = b->hello_flags;
329 hello.attach_flags = b->attach_flags;
330 hello.pool_size = KDBUS_POOL_SIZE;
331
332 r = ioctl(b->input_fd, KDBUS_CMD_HELLO, &hello);
333 if (r < 0)
334 return -errno;
335
336 if (!b->kdbus_buffer) {
337 b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, b->input_fd, 0);
338 if (b->kdbus_buffer == MAP_FAILED) {
339 b->kdbus_buffer = NULL;
340 return -errno;
341 }
342 }
343
344 /* The higher 32bit of both flags fields are considered
345 * 'incompatible flags'. Refuse them all for now. */
346 if (hello.bus_flags > 0xFFFFFFFFULL ||
347 hello.conn_flags > 0xFFFFFFFFULL)
348 return -ENOTSUP;
349
350 if (hello.bloom_size != BLOOM_SIZE)
351 return -ENOTSUP;
352
353 if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello.id) < 0)
354 return -ENOMEM;
355
356 b->is_kernel = true;
357 b->bus_client = true;
358 b->can_fds = !!(hello.conn_flags & KDBUS_HELLO_ACCEPT_FD);
359
360 r = bus_start_running(b);
361 if (r < 0)
362 return r;
363
364 return 1;
365 }
366
367 int bus_kernel_connect(sd_bus *b) {
368 assert(b);
369 assert(b->input_fd < 0);
370 assert(b->output_fd < 0);
371 assert(b->kernel);
372
373 if (b->is_server)
374 return -EINVAL;
375
376 b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
377 if (b->input_fd < 0)
378 return -errno;
379
380 b->output_fd = b->input_fd;
381
382 return bus_kernel_take_fd(b);
383 }
384
385 int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
386 int r;
387
388 assert(bus);
389 assert(m);
390 assert(bus->state == BUS_RUNNING);
391
392 r = bus_message_setup_kmsg(bus, m);
393 if (r < 0)
394 return r;
395
396 r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
397 if (r < 0)
398 return errno == EAGAIN ? 0 : -errno;
399
400 return 1;
401 }
402
403 static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
404 uint64_t off;
405 struct kdbus_item *d;
406
407 assert(bus);
408 assert(k);
409
410 off = (uint8_t *)k - (uint8_t *)bus->kdbus_buffer;
411 ioctl(bus->input_fd, KDBUS_CMD_MSG_RELEASE, &off);
412
413 KDBUS_PART_FOREACH(d, k, items) {
414
415 if (d->type == KDBUS_MSG_FDS)
416 close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
417 else if (d->type == KDBUS_MSG_PAYLOAD_MEMFD)
418 close_nointr_nofail(d->memfd.fd);
419 }
420 }
421
422 static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_message **ret) {
423 sd_bus_message *m = NULL;
424 struct kdbus_item *d;
425 unsigned n_fds = 0;
426 _cleanup_free_ int *fds = NULL;
427 struct bus_header *h = NULL;
428 size_t total, n_bytes = 0, idx = 0;
429 const char *destination = NULL, *seclabel = NULL;
430 int r;
431
432 assert(bus);
433 assert(k);
434 assert(ret);
435
436 if (k->payload_type != KDBUS_PAYLOAD_DBUS1)
437 return 0;
438
439 KDBUS_PART_FOREACH(d, k, items) {
440 size_t l;
441
442 l = d->size - offsetof(struct kdbus_item, data);
443
444 if (d->type == KDBUS_MSG_PAYLOAD_OFF) {
445
446 if (!h) {
447 h = (struct bus_header *)((uint8_t *)bus->kdbus_buffer + d->vec.offset);
448
449 if (!bus_header_is_complete(h, d->vec.size))
450 return -EBADMSG;
451 }
452
453 n_bytes += d->vec.size;
454
455 } else if (d->type == KDBUS_MSG_PAYLOAD_MEMFD) {
456
457 if (!h)
458 return -EBADMSG;
459
460 n_bytes += d->memfd.size;
461
462 } else if (d->type == KDBUS_MSG_FDS) {
463 int *f;
464 unsigned j;
465
466 j = l / sizeof(int);
467 f = realloc(fds, sizeof(int) * (n_fds + j));
468 if (!f)
469 return -ENOMEM;
470
471 fds = f;
472 memcpy(fds + n_fds, d->fds, sizeof(int) * j);
473 n_fds += j;
474
475 } else if (d->type == KDBUS_MSG_SRC_SECLABEL)
476 seclabel = d->str;
477 }
478
479 if (!h)
480 return -EBADMSG;
481
482 r = bus_header_message_size(h, &total);
483 if (r < 0)
484 return r;
485
486 if (n_bytes != total)
487 return -EBADMSG;
488
489 r = bus_message_from_header(bus, h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m);
490 if (r < 0)
491 return r;
492
493 KDBUS_PART_FOREACH(d, k, items) {
494 size_t l;
495
496 l = d->size - offsetof(struct kdbus_item, data);
497
498 if (d->type == KDBUS_MSG_PAYLOAD_OFF) {
499 size_t begin_body;
500
501 begin_body = BUS_MESSAGE_BODY_BEGIN(m);
502
503 if (idx + d->vec.size > begin_body) {
504 struct bus_body_part *part;
505
506 /* Contains body material */
507
508 part = message_append_part(m);
509 if (!part) {
510 r = -ENOMEM;
511 goto fail;
512 }
513
514 /* A -1 offset is NUL padding. */
515 part->is_zero = d->vec.offset == ~0ULL;
516
517 if (idx >= begin_body) {
518 if (!part->is_zero)
519 part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset;
520 part->size = d->vec.size;
521 } else {
522 if (!part->is_zero)
523 part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset + (begin_body - idx);
524 part->size = d->vec.size - (begin_body - idx);
525 }
526
527 part->sealed = true;
528 }
529
530 idx += d->vec.size;
531 } else if (d->type == KDBUS_MSG_PAYLOAD_MEMFD) {
532 struct bus_body_part *part;
533
534 if (idx < BUS_MESSAGE_BODY_BEGIN(m)) {
535 r = -EBADMSG;
536 goto fail;
537 }
538
539 part = message_append_part(m);
540 if (!part) {
541 r = -ENOMEM;
542 goto fail;
543 }
544
545 part->memfd = d->memfd.fd;
546 part->size = d->memfd.size;
547 part->sealed = true;
548
549 idx += d->memfd.size;
550
551 } else if (d->type == KDBUS_MSG_SRC_CREDS) {
552 m->creds.pid_starttime = d->creds.starttime / NSEC_PER_USEC;
553 m->creds.uid = d->creds.uid;
554 m->creds.gid = d->creds.gid;
555 m->creds.pid = d->creds.pid;
556 m->creds.tid = d->creds.tid;
557 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;
558
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
563 } else if (d->type == KDBUS_MSG_SRC_PID_COMM) {
564 m->creds.comm = d->str;
565 m->creds.mask |= SD_BUS_CREDS_COMM & bus->creds_mask;
566
567 } else if (d->type == KDBUS_MSG_SRC_TID_COMM) {
568 m->creds.tid_comm = d->str;
569 m->creds.mask |= SD_BUS_CREDS_TID_COMM & bus->creds_mask;
570
571 } else if (d->type == KDBUS_MSG_SRC_EXE) {
572 m->creds.exe = d->str;
573 m->creds.mask |= SD_BUS_CREDS_EXE & bus->creds_mask;
574
575 } else if (d->type == KDBUS_MSG_SRC_CMDLINE) {
576 m->creds.cmdline = d->str;
577 m->creds.cmdline_length = l;
578 m->creds.mask |= SD_BUS_CREDS_CMDLINE & bus->creds_mask;
579
580 } else if (d->type == KDBUS_MSG_SRC_CGROUP) {
581 m->creds.cgroup = d->str;
582 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;
583
584 } else if (d->type == KDBUS_MSG_SRC_AUDIT) {
585 m->creds.audit_session_id = d->audit.sessionid;
586 m->creds.audit_login_uid = d->audit.loginuid;
587 m->creds.mask |= (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID) & bus->creds_mask;
588
589 } else if (d->type == KDBUS_MSG_SRC_CAPS) {
590 m->creds.capability = d->data;
591 m->creds.capability_size = l;
592 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;
593
594 } else if (d->type == KDBUS_MSG_DST_NAME)
595 destination = d->str;
596 else if (d->type != KDBUS_MSG_FDS &&
597 d->type != KDBUS_MSG_SRC_SECLABEL &&
598 d->type != KDBUS_MSG_SRC_NAMES)
599 log_debug("Got unknown field from kernel %llu", d->type);
600 }
601
602 r = bus_message_parse_fields(m);
603 if (r < 0)
604 goto fail;
605
606 if (k->src_id == KDBUS_SRC_ID_KERNEL)
607 m->sender = "org.freedesktop.DBus";
608 else {
609 snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
610 m->sender = m->sender_buffer;
611 }
612
613 if (!m->destination) {
614 if (destination)
615 m->destination = destination;
616 else if (k->dst_id != KDBUS_DST_ID_WELL_KNOWN_NAME &&
617 k->dst_id != KDBUS_DST_ID_BROADCAST) {
618 snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
619 m->destination = m->destination_buffer;
620 }
621 }
622
623 /* We take possession of the kmsg struct now */
624 m->kdbus = k;
625 m->release_kdbus = true;
626 m->free_fds = true;
627
628 fds = NULL;
629
630 *ret = m;
631 return 1;
632
633 fail:
634 if (m) {
635 struct bus_body_part *part;
636 unsigned i;
637
638 /* Make sure the memfds are not freed twice */
639 MESSAGE_FOREACH_PART(part, i, m)
640 if (part->memfd >= 0)
641 part->memfd = -1;
642
643 sd_bus_message_unref(m);
644 }
645
646 return r;
647 }
648
649 int bus_kernel_read_message(sd_bus *bus, sd_bus_message **m) {
650 uint64_t off;
651 struct kdbus_msg *k;
652 int r;
653
654 assert(bus);
655 assert(m);
656
657 r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, &off);
658 if (r < 0) {
659 if (errno == EAGAIN)
660 return 0;
661
662 return -errno;
663 }
664 k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + off);
665
666 r = bus_kernel_make_message(bus, k, m);
667 if (r <= 0)
668 close_kdbus_msg(bus, k);
669
670 return r < 0 ? r : 1;
671 }
672
673 int bus_kernel_create(const char *name, char **s) {
674 struct kdbus_cmd_bus_make *make;
675 struct kdbus_item *n;
676 size_t l;
677 int fd;
678 char *p;
679
680 assert(name);
681 assert(s);
682
683 fd = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
684 if (fd < 0)
685 return -errno;
686
687 l = strlen(name);
688 make = alloca0(offsetof(struct kdbus_cmd_bus_make, items) +
689 KDBUS_PART_HEADER_SIZE + sizeof(uint64_t) +
690 KDBUS_PART_HEADER_SIZE + DECIMAL_STR_MAX(uid_t) + 1 + l + 1);
691
692 n = make->items;
693 n->type = KDBUS_MAKE_NAME;
694 sprintf(n->str, "%lu-%s", (unsigned long) getuid(), name);
695 n->size = KDBUS_PART_HEADER_SIZE + strlen(n->str) + 1;
696
697 make->size = offsetof(struct kdbus_cmd_bus_make, items) + n->size;
698 make->flags = KDBUS_MAKE_POLICY_OPEN;
699 make->bus_flags = 0;
700 make->bloom_size = BLOOM_SIZE;
701 assert_cc(BLOOM_SIZE % 8 == 0);
702
703 p = strjoin("/dev/kdbus/", n->str, "/bus", NULL);
704 if (!p)
705 return -ENOMEM;
706
707 if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
708 close_nointr_nofail(fd);
709 free(p);
710 return -errno;
711 }
712
713 if (s)
714 *s = p;
715
716 return fd;
717 }
718
719 int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *size) {
720 struct memfd_cache *c;
721 int fd;
722
723 assert(address);
724 assert(size);
725
726 if (!bus || !bus->is_kernel)
727 return -ENOTSUP;
728
729 assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
730
731 if (bus->n_memfd_cache <= 0) {
732 int r;
733
734 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
735
736 r = ioctl(bus->input_fd, KDBUS_CMD_MEMFD_NEW, &fd);
737 if (r < 0)
738 return -errno;
739
740 *address = NULL;
741 *size = 0;
742 return fd;
743 }
744
745 c = &bus->memfd_cache[--bus->n_memfd_cache];
746
747 assert(c->fd >= 0);
748 assert(c->size == 0 || c->address);
749
750 *address = c->address;
751 *size = c->size;
752 fd = c->fd;
753
754 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
755
756 return fd;
757 }
758
759 static void close_and_munmap(int fd, void *address, size_t size) {
760 if (size > 0)
761 assert_se(munmap(address, PAGE_ALIGN(size)) >= 0);
762
763 close_nointr_nofail(fd);
764 }
765
766 void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t size) {
767 struct memfd_cache *c;
768 uint64_t max_sz = PAGE_ALIGN(MEMFD_CACHE_ITEM_SIZE_MAX);
769
770 assert(fd >= 0);
771 assert(size == 0 || address);
772
773 if (!bus || !bus->is_kernel) {
774 close_and_munmap(fd, address, size);
775 return;
776 }
777
778 assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
779
780 if (bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
781 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
782
783 close_and_munmap(fd, address, size);
784 return;
785 }
786
787 c = &bus->memfd_cache[bus->n_memfd_cache++];
788 c->fd = fd;
789 c->address = address;
790
791 /* If overly long, let's return a bit to the OS */
792 if (size > max_sz) {
793 assert_se(ioctl(fd, KDBUS_CMD_MEMFD_SIZE_SET, &max_sz) >= 0);
794 assert_se(munmap((uint8_t*) address + max_sz, PAGE_ALIGN(size - max_sz)) >= 0);
795 c->size = max_sz;
796 } else
797 c->size = size;
798
799 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
800 }
801
802 void bus_kernel_flush_memfd(sd_bus *b) {
803 unsigned i;
804
805 assert(b);
806
807 for (i = 0; i < b->n_memfd_cache; i++)
808 close_and_munmap(b->memfd_cache[i].fd, b->memfd_cache[i].address, b->memfd_cache[i].size);
809 }
810
811 int sd_bus_kernel_translate_request_name_flags(uint64_t sd_bus_flags, uint64_t *kdbus_flags) {
812
813 assert_return(kdbus_flags != NULL, -EINVAL);
814
815 *kdbus_flags = 0;
816
817 if (sd_bus_flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
818 *kdbus_flags |= KDBUS_NAME_ALLOW_REPLACEMENT;
819
820 if (sd_bus_flags & SD_BUS_NAME_REPLACE_EXISTING)
821 *kdbus_flags |= KDBUS_NAME_REPLACE_EXISTING;
822
823 if (!(sd_bus_flags & SD_BUS_NAME_DO_NOT_QUEUE))
824 *kdbus_flags |= KDBUS_NAME_QUEUE;
825
826 return 0;
827 }