chiark / gitweb /
bus: properly handle message bodies that are a chain of memory areas rather than...
[elogind.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 kdbus_item *d;
188         bool well_known;
189         uint64_t unique;
190         size_t sz, dl;
191         int r;
192         struct bus_body_part *part;
193
194         assert(b);
195         assert(m);
196         assert(m->sealed);
197
198         if (m->kdbus)
199                 return 0;
200
201         if (m->destination) {
202                 r = parse_unique_name(m->destination, &unique);
203                 if (r < 0)
204                         return r;
205
206                 well_known = r == 0;
207         } else
208                 well_known = false;
209
210         sz = offsetof(struct kdbus_msg, items);
211
212         /* Add in fixed header, fields header and payload */
213         sz += (1 + !!m->fields + m->n_body_parts) *
214                 ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec));
215
216         /* Add space for bloom filter */
217         sz += ALIGN8(offsetof(struct kdbus_item, data) + BLOOM_SIZE);
218
219         /* Add in well-known destination header */
220         if (well_known) {
221                 dl = strlen(m->destination);
222                 sz += ALIGN8(offsetof(struct kdbus_item, str) + dl + 1);
223         }
224
225         /* Add space for unix fds */
226         if (m->n_fds > 0)
227                 sz += ALIGN8(offsetof(struct kdbus_item, fds) + sizeof(int)*m->n_fds);
228
229         m->kdbus = memalign(8, sz);
230         if (!m->kdbus)
231                 return -ENOMEM;
232
233         memset(m->kdbus, 0, sz);
234
235         m->kdbus->flags =
236                 ((m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_FLAGS_EXPECT_REPLY) |
237                 ((m->header->flags & SD_BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_FLAGS_NO_AUTO_START : 0);
238         m->kdbus->dst_id =
239                 well_known ? 0 :
240                 m->destination ? unique : KDBUS_DST_ID_BROADCAST;
241         m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS1;
242         m->kdbus->cookie = m->header->serial;
243
244         m->kdbus->timeout_ns = m->timeout * NSEC_PER_USEC;
245
246         d = m->kdbus->items;
247
248         if (well_known)
249                 append_destination(&d, m->destination, dl);
250
251         append_payload_vec(&d, m->header, sizeof(*m->header));
252
253         if (m->fields)
254                 append_payload_vec(&d, m->fields, ALIGN8(m->header->fields_size));
255
256         for (part = &m->body; part && part->size > 0; part = part->next)
257                 append_payload_vec(&d, part->data, part->size);
258
259         if (m->kdbus->dst_id == KDBUS_DST_ID_BROADCAST) {
260                 void *p;
261
262                 p = append_bloom(&d, BLOOM_SIZE);
263                 r = bus_message_setup_bloom(m, p);
264                 if (r < 0) {
265                         free(m->kdbus);
266                         m->kdbus = NULL;
267                         return -r;
268                 }
269         }
270
271         if (m->n_fds > 0)
272                 append_fds(&d, m->fds, m->n_fds);
273
274         m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus;
275         assert(m->kdbus->size <= sz);
276
277         m->free_kdbus = true;
278
279         return 0;
280 }
281
282 int bus_kernel_take_fd(sd_bus *b) {
283         uint8_t h[ALIGN8(sizeof(struct kdbus_cmd_hello)) +
284                   ALIGN8(KDBUS_ITEM_HEADER_SIZE) +
285                   ALIGN8(sizeof(struct kdbus_vec))] = {};
286
287         struct kdbus_cmd_hello *hello = (struct kdbus_cmd_hello*) h;
288
289         int r;
290
291         assert(b);
292
293         if (b->is_server)
294                 return -EINVAL;
295
296         if (!b->kdbus_buffer) {
297                 b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
298                 if (b->kdbus_buffer == MAP_FAILED) {
299                         b->kdbus_buffer = NULL;
300                         return -errno;
301                 }
302         }
303
304         hello->size = sizeof(h);
305         hello->conn_flags =
306                 KDBUS_HELLO_ACCEPT_FD|
307                 KDBUS_HELLO_ATTACH_COMM|
308                 KDBUS_HELLO_ATTACH_EXE|
309                 KDBUS_HELLO_ATTACH_CMDLINE|
310                 KDBUS_HELLO_ATTACH_CGROUP|
311                 KDBUS_HELLO_ATTACH_CAPS|
312                 KDBUS_HELLO_ATTACH_SECLABEL|
313                 KDBUS_HELLO_ATTACH_AUDIT;
314
315         hello->items[0].type = KDBUS_HELLO_POOL;
316         hello->items[0].size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
317         hello->items[0].vec.address = (uint64_t) b->kdbus_buffer;
318         hello->items[0].vec.size = KDBUS_POOL_SIZE;
319
320         r = ioctl(b->input_fd, KDBUS_CMD_HELLO, hello);
321         if (r < 0)
322                 return -errno;
323
324         /* The higher 32bit of both flags fields are considered
325          * 'incompatible flags'. Refuse them all for now. */
326         if (hello->bus_flags > 0xFFFFFFFFULL ||
327             hello->conn_flags > 0xFFFFFFFFULL)
328                 return -ENOTSUP;
329
330         if (hello->bloom_size != BLOOM_SIZE)
331                 return -ENOTSUP;
332
333         if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello->id) < 0)
334                 return -ENOMEM;
335
336         b->is_kernel = true;
337         b->bus_client = true;
338         b->can_fds = true;
339
340         r = bus_start_running(b);
341         if (r < 0)
342                 return r;
343
344         return 1;
345 }
346
347 int bus_kernel_connect(sd_bus *b) {
348         assert(b);
349         assert(b->input_fd < 0);
350         assert(b->output_fd < 0);
351         assert(b->kernel);
352
353         if (b->is_server)
354                 return -EINVAL;
355
356         b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
357         if (b->input_fd < 0)
358                 return -errno;
359
360         b->output_fd = b->input_fd;
361
362         return bus_kernel_take_fd(b);
363 }
364
365 int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
366         int r;
367
368         assert(bus);
369         assert(m);
370         assert(bus->state == BUS_RUNNING);
371
372         r = bus_message_setup_kmsg(bus, m);
373         if (r < 0)
374                 return r;
375
376         r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
377         if (r < 0)
378                 return errno == EAGAIN ? 0 : -errno;
379
380         return 1;
381 }
382
383 static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
384         struct kdbus_item *d;
385
386         assert(bus);
387         assert(k);
388
389         ioctl(bus->input_fd, KDBUS_CMD_MSG_RELEASE, k);
390
391         KDBUS_ITEM_FOREACH(d, k) {
392
393                 if (d->type != KDBUS_MSG_FDS)
394                         continue;
395
396                 close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
397         }
398 }
399
400 static bool range_contains(
401                 size_t astart, size_t asize,
402                 size_t bstart, size_t bsize,
403                 void *a, void **b) {
404
405         if (bstart < astart)
406                 return false;
407
408         if (bstart + bsize > astart + asize)
409                 return false;
410
411         *b = (uint8_t*) a + (bstart - astart);
412
413         return true;
414 }
415
416 static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_message **ret) {
417         sd_bus_message *m = NULL;
418         struct kdbus_item *d;
419         unsigned n_payload = 0, n_fds = 0;
420         _cleanup_free_ int *fds = NULL;
421         struct bus_header *h = NULL;
422         size_t total, n_bytes = 0, idx = 0;
423         const char *destination = NULL, *seclabel = NULL;
424         int r;
425
426         assert(bus);
427         assert(k);
428         assert(ret);
429
430         if (k->payload_type != KDBUS_PAYLOAD_DBUS1)
431                 return 0;
432
433         KDBUS_ITEM_FOREACH(d, k) {
434                 size_t l;
435
436                 l = d->size - offsetof(struct kdbus_item, data);
437
438                 if (d->type == KDBUS_MSG_PAYLOAD_VEC) {
439
440                         if (!h) {
441                                 if (d->vec.size < sizeof(struct bus_header))
442                                         return -EBADMSG;
443
444                                 h = (struct bus_header*)UINT64_TO_PTR(d->vec.address);
445                         }
446
447                         n_payload++;
448                         n_bytes += d->vec.size;
449
450                 } else if (d->type == KDBUS_MSG_FDS) {
451                         int *f;
452                         unsigned j;
453
454                         j = l / sizeof(int);
455                         f = realloc(fds, sizeof(int) * (n_fds + j));
456                         if (!f)
457                                 return -ENOMEM;
458
459                         fds = f;
460                         memcpy(fds + n_fds, d->fds, sizeof(int) * j);
461                         n_fds += j;
462
463                 } else if (d->type == KDBUS_MSG_DST_NAME)
464                         destination = d->str;
465                 else if (d->type == KDBUS_MSG_SRC_SECLABEL)
466                         seclabel = d->str;
467         }
468
469         if (!h)
470                 return -EBADMSG;
471
472         r = bus_header_size(h, &total);
473         if (r < 0)
474                 return r;
475
476         if (n_bytes != total)
477                 return -EBADMSG;
478
479         //if (n_payload > 2)
480         //        return -EBADMSG;
481
482         r = bus_message_from_header(h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m);
483         if (r < 0)
484                 return r;
485
486         KDBUS_ITEM_FOREACH(d, k) {
487                 size_t l;
488
489                 l = d->size - offsetof(struct kdbus_item, data);
490
491                 if (d->type == KDBUS_MSG_PAYLOAD_VEC) {
492                         size_t begin_body;
493
494                         /* Fill in fields material */
495                         range_contains(idx, d->vec.size, ALIGN8(sizeof(struct bus_header)), BUS_MESSAGE_FIELDS_SIZE(m),
496                                        UINT64_TO_PTR(d->vec.address), &m->fields);
497
498                         begin_body = ALIGN8(sizeof(struct bus_header)) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
499
500                         if (idx + d->vec.size > begin_body) {
501                                 struct bus_body_part *part;
502
503                                 /* Contains body material */
504
505                                 part = message_append_part(m);
506                                 if (!part) {
507                                         sd_bus_message_unref(m);
508                                         return -ENOMEM;
509                                 }
510
511                                 if (idx >= begin_body) {
512                                         part->data = (void*) d->vec.address;
513                                         part->size = d->vec.size;
514                                 } else {
515                                         part->data = (uint8_t*) (uintptr_t) d->vec.address + (begin_body - idx);
516                                         part->size = d->vec.size - (begin_body - idx);
517                                 }
518
519                                 part->sealed = true;
520                         }
521
522                         idx += d->vec.size;
523
524                 } else if (d->type == KDBUS_MSG_SRC_CREDS) {
525                         m->pid_starttime = d->creds.starttime / NSEC_PER_USEC;
526                         m->uid = d->creds.uid;
527                         m->gid = d->creds.gid;
528                         m->pid = d->creds.pid;
529                         m->tid = d->creds.tid;
530                         m->uid_valid = m->gid_valid = true;
531                 } else if (d->type == KDBUS_MSG_TIMESTAMP) {
532                         m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC;
533                         m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC;
534                 } else if (d->type == KDBUS_MSG_SRC_PID_COMM)
535                         m->comm = d->str;
536                 else if (d->type == KDBUS_MSG_SRC_TID_COMM)
537                         m->tid_comm = d->str;
538                 else if (d->type == KDBUS_MSG_SRC_EXE)
539                         m->exe = d->str;
540                 else if (d->type == KDBUS_MSG_SRC_CMDLINE) {
541                         m->cmdline = d->str;
542                         m->cmdline_length = l;
543                 } else if (d->type == KDBUS_MSG_SRC_CGROUP)
544                         m->cgroup = d->str;
545                 else if (d->type == KDBUS_MSG_SRC_AUDIT)
546                         m->audit = &d->audit;
547                 else if (d->type == KDBUS_MSG_SRC_CAPS) {
548                         m->capability = d->data;
549                         m->capability_size = l;
550                 } else if (d->type != KDBUS_MSG_FDS &&
551                            d->type != KDBUS_MSG_DST_NAME &&
552                            d->type != KDBUS_MSG_SRC_SECLABEL)
553                         log_debug("Got unknown field from kernel %llu", d->type);
554         }
555
556         if ((BUS_MESSAGE_FIELDS_SIZE(m) > 0 && !m->fields) || BUS_MESSAGE_SIZE(m) != idx) {
557                 sd_bus_message_unref(m);
558                 return -EBADMSG;
559         }
560
561         r = bus_message_parse_fields(m);
562         if (r < 0) {
563                 sd_bus_message_unref(m);
564                 return r;
565         }
566
567         if (k->src_id == KDBUS_SRC_ID_KERNEL)
568                 m->sender = "org.freedesktop.DBus";
569         else {
570                 snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
571                 m->sender = m->sender_buffer;
572         }
573
574         if (!m->destination) {
575                 if (destination)
576                         m->destination = destination;
577                 else if (k->dst_id != KDBUS_DST_ID_WELL_KNOWN_NAME &&
578                          k->dst_id != KDBUS_DST_ID_BROADCAST) {
579                         snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
580                         m->destination = m->destination_buffer;
581                 }
582         }
583
584         /* We take possession of the kmsg struct now */
585         m->kdbus = k;
586         m->bus = sd_bus_ref(bus);
587         m->release_kdbus = true;
588         m->free_fds = true;
589
590         fds = NULL;
591
592         *ret = m;
593         return 1;
594 }
595
596 int bus_kernel_read_message(sd_bus *bus, sd_bus_message **m) {
597         struct kdbus_msg *k;
598         int r;
599
600         assert(bus);
601         assert(m);
602
603         r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, &k);
604         if (r < 0) {
605                 if (errno == EAGAIN)
606                         return 0;
607
608                 return -errno;
609         }
610
611
612 /*                 /\* Let's tell valgrind that there's really no need to */
613 /*                  * initialize this fully. This should be removed again */
614 /*                  * when valgrind learned the kdbus ioctls natively. *\/ */
615 /* #ifdef HAVE_VALGRIND_MEMCHECK_H */
616 /*                 VALGRIND_MAKE_MEM_DEFINED(k, sz); */
617 /* #endif */
618
619
620         r = bus_kernel_make_message(bus, k, m);
621         if (r <= 0)
622                 close_kdbus_msg(bus, k);
623
624         return r < 0 ? r : 1;
625 }
626
627 int bus_kernel_create(const char *name, char **s) {
628         struct kdbus_cmd_bus_make *make;
629         struct kdbus_item *n, *cg;
630         size_t l;
631         int fd;
632         char *p;
633
634         assert(name);
635         assert(s);
636
637         fd = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
638         if (fd < 0)
639                 return -errno;
640
641         l = strlen(name);
642         make = alloca0(offsetof(struct kdbus_cmd_bus_make, items) +
643                        KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t) +
644                        KDBUS_ITEM_HEADER_SIZE + DECIMAL_STR_MAX(uid_t) + 1 + l + 1);
645
646         cg = make->items;
647         cg->type = KDBUS_MAKE_CGROUP;
648         cg->data64[0] = 1;
649         cg->size = KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t);
650
651         n = KDBUS_ITEM_NEXT(cg);
652         n->type = KDBUS_MAKE_NAME;
653         sprintf(n->str, "%lu-%s", (unsigned long) getuid(), name);
654         n->size = KDBUS_ITEM_HEADER_SIZE + strlen(n->str) + 1;
655
656         make->size = offsetof(struct kdbus_cmd_bus_make, items) + cg->size + n->size;
657         make->flags = KDBUS_MAKE_POLICY_OPEN;
658         make->bus_flags = 0;
659         make->bloom_size = BLOOM_SIZE;
660         assert_cc(BLOOM_SIZE % 8 == 0);
661
662         p = strjoin("/dev/kdbus/", n->str, "/bus", NULL);
663         if (!p)
664                 return -ENOMEM;
665
666         if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
667                 close_nointr_nofail(fd);
668                 free(p);
669                 return -errno;
670         }
671
672         if (s)
673                 *s = p;
674
675         return fd;
676 }
677
678 int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *size) {
679         struct memfd_cache *c;
680
681         assert(address);
682         assert(size);
683
684         if (!bus || !bus->is_kernel)
685                 return -ENOTSUP;
686
687         if (bus->n_memfd_cache <= 0) {
688                 int fd;
689
690                 fd = ioctl(bus->input_fd, KDBUS_CMD_MEMFD_NEW, &fd);
691                 if (fd < 0)
692                         return -errno;
693
694                 *address = NULL;
695                 *size = 0;
696                 return fd;
697         }
698
699         c = &bus->memfd_cache[-- bus->n_memfd_cache];
700
701         assert(c->fd >= 0);
702         assert(c->size == 0 || c->address);
703
704         *address = c->address;
705         *size = c->size;
706
707         return c->fd;
708 }
709
710 void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t size) {
711         struct memfd_cache *c;
712
713         assert(fd >= 0);
714         assert(size == 0 || address);
715
716         if (!bus || !bus->is_kernel ||
717             bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
718
719                 if (size > 0)
720                         assert_se(munmap(address, PAGE_ALIGN(size)) == 0);
721
722                 close_nointr_nofail(fd);
723                 return;
724         }
725
726         c = &bus->memfd_cache[bus->n_memfd_cache++];
727         c->fd = fd;
728         c->address = address;
729
730         /* If overly long, let's return a bit to the OS */
731         if (size > MEMFD_CACHE_ITEM_SIZE_MAX) {
732                 uint64_t sz = MEMFD_CACHE_ITEM_SIZE_MAX;
733
734                 ioctl(bus->input_fd, KDBUS_CMD_MEMFD_SIZE_SET, &sz);
735
736                 c->size = MEMFD_CACHE_ITEM_SIZE_MAX;
737         } else
738                 c->size = size;
739 }
740
741 void bus_kernel_flush_memfd(sd_bus *b) {
742         unsigned i;
743
744         assert(b);
745
746         for (i = 0; i < b->n_memfd_cache; i++) {
747                 if (b->memfd_cache[i].size > 0)
748                         assert_se(munmap(b->memfd_cache[i].address, PAGE_ALIGN(b->memfd_cache[i].size)) == 0);
749
750                 close_nointr_nofail(b->memfd_cache[i].fd);
751         }
752 }