chiark / gitweb /
378d1af1a0e82e8d6d673adbb5bb3febcb43f8bb
[elogind.git] / src / libelogind / sd-bus / bus-message.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 #include <errno.h>
23 #include <fcntl.h>
24 #include <sys/mman.h>
25
26 #include "util.h"
27 #include "utf8.h"
28 #include "strv.h"
29 #include "time-util.h"
30 #include "memfd-util.h"
31
32 #include "sd-bus.h"
33 #include "bus-message.h"
34 #include "bus-internal.h"
35 #include "bus-type.h"
36 #include "bus-signature.h"
37 #include "bus-gvariant.h"
38 #include "bus-util.h"
39
40 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
41
42 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
43
44         if (p == NULL)
45                 return NULL;
46
47         if (old_base == new_base)
48                 return (void*) p;
49
50         if ((uint8_t*) p < (uint8_t*) old_base)
51                 return (void*) p;
52
53         if ((uint8_t*) p >= (uint8_t*) old_base + sz)
54                 return (void*) p;
55
56         return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
57 }
58
59 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
60         assert(m);
61         assert(part);
62
63         if (part->memfd >= 0) {
64                 /* If we can reuse the memfd, try that. For that it
65                  * can't be sealed yet. */
66
67                 if (!part->sealed) {
68                         assert(part->memfd_offset == 0);
69                         assert(part->data == part->mmap_begin);
70                         bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped, part->allocated);
71                 } else {
72                         if (part->mapped > 0)
73                                 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
74
75                         safe_close(part->memfd);
76                 }
77
78         } else if (part->munmap_this)
79                 munmap(part->mmap_begin, part->mapped);
80         else if (part->free_this)
81                 free(part->data);
82
83         if (part != &m->body)
84                 free(part);
85 }
86
87 static void message_reset_parts(sd_bus_message *m) {
88         struct bus_body_part *part;
89
90         assert(m);
91
92         part = &m->body;
93         while (m->n_body_parts > 0) {
94                 struct bus_body_part *next = part->next;
95                 message_free_part(m, part);
96                 part = next;
97                 m->n_body_parts--;
98         }
99
100         m->body_end = NULL;
101
102         m->cached_rindex_part = NULL;
103         m->cached_rindex_part_begin = 0;
104 }
105
106 static void message_reset_containers(sd_bus_message *m) {
107         unsigned i;
108
109         assert(m);
110
111         for (i = 0; i < m->n_containers; i++) {
112                 free(m->containers[i].signature);
113                 free(m->containers[i].offsets);
114         }
115
116         free(m->containers);
117         m->containers = NULL;
118
119         m->n_containers = m->containers_allocated = 0;
120         m->root_container.index = 0;
121 }
122
123 static void message_free(sd_bus_message *m) {
124         assert(m);
125
126         if (m->free_header)
127                 free(m->header);
128
129         message_reset_parts(m);
130
131         if (m->release_kdbus)
132                 bus_kernel_cmd_free(m->bus, (uint8_t *) m->kdbus - (uint8_t *) m->bus->kdbus_buffer);
133
134         if (m->free_kdbus)
135                 free(m->kdbus);
136
137         sd_bus_unref(m->bus);
138
139         if (m->free_fds) {
140                 close_many(m->fds, m->n_fds);
141                 free(m->fds);
142         }
143
144         if (m->iovec != m->iovec_fixed)
145                 free(m->iovec);
146
147         m->destination_ptr = mfree(m->destination_ptr);
148         message_reset_containers(m);
149         free(m->root_container.signature);
150         free(m->root_container.offsets);
151
152         free(m->root_container.peeked_signature);
153
154         bus_creds_done(&m->creds);
155         free(m);
156 }
157
158 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
159         void *op, *np;
160         size_t old_size, new_size, start;
161
162         assert(m);
163
164         if (m->poisoned)
165                 return NULL;
166
167         old_size = sizeof(struct bus_header) + m->fields_size;
168         start = ALIGN_TO(old_size, align);
169         new_size = start + sz;
170
171         if (new_size < start ||
172             new_size > (size_t) ((uint32_t) -1))
173                 goto poison;
174
175         if (old_size == new_size)
176                 return (uint8_t*) m->header + old_size;
177
178         if (m->free_header) {
179                 np = realloc(m->header, ALIGN8(new_size));
180                 if (!np)
181                         goto poison;
182         } else {
183                 /* Initially, the header is allocated as part of of
184                  * the sd_bus_message itself, let's replace it by
185                  * dynamic data */
186
187                 np = malloc(ALIGN8(new_size));
188                 if (!np)
189                         goto poison;
190
191                 memcpy(np, m->header, sizeof(struct bus_header));
192         }
193
194         /* Zero out padding */
195         if (start > old_size)
196                 memzero((uint8_t*) np + old_size, start - old_size);
197
198         op = m->header;
199         m->header = np;
200         m->fields_size = new_size - sizeof(struct bus_header);
201
202         /* Adjust quick access pointers */
203         m->path = adjust_pointer(m->path, op, old_size, m->header);
204         m->interface = adjust_pointer(m->interface, op, old_size, m->header);
205         m->member = adjust_pointer(m->member, op, old_size, m->header);
206         m->destination = adjust_pointer(m->destination, op, old_size, m->header);
207         m->sender = adjust_pointer(m->sender, op, old_size, m->header);
208         m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
209
210         m->free_header = true;
211
212         if (add_offset) {
213                 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
214                         goto poison;
215
216                 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
217         }
218
219         return (uint8_t*) np + start;
220
221 poison:
222         m->poisoned = true;
223         return NULL;
224 }
225
226 static int message_append_field_string(
227                 sd_bus_message *m,
228                 uint64_t h,
229                 char type,
230                 const char *s,
231                 const char **ret) {
232
233         size_t l;
234         uint8_t *p;
235
236         assert(m);
237
238         /* dbus1 only allows 8bit header field ids */
239         if (h > 0xFF)
240                 return -EINVAL;
241
242         /* dbus1 doesn't allow strings over 32bit, let's enforce this
243          * globally, to not risk convertability */
244         l = strlen(s);
245         if (l > (size_t) (uint32_t) -1)
246                 return -EINVAL;
247
248         /* Signature "(yv)" where the variant contains "s" */
249
250         if (BUS_MESSAGE_IS_GVARIANT(m)) {
251
252                 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
253                 p = message_extend_fields(m, 8, 8 + l + 1 + 1 + 1, true);
254                 if (!p)
255                         return -ENOMEM;
256
257                 *((uint64_t*) p) = h;
258                 memcpy(p+8, s, l);
259                 p[8+l] = 0;
260                 p[8+l+1] = 0;
261                 p[8+l+2] = type;
262
263                 if (ret)
264                         *ret = (char*) p + 8;
265
266         } else {
267                 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
268                 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
269                 if (!p)
270                         return -ENOMEM;
271
272                 p[0] = (uint8_t) h;
273                 p[1] = 1;
274                 p[2] = type;
275                 p[3] = 0;
276
277                 ((uint32_t*) p)[1] = l;
278                 memcpy(p + 8, s, l + 1);
279
280                 if (ret)
281                         *ret = (char*) p + 8;
282         }
283
284         return 0;
285 }
286
287 static int message_append_field_signature(
288                 sd_bus_message *m,
289                 uint64_t h,
290                 const char *s,
291                 const char **ret) {
292
293         size_t l;
294         uint8_t *p;
295
296         assert(m);
297
298         /* dbus1 only allows 8bit header field ids */
299         if (h > 0xFF)
300                 return -EINVAL;
301
302         /* dbus1 doesn't allow signatures over 8bit, let's enforce
303          * this globally, to not risk convertability */
304         l = strlen(s);
305         if (l > 255)
306                 return -EINVAL;
307
308         /* Signature "(yv)" where the variant contains "g" */
309
310         if (BUS_MESSAGE_IS_GVARIANT(m))
311                 /* For gvariant the serialization is the same as for normal strings */
312                 return message_append_field_string(m, h, 'g', s, ret);
313         else {
314                 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
315                 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
316                 if (!p)
317                         return -ENOMEM;
318
319                 p[0] = (uint8_t) h;
320                 p[1] = 1;
321                 p[2] = SD_BUS_TYPE_SIGNATURE;
322                 p[3] = 0;
323                 p[4] = l;
324                 memcpy(p + 5, s, l + 1);
325
326                 if (ret)
327                         *ret = (const char*) p + 5;
328         }
329
330         return 0;
331 }
332
333 static int message_append_field_uint32(sd_bus_message *m, uint64_t h, uint32_t x) {
334         uint8_t *p;
335
336         assert(m);
337
338         /* dbus1 only allows 8bit header field ids */
339         if (h > 0xFF)
340                 return -EINVAL;
341
342         if (BUS_MESSAGE_IS_GVARIANT(m)) {
343                 /* (field id 64bit + ((value + NUL + signature string 'u') */
344
345                 p = message_extend_fields(m, 8, 8 + 4 + 1 + 1, true);
346                 if (!p)
347                         return -ENOMEM;
348
349                 *((uint64_t*) p) = h;
350                 *((uint32_t*) (p + 8)) = x;
351                 p[12] = 0;
352                 p[13] = 'u';
353         } else {
354                 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
355                 p = message_extend_fields(m, 8, 4 + 4, false);
356                 if (!p)
357                         return -ENOMEM;
358
359                 p[0] = (uint8_t) h;
360                 p[1] = 1;
361                 p[2] = 'u';
362                 p[3] = 0;
363
364                 ((uint32_t*) p)[1] = x;
365         }
366
367         return 0;
368 }
369
370 static int message_append_field_uint64(sd_bus_message *m, uint64_t h, uint64_t x) {
371         uint8_t *p;
372
373         assert(m);
374
375         /* dbus1 only allows 8bit header field ids */
376         if (h > 0xFF)
377                 return -EINVAL;
378
379         if (BUS_MESSAGE_IS_GVARIANT(m)) {
380                 /* (field id 64bit + ((value + NUL + signature string 't') */
381
382                 p = message_extend_fields(m, 8, 8 + 8 + 1 + 1, true);
383                 if (!p)
384                         return -ENOMEM;
385
386                 *((uint64_t*) p) = h;
387                 *((uint64_t*) (p + 8)) = x;
388                 p[16] = 0;
389                 p[17] = 't';
390         } else {
391                 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
392                 p = message_extend_fields(m, 8, 4 + 4 + 8, false);
393                 if (!p)
394                         return -ENOMEM;
395
396                 p[0] = (uint8_t) h;
397                 p[1] = 1;
398                 p[2] = 't';
399                 p[3] = 0;
400                 p[4] = 0;
401                 p[5] = 0;
402                 p[6] = 0;
403                 p[7] = 0;
404
405                 ((uint64_t*) p)[1] = x;
406         }
407
408         return 0;
409 }
410
411 static int message_append_reply_cookie(sd_bus_message *m, uint64_t cookie) {
412         assert(m);
413
414         if (BUS_MESSAGE_IS_GVARIANT(m))
415                 return message_append_field_uint64(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, cookie);
416         else {
417                 /* 64bit cookies are not supported on dbus1 */
418                 if (cookie > 0xffffffffUL)
419                         return -EOPNOTSUPP;
420
421                 return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie);
422         }
423 }
424
425 int bus_message_from_header(
426                 sd_bus *bus,
427                 void *header,
428                 size_t header_accessible,
429                 void *footer,
430                 size_t footer_accessible,
431                 size_t message_size,
432                 int *fds,
433                 unsigned n_fds,
434                 const char *label,
435                 size_t extra,
436                 sd_bus_message **ret) {
437
438         _cleanup_free_ sd_bus_message *m = NULL;
439         struct bus_header *h;
440         size_t a, label_sz;
441
442         assert(bus);
443         assert(header || header_accessible <= 0);
444         assert(footer || footer_accessible <= 0);
445         assert(fds || n_fds <= 0);
446         assert(ret);
447
448         if (header_accessible < sizeof(struct bus_header))
449                 return -EBADMSG;
450
451         if (header_accessible > message_size)
452                 return -EBADMSG;
453         if (footer_accessible > message_size)
454                 return -EBADMSG;
455
456         h = header;
457         if (!IN_SET(h->version, 1, 2))
458                 return -EBADMSG;
459
460         if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
461                 return -EBADMSG;
462
463         if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN))
464                 return -EBADMSG;
465
466         /* Note that we are happy with unknown flags in the flags header! */
467
468         a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
469
470         if (label) {
471                 label_sz = strlen(label);
472                 a += label_sz + 1;
473         }
474
475         m = malloc0(a);
476         if (!m)
477                 return -ENOMEM;
478
479         m->n_ref = 1;
480         m->sealed = true;
481         m->header = header;
482         m->header_accessible = header_accessible;
483         m->footer = footer;
484         m->footer_accessible = footer_accessible;
485
486         if (BUS_MESSAGE_IS_GVARIANT(m)) {
487                 size_t ws;
488
489                 if (h->dbus2.cookie == 0)
490                         return -EBADMSG;
491
492                 /* dbus2 derives the sizes from the message size and
493                 the offset table at the end, since it is formatted as
494                 gvariant "yyyyuta{tv}v". Since the message itself is a
495                 structure with precisely to variable sized entries,
496                 there's only one offset in the table, which marks the
497                 end of the fields array. */
498
499                 ws = bus_gvariant_determine_word_size(message_size, 0);
500                 if (footer_accessible < ws)
501                         return -EBADMSG;
502
503                 m->fields_size = bus_gvariant_read_word_le((uint8_t*) footer + footer_accessible - ws, ws);
504                 if (ALIGN8(m->fields_size) > message_size - ws)
505                         return -EBADMSG;
506                 if (m->fields_size < sizeof(struct bus_header))
507                         return -EBADMSG;
508
509                 m->fields_size -= sizeof(struct bus_header);
510                 m->body_size = message_size - (sizeof(struct bus_header) + ALIGN8(m->fields_size));
511         } else {
512                 if (h->dbus1.serial == 0)
513                         return -EBADMSG;
514
515                 /* dbus1 has the sizes in the header */
516                 m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size);
517                 m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size);
518
519                 if (sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size != message_size)
520                         return -EBADMSG;
521         }
522
523         m->fds = fds;
524         m->n_fds = n_fds;
525
526         if (label) {
527                 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
528                 memcpy(m->creds.label, label, label_sz + 1);
529
530                 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
531         }
532
533         m->bus = sd_bus_ref(bus);
534         *ret = m;
535         m = NULL;
536
537         return 0;
538 }
539
540 int bus_message_from_malloc(
541                 sd_bus *bus,
542                 void *buffer,
543                 size_t length,
544                 int *fds,
545                 unsigned n_fds,
546                 const char *label,
547                 sd_bus_message **ret) {
548
549         sd_bus_message *m;
550         size_t sz;
551         int r;
552
553         r = bus_message_from_header(
554                         bus,
555                         buffer, length, /* in this case the initial bytes and the final bytes are the same */
556                         buffer, length,
557                         length,
558                         fds, n_fds,
559                         label,
560                         0, &m);
561         if (r < 0)
562                 return r;
563
564         sz = length - sizeof(struct bus_header) - ALIGN8(m->fields_size);
565         if (sz > 0) {
566                 m->n_body_parts = 1;
567                 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(m->fields_size);
568                 m->body.size = sz;
569                 m->body.sealed = true;
570                 m->body.memfd = -1;
571         }
572
573         m->n_iovec = 1;
574         m->iovec = m->iovec_fixed;
575         m->iovec[0].iov_base = buffer;
576         m->iovec[0].iov_len = length;
577
578         r = bus_message_parse_fields(m);
579         if (r < 0)
580                 goto fail;
581
582         /* We take possession of the memory and fds now */
583         m->free_header = true;
584         m->free_fds = true;
585
586         *ret = m;
587         return 0;
588
589 fail:
590         message_free(m);
591         return r;
592 }
593
594 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
595         sd_bus_message *m;
596
597         assert(bus);
598
599         m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
600         if (!m)
601                 return NULL;
602
603         m->n_ref = 1;
604         m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
605         m->header->endian = BUS_NATIVE_ENDIAN;
606         m->header->type = type;
607         m->header->version = bus->message_version;
608         m->allow_fds = bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
609         m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
610         m->bus = sd_bus_ref(bus);
611
612         if (bus->allow_interactive_authorization)
613                 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
614
615         return m;
616 }
617
618 _public_ int sd_bus_message_new_signal(
619                 sd_bus *bus,
620                 sd_bus_message **m,
621                 const char *path,
622                 const char *interface,
623                 const char *member) {
624
625         sd_bus_message *t;
626         int r;
627
628         assert_return(bus, -ENOTCONN);
629         assert_return(bus->state != BUS_UNSET, -ENOTCONN);
630         assert_return(object_path_is_valid(path), -EINVAL);
631         assert_return(interface_name_is_valid(interface), -EINVAL);
632         assert_return(member_name_is_valid(member), -EINVAL);
633         assert_return(m, -EINVAL);
634
635         t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
636         if (!t)
637                 return -ENOMEM;
638
639         t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
640
641         r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
642         if (r < 0)
643                 goto fail;
644         r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
645         if (r < 0)
646                 goto fail;
647         r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
648         if (r < 0)
649                 goto fail;
650
651         *m = t;
652         return 0;
653
654 fail:
655         sd_bus_message_unref(t);
656         return r;
657 }
658
659 _public_ int sd_bus_message_new_method_call(
660                 sd_bus *bus,
661                 sd_bus_message **m,
662                 const char *destination,
663                 const char *path,
664                 const char *interface,
665                 const char *member) {
666
667         sd_bus_message *t;
668         int r;
669
670         assert_return(bus, -ENOTCONN);
671         assert_return(bus->state != BUS_UNSET, -ENOTCONN);
672         assert_return(!destination || service_name_is_valid(destination), -EINVAL);
673         assert_return(object_path_is_valid(path), -EINVAL);
674         assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
675         assert_return(member_name_is_valid(member), -EINVAL);
676         assert_return(m, -EINVAL);
677
678         t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
679         if (!t)
680                 return -ENOMEM;
681
682         r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
683         if (r < 0)
684                 goto fail;
685         r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
686         if (r < 0)
687                 goto fail;
688
689         if (interface) {
690                 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
691                 if (r < 0)
692                         goto fail;
693         }
694
695         if (destination) {
696                 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
697                 if (r < 0)
698                         goto fail;
699         }
700
701         *m = t;
702         return 0;
703
704 fail:
705         message_free(t);
706         return r;
707 }
708
709 static int message_new_reply(
710                 sd_bus_message *call,
711                 uint8_t type,
712                 sd_bus_message **m) {
713
714         sd_bus_message *t;
715         int r;
716
717         assert_return(call, -EINVAL);
718         assert_return(call->sealed, -EPERM);
719         assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
720         assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
721         assert_return(m, -EINVAL);
722
723         t = message_new(call->bus, type);
724         if (!t)
725                 return -ENOMEM;
726
727         t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
728         t->reply_cookie = BUS_MESSAGE_COOKIE(call);
729         if (t->reply_cookie == 0)
730                 return -EOPNOTSUPP;
731
732         r = message_append_reply_cookie(t, t->reply_cookie);
733         if (r < 0)
734                 goto fail;
735
736         if (call->sender) {
737                 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
738                 if (r < 0)
739                         goto fail;
740         }
741
742         t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
743         t->enforced_reply_signature = call->enforced_reply_signature;
744
745         *m = t;
746         return 0;
747
748 fail:
749         message_free(t);
750         return r;
751 }
752
753 _public_ int sd_bus_message_new_method_return(
754                 sd_bus_message *call,
755                 sd_bus_message **m) {
756
757         return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
758 }
759
760 _public_ int sd_bus_message_new_method_error(
761                 sd_bus_message *call,
762                 sd_bus_message **m,
763                 const sd_bus_error *e) {
764
765         sd_bus_message *t;
766         int r;
767
768         assert_return(sd_bus_error_is_set(e), -EINVAL);
769         assert_return(m, -EINVAL);
770
771         r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
772         if (r < 0)
773                 return r;
774
775         r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
776         if (r < 0)
777                 goto fail;
778
779         if (e->message) {
780                 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
781                 if (r < 0)
782                         goto fail;
783         }
784
785         t->error._need_free = -1;
786
787         *m = t;
788         return 0;
789
790 fail:
791         message_free(t);
792         return r;
793 }
794
795 _public_ int sd_bus_message_new_method_errorf(
796                 sd_bus_message *call,
797                 sd_bus_message **m,
798                 const char *name,
799                 const char *format,
800                 ...) {
801
802         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
803         va_list ap;
804
805         assert_return(name, -EINVAL);
806         assert_return(m, -EINVAL);
807
808         va_start(ap, format);
809         bus_error_setfv(&error, name, format, ap);
810         va_end(ap);
811
812         return sd_bus_message_new_method_error(call, m, &error);
813 }
814
815 _public_ int sd_bus_message_new_method_errno(
816                 sd_bus_message *call,
817                 sd_bus_message **m,
818                 int error,
819                 const sd_bus_error *p) {
820
821         _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
822
823         if (sd_bus_error_is_set(p))
824                 return sd_bus_message_new_method_error(call, m, p);
825
826         sd_bus_error_set_errno(&berror, error);
827
828         return sd_bus_message_new_method_error(call, m, &berror);
829 }
830
831 /// UNNEEDED by elogind
832 #if 0
833 _public_ int sd_bus_message_new_method_errnof(
834                 sd_bus_message *call,
835                 sd_bus_message **m,
836                 int error,
837                 const char *format,
838                 ...) {
839
840         _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
841         va_list ap;
842
843         va_start(ap, format);
844         sd_bus_error_set_errnofv(&berror, error, format, ap);
845         va_end(ap);
846
847         return sd_bus_message_new_method_error(call, m, &berror);
848 }
849 #endif // 0
850
851 void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
852         assert(bus);
853         assert(m);
854
855         m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
856         m->creds.well_known_names_local = true;
857         m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
858 }
859
860 void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
861         assert(bus);
862         assert(m);
863
864         m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
865         m->creds.well_known_names_driver = true;
866         m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
867 }
868
869 int bus_message_new_synthetic_error(
870                 sd_bus *bus,
871                 uint64_t cookie,
872                 const sd_bus_error *e,
873                 sd_bus_message **m) {
874
875         sd_bus_message *t;
876         int r;
877
878         assert(bus);
879         assert(sd_bus_error_is_set(e));
880         assert(m);
881
882         t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
883         if (!t)
884                 return -ENOMEM;
885
886         t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
887         t->reply_cookie = cookie;
888
889         r = message_append_reply_cookie(t, t->reply_cookie);
890         if (r < 0)
891                 goto fail;
892
893         if (bus && bus->unique_name) {
894                 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
895                 if (r < 0)
896                         goto fail;
897         }
898
899         r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
900         if (r < 0)
901                 goto fail;
902
903         if (e->message) {
904                 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
905                 if (r < 0)
906                         goto fail;
907         }
908
909         t->error._need_free = -1;
910
911         bus_message_set_sender_driver(bus, t);
912
913         *m = t;
914         return 0;
915
916 fail:
917         message_free(t);
918         return r;
919 }
920
921 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
922         assert_return(m, NULL);
923
924         assert(m->n_ref > 0);
925         m->n_ref++;
926
927         return m;
928 }
929
930 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
931
932         if (!m)
933                 return NULL;
934
935         assert(m->n_ref > 0);
936         m->n_ref--;
937
938         if (m->n_ref > 0)
939                 return NULL;
940
941         message_free(m);
942         return NULL;
943 }
944
945 /// UNNEEDED by elogind
946 #if 0
947 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
948         assert_return(m, -EINVAL);
949         assert_return(type, -EINVAL);
950
951         *type = m->header->type;
952         return 0;
953 }
954
955 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
956         uint64_t c;
957
958         assert_return(m, -EINVAL);
959         assert_return(cookie, -EINVAL);
960
961         c = BUS_MESSAGE_COOKIE(m);
962         if (c == 0)
963                 return -ENODATA;
964
965         *cookie = BUS_MESSAGE_COOKIE(m);
966         return 0;
967 }
968
969 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
970         assert_return(m, -EINVAL);
971         assert_return(cookie, -EINVAL);
972
973         if (m->reply_cookie == 0)
974                 return -ENODATA;
975
976         *cookie = m->reply_cookie;
977         return 0;
978 }
979
980 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
981         assert_return(m, -EINVAL);
982
983         return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
984                 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
985 }
986
987 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
988         assert_return(m, -EINVAL);
989
990         return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
991 }
992 #endif // 0
993
994 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
995         assert_return(m, -EINVAL);
996
997         return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
998                 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
999 }
1000
1001 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
1002         assert_return(m, NULL);
1003
1004         return m->path;
1005 }
1006
1007 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
1008         assert_return(m, NULL);
1009
1010         return m->interface;
1011 }
1012
1013 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
1014         assert_return(m, NULL);
1015
1016         return m->member;
1017 }
1018
1019 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
1020         assert_return(m, NULL);
1021
1022         return m->destination;
1023 }
1024
1025 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
1026         assert_return(m, NULL);
1027
1028         return m->sender;
1029 }
1030
1031 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
1032         assert_return(m, NULL);
1033
1034         if (!sd_bus_error_is_set(&m->error))
1035                 return NULL;
1036
1037         return &m->error;
1038 }
1039
1040 /// UNNEEDED by elogind
1041 #if 0
1042 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
1043         assert_return(m, -EINVAL);
1044         assert_return(usec, -EINVAL);
1045
1046         if (m->monotonic <= 0)
1047                 return -ENODATA;
1048
1049         *usec = m->monotonic;
1050         return 0;
1051 }
1052
1053 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
1054         assert_return(m, -EINVAL);
1055         assert_return(usec, -EINVAL);
1056
1057         if (m->realtime <= 0)
1058                 return -ENODATA;
1059
1060         *usec = m->realtime;
1061         return 0;
1062 }
1063
1064 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
1065         assert_return(m, -EINVAL);
1066         assert_return(seqnum, -EINVAL);
1067
1068         if (m->seqnum <= 0)
1069                 return -ENODATA;
1070
1071         *seqnum = m->seqnum;
1072         return 0;
1073 }
1074 #endif // 0
1075
1076 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
1077         assert_return(m, NULL);
1078
1079         if (m->creds.mask == 0)
1080                 return NULL;
1081
1082         return &m->creds;
1083 }
1084
1085 /// UNNEEDED by elogind
1086 #if 0
1087 _public_ int sd_bus_message_is_signal(
1088                 sd_bus_message *m,
1089                 const char *interface,
1090                 const char *member) {
1091
1092         assert_return(m, -EINVAL);
1093
1094         if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
1095                 return 0;
1096
1097         if (interface && (!m->interface || !streq(m->interface, interface)))
1098                 return 0;
1099
1100         if (member &&  (!m->member || !streq(m->member, member)))
1101                 return 0;
1102
1103         return 1;
1104 }
1105 #endif // 0
1106
1107 _public_ int sd_bus_message_is_method_call(
1108                 sd_bus_message *m,
1109                 const char *interface,
1110                 const char *member) {
1111
1112         assert_return(m, -EINVAL);
1113
1114         if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1115                 return 0;
1116
1117         if (interface && (!m->interface || !streq(m->interface, interface)))
1118                 return 0;
1119
1120         if (member &&  (!m->member || !streq(m->member, member)))
1121                 return 0;
1122
1123         return 1;
1124 }
1125
1126 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1127         assert_return(m, -EINVAL);
1128
1129         if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1130                 return 0;
1131
1132         if (name && (!m->error.name || !streq(m->error.name, name)))
1133                 return 0;
1134
1135         return 1;
1136 }
1137
1138 /// UNNEEDED by elogind
1139 #if 0
1140 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1141         assert_return(m, -EINVAL);
1142         assert_return(!m->sealed, -EPERM);
1143         assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1144
1145         if (b)
1146                 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
1147         else
1148                 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
1149
1150         return 0;
1151 }
1152 #endif // 0
1153
1154 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1155         assert_return(m, -EINVAL);
1156         assert_return(!m->sealed, -EPERM);
1157
1158         if (b)
1159                 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
1160         else
1161                 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
1162
1163         return 0;
1164 }
1165
1166 /// UNNEEDED by elogind
1167 #if 0
1168 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1169         assert_return(m, -EINVAL);
1170         assert_return(!m->sealed, -EPERM);
1171
1172         if (b)
1173                 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1174         else
1175                 m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1176
1177         return 0;
1178 }
1179 #endif // 0
1180
1181 static struct bus_container *message_get_container(sd_bus_message *m) {
1182         assert(m);
1183
1184         if (m->n_containers == 0)
1185                 return &m->root_container;
1186
1187         assert(m->containers);
1188         return m->containers + m->n_containers - 1;
1189 }
1190
1191 struct bus_body_part *message_append_part(sd_bus_message *m) {
1192         struct bus_body_part *part;
1193
1194         assert(m);
1195
1196         if (m->poisoned)
1197                 return NULL;
1198
1199         if (m->n_body_parts <= 0) {
1200                 part = &m->body;
1201                 zero(*part);
1202         } else {
1203                 assert(m->body_end);
1204
1205                 part = new0(struct bus_body_part, 1);
1206                 if (!part) {
1207                         m->poisoned = true;
1208                         return NULL;
1209                 }
1210
1211                 m->body_end->next = part;
1212         }
1213
1214         part->memfd = -1;
1215         m->body_end = part;
1216         m->n_body_parts ++;
1217
1218         return part;
1219 }
1220
1221 static void part_zero(struct bus_body_part *part, size_t sz) {
1222         assert(part);
1223         assert(sz > 0);
1224         assert(sz < 8);
1225
1226         /* All other fields can be left in their defaults */
1227         assert(!part->data);
1228         assert(part->memfd < 0);
1229
1230         part->size = sz;
1231         part->is_zero = true;
1232         part->sealed = true;
1233 }
1234
1235 static int part_make_space(
1236                 struct sd_bus_message *m,
1237                 struct bus_body_part *part,
1238                 size_t sz,
1239                 void **q) {
1240
1241         void *n;
1242         int r;
1243
1244         assert(m);
1245         assert(part);
1246         assert(!part->sealed);
1247
1248         if (m->poisoned)
1249                 return -ENOMEM;
1250
1251         if (!part->data && part->memfd < 0) {
1252                 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1253                 part->mmap_begin = part->data;
1254         }
1255
1256         if (part->memfd >= 0) {
1257
1258                 if (part->allocated == 0 || sz > part->allocated) {
1259                         uint64_t new_allocated;
1260
1261                         new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1262                         r = memfd_set_size(part->memfd, new_allocated);
1263                         if (r < 0) {
1264                                 m->poisoned = true;
1265                                 return r;
1266                         }
1267
1268                         part->allocated = new_allocated;
1269                 }
1270
1271                 if (!part->data || sz > part->mapped) {
1272                         size_t psz;
1273
1274                         psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1275                         if (part->mapped <= 0)
1276                                 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1277                         else
1278                                 n = mremap(part->mmap_begin, part->mapped, psz, MREMAP_MAYMOVE);
1279
1280                         if (n == MAP_FAILED) {
1281                                 m->poisoned = true;
1282                                 return -errno;
1283                         }
1284
1285                         part->mmap_begin = part->data = n;
1286                         part->mapped = psz;
1287                         part->memfd_offset = 0;
1288                 }
1289
1290                 part->munmap_this = true;
1291         } else {
1292                 if (part->allocated == 0 || sz > part->allocated) {
1293                         size_t new_allocated;
1294
1295                         new_allocated = sz > 0 ? 2 * sz : 64;
1296                         n = realloc(part->data, new_allocated);
1297                         if (!n) {
1298                                 m->poisoned = true;
1299                                 return -ENOMEM;
1300                         }
1301
1302                         part->data = n;
1303                         part->allocated = new_allocated;
1304                         part->free_this = true;
1305                 }
1306         }
1307
1308         if (q)
1309                 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1310
1311         part->size = sz;
1312         return 0;
1313 }
1314
1315 static int message_add_offset(sd_bus_message *m, size_t offset) {
1316         struct bus_container *c;
1317
1318         assert(m);
1319         assert(BUS_MESSAGE_IS_GVARIANT(m));
1320
1321         /* Add offset to current container, unless this is the first
1322          * item in it, which will have the 0 offset, which we can
1323          * ignore. */
1324         c = message_get_container(m);
1325
1326         if (!c->need_offsets)
1327                 return 0;
1328
1329         if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1330                 return -ENOMEM;
1331
1332         c->offsets[c->n_offsets++] = offset;
1333         return 0;
1334 }
1335
1336 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1337         struct bus_container *c;
1338
1339         assert(m);
1340
1341         if (expand <= 0)
1342                 return;
1343
1344         /* Update counters */
1345         for (c = m->containers; c < m->containers + m->n_containers; c++) {
1346
1347                 if (c->array_size)
1348                         *c->array_size += expand;
1349         }
1350 }
1351
1352 static void *message_extend_body(
1353                 sd_bus_message *m,
1354                 size_t align,
1355                 size_t sz,
1356                 bool add_offset,
1357                 bool force_inline) {
1358
1359         size_t start_body, end_body, padding, added;
1360         void *p;
1361         int r;
1362
1363         assert(m);
1364         assert(align > 0);
1365         assert(!m->sealed);
1366
1367         if (m->poisoned)
1368                 return NULL;
1369
1370         start_body = ALIGN_TO((size_t) m->body_size, align);
1371         end_body = start_body + sz;
1372
1373         padding = start_body - m->body_size;
1374         added = padding + sz;
1375
1376         /* Check for 32bit overflows */
1377         if (end_body > (size_t) ((uint32_t) -1) ||
1378             end_body < start_body) {
1379                 m->poisoned = true;
1380                 return NULL;
1381         }
1382
1383         if (added > 0) {
1384                 struct bus_body_part *part = NULL;
1385                 bool add_new_part;
1386
1387                 add_new_part =
1388                         m->n_body_parts <= 0 ||
1389                         m->body_end->sealed ||
1390                         (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1391                         (force_inline && m->body_end->size > MEMFD_MIN_SIZE); /* if this must be an inlined extension, let's create a new part if the previous part is large enough to be inlined */
1392
1393                 if (add_new_part) {
1394                         if (padding > 0) {
1395                                 part = message_append_part(m);
1396                                 if (!part)
1397                                         return NULL;
1398
1399                                 part_zero(part, padding);
1400                         }
1401
1402                         part = message_append_part(m);
1403                         if (!part)
1404                                 return NULL;
1405
1406                         r = part_make_space(m, part, sz, &p);
1407                         if (r < 0)
1408                                 return NULL;
1409                 } else {
1410                         struct bus_container *c;
1411                         void *op;
1412                         size_t os, start_part, end_part;
1413
1414                         part = m->body_end;
1415                         op = part->data;
1416                         os = part->size;
1417
1418                         start_part = ALIGN_TO(part->size, align);
1419                         end_part = start_part + sz;
1420
1421                         r = part_make_space(m, part, end_part, &p);
1422                         if (r < 0)
1423                                 return NULL;
1424
1425                         if (padding > 0) {
1426                                 memzero(p, padding);
1427                                 p = (uint8_t*) p + padding;
1428                         }
1429
1430                         /* Readjust pointers */
1431                         for (c = m->containers; c < m->containers + m->n_containers; c++)
1432                                 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1433
1434                         m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1435                 }
1436         } else
1437                 /* Return something that is not NULL and is aligned */
1438                 p = (uint8_t *) NULL + align;
1439
1440         m->body_size = end_body;
1441         message_extend_containers(m, added);
1442
1443         if (add_offset) {
1444                 r = message_add_offset(m, end_body);
1445                 if (r < 0) {
1446                         m->poisoned = true;
1447                         return NULL;
1448                 }
1449         }
1450
1451         return p;
1452 }
1453
1454 static int message_push_fd(sd_bus_message *m, int fd) {
1455         int *f, copy;
1456
1457         assert(m);
1458
1459         if (fd < 0)
1460                 return -EINVAL;
1461
1462         if (!m->allow_fds)
1463                 return -EOPNOTSUPP;
1464
1465         copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1466         if (copy < 0)
1467                 return -errno;
1468
1469         f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1470         if (!f) {
1471                 m->poisoned = true;
1472                 safe_close(copy);
1473                 return -ENOMEM;
1474         }
1475
1476         m->fds = f;
1477         m->fds[m->n_fds] = copy;
1478         m->free_fds = true;
1479
1480         return copy;
1481 }
1482
1483 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1484         _cleanup_close_ int fd = -1;
1485         struct bus_container *c;
1486         ssize_t align, sz;
1487         void *a;
1488
1489         assert_return(m, -EINVAL);
1490         assert_return(!m->sealed, -EPERM);
1491         assert_return(bus_type_is_basic(type), -EINVAL);
1492         assert_return(!m->poisoned, -ESTALE);
1493
1494         c = message_get_container(m);
1495
1496         if (c->signature && c->signature[c->index]) {
1497                 /* Container signature is already set */
1498
1499                 if (c->signature[c->index] != type)
1500                         return -ENXIO;
1501         } else {
1502                 char *e;
1503
1504                 /* Maybe we can append to the signature? But only if this is the top-level container */
1505                 if (c->enclosing != 0)
1506                         return -ENXIO;
1507
1508                 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1509                 if (!e) {
1510                         m->poisoned = true;
1511                         return -ENOMEM;
1512                 }
1513         }
1514
1515         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1516                 uint8_t u8;
1517                 uint32_t u32;
1518
1519                 switch (type) {
1520
1521                 case SD_BUS_TYPE_SIGNATURE:
1522                 case SD_BUS_TYPE_STRING:
1523                         p = strempty(p);
1524
1525                         /* Fall through... */
1526                 case SD_BUS_TYPE_OBJECT_PATH:
1527                         if (!p)
1528                                 return -EINVAL;
1529
1530                         align = 1;
1531                         sz = strlen(p) + 1;
1532                         break;
1533
1534                 case SD_BUS_TYPE_BOOLEAN:
1535
1536                         u8 = p && *(int*) p;
1537                         p = &u8;
1538
1539                         align = sz = 1;
1540                         break;
1541
1542                 case SD_BUS_TYPE_UNIX_FD:
1543
1544                         if (!p)
1545                                 return -EINVAL;
1546
1547                         fd = message_push_fd(m, *(int*) p);
1548                         if (fd < 0)
1549                                 return fd;
1550
1551                         u32 = m->n_fds;
1552                         p = &u32;
1553
1554                         align = sz = 4;
1555                         break;
1556
1557                 default:
1558                         align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1559                         sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1560                         break;
1561                 }
1562
1563                 assert(align > 0);
1564                 assert(sz > 0);
1565
1566                 a = message_extend_body(m, align, sz, true, false);
1567                 if (!a)
1568                         return -ENOMEM;
1569
1570                 memcpy(a, p, sz);
1571
1572                 if (stored)
1573                         *stored = (const uint8_t*) a;
1574
1575         } else {
1576                 uint32_t u32;
1577
1578                 switch (type) {
1579
1580                 case SD_BUS_TYPE_STRING:
1581                         /* To make things easy we'll serialize a NULL string
1582                          * into the empty string */
1583                         p = strempty(p);
1584
1585                         /* Fall through... */
1586                 case SD_BUS_TYPE_OBJECT_PATH:
1587
1588                         if (!p)
1589                                 return -EINVAL;
1590
1591                         align = 4;
1592                         sz = 4 + strlen(p) + 1;
1593                         break;
1594
1595                 case SD_BUS_TYPE_SIGNATURE:
1596
1597                         p = strempty(p);
1598
1599                         align = 1;
1600                         sz = 1 + strlen(p) + 1;
1601                         break;
1602
1603                 case SD_BUS_TYPE_BOOLEAN:
1604
1605                         u32 = p && *(int*) p;
1606                         p = &u32;
1607
1608                         align = sz = 4;
1609                         break;
1610
1611                 case SD_BUS_TYPE_UNIX_FD:
1612
1613                         if (!p)
1614                                 return -EINVAL;
1615
1616                         fd = message_push_fd(m, *(int*) p);
1617                         if (fd < 0)
1618                                 return fd;
1619
1620                         u32 = m->n_fds;
1621                         p = &u32;
1622
1623                         align = sz = 4;
1624                         break;
1625
1626                 default:
1627                         align = bus_type_get_alignment(type);
1628                         sz = bus_type_get_size(type);
1629                         break;
1630                 }
1631
1632                 assert(align > 0);
1633                 assert(sz > 0);
1634
1635                 a = message_extend_body(m, align, sz, false, false);
1636                 if (!a)
1637                         return -ENOMEM;
1638
1639                 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1640                         *(uint32_t*) a = sz - 5;
1641                         memcpy((uint8_t*) a + 4, p, sz - 4);
1642
1643                         if (stored)
1644                                 *stored = (const uint8_t*) a + 4;
1645
1646                 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1647                         *(uint8_t*) a = sz - 2;
1648                         memcpy((uint8_t*) a + 1, p, sz - 1);
1649
1650                         if (stored)
1651                                 *stored = (const uint8_t*) a + 1;
1652                 } else {
1653                         memcpy(a, p, sz);
1654
1655                         if (stored)
1656                                 *stored = a;
1657                 }
1658         }
1659
1660         if (type == SD_BUS_TYPE_UNIX_FD)
1661                 m->n_fds ++;
1662
1663         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1664                 c->index++;
1665
1666         fd = -1;
1667         return 0;
1668 }
1669
1670 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1671         return message_append_basic(m, type, p, NULL);
1672 }
1673
1674 _public_ int sd_bus_message_append_string_space(
1675                 sd_bus_message *m,
1676                 size_t size,
1677                 char **s) {
1678
1679         struct bus_container *c;
1680         void *a;
1681
1682         assert_return(m, -EINVAL);
1683         assert_return(s, -EINVAL);
1684         assert_return(!m->sealed, -EPERM);
1685         assert_return(!m->poisoned, -ESTALE);
1686
1687         c = message_get_container(m);
1688
1689         if (c->signature && c->signature[c->index]) {
1690                 /* Container signature is already set */
1691
1692                 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1693                         return -ENXIO;
1694         } else {
1695                 char *e;
1696
1697                 /* Maybe we can append to the signature? But only if this is the top-level container */
1698                 if (c->enclosing != 0)
1699                         return -ENXIO;
1700
1701                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1702                 if (!e) {
1703                         m->poisoned = true;
1704                         return -ENOMEM;
1705                 }
1706         }
1707
1708         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1709                 a = message_extend_body(m, 1, size + 1, true, false);
1710                 if (!a)
1711                         return -ENOMEM;
1712
1713                 *s = a;
1714         } else {
1715                 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1716                 if (!a)
1717                         return -ENOMEM;
1718
1719                 *(uint32_t*) a = size;
1720                 *s = (char*) a + 4;
1721         }
1722
1723         (*s)[size] = 0;
1724
1725         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1726                 c->index++;
1727
1728         return 0;
1729 }
1730
1731 /// UNNEEDED by elogind
1732 #if 0
1733 _public_ int sd_bus_message_append_string_iovec(
1734                 sd_bus_message *m,
1735                 const struct iovec *iov,
1736                 unsigned n) {
1737
1738         size_t size;
1739         unsigned i;
1740         char *p;
1741         int r;
1742
1743         assert_return(m, -EINVAL);
1744         assert_return(!m->sealed, -EPERM);
1745         assert_return(iov || n == 0, -EINVAL);
1746         assert_return(!m->poisoned, -ESTALE);
1747
1748         size = IOVEC_TOTAL_SIZE(iov, n);
1749
1750         r = sd_bus_message_append_string_space(m, size, &p);
1751         if (r < 0)
1752                 return r;
1753
1754         for (i = 0; i < n; i++) {
1755
1756                 if (iov[i].iov_base)
1757                         memcpy(p, iov[i].iov_base, iov[i].iov_len);
1758                 else
1759                         memset(p, ' ', iov[i].iov_len);
1760
1761                 p += iov[i].iov_len;
1762         }
1763
1764         return 0;
1765 }
1766 #endif // 0
1767
1768 static int bus_message_open_array(
1769                 sd_bus_message *m,
1770                 struct bus_container *c,
1771                 const char *contents,
1772                 uint32_t **array_size,
1773                 size_t *begin,
1774                 bool *need_offsets) {
1775
1776         unsigned nindex;
1777         int alignment, r;
1778
1779         assert(m);
1780         assert(c);
1781         assert(contents);
1782         assert(array_size);
1783         assert(begin);
1784         assert(need_offsets);
1785
1786         if (!signature_is_single(contents, true))
1787                 return -EINVAL;
1788
1789         if (c->signature && c->signature[c->index]) {
1790
1791                 /* Verify the existing signature */
1792
1793                 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1794                         return -ENXIO;
1795
1796                 if (!startswith(c->signature + c->index + 1, contents))
1797                         return -ENXIO;
1798
1799                 nindex = c->index + 1 + strlen(contents);
1800         } else {
1801                 char *e;
1802
1803                 if (c->enclosing != 0)
1804                         return -ENXIO;
1805
1806                 /* Extend the existing signature */
1807
1808                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1809                 if (!e) {
1810                         m->poisoned = true;
1811                         return -ENOMEM;
1812                 }
1813
1814                 nindex = e - c->signature;
1815         }
1816
1817         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1818                 alignment = bus_gvariant_get_alignment(contents);
1819                 if (alignment < 0)
1820                         return alignment;
1821
1822                 /* Add alignment padding and add to offset list */
1823                 if (!message_extend_body(m, alignment, 0, false, false))
1824                         return -ENOMEM;
1825
1826                 r = bus_gvariant_is_fixed_size(contents);
1827                 if (r < 0)
1828                         return r;
1829
1830                 *begin = m->body_size;
1831                 *need_offsets = r == 0;
1832         } else {
1833                 void *a, *op;
1834                 size_t os;
1835                 struct bus_body_part *o;
1836
1837                 alignment = bus_type_get_alignment(contents[0]);
1838                 if (alignment < 0)
1839                         return alignment;
1840
1841                 a = message_extend_body(m, 4, 4, false, false);
1842                 if (!a)
1843                         return -ENOMEM;
1844
1845                 o = m->body_end;
1846                 op = m->body_end->data;
1847                 os = m->body_end->size;
1848
1849                 /* Add alignment between size and first element */
1850                 if (!message_extend_body(m, alignment, 0, false, false))
1851                         return -ENOMEM;
1852
1853                 /* location of array size might have changed so let's readjust a */
1854                 if (o == m->body_end)
1855                         a = adjust_pointer(a, op, os, m->body_end->data);
1856
1857                 *(uint32_t*) a = 0;
1858                 *array_size = a;
1859         }
1860
1861         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1862                 c->index = nindex;
1863
1864         return 0;
1865 }
1866
1867 static int bus_message_open_variant(
1868                 sd_bus_message *m,
1869                 struct bus_container *c,
1870                 const char *contents) {
1871
1872         assert(m);
1873         assert(c);
1874         assert(contents);
1875
1876         if (!signature_is_single(contents, false))
1877                 return -EINVAL;
1878
1879         if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1880                 return -EINVAL;
1881
1882         if (c->signature && c->signature[c->index]) {
1883
1884                 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1885                         return -ENXIO;
1886
1887         } else {
1888                 char *e;
1889
1890                 if (c->enclosing != 0)
1891                         return -ENXIO;
1892
1893                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1894                 if (!e) {
1895                         m->poisoned = true;
1896                         return -ENOMEM;
1897                 }
1898         }
1899
1900         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1901                 /* Variants are always aligned to 8 */
1902
1903                 if (!message_extend_body(m, 8, 0, false, false))
1904                         return -ENOMEM;
1905
1906         } else {
1907                 size_t l;
1908                 void *a;
1909
1910                 l = strlen(contents);
1911                 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1912                 if (!a)
1913                         return -ENOMEM;
1914
1915                 *(uint8_t*) a = l;
1916                 memcpy((uint8_t*) a + 1, contents, l + 1);
1917         }
1918
1919         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1920                 c->index++;
1921
1922         return 0;
1923 }
1924
1925 static int bus_message_open_struct(
1926                 sd_bus_message *m,
1927                 struct bus_container *c,
1928                 const char *contents,
1929                 size_t *begin,
1930                 bool *need_offsets) {
1931
1932         size_t nindex;
1933         int r;
1934
1935         assert(m);
1936         assert(c);
1937         assert(contents);
1938         assert(begin);
1939         assert(need_offsets);
1940
1941         if (!signature_is_valid(contents, false))
1942                 return -EINVAL;
1943
1944         if (c->signature && c->signature[c->index]) {
1945                 size_t l;
1946
1947                 l = strlen(contents);
1948
1949                 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1950                     !startswith(c->signature + c->index + 1, contents) ||
1951                     c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1952                         return -ENXIO;
1953
1954                 nindex = c->index + 1 + l + 1;
1955         } else {
1956                 char *e;
1957
1958                 if (c->enclosing != 0)
1959                         return -ENXIO;
1960
1961                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1962                 if (!e) {
1963                         m->poisoned = true;
1964                         return -ENOMEM;
1965                 }
1966
1967                 nindex = e - c->signature;
1968         }
1969
1970         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1971                 int alignment;
1972
1973                 alignment = bus_gvariant_get_alignment(contents);
1974                 if (alignment < 0)
1975                         return alignment;
1976
1977                 if (!message_extend_body(m, alignment, 0, false, false))
1978                         return -ENOMEM;
1979
1980                 r = bus_gvariant_is_fixed_size(contents);
1981                 if (r < 0)
1982                         return r;
1983
1984                 *begin = m->body_size;
1985                 *need_offsets = r == 0;
1986         } else {
1987                 /* Align contents to 8 byte boundary */
1988                 if (!message_extend_body(m, 8, 0, false, false))
1989                         return -ENOMEM;
1990         }
1991
1992         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1993                 c->index = nindex;
1994
1995         return 0;
1996 }
1997
1998 static int bus_message_open_dict_entry(
1999                 sd_bus_message *m,
2000                 struct bus_container *c,
2001                 const char *contents,
2002                 size_t *begin,
2003                 bool *need_offsets) {
2004
2005         int r;
2006
2007         assert(m);
2008         assert(c);
2009         assert(contents);
2010         assert(begin);
2011         assert(need_offsets);
2012
2013         if (!signature_is_pair(contents))
2014                 return -EINVAL;
2015
2016         if (c->enclosing != SD_BUS_TYPE_ARRAY)
2017                 return -ENXIO;
2018
2019         if (c->signature && c->signature[c->index]) {
2020                 size_t l;
2021
2022                 l = strlen(contents);
2023
2024                 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
2025                     !startswith(c->signature + c->index + 1, contents) ||
2026                     c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
2027                         return -ENXIO;
2028         } else
2029                 return -ENXIO;
2030
2031         if (BUS_MESSAGE_IS_GVARIANT(m)) {
2032                 int alignment;
2033
2034                 alignment = bus_gvariant_get_alignment(contents);
2035                 if (alignment < 0)
2036                         return alignment;
2037
2038                 if (!message_extend_body(m, alignment, 0, false, false))
2039                         return -ENOMEM;
2040
2041                 r = bus_gvariant_is_fixed_size(contents);
2042                 if (r < 0)
2043                         return r;
2044
2045                 *begin = m->body_size;
2046                 *need_offsets = r == 0;
2047         } else {
2048                 /* Align contents to 8 byte boundary */
2049                 if (!message_extend_body(m, 8, 0, false, false))
2050                         return -ENOMEM;
2051         }
2052
2053         return 0;
2054 }
2055
2056 _public_ int sd_bus_message_open_container(
2057                 sd_bus_message *m,
2058                 char type,
2059                 const char *contents) {
2060
2061         struct bus_container *c, *w;
2062         uint32_t *array_size = NULL;
2063         char *signature;
2064         size_t before, begin = 0;
2065         bool need_offsets = false;
2066         int r;
2067
2068         assert_return(m, -EINVAL);
2069         assert_return(!m->sealed, -EPERM);
2070         assert_return(contents, -EINVAL);
2071         assert_return(!m->poisoned, -ESTALE);
2072
2073         /* Make sure we have space for one more container */
2074         if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
2075                 m->poisoned = true;
2076                 return -ENOMEM;
2077         }
2078
2079         c = message_get_container(m);
2080
2081         signature = strdup(contents);
2082         if (!signature) {
2083                 m->poisoned = true;
2084                 return -ENOMEM;
2085         }
2086
2087         /* Save old index in the parent container, in case we have to
2088          * abort this container */
2089         c->saved_index = c->index;
2090         before = m->body_size;
2091
2092         if (type == SD_BUS_TYPE_ARRAY)
2093                 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
2094         else if (type == SD_BUS_TYPE_VARIANT)
2095                 r = bus_message_open_variant(m, c, contents);
2096         else if (type == SD_BUS_TYPE_STRUCT)
2097                 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
2098         else if (type == SD_BUS_TYPE_DICT_ENTRY)
2099                 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
2100         else
2101                 r = -EINVAL;
2102
2103         if (r < 0) {
2104                 free(signature);
2105                 return r;
2106         }
2107
2108         /* OK, let's fill it in */
2109         w = m->containers + m->n_containers++;
2110         w->enclosing = type;
2111         w->signature = signature;
2112         w->index = 0;
2113         w->array_size = array_size;
2114         w->before = before;
2115         w->begin = begin;
2116         w->n_offsets = w->offsets_allocated = 0;
2117         w->offsets = NULL;
2118         w->need_offsets = need_offsets;
2119
2120         return 0;
2121 }
2122
2123 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2124
2125         assert(m);
2126         assert(c);
2127
2128         if (!BUS_MESSAGE_IS_GVARIANT(m))
2129                 return 0;
2130
2131         if (c->need_offsets) {
2132                 size_t payload, sz, i;
2133                 uint8_t *a;
2134
2135                 /* Variable-width arrays */
2136
2137                 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2138                 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2139
2140                 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2141                 if (!a)
2142                         return -ENOMEM;
2143
2144                 for (i = 0; i < c->n_offsets; i++)
2145                         bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2146         } else {
2147                 void *a;
2148
2149                 /* Fixed-width or empty arrays */
2150
2151                 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2152                 if (!a)
2153                         return -ENOMEM;
2154         }
2155
2156         return 0;
2157 }
2158
2159 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2160         uint8_t *a;
2161         size_t l;
2162
2163         assert(m);
2164         assert(c);
2165         assert(c->signature);
2166
2167         if (!BUS_MESSAGE_IS_GVARIANT(m))
2168                 return 0;
2169
2170         l = strlen(c->signature);
2171
2172         a = message_extend_body(m, 1, 1 + l, true, false);
2173         if (!a)
2174                 return -ENOMEM;
2175
2176         a[0] = 0;
2177         memcpy(a+1, c->signature, l);
2178
2179         return 0;
2180 }
2181
2182 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2183         bool fixed_size = true;
2184         size_t n_variable = 0;
2185         unsigned i = 0;
2186         const char *p;
2187         uint8_t *a;
2188         int r;
2189
2190         assert(m);
2191         assert(c);
2192
2193         if (!BUS_MESSAGE_IS_GVARIANT(m))
2194                 return 0;
2195
2196         p = strempty(c->signature);
2197         while (*p != 0) {
2198                 size_t n;
2199
2200                 r = signature_element_length(p, &n);
2201                 if (r < 0)
2202                         return r;
2203                 else {
2204                         char t[n+1];
2205
2206                         memcpy(t, p, n);
2207                         t[n] = 0;
2208
2209                         r = bus_gvariant_is_fixed_size(t);
2210                         if (r < 0)
2211                                 return r;
2212                 }
2213
2214                 assert(!c->need_offsets || i <= c->n_offsets);
2215
2216                 /* We need to add an offset for each item that has a
2217                  * variable size and that is not the last one in the
2218                  * list */
2219                 if (r == 0)
2220                         fixed_size = false;
2221                 if (r == 0 && p[n] != 0)
2222                         n_variable++;
2223
2224                 i++;
2225                 p += n;
2226         }
2227
2228         assert(!c->need_offsets || i == c->n_offsets);
2229         assert(c->need_offsets || n_variable == 0);
2230
2231         if (isempty(c->signature)) {
2232                 /* The unary type is encoded as fixed 1 byte padding */
2233                 a = message_extend_body(m, 1, 1, add_offset, false);
2234                 if (!a)
2235                         return -ENOMEM;
2236
2237                 *a = 0;
2238         } else if (n_variable <= 0) {
2239                 int alignment = 1;
2240
2241                 /* Structures with fixed-size members only have to be
2242                  * fixed-size themselves. But gvariant requires all fixed-size
2243                  * elements to be sized a multiple of their alignment. Hence,
2244                  * we must *always* add final padding after the last member so
2245                  * the overall size of the structure is properly aligned. */
2246                 if (fixed_size)
2247                         alignment = bus_gvariant_get_alignment(strempty(c->signature));
2248
2249                 assert(alignment > 0);
2250
2251                 a = message_extend_body(m, alignment, 0, add_offset, false);
2252                 if (!a)
2253                         return -ENOMEM;
2254         } else {
2255                 size_t sz;
2256                 unsigned j;
2257
2258                 assert(c->offsets[c->n_offsets-1] == m->body_size);
2259
2260                 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2261
2262                 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2263                 if (!a)
2264                         return -ENOMEM;
2265
2266                 p = strempty(c->signature);
2267                 for (i = 0, j = 0; i < c->n_offsets; i++) {
2268                         unsigned k;
2269                         size_t n;
2270
2271                         r = signature_element_length(p, &n);
2272                         if (r < 0)
2273                                 return r;
2274                         else {
2275                                 char t[n+1];
2276
2277                                 memcpy(t, p, n);
2278                                 t[n] = 0;
2279
2280                                 p += n;
2281
2282                                 r = bus_gvariant_is_fixed_size(t);
2283                                 if (r < 0)
2284                                         return r;
2285                                 if (r > 0 || p[0] == 0)
2286                                         continue;
2287                         }
2288
2289                         k = n_variable - 1 - j;
2290
2291                         bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2292
2293                         j++;
2294                 }
2295         }
2296
2297         return 0;
2298 }
2299
2300 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2301         struct bus_container *c;
2302         int r;
2303
2304         assert_return(m, -EINVAL);
2305         assert_return(!m->sealed, -EPERM);
2306         assert_return(m->n_containers > 0, -EINVAL);
2307         assert_return(!m->poisoned, -ESTALE);
2308
2309         c = message_get_container(m);
2310
2311         if (c->enclosing != SD_BUS_TYPE_ARRAY)
2312                 if (c->signature && c->signature[c->index] != 0)
2313                         return -EINVAL;
2314
2315         m->n_containers--;
2316
2317         if (c->enclosing == SD_BUS_TYPE_ARRAY)
2318                 r = bus_message_close_array(m, c);
2319         else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2320                 r = bus_message_close_variant(m, c);
2321         else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2322                 r = bus_message_close_struct(m, c, true);
2323         else
2324                 assert_not_reached("Unknown container type");
2325
2326         free(c->signature);
2327         free(c->offsets);
2328
2329         return r;
2330 }
2331
2332 typedef struct {
2333         const char *types;
2334         unsigned n_struct;
2335         unsigned n_array;
2336 } TypeStack;
2337
2338 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2339         assert(stack);
2340         assert(max > 0);
2341
2342         if (*i >= max)
2343                 return -EINVAL;
2344
2345         stack[*i].types = types;
2346         stack[*i].n_struct = n_struct;
2347         stack[*i].n_array = n_array;
2348         (*i)++;
2349
2350         return 0;
2351 }
2352
2353 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2354         assert(stack);
2355         assert(max > 0);
2356         assert(types);
2357         assert(n_struct);
2358         assert(n_array);
2359
2360         if (*i <= 0)
2361                 return 0;
2362
2363         (*i)--;
2364         *types = stack[*i].types;
2365         *n_struct = stack[*i].n_struct;
2366         *n_array = stack[*i].n_array;
2367
2368         return 1;
2369 }
2370
2371 int bus_message_append_ap(
2372                 sd_bus_message *m,
2373                 const char *types,
2374                 va_list ap) {
2375
2376         unsigned n_array, n_struct;
2377         TypeStack stack[BUS_CONTAINER_DEPTH];
2378         unsigned stack_ptr = 0;
2379         int r;
2380
2381         assert(m);
2382
2383         if (!types)
2384                 return 0;
2385
2386         n_array = (unsigned) -1;
2387         n_struct = strlen(types);
2388
2389         for (;;) {
2390                 const char *t;
2391
2392                 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2393                         r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2394                         if (r < 0)
2395                                 return r;
2396                         if (r == 0)
2397                                 break;
2398
2399                         r = sd_bus_message_close_container(m);
2400                         if (r < 0)
2401                                 return r;
2402
2403                         continue;
2404                 }
2405
2406                 t = types;
2407                 if (n_array != (unsigned) -1)
2408                         n_array --;
2409                 else {
2410                         types ++;
2411                         n_struct--;
2412                 }
2413
2414                 switch (*t) {
2415
2416                 case SD_BUS_TYPE_BYTE: {
2417                         uint8_t x;
2418
2419                         x = (uint8_t) va_arg(ap, int);
2420                         r = sd_bus_message_append_basic(m, *t, &x);
2421                         break;
2422                 }
2423
2424                 case SD_BUS_TYPE_BOOLEAN:
2425                 case SD_BUS_TYPE_INT32:
2426                 case SD_BUS_TYPE_UINT32:
2427                 case SD_BUS_TYPE_UNIX_FD: {
2428                         uint32_t x;
2429
2430                         /* We assume a boolean is the same as int32_t */
2431                         assert_cc(sizeof(int32_t) == sizeof(int));
2432
2433                         x = va_arg(ap, uint32_t);
2434                         r = sd_bus_message_append_basic(m, *t, &x);
2435                         break;
2436                 }
2437
2438                 case SD_BUS_TYPE_INT16:
2439                 case SD_BUS_TYPE_UINT16: {
2440                         uint16_t x;
2441
2442                         x = (uint16_t) va_arg(ap, int);
2443                         r = sd_bus_message_append_basic(m, *t, &x);
2444                         break;
2445                 }
2446
2447                 case SD_BUS_TYPE_INT64:
2448                 case SD_BUS_TYPE_UINT64: {
2449                         uint64_t x;
2450
2451                         x = va_arg(ap, uint64_t);
2452                         r = sd_bus_message_append_basic(m, *t, &x);
2453                         break;
2454                 }
2455
2456                 case SD_BUS_TYPE_DOUBLE: {
2457                         double x;
2458
2459                         x = va_arg(ap, double);
2460                         r = sd_bus_message_append_basic(m, *t, &x);
2461                         break;
2462                 }
2463
2464                 case SD_BUS_TYPE_STRING:
2465                 case SD_BUS_TYPE_OBJECT_PATH:
2466                 case SD_BUS_TYPE_SIGNATURE: {
2467                         const char *x;
2468
2469                         x = va_arg(ap, const char*);
2470                         r = sd_bus_message_append_basic(m, *t, x);
2471                         break;
2472                 }
2473
2474                 case SD_BUS_TYPE_ARRAY: {
2475                         size_t k;
2476
2477                         r = signature_element_length(t + 1, &k);
2478                         if (r < 0)
2479                                 return r;
2480
2481                         {
2482                                 char s[k + 1];
2483                                 memcpy(s, t + 1, k);
2484                                 s[k] = 0;
2485
2486                                 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2487                                 if (r < 0)
2488                                         return r;
2489                         }
2490
2491                         if (n_array == (unsigned) -1) {
2492                                 types += k;
2493                                 n_struct -= k;
2494                         }
2495
2496                         r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2497                         if (r < 0)
2498                                 return r;
2499
2500                         types = t + 1;
2501                         n_struct = k;
2502                         n_array = va_arg(ap, unsigned);
2503
2504                         break;
2505                 }
2506
2507                 case SD_BUS_TYPE_VARIANT: {
2508                         const char *s;
2509
2510                         s = va_arg(ap, const char*);
2511                         if (!s)
2512                                 return -EINVAL;
2513
2514                         r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2515                         if (r < 0)
2516                                 return r;
2517
2518                         r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2519                         if (r < 0)
2520                                 return r;
2521
2522                         types = s;
2523                         n_struct = strlen(s);
2524                         n_array = (unsigned) -1;
2525
2526                         break;
2527                 }
2528
2529                 case SD_BUS_TYPE_STRUCT_BEGIN:
2530                 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2531                         size_t k;
2532
2533                         r = signature_element_length(t, &k);
2534                         if (r < 0)
2535                                 return r;
2536
2537                         {
2538                                 char s[k - 1];
2539
2540                                 memcpy(s, t + 1, k - 2);
2541                                 s[k - 2] = 0;
2542
2543                                 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2544                                 if (r < 0)
2545                                         return r;
2546                         }
2547
2548                         if (n_array == (unsigned) -1) {
2549                                 types += k - 1;
2550                                 n_struct -= k - 1;
2551                         }
2552
2553                         r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2554                         if (r < 0)
2555                                 return r;
2556
2557                         types = t + 1;
2558                         n_struct = k - 2;
2559                         n_array = (unsigned) -1;
2560
2561                         break;
2562                 }
2563
2564                 default:
2565                         r = -EINVAL;
2566                 }
2567
2568                 if (r < 0)
2569                         return r;
2570         }
2571
2572         return 1;
2573 }
2574
2575 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2576         va_list ap;
2577         int r;
2578
2579         assert_return(m, -EINVAL);
2580         assert_return(types, -EINVAL);
2581         assert_return(!m->sealed, -EPERM);
2582         assert_return(!m->poisoned, -ESTALE);
2583
2584         va_start(ap, types);
2585         r = bus_message_append_ap(m, types, ap);
2586         va_end(ap);
2587
2588         return r;
2589 }
2590
2591 _public_ int sd_bus_message_append_array_space(
2592                 sd_bus_message *m,
2593                 char type,
2594                 size_t size,
2595                 void **ptr) {
2596
2597         ssize_t align, sz;
2598         void *a;
2599         int r;
2600
2601         assert_return(m, -EINVAL);
2602         assert_return(!m->sealed, -EPERM);
2603         assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2604         assert_return(ptr || size == 0, -EINVAL);
2605         assert_return(!m->poisoned, -ESTALE);
2606
2607         /* alignment and size of the trivial types (except bool) is
2608          * identical for gvariant and dbus1 marshalling */
2609         align = bus_type_get_alignment(type);
2610         sz = bus_type_get_size(type);
2611
2612         assert_se(align > 0);
2613         assert_se(sz > 0);
2614
2615         if (size % sz != 0)
2616                 return -EINVAL;
2617
2618         r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2619         if (r < 0)
2620                 return r;
2621
2622         a = message_extend_body(m, align, size, false, false);
2623         if (!a)
2624                 return -ENOMEM;
2625
2626         r = sd_bus_message_close_container(m);
2627         if (r < 0)
2628                 return r;
2629
2630         *ptr = a;
2631         return 0;
2632 }
2633
2634 _public_ int sd_bus_message_append_array(
2635                 sd_bus_message *m,
2636                 char type,
2637                 const void *ptr,
2638                 size_t size) {
2639         int r;
2640         void *p;
2641
2642         assert_return(m, -EINVAL);
2643         assert_return(!m->sealed, -EPERM);
2644         assert_return(bus_type_is_trivial(type), -EINVAL);
2645         assert_return(ptr || size == 0, -EINVAL);
2646         assert_return(!m->poisoned, -ESTALE);
2647
2648         r = sd_bus_message_append_array_space(m, type, size, &p);
2649         if (r < 0)
2650                 return r;
2651
2652         if (size > 0)
2653                 memcpy(p, ptr, size);
2654
2655         return 0;
2656 }
2657
2658 /// UNNEEDED by elogind
2659 #if 0
2660 _public_ int sd_bus_message_append_array_iovec(
2661                 sd_bus_message *m,
2662                 char type,
2663                 const struct iovec *iov,
2664                 unsigned n) {
2665
2666         size_t size;
2667         unsigned i;
2668         void *p;
2669         int r;
2670
2671         assert_return(m, -EINVAL);
2672         assert_return(!m->sealed, -EPERM);
2673         assert_return(bus_type_is_trivial(type), -EINVAL);
2674         assert_return(iov || n == 0, -EINVAL);
2675         assert_return(!m->poisoned, -ESTALE);
2676
2677         size = IOVEC_TOTAL_SIZE(iov, n);
2678
2679         r = sd_bus_message_append_array_space(m, type, size, &p);
2680         if (r < 0)
2681                 return r;
2682
2683         for (i = 0; i < n; i++) {
2684
2685                 if (iov[i].iov_base)
2686                         memcpy(p, iov[i].iov_base, iov[i].iov_len);
2687                 else
2688                         memzero(p, iov[i].iov_len);
2689
2690                 p = (uint8_t*) p + iov[i].iov_len;
2691         }
2692
2693         return 0;
2694 }
2695
2696 _public_ int sd_bus_message_append_array_memfd(
2697                 sd_bus_message *m,
2698                 char type,
2699                 int memfd,
2700                 uint64_t offset,
2701                 uint64_t size) {
2702
2703         _cleanup_close_ int copy_fd = -1;
2704         struct bus_body_part *part;
2705         ssize_t align, sz;
2706         uint64_t real_size;
2707         void *a;
2708         int r;
2709
2710         assert_return(m, -EINVAL);
2711         assert_return(memfd >= 0, -EBADF);
2712         assert_return(bus_type_is_trivial(type), -EINVAL);
2713         assert_return(size > 0, -EINVAL);
2714         assert_return(!m->sealed, -EPERM);
2715         assert_return(!m->poisoned, -ESTALE);
2716
2717         r = memfd_set_sealed(memfd);
2718         if (r < 0)
2719                 return r;
2720
2721         copy_fd = dup(memfd);
2722         if (copy_fd < 0)
2723                 return copy_fd;
2724
2725         r = memfd_get_size(memfd, &real_size);
2726         if (r < 0)
2727                 return r;
2728
2729         if (offset == 0 && size == (uint64_t) -1)
2730                 size = real_size;
2731         else if (offset + size > real_size)
2732                 return -EMSGSIZE;
2733
2734         align = bus_type_get_alignment(type);
2735         sz = bus_type_get_size(type);
2736
2737         assert_se(align > 0);
2738         assert_se(sz > 0);
2739
2740         if (offset % align != 0)
2741                 return -EINVAL;
2742
2743         if (size % sz != 0)
2744                 return -EINVAL;
2745
2746         if (size > (uint64_t) (uint32_t) -1)
2747                 return -EINVAL;
2748
2749         r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2750         if (r < 0)
2751                 return r;
2752
2753         a = message_extend_body(m, align, 0, false, false);
2754         if (!a)
2755                 return -ENOMEM;
2756
2757         part = message_append_part(m);
2758         if (!part)
2759                 return -ENOMEM;
2760
2761         part->memfd = copy_fd;
2762         part->memfd_offset = offset;
2763         part->sealed = true;
2764         part->size = size;
2765         copy_fd = -1;
2766
2767         m->body_size += size;
2768         message_extend_containers(m, size);
2769
2770         return sd_bus_message_close_container(m);
2771 }
2772
2773 _public_ int sd_bus_message_append_string_memfd(
2774                 sd_bus_message *m,
2775                 int memfd,
2776                 uint64_t offset,
2777                 uint64_t size) {
2778
2779         _cleanup_close_ int copy_fd = -1;
2780         struct bus_body_part *part;
2781         struct bus_container *c;
2782         uint64_t real_size;
2783         void *a;
2784         int r;
2785
2786         assert_return(m, -EINVAL);
2787         assert_return(memfd >= 0, -EBADF);
2788         assert_return(size > 0, -EINVAL);
2789         assert_return(!m->sealed, -EPERM);
2790         assert_return(!m->poisoned, -ESTALE);
2791
2792         r = memfd_set_sealed(memfd);
2793         if (r < 0)
2794                 return r;
2795
2796         copy_fd = dup(memfd);
2797         if (copy_fd < 0)
2798                 return copy_fd;
2799
2800         r = memfd_get_size(memfd, &real_size);
2801         if (r < 0)
2802                 return r;
2803
2804         if (offset == 0 && size == (uint64_t) -1)
2805                 size = real_size;
2806         else if (offset + size > real_size)
2807                 return -EMSGSIZE;
2808
2809         /* We require this to be NUL terminated */
2810         if (size == 0)
2811                 return -EINVAL;
2812
2813         if (size > (uint64_t) (uint32_t) -1)
2814                 return -EINVAL;
2815
2816         c = message_get_container(m);
2817         if (c->signature && c->signature[c->index]) {
2818                 /* Container signature is already set */
2819
2820                 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2821                         return -ENXIO;
2822         } else {
2823                 char *e;
2824
2825                 /* Maybe we can append to the signature? But only if this is the top-level container */
2826                 if (c->enclosing != 0)
2827                         return -ENXIO;
2828
2829                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2830                 if (!e) {
2831                         m->poisoned = true;
2832                         return -ENOMEM;
2833                 }
2834         }
2835
2836         if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2837                 a = message_extend_body(m, 4, 4, false, false);
2838                 if (!a)
2839                         return -ENOMEM;
2840
2841                 *(uint32_t*) a = size - 1;
2842         }
2843
2844         part = message_append_part(m);
2845         if (!part)
2846                 return -ENOMEM;
2847
2848         part->memfd = copy_fd;
2849         part->memfd_offset = offset;
2850         part->sealed = true;
2851         part->size = size;
2852         copy_fd = -1;
2853
2854         m->body_size += size;
2855         message_extend_containers(m, size);
2856
2857         if (BUS_MESSAGE_IS_GVARIANT(m)) {
2858                 r = message_add_offset(m, m->body_size);
2859                 if (r < 0) {
2860                         m->poisoned = true;
2861                         return -ENOMEM;
2862                 }
2863         }
2864
2865         if (c->enclosing != SD_BUS_TYPE_ARRAY)
2866                 c->index++;
2867
2868         return 0;
2869 }
2870 #endif // 0
2871
2872 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2873         char **i;
2874         int r;
2875
2876         assert_return(m, -EINVAL);
2877         assert_return(!m->sealed, -EPERM);
2878         assert_return(!m->poisoned, -ESTALE);
2879
2880         r = sd_bus_message_open_container(m, 'a', "s");
2881         if (r < 0)
2882                 return r;
2883
2884         STRV_FOREACH(i, l) {
2885                 r = sd_bus_message_append_basic(m, 's', *i);
2886                 if (r < 0)
2887                         return r;
2888         }
2889
2890         return sd_bus_message_close_container(m);
2891 }
2892
2893 static int bus_message_close_header(sd_bus_message *m) {
2894
2895         assert(m);
2896
2897         /* The actual user data is finished now, we just complete the
2898            variant and struct now (at least on gvariant). Remember
2899            this position, so that during parsing we know where to to
2900            put the outer container end. */
2901         m->user_body_size = m->body_size;
2902
2903         if (BUS_MESSAGE_IS_GVARIANT(m)) {
2904                 const char *signature;
2905                 size_t sz, l;
2906                 void *d;
2907
2908                 /* Add offset table to end of fields array */
2909                 if (m->n_header_offsets >= 1) {
2910                         uint8_t *a;
2911                         unsigned i;
2912
2913                         assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2914
2915                         sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2916                         a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2917                         if (!a)
2918                                 return -ENOMEM;
2919
2920                         for (i = 0; i < m->n_header_offsets; i++)
2921                                 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2922                 }
2923
2924                 /* Add gvariant NUL byte plus signature to the end of
2925                  * the body, followed by the final offset pointing to
2926                  * the end of the fields array */
2927
2928                 signature = strempty(m->root_container.signature);
2929                 l = strlen(signature);
2930
2931                 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1);
2932                 d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true);
2933                 if (!d)
2934                         return -ENOMEM;
2935
2936                 *(uint8_t*) d = 0;
2937                 *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN;
2938                 memcpy((uint8_t*) d + 2, signature, l);
2939                 *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END;
2940
2941                 bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size);
2942
2943                 m->footer = d;
2944                 m->footer_accessible = 1 + l + 2 + sz;
2945         } else {
2946                 m->header->dbus1.fields_size = m->fields_size;
2947                 m->header->dbus1.body_size = m->body_size;
2948         }
2949
2950         return 0;
2951 }
2952
2953 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2954         struct bus_body_part *part;
2955         size_t a;
2956         unsigned i;
2957         int r;
2958
2959         assert(m);
2960
2961         if (m->sealed)
2962                 return -EPERM;
2963
2964         if (m->n_containers > 0)
2965                 return -EBADMSG;
2966
2967         if (m->poisoned)
2968                 return -ESTALE;
2969
2970         if (cookie > 0xffffffffULL &&
2971             !BUS_MESSAGE_IS_GVARIANT(m))
2972                 return -EOPNOTSUPP;
2973
2974         /* In vtables the return signature of method calls is listed,
2975          * let's check if they match if this is a response */
2976         if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2977             m->enforced_reply_signature &&
2978             !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2979                 return -ENOMSG;
2980
2981         /* If gvariant marshalling is used we need to close the body structure */
2982         r = bus_message_close_struct(m, &m->root_container, false);
2983         if (r < 0)
2984                 return r;
2985
2986         /* If there's a non-trivial signature set, then add it in
2987          * here, but only on dbus1 */
2988         if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2989                 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2990                 if (r < 0)
2991                         return r;
2992         }
2993
2994         if (m->n_fds > 0) {
2995                 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2996                 if (r < 0)
2997                         return r;
2998         }
2999
3000         r = bus_message_close_header(m);
3001         if (r < 0)
3002                 return r;
3003
3004         if (BUS_MESSAGE_IS_GVARIANT(m))
3005                 m->header->dbus2.cookie = cookie;
3006         else
3007                 m->header->dbus1.serial = (uint32_t) cookie;
3008
3009         m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
3010
3011         /* Add padding at the end of the fields part, since we know
3012          * the body needs to start at an 8 byte alignment. We made
3013          * sure we allocated enough space for this, so all we need to
3014          * do here is to zero it out. */
3015         a = ALIGN8(m->fields_size) - m->fields_size;
3016         if (a > 0)
3017                 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
3018
3019         /* If this is something we can send as memfd, then let's seal
3020         the memfd now. Note that we can send memfds as payload only
3021         for directed messages, and not for broadcasts. */
3022         if (m->destination && m->bus->use_memfd) {
3023                 MESSAGE_FOREACH_PART(part, i, m)
3024                         if (part->memfd >= 0 &&
3025                             !part->sealed &&
3026                             (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
3027                             part != m->body_end) { /* The last part may never be sent as memfd */
3028                                 uint64_t sz;
3029
3030                                 /* Try to seal it if that makes
3031                                  * sense. First, unmap our own map to
3032                                  * make sure we don't keep it busy. */
3033                                 bus_body_part_unmap(part);
3034
3035                                 /* Then, sync up real memfd size */
3036                                 sz = part->size;
3037                                 r = memfd_set_size(part->memfd, sz);
3038                                 if (r < 0)
3039                                         return r;
3040
3041                                 /* Finally, try to seal */
3042                                 if (memfd_set_sealed(part->memfd) >= 0)
3043                                         part->sealed = true;
3044                         }
3045         }
3046
3047         m->root_container.end = m->user_body_size;
3048         m->root_container.index = 0;
3049         m->root_container.offset_index = 0;
3050         m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
3051
3052         m->sealed = true;
3053
3054         return 0;
3055 }
3056
3057 int bus_body_part_map(struct bus_body_part *part) {
3058         void *p;
3059         size_t psz, shift;
3060
3061         assert_se(part);
3062
3063         if (part->data)
3064                 return 0;
3065
3066         if (part->size <= 0)
3067                 return 0;
3068
3069         /* For smaller zero parts (as used for padding) we don't need to map anything... */
3070         if (part->memfd < 0 && part->is_zero && part->size < 8) {
3071                 static const uint8_t zeroes[7] = { };
3072                 part->data = (void*) zeroes;
3073                 return 0;
3074         }
3075
3076         shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
3077         psz = PAGE_ALIGN(part->size + shift);
3078
3079         if (part->memfd >= 0)
3080                 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
3081         else if (part->is_zero)
3082                 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
3083         else
3084                 return -EINVAL;
3085
3086         if (p == MAP_FAILED)
3087                 return -errno;
3088
3089         part->mapped = psz;
3090         part->mmap_begin = p;
3091         part->data = (uint8_t*) p + shift;
3092         part->munmap_this = true;
3093
3094         return 0;
3095 }
3096
3097 void bus_body_part_unmap(struct bus_body_part *part) {
3098
3099         assert_se(part);
3100
3101         if (part->memfd < 0)
3102                 return;
3103
3104         if (!part->mmap_begin)
3105                 return;
3106
3107         if (!part->munmap_this)
3108                 return;
3109
3110         assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3111
3112         part->mmap_begin = NULL;
3113         part->data = NULL;
3114         part->mapped = 0;
3115         part->munmap_this = false;
3116
3117         return;
3118 }
3119
3120 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3121         size_t k, start, end;
3122
3123         assert(rindex);
3124         assert(align > 0);
3125
3126         start = ALIGN_TO((size_t) *rindex, align);
3127         end = start + nbytes;
3128
3129         if (end > sz)
3130                 return -EBADMSG;
3131
3132         /* Verify that padding is 0 */
3133         for (k = *rindex; k < start; k++)
3134                 if (((const uint8_t*) p)[k] != 0)
3135                         return -EBADMSG;
3136
3137         if (r)
3138                 *r = (uint8_t*) p + start;
3139
3140         *rindex = end;
3141
3142         return 1;
3143 }
3144
3145 static bool message_end_of_signature(sd_bus_message *m) {
3146         struct bus_container *c;
3147
3148         assert(m);
3149
3150         c = message_get_container(m);
3151         return !c->signature || c->signature[c->index] == 0;
3152 }
3153
3154 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3155         struct bus_container *c;
3156
3157         assert(m);
3158
3159         c = message_get_container(m);
3160         if (c->enclosing != SD_BUS_TYPE_ARRAY)
3161                 return false;
3162
3163         if (BUS_MESSAGE_IS_GVARIANT(m))
3164                 return index >= c->end;
3165         else {
3166                 assert(c->array_size);
3167                 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3168         }
3169 }
3170
3171 /// UNNEEDED by elogind
3172 #if 0
3173 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3174         assert_return(m, -EINVAL);
3175         assert_return(m->sealed, -EPERM);
3176
3177         if (complete && m->n_containers > 0)
3178                 return false;
3179
3180         if (message_end_of_signature(m))
3181                 return true;
3182
3183         if (message_end_of_array(m, m->rindex))
3184                 return true;
3185
3186         return false;
3187 }
3188 #endif // 0
3189
3190 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3191         struct bus_body_part *part;
3192         size_t begin;
3193         int r;
3194
3195         assert(m);
3196
3197         if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3198                 part = m->cached_rindex_part;
3199                 begin = m->cached_rindex_part_begin;
3200         } else {
3201                 part = &m->body;
3202                 begin = 0;
3203         }
3204
3205         while (part) {
3206                 if (index < begin)
3207                         return NULL;
3208
3209                 if (index + sz <= begin + part->size) {
3210
3211                         r = bus_body_part_map(part);
3212                         if (r < 0)
3213                                 return NULL;
3214
3215                         if (p)
3216                                 *p = (uint8_t*) part->data + index - begin;
3217
3218                         m->cached_rindex_part = part;
3219                         m->cached_rindex_part_begin = begin;
3220
3221                         return part;
3222                 }
3223
3224                 begin += part->size;
3225                 part = part->next;
3226         }
3227
3228         return NULL;
3229 }
3230
3231 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3232         int r;
3233
3234         assert(m);
3235         assert(c);
3236         assert(rindex);
3237
3238         if (!BUS_MESSAGE_IS_GVARIANT(m))
3239                 return 0;
3240
3241         if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3242                 int sz;
3243
3244                 sz = bus_gvariant_get_size(c->signature);
3245                 if (sz < 0) {
3246                         int alignment;
3247
3248                         if (c->offset_index+1 >= c->n_offsets)
3249                                 goto end;
3250
3251                         /* Variable-size array */
3252
3253                         alignment = bus_gvariant_get_alignment(c->signature);
3254                         assert(alignment > 0);
3255
3256                         *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3257                         c->item_size = c->offsets[c->offset_index+1] - *rindex;
3258                 } else {
3259
3260                         if (c->offset_index+1 >= (c->end-c->begin)/sz)
3261                                 goto end;
3262
3263                         /* Fixed-size array */
3264                         *rindex = c->begin + (c->offset_index+1) * sz;
3265                         c->item_size = sz;
3266                 }
3267
3268                 c->offset_index++;
3269
3270         } else if (c->enclosing == 0 ||
3271                    c->enclosing == SD_BUS_TYPE_STRUCT ||
3272                    c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3273
3274                 int alignment;
3275                 size_t n, j;
3276
3277                 if (c->offset_index+1 >= c->n_offsets)
3278                         goto end;
3279
3280                 r = signature_element_length(c->signature + c->index, &n);
3281                 if (r < 0)
3282                         return r;
3283
3284                 r = signature_element_length(c->signature + c->index + n, &j);
3285                 if (r < 0)
3286                         return r;
3287                 else {
3288                         char t[j+1];
3289                         memcpy(t, c->signature + c->index + n, j);
3290                         t[j] = 0;
3291
3292                         alignment = bus_gvariant_get_alignment(t);
3293                 }
3294
3295                 assert(alignment > 0);
3296
3297                 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3298                 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3299
3300                 c->offset_index++;
3301
3302         } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3303                 goto end;
3304         else
3305                 assert_not_reached("Unknown container type");
3306
3307         return 0;
3308
3309 end:
3310         /* Reached the end */
3311         *rindex = c->end;
3312         c->item_size = 0;
3313         return 0;
3314 }
3315
3316
3317 static int message_peek_body(
3318                 sd_bus_message *m,
3319                 size_t *rindex,
3320                 size_t align,
3321                 size_t nbytes,
3322                 void **ret) {
3323
3324         size_t k, start, end, padding;
3325         struct bus_body_part *part;
3326         uint8_t *q;
3327
3328         assert(m);
3329         assert(rindex);
3330         assert(align > 0);
3331
3332         start = ALIGN_TO((size_t) *rindex, align);
3333         padding = start - *rindex;
3334         end = start + nbytes;
3335
3336         if (end > m->user_body_size)
3337                 return -EBADMSG;
3338
3339         part = find_part(m, *rindex, padding, (void**) &q);
3340         if (!part)
3341                 return -EBADMSG;
3342
3343         if (q) {
3344                 /* Verify padding */
3345                 for (k = 0; k < padding; k++)
3346                         if (q[k] != 0)
3347                                 return -EBADMSG;
3348         }
3349
3350         part = find_part(m, start, nbytes, (void**) &q);
3351         if (!part || (nbytes > 0 && !q))
3352                 return -EBADMSG;
3353
3354         *rindex = end;
3355
3356         if (ret)
3357                 *ret = q;
3358
3359         return 0;
3360 }
3361
3362 static bool validate_nul(const char *s, size_t l) {
3363
3364         /* Check for NUL chars in the string */
3365         if (memchr(s, 0, l))
3366                 return false;
3367
3368         /* Check for NUL termination */
3369         if (s[l] != 0)
3370                 return false;
3371
3372         return true;
3373 }
3374
3375 static bool validate_string(const char *s, size_t l) {
3376
3377         if (!validate_nul(s, l))
3378                 return false;
3379
3380         /* Check if valid UTF8 */
3381         if (!utf8_is_valid(s))
3382                 return false;
3383
3384         return true;
3385 }
3386
3387 static bool validate_signature(const char *s, size_t l) {
3388
3389         if (!validate_nul(s, l))
3390                 return false;
3391
3392         /* Check if valid signature */
3393         if (!signature_is_valid(s, true))
3394                 return false;
3395
3396         return true;
3397 }
3398
3399 static bool validate_object_path(const char *s, size_t l) {
3400
3401         if (!validate_nul(s, l))
3402                 return false;
3403
3404         if (!object_path_is_valid(s))
3405                 return false;
3406
3407         return true;
3408 }
3409
3410 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3411         struct bus_container *c;
3412         size_t rindex;
3413         void *q;
3414         int r;
3415
3416         assert_return(m, -EINVAL);
3417         assert_return(m->sealed, -EPERM);
3418         assert_return(bus_type_is_basic(type), -EINVAL);
3419
3420         if (message_end_of_signature(m))
3421                 return -ENXIO;
3422
3423         if (message_end_of_array(m, m->rindex))
3424                 return 0;
3425
3426         c = message_get_container(m);
3427         if (c->signature[c->index] != type)
3428                 return -ENXIO;
3429
3430         rindex = m->rindex;
3431
3432         if (BUS_MESSAGE_IS_GVARIANT(m)) {
3433
3434                 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3435                         bool ok;
3436
3437                         r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3438                         if (r < 0)
3439                                 return r;
3440
3441                         if (type == SD_BUS_TYPE_STRING)
3442                                 ok = validate_string(q, c->item_size-1);
3443                         else if (type == SD_BUS_TYPE_OBJECT_PATH)
3444                                 ok = validate_object_path(q, c->item_size-1);
3445                         else
3446                                 ok = validate_signature(q, c->item_size-1);
3447
3448                         if (!ok)
3449                                 return -EBADMSG;
3450
3451                         if (p)
3452                                 *(const char**) p = q;
3453                 } else {
3454                         int sz, align;
3455
3456                         sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3457                         assert(sz > 0);
3458                         if ((size_t) sz != c->item_size)
3459                                 return -EBADMSG;
3460
3461                         align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3462                         assert(align > 0);
3463
3464                         r = message_peek_body(m, &rindex, align, c->item_size, &q);
3465                         if (r < 0)
3466                                 return r;
3467
3468                         switch (type) {
3469
3470                         case SD_BUS_TYPE_BYTE:
3471                                 if (p)
3472                                         *(uint8_t*) p = *(uint8_t*) q;
3473                                 break;
3474
3475                         case SD_BUS_TYPE_BOOLEAN:
3476                                 if (p)
3477                                         *(int*) p = !!*(uint8_t*) q;
3478                                 break;
3479
3480                         case SD_BUS_TYPE_INT16:
3481                         case SD_BUS_TYPE_UINT16:
3482                                 if (p)
3483                                         *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3484                                 break;
3485
3486                         case SD_BUS_TYPE_INT32:
3487                         case SD_BUS_TYPE_UINT32:
3488                                 if (p)
3489                                         *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3490                                 break;
3491
3492                         case SD_BUS_TYPE_INT64:
3493                         case SD_BUS_TYPE_UINT64:
3494                         case SD_BUS_TYPE_DOUBLE:
3495                                 if (p)
3496                                         *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3497                                 break;
3498
3499                         case SD_BUS_TYPE_UNIX_FD: {
3500                                 uint32_t j;
3501
3502                                 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3503                                 if (j >= m->n_fds)
3504                                         return -EBADMSG;
3505
3506                                 if (p)
3507                                         *(int*) p = m->fds[j];
3508
3509                                 break;
3510                         }
3511
3512                         default:
3513                                 assert_not_reached("unexpected type");
3514                         }
3515                 }
3516
3517                 r = container_next_item(m, c, &rindex);
3518                 if (r < 0)
3519                         return r;
3520         } else {
3521
3522                 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3523                         uint32_t l;
3524                         bool ok;
3525
3526                         r = message_peek_body(m, &rindex, 4, 4, &q);
3527                         if (r < 0)
3528                                 return r;
3529
3530                         l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3531                         r = message_peek_body(m, &rindex, 1, l+1, &q);
3532                         if (r < 0)
3533                                 return r;
3534
3535                         if (type == SD_BUS_TYPE_OBJECT_PATH)
3536                                 ok = validate_object_path(q, l);
3537                         else
3538                                 ok = validate_string(q, l);
3539                         if (!ok)
3540                                 return -EBADMSG;
3541
3542                         if (p)
3543                                 *(const char**) p = q;
3544
3545                 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3546                         uint8_t l;
3547
3548                         r = message_peek_body(m, &rindex, 1, 1, &q);
3549                         if (r < 0)
3550                                 return r;
3551
3552                         l = *(uint8_t*) q;
3553                         r = message_peek_body(m, &rindex, 1, l+1, &q);
3554                         if (r < 0)
3555                                 return r;
3556
3557                         if (!validate_signature(q, l))
3558                                 return -EBADMSG;
3559
3560                         if (p)
3561                                 *(const char**) p = q;
3562
3563                 } else {
3564                         ssize_t sz, align;
3565
3566                         align = bus_type_get_alignment(type);
3567                         assert(align > 0);
3568
3569                         sz = bus_type_get_size(type);
3570                         assert(sz > 0);
3571
3572                         r = message_peek_body(m, &rindex, align, sz, &q);
3573                         if (r < 0)
3574                                 return r;
3575
3576                         switch (type) {
3577
3578                         case SD_BUS_TYPE_BYTE:
3579                                 if (p)
3580                                         *(uint8_t*) p = *(uint8_t*) q;
3581                                 break;
3582
3583                         case SD_BUS_TYPE_BOOLEAN:
3584                                 if (p)
3585                                         *(int*) p = !!*(uint32_t*) q;
3586                                 break;
3587
3588                         case SD_BUS_TYPE_INT16:
3589                         case SD_BUS_TYPE_UINT16:
3590                                 if (p)
3591                                         *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3592                                 break;
3593
3594                         case SD_BUS_TYPE_INT32:
3595                         case SD_BUS_TYPE_UINT32:
3596                                 if (p)
3597                                         *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3598                                 break;
3599
3600                         case SD_BUS_TYPE_INT64:
3601                         case SD_BUS_TYPE_UINT64:
3602                         case SD_BUS_TYPE_DOUBLE:
3603                                 if (p)
3604                                         *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3605                                 break;
3606
3607                         case SD_BUS_TYPE_UNIX_FD: {
3608                                 uint32_t j;
3609
3610                                 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3611                                 if (j >= m->n_fds)
3612                                         return -EBADMSG;
3613
3614                                 if (p)
3615                                         *(int*) p = m->fds[j];
3616                                 break;
3617                         }
3618
3619                         default:
3620                                 assert_not_reached("Unknown basic type...");
3621                         }
3622                 }
3623         }
3624
3625         m->rindex = rindex;
3626
3627         if (c->enclosing != SD_BUS_TYPE_ARRAY)
3628                 c->index++;
3629
3630         return 1;
3631 }
3632
3633 static int bus_message_enter_array(
3634                 sd_bus_message *m,
3635                 struct bus_container *c,
3636                 const char *contents,
3637                 uint32_t **array_size,
3638                 size_t *item_size,
3639                 size_t **offsets,
3640                 size_t *n_offsets) {
3641
3642         size_t rindex;
3643         void *q;
3644         int r, alignment;
3645
3646         assert(m);
3647         assert(c);
3648         assert(contents);
3649         assert(array_size);
3650         assert(item_size);
3651         assert(offsets);
3652         assert(n_offsets);
3653
3654         if (!signature_is_single(contents, true))
3655                 return -EINVAL;