chiark / gitweb /
libsystemd-bus: catch up with latest kdbus changes
[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.attach_flags = b->attach_flags;
330         hello.pool_size = KDBUS_POOL_SIZE;
331
332         r = ioctl(b->input_fd, KDBUS_CMD_HELLO, &hello);
333         if (r < 0)
334                 return -errno;
335
336         if (!b->kdbus_buffer) {
337                 b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, b->input_fd, 0);
338                 if (b->kdbus_buffer == MAP_FAILED) {
339                         b->kdbus_buffer = NULL;
340                         return -errno;
341                 }
342         }
343
344         /* The higher 32bit of both flags fields are considered
345          * 'incompatible flags'. Refuse them all for now. */
346         if (hello.bus_flags > 0xFFFFFFFFULL ||
347             hello.conn_flags > 0xFFFFFFFFULL)
348                 return -ENOTSUP;
349
350         if (hello.bloom_size != BLOOM_SIZE)
351                 return -ENOTSUP;
352
353         if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello.id) < 0)
354                 return -ENOMEM;
355
356         b->is_kernel = true;
357         b->bus_client = true;
358         b->can_fds = !!(hello.conn_flags & KDBUS_HELLO_ACCEPT_FD);
359
360         r = bus_start_running(b);
361         if (r < 0)
362                 return r;
363
364         return 1;
365 }
366
367 int bus_kernel_connect(sd_bus *b) {
368         assert(b);
369         assert(b->input_fd < 0);
370         assert(b->output_fd < 0);
371         assert(b->kernel);
372
373         if (b->is_server)
374                 return -EINVAL;
375
376         b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
377         if (b->input_fd < 0)
378                 return -errno;
379
380         b->output_fd = b->input_fd;
381
382         return bus_kernel_take_fd(b);
383 }
384
385 int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
386         int r;
387
388         assert(bus);
389         assert(m);
390         assert(bus->state == BUS_RUNNING);
391
392         r = bus_message_setup_kmsg(bus, m);
393         if (r < 0)
394                 return r;
395
396         r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
397         if (r < 0)
398                 return errno == EAGAIN ? 0 : -errno;
399
400         return 1;
401 }
402
403 static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
404         uint64_t off;
405         struct kdbus_item *d;
406
407         assert(bus);
408         assert(k);
409
410         off = (uint8_t *)k - (uint8_t *)bus->kdbus_buffer;
411         ioctl(bus->input_fd, KDBUS_CMD_MSG_RELEASE, &off);
412
413         KDBUS_PART_FOREACH(d, k, items) {
414
415                 if (d->type == KDBUS_MSG_FDS)
416                         close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
417                 else if (d->type == KDBUS_MSG_PAYLOAD_MEMFD)
418                         close_nointr_nofail(d->memfd.fd);
419         }
420 }
421
422 static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_message **ret) {
423         sd_bus_message *m = NULL;
424         struct kdbus_item *d;
425         unsigned n_fds = 0;
426         _cleanup_free_ int *fds = NULL;
427         struct bus_header *h = NULL;
428         size_t total, n_bytes = 0, idx = 0;
429         const char *destination = NULL, *seclabel = NULL;
430         int r;
431
432         assert(bus);
433         assert(k);
434         assert(ret);
435
436         if (k->payload_type != KDBUS_PAYLOAD_DBUS1)
437                 return 0;
438
439         KDBUS_PART_FOREACH(d, k, items) {
440                 size_t l;
441
442                 l = d->size - offsetof(struct kdbus_item, data);
443
444                 if (d->type == KDBUS_MSG_PAYLOAD_OFF) {
445
446                         if (!h) {
447                                 h = (struct bus_header *)((uint8_t *)bus->kdbus_buffer + d->vec.offset);
448
449                                 if (!bus_header_is_complete(h, d->vec.size))
450                                         return -EBADMSG;
451                         }
452
453                         n_bytes += d->vec.size;
454
455                 } else if (d->type == KDBUS_MSG_PAYLOAD_MEMFD) {
456
457                         if (!h)
458                                 return -EBADMSG;
459
460                         n_bytes += d->memfd.size;
461
462                 } else if (d->type == KDBUS_MSG_FDS) {
463                         int *f;
464                         unsigned j;
465
466                         j = l / sizeof(int);
467                         f = realloc(fds, sizeof(int) * (n_fds + j));
468                         if (!f)
469                                 return -ENOMEM;
470
471                         fds = f;
472                         memcpy(fds + n_fds, d->fds, sizeof(int) * j);
473                         n_fds += j;
474
475                 } else if (d->type == KDBUS_MSG_SRC_SECLABEL)
476                         seclabel = d->str;
477         }
478
479         if (!h)
480                 return -EBADMSG;
481
482         r = bus_header_message_size(h, &total);
483         if (r < 0)
484                 return r;
485
486         if (n_bytes != total)
487                 return -EBADMSG;
488
489         r = bus_message_from_header(bus, h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m);
490         if (r < 0)
491                 return r;
492
493         KDBUS_PART_FOREACH(d, k, items) {
494                 size_t l;
495
496                 l = d->size - offsetof(struct kdbus_item, data);
497
498                 if (d->type == KDBUS_MSG_PAYLOAD_OFF) {
499                         size_t begin_body;
500
501                         begin_body = BUS_MESSAGE_BODY_BEGIN(m);
502
503                         if (idx + d->vec.size > begin_body) {
504                                 struct bus_body_part *part;
505
506                                 /* Contains body material */
507
508                                 part = message_append_part(m);
509                                 if (!part) {
510                                         r = -ENOMEM;
511                                         goto fail;
512                                 }
513
514                                 /* A -1 offset is NUL padding. */
515                                 part->is_zero = d->vec.offset == ~0ULL;
516
517                                 if (idx >= begin_body) {
518                                         if (!part->is_zero)
519                                                 part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset;
520                                         part->size = d->vec.size;
521                                 } else {
522                                         if (!part->is_zero)
523                                                 part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset + (begin_body - idx);
524                                         part->size = d->vec.size - (begin_body - idx);
525                                 }
526
527                                 part->sealed = true;
528                         }
529
530                         idx += d->vec.size;
531                 } else if (d->type == KDBUS_MSG_PAYLOAD_MEMFD) {
532                         struct bus_body_part *part;
533
534                         if (idx < BUS_MESSAGE_BODY_BEGIN(m)) {
535                                 r = -EBADMSG;
536                                 goto fail;
537                         }
538
539                         part = message_append_part(m);
540                         if (!part) {
541                                 r = -ENOMEM;
542                                 goto fail;
543                         }
544
545                         part->memfd = d->memfd.fd;
546                         part->size = d->memfd.size;
547                         part->sealed = true;
548
549                         idx += d->memfd.size;
550
551                 } else if (d->type == KDBUS_MSG_SRC_CREDS) {
552                         m->creds.pid_starttime = d->creds.starttime / NSEC_PER_USEC;
553                         m->creds.uid = d->creds.uid;
554                         m->creds.gid = d->creds.gid;
555                         m->creds.pid = d->creds.pid;
556                         m->creds.tid = d->creds.tid;
557                         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;
558
559                 } else if (d->type == KDBUS_MSG_TIMESTAMP) {
560                         m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC;
561                         m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC;
562
563                 } else if (d->type == KDBUS_MSG_SRC_PID_COMM) {
564                         m->creds.comm = d->str;
565                         m->creds.mask |= SD_BUS_CREDS_COMM & bus->creds_mask;
566
567                 } else if (d->type == KDBUS_MSG_SRC_TID_COMM) {
568                         m->creds.tid_comm = d->str;
569                         m->creds.mask |= SD_BUS_CREDS_TID_COMM & bus->creds_mask;
570
571                 } else if (d->type == KDBUS_MSG_SRC_EXE) {
572                         m->creds.exe = d->str;
573                         m->creds.mask |= SD_BUS_CREDS_EXE & bus->creds_mask;
574
575                 } else if (d->type == KDBUS_MSG_SRC_CMDLINE) {
576                         m->creds.cmdline = d->str;
577                         m->creds.cmdline_length = l;
578                         m->creds.mask |= SD_BUS_CREDS_CMDLINE & bus->creds_mask;
579
580                 } else if (d->type == KDBUS_MSG_SRC_CGROUP) {
581                         m->creds.cgroup = d->str;
582                         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;
583
584                 } else if (d->type == KDBUS_MSG_SRC_AUDIT) {
585                         m->creds.audit_session_id = d->audit.sessionid;
586                         m->creds.audit_login_uid = d->audit.loginuid;
587                         m->creds.mask |= (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID) & bus->creds_mask;
588
589                 } else if (d->type == KDBUS_MSG_SRC_CAPS) {
590                         m->creds.capability = d->data;
591                         m->creds.capability_size = l;
592                         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;
593
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                              d->type != KDBUS_MSG_SRC_NAMES)
599                         log_debug("Got unknown field from kernel %llu", d->type);
600         }
601
602         r = bus_message_parse_fields(m);
603         if (r < 0)
604                 goto fail;
605
606         if (k->src_id == KDBUS_SRC_ID_KERNEL)
607                 m->sender = "org.freedesktop.DBus";
608         else {
609                 snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
610                 m->sender = m->sender_buffer;
611         }
612
613         if (!m->destination) {
614                 if (destination)
615                         m->destination = destination;
616                 else if (k->dst_id != KDBUS_DST_ID_WELL_KNOWN_NAME &&
617                          k->dst_id != KDBUS_DST_ID_BROADCAST) {
618                         snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
619                         m->destination = m->destination_buffer;
620                 }
621         }
622
623         /* We take possession of the kmsg struct now */
624         m->kdbus = k;
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         uint64_t off;
651         struct kdbus_msg *k;
652         int r;
653
654         assert(bus);
655         assert(m);
656
657         r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, &off);
658         if (r < 0) {
659                 if (errno == EAGAIN)
660                         return 0;
661
662                 return -errno;
663         }
664         k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + off);
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;
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_PART_HEADER_SIZE + sizeof(uint64_t) +
690                        KDBUS_PART_HEADER_SIZE + DECIMAL_STR_MAX(uid_t) + 1 + l + 1);
691
692         n = make->items;
693         n->type = KDBUS_MAKE_NAME;
694         sprintf(n->str, "%lu-%s", (unsigned long) getuid(), name);
695         n->size = KDBUS_PART_HEADER_SIZE + strlen(n->str) + 1;
696
697         make->size = offsetof(struct kdbus_cmd_bus_make, items) + n->size;
698         make->flags = KDBUS_MAKE_POLICY_OPEN;
699         make->bus_flags = 0;
700         make->bloom_size = BLOOM_SIZE;
701         assert_cc(BLOOM_SIZE % 8 == 0);
702
703         p = strjoin("/dev/kdbus/", n->str, "/bus", NULL);
704         if (!p)
705                 return -ENOMEM;
706
707         if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
708                 close_nointr_nofail(fd);
709                 free(p);
710                 return -errno;
711         }
712
713         if (s)
714                 *s = p;
715
716         return fd;
717 }
718
719 int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *size) {
720         struct memfd_cache *c;
721         int fd;
722
723         assert(address);
724         assert(size);
725
726         if (!bus || !bus->is_kernel)
727                 return -ENOTSUP;
728
729         assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
730
731         if (bus->n_memfd_cache <= 0) {
732                 int r;
733
734                 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
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         fd = c->fd;
753
754         assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
755
756         return fd;
757 }
758
759 static void close_and_munmap(int fd, void *address, size_t size) {
760         if (size > 0)
761                 assert_se(munmap(address, PAGE_ALIGN(size)) >= 0);
762
763         close_nointr_nofail(fd);
764 }
765
766 void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t size) {
767         struct memfd_cache *c;
768         uint64_t max_sz = PAGE_ALIGN(MEMFD_CACHE_ITEM_SIZE_MAX);
769
770         assert(fd >= 0);
771         assert(size == 0 || address);
772
773         if (!bus || !bus->is_kernel) {
774                 close_and_munmap(fd, address, size);
775                 return;
776         }
777
778         assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
779
780         if (bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
781                 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
782
783                 close_and_munmap(fd, address, size);
784                 return;
785         }
786
787         c = &bus->memfd_cache[bus->n_memfd_cache++];
788         c->fd = fd;
789         c->address = address;
790
791         /* If overly long, let's return a bit to the OS */
792         if (size > max_sz) {
793                 assert_se(ioctl(fd, KDBUS_CMD_MEMFD_SIZE_SET, &max_sz) >= 0);
794                 assert_se(munmap((uint8_t*) address + max_sz, PAGE_ALIGN(size - max_sz)) >= 0);
795                 c->size = max_sz;
796         } else
797                 c->size = size;
798
799         assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
800 }
801
802 void bus_kernel_flush_memfd(sd_bus *b) {
803         unsigned i;
804
805         assert(b);
806
807         for (i = 0; i < b->n_memfd_cache; i++)
808                 close_and_munmap(b->memfd_cache[i].fd, b->memfd_cache[i].address, b->memfd_cache[i].size);
809 }
810
811 int sd_bus_kernel_translate_request_name_flags(uint64_t sd_bus_flags, uint64_t *kdbus_flags) {
812
813         assert_return(kdbus_flags != NULL, -EINVAL);
814
815         *kdbus_flags = 0;
816
817         if (sd_bus_flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
818                 *kdbus_flags |= KDBUS_NAME_ALLOW_REPLACEMENT;
819
820         if (sd_bus_flags & SD_BUS_NAME_REPLACE_EXISTING)
821                 *kdbus_flags |= KDBUS_NAME_REPLACE_EXISTING;
822
823         if (!(sd_bus_flags & SD_BUS_NAME_DO_NOT_QUEUE))
824                 *kdbus_flags |= KDBUS_NAME_QUEUE;
825
826         return 0;
827 }