chiark / gitweb /
libsystemd-bus: rename sd_bus_kernel_translate_request_name_flags
[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 #include "bus-util.h"
37
38 #define UNIQUE_NAME_MAX (3+DECIMAL_STR_MAX(uint64_t))
39
40 int bus_kernel_parse_unique_name(const char *s, uint64_t *id) {
41         int r;
42
43         assert(s);
44         assert(id);
45
46         if (!startswith(s, ":1."))
47                 return 0;
48
49         r = safe_atou64(s + 3, id);
50         if (r < 0)
51                 return r;
52
53         return 1;
54 }
55
56 static void append_payload_vec(struct kdbus_item **d, const void *p, size_t sz) {
57         assert(d);
58         assert(sz > 0);
59
60         *d = ALIGN8_PTR(*d);
61
62         /* Note that p can be NULL, which encodes a region full of
63          * zeroes, which is useful to optimize certain padding
64          * conditions */
65
66         (*d)->size = offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec);
67         (*d)->type = KDBUS_ITEM_PAYLOAD_VEC;
68         (*d)->vec.address = PTR_TO_UINT64(p);
69         (*d)->vec.size = sz;
70
71         *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
72 }
73
74 static void append_payload_memfd(struct kdbus_item **d, int memfd, size_t sz) {
75         assert(d);
76         assert(memfd >= 0);
77         assert(sz > 0);
78
79         *d = ALIGN8_PTR(*d);
80         (*d)->size = offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd);
81         (*d)->type = KDBUS_ITEM_PAYLOAD_MEMFD;
82         (*d)->memfd.fd = memfd;
83         (*d)->memfd.size = sz;
84
85         *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
86 }
87
88 static void append_destination(struct kdbus_item **d, const char *s, size_t length) {
89         assert(d);
90         assert(s);
91
92         *d = ALIGN8_PTR(*d);
93
94         (*d)->size = offsetof(struct kdbus_item, str) + length + 1;
95         (*d)->type = KDBUS_ITEM_DST_NAME;
96         memcpy((*d)->str, s, length + 1);
97
98         *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
99 }
100
101 static void* append_bloom(struct kdbus_item **d, size_t length) {
102         void *r;
103
104         assert(d);
105
106         *d = ALIGN8_PTR(*d);
107
108         (*d)->size = offsetof(struct kdbus_item, data) + length;
109         (*d)->type = KDBUS_ITEM_BLOOM;
110         r = (*d)->data;
111
112         *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
113
114         return r;
115 }
116
117 static void append_fds(struct kdbus_item **d, const int fds[], unsigned n_fds) {
118         assert(d);
119         assert(fds);
120         assert(n_fds > 0);
121
122         *d = ALIGN8_PTR(*d);
123         (*d)->size = offsetof(struct kdbus_item, fds) + sizeof(int) * n_fds;
124         (*d)->type = KDBUS_ITEM_FDS;
125         memcpy((*d)->fds, fds, sizeof(int) * n_fds);
126
127         *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
128 }
129
130 static int bus_message_setup_bloom(sd_bus_message *m, void *bloom) {
131         unsigned i;
132         int r;
133
134         assert(m);
135         assert(bloom);
136
137         memset(bloom, 0, BLOOM_SIZE);
138
139         bloom_add_pair(bloom, "message-type", bus_message_type_to_string(m->header->type));
140
141         if (m->interface)
142                 bloom_add_pair(bloom, "interface", m->interface);
143         if (m->member)
144                 bloom_add_pair(bloom, "member", m->member);
145         if (m->path) {
146                 bloom_add_pair(bloom, "path", m->path);
147                 bloom_add_pair(bloom, "path-slash-prefix", m->path);
148                 bloom_add_prefixes(bloom, "path-slash-prefix", m->path, '/');
149         }
150
151         r = sd_bus_message_rewind(m, true);
152         if (r < 0)
153                 return r;
154
155         for (i = 0; i < 64; i++) {
156                 char type;
157                 const char *t;
158                 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
159                 char *e;
160
161                 r = sd_bus_message_peek_type(m, &type, NULL);
162                 if (r < 0)
163                         return r;
164
165                 if (type != SD_BUS_TYPE_STRING &&
166                     type != SD_BUS_TYPE_OBJECT_PATH &&
167                     type != SD_BUS_TYPE_SIGNATURE)
168                         break;
169
170                 r = sd_bus_message_read_basic(m, type, &t);
171                 if (r < 0)
172                         return r;
173
174                 e = stpcpy(buf, "arg");
175                 if (i < 10)
176                         *(e++) = '0' + i;
177                 else {
178                         *(e++) = '0' + (i / 10);
179                         *(e++) = '0' + (i % 10);
180                 }
181
182                 *e = 0;
183                 bloom_add_pair(bloom, buf, t);
184
185                 strcpy(e, "-dot-prefix");
186                 bloom_add_prefixes(bloom, buf, t, '.');
187                 strcpy(e, "-slash-prefix");
188                 bloom_add_prefixes(bloom, buf, t, '/');
189         }
190
191         return 0;
192 }
193
194 static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
195         struct bus_body_part *part;
196         struct kdbus_item *d;
197         bool well_known;
198         uint64_t unique;
199         size_t sz, dl;
200         unsigned i;
201         int r;
202
203         assert(b);
204         assert(m);
205         assert(m->sealed);
206
207         if (m->kdbus)
208                 return 0;
209
210         if (m->destination) {
211                 r = bus_kernel_parse_unique_name(m->destination, &unique);
212                 if (r < 0)
213                         return r;
214
215                 well_known = r == 0;
216         } else
217                 well_known = false;
218
219         sz = offsetof(struct kdbus_msg, items);
220
221         assert_cc(ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec)) ==
222                   ALIGN8(offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd)));
223
224         /* Add in fixed header, fields header and payload */
225         sz += (1 + m->n_body_parts) *
226                 ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec));
227
228         /* Add space for bloom filter */
229         sz += ALIGN8(offsetof(struct kdbus_item, data) + BLOOM_SIZE);
230
231         /* Add in well-known destination header */
232         if (well_known) {
233                 dl = strlen(m->destination);
234                 sz += ALIGN8(offsetof(struct kdbus_item, str) + dl + 1);
235         }
236
237         /* Add space for unix fds */
238         if (m->n_fds > 0)
239                 sz += ALIGN8(offsetof(struct kdbus_item, fds) + sizeof(int)*m->n_fds);
240
241         m->kdbus = memalign(8, sz);
242         if (!m->kdbus) {
243                 r = -ENOMEM;
244                 goto fail;
245         }
246
247         m->free_kdbus = true;
248         memset(m->kdbus, 0, sz);
249
250         m->kdbus->flags =
251                 ((m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_FLAGS_EXPECT_REPLY) |
252                 ((m->header->flags & SD_BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_FLAGS_NO_AUTO_START : 0);
253         m->kdbus->dst_id =
254                 well_known ? 0 :
255                 m->destination ? unique : KDBUS_DST_ID_BROADCAST;
256         m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS1;
257         m->kdbus->cookie = m->header->serial;
258
259         m->kdbus->timeout_ns = m->timeout * NSEC_PER_USEC;
260
261         d = m->kdbus->items;
262
263         if (well_known)
264                 append_destination(&d, m->destination, dl);
265
266         append_payload_vec(&d, m->header, BUS_MESSAGE_BODY_BEGIN(m));
267
268         MESSAGE_FOREACH_PART(part, i, m) {
269                 if (part->is_zero) {
270                         /* If this is padding then simply send a
271                          * vector with a NULL data pointer which the
272                          * kernel will just pass through. This is the
273                          * most efficient way to encode zeroes */
274
275                         append_payload_vec(&d, NULL, part->size);
276                         continue;
277                 }
278
279                 if (part->memfd >= 0 && part->sealed && m->destination) {
280                         /* Try to send a memfd, if the part is
281                          * sealed and this is not a broadcast. Since we can only  */
282
283                         append_payload_memfd(&d, part->memfd, part->size);
284                         continue;
285                 }
286
287                 /* Otherwise let's send a vector to the actual data,
288                  * for that we need to map it first. */
289                 r = bus_body_part_map(part);
290                 if (r < 0)
291                         goto fail;
292
293                 append_payload_vec(&d, part->data, part->size);
294         }
295
296         if (m->kdbus->dst_id == KDBUS_DST_ID_BROADCAST) {
297                 void *p;
298
299                 p = append_bloom(&d, BLOOM_SIZE);
300                 r = bus_message_setup_bloom(m, p);
301                 if (r < 0)
302                         goto fail;
303         }
304
305         if (m->n_fds > 0)
306                 append_fds(&d, m->fds, m->n_fds);
307
308         m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus;
309         assert(m->kdbus->size <= sz);
310
311         return 0;
312
313 fail:
314         m->poisoned = true;
315         return r;
316 }
317
318 int bus_kernel_take_fd(sd_bus *b) {
319         struct kdbus_cmd_hello hello;
320         int r;
321
322         assert(b);
323
324         if (b->is_server)
325                 return -EINVAL;
326
327         b->use_memfd = 1;
328
329         zero(hello);
330         hello.size = sizeof(hello);
331         hello.conn_flags = b->hello_flags;
332         hello.attach_flags = b->attach_flags;
333         hello.pool_size = KDBUS_POOL_SIZE;
334
335         r = ioctl(b->input_fd, KDBUS_CMD_HELLO, &hello);
336         if (r < 0)
337                 return -errno;
338
339         if (!b->kdbus_buffer) {
340                 b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, b->input_fd, 0);
341                 if (b->kdbus_buffer == MAP_FAILED) {
342                         b->kdbus_buffer = NULL;
343                         return -errno;
344                 }
345         }
346
347         /* The higher 32bit of both flags fields are considered
348          * 'incompatible flags'. Refuse them all for now. */
349         if (hello.bus_flags > 0xFFFFFFFFULL ||
350             hello.conn_flags > 0xFFFFFFFFULL)
351                 return -ENOTSUP;
352
353         if (hello.bloom_size != BLOOM_SIZE)
354                 return -ENOTSUP;
355
356         if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello.id) < 0)
357                 return -ENOMEM;
358
359         b->is_kernel = true;
360         b->bus_client = true;
361         b->can_fds = !!(hello.conn_flags & KDBUS_HELLO_ACCEPT_FD);
362
363         /* the kernel told us the UUID of the underlying bus */
364         memcpy(b->server_id.bytes, hello.id128, sizeof(b->server_id.bytes));
365
366         r = bus_start_running(b);
367         if (r < 0)
368                 return r;
369
370         return 1;
371 }
372
373 int bus_kernel_connect(sd_bus *b) {
374         assert(b);
375         assert(b->input_fd < 0);
376         assert(b->output_fd < 0);
377         assert(b->kernel);
378
379         if (b->is_server)
380                 return -EINVAL;
381
382         b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
383         if (b->input_fd < 0)
384                 return -errno;
385
386         b->output_fd = b->input_fd;
387
388         return bus_kernel_take_fd(b);
389 }
390
391 int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
392         int r;
393
394         assert(bus);
395         assert(m);
396         assert(bus->state == BUS_RUNNING);
397
398         r = bus_message_setup_kmsg(bus, m);
399         if (r < 0)
400                 return r;
401
402         r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
403         if (r < 0)
404                 return errno == EAGAIN ? 0 : -errno;
405
406         return 1;
407 }
408
409 static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
410         uint64_t off;
411         struct kdbus_item *d;
412
413         assert(bus);
414         assert(k);
415
416         off = (uint8_t *)k - (uint8_t *)bus->kdbus_buffer;
417         ioctl(bus->input_fd, KDBUS_CMD_MSG_RELEASE, &off);
418
419         KDBUS_PART_FOREACH(d, k, items) {
420
421                 if (d->type == KDBUS_ITEM_FDS)
422                         close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
423                 else if (d->type == KDBUS_ITEM_PAYLOAD_MEMFD)
424                         close_nointr_nofail(d->memfd.fd);
425         }
426 }
427
428 static int return_name_owner_changed(sd_bus *bus, const char *name, const char *old_owner, const char *new_owner, sd_bus_message **ret) {
429         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
430         int r;
431
432         assert(bus);
433         assert(ret);
434
435         r = sd_bus_message_new_signal(
436                         bus,
437                         "/org/freedesktop/DBus",
438                         "org.freedesktop.DBus",
439                         "NameOwnerChanged",
440                         &m);
441         if (r < 0)
442                 return r;
443
444         r = sd_bus_message_append(m, "sss", name, old_owner, new_owner);
445         if (r < 0)
446                 return r;
447
448         m->sender = "org.freedesktop.DBus";
449
450         r = bus_seal_message(bus, m);
451         if (r < 0)
452                 return r;
453
454         *ret = m;
455         m = NULL;
456
457         return 1;
458 }
459
460 static int translate_name_change(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d, sd_bus_message **ret) {
461         char new_owner[UNIQUE_NAME_MAX], old_owner[UNIQUE_NAME_MAX];
462
463         assert(bus);
464         assert(k);
465         assert(d);
466         assert(ret);
467
468         if (d->name_change.flags != 0)
469                 return 0;
470
471         if (d->type == KDBUS_ITEM_NAME_ADD)
472                 old_owner[0] = 0;
473         else
474                 sprintf(old_owner, ":1.%llu", (unsigned long long) d->name_change.old_id);
475
476         if (d->type == KDBUS_ITEM_NAME_REMOVE)
477                 new_owner[0] = 0;
478         else
479                 sprintf(new_owner, ":1.%llu", (unsigned long long) d->name_change.new_id);
480
481         return return_name_owner_changed(bus, d->name_change.name, old_owner, new_owner, ret);
482 }
483
484 static int translate_id_change(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d, sd_bus_message **ret) {
485         char owner[UNIQUE_NAME_MAX];
486
487         assert(bus);
488         assert(k);
489         assert(d);
490         assert(ret);
491
492         sprintf(owner, ":1.%llu", d->id_change.id);
493
494         return return_name_owner_changed(
495                         bus, owner,
496                         d->type == KDBUS_ITEM_ID_ADD ? NULL : owner,
497                         d->type == KDBUS_ITEM_ID_ADD ? owner : NULL,
498                         ret);
499 }
500
501 static int translate_reply(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d, sd_bus_message **ret) {
502         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
503         int r;
504
505         assert(bus);
506         assert(k);
507         assert(d);
508         assert(ret);
509
510         r = bus_message_new_synthetic_error(
511                         bus,
512                         k->cookie_reply,
513                         d->type == KDBUS_ITEM_REPLY_TIMEOUT ?
514                         &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call timed out") :
515                         &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call peer died"),
516                         &m);
517         if (r < 0)
518                 return r;
519
520         m->sender = "org.freedesktop.DBus";
521
522         r = bus_seal_message(bus, m);
523         if (r < 0)
524                 return r;
525
526         *ret = m;
527         m = NULL;
528
529         return 1;
530 }
531
532 static int bus_kernel_translate_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_message **ret) {
533         struct kdbus_item *d, *found = NULL;
534
535         static int (* const translate[])(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d, sd_bus_message **ret) = {
536                 [KDBUS_ITEM_NAME_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
537                 [KDBUS_ITEM_NAME_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
538                 [KDBUS_ITEM_NAME_CHANGE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
539
540                 [KDBUS_ITEM_ID_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
541                 [KDBUS_ITEM_ID_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
542
543                 [KDBUS_ITEM_REPLY_TIMEOUT - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
544                 [KDBUS_ITEM_REPLY_DEAD - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
545         };
546
547         assert(bus);
548         assert(k);
549         assert(ret);
550         assert(k->payload_type == KDBUS_PAYLOAD_KERNEL);
551
552         KDBUS_PART_FOREACH(d, k, items) {
553                 if (d->type >= _KDBUS_ITEM_KERNEL_BASE && d->type < _KDBUS_ITEM_KERNEL_BASE + ELEMENTSOF(translate)) {
554                         if (found)
555                                 return -EBADMSG;
556                         found = d;
557                 } else
558                         log_debug("Got unknown field from kernel %llu", d->type);
559         }
560
561         if (!found) {
562                 log_debug("Didn't find a kernel message to translate.");
563                 return 0;
564         }
565
566         return translate[found->type](bus, k, d, ret);
567 }
568
569 int kdbus_translate_attach_flags(uint64_t mask, uint64_t *kdbus_mask) {
570
571         uint64_t m = 0;
572
573         SET_FLAG(m, KDBUS_ATTACH_CREDS,
574                  !!(mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID)));
575
576         SET_FLAG(m, KDBUS_ATTACH_COMM,
577                  !!(mask & (SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM)));
578
579         SET_FLAG(m, KDBUS_ATTACH_EXE,
580                  !!(mask & SD_BUS_CREDS_EXE));
581
582         SET_FLAG(m, KDBUS_ATTACH_CMDLINE,
583                  !!(mask & SD_BUS_CREDS_CMDLINE));
584
585         SET_FLAG(m, KDBUS_ATTACH_CGROUP,
586                  !!(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)));
587
588         SET_FLAG(m, KDBUS_ATTACH_CAPS,
589                  !!(mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)));
590
591         SET_FLAG(m, KDBUS_ATTACH_SECLABEL,
592                  !!(mask & SD_BUS_CREDS_SELINUX_CONTEXT));
593
594         SET_FLAG(m, KDBUS_ATTACH_AUDIT,
595                  !!(mask & (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)));
596
597         *kdbus_mask = m;
598
599         return 0;
600 }
601
602 static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_message **ret) {
603         sd_bus_message *m = NULL;
604         struct kdbus_item *d;
605         unsigned n_fds = 0;
606         _cleanup_free_ int *fds = NULL;
607         struct bus_header *h = NULL;
608         size_t total, n_bytes = 0, idx = 0;
609         const char *destination = NULL, *seclabel = NULL;
610         int r;
611
612         assert(bus);
613         assert(k);
614         assert(ret);
615         assert(k->payload_type == KDBUS_PAYLOAD_DBUS1);
616
617         KDBUS_PART_FOREACH(d, k, items) {
618                 size_t l;
619
620                 l = d->size - offsetof(struct kdbus_item, data);
621
622                 switch (d->type) {
623
624                 case KDBUS_ITEM_PAYLOAD_OFF:
625                         if (!h) {
626                                 h = (struct bus_header *)((uint8_t *)bus->kdbus_buffer + d->vec.offset);
627
628                                 if (!bus_header_is_complete(h, d->vec.size))
629                                         return -EBADMSG;
630                         }
631
632                         n_bytes += d->vec.size;
633                         break;
634
635                 case KDBUS_ITEM_PAYLOAD_MEMFD:
636                         if (!h)
637                                 return -EBADMSG;
638
639                         n_bytes += d->memfd.size;
640                         break;
641
642                 case KDBUS_ITEM_FDS: {
643                         int *f;
644                         unsigned j;
645
646                         j = l / sizeof(int);
647                         f = realloc(fds, sizeof(int) * (n_fds + j));
648                         if (!f)
649                                 return -ENOMEM;
650
651                         fds = f;
652                         memcpy(fds + n_fds, d->fds, sizeof(int) * j);
653                         n_fds += j;
654                         break;
655                 }
656
657                 case KDBUS_ITEM_SECLABEL:
658                         seclabel = d->str;
659                         break;
660                 }
661         }
662
663         if (!h)
664                 return -EBADMSG;
665
666         r = bus_header_message_size(h, &total);
667         if (r < 0)
668                 return r;
669
670         if (n_bytes != total)
671                 return -EBADMSG;
672
673         r = bus_message_from_header(bus, h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m);
674         if (r < 0)
675                 return r;
676
677         KDBUS_PART_FOREACH(d, k, items) {
678                 size_t l;
679
680                 l = d->size - offsetof(struct kdbus_item, data);
681
682                 switch (d->type) {
683
684                 case KDBUS_ITEM_PAYLOAD_OFF: {
685                         size_t begin_body;
686
687                         begin_body = BUS_MESSAGE_BODY_BEGIN(m);
688
689                         if (idx + d->vec.size > begin_body) {
690                                 struct bus_body_part *part;
691
692                                 /* Contains body material */
693
694                                 part = message_append_part(m);
695                                 if (!part) {
696                                         r = -ENOMEM;
697                                         goto fail;
698                                 }
699
700                                 /* A -1 offset is NUL padding. */
701                                 part->is_zero = d->vec.offset == ~0ULL;
702
703                                 if (idx >= begin_body) {
704                                         if (!part->is_zero)
705                                                 part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset;
706                                         part->size = d->vec.size;
707                                 } else {
708                                         if (!part->is_zero)
709                                                 part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset + (begin_body - idx);
710                                         part->size = d->vec.size - (begin_body - idx);
711                                 }
712
713                                 part->sealed = true;
714                         }
715
716                         idx += d->vec.size;
717                         break;
718                 }
719
720                 case KDBUS_ITEM_PAYLOAD_MEMFD: {
721                         struct bus_body_part *part;
722
723                         if (idx < BUS_MESSAGE_BODY_BEGIN(m)) {
724                                 r = -EBADMSG;
725                                 goto fail;
726                         }
727
728                         part = message_append_part(m);
729                         if (!part) {
730                                 r = -ENOMEM;
731                                 goto fail;
732                         }
733
734                         part->memfd = d->memfd.fd;
735                         part->size = d->memfd.size;
736                         part->sealed = true;
737
738                         idx += d->memfd.size;
739                         break;
740                 }
741
742                 case KDBUS_ITEM_CREDS:
743                         m->creds.pid_starttime = d->creds.starttime / NSEC_PER_USEC;
744                         m->creds.uid = d->creds.uid;
745                         m->creds.gid = d->creds.gid;
746                         m->creds.pid = d->creds.pid;
747                         m->creds.tid = d->creds.tid;
748                         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;
749                         break;
750
751                 case KDBUS_ITEM_TIMESTAMP:
752                         m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC;
753                         m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC;
754                         break;
755
756                 case KDBUS_ITEM_PID_COMM:
757                         m->creds.comm = d->str;
758                         m->creds.mask |= SD_BUS_CREDS_COMM & bus->creds_mask;
759                         break;
760
761                 case KDBUS_ITEM_TID_COMM:
762                         m->creds.tid_comm = d->str;
763                         m->creds.mask |= SD_BUS_CREDS_TID_COMM & bus->creds_mask;
764                         break;
765
766                 case KDBUS_ITEM_EXE:
767                         m->creds.exe = d->str;
768                         m->creds.mask |= SD_BUS_CREDS_EXE & bus->creds_mask;
769                         break;
770
771                 case KDBUS_ITEM_CMDLINE:
772                         m->creds.cmdline = d->str;
773                         m->creds.cmdline_length = l;
774                         m->creds.mask |= SD_BUS_CREDS_CMDLINE & bus->creds_mask;
775                         break;
776
777                 case KDBUS_ITEM_CGROUP:
778                         m->creds.cgroup = d->str;
779                         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;
780                         break;
781
782                 case KDBUS_ITEM_AUDIT:
783                         m->creds.audit_session_id = d->audit.sessionid;
784                         m->creds.audit_login_uid = d->audit.loginuid;
785                         m->creds.mask |= (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID) & bus->creds_mask;
786                         break;
787
788                 case KDBUS_ITEM_CAPS:
789                         m->creds.capability = d->data;
790                         m->creds.capability_size = l;
791                         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;
792                         break;
793
794                 case KDBUS_ITEM_DST_NAME:
795                         destination = d->str;
796                         break;
797
798                 case KDBUS_ITEM_FDS:
799                 case KDBUS_ITEM_SECLABEL:
800                 case KDBUS_ITEM_NAMES:
801                         break;
802
803                 default:
804                         log_debug("Got unknown field from kernel %llu", d->type);
805                 }
806         }
807
808         r = bus_message_parse_fields(m);
809         if (r < 0)
810                 goto fail;
811
812         if (k->src_id == KDBUS_SRC_ID_KERNEL)
813                 m->sender = "org.freedesktop.DBus";
814         else {
815                 snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
816                 m->sender = m->sender_buffer;
817         }
818
819         if (!m->destination) {
820                 if (destination)
821                         m->destination = destination;
822                 else if (k->dst_id != KDBUS_DST_ID_WELL_KNOWN_NAME &&
823                          k->dst_id != KDBUS_DST_ID_BROADCAST) {
824                         snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
825                         m->destination = m->destination_buffer;
826                 }
827         }
828
829         /* We take possession of the kmsg struct now */
830         m->kdbus = k;
831         m->release_kdbus = true;
832         m->free_fds = true;
833
834         fds = NULL;
835
836         *ret = m;
837         return 1;
838
839 fail:
840         if (m) {
841                 struct bus_body_part *part;
842                 unsigned i;
843
844                 /* Make sure the memfds are not freed twice */
845                 MESSAGE_FOREACH_PART(part, i, m)
846                         if (part->memfd >= 0)
847                                 part->memfd = -1;
848
849                 sd_bus_message_unref(m);
850         }
851
852         return r;
853 }
854
855 int bus_kernel_read_message(sd_bus *bus, sd_bus_message **m) {
856         uint64_t off;
857         struct kdbus_msg *k;
858         int r;
859
860         assert(bus);
861         assert(m);
862
863         r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, &off);
864         if (r < 0) {
865                 if (errno == EAGAIN)
866                         return 0;
867
868                 return -errno;
869         }
870         k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + off);
871
872         if (k->payload_type == KDBUS_PAYLOAD_DBUS1)
873                 r = bus_kernel_make_message(bus, k, m);
874         else if (k->payload_type == KDBUS_PAYLOAD_KERNEL)
875                 r = bus_kernel_translate_message(bus, k, m);
876         else
877                 r = 0;
878
879         if (r <= 0)
880                 close_kdbus_msg(bus, k);
881
882         return r < 0 ? r : 1;
883 }
884
885 int bus_kernel_create(const char *name, char **s) {
886         struct kdbus_cmd_bus_make *make;
887         struct kdbus_item *n;
888         size_t l;
889         int fd;
890         char *p;
891
892         assert(name);
893         assert(s);
894
895         fd = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
896         if (fd < 0)
897                 return -errno;
898
899         l = strlen(name);
900         make = alloca0(offsetof(struct kdbus_cmd_bus_make, items) +
901                        KDBUS_PART_HEADER_SIZE + sizeof(uint64_t) +
902                        KDBUS_PART_HEADER_SIZE + DECIMAL_STR_MAX(uid_t) + 1 + l + 1);
903
904         n = make->items;
905         n->type = KDBUS_MAKE_NAME;
906         sprintf(n->str, "%lu-%s", (unsigned long) getuid(), name);
907         n->size = KDBUS_PART_HEADER_SIZE + strlen(n->str) + 1;
908
909         make->size = offsetof(struct kdbus_cmd_bus_make, items) + n->size;
910         make->flags = KDBUS_MAKE_POLICY_OPEN;
911         make->bus_flags = 0;
912         make->bloom_size = BLOOM_SIZE;
913         assert_cc(BLOOM_SIZE % 8 == 0);
914
915         p = strjoin("/dev/kdbus/", n->str, "/bus", NULL);
916         if (!p)
917                 return -ENOMEM;
918
919         if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
920                 close_nointr_nofail(fd);
921                 free(p);
922                 return -errno;
923         }
924
925         if (s)
926                 *s = p;
927
928         return fd;
929 }
930
931 int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *size) {
932         struct memfd_cache *c;
933         int fd;
934
935         assert(address);
936         assert(size);
937
938         if (!bus || !bus->is_kernel)
939                 return -ENOTSUP;
940
941         assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
942
943         if (bus->n_memfd_cache <= 0) {
944                 int r;
945
946                 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
947
948                 r = ioctl(bus->input_fd, KDBUS_CMD_MEMFD_NEW, &fd);
949                 if (r < 0)
950                         return -errno;
951
952                 *address = NULL;
953                 *size = 0;
954                 return fd;
955         }
956
957         c = &bus->memfd_cache[--bus->n_memfd_cache];
958
959         assert(c->fd >= 0);
960         assert(c->size == 0 || c->address);
961
962         *address = c->address;
963         *size = c->size;
964         fd = c->fd;
965
966         assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
967
968         return fd;
969 }
970
971 static void close_and_munmap(int fd, void *address, size_t size) {
972         if (size > 0)
973                 assert_se(munmap(address, PAGE_ALIGN(size)) >= 0);
974
975         close_nointr_nofail(fd);
976 }
977
978 void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t size) {
979         struct memfd_cache *c;
980         uint64_t max_sz = PAGE_ALIGN(MEMFD_CACHE_ITEM_SIZE_MAX);
981
982         assert(fd >= 0);
983         assert(size == 0 || address);
984
985         if (!bus || !bus->is_kernel) {
986                 close_and_munmap(fd, address, size);
987                 return;
988         }
989
990         assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
991
992         if (bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
993                 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
994
995                 close_and_munmap(fd, address, size);
996                 return;
997         }
998
999         c = &bus->memfd_cache[bus->n_memfd_cache++];
1000         c->fd = fd;
1001         c->address = address;
1002
1003         /* If overly long, let's return a bit to the OS */
1004         if (size > max_sz) {
1005                 assert_se(ioctl(fd, KDBUS_CMD_MEMFD_SIZE_SET, &max_sz) >= 0);
1006                 assert_se(munmap((uint8_t*) address + max_sz, PAGE_ALIGN(size - max_sz)) >= 0);
1007                 c->size = max_sz;
1008         } else
1009                 c->size = size;
1010
1011         assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
1012 }
1013
1014 void bus_kernel_flush_memfd(sd_bus *b) {
1015         unsigned i;
1016
1017         assert(b);
1018
1019         for (i = 0; i < b->n_memfd_cache; i++)
1020                 close_and_munmap(b->memfd_cache[i].fd, b->memfd_cache[i].address, b->memfd_cache[i].size);
1021 }
1022
1023 int kdbus_translate_request_name_flags(uint64_t sd_bus_flags, uint64_t *kdbus_flags) {
1024
1025         assert_return(kdbus_flags != NULL, -EINVAL);
1026
1027         *kdbus_flags = 0;
1028
1029         if (sd_bus_flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
1030                 *kdbus_flags |= KDBUS_NAME_ALLOW_REPLACEMENT;
1031
1032         if (sd_bus_flags & SD_BUS_NAME_REPLACE_EXISTING)
1033                 *kdbus_flags |= KDBUS_NAME_REPLACE_EXISTING;
1034
1035         if (!(sd_bus_flags & SD_BUS_NAME_DO_NOT_QUEUE))
1036                 *kdbus_flags |= KDBUS_NAME_QUEUE;
1037
1038         return 0;
1039 }