chiark / gitweb /
6962fdcdb326b889275cc417e2d6c412a6825cd9
[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_ITEM_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_ITEM_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_ITEM_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_ITEM_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_ITEM_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         /* the kernel told us the UUID of the underlying bus */
361         memcpy(b->server_id.bytes, hello.id128, sizeof(b->server_id.bytes));
362
363         r = bus_start_running(b);
364         if (r < 0)
365                 return r;
366
367         return 1;
368 }
369
370 int bus_kernel_connect(sd_bus *b) {
371         assert(b);
372         assert(b->input_fd < 0);
373         assert(b->output_fd < 0);
374         assert(b->kernel);
375
376         if (b->is_server)
377                 return -EINVAL;
378
379         b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
380         if (b->input_fd < 0)
381                 return -errno;
382
383         b->output_fd = b->input_fd;
384
385         return bus_kernel_take_fd(b);
386 }
387
388 int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
389         int r;
390
391         assert(bus);
392         assert(m);
393         assert(bus->state == BUS_RUNNING);
394
395         r = bus_message_setup_kmsg(bus, m);
396         if (r < 0)
397                 return r;
398
399         r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
400         if (r < 0)
401                 return errno == EAGAIN ? 0 : -errno;
402
403         return 1;
404 }
405
406 static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
407         uint64_t off;
408         struct kdbus_item *d;
409
410         assert(bus);
411         assert(k);
412
413         off = (uint8_t *)k - (uint8_t *)bus->kdbus_buffer;
414         ioctl(bus->input_fd, KDBUS_CMD_MSG_RELEASE, &off);
415
416         KDBUS_PART_FOREACH(d, k, items) {
417
418                 if (d->type == KDBUS_ITEM_FDS)
419                         close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
420                 else if (d->type == KDBUS_ITEM_PAYLOAD_MEMFD)
421                         close_nointr_nofail(d->memfd.fd);
422         }
423 }
424
425 static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_message **ret) {
426         sd_bus_message *m = NULL;
427         struct kdbus_item *d;
428         unsigned n_fds = 0;
429         _cleanup_free_ int *fds = NULL;
430         struct bus_header *h = NULL;
431         size_t total, n_bytes = 0, idx = 0;
432         const char *destination = NULL, *seclabel = NULL;
433         int r;
434
435         assert(bus);
436         assert(k);
437         assert(ret);
438
439         if (k->payload_type != KDBUS_PAYLOAD_DBUS1)
440                 return 0;
441
442         KDBUS_PART_FOREACH(d, k, items) {
443                 size_t l;
444
445                 l = d->size - offsetof(struct kdbus_item, data);
446
447                 if (d->type == KDBUS_ITEM_PAYLOAD_OFF) {
448
449                         if (!h) {
450                                 h = (struct bus_header *)((uint8_t *)bus->kdbus_buffer + d->vec.offset);
451
452                                 if (!bus_header_is_complete(h, d->vec.size))
453                                         return -EBADMSG;
454                         }
455
456                         n_bytes += d->vec.size;
457
458                 } else if (d->type == KDBUS_ITEM_PAYLOAD_MEMFD) {
459
460                         if (!h)
461                                 return -EBADMSG;
462
463                         n_bytes += d->memfd.size;
464
465                 } else if (d->type == KDBUS_ITEM_FDS) {
466                         int *f;
467                         unsigned j;
468
469                         j = l / sizeof(int);
470                         f = realloc(fds, sizeof(int) * (n_fds + j));
471                         if (!f)
472                                 return -ENOMEM;
473
474                         fds = f;
475                         memcpy(fds + n_fds, d->fds, sizeof(int) * j);
476                         n_fds += j;
477
478                 } else if (d->type == KDBUS_ITEM_SECLABEL)
479                         seclabel = d->str;
480         }
481
482         if (!h)
483                 return -EBADMSG;
484
485         r = bus_header_message_size(h, &total);
486         if (r < 0)
487                 return r;
488
489         if (n_bytes != total)
490                 return -EBADMSG;
491
492         r = bus_message_from_header(bus, h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m);
493         if (r < 0)
494                 return r;
495
496         KDBUS_PART_FOREACH(d, k, items) {
497                 size_t l;
498
499                 l = d->size - offsetof(struct kdbus_item, data);
500
501                 if (d->type == KDBUS_ITEM_PAYLOAD_OFF) {
502                         size_t begin_body;
503
504                         begin_body = BUS_MESSAGE_BODY_BEGIN(m);
505
506                         if (idx + d->vec.size > begin_body) {
507                                 struct bus_body_part *part;
508
509                                 /* Contains body material */
510
511                                 part = message_append_part(m);
512                                 if (!part) {
513                                         r = -ENOMEM;
514                                         goto fail;
515                                 }
516
517                                 /* A -1 offset is NUL padding. */
518                                 part->is_zero = d->vec.offset == ~0ULL;
519
520                                 if (idx >= begin_body) {
521                                         if (!part->is_zero)
522                                                 part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset;
523                                         part->size = d->vec.size;
524                                 } else {
525                                         if (!part->is_zero)
526                                                 part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset + (begin_body - idx);
527                                         part->size = d->vec.size - (begin_body - idx);
528                                 }
529
530                                 part->sealed = true;
531                         }
532
533                         idx += d->vec.size;
534                 } else if (d->type == KDBUS_ITEM_PAYLOAD_MEMFD) {
535                         struct bus_body_part *part;
536
537                         if (idx < BUS_MESSAGE_BODY_BEGIN(m)) {
538                                 r = -EBADMSG;
539                                 goto fail;
540                         }
541
542                         part = message_append_part(m);
543                         if (!part) {
544                                 r = -ENOMEM;
545                                 goto fail;
546                         }
547
548                         part->memfd = d->memfd.fd;
549                         part->size = d->memfd.size;
550                         part->sealed = true;
551
552                         idx += d->memfd.size;
553
554                 } else if (d->type == KDBUS_ITEM_CREDS) {
555                         m->creds.pid_starttime = d->creds.starttime / NSEC_PER_USEC;
556                         m->creds.uid = d->creds.uid;
557                         m->creds.gid = d->creds.gid;
558                         m->creds.pid = d->creds.pid;
559                         m->creds.tid = d->creds.tid;
560                         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;
561
562                 } else if (d->type == KDBUS_ITEM_TIMESTAMP) {
563                         m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC;
564                         m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC;
565
566                 } else if (d->type == KDBUS_ITEM_PID_COMM) {
567                         m->creds.comm = d->str;
568                         m->creds.mask |= SD_BUS_CREDS_COMM & bus->creds_mask;
569
570                 } else if (d->type == KDBUS_ITEM_TID_COMM) {
571                         m->creds.tid_comm = d->str;
572                         m->creds.mask |= SD_BUS_CREDS_TID_COMM & bus->creds_mask;
573
574                 } else if (d->type == KDBUS_ITEM_EXE) {
575                         m->creds.exe = d->str;
576                         m->creds.mask |= SD_BUS_CREDS_EXE & bus->creds_mask;
577
578                 } else if (d->type == KDBUS_ITEM_CMDLINE) {
579                         m->creds.cmdline = d->str;
580                         m->creds.cmdline_length = l;
581                         m->creds.mask |= SD_BUS_CREDS_CMDLINE & bus->creds_mask;
582
583                 } else if (d->type == KDBUS_ITEM_CGROUP) {
584                         m->creds.cgroup = d->str;
585                         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;
586
587                 } else if (d->type == KDBUS_ITEM_AUDIT) {
588                         m->creds.audit_session_id = d->audit.sessionid;
589                         m->creds.audit_login_uid = d->audit.loginuid;
590                         m->creds.mask |= (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID) & bus->creds_mask;
591
592                 } else if (d->type == KDBUS_ITEM_CAPS) {
593                         m->creds.capability = d->data;
594                         m->creds.capability_size = l;
595                         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;
596
597                 } else if (d->type == KDBUS_ITEM_DST_NAME)
598                         destination = d->str;
599                 else if (d->type != KDBUS_ITEM_FDS &&
600                            d->type != KDBUS_ITEM_SECLABEL &&
601                              d->type != KDBUS_ITEM_NAMES)
602                         log_debug("Got unknown field from kernel %llu", d->type);
603         }
604
605         r = bus_message_parse_fields(m);
606         if (r < 0)
607                 goto fail;
608
609         if (k->src_id == KDBUS_SRC_ID_KERNEL)
610                 m->sender = "org.freedesktop.DBus";
611         else {
612                 snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
613                 m->sender = m->sender_buffer;
614         }
615
616         if (!m->destination) {
617                 if (destination)
618                         m->destination = destination;
619                 else if (k->dst_id != KDBUS_DST_ID_WELL_KNOWN_NAME &&
620                          k->dst_id != KDBUS_DST_ID_BROADCAST) {
621                         snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
622                         m->destination = m->destination_buffer;
623                 }
624         }
625
626         /* We take possession of the kmsg struct now */
627         m->kdbus = k;
628         m->release_kdbus = true;
629         m->free_fds = true;
630
631         fds = NULL;
632
633         *ret = m;
634         return 1;
635
636 fail:
637         if (m) {
638                 struct bus_body_part *part;
639                 unsigned i;
640
641                 /* Make sure the memfds are not freed twice */
642                 MESSAGE_FOREACH_PART(part, i, m)
643                         if (part->memfd >= 0)
644                                 part->memfd = -1;
645
646                 sd_bus_message_unref(m);
647         }
648
649         return r;
650 }
651
652 int bus_kernel_read_message(sd_bus *bus, sd_bus_message **m) {
653         uint64_t off;
654         struct kdbus_msg *k;
655         int r;
656
657         assert(bus);
658         assert(m);
659
660         r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, &off);
661         if (r < 0) {
662                 if (errno == EAGAIN)
663                         return 0;
664
665                 return -errno;
666         }
667         k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + off);
668
669         r = bus_kernel_make_message(bus, k, m);
670         if (r <= 0)
671                 close_kdbus_msg(bus, k);
672
673         return r < 0 ? r : 1;
674 }
675
676 int bus_kernel_create(const char *name, char **s) {
677         struct kdbus_cmd_bus_make *make;
678         struct kdbus_item *n;
679         size_t l;
680         int fd;
681         char *p;
682
683         assert(name);
684         assert(s);
685
686         fd = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
687         if (fd < 0)
688                 return -errno;
689
690         l = strlen(name);
691         make = alloca0(offsetof(struct kdbus_cmd_bus_make, items) +
692                        KDBUS_PART_HEADER_SIZE + sizeof(uint64_t) +
693                        KDBUS_PART_HEADER_SIZE + DECIMAL_STR_MAX(uid_t) + 1 + l + 1);
694
695         n = make->items;
696         n->type = KDBUS_MAKE_NAME;
697         sprintf(n->str, "%lu-%s", (unsigned long) getuid(), name);
698         n->size = KDBUS_PART_HEADER_SIZE + strlen(n->str) + 1;
699
700         make->size = offsetof(struct kdbus_cmd_bus_make, items) + 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         int fd;
725
726         assert(address);
727         assert(size);
728
729         if (!bus || !bus->is_kernel)
730                 return -ENOTSUP;
731
732         assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
733
734         if (bus->n_memfd_cache <= 0) {
735                 int r;
736
737                 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
738
739                 r = ioctl(bus->input_fd, KDBUS_CMD_MEMFD_NEW, &fd);
740                 if (r < 0)
741                         return -errno;
742
743                 *address = NULL;
744                 *size = 0;
745                 return fd;
746         }
747
748         c = &bus->memfd_cache[--bus->n_memfd_cache];
749
750         assert(c->fd >= 0);
751         assert(c->size == 0 || c->address);
752
753         *address = c->address;
754         *size = c->size;
755         fd = c->fd;
756
757         assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
758
759         return fd;
760 }
761
762 static void close_and_munmap(int fd, void *address, size_t size) {
763         if (size > 0)
764                 assert_se(munmap(address, PAGE_ALIGN(size)) >= 0);
765
766         close_nointr_nofail(fd);
767 }
768
769 void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t size) {
770         struct memfd_cache *c;
771         uint64_t max_sz = PAGE_ALIGN(MEMFD_CACHE_ITEM_SIZE_MAX);
772
773         assert(fd >= 0);
774         assert(size == 0 || address);
775
776         if (!bus || !bus->is_kernel) {
777                 close_and_munmap(fd, address, size);
778                 return;
779         }
780
781         assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
782
783         if (bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
784                 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
785
786                 close_and_munmap(fd, address, size);
787                 return;
788         }
789
790         c = &bus->memfd_cache[bus->n_memfd_cache++];
791         c->fd = fd;
792         c->address = address;
793
794         /* If overly long, let's return a bit to the OS */
795         if (size > max_sz) {
796                 assert_se(ioctl(fd, KDBUS_CMD_MEMFD_SIZE_SET, &max_sz) >= 0);
797                 assert_se(munmap((uint8_t*) address + max_sz, PAGE_ALIGN(size - max_sz)) >= 0);
798                 c->size = max_sz;
799         } else
800                 c->size = size;
801
802         assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
803 }
804
805 void bus_kernel_flush_memfd(sd_bus *b) {
806         unsigned i;
807
808         assert(b);
809
810         for (i = 0; i < b->n_memfd_cache; i++)
811                 close_and_munmap(b->memfd_cache[i].fd, b->memfd_cache[i].address, b->memfd_cache[i].size);
812 }
813
814 int sd_bus_kernel_translate_request_name_flags(uint64_t sd_bus_flags, uint64_t *kdbus_flags) {
815
816         assert_return(kdbus_flags != NULL, -EINVAL);
817
818         *kdbus_flags = 0;
819
820         if (sd_bus_flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
821                 *kdbus_flags |= KDBUS_NAME_ALLOW_REPLACEMENT;
822
823         if (sd_bus_flags & SD_BUS_NAME_REPLACE_EXISTING)
824                 *kdbus_flags |= KDBUS_NAME_REPLACE_EXISTING;
825
826         if (!(sd_bus_flags & SD_BUS_NAME_DO_NOT_QUEUE))
827                 *kdbus_flags |= KDBUS_NAME_QUEUE;
828
829         return 0;
830 }