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