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