]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-bus/bus-kernel.c
bus: add minimal locking around the memfd cache
[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 #define KDBUS_ITEM_NEXT(item) \
38 (typeof(item))(((uint8_t *)item) + ALIGN8((item)->size))
39
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))
44
45 #define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data)
46 #define KDBUS_ITEM_SIZE(s) ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE)
47
48 static 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
64 static void append_payload_vec(struct kdbus_item **d, const void *p, size_t sz) {
65 assert(d);
66 assert(sz > 0);
67
68 *d = ALIGN8_PTR(*d);
69
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
74 (*d)->size = offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec);
75 (*d)->type = KDBUS_MSG_PAYLOAD_VEC;
76 (*d)->vec.address = PTR_TO_UINT64(p);
77 (*d)->vec.size = sz;
78
79 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
80 }
81
82 static 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
96 static void append_destination(struct kdbus_item **d, const char *s, size_t length) {
97 assert(d);
98 assert(s);
99
100 *d = ALIGN8_PTR(*d);
101
102 (*d)->size = offsetof(struct kdbus_item, str) + length + 1;
103 (*d)->type = KDBUS_MSG_DST_NAME;
104 memcpy((*d)->str, s, length + 1);
105
106 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
107 }
108
109 static void* append_bloom(struct kdbus_item **d, size_t length) {
110 void *r;
111
112 assert(d);
113
114 *d = ALIGN8_PTR(*d);
115
116 (*d)->size = offsetof(struct kdbus_item, data) + length;
117 (*d)->type = KDBUS_MSG_BLOOM;
118 r = (*d)->data;
119
120 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
121
122 return r;
123 }
124
125 static void append_fds(struct kdbus_item **d, const int fds[], unsigned n_fds) {
126 assert(d);
127 assert(fds);
128 assert(n_fds > 0);
129
130 *d = ALIGN8_PTR(*d);
131 (*d)->size = offsetof(struct kdbus_item, fds) + sizeof(int) * n_fds;
132 (*d)->type = KDBUS_MSG_FDS;
133 memcpy((*d)->fds, fds, sizeof(int) * n_fds);
134
135 *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
136 }
137
138 static 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;
199 }
200
201 static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
202 struct bus_body_part *part;
203 struct kdbus_item *d;
204 bool well_known;
205 uint64_t unique;
206 size_t sz, dl;
207 unsigned i;
208 int r;
209
210 assert(b);
211 assert(m);
212 assert(m->sealed);
213
214 if (m->kdbus)
215 return 0;
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
226 sz = offsetof(struct kdbus_msg, items);
227
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
231 /* Add in fixed header, fields header and payload */
232 sz += (1 + m->n_body_parts) *
233 ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec));
234
235 /* Add space for bloom filter */
236 sz += ALIGN8(offsetof(struct kdbus_item, data) + BLOOM_SIZE);
237
238 /* Add in well-known destination header */
239 if (well_known) {
240 dl = strlen(m->destination);
241 sz += ALIGN8(offsetof(struct kdbus_item, str) + dl + 1);
242 }
243
244 /* Add space for unix fds */
245 if (m->n_fds > 0)
246 sz += ALIGN8(offsetof(struct kdbus_item, fds) + sizeof(int)*m->n_fds);
247
248 m->kdbus = memalign(8, sz);
249 if (!m->kdbus) {
250 r = -ENOMEM;
251 goto fail;
252 }
253
254 m->free_kdbus = true;
255 memset(m->kdbus, 0, sz);
256
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 :
262 m->destination ? unique : KDBUS_DST_ID_BROADCAST;
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
268 d = m->kdbus->items;
269
270 if (well_known)
271 append_destination(&d, m->destination, dl);
272
273 append_payload_vec(&d, m->header, BUS_MESSAGE_BODY_BEGIN(m));
274
275 MESSAGE_FOREACH_PART(part, i, m) {
276 if (part->is_zero) {
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
282 append_payload_vec(&d, NULL, part->size);
283 continue;
284 }
285
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 */
289
290 append_payload_memfd(&d, part->memfd, part->size);
291 continue;
292 }
293
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;
299
300 append_payload_vec(&d, part->data, part->size);
301 }
302
303 if (m->kdbus->dst_id == KDBUS_DST_ID_BROADCAST) {
304 void *p;
305
306 p = append_bloom(&d, BLOOM_SIZE);
307 r = bus_message_setup_bloom(m, p);
308 if (r < 0)
309 goto fail;
310 }
311
312 if (m->n_fds > 0)
313 append_fds(&d, m->fds, m->n_fds);
314
315 m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus;
316 assert(m->kdbus->size <= sz);
317
318 return 0;
319
320 fail:
321 m->poisoned = true;
322 return r;
323 }
324
325 int bus_kernel_take_fd(sd_bus *b) {
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
332 int r;
333
334 assert(b);
335
336 if (b->is_server)
337 return -EINVAL;
338
339 if (!b->kdbus_buffer) {
340 b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
341 if (b->kdbus_buffer == MAP_FAILED) {
342 b->kdbus_buffer = NULL;
343 return -errno;
344 }
345 }
346
347 hello->size = sizeof(h);
348 hello->conn_flags =
349 KDBUS_HELLO_ACCEPT_FD|
350 KDBUS_HELLO_ATTACH_COMM|
351 KDBUS_HELLO_ATTACH_EXE|
352 KDBUS_HELLO_ATTACH_CMDLINE|
353 KDBUS_HELLO_ATTACH_CGROUP|
354 KDBUS_HELLO_ATTACH_CAPS|
355 KDBUS_HELLO_ATTACH_SECLABEL|
356 KDBUS_HELLO_ATTACH_AUDIT;
357
358 hello->items[0].type = KDBUS_HELLO_POOL;
359 hello->items[0].size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
360 hello->items[0].vec.address = (uint64_t) b->kdbus_buffer;
361 hello->items[0].vec.size = KDBUS_POOL_SIZE;
362
363 r = ioctl(b->input_fd, KDBUS_CMD_HELLO, hello);
364 if (r < 0)
365 return -errno;
366
367 /* The higher 32bit of both flags fields are considered
368 * 'incompatible flags'. Refuse them all for now. */
369 if (hello->bus_flags > 0xFFFFFFFFULL ||
370 hello->conn_flags > 0xFFFFFFFFULL)
371 return -ENOTSUP;
372
373 if (hello->bloom_size != BLOOM_SIZE)
374 return -ENOTSUP;
375
376 if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello->id) < 0)
377 return -ENOMEM;
378
379 b->is_kernel = true;
380 b->bus_client = true;
381 b->can_fds = true;
382
383 r = bus_start_running(b);
384 if (r < 0)
385 return r;
386
387 return 1;
388 }
389
390 int bus_kernel_connect(sd_bus *b) {
391 assert(b);
392 assert(b->input_fd < 0);
393 assert(b->output_fd < 0);
394 assert(b->kernel);
395
396 if (b->is_server)
397 return -EINVAL;
398
399 b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
400 if (b->input_fd < 0)
401 return -errno;
402
403 b->output_fd = b->input_fd;
404
405 return bus_kernel_take_fd(b);
406 }
407
408 int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
409 int r;
410
411 assert(bus);
412 assert(m);
413 assert(bus->state == BUS_RUNNING);
414
415 r = bus_message_setup_kmsg(bus, m);
416 if (r < 0)
417 return r;
418
419 r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
420 if (r < 0)
421 return errno == EAGAIN ? 0 : -errno;
422
423 return 1;
424 }
425
426 static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
427 struct kdbus_item *d;
428
429 assert(bus);
430 assert(k);
431
432 ioctl(bus->input_fd, KDBUS_CMD_MSG_RELEASE, k);
433
434 KDBUS_ITEM_FOREACH(d, k) {
435
436 if (d->type == KDBUS_MSG_FDS)
437 close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
438 else if (d->type == KDBUS_MSG_PAYLOAD_MEMFD)
439 close_nointr_nofail(d->memfd.fd);
440 }
441 }
442
443 static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_message **ret) {
444 sd_bus_message *m = NULL;
445 struct kdbus_item *d;
446 unsigned n_fds = 0;
447 _cleanup_free_ int *fds = NULL;
448 struct bus_header *h = NULL;
449 size_t total, n_bytes = 0, idx = 0;
450 const char *destination = NULL, *seclabel = NULL;
451 int r;
452
453 assert(bus);
454 assert(k);
455 assert(ret);
456
457 if (k->payload_type != KDBUS_PAYLOAD_DBUS1)
458 return 0;
459
460 KDBUS_ITEM_FOREACH(d, k) {
461 size_t l;
462
463 l = d->size - offsetof(struct kdbus_item, data);
464
465 if (d->type == KDBUS_MSG_PAYLOAD_VEC) {
466
467 if (!h) {
468 h = UINT64_TO_PTR(d->vec.address);
469
470 if (!bus_header_is_complete(h, d->vec.size))
471 return -EBADMSG;
472 }
473
474 n_bytes += d->vec.size;
475
476 } else if (d->type == KDBUS_MSG_PAYLOAD_MEMFD) {
477
478 if (!h)
479 return -EBADMSG;
480
481 n_bytes += d->memfd.size;
482
483 } else if (d->type == KDBUS_MSG_FDS) {
484 int *f;
485 unsigned j;
486
487 j = l / sizeof(int);
488 f = realloc(fds, sizeof(int) * (n_fds + j));
489 if (!f)
490 return -ENOMEM;
491
492 fds = f;
493 memcpy(fds + n_fds, d->fds, sizeof(int) * j);
494 n_fds += j;
495
496 } else if (d->type == KDBUS_MSG_SRC_SECLABEL)
497 seclabel = d->str;
498 }
499
500 if (!h)
501 return -EBADMSG;
502
503 r = bus_header_message_size(h, &total);
504 if (r < 0)
505 return r;
506
507 if (n_bytes != total)
508 return -EBADMSG;
509
510 r = bus_message_from_header(h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m);
511 if (r < 0)
512 return r;
513
514 KDBUS_ITEM_FOREACH(d, k) {
515 size_t l;
516
517 l = d->size - offsetof(struct kdbus_item, data);
518
519 if (d->type == KDBUS_MSG_PAYLOAD_VEC) {
520 size_t begin_body;
521
522 begin_body = BUS_MESSAGE_BODY_BEGIN(m);
523
524 if (idx + d->vec.size > begin_body) {
525 struct bus_body_part *part;
526
527 /* Contains body material */
528
529 part = message_append_part(m);
530 if (!part) {
531 r = -ENOMEM;
532 goto fail;
533 }
534
535 if (idx >= begin_body) {
536 part->data = UINT64_TO_PTR(d->vec.address);
537 part->size = d->vec.size;
538 } else {
539 part->data = d->vec.address != 0 ? (uint8_t*) UINT64_TO_PTR(d->vec.address) + (begin_body - idx) : NULL;
540 part->size = d->vec.size - (begin_body - idx);
541 }
542
543 part->is_zero = d->vec.address == 0;
544 part->sealed = true;
545 }
546
547 idx += d->vec.size;
548 } else if (d->type == KDBUS_MSG_PAYLOAD_MEMFD) {
549 struct bus_body_part *part;
550
551 if (idx < BUS_MESSAGE_BODY_BEGIN(m)) {
552 r = -EBADMSG;
553 goto fail;
554 }
555
556 part = message_append_part(m);
557 if (!part) {
558 r = -ENOMEM;
559 goto fail;
560 }
561
562 part->memfd = d->memfd.fd;
563 part->size = d->memfd.size;
564 part->sealed = true;
565
566 idx += d->memfd.size;
567
568 } else if (d->type == KDBUS_MSG_SRC_CREDS) {
569 m->pid_starttime = d->creds.starttime / NSEC_PER_USEC;
570 m->uid = d->creds.uid;
571 m->gid = d->creds.gid;
572 m->pid = d->creds.pid;
573 m->tid = d->creds.tid;
574 m->uid_valid = m->gid_valid = true;
575 } else if (d->type == KDBUS_MSG_TIMESTAMP) {
576 m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC;
577 m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC;
578 } else if (d->type == KDBUS_MSG_SRC_PID_COMM)
579 m->comm = d->str;
580 else if (d->type == KDBUS_MSG_SRC_TID_COMM)
581 m->tid_comm = d->str;
582 else if (d->type == KDBUS_MSG_SRC_EXE)
583 m->exe = d->str;
584 else if (d->type == KDBUS_MSG_SRC_CMDLINE) {
585 m->cmdline = d->str;
586 m->cmdline_length = l;
587 } else if (d->type == KDBUS_MSG_SRC_CGROUP)
588 m->cgroup = d->str;
589 else if (d->type == KDBUS_MSG_SRC_AUDIT)
590 m->audit = &d->audit;
591 else if (d->type == KDBUS_MSG_SRC_CAPS) {
592 m->capability = d->data;
593 m->capability_size = l;
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 log_debug("Got unknown field from kernel %llu", d->type);
599 }
600
601 r = bus_message_parse_fields(m);
602 if (r < 0)
603 goto fail;
604
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
622 /* We take possession of the kmsg struct now */
623 m->kdbus = k;
624 m->bus = sd_bus_ref(bus);
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 struct kdbus_msg *k;
651 int r;
652
653 assert(bus);
654 assert(m);
655
656 r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, &k);
657 if (r < 0) {
658 if (errno == EAGAIN)
659 return 0;
660
661 return -errno;
662 }
663
664 r = bus_kernel_make_message(bus, k, m);
665 if (r <= 0)
666 close_kdbus_msg(bus, k);
667
668 return r < 0 ? r : 1;
669 }
670
671 int bus_kernel_create(const char *name, char **s) {
672 struct kdbus_cmd_bus_make *make;
673 struct kdbus_item *n, *cg;
674 size_t l;
675 int fd;
676 char *p;
677
678 assert(name);
679 assert(s);
680
681 fd = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
682 if (fd < 0)
683 return -errno;
684
685 l = strlen(name);
686 make = alloca0(offsetof(struct kdbus_cmd_bus_make, items) +
687 KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t) +
688 KDBUS_ITEM_HEADER_SIZE + DECIMAL_STR_MAX(uid_t) + 1 + l + 1);
689
690 cg = make->items;
691 cg->type = KDBUS_MAKE_CGROUP;
692 cg->data64[0] = 1;
693 cg->size = KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t);
694
695 n = KDBUS_ITEM_NEXT(cg);
696 n->type = KDBUS_MAKE_NAME;
697 sprintf(n->str, "%lu-%s", (unsigned long) getuid(), name);
698 n->size = KDBUS_ITEM_HEADER_SIZE + strlen(n->str) + 1;
699
700 make->size = offsetof(struct kdbus_cmd_bus_make, items) + cg->size + n->size;
701 make->flags = KDBUS_MAKE_POLICY_OPEN;
702 make->bus_flags = 0;
703 make->bloom_size = BLOOM_SIZE;
704 assert_cc(BLOOM_SIZE % 8 == 0);
705
706 p = strjoin("/dev/kdbus/", n->str, "/bus", NULL);
707 if (!p)
708 return -ENOMEM;
709
710 if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
711 close_nointr_nofail(fd);
712 free(p);
713 return -errno;
714 }
715
716 if (s)
717 *s = p;
718
719 return fd;
720 }
721
722 int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *size) {
723 struct memfd_cache *c;
724 int fd;
725
726 assert(address);
727 assert(size);
728
729 if (!bus || !bus->is_kernel)
730 return -ENOTSUP;
731
732 assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) == 0);
733
734 if (bus->n_memfd_cache <= 0) {
735 int r;
736
737 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0);
738
739 r = ioctl(bus->input_fd, KDBUS_CMD_MEMFD_NEW, &fd);
740 if (r < 0)
741 return -errno;
742
743 *address = NULL;
744 *size = 0;
745 return fd;
746 }
747
748 c = &bus->memfd_cache[-- bus->n_memfd_cache];
749
750 assert(c->fd >= 0);
751 assert(c->size == 0 || c->address);
752
753 *address = c->address;
754 *size = c->size;
755 fd = c->fd;
756
757 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0);
758
759 return fd;
760 }
761
762 static void close_and_munmap(int fd, void *address, size_t size) {
763 if (size > 0)
764 assert_se(munmap(address, PAGE_ALIGN(size)) == 0);
765
766 close_nointr_nofail(fd);
767 }
768
769 void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t size) {
770 struct memfd_cache *c;
771
772 assert(fd >= 0);
773 assert(size == 0 || address);
774
775 if (!bus || !bus->is_kernel) {
776 close_and_munmap(fd, address, size);
777 return;
778 }
779
780 assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) == 0);
781
782 if (bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
783 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0);
784
785 close_and_munmap(fd, address, size);
786 return;
787 }
788
789 c = &bus->memfd_cache[bus->n_memfd_cache++];
790 c->fd = fd;
791 c->address = address;
792
793 /* If overly long, let's return a bit to the OS */
794 if (size > MEMFD_CACHE_ITEM_SIZE_MAX) {
795 uint64_t sz = MEMFD_CACHE_ITEM_SIZE_MAX;
796
797 ioctl(bus->input_fd, KDBUS_CMD_MEMFD_SIZE_SET, &sz);
798
799 c->size = MEMFD_CACHE_ITEM_SIZE_MAX;
800 } else
801 c->size = size;
802
803 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0);
804 }
805
806 void bus_kernel_flush_memfd(sd_bus *b) {
807 unsigned i;
808
809 assert(b);
810
811 for (i = 0; i < b->n_memfd_cache; i++) {
812 if (b->memfd_cache[i].size > 0)
813 assert_se(munmap(b->memfd_cache[i].address, PAGE_ALIGN(b->memfd_cache[i].size)) == 0);
814
815 close_nointr_nofail(b->memfd_cache[i].fd);
816 }
817 }