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