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