1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <sys/mman.h>
6 
7 #include "sd-bus.h"
8 
9 #include "alloc-util.h"
10 #include "bus-gvariant.h"
11 #include "bus-internal.h"
12 #include "bus-message.h"
13 #include "bus-signature.h"
14 #include "bus-type.h"
15 #include "fd-util.h"
16 #include "io-util.h"
17 #include "memfd-util.h"
18 #include "memory-util.h"
19 #include "string-util.h"
20 #include "strv.h"
21 #include "time-util.h"
22 #include "utf8.h"
23 
24 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
25 
adjust_pointer(const void * p,void * old_base,size_t sz,void * new_base)26 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
27 
28         if (!p)
29                 return NULL;
30 
31         if (old_base == new_base)
32                 return (void*) p;
33 
34         if ((uint8_t*) p < (uint8_t*) old_base)
35                 return (void*) p;
36 
37         if ((uint8_t*) p >= (uint8_t*) old_base + sz)
38                 return (void*) p;
39 
40         return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
41 }
42 
message_free_part(sd_bus_message * m,struct bus_body_part * part)43 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
44         assert(m);
45         assert(part);
46 
47         if (part->memfd >= 0) {
48                 /* erase if requested, but only if the memfd is not sealed yet, i.e. is writable */
49                 if (m->sensitive && !m->sealed)
50                         explicit_bzero_safe(part->data, part->size);
51 
52                 close_and_munmap(part->memfd, part->mmap_begin, part->mapped);
53         } else if (part->munmap_this)
54                 /* We don't erase sensitive data here, since the data is memory mapped from someone else, and
55                  * we just don't know if it's OK to write to it */
56                 munmap(part->mmap_begin, part->mapped);
57         else {
58                 /* Erase this if that is requested. Since this is regular memory we know we can write it. */
59                 if (m->sensitive)
60                         explicit_bzero_safe(part->data, part->size);
61 
62                 if (part->free_this)
63                         free(part->data);
64         }
65 
66         if (part != &m->body)
67                 free(part);
68 }
69 
message_reset_parts(sd_bus_message * m)70 static void message_reset_parts(sd_bus_message *m) {
71         struct bus_body_part *part;
72 
73         assert(m);
74 
75         part = &m->body;
76         while (m->n_body_parts > 0) {
77                 struct bus_body_part *next = part->next;
78                 message_free_part(m, part);
79                 part = next;
80                 m->n_body_parts--;
81         }
82 
83         m->body_end = NULL;
84 
85         m->cached_rindex_part = NULL;
86         m->cached_rindex_part_begin = 0;
87 }
88 
message_get_last_container(sd_bus_message * m)89 static struct bus_container *message_get_last_container(sd_bus_message *m) {
90         assert(m);
91 
92         if (m->n_containers == 0)
93                 return &m->root_container;
94 
95         assert(m->containers);
96         return m->containers + m->n_containers - 1;
97 }
98 
message_free_last_container(sd_bus_message * m)99 static void message_free_last_container(sd_bus_message *m) {
100         struct bus_container *c;
101 
102         c = message_get_last_container(m);
103 
104         free(c->signature);
105         free(c->peeked_signature);
106         free(c->offsets);
107 
108         /* Move to previous container, but not if we are on root container */
109         if (m->n_containers > 0)
110                 m->n_containers--;
111 }
112 
message_reset_containers(sd_bus_message * m)113 static void message_reset_containers(sd_bus_message *m) {
114         assert(m);
115 
116         while (m->n_containers > 0)
117                 message_free_last_container(m);
118 
119         m->containers = mfree(m->containers);
120         m->root_container.index = 0;
121 }
122 
message_free(sd_bus_message * m)123 static sd_bus_message* message_free(sd_bus_message *m) {
124         assert(m);
125 
126         message_reset_parts(m);
127 
128         if (m->free_header)
129                 free(m->header);
130 
131         /* Note that we don't unref m->bus here. That's already done by sd_bus_message_unref() as each user
132          * reference to the bus message also is considered a reference to the bus connection itself. */
133 
134         if (m->free_fds) {
135                 close_many(m->fds, m->n_fds);
136                 free(m->fds);
137         }
138 
139         if (m->iovec != m->iovec_fixed)
140                 free(m->iovec);
141 
142         message_reset_containers(m);
143         assert(m->n_containers == 0);
144         message_free_last_container(m);
145 
146         bus_creds_done(&m->creds);
147         return mfree(m);
148 }
149 
message_extend_fields(sd_bus_message * m,size_t align,size_t sz,bool add_offset)150 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
151         void *op, *np;
152         size_t old_size, new_size, start;
153 
154         assert(m);
155 
156         if (m->poisoned)
157                 return NULL;
158 
159         old_size = sizeof(struct bus_header) + m->fields_size;
160         start = ALIGN_TO(old_size, align);
161         new_size = start + sz;
162 
163         if (new_size < start || new_size > UINT32_MAX)
164                 goto poison;
165 
166         if (old_size == new_size)
167                 return (uint8_t*) m->header + old_size;
168 
169         if (m->free_header) {
170                 np = realloc(m->header, ALIGN8(new_size));
171                 if (!np)
172                         goto poison;
173         } else {
174                 /* Initially, the header is allocated as part of
175                  * the sd_bus_message itself, let's replace it by
176                  * dynamic data */
177 
178                 np = malloc(ALIGN8(new_size));
179                 if (!np)
180                         goto poison;
181 
182                 memcpy(np, m->header, sizeof(struct bus_header));
183         }
184 
185         /* Zero out padding */
186         if (start > old_size)
187                 memzero((uint8_t*) np + old_size, start - old_size);
188 
189         op = m->header;
190         m->header = np;
191         m->fields_size = new_size - sizeof(struct bus_header);
192 
193         /* Adjust quick access pointers */
194         m->path = adjust_pointer(m->path, op, old_size, m->header);
195         m->interface = adjust_pointer(m->interface, op, old_size, m->header);
196         m->member = adjust_pointer(m->member, op, old_size, m->header);
197         m->destination = adjust_pointer(m->destination, op, old_size, m->header);
198         m->sender = adjust_pointer(m->sender, op, old_size, m->header);
199         m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
200 
201         m->free_header = true;
202 
203         if (add_offset) {
204                 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
205                         goto poison;
206 
207                 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
208         }
209 
210         return (uint8_t*) np + start;
211 
212 poison:
213         m->poisoned = true;
214         return NULL;
215 }
216 
message_append_field_string(sd_bus_message * m,uint64_t h,char type,const char * s,const char ** ret)217 static int message_append_field_string(
218                 sd_bus_message *m,
219                 uint64_t h,
220                 char type,
221                 const char *s,
222                 const char **ret) {
223 
224         size_t l;
225         uint8_t *p;
226 
227         assert(m);
228 
229         /* dbus1 only allows 8bit header field ids */
230         if (h > 0xFF)
231                 return -EINVAL;
232 
233         /* dbus1 doesn't allow strings over 32bit, let's enforce this
234          * globally, to not risk convertability */
235         l = strlen(s);
236         if (l > UINT32_MAX)
237                 return -EINVAL;
238 
239         /* Signature "(yv)" where the variant contains "s" */
240 
241         if (BUS_MESSAGE_IS_GVARIANT(m)) {
242 
243                 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
244                 p = message_extend_fields(m, 8, 8 + l + 1 + 1 + 1, true);
245                 if (!p)
246                         return -ENOMEM;
247 
248                 *((uint64_t*) p) = h;
249                 memcpy(p+8, s, l);
250                 p[8+l] = 0;
251                 p[8+l+1] = 0;
252                 p[8+l+2] = type;
253 
254                 if (ret)
255                         *ret = (char*) p + 8;
256 
257         } else {
258                 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
259                 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
260                 if (!p)
261                         return -ENOMEM;
262 
263                 p[0] = (uint8_t) h;
264                 p[1] = 1;
265                 p[2] = type;
266                 p[3] = 0;
267 
268                 ((uint32_t*) p)[1] = l;
269                 memcpy(p + 8, s, l + 1);
270 
271                 if (ret)
272                         *ret = (char*) p + 8;
273         }
274 
275         return 0;
276 }
277 
message_append_field_signature(sd_bus_message * m,uint64_t h,const char * s,const char ** ret)278 static int message_append_field_signature(
279                 sd_bus_message *m,
280                 uint64_t h,
281                 const char *s,
282                 const char **ret) {
283 
284         size_t l;
285         uint8_t *p;
286 
287         assert(m);
288 
289         /* dbus1 only allows 8bit header field ids */
290         if (h > 0xFF)
291                 return -EINVAL;
292 
293         /* dbus1 doesn't allow signatures over 8bit, let's enforce
294          * this globally, to not risk convertability */
295         l = strlen(s);
296         if (l > SD_BUS_MAXIMUM_SIGNATURE_LENGTH)
297                 return -EINVAL;
298 
299         /* Signature "(yv)" where the variant contains "g" */
300 
301         if (BUS_MESSAGE_IS_GVARIANT(m))
302                 /* For gvariant the serialization is the same as for normal strings */
303                 return message_append_field_string(m, h, 'g', s, ret);
304         else {
305                 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
306                 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
307                 if (!p)
308                         return -ENOMEM;
309 
310                 p[0] = (uint8_t) h;
311                 p[1] = 1;
312                 p[2] = SD_BUS_TYPE_SIGNATURE;
313                 p[3] = 0;
314                 p[4] = l;
315                 memcpy(p + 5, s, l + 1);
316 
317                 if (ret)
318                         *ret = (const char*) p + 5;
319         }
320 
321         return 0;
322 }
323 
message_append_field_uint32(sd_bus_message * m,uint64_t h,uint32_t x)324 static int message_append_field_uint32(sd_bus_message *m, uint64_t h, uint32_t x) {
325         uint8_t *p;
326 
327         assert(m);
328 
329         /* dbus1 only allows 8bit header field ids */
330         if (h > 0xFF)
331                 return -EINVAL;
332 
333         if (BUS_MESSAGE_IS_GVARIANT(m)) {
334                 /* (field id 64bit + ((value + NUL + signature string 'u') */
335 
336                 p = message_extend_fields(m, 8, 8 + 4 + 1 + 1, true);
337                 if (!p)
338                         return -ENOMEM;
339 
340                 *((uint64_t*) p) = h;
341                 *((uint32_t*) (p + 8)) = x;
342                 p[12] = 0;
343                 p[13] = 'u';
344         } else {
345                 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
346                 p = message_extend_fields(m, 8, 4 + 4, false);
347                 if (!p)
348                         return -ENOMEM;
349 
350                 p[0] = (uint8_t) h;
351                 p[1] = 1;
352                 p[2] = 'u';
353                 p[3] = 0;
354 
355                 ((uint32_t*) p)[1] = x;
356         }
357 
358         return 0;
359 }
360 
message_append_field_uint64(sd_bus_message * m,uint64_t h,uint64_t x)361 static int message_append_field_uint64(sd_bus_message *m, uint64_t h, uint64_t x) {
362         uint8_t *p;
363 
364         assert(m);
365 
366         /* dbus1 only allows 8bit header field ids */
367         if (h > 0xFF)
368                 return -EINVAL;
369 
370         if (BUS_MESSAGE_IS_GVARIANT(m)) {
371                 /* (field id 64bit + ((value + NUL + signature string 't') */
372 
373                 p = message_extend_fields(m, 8, 8 + 8 + 1 + 1, true);
374                 if (!p)
375                         return -ENOMEM;
376 
377                 *((uint64_t*) p) = h;
378                 *((uint64_t*) (p + 8)) = x;
379                 p[16] = 0;
380                 p[17] = 't';
381         } else {
382                 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
383                 p = message_extend_fields(m, 8, 4 + 4 + 8, false);
384                 if (!p)
385                         return -ENOMEM;
386 
387                 p[0] = (uint8_t) h;
388                 p[1] = 1;
389                 p[2] = 't';
390                 p[3] = 0;
391                 p[4] = 0;
392                 p[5] = 0;
393                 p[6] = 0;
394                 p[7] = 0;
395 
396                 ((uint64_t*) p)[1] = x;
397         }
398 
399         return 0;
400 }
401 
message_append_reply_cookie(sd_bus_message * m,uint64_t cookie)402 static int message_append_reply_cookie(sd_bus_message *m, uint64_t cookie) {
403         assert(m);
404 
405         if (BUS_MESSAGE_IS_GVARIANT(m))
406                 return message_append_field_uint64(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, cookie);
407         else {
408                 /* 64bit cookies are not supported on dbus1 */
409                 if (cookie > 0xffffffffUL)
410                         return -EOPNOTSUPP;
411 
412                 return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie);
413         }
414 }
415 
bus_message_from_header(sd_bus * bus,void * header,size_t header_accessible,void * footer,size_t footer_accessible,size_t message_size,int * fds,size_t n_fds,const char * label,size_t extra,sd_bus_message ** ret)416 int bus_message_from_header(
417                 sd_bus *bus,
418                 void *header,
419                 size_t header_accessible,
420                 void *footer,
421                 size_t footer_accessible,
422                 size_t message_size,
423                 int *fds,
424                 size_t n_fds,
425                 const char *label,
426                 size_t extra,
427                 sd_bus_message **ret) {
428 
429         _cleanup_free_ sd_bus_message *m = NULL;
430         struct bus_header *h;
431         size_t a, label_sz;
432 
433         assert(bus);
434         assert(header || header_accessible <= 0);
435         assert(footer || footer_accessible <= 0);
436         assert(fds || n_fds <= 0);
437         assert(ret);
438 
439         if (header_accessible < sizeof(struct bus_header))
440                 return -EBADMSG;
441 
442         if (header_accessible > message_size)
443                 return -EBADMSG;
444         if (footer_accessible > message_size)
445                 return -EBADMSG;
446 
447         h = header;
448         if (!IN_SET(h->version, 1, 2))
449                 return -EBADMSG;
450 
451         if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
452                 return -EBADMSG;
453 
454         if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN))
455                 return -EBADMSG;
456 
457         /* Note that we are happy with unknown flags in the flags header! */
458 
459         a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
460 
461         if (label) {
462                 label_sz = strlen(label);
463                 a += label_sz + 1;
464         }
465 
466         m = malloc0(a);
467         if (!m)
468                 return -ENOMEM;
469 
470         m->sealed = true;
471         m->header = header;
472         m->header_accessible = header_accessible;
473         m->footer = footer;
474         m->footer_accessible = footer_accessible;
475 
476         if (BUS_MESSAGE_IS_GVARIANT(m)) {
477                 size_t ws;
478 
479                 if (h->dbus2.cookie == 0)
480                         return -EBADMSG;
481 
482                 /* dbus2 derives the sizes from the message size and
483                 the offset table at the end, since it is formatted as
484                 gvariant "yyyyuta{tv}v". Since the message itself is a
485                 structure with precisely to variable sized entries,
486                 there's only one offset in the table, which marks the
487                 end of the fields array. */
488 
489                 ws = bus_gvariant_determine_word_size(message_size, 0);
490                 if (footer_accessible < ws)
491                         return -EBADMSG;
492 
493                 m->fields_size = bus_gvariant_read_word_le((uint8_t*) footer + footer_accessible - ws, ws);
494                 if (ALIGN8(m->fields_size) > message_size - ws)
495                         return -EBADMSG;
496                 if (m->fields_size < sizeof(struct bus_header))
497                         return -EBADMSG;
498 
499                 m->fields_size -= sizeof(struct bus_header);
500                 m->body_size = message_size - (sizeof(struct bus_header) + ALIGN8(m->fields_size));
501         } else {
502                 if (h->dbus1.serial == 0)
503                         return -EBADMSG;
504 
505                 /* dbus1 has the sizes in the header */
506                 m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size);
507                 m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size);
508 
509                 if (sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size != message_size)
510                         return -EBADMSG;
511         }
512 
513         m->fds = fds;
514         m->n_fds = n_fds;
515 
516         if (label) {
517                 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
518                 memcpy(m->creds.label, label, label_sz + 1);
519 
520                 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
521         }
522 
523         m->n_ref = 1;
524         m->bus = sd_bus_ref(bus);
525 
526         *ret = TAKE_PTR(m);
527 
528         return 0;
529 }
530 
bus_message_from_malloc(sd_bus * bus,void * buffer,size_t length,int * fds,size_t n_fds,const char * label,sd_bus_message ** ret)531 int bus_message_from_malloc(
532                 sd_bus *bus,
533                 void *buffer,
534                 size_t length,
535                 int *fds,
536                 size_t n_fds,
537                 const char *label,
538                 sd_bus_message **ret) {
539 
540         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
541         size_t sz;
542         int r;
543 
544         r = bus_message_from_header(
545                         bus,
546                         buffer, length, /* in this case the initial bytes and the final bytes are the same */
547                         buffer, length,
548                         length,
549                         fds, n_fds,
550                         label,
551                         0, &m);
552         if (r < 0)
553                 return r;
554 
555         sz = length - sizeof(struct bus_header) - ALIGN8(m->fields_size);
556         if (sz > 0) {
557                 m->n_body_parts = 1;
558                 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(m->fields_size);
559                 m->body.size = sz;
560                 m->body.sealed = true;
561                 m->body.memfd = -1;
562         }
563 
564         m->n_iovec = 1;
565         m->iovec = m->iovec_fixed;
566         m->iovec[0] = IOVEC_MAKE(buffer, length);
567 
568         r = bus_message_parse_fields(m);
569         if (r < 0)
570                 return r;
571 
572         /* We take possession of the memory and fds now */
573         m->free_header = true;
574         m->free_fds = true;
575 
576         *ret = TAKE_PTR(m);
577         return 0;
578 }
579 
sd_bus_message_new(sd_bus * bus,sd_bus_message ** m,uint8_t type)580 _public_ int sd_bus_message_new(
581                 sd_bus *bus,
582                 sd_bus_message **m,
583                 uint8_t type) {
584 
585         assert_return(bus, -ENOTCONN);
586         assert_return(bus = bus_resolve(bus), -ENOPKG);
587         assert_return(bus->state != BUS_UNSET, -ENOTCONN);
588         assert_return(m, -EINVAL);
589         /* Creation of messages with _SD_BUS_MESSAGE_TYPE_INVALID is allowed. */
590         assert_return(type < _SD_BUS_MESSAGE_TYPE_MAX, -EINVAL);
591 
592         sd_bus_message *t = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
593         if (!t)
594                 return -ENOMEM;
595 
596         t->n_ref = 1;
597         t->bus = sd_bus_ref(bus);
598         t->header = (struct bus_header*) ((uint8_t*) t + ALIGN(sizeof(struct sd_bus_message)));
599         t->header->endian = BUS_NATIVE_ENDIAN;
600         t->header->type = type;
601         t->header->version = bus->message_version;
602         t->allow_fds = bus->can_fds || !IN_SET(bus->state, BUS_HELLO, BUS_RUNNING);
603         t->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(t);
604 
605         if (bus->allow_interactive_authorization)
606                 t->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
607 
608         *m = t;
609         return 0;
610 }
611 
sd_bus_message_new_signal(sd_bus * bus,sd_bus_message ** m,const char * path,const char * interface,const char * member)612 _public_ int sd_bus_message_new_signal(
613                 sd_bus *bus,
614                 sd_bus_message **m,
615                 const char *path,
616                 const char *interface,
617                 const char *member) {
618 
619         _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL;
620         int r;
621 
622         assert_return(bus, -ENOTCONN);
623         assert_return(bus = bus_resolve(bus), -ENOPKG);
624         assert_return(bus->state != BUS_UNSET, -ENOTCONN);
625         assert_return(object_path_is_valid(path), -EINVAL);
626         assert_return(interface_name_is_valid(interface), -EINVAL);
627         assert_return(member_name_is_valid(member), -EINVAL);
628         assert_return(m, -EINVAL);
629 
630         r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_SIGNAL);
631         if (r < 0)
632                 return -ENOMEM;
633 
634         assert(t);
635 
636         t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
637 
638         r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
639         if (r < 0)
640                 return r;
641         r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
642         if (r < 0)
643                 return r;
644         r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
645         if (r < 0)
646                 return r;
647 
648         *m = TAKE_PTR(t);
649         return 0;
650 }
651 
sd_bus_message_new_method_call(sd_bus * bus,sd_bus_message ** m,const char * destination,const char * path,const char * interface,const char * member)652 _public_ int sd_bus_message_new_method_call(
653                 sd_bus *bus,
654                 sd_bus_message **m,
655                 const char *destination,
656                 const char *path,
657                 const char *interface,
658                 const char *member) {
659 
660         _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL;
661         int r;
662 
663         assert_return(bus, -ENOTCONN);
664         assert_return(bus = bus_resolve(bus), -ENOPKG);
665         assert_return(bus->state != BUS_UNSET, -ENOTCONN);
666         assert_return(!destination || service_name_is_valid(destination), -EINVAL);
667         assert_return(object_path_is_valid(path), -EINVAL);
668         assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
669         assert_return(member_name_is_valid(member), -EINVAL);
670         assert_return(m, -EINVAL);
671 
672         r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_METHOD_CALL);
673         if (r < 0)
674                 return -ENOMEM;
675 
676         assert(t);
677 
678         r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
679         if (r < 0)
680                 return r;
681         r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
682         if (r < 0)
683                 return r;
684 
685         if (interface) {
686                 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
687                 if (r < 0)
688                         return r;
689         }
690 
691         if (destination) {
692                 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
693                 if (r < 0)
694                         return r;
695         }
696 
697         *m = TAKE_PTR(t);
698         return 0;
699 }
700 
message_new_reply(sd_bus_message * call,uint8_t type,sd_bus_message ** m)701 static int message_new_reply(
702                 sd_bus_message *call,
703                 uint8_t type,
704                 sd_bus_message **m) {
705 
706         _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL;
707         uint64_t cookie;
708         int r;
709 
710         assert_return(call, -EINVAL);
711         assert_return(call->sealed, -EPERM);
712         assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
713         assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
714         assert_return(m, -EINVAL);
715 
716         cookie = BUS_MESSAGE_COOKIE(call);
717         if (cookie == 0)
718                 return -EOPNOTSUPP;
719 
720         r = sd_bus_message_new(call->bus, &t, type);
721         if (r < 0)
722                 return -ENOMEM;
723 
724         assert(t);
725 
726         t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
727         t->reply_cookie = cookie;
728         r = message_append_reply_cookie(t, t->reply_cookie);
729         if (r < 0)
730                 return r;
731 
732         if (call->sender) {
733                 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
734                 if (r < 0)
735                         return r;
736         }
737 
738         t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
739         t->enforced_reply_signature = call->enforced_reply_signature;
740 
741         /* let's copy the sensitive flag over. Let's do that as a safety precaution to keep a transaction
742          * wholly sensitive if already the incoming message was sensitive. This is particularly useful when a
743          * vtable record sets the SD_BUS_VTABLE_SENSITIVE flag on a method call, since this means it applies
744          * to both the message call and the reply. */
745         t->sensitive = call->sensitive;
746 
747         *m = TAKE_PTR(t);
748         return 0;
749 }
750 
sd_bus_message_new_method_return(sd_bus_message * call,sd_bus_message ** m)751 _public_ int sd_bus_message_new_method_return(
752                 sd_bus_message *call,
753                 sd_bus_message **m) {
754 
755         return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
756 }
757 
sd_bus_message_new_method_error(sd_bus_message * call,sd_bus_message ** m,const sd_bus_error * e)758 _public_ int sd_bus_message_new_method_error(
759                 sd_bus_message *call,
760                 sd_bus_message **m,
761                 const sd_bus_error *e) {
762 
763         _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL;
764         int r;
765 
766         assert_return(sd_bus_error_is_set(e), -EINVAL);
767         assert_return(m, -EINVAL);
768 
769         r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
770         if (r < 0)
771                 return r;
772 
773         r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
774         if (r < 0)
775                 return r;
776 
777         if (e->message) {
778                 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
779                 if (r < 0)
780                         return r;
781         }
782 
783         t->error._need_free = -1;
784 
785         *m = TAKE_PTR(t);
786         return 0;
787 }
788 
sd_bus_message_new_method_errorf(sd_bus_message * call,sd_bus_message ** m,const char * name,const char * format,...)789 _public_ int sd_bus_message_new_method_errorf(
790                 sd_bus_message *call,
791                 sd_bus_message **m,
792                 const char *name,
793                 const char *format,
794                 ...) {
795 
796         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
797         va_list ap;
798 
799         assert_return(name, -EINVAL);
800         assert_return(m, -EINVAL);
801 
802         va_start(ap, format);
803         bus_error_setfv(&error, name, format, ap);
804         va_end(ap);
805 
806         return sd_bus_message_new_method_error(call, m, &error);
807 }
808 
sd_bus_message_new_method_errno(sd_bus_message * call,sd_bus_message ** m,int error,const sd_bus_error * p)809 _public_ int sd_bus_message_new_method_errno(
810                 sd_bus_message *call,
811                 sd_bus_message **m,
812                 int error,
813                 const sd_bus_error *p) {
814 
815         _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
816 
817         if (sd_bus_error_is_set(p))
818                 return sd_bus_message_new_method_error(call, m, p);
819 
820         sd_bus_error_set_errno(&berror, error);
821 
822         return sd_bus_message_new_method_error(call, m, &berror);
823 }
824 
sd_bus_message_new_method_errnof(sd_bus_message * call,sd_bus_message ** m,int error,const char * format,...)825 _public_ int sd_bus_message_new_method_errnof(
826                 sd_bus_message *call,
827                 sd_bus_message **m,
828                 int error,
829                 const char *format,
830                 ...) {
831 
832         _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
833         va_list ap;
834 
835         va_start(ap, format);
836         sd_bus_error_set_errnofv(&berror, error, format, ap);
837         va_end(ap);
838 
839         return sd_bus_message_new_method_error(call, m, &berror);
840 }
841 
bus_message_set_sender_local(sd_bus * bus,sd_bus_message * m)842 void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
843         assert(bus);
844         assert(m);
845 
846         m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
847         m->creds.well_known_names_local = true;
848         m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
849 }
850 
bus_message_set_sender_driver(sd_bus * bus,sd_bus_message * m)851 void bus_message_set_sender_driver(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";
856         m->creds.well_known_names_driver = true;
857         m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
858 }
859 
bus_message_new_synthetic_error(sd_bus * bus,uint64_t cookie,const sd_bus_error * e,sd_bus_message ** m)860 int bus_message_new_synthetic_error(
861                 sd_bus *bus,
862                 uint64_t cookie,
863                 const sd_bus_error *e,
864                 sd_bus_message **m) {
865 
866         _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL;
867         int r;
868 
869         assert(bus);
870         assert(sd_bus_error_is_set(e));
871         assert(m);
872 
873         r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_METHOD_ERROR);
874         if (r < 0)
875                 return -ENOMEM;
876 
877         assert(t);
878 
879         t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
880         t->reply_cookie = cookie;
881 
882         r = message_append_reply_cookie(t, t->reply_cookie);
883         if (r < 0)
884                 return r;
885 
886         if (bus && bus->unique_name) {
887                 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
888                 if (r < 0)
889                         return r;
890         }
891 
892         r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
893         if (r < 0)
894                 return r;
895 
896         if (e->message) {
897                 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
898                 if (r < 0)
899                         return r;
900         }
901 
902         t->error._need_free = -1;
903 
904         bus_message_set_sender_driver(bus, t);
905 
906         *m = TAKE_PTR(t);
907         return 0;
908 }
909 
sd_bus_message_ref(sd_bus_message * m)910 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
911         if (!m)
912                 return NULL;
913 
914         /* We are fine if this message so far was either explicitly reffed or not reffed but queued into at
915          * least one bus connection object. */
916         assert(m->n_ref > 0 || m->n_queued > 0);
917 
918         m->n_ref++;
919 
920         /* Each user reference to a bus message shall also be considered a ref on the bus */
921         sd_bus_ref(m->bus);
922         return m;
923 }
924 
sd_bus_message_unref(sd_bus_message * m)925 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
926         if (!m)
927                 return NULL;
928 
929         assert(m->n_ref > 0);
930 
931         sd_bus_unref(m->bus); /* Each regular ref is also a ref on the bus connection. Let's hence drop it
932                                * here. Note we have to do this before decrementing our own n_ref here, since
933                                * otherwise, if this message is currently queued sd_bus_unref() might call
934                                * bus_message_unref_queued() for this which might then destroy the message
935                                * while we are still processing it. */
936         m->n_ref--;
937 
938         if (m->n_ref > 0 || m->n_queued > 0)
939                 return NULL;
940 
941         /* Unset the bus field if neither the user has a reference nor this message is queued. We are careful
942          * to reset the field only after the last reference to the bus is dropped, after all we might keep
943          * multiple references to the bus, once for each reference kept on ourselves. */
944         m->bus = NULL;
945 
946         return message_free(m);
947 }
948 
bus_message_ref_queued(sd_bus_message * m,sd_bus * bus)949 sd_bus_message* bus_message_ref_queued(sd_bus_message *m, sd_bus *bus) {
950         if (!m)
951                 return NULL;
952 
953         /* If this is a different bus than the message is associated with, then implicitly turn this into a
954          * regular reference. This means that you can create a memory leak by enqueuing a message generated
955          * on one bus onto another at the same time as enqueueing a message from the second one on the first,
956          * as we'll not detect the cyclic references there. */
957         if (bus != m->bus)
958                 return sd_bus_message_ref(m);
959 
960         assert(m->n_ref > 0 || m->n_queued > 0);
961         m->n_queued++;
962 
963         return m;
964 }
965 
bus_message_unref_queued(sd_bus_message * m,sd_bus * bus)966 sd_bus_message* bus_message_unref_queued(sd_bus_message *m, sd_bus *bus) {
967         if (!m)
968                 return NULL;
969 
970         if (bus != m->bus)
971                 return sd_bus_message_unref(m);
972 
973         assert(m->n_queued > 0);
974         m->n_queued--;
975 
976         if (m->n_ref > 0 || m->n_queued > 0)
977                 return NULL;
978 
979         m->bus = NULL;
980 
981         return message_free(m);
982 }
983 
sd_bus_message_get_type(sd_bus_message * m,uint8_t * type)984 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
985         assert_return(m, -EINVAL);
986         assert_return(type, -EINVAL);
987 
988         *type = m->header->type;
989         return 0;
990 }
991 
sd_bus_message_get_cookie(sd_bus_message * m,uint64_t * cookie)992 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
993         uint64_t c;
994 
995         assert_return(m, -EINVAL);
996         assert_return(cookie, -EINVAL);
997 
998         c = BUS_MESSAGE_COOKIE(m);
999         if (c == 0)
1000                 return -ENODATA;
1001 
1002         *cookie = BUS_MESSAGE_COOKIE(m);
1003         return 0;
1004 }
1005 
sd_bus_message_get_reply_cookie(sd_bus_message * m,uint64_t * cookie)1006 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
1007         assert_return(m, -EINVAL);
1008         assert_return(cookie, -EINVAL);
1009 
1010         if (m->reply_cookie == 0)
1011                 return -ENODATA;
1012 
1013         *cookie = m->reply_cookie;
1014         return 0;
1015 }
1016 
sd_bus_message_get_expect_reply(sd_bus_message * m)1017 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
1018         assert_return(m, -EINVAL);
1019 
1020         return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
1021                 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
1022 }
1023 
sd_bus_message_get_auto_start(sd_bus_message * m)1024 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
1025         assert_return(m, -EINVAL);
1026 
1027         return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
1028 }
1029 
sd_bus_message_get_allow_interactive_authorization(sd_bus_message * m)1030 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
1031         assert_return(m, -EINVAL);
1032 
1033         return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
1034                 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
1035 }
1036 
sd_bus_message_get_path(sd_bus_message * m)1037 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
1038         assert_return(m, NULL);
1039 
1040         return m->path;
1041 }
1042 
sd_bus_message_get_interface(sd_bus_message * m)1043 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
1044         assert_return(m, NULL);
1045 
1046         return m->interface;
1047 }
1048 
sd_bus_message_get_member(sd_bus_message * m)1049 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
1050         assert_return(m, NULL);
1051 
1052         return m->member;
1053 }
1054 
sd_bus_message_get_destination(sd_bus_message * m)1055 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
1056         assert_return(m, NULL);
1057 
1058         return m->destination;
1059 }
1060 
sd_bus_message_get_sender(sd_bus_message * m)1061 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
1062         assert_return(m, NULL);
1063 
1064         return m->sender;
1065 }
1066 
sd_bus_message_get_error(sd_bus_message * m)1067 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
1068         assert_return(m, NULL);
1069 
1070         if (!sd_bus_error_is_set(&m->error))
1071                 return NULL;
1072 
1073         return &m->error;
1074 }
1075 
sd_bus_message_get_monotonic_usec(sd_bus_message * m,uint64_t * usec)1076 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
1077         assert_return(m, -EINVAL);
1078         assert_return(usec, -EINVAL);
1079 
1080         if (m->monotonic <= 0)
1081                 return -ENODATA;
1082 
1083         *usec = m->monotonic;
1084         return 0;
1085 }
1086 
sd_bus_message_get_realtime_usec(sd_bus_message * m,uint64_t * usec)1087 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
1088         assert_return(m, -EINVAL);
1089         assert_return(usec, -EINVAL);
1090 
1091         if (m->realtime <= 0)
1092                 return -ENODATA;
1093 
1094         *usec = m->realtime;
1095         return 0;
1096 }
1097 
sd_bus_message_get_seqnum(sd_bus_message * m,uint64_t * seqnum)1098 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
1099         assert_return(m, -EINVAL);
1100         assert_return(seqnum, -EINVAL);
1101 
1102         if (m->seqnum <= 0)
1103                 return -ENODATA;
1104 
1105         *seqnum = m->seqnum;
1106         return 0;
1107 }
1108 
sd_bus_message_get_creds(sd_bus_message * m)1109 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
1110         assert_return(m, NULL);
1111 
1112         if (m->creds.mask == 0)
1113                 return NULL;
1114 
1115         return &m->creds;
1116 }
1117 
sd_bus_message_is_signal(sd_bus_message * m,const char * interface,const char * member)1118 _public_ int sd_bus_message_is_signal(
1119                 sd_bus_message *m,
1120                 const char *interface,
1121                 const char *member) {
1122 
1123         assert_return(m, -EINVAL);
1124 
1125         if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
1126                 return 0;
1127 
1128         if (interface && !streq_ptr(m->interface, interface))
1129                 return 0;
1130 
1131         if (member && !streq_ptr(m->member, member))
1132                 return 0;
1133 
1134         return 1;
1135 }
1136 
sd_bus_message_is_method_call(sd_bus_message * m,const char * interface,const char * member)1137 _public_ int sd_bus_message_is_method_call(
1138                 sd_bus_message *m,
1139                 const char *interface,
1140                 const char *member) {
1141 
1142         assert_return(m, -EINVAL);
1143 
1144         if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1145                 return 0;
1146 
1147         if (interface && !streq_ptr(m->interface, interface))
1148                 return 0;
1149 
1150         if (member && !streq_ptr(m->member, member))
1151                 return 0;
1152 
1153         return 1;
1154 }
1155 
sd_bus_message_is_method_error(sd_bus_message * m,const char * name)1156 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1157         assert_return(m, -EINVAL);
1158 
1159         if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1160                 return 0;
1161 
1162         if (name && !streq_ptr(m->error.name, name))
1163                 return 0;
1164 
1165         return 1;
1166 }
1167 
sd_bus_message_set_expect_reply(sd_bus_message * m,int b)1168 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1169         assert_return(m, -EINVAL);
1170         assert_return(!m->sealed, -EPERM);
1171         assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1172 
1173         SET_FLAG(m->header->flags, BUS_MESSAGE_NO_REPLY_EXPECTED, !b);
1174 
1175         return 0;
1176 }
1177 
sd_bus_message_set_auto_start(sd_bus_message * m,int b)1178 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1179         assert_return(m, -EINVAL);
1180         assert_return(!m->sealed, -EPERM);
1181 
1182         SET_FLAG(m->header->flags, BUS_MESSAGE_NO_AUTO_START, !b);
1183 
1184         return 0;
1185 }
1186 
sd_bus_message_set_allow_interactive_authorization(sd_bus_message * m,int b)1187 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1188         assert_return(m, -EINVAL);
1189         assert_return(!m->sealed, -EPERM);
1190 
1191         SET_FLAG(m->header->flags, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION, b);
1192 
1193         return 0;
1194 }
1195 
message_append_part(sd_bus_message * m)1196 struct bus_body_part *message_append_part(sd_bus_message *m) {
1197         struct bus_body_part *part;
1198 
1199         assert(m);
1200 
1201         if (m->poisoned)
1202                 return NULL;
1203 
1204         if (m->n_body_parts <= 0) {
1205                 part = &m->body;
1206                 zero(*part);
1207         } else {
1208                 assert(m->body_end);
1209 
1210                 part = new0(struct bus_body_part, 1);
1211                 if (!part) {
1212                         m->poisoned = true;
1213                         return NULL;
1214                 }
1215 
1216                 m->body_end->next = part;
1217         }
1218 
1219         part->memfd = -1;
1220         m->body_end = part;
1221         m->n_body_parts++;
1222 
1223         return part;
1224 }
1225 
part_zero(struct bus_body_part * part,size_t sz)1226 static void part_zero(struct bus_body_part *part, size_t sz) {
1227         assert(part);
1228         assert(sz > 0);
1229         assert(sz < 8);
1230 
1231         /* All other fields can be left in their defaults */
1232         assert(!part->data);
1233         assert(part->memfd < 0);
1234 
1235         part->size = sz;
1236         part->is_zero = true;
1237         part->sealed = true;
1238 }
1239 
part_make_space(struct sd_bus_message * m,struct bus_body_part * part,size_t sz,void ** q)1240 static int part_make_space(
1241                 struct sd_bus_message *m,
1242                 struct bus_body_part *part,
1243                 size_t sz,
1244                 void **q) {
1245 
1246         void *n;
1247 
1248         assert(m);
1249         assert(part);
1250         assert(!part->sealed);
1251 
1252         if (m->poisoned)
1253                 return -ENOMEM;
1254 
1255         if (part->allocated == 0 || sz > part->allocated) {
1256                 size_t new_allocated;
1257 
1258                 new_allocated = sz > 0 ? 2 * sz : 64;
1259                 n = realloc(part->data, new_allocated);
1260                 if (!n) {
1261                         m->poisoned = true;
1262                         return -ENOMEM;
1263                 }
1264 
1265                 part->data = n;
1266                 part->allocated = new_allocated;
1267                 part->free_this = true;
1268         }
1269 
1270         if (q)
1271                 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1272 
1273         part->size = sz;
1274         return 0;
1275 }
1276 
message_add_offset(sd_bus_message * m,size_t offset)1277 static int message_add_offset(sd_bus_message *m, size_t offset) {
1278         struct bus_container *c;
1279 
1280         assert(m);
1281         assert(BUS_MESSAGE_IS_GVARIANT(m));
1282 
1283         /* Add offset to current container, unless this is the first
1284          * item in it, which will have the 0 offset, which we can
1285          * ignore. */
1286         c = message_get_last_container(m);
1287 
1288         if (!c->need_offsets)
1289                 return 0;
1290 
1291         if (!GREEDY_REALLOC(c->offsets, c->n_offsets + 1))
1292                 return -ENOMEM;
1293 
1294         c->offsets[c->n_offsets++] = offset;
1295         return 0;
1296 }
1297 
message_extend_containers(sd_bus_message * m,size_t expand)1298 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1299         assert(m);
1300 
1301         if (expand <= 0)
1302                 return;
1303 
1304         if (m->n_containers <= 0)
1305                 return;
1306 
1307         /* Update counters */
1308         for (struct bus_container *c = m->containers; c < m->containers + m->n_containers; c++)
1309                 if (c->array_size)
1310                         *c->array_size += expand;
1311 }
1312 
message_extend_body(sd_bus_message * m,size_t align,size_t sz,bool add_offset,bool force_inline)1313 static void *message_extend_body(
1314                 sd_bus_message *m,
1315                 size_t align,
1316                 size_t sz,
1317                 bool add_offset,
1318                 bool force_inline) {
1319 
1320         size_t start_body, end_body, padding, added;
1321         void *p;
1322         int r;
1323 
1324         assert(m);
1325         assert(align > 0);
1326         assert(!m->sealed);
1327 
1328         if (m->poisoned)
1329                 return NULL;
1330 
1331         start_body = ALIGN_TO((size_t) m->body_size, align);
1332         end_body = start_body + sz;
1333 
1334         padding = start_body - m->body_size;
1335         added = padding + sz;
1336 
1337         /* Check for 32bit overflows */
1338         if (end_body < start_body || end_body > UINT32_MAX) {
1339                 m->poisoned = true;
1340                 return NULL;
1341         }
1342 
1343         if (added > 0) {
1344                 struct bus_body_part *part = NULL;
1345                 bool add_new_part;
1346 
1347                 add_new_part =
1348                         m->n_body_parts <= 0 ||
1349                         m->body_end->sealed ||
1350                         (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1351                         (force_inline && m->body_end->size > MEMFD_MIN_SIZE);
1352                         /* If this must be an inlined extension, let's create a new part if
1353                          * the previous part is large enough to be inlined. */
1354 
1355                 if (add_new_part) {
1356                         if (padding > 0) {
1357                                 part = message_append_part(m);
1358                                 if (!part)
1359                                         return NULL;
1360 
1361                                 part_zero(part, padding);
1362                         }
1363 
1364                         part = message_append_part(m);
1365                         if (!part)
1366                                 return NULL;
1367 
1368                         r = part_make_space(m, part, sz, &p);
1369                         if (r < 0)
1370                                 return NULL;
1371                 } else {
1372                         void *op;
1373                         size_t os, start_part, end_part;
1374 
1375                         part = m->body_end;
1376                         op = part->data;
1377                         os = part->size;
1378 
1379                         start_part = ALIGN_TO(part->size, align);
1380                         end_part = start_part + sz;
1381 
1382                         r = part_make_space(m, part, end_part, &p);
1383                         if (r < 0)
1384                                 return NULL;
1385 
1386                         if (padding > 0) {
1387                                 memzero(p, padding);
1388                                 p = (uint8_t*) p + padding;
1389                         }
1390 
1391                         /* Readjust pointers */
1392                         if (m->n_containers > 0)
1393                                 for (struct bus_container *c = m->containers; c < m->containers + m->n_containers; c++)
1394                                         c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1395 
1396                         m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1397                 }
1398         } else
1399                 /* Return something that is not NULL and is aligned */
1400                 p = (uint8_t*) align;
1401 
1402         m->body_size = end_body;
1403         message_extend_containers(m, added);
1404 
1405         if (add_offset) {
1406                 r = message_add_offset(m, end_body);
1407                 if (r < 0) {
1408                         m->poisoned = true;
1409                         return NULL;
1410                 }
1411         }
1412 
1413         return p;
1414 }
1415 
message_push_fd(sd_bus_message * m,int fd)1416 static int message_push_fd(sd_bus_message *m, int fd) {
1417         int *f, copy;
1418 
1419         assert(m);
1420 
1421         if (fd < 0)
1422                 return -EINVAL;
1423 
1424         if (!m->allow_fds)
1425                 return -EOPNOTSUPP;
1426 
1427         copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1428         if (copy < 0)
1429                 return -errno;
1430 
1431         f = reallocarray(m->fds, sizeof(int), m->n_fds + 1);
1432         if (!f) {
1433                 m->poisoned = true;
1434                 safe_close(copy);
1435                 return -ENOMEM;
1436         }
1437 
1438         m->fds = f;
1439         m->fds[m->n_fds] = copy;
1440         m->free_fds = true;
1441 
1442         return copy;
1443 }
1444 
message_append_basic(sd_bus_message * m,char type,const void * p,const void ** stored)1445 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1446         _cleanup_close_ int fd = -1;
1447         struct bus_container *c;
1448         ssize_t align, sz;
1449         void *a;
1450 
1451         assert_return(m, -EINVAL);
1452         assert_return(!m->sealed, -EPERM);
1453         assert_return(bus_type_is_basic(type), -EINVAL);
1454         assert_return(!m->poisoned, -ESTALE);
1455 
1456         c = message_get_last_container(m);
1457 
1458         if (c->signature && c->signature[c->index]) {
1459                 /* Container signature is already set */
1460 
1461                 if (c->signature[c->index] != type)
1462                         return -ENXIO;
1463         } else {
1464                 char *e;
1465 
1466                 /* Maybe we can append to the signature? But only if this is the top-level container */
1467                 if (c->enclosing != 0)
1468                         return -ENXIO;
1469 
1470                 e = strextend(&c->signature, CHAR_TO_STR(type));
1471                 if (!e) {
1472                         m->poisoned = true;
1473                         return -ENOMEM;
1474                 }
1475         }
1476 
1477         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1478                 uint8_t u8;
1479                 uint32_t u32;
1480 
1481                 switch (type) {
1482 
1483                 case SD_BUS_TYPE_SIGNATURE:
1484                 case SD_BUS_TYPE_STRING:
1485                         p = strempty(p);
1486 
1487                         _fallthrough_;
1488                 case SD_BUS_TYPE_OBJECT_PATH:
1489                         if (!p)
1490                                 return -EINVAL;
1491 
1492                         align = 1;
1493                         sz = strlen(p) + 1;
1494                         break;
1495 
1496                 case SD_BUS_TYPE_BOOLEAN:
1497 
1498                         u8 = p && *(int*) p;
1499                         p = &u8;
1500 
1501                         align = sz = 1;
1502                         break;
1503 
1504                 case SD_BUS_TYPE_UNIX_FD:
1505 
1506                         if (!p)
1507                                 return -EINVAL;
1508 
1509                         fd = message_push_fd(m, *(int*) p);
1510                         if (fd < 0)
1511                                 return fd;
1512 
1513                         u32 = m->n_fds;
1514                         p = &u32;
1515 
1516                         align = sz = 4;
1517                         break;
1518 
1519                 default:
1520                         align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1521                         sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1522                         break;
1523                 }
1524 
1525                 assert(align > 0);
1526                 assert(sz > 0);
1527 
1528                 a = message_extend_body(m, align, sz, true, false);
1529                 if (!a)
1530                         return -ENOMEM;
1531 
1532                 memcpy(a, p, sz);
1533 
1534                 if (stored)
1535                         *stored = (const uint8_t*) a;
1536 
1537         } else {
1538                 uint32_t u32;
1539 
1540                 switch (type) {
1541 
1542                 case SD_BUS_TYPE_STRING:
1543                         /* To make things easy we'll serialize a NULL string
1544                          * into the empty string */
1545                         p = strempty(p);
1546 
1547                         _fallthrough_;
1548                 case SD_BUS_TYPE_OBJECT_PATH:
1549 
1550                         if (!p)
1551                                 return -EINVAL;
1552 
1553                         align = 4;
1554                         sz = 4 + strlen(p) + 1;
1555                         break;
1556 
1557                 case SD_BUS_TYPE_SIGNATURE:
1558 
1559                         p = strempty(p);
1560 
1561                         align = 1;
1562                         sz = 1 + strlen(p) + 1;
1563                         break;
1564 
1565                 case SD_BUS_TYPE_BOOLEAN:
1566 
1567                         u32 = p && *(int*) p;
1568                         p = &u32;
1569 
1570                         align = sz = 4;
1571                         break;
1572 
1573                 case SD_BUS_TYPE_UNIX_FD:
1574 
1575                         if (!p)
1576                                 return -EINVAL;
1577 
1578                         fd = message_push_fd(m, *(int*) p);
1579                         if (fd < 0)
1580                                 return fd;
1581 
1582                         u32 = m->n_fds;
1583                         p = &u32;
1584 
1585                         align = sz = 4;
1586                         break;
1587 
1588                 default:
1589                         align = bus_type_get_alignment(type);
1590                         sz = bus_type_get_size(type);
1591                         break;
1592                 }
1593 
1594                 assert(align > 0);
1595                 assert(sz > 0);
1596 
1597                 a = message_extend_body(m, align, sz, false, false);
1598                 if (!a)
1599                         return -ENOMEM;
1600 
1601                 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
1602                         *(uint32_t*) a = sz - 5;
1603                         memcpy((uint8_t*) a + 4, p, sz - 4);
1604 
1605                         if (stored)
1606                                 *stored = (const uint8_t*) a + 4;
1607 
1608                 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1609                         *(uint8_t*) a = sz - 2;
1610                         memcpy((uint8_t*) a + 1, p, sz - 1);
1611 
1612                         if (stored)
1613                                 *stored = (const uint8_t*) a + 1;
1614                 } else {
1615                         memcpy(a, p, sz);
1616 
1617                         if (stored)
1618                                 *stored = a;
1619                 }
1620         }
1621 
1622         if (type == SD_BUS_TYPE_UNIX_FD)
1623                 m->n_fds++;
1624 
1625         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1626                 c->index++;
1627 
1628         fd = -1;
1629         return 0;
1630 }
1631 
sd_bus_message_append_basic(sd_bus_message * m,char type,const void * p)1632 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1633         return message_append_basic(m, type, p, NULL);
1634 }
1635 
sd_bus_message_append_string_space(sd_bus_message * m,size_t size,char ** s)1636 _public_ int sd_bus_message_append_string_space(
1637                 sd_bus_message *m,
1638                 size_t size,
1639                 char **s) {
1640 
1641         struct bus_container *c;
1642         void *a;
1643 
1644         assert_return(m, -EINVAL);
1645         assert_return(s, -EINVAL);
1646         assert_return(!m->sealed, -EPERM);
1647         assert_return(!m->poisoned, -ESTALE);
1648 
1649         c = message_get_last_container(m);
1650 
1651         if (c->signature && c->signature[c->index]) {
1652                 /* Container signature is already set */
1653 
1654                 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1655                         return -ENXIO;
1656         } else {
1657                 char *e;
1658 
1659                 /* Maybe we can append to the signature? But only if this is the top-level container */
1660                 if (c->enclosing != 0)
1661                         return -ENXIO;
1662 
1663                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING));
1664                 if (!e) {
1665                         m->poisoned = true;
1666                         return -ENOMEM;
1667                 }
1668         }
1669 
1670         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1671                 a = message_extend_body(m, 1, size + 1, true, false);
1672                 if (!a)
1673                         return -ENOMEM;
1674 
1675                 *s = a;
1676         } else {
1677                 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1678                 if (!a)
1679                         return -ENOMEM;
1680 
1681                 *(uint32_t*) a = size;
1682                 *s = (char*) a + 4;
1683         }
1684 
1685         (*s)[size] = 0;
1686 
1687         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1688                 c->index++;
1689 
1690         return 0;
1691 }
1692 
sd_bus_message_append_string_iovec(sd_bus_message * m,const struct iovec * iov,unsigned n)1693 _public_ int sd_bus_message_append_string_iovec(
1694                 sd_bus_message *m,
1695                 const struct iovec *iov,
1696                 unsigned n /* should be size_t, but is API now… �� */) {
1697 
1698         size_t size;
1699         unsigned i;
1700         char *p;
1701         int r;
1702 
1703         assert_return(m, -EINVAL);
1704         assert_return(!m->sealed, -EPERM);
1705         assert_return(iov || n == 0, -EINVAL);
1706         assert_return(!m->poisoned, -ESTALE);
1707 
1708         size = IOVEC_TOTAL_SIZE(iov, n);
1709 
1710         r = sd_bus_message_append_string_space(m, size, &p);
1711         if (r < 0)
1712                 return r;
1713 
1714         for (i = 0; i < n; i++) {
1715 
1716                 if (iov[i].iov_base)
1717                         memcpy(p, iov[i].iov_base, iov[i].iov_len);
1718                 else
1719                         memset(p, ' ', iov[i].iov_len);
1720 
1721                 p += iov[i].iov_len;
1722         }
1723 
1724         return 0;
1725 }
1726 
bus_message_open_array(sd_bus_message * m,struct bus_container * c,const char * contents,uint32_t ** array_size,size_t * begin,bool * need_offsets)1727 static int bus_message_open_array(
1728                 sd_bus_message *m,
1729                 struct bus_container *c,
1730                 const char *contents,
1731                 uint32_t **array_size,
1732                 size_t *begin,
1733                 bool *need_offsets) {
1734 
1735         unsigned nindex;
1736         int alignment, r;
1737 
1738         assert(m);
1739         assert(c);
1740         assert(contents);
1741         assert(array_size);
1742         assert(begin);
1743         assert(need_offsets);
1744 
1745         if (!signature_is_single(contents, true))
1746                 return -EINVAL;
1747 
1748         if (c->signature && c->signature[c->index]) {
1749 
1750                 /* Verify the existing signature */
1751 
1752                 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1753                         return -ENXIO;
1754 
1755                 if (!startswith(c->signature + c->index + 1, contents))
1756                         return -ENXIO;
1757 
1758                 nindex = c->index + 1 + strlen(contents);
1759         } else {
1760                 char *e;
1761 
1762                 if (c->enclosing != 0)
1763                         return -ENXIO;
1764 
1765                 /* Extend the existing signature */
1766 
1767                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents);
1768                 if (!e) {
1769                         m->poisoned = true;
1770                         return -ENOMEM;
1771                 }
1772 
1773                 nindex = e - c->signature;
1774         }
1775 
1776         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1777                 alignment = bus_gvariant_get_alignment(contents);
1778                 if (alignment < 0)
1779                         return alignment;
1780 
1781                 /* Add alignment padding and add to offset list */
1782                 if (!message_extend_body(m, alignment, 0, false, false))
1783                         return -ENOMEM;
1784 
1785                 r = bus_gvariant_is_fixed_size(contents);
1786                 if (r < 0)
1787                         return r;
1788 
1789                 *begin = m->body_size;
1790                 *need_offsets = r == 0;
1791         } else {
1792                 void *a, *op;
1793                 size_t os;
1794                 struct bus_body_part *o;
1795 
1796                 alignment = bus_type_get_alignment(contents[0]);
1797                 if (alignment < 0)
1798                         return alignment;
1799 
1800                 a = message_extend_body(m, 4, 4, false, false);
1801                 if (!a)
1802                         return -ENOMEM;
1803 
1804                 o = m->body_end;
1805                 op = m->body_end->data;
1806                 os = m->body_end->size;
1807 
1808                 /* Add alignment between size and first element */
1809                 if (!message_extend_body(m, alignment, 0, false, false))
1810                         return -ENOMEM;
1811 
1812                 /* location of array size might have changed so let's readjust a */
1813                 if (o == m->body_end)
1814                         a = adjust_pointer(a, op, os, m->body_end->data);
1815 
1816                 *(uint32_t*) a = 0;
1817                 *array_size = a;
1818         }
1819 
1820         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1821                 c->index = nindex;
1822 
1823         return 0;
1824 }
1825 
bus_message_open_variant(sd_bus_message * m,struct bus_container * c,const char * contents)1826 static int bus_message_open_variant(
1827                 sd_bus_message *m,
1828                 struct bus_container *c,
1829                 const char *contents) {
1830 
1831         assert(m);
1832         assert(c);
1833         assert(contents);
1834 
1835         if (!signature_is_single(contents, false))
1836                 return -EINVAL;
1837 
1838         if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1839                 return -EINVAL;
1840 
1841         if (c->signature && c->signature[c->index]) {
1842 
1843                 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1844                         return -ENXIO;
1845 
1846         } else {
1847                 char *e;
1848 
1849                 if (c->enclosing != 0)
1850                         return -ENXIO;
1851 
1852                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT));
1853                 if (!e) {
1854                         m->poisoned = true;
1855                         return -ENOMEM;
1856                 }
1857         }
1858 
1859         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1860                 /* Variants are always aligned to 8 */
1861 
1862                 if (!message_extend_body(m, 8, 0, false, false))
1863                         return -ENOMEM;
1864 
1865         } else {
1866                 size_t l;
1867                 void *a;
1868 
1869                 l = strlen(contents);
1870                 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1871                 if (!a)
1872                         return -ENOMEM;
1873 
1874                 *(uint8_t*) a = l;
1875                 memcpy((uint8_t*) a + 1, contents, l + 1);
1876         }
1877 
1878         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1879                 c->index++;
1880 
1881         return 0;
1882 }
1883 
bus_message_open_struct(sd_bus_message * m,struct bus_container * c,const char * contents,size_t * begin,bool * need_offsets)1884 static int bus_message_open_struct(
1885                 sd_bus_message *m,
1886                 struct bus_container *c,
1887                 const char *contents,
1888                 size_t *begin,
1889                 bool *need_offsets) {
1890 
1891         size_t nindex;
1892         int r;
1893 
1894         assert(m);
1895         assert(c);
1896         assert(contents);
1897         assert(begin);
1898         assert(need_offsets);
1899 
1900         if (!signature_is_valid(contents, false))
1901                 return -EINVAL;
1902 
1903         if (c->signature && c->signature[c->index]) {
1904                 size_t l;
1905 
1906                 l = strlen(contents);
1907 
1908                 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1909                     !startswith(c->signature + c->index + 1, contents) ||
1910                     c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1911                         return -ENXIO;
1912 
1913                 nindex = c->index + 1 + l + 1;
1914         } else {
1915                 char *e;
1916 
1917                 if (c->enclosing != 0)
1918                         return -ENXIO;
1919 
1920                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END));
1921                 if (!e) {
1922                         m->poisoned = true;
1923                         return -ENOMEM;
1924                 }
1925 
1926                 nindex = e - c->signature;
1927         }
1928 
1929         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1930                 int alignment;
1931 
1932                 alignment = bus_gvariant_get_alignment(contents);
1933                 if (alignment < 0)
1934                         return alignment;
1935 
1936                 if (!message_extend_body(m, alignment, 0, false, false))
1937                         return -ENOMEM;
1938 
1939                 r = bus_gvariant_is_fixed_size(contents);
1940                 if (r < 0)
1941                         return r;
1942 
1943                 *begin = m->body_size;
1944                 *need_offsets = r == 0;
1945         } else {
1946                 /* Align contents to 8 byte boundary */
1947                 if (!message_extend_body(m, 8, 0, false, false))
1948                         return -ENOMEM;
1949         }
1950 
1951         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1952                 c->index = nindex;
1953 
1954         return 0;
1955 }
1956 
bus_message_open_dict_entry(sd_bus_message * m,struct bus_container * c,const char * contents,size_t * begin,bool * need_offsets)1957 static int bus_message_open_dict_entry(
1958                 sd_bus_message *m,
1959                 struct bus_container *c,
1960                 const char *contents,
1961                 size_t *begin,
1962                 bool *need_offsets) {
1963 
1964         int r;
1965 
1966         assert(m);
1967         assert(c);
1968         assert(contents);
1969         assert(begin);
1970         assert(need_offsets);
1971 
1972         if (!signature_is_pair(contents))
1973                 return -EINVAL;
1974 
1975         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1976                 return -ENXIO;
1977 
1978         if (c->signature && c->signature[c->index]) {
1979                 size_t l;
1980 
1981                 l = strlen(contents);
1982 
1983                 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1984                     !startswith(c->signature + c->index + 1, contents) ||
1985                     c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1986                         return -ENXIO;
1987         } else
1988                 return -ENXIO;
1989 
1990         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1991                 int alignment;
1992 
1993                 alignment = bus_gvariant_get_alignment(contents);
1994                 if (alignment < 0)
1995                         return alignment;
1996 
1997                 if (!message_extend_body(m, alignment, 0, false, false))
1998                         return -ENOMEM;
1999 
2000                 r = bus_gvariant_is_fixed_size(contents);
2001                 if (r < 0)
2002                         return r;
2003 
2004                 *begin = m->body_size;
2005                 *need_offsets = r == 0;
2006         } else {
2007                 /* Align contents to 8 byte boundary */
2008                 if (!message_extend_body(m, 8, 0, false, false))
2009                         return -ENOMEM;
2010         }
2011 
2012         return 0;
2013 }
2014 
sd_bus_message_open_container(sd_bus_message * m,char type,const char * contents)2015 _public_ int sd_bus_message_open_container(
2016                 sd_bus_message *m,
2017                 char type,
2018                 const char *contents) {
2019 
2020         struct bus_container *c;
2021         uint32_t *array_size = NULL;
2022         _cleanup_free_ char *signature = NULL;
2023         size_t before, begin = 0;
2024         bool need_offsets = false;
2025         int r;
2026 
2027         assert_return(m, -EINVAL);
2028         assert_return(!m->sealed, -EPERM);
2029         assert_return(contents, -EINVAL);
2030         assert_return(!m->poisoned, -ESTALE);
2031 
2032         /* Make sure we have space for one more container */
2033         if (!GREEDY_REALLOC(m->containers, m->n_containers + 1)) {
2034                 m->poisoned = true;
2035                 return -ENOMEM;
2036         }
2037 
2038         c = message_get_last_container(m);
2039 
2040         signature = strdup(contents);
2041         if (!signature) {
2042                 m->poisoned = true;
2043                 return -ENOMEM;
2044         }
2045 
2046         /* Save old index in the parent container, in case we have to
2047          * abort this container */
2048         c->saved_index = c->index;
2049         before = m->body_size;
2050 
2051         if (type == SD_BUS_TYPE_ARRAY)
2052                 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
2053         else if (type == SD_BUS_TYPE_VARIANT)
2054                 r = bus_message_open_variant(m, c, contents);
2055         else if (type == SD_BUS_TYPE_STRUCT)
2056                 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
2057         else if (type == SD_BUS_TYPE_DICT_ENTRY)
2058                 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
2059         else
2060                 r = -EINVAL;
2061         if (r < 0)
2062                 return r;
2063 
2064         /* OK, let's fill it in */
2065         m->containers[m->n_containers++] = (struct bus_container) {
2066                 .enclosing = type,
2067                 .signature = TAKE_PTR(signature),
2068                 .array_size = array_size,
2069                 .before = before,
2070                 .begin = begin,
2071                 .need_offsets = need_offsets,
2072         };
2073 
2074         return 0;
2075 }
2076 
bus_message_close_array(sd_bus_message * m,struct bus_container * c)2077 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2078 
2079         assert(m);
2080         assert(c);
2081 
2082         if (!BUS_MESSAGE_IS_GVARIANT(m))
2083                 return 0;
2084 
2085         if (c->need_offsets) {
2086                 size_t payload, sz, i;
2087                 uint8_t *a;
2088 
2089                 /* Variable-width arrays */
2090 
2091                 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2092                 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2093 
2094                 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2095                 if (!a)
2096                         return -ENOMEM;
2097 
2098                 for (i = 0; i < c->n_offsets; i++)
2099                         bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2100         } else {
2101                 void *a;
2102 
2103                 /* Fixed-width or empty arrays */
2104 
2105                 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2106                 if (!a)
2107                         return -ENOMEM;
2108         }
2109 
2110         return 0;
2111 }
2112 
bus_message_close_variant(sd_bus_message * m,struct bus_container * c)2113 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2114         uint8_t *a;
2115         size_t l;
2116 
2117         assert(m);
2118         assert(c);
2119         assert(c->signature);
2120 
2121         if (!BUS_MESSAGE_IS_GVARIANT(m))
2122                 return 0;
2123 
2124         l = strlen(c->signature);
2125 
2126         a = message_extend_body(m, 1, 1 + l, true, false);
2127         if (!a)
2128                 return -ENOMEM;
2129 
2130         a[0] = 0;
2131         memcpy(a+1, c->signature, l);
2132 
2133         return 0;
2134 }
2135 
bus_message_close_struct(sd_bus_message * m,struct bus_container * c,bool add_offset)2136 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2137         bool fixed_size = true;
2138         size_t n_variable = 0;
2139         unsigned i = 0;
2140         const char *p;
2141         uint8_t *a;
2142         int r;
2143 
2144         assert(m);
2145         assert(c);
2146 
2147         if (!BUS_MESSAGE_IS_GVARIANT(m))
2148                 return 0;
2149 
2150         p = strempty(c->signature);
2151         while (*p != 0) {
2152                 size_t n;
2153 
2154                 r = signature_element_length(p, &n);
2155                 if (r < 0)
2156                         return r;
2157                 else {
2158                         char t[n+1];
2159 
2160                         memcpy(t, p, n);
2161                         t[n] = 0;
2162 
2163                         r = bus_gvariant_is_fixed_size(t);
2164                         if (r < 0)
2165                                 return r;
2166                 }
2167 
2168                 assert(!c->need_offsets || i <= c->n_offsets);
2169 
2170                 /* We need to add an offset for each item that has a
2171                  * variable size and that is not the last one in the
2172                  * list */
2173                 if (r == 0)
2174                         fixed_size = false;
2175                 if (r == 0 && p[n] != 0)
2176                         n_variable++;
2177 
2178                 i++;
2179                 p += n;
2180         }
2181 
2182         assert(!c->need_offsets || i == c->n_offsets);
2183         assert(c->need_offsets || n_variable == 0);
2184 
2185         if (isempty(c->signature)) {
2186                 /* The unary type is encoded as fixed 1 byte padding */
2187                 a = message_extend_body(m, 1, 1, add_offset, false);
2188                 if (!a)
2189                         return -ENOMEM;
2190 
2191                 *a = 0;
2192         } else if (n_variable <= 0) {
2193                 int alignment = 1;
2194 
2195                 /* Structures with fixed-size members only have to be
2196                  * fixed-size themselves. But gvariant requires all fixed-size
2197                  * elements to be sized a multiple of their alignment. Hence,
2198                  * we must *always* add final padding after the last member so
2199                  * the overall size of the structure is properly aligned. */
2200                 if (fixed_size)
2201                         alignment = bus_gvariant_get_alignment(strempty(c->signature));
2202 
2203                 assert(alignment > 0);
2204 
2205                 a = message_extend_body(m, alignment, 0, add_offset, false);
2206                 if (!a)
2207                         return -ENOMEM;
2208         } else {
2209                 size_t sz;
2210                 unsigned j;
2211 
2212                 assert(c->offsets[c->n_offsets-1] == m->body_size);
2213 
2214                 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2215 
2216                 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2217                 if (!a)
2218                         return -ENOMEM;
2219 
2220                 p = strempty(c->signature);
2221                 for (i = 0, j = 0; i < c->n_offsets; i++) {
2222                         unsigned k;
2223                         size_t n;
2224 
2225                         r = signature_element_length(p, &n);
2226                         if (r < 0)
2227                                 return r;
2228                         else {
2229                                 char t[n+1];
2230 
2231                                 memcpy(t, p, n);
2232                                 t[n] = 0;
2233 
2234                                 p += n;
2235 
2236                                 r = bus_gvariant_is_fixed_size(t);
2237                                 if (r < 0)
2238                                         return r;
2239                                 if (r > 0 || p[0] == 0)
2240                                         continue;
2241                         }
2242 
2243                         k = n_variable - 1 - j;
2244 
2245                         bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2246 
2247                         j++;
2248                 }
2249         }
2250 
2251         return 0;
2252 }
2253 
sd_bus_message_close_container(sd_bus_message * m)2254 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2255         struct bus_container *c;
2256         int r;
2257 
2258         assert_return(m, -EINVAL);
2259         assert_return(!m->sealed, -EPERM);
2260         assert_return(m->n_containers > 0, -EINVAL);
2261         assert_return(!m->poisoned, -ESTALE);
2262 
2263         c = message_get_last_container(m);
2264 
2265         if (c->enclosing != SD_BUS_TYPE_ARRAY)
2266                 if (c->signature && c->signature[c->index] != 0)
2267                         return -EINVAL;
2268 
2269         m->n_containers--;
2270 
2271         if (c->enclosing == SD_BUS_TYPE_ARRAY)
2272                 r = bus_message_close_array(m, c);
2273         else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2274                 r = bus_message_close_variant(m, c);
2275         else if (IN_SET(c->enclosing, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY))
2276                 r = bus_message_close_struct(m, c, true);
2277         else
2278                 assert_not_reached();
2279 
2280         free(c->signature);
2281         free(c->offsets);
2282 
2283         return r;
2284 }
2285 
2286 typedef struct {
2287         const char *types;
2288         unsigned n_struct;
2289         unsigned n_array;
2290 } TypeStack;
2291 
type_stack_push(TypeStack * stack,unsigned max,unsigned * i,const char * types,unsigned n_struct,unsigned n_array)2292 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2293         assert(stack);
2294         assert(max > 0);
2295 
2296         if (*i >= max)
2297                 return -EINVAL;
2298 
2299         stack[*i].types = types;
2300         stack[*i].n_struct = n_struct;
2301         stack[*i].n_array = n_array;
2302         (*i)++;
2303 
2304         return 0;
2305 }
2306 
type_stack_pop(TypeStack * stack,unsigned max,unsigned * i,const char ** types,unsigned * n_struct,unsigned * n_array)2307 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2308         assert(stack);
2309         assert(max > 0);
2310         assert(types);
2311         assert(n_struct);
2312         assert(n_array);
2313 
2314         if (*i <= 0)
2315                 return 0;
2316 
2317         (*i)--;
2318         *types = stack[*i].types;
2319         *n_struct = stack[*i].n_struct;
2320         *n_array = stack[*i].n_array;
2321 
2322         return 1;
2323 }
2324 
sd_bus_message_appendv(sd_bus_message * m,const char * types,va_list ap)2325 _public_ int sd_bus_message_appendv(
2326                 sd_bus_message *m,
2327                 const char *types,
2328                 va_list ap) {
2329 
2330         unsigned n_array, n_struct;
2331         TypeStack stack[BUS_CONTAINER_DEPTH];
2332         unsigned stack_ptr = 0;
2333         int r;
2334 
2335         assert_return(m, -EINVAL);
2336         assert_return(types, -EINVAL);
2337         assert_return(!m->sealed, -EPERM);
2338         assert_return(!m->poisoned, -ESTALE);
2339 
2340         n_array = UINT_MAX;
2341         n_struct = strlen(types);
2342 
2343         for (;;) {
2344                 const char *t;
2345 
2346                 if (n_array == 0 || (n_array == UINT_MAX && n_struct == 0)) {
2347                         r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2348                         if (r < 0)
2349                                 return r;
2350                         if (r == 0)
2351                                 break;
2352 
2353                         r = sd_bus_message_close_container(m);
2354                         if (r < 0)
2355                                 return r;
2356 
2357                         continue;
2358                 }
2359 
2360                 t = types;
2361                 if (n_array != UINT_MAX)
2362                         n_array--;
2363                 else {
2364                         types++;
2365                         n_struct--;
2366                 }
2367 
2368                 switch (*t) {
2369 
2370                 case SD_BUS_TYPE_BYTE: {
2371                         uint8_t x;
2372 
2373                         x = (uint8_t) va_arg(ap, int);
2374                         r = sd_bus_message_append_basic(m, *t, &x);
2375                         break;
2376                 }
2377 
2378                 case SD_BUS_TYPE_BOOLEAN:
2379                 case SD_BUS_TYPE_INT32:
2380                 case SD_BUS_TYPE_UINT32:
2381                 case SD_BUS_TYPE_UNIX_FD: {
2382                         uint32_t x;
2383 
2384                         /* We assume a boolean is the same as int32_t */
2385                         assert_cc(sizeof(int32_t) == sizeof(int));
2386 
2387                         x = va_arg(ap, uint32_t);
2388                         r = sd_bus_message_append_basic(m, *t, &x);
2389                         break;
2390                 }
2391 
2392                 case SD_BUS_TYPE_INT16:
2393                 case SD_BUS_TYPE_UINT16: {
2394                         uint16_t x;
2395 
2396                         x = (uint16_t) va_arg(ap, int);
2397                         r = sd_bus_message_append_basic(m, *t, &x);
2398                         break;
2399                 }
2400 
2401                 case SD_BUS_TYPE_INT64:
2402                 case SD_BUS_TYPE_UINT64: {
2403                         uint64_t x;
2404 
2405                         x = va_arg(ap, uint64_t);
2406                         r = sd_bus_message_append_basic(m, *t, &x);
2407                         break;
2408                 }
2409 
2410                 case SD_BUS_TYPE_DOUBLE: {
2411                         double x;
2412 
2413                         x = va_arg(ap, double);
2414                         r = sd_bus_message_append_basic(m, *t, &x);
2415                         break;
2416                 }
2417 
2418                 case SD_BUS_TYPE_STRING:
2419                 case SD_BUS_TYPE_OBJECT_PATH:
2420                 case SD_BUS_TYPE_SIGNATURE: {
2421                         const char *x;
2422 
2423                         x = va_arg(ap, const char*);
2424                         r = sd_bus_message_append_basic(m, *t, x);
2425                         break;
2426                 }
2427 
2428                 case SD_BUS_TYPE_ARRAY: {
2429                         size_t k;
2430 
2431                         r = signature_element_length(t + 1, &k);
2432                         if (r < 0)
2433                                 return r;
2434 
2435                         {
2436                                 char s[k + 1];
2437                                 memcpy(s, t + 1, k);
2438                                 s[k] = 0;
2439 
2440                                 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2441                                 if (r < 0)
2442                                         return r;
2443                         }
2444 
2445                         if (n_array == UINT_MAX) {
2446                                 types += k;
2447                                 n_struct -= k;
2448                         }
2449 
2450                         r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2451                         if (r < 0)
2452                                 return r;
2453 
2454                         types = t + 1;
2455                         n_struct = k;
2456                         n_array = va_arg(ap, unsigned);
2457 
2458                         break;
2459                 }
2460 
2461                 case SD_BUS_TYPE_VARIANT: {
2462                         const char *s;
2463 
2464                         s = va_arg(ap, const char*);
2465                         if (!s)
2466                                 return -EINVAL;
2467 
2468                         r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2469                         if (r < 0)
2470                                 return r;
2471 
2472                         r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2473                         if (r < 0)
2474                                 return r;
2475 
2476                         types = s;
2477                         n_struct = strlen(s);
2478                         n_array = UINT_MAX;
2479 
2480                         break;
2481                 }
2482 
2483                 case SD_BUS_TYPE_STRUCT_BEGIN:
2484                 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2485                         size_t k;
2486 
2487                         r = signature_element_length(t, &k);
2488                         if (r < 0)
2489                                 return r;
2490 
2491                         {
2492                                 char s[k - 1];
2493 
2494                                 memcpy(s, t + 1, k - 2);
2495                                 s[k - 2] = 0;
2496 
2497                                 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2498                                 if (r < 0)
2499                                         return r;
2500                         }
2501 
2502                         if (n_array == UINT_MAX) {
2503                                 types += k - 1;
2504                                 n_struct -= k - 1;
2505                         }
2506 
2507                         r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2508                         if (r < 0)
2509                                 return r;
2510 
2511                         types = t + 1;
2512                         n_struct = k - 2;
2513                         n_array = UINT_MAX;
2514 
2515                         break;
2516                 }
2517 
2518                 default:
2519                         r = -EINVAL;
2520                 }
2521 
2522                 if (r < 0)
2523                         return r;
2524         }
2525 
2526         return 1;
2527 }
2528 
sd_bus_message_append(sd_bus_message * m,const char * types,...)2529 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2530         va_list ap;
2531         int r;
2532 
2533         va_start(ap, types);
2534         r = sd_bus_message_appendv(m, types, ap);
2535         va_end(ap);
2536 
2537         return r;
2538 }
2539 
sd_bus_message_append_array_space(sd_bus_message * m,char type,size_t size,void ** ptr)2540 _public_ int sd_bus_message_append_array_space(
2541                 sd_bus_message *m,
2542                 char type,
2543                 size_t size,
2544                 void **ptr) {
2545 
2546         ssize_t align, sz;
2547         void *a;
2548         int r;
2549 
2550         assert_return(m, -EINVAL);
2551         assert_return(!m->sealed, -EPERM);
2552         assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2553         assert_return(ptr || size == 0, -EINVAL);
2554         assert_return(!m->poisoned, -ESTALE);
2555 
2556         /* alignment and size of the trivial types (except bool) is
2557          * identical for gvariant and dbus1 marshalling */
2558         align = bus_type_get_alignment(type);
2559         sz = bus_type_get_size(type);
2560 
2561         assert_se(align > 0);
2562         assert_se(sz > 0);
2563 
2564         if (size % sz != 0)
2565                 return -EINVAL;
2566 
2567         r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2568         if (r < 0)
2569                 return r;
2570 
2571         a = message_extend_body(m, align, size, false, false);
2572         if (!a)
2573                 return -ENOMEM;
2574 
2575         r = sd_bus_message_close_container(m);
2576         if (r < 0)
2577                 return r;
2578 
2579         *ptr = a;
2580         return 0;
2581 }
2582 
sd_bus_message_append_array(sd_bus_message * m,char type,const void * ptr,size_t size)2583 _public_ int sd_bus_message_append_array(
2584                 sd_bus_message *m,
2585                 char type,
2586                 const void *ptr,
2587                 size_t size) {
2588         int r;
2589         void *p;
2590 
2591         assert_return(m, -EINVAL);
2592         assert_return(!m->sealed, -EPERM);
2593         assert_return(bus_type_is_trivial(type), -EINVAL);
2594         assert_return(ptr || size == 0, -EINVAL);
2595         assert_return(!m->poisoned, -ESTALE);
2596 
2597         r = sd_bus_message_append_array_space(m, type, size, &p);
2598         if (r < 0)
2599                 return r;
2600 
2601         memcpy_safe(p, ptr, size);
2602 
2603         return 0;
2604 }
2605 
sd_bus_message_append_array_iovec(sd_bus_message * m,char type,const struct iovec * iov,unsigned n)2606 _public_ int sd_bus_message_append_array_iovec(
2607                 sd_bus_message *m,
2608                 char type,
2609                 const struct iovec *iov,
2610                 unsigned n /* should be size_t, but is API now… �� */) {
2611 
2612         size_t size;
2613         unsigned i;
2614         void *p;
2615         int r;
2616 
2617         assert_return(m, -EINVAL);
2618         assert_return(!m->sealed, -EPERM);
2619         assert_return(bus_type_is_trivial(type), -EINVAL);
2620         assert_return(iov || n == 0, -EINVAL);
2621         assert_return(!m->poisoned, -ESTALE);
2622 
2623         size = IOVEC_TOTAL_SIZE(iov, n);
2624 
2625         r = sd_bus_message_append_array_space(m, type, size, &p);
2626         if (r < 0)
2627                 return r;
2628 
2629         for (i = 0; i < n; i++) {
2630 
2631                 if (iov[i].iov_base)
2632                         memcpy(p, iov[i].iov_base, iov[i].iov_len);
2633                 else
2634                         memzero(p, iov[i].iov_len);
2635 
2636                 p = (uint8_t*) p + iov[i].iov_len;
2637         }
2638 
2639         return 0;
2640 }
2641 
sd_bus_message_append_array_memfd(sd_bus_message * m,char type,int memfd,uint64_t offset,uint64_t size)2642 _public_ int sd_bus_message_append_array_memfd(
2643                 sd_bus_message *m,
2644                 char type,
2645                 int memfd,
2646                 uint64_t offset,
2647                 uint64_t size) {
2648 
2649         _cleanup_close_ int copy_fd = -1;
2650         struct bus_body_part *part;
2651         ssize_t align, sz;
2652         uint64_t real_size;
2653         void *a;
2654         int r;
2655 
2656         assert_return(m, -EINVAL);
2657         assert_return(memfd >= 0, -EBADF);
2658         assert_return(bus_type_is_trivial(type), -EINVAL);
2659         assert_return(size > 0, -EINVAL);
2660         assert_return(!m->sealed, -EPERM);
2661         assert_return(!m->poisoned, -ESTALE);
2662 
2663         r = memfd_set_sealed(memfd);
2664         if (r < 0)
2665                 return r;
2666 
2667         copy_fd = fcntl(memfd, F_DUPFD_CLOEXEC, 3);
2668         if (copy_fd < 0)
2669                 return copy_fd;
2670 
2671         r = memfd_get_size(memfd, &real_size);
2672         if (r < 0)
2673                 return r;
2674 
2675         if (offset == 0 && size == UINT64_MAX)
2676                 size = real_size;
2677         else if (offset + size > real_size)
2678                 return -EMSGSIZE;
2679 
2680         align = bus_type_get_alignment(type);
2681         sz = bus_type_get_size(type);
2682 
2683         assert_se(align > 0);
2684         assert_se(sz > 0);
2685 
2686         if (offset % align != 0)
2687                 return -EINVAL;
2688 
2689         if (size % sz != 0)
2690                 return -EINVAL;
2691 
2692         if (size > (uint64_t) UINT32_MAX)
2693                 return -EINVAL;
2694 
2695         r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2696         if (r < 0)
2697                 return r;
2698 
2699         a = message_extend_body(m, align, 0, false, false);
2700         if (!a)
2701                 return -ENOMEM;
2702 
2703         part = message_append_part(m);
2704         if (!part)
2705                 return -ENOMEM;
2706 
2707         part->memfd = copy_fd;
2708         part->memfd_offset = offset;
2709         part->sealed = true;
2710         part->size = size;
2711         copy_fd = -1;
2712 
2713         m->body_size += size;
2714         message_extend_containers(m, size);
2715 
2716         return sd_bus_message_close_container(m);
2717 }
2718 
sd_bus_message_append_string_memfd(sd_bus_message * m,int memfd,uint64_t offset,uint64_t size)2719 _public_ int sd_bus_message_append_string_memfd(
2720                 sd_bus_message *m,
2721                 int memfd,
2722                 uint64_t offset,
2723                 uint64_t size) {
2724 
2725         _cleanup_close_ int copy_fd = -1;
2726         struct bus_body_part *part;
2727         struct bus_container *c;
2728         uint64_t real_size;
2729         void *a;
2730         int r;
2731 
2732         assert_return(m, -EINVAL);
2733         assert_return(memfd >= 0, -EBADF);
2734         assert_return(size > 0, -EINVAL);
2735         assert_return(!m->sealed, -EPERM);
2736         assert_return(!m->poisoned, -ESTALE);
2737 
2738         r = memfd_set_sealed(memfd);
2739         if (r < 0)
2740                 return r;
2741 
2742         copy_fd = fcntl(memfd, FD_CLOEXEC, 3);
2743         if (copy_fd < 0)
2744                 return copy_fd;
2745 
2746         r = memfd_get_size(memfd, &real_size);
2747         if (r < 0)
2748                 return r;
2749 
2750         if (offset == 0 && size == UINT64_MAX)
2751                 size = real_size;
2752         else if (offset + size > real_size)
2753                 return -EMSGSIZE;
2754 
2755         /* We require this to be NUL terminated */
2756         if (size == 0)
2757                 return -EINVAL;
2758 
2759         if (size > (uint64_t) UINT32_MAX)
2760                 return -EINVAL;
2761 
2762         c = message_get_last_container(m);
2763         if (c->signature && c->signature[c->index]) {
2764                 /* Container signature is already set */
2765 
2766                 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2767                         return -ENXIO;
2768         } else {
2769                 char *e;
2770 
2771                 /* Maybe we can append to the signature? But only if this is the top-level container */
2772                 if (c->enclosing != 0)
2773                         return -ENXIO;
2774 
2775                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING));
2776                 if (!e) {
2777                         m->poisoned = true;
2778                         return -ENOMEM;
2779                 }
2780         }
2781 
2782         if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2783                 a = message_extend_body(m, 4, 4, false, false);
2784                 if (!a)
2785                         return -ENOMEM;
2786 
2787                 *(uint32_t*) a = size - 1;
2788         }
2789 
2790         part = message_append_part(m);
2791         if (!part)
2792                 return -ENOMEM;
2793 
2794         part->memfd = copy_fd;
2795         part->memfd_offset = offset;
2796         part->sealed = true;
2797         part->size = size;
2798         copy_fd = -1;
2799 
2800         m->body_size += size;
2801         message_extend_containers(m, size);
2802 
2803         if (BUS_MESSAGE_IS_GVARIANT(m)) {
2804                 r = message_add_offset(m, m->body_size);
2805                 if (r < 0) {
2806                         m->poisoned = true;
2807                         return -ENOMEM;
2808                 }
2809         }
2810 
2811         if (c->enclosing != SD_BUS_TYPE_ARRAY)
2812                 c->index++;
2813 
2814         return 0;
2815 }
2816 
sd_bus_message_append_strv(sd_bus_message * m,char ** l)2817 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2818         int r;
2819 
2820         assert_return(m, -EINVAL);
2821         assert_return(!m->sealed, -EPERM);
2822         assert_return(!m->poisoned, -ESTALE);
2823 
2824         r = sd_bus_message_open_container(m, 'a', "s");
2825         if (r < 0)
2826                 return r;
2827 
2828         STRV_FOREACH(i, l) {
2829                 r = sd_bus_message_append_basic(m, 's', *i);
2830                 if (r < 0)
2831                         return r;
2832         }
2833 
2834         return sd_bus_message_close_container(m);
2835 }
2836 
bus_message_close_header(sd_bus_message * m)2837 static int bus_message_close_header(sd_bus_message *m) {
2838 
2839         assert(m);
2840 
2841         /* The actual user data is finished now, we just complete the
2842            variant and struct now (at least on gvariant). Remember
2843            this position, so that during parsing we know where to
2844            put the outer container end. */
2845         m->user_body_size = m->body_size;
2846 
2847         if (BUS_MESSAGE_IS_GVARIANT(m)) {
2848                 const char *signature;
2849                 size_t sz, l;
2850                 void *d;
2851 
2852                 /* Add offset table to end of fields array */
2853                 if (m->n_header_offsets >= 1) {
2854                         uint8_t *a;
2855                         unsigned i;
2856 
2857                         assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2858 
2859                         sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2860                         a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2861                         if (!a)
2862                                 return -ENOMEM;
2863 
2864                         for (i = 0; i < m->n_header_offsets; i++)
2865                                 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2866                 }
2867 
2868                 /* Add gvariant NUL byte plus signature to the end of
2869                  * the body, followed by the final offset pointing to
2870                  * the end of the fields array */
2871 
2872                 signature = strempty(m->root_container.signature);
2873                 l = strlen(signature);
2874 
2875                 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1);
2876                 d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true);
2877                 if (!d)
2878                         return -ENOMEM;
2879 
2880                 *(uint8_t*) d = 0;
2881                 *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN;
2882                 memcpy((uint8_t*) d + 2, signature, l);
2883                 *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END;
2884 
2885                 bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size);
2886 
2887                 m->footer = d;
2888                 m->footer_accessible = 1 + l + 2 + sz;
2889         } else {
2890                 m->header->dbus1.fields_size = m->fields_size;
2891                 m->header->dbus1.body_size = m->body_size;
2892         }
2893 
2894         return 0;
2895 }
2896 
sd_bus_message_seal(sd_bus_message * m,uint64_t cookie,uint64_t timeout_usec)2897 _public_ int sd_bus_message_seal(sd_bus_message *m, uint64_t cookie, uint64_t timeout_usec) {
2898         struct bus_body_part *part;
2899         size_t a;
2900         unsigned i;
2901         int r;
2902 
2903         assert_return(m, -EINVAL);
2904 
2905         if (m->sealed)
2906                 return -EPERM;
2907 
2908         if (m->n_containers > 0)
2909                 return -EBADMSG;
2910 
2911         if (m->poisoned)
2912                 return -ESTALE;
2913 
2914         if (cookie > 0xffffffffULL &&
2915             !BUS_MESSAGE_IS_GVARIANT(m))
2916                 return -EOPNOTSUPP;
2917 
2918         /* In vtables the return signature of method calls is listed,
2919          * let's check if they match if this is a response */
2920         if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2921             m->enforced_reply_signature &&
2922             !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2923                 return -ENOMSG;
2924 
2925         /* If gvariant marshalling is used we need to close the body structure */
2926         r = bus_message_close_struct(m, &m->root_container, false);
2927         if (r < 0)
2928                 return r;
2929 
2930         /* If there's a non-trivial signature set, then add it in
2931          * here, but only on dbus1 */
2932         if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2933                 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2934                 if (r < 0)
2935                         return r;
2936         }
2937 
2938         if (m->n_fds > 0) {
2939                 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2940                 if (r < 0)
2941                         return r;
2942         }
2943 
2944         r = bus_message_close_header(m);
2945         if (r < 0)
2946                 return r;
2947 
2948         if (BUS_MESSAGE_IS_GVARIANT(m))
2949                 m->header->dbus2.cookie = cookie;
2950         else
2951                 m->header->dbus1.serial = (uint32_t) cookie;
2952 
2953         m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout_usec;
2954 
2955         /* Add padding at the end of the fields part, since we know
2956          * the body needs to start at an 8 byte alignment. We made
2957          * sure we allocated enough space for this, so all we need to
2958          * do here is to zero it out. */
2959         a = ALIGN8(m->fields_size) - m->fields_size;
2960         if (a > 0)
2961                 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
2962 
2963         /* If this is something we can send as memfd, then let's seal
2964         the memfd now. Note that we can send memfds as payload only
2965         for directed messages, and not for broadcasts. */
2966         if (m->destination && m->bus->use_memfd) {
2967                 MESSAGE_FOREACH_PART(part, i, m)
2968                         if (part->memfd >= 0 &&
2969                             !part->sealed &&
2970                             (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
2971                             part != m->body_end) { /* The last part may never be sent as memfd */
2972                                 uint64_t sz;
2973 
2974                                 /* Try to seal it if that makes
2975                                  * sense. First, unmap our own map to
2976                                  * make sure we don't keep it busy. */
2977                                 bus_body_part_unmap(part);
2978 
2979                                 /* Then, sync up real memfd size */
2980                                 sz = part->size;
2981                                 r = memfd_set_size(part->memfd, sz);
2982                                 if (r < 0)
2983                                         return r;
2984 
2985                                 /* Finally, try to seal */
2986                                 if (memfd_set_sealed(part->memfd) >= 0)
2987                                         part->sealed = true;
2988                         }
2989         }
2990 
2991         m->root_container.end = m->user_body_size;
2992         m->root_container.index = 0;
2993         m->root_container.offset_index = 0;
2994         m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2995 
2996         m->sealed = true;
2997 
2998         return 0;
2999 }
3000 
bus_body_part_map(struct bus_body_part * part)3001 int bus_body_part_map(struct bus_body_part *part) {
3002         void *p;
3003         size_t psz, shift;
3004 
3005         assert_se(part);
3006 
3007         if (part->data)
3008                 return 0;
3009 
3010         if (part->size <= 0)
3011                 return 0;
3012 
3013         /* For smaller zero parts (as used for padding) we don't need to map anything... */
3014         if (part->memfd < 0 && part->is_zero && part->size < 8) {
3015                 static const uint8_t zeroes[7] = { };
3016                 part->data = (void*) zeroes;
3017                 return 0;
3018         }
3019 
3020         shift = PAGE_OFFSET(part->memfd_offset);
3021         psz = PAGE_ALIGN(part->size + shift);
3022 
3023         if (part->memfd >= 0)
3024                 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
3025         else if (part->is_zero)
3026                 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
3027         else
3028                 return -EINVAL;
3029 
3030         if (p == MAP_FAILED)
3031                 return -errno;
3032 
3033         part->mapped = psz;
3034         part->mmap_begin = p;
3035         part->data = (uint8_t*) p + shift;
3036         part->munmap_this = true;
3037 
3038         return 0;
3039 }
3040 
bus_body_part_unmap(struct bus_body_part * part)3041 void bus_body_part_unmap(struct bus_body_part *part) {
3042 
3043         assert_se(part);
3044 
3045         if (part->memfd < 0)
3046                 return;
3047 
3048         if (!part->mmap_begin)
3049                 return;
3050 
3051         if (!part->munmap_this)
3052                 return;
3053 
3054         assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3055 
3056         part->mmap_begin = NULL;
3057         part->data = NULL;
3058         part->mapped = 0;
3059         part->munmap_this = false;
3060 
3061         return;
3062 }
3063 
buffer_peek(const void * p,uint32_t sz,size_t * rindex,size_t align,size_t nbytes,void ** r)3064 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3065         size_t k, start, end;
3066 
3067         assert(rindex);
3068         assert(align > 0);
3069 
3070         start = ALIGN_TO((size_t) *rindex, align);
3071         end = start + nbytes;
3072 
3073         if (end > sz)
3074                 return -EBADMSG;
3075 
3076         /* Verify that padding is 0 */
3077         for (k = *rindex; k < start; k++)
3078                 if (((const uint8_t*) p)[k] != 0)
3079                         return -EBADMSG;
3080 
3081         if (r)
3082                 *r = (uint8_t*) p + start;
3083 
3084         *rindex = end;
3085 
3086         return 1;
3087 }
3088 
message_end_of_signature(sd_bus_message * m)3089 static bool message_end_of_signature(sd_bus_message *m) {
3090         struct bus_container *c;
3091 
3092         assert(m);
3093 
3094         c = message_get_last_container(m);
3095         return !c->signature || c->signature[c->index] == 0;
3096 }
3097 
message_end_of_array(sd_bus_message * m,size_t index)3098 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3099         struct bus_container *c;
3100 
3101         assert(m);
3102 
3103         c = message_get_last_container(m);
3104         if (c->enclosing != SD_BUS_TYPE_ARRAY)
3105                 return false;
3106 
3107         if (BUS_MESSAGE_IS_GVARIANT(m))
3108                 return index >= c->end;
3109         else {
3110                 assert(c->array_size);
3111                 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3112         }
3113 }
3114 
sd_bus_message_at_end(sd_bus_message * m,int complete)3115 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3116         assert_return(m, -EINVAL);
3117         assert_return(m->sealed, -EPERM);
3118 
3119         if (complete && m->n_containers > 0)
3120                 return false;
3121 
3122         if (message_end_of_signature(m))
3123                 return true;
3124 
3125         if (message_end_of_array(m, m->rindex))
3126                 return true;
3127 
3128         return false;
3129 }
3130 
find_part(sd_bus_message * m,size_t index,size_t sz,void ** p)3131 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3132         struct bus_body_part *part;
3133         size_t begin;
3134         int r;
3135 
3136         assert(m);
3137 
3138         if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3139                 part = m->cached_rindex_part;
3140                 begin = m->cached_rindex_part_begin;
3141         } else {
3142                 part = &m->body;
3143                 begin = 0;
3144         }
3145 
3146         while (part) {
3147                 if (index < begin)
3148                         return NULL;
3149 
3150                 if (index + sz <= begin + part->size) {
3151 
3152                         r = bus_body_part_map(part);
3153                         if (r < 0)
3154                                 return NULL;
3155 
3156                         if (p)
3157                                 *p = part->data ? (uint8_t*) part->data + index - begin
3158                                         : NULL; /* Avoid dereferencing a NULL pointer. */
3159 
3160                         m->cached_rindex_part = part;
3161                         m->cached_rindex_part_begin = begin;
3162 
3163                         return part;
3164                 }
3165 
3166                 begin += part->size;
3167                 part = part->next;
3168         }
3169 
3170         return NULL;
3171 }
3172 
container_next_item(sd_bus_message * m,struct bus_container * c,size_t * rindex)3173 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3174         int r;
3175 
3176         assert(m);
3177         assert(c);
3178         assert(rindex);
3179 
3180         if (!BUS_MESSAGE_IS_GVARIANT(m))
3181                 return 0;
3182 
3183         if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3184                 int sz;
3185 
3186                 sz = bus_gvariant_get_size(c->signature);
3187                 if (sz == 0)
3188                         return -EBADMSG;
3189                 if (sz < 0) {
3190                         int alignment;
3191 
3192                         if (c->offset_index+1 >= c->n_offsets)
3193                                 goto end;
3194 
3195                         /* Variable-size array */
3196 
3197                         alignment = bus_gvariant_get_alignment(c->signature);
3198                         assert(alignment > 0);
3199 
3200                         *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3201                         assert(c->offsets[c->offset_index+1] >= *rindex);
3202                         c->item_size = c->offsets[c->offset_index+1] - *rindex;
3203                 } else {
3204 
3205                         if (c->offset_index+1 >= (c->end-c->begin)/sz)
3206                                 goto end;
3207 
3208                         /* Fixed-size array */
3209                         *rindex = c->begin + (c->offset_index+1) * sz;
3210                         c->item_size = sz;
3211                 }
3212 
3213                 c->offset_index++;
3214 
3215         } else if (IN_SET(c->enclosing, 0, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) {
3216 
3217                 int alignment;
3218                 size_t n, j;
3219 
3220                 if (c->offset_index+1 >= c->n_offsets)
3221                         goto end;
3222 
3223                 r = signature_element_length(c->signature + c->index, &n);
3224                 if (r < 0)
3225                         return r;
3226 
3227                 r = signature_element_length(c->signature + c->index + n, &j);
3228                 if (r < 0)
3229                         return r;
3230                 else {
3231                         char t[j+1];
3232                         memcpy(t, c->signature + c->index + n, j);
3233                         t[j] = 0;
3234 
3235                         alignment = bus_gvariant_get_alignment(t);
3236                 }
3237 
3238                 assert(alignment > 0);
3239 
3240                 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3241                 assert(c->offsets[c->offset_index+1] >= *rindex);
3242                 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3243 
3244                 c->offset_index++;
3245 
3246         } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3247                 goto end;
3248         else
3249                 assert_not_reached();
3250 
3251         return 0;
3252 
3253 end:
3254         /* Reached the end */
3255         *rindex = c->end;
3256         c->item_size = 0;
3257         return 0;
3258 }
3259 
message_peek_body(sd_bus_message * m,size_t * rindex,size_t align,size_t nbytes,void ** ret)3260 static int message_peek_body(
3261                 sd_bus_message *m,
3262                 size_t *rindex,
3263                 size_t align,
3264                 size_t nbytes,
3265                 void **ret) {
3266 
3267         size_t k, start, end, padding;
3268         struct bus_body_part *part;
3269         uint8_t *q;
3270 
3271         assert(m);
3272         assert(rindex);
3273         assert(align > 0);
3274 
3275         start = ALIGN_TO((size_t) *rindex, align);
3276         padding = start - *rindex;
3277         end = start + nbytes;
3278 
3279         if (end > m->user_body_size)
3280                 return -EBADMSG;
3281 
3282         part = find_part(m, *rindex, padding, (void**) &q);
3283         if (!part)
3284                 return -EBADMSG;
3285 
3286         if (q) {
3287                 /* Verify padding */
3288                 for (k = 0; k < padding; k++)
3289                         if (q[k] != 0)
3290                                 return -EBADMSG;
3291         }
3292 
3293         part = find_part(m, start, nbytes, (void**) &q);
3294         if (!part || (nbytes > 0 && !q))
3295                 return -EBADMSG;
3296 
3297         *rindex = end;
3298 
3299         if (ret)
3300                 *ret = q;
3301 
3302         return 0;
3303 }
3304 
validate_nul(const char * s,size_t l)3305 static bool validate_nul(const char *s, size_t l) {
3306 
3307         /* Check for NUL chars in the string */
3308         if (memchr(s, 0, l))
3309                 return false;
3310 
3311         /* Check for NUL termination */
3312         if (s[l] != 0)
3313                 return false;
3314 
3315         return true;
3316 }
3317 
validate_string(const char * s,size_t l)3318 static bool validate_string(const char *s, size_t l) {
3319 
3320         if (!validate_nul(s, l))
3321                 return false;
3322 
3323         /* Check if valid UTF8 */
3324         if (!utf8_is_valid(s))
3325                 return false;
3326 
3327         return true;
3328 }
3329 
validate_signature(const char * s,size_t l)3330 static bool validate_signature(const char *s, size_t l) {
3331 
3332         if (!validate_nul(s, l))
3333                 return false;
3334 
3335         /* Check if valid signature */
3336         if (!signature_is_valid(s, true))
3337                 return false;
3338 
3339         return true;
3340 }
3341 
validate_object_path(const char * s,size_t l)3342 static bool validate_object_path(const char *s, size_t l) {
3343 
3344         if (!validate_nul(s, l))
3345                 return false;
3346 
3347         if (!object_path_is_valid(s))
3348                 return false;
3349 
3350         return true;
3351 }
3352 
sd_bus_message_read_basic(sd_bus_message * m,char type,void * p)3353 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3354         struct bus_container *c;
3355         size_t rindex;
3356         void *q;
3357         int r;
3358 
3359         assert_return(m, -EINVAL);
3360         assert_return(m->sealed, -EPERM);
3361         assert_return(bus_type_is_basic(type), -EINVAL);
3362 
3363         if (message_end_of_signature(m))
3364                 return -ENXIO;
3365 
3366         if (message_end_of_array(m, m->rindex))
3367                 return 0;
3368 
3369         c = message_get_last_container(m);
3370         if (c->signature[c->index] != type)
3371                 return -ENXIO;
3372 
3373         rindex = m->rindex;
3374 
3375         if (BUS_MESSAGE_IS_GVARIANT(m)) {
3376 
3377                 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3378                         bool ok;
3379 
3380                         /* D-Bus spec: The marshalling formats for the string-like types all end
3381                          * with a single zero (NUL) byte, but that byte is not considered to be part
3382                          * of the text. */
3383                         if (c->item_size == 0)
3384                                 return -EBADMSG;
3385 
3386                         r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3387                         if (r < 0)
3388                                 return r;
3389 
3390                         if (type == SD_BUS_TYPE_STRING)
3391                                 ok = validate_string(q, c->item_size-1);
3392                         else if (type == SD_BUS_TYPE_OBJECT_PATH)
3393                                 ok = validate_object_path(q, c->item_size-1);
3394                         else
3395                                 ok = validate_signature(q, c->item_size-1);
3396 
3397                         if (!ok)
3398                                 return -EBADMSG;
3399 
3400                         if (p)
3401                                 *(const char**) p = q;
3402                 } else {
3403                         int sz, align;
3404 
3405                         sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3406                         assert(sz > 0);
3407                         if ((size_t) sz != c->item_size)
3408                                 return -EBADMSG;
3409 
3410                         align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3411                         assert(align > 0);
3412 
3413                         r = message_peek_body(m, &rindex, align, c->item_size, &q);
3414                         if (r < 0)
3415                                 return r;
3416 
3417                         switch (type) {
3418 
3419                         case SD_BUS_TYPE_BYTE:
3420                                 if (p)
3421                                         *(uint8_t*) p = *(uint8_t*) q;
3422                                 break;
3423 
3424                         case SD_BUS_TYPE_BOOLEAN:
3425                                 if (p)
3426                                         *(int*) p = !!*(uint8_t*) q;
3427                                 break;
3428 
3429                         case SD_BUS_TYPE_INT16:
3430                         case SD_BUS_TYPE_UINT16:
3431                                 if (p)
3432                                         *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3433                                 break;
3434 
3435                         case SD_BUS_TYPE_INT32:
3436                         case SD_BUS_TYPE_UINT32:
3437                                 if (p)
3438                                         *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3439                                 break;
3440 
3441                         case SD_BUS_TYPE_INT64:
3442                         case SD_BUS_TYPE_UINT64:
3443                         case SD_BUS_TYPE_DOUBLE:
3444                                 if (p)
3445                                         *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3446                                 break;
3447 
3448                         case SD_BUS_TYPE_UNIX_FD: {
3449                                 uint32_t j;
3450 
3451                                 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3452                                 if (j >= m->n_fds)
3453                                         return -EBADMSG;
3454 
3455                                 if (p)
3456                                         *(int*) p = m->fds[j];
3457 
3458                                 break;
3459                         }
3460 
3461                         default:
3462                                 assert_not_reached();
3463                         }
3464                 }
3465 
3466                 r = container_next_item(m, c, &rindex);
3467                 if (r < 0)
3468                         return r;
3469         } else {
3470 
3471                 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3472                         uint32_t l;
3473                         bool ok;
3474 
3475                         r = message_peek_body(m, &rindex, 4, 4, &q);
3476                         if (r < 0)
3477                                 return r;
3478 
3479                         l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3480                         if (l == UINT32_MAX)
3481                                 /* avoid overflow right below */
3482                                 return -EBADMSG;
3483 
3484                         r = message_peek_body(m, &rindex, 1, l+1, &q);
3485                         if (r < 0)
3486                                 return r;
3487 
3488                         if (type == SD_BUS_TYPE_OBJECT_PATH)
3489                                 ok = validate_object_path(q, l);
3490                         else
3491                                 ok = validate_string(q, l);
3492                         if (!ok)
3493                                 return -EBADMSG;
3494 
3495                         if (p)
3496                                 *(const char**) p = q;
3497 
3498                 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3499                         uint8_t l;
3500 
3501                         r = message_peek_body(m, &rindex, 1, 1, &q);
3502                         if (r < 0)
3503                                 return r;
3504 
3505                         l = *(uint8_t*) q;
3506                         if (l == UINT8_MAX)
3507                                 /* avoid overflow right below */
3508                                 return -EBADMSG;
3509 
3510                         r = message_peek_body(m, &rindex, 1, l+1, &q);
3511                         if (r < 0)
3512                                 return r;
3513 
3514                         if (!validate_signature(q, l))
3515                                 return -EBADMSG;
3516 
3517                         if (p)
3518                                 *(const char**) p = q;
3519 
3520                 } else {
3521                         ssize_t sz, align;
3522 
3523                         align = bus_type_get_alignment(type);
3524                         assert(align > 0);
3525 
3526                         sz = bus_type_get_size(type);
3527                         assert(sz > 0);
3528 
3529                         r = message_peek_body(m, &rindex, align, sz, &q);
3530                         if (r < 0)
3531                                 return r;
3532 
3533                         switch (type) {
3534 
3535                         case SD_BUS_TYPE_BYTE:
3536                                 if (p)
3537                                         *(uint8_t*) p = *(uint8_t*) q;
3538                                 break;
3539 
3540                         case SD_BUS_TYPE_BOOLEAN:
3541                                 if (p)
3542                                         *(int*) p = !!*(uint32_t*) q;
3543                                 break;
3544 
3545                         case SD_BUS_TYPE_INT16:
3546                         case SD_BUS_TYPE_UINT16:
3547                                 if (p)
3548                                         *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3549                                 break;
3550 
3551                         case SD_BUS_TYPE_INT32:
3552                         case SD_BUS_TYPE_UINT32:
3553                                 if (p)
3554                                         *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3555                                 break;
3556 
3557                         case SD_BUS_TYPE_INT64:
3558                         case SD_BUS_TYPE_UINT64:
3559                         case SD_BUS_TYPE_DOUBLE:
3560                                 if (p)
3561                                         *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3562                                 break;
3563 
3564                         case SD_BUS_TYPE_UNIX_FD: {
3565                                 uint32_t j;
3566 
3567                                 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3568                                 if (j >= m->n_fds)
3569                                         return -EBADMSG;
3570 
3571                                 if (p)
3572                                         *(int*) p = m->fds[j];
3573                                 break;
3574                         }
3575 
3576                         default:
3577                                 assert_not_reached();
3578                         }
3579                 }
3580         }
3581 
3582         m->rindex = rindex;
3583 
3584         if (c->enclosing != SD_BUS_TYPE_ARRAY)
3585                 c->index++;
3586 
3587         return 1;
3588 }
3589 
bus_message_enter_array(sd_bus_message * m,struct bus_container * c,const char * contents,uint32_t ** array_size,size_t * item_size,size_t ** offsets,size_t * n_offsets)3590 static int bus_message_enter_array(
3591                 sd_bus_message *m,
3592                 struct bus_container *c,
3593                 const char *contents,
3594                 uint32_t **array_size,
3595                 size_t *item_size,
3596                 size_t **offsets,
3597                 size_t *n_offsets) {
3598 
3599         size_t rindex;
3600         void *q;
3601         int r;
3602 
3603         assert(m);
3604         assert(c);
3605         assert(contents);
3606         assert(array_size);
3607         assert(item_size);
3608         assert(offsets);
3609         assert(n_offsets);
3610 
3611         if (!signature_is_single(contents, true))
3612                 return -EINVAL;
3613 
3614         if (!c->signature || c->signature[c->index] == 0)
3615                 return -ENXIO;
3616 
3617         if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3618                 return -ENXIO;
3619 
3620         if (!startswith(c->signature + c->index + 1, contents))
3621                 return -ENXIO;
3622 
3623         rindex = m->rindex;
3624 
3625         if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3626                 /* dbus1 */
3627                 int alignment;
3628 
3629                 r = message_peek_body(m, &rindex, 4, 4, &q);
3630                 if (r < 0)
3631                         return r;
3632 
3633                 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3634                         return -EBADMSG;
3635 
3636                 alignment = bus_type_get_alignment(contents[0]);
3637                 if (alignment < 0)
3638                         return alignment;
3639 
3640                 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3641                 if (r < 0)
3642                         return r;
3643 
3644                 *array_size = (uint32_t*) q;
3645 
3646         } else if (c->item_size <= 0) {
3647 
3648                 /* gvariant: empty array */
3649                 *item_size = 0;
3650                 *offsets = NULL;
3651                 *n_offsets = 0;
3652 
3653         } else if (bus_gvariant_is_fixed_size(contents)) {
3654 
3655                 /* gvariant: fixed length array */
3656                 *item_size = bus_gvariant_get_size(contents);
3657                 *offsets = NULL;
3658                 *n_offsets = 0;
3659 
3660         } else {
3661                 size_t where, previous = 0, framing, sz;
3662                 int alignment;
3663                 unsigned i;
3664 
3665                 /* gvariant: variable length array */
3666                 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3667 
3668                 where = rindex + c->item_size - sz;
3669                 r = message_peek_body(m, &where, 1, sz, &q);
3670                 if (r < 0)
3671                         return r;
3672 
3673                 framing = bus_gvariant_read_word_le(q, sz);
3674                 if (framing > c->item_size - sz)
3675                         return -EBADMSG;
3676                 if ((c->item_size - framing) % sz != 0)
3677                         return -EBADMSG;
3678 
3679                 *n_offsets = (c->item_size - framing) / sz;
3680 
3681                 where = rindex + framing;
3682                 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3683                 if (r < 0)
3684                         return r;
3685 
3686                 *offsets = new(size_t, *n_offsets);
3687                 if (!*offsets)
3688                         return -ENOMEM;
3689 
3690                 alignment = bus_gvariant_get_alignment(c->signature);
3691                 assert(alignment > 0);
3692 
3693                 for (i = 0; i < *n_offsets; i++) {
3694                         size_t x, start;
3695 
3696                         start = ALIGN_TO(previous, alignment);
3697 
3698                         x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3699                         if (x > c->item_size - sz)
3700                                 return -EBADMSG;
3701                         if (x < start)
3702                                 return -EBADMSG;
3703 
3704                         (*offsets)[i] = rindex + x;
3705                         previous = x;
3706                 }
3707 
3708                 *item_size = (*offsets)[0] - rindex;
3709         }
3710 
3711         m->rindex = rindex;
3712 
3713         if (c->enclosing != SD_BUS_TYPE_ARRAY)
3714                 c->index += 1 + strlen(contents);
3715 
3716         return 1;
3717 }
3718 
bus_message_enter_variant(sd_bus_message * m,struct bus_container * c,const char * contents,size_t * item_size)3719 static int bus_message_enter_variant(
3720                 sd_bus_message *m,
3721                 struct bus_container *c,
3722                 const char *contents,
3723                 size_t *item_size) {
3724 
3725         size_t rindex;
3726         uint8_t l;
3727         void *q;
3728         int r;
3729 
3730         assert(m);
3731         assert(c);
3732         assert(contents);
3733         assert(item_size);
3734 
3735         if (!signature_is_single(contents, false))
3736                 return -EINVAL;
3737 
3738         if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3739                 return -EINVAL;
3740 
3741         if (!c->signature || c->signature[c->index] == 0)
3742                 return -ENXIO;
3743 
3744         if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3745                 return -ENXIO;
3746 
3747         rindex = m->rindex;
3748 
3749         if (BUS_MESSAGE_IS_GVARIANT(m)) {
3750                 size_t k, where;
3751 
3752                 k = strlen(contents);
3753                 if (1+k > c->item_size)
3754                         return -EBADMSG;
3755 
3756                 where = rindex + c->item_size - (1+k);
3757                 r = message_peek_body(m, &where, 1, 1+k, &q);
3758                 if (r < 0)
3759                         return r;
3760 
3761                 if (*(char*) q != 0)
3762                         return -EBADMSG;
3763 
3764                 if (memcmp((uint8_t*) q+1, contents, k))
3765                         return -ENXIO;
3766 
3767                 *item_size = c->item_size - (1+k);
3768 
3769         } else {
3770                 r = message_peek_body(m, &rindex, 1, 1, &q);
3771                 if (r < 0)
3772                         return r;
3773 
3774                 l = *(uint8_t*) q;
3775                 if (l == UINT8_MAX)
3776                         /* avoid overflow right below */
3777                         return -EBADMSG;
3778 
3779                 r = message_peek_body(m, &rindex, 1, l+1, &q);
3780                 if (r < 0)
3781                         return r;
3782 
3783                 if (!validate_signature(q, l))
3784                         return -EBADMSG;
3785 
3786                 if (!streq(q, contents))
3787                         return -ENXIO;
3788         }
3789 
3790         m->rindex = rindex;
3791 
3792         if (c->enclosing != SD_BUS_TYPE_ARRAY)
3793                 c->index++;
3794 
3795         return 1;
3796 }
3797 
build_struct_offsets(sd_bus_message * m,const char * signature,size_t size,size_t * item_size,size_t ** offsets,size_t * n_offsets)3798 static int build_struct_offsets(
3799                 sd_bus_message *m,
3800                 const char *signature,
3801                 size_t size,
3802                 size_t *item_size,
3803                 size_t **offsets,
3804                 size_t *n_offsets) {
3805 
3806         unsigned n_variable = 0, n_total = 0, v;
3807         size_t previous, where;
3808         const char *p;
3809         size_t sz;
3810         void *q;
3811         int r;
3812 
3813         assert(m);
3814         assert(item_size);
3815         assert(offsets);
3816         assert(n_offsets);
3817 
3818         if (isempty(signature)) {
3819                 /* Unary type is encoded as *fixed* 1 byte padding */
3820                 r = message_peek_body(m, &m->rindex, 1, 1, &q);
3821                 if (r < 0)
3822                         return r;
3823 
3824                 if (*(uint8_t *) q != 0)
3825                         return -EBADMSG;
3826 
3827                 *item_size = 0;
3828                 *offsets = NULL;
3829                 *n_offsets = 0;
3830                 return 0;
3831         }
3832 
3833         sz = bus_gvariant_determine_word_size(size, 0);
3834         if (sz <= 0)
3835                 return -EBADMSG;
3836 
3837         /* First, loop over signature and count variable elements and
3838          * elements in general. We use this to know how large the
3839          * offset array is at the end of the structure. Note that
3840          * GVariant only stores offsets for all variable size elements
3841          * that are not the last item. */
3842 
3843         p = signature;
3844         while (*p != 0) {
3845                 size_t n;
3846 
3847                 r = signature_element_length(p, &n);
3848                 if (r < 0)
3849                         return r;
3850                 else {
3851                         char t[n+1];
3852 
3853                         memcpy(t, p, n);
3854                         t[n] = 0;
3855 
3856                         r = bus_gvariant_is_fixed_size(t);
3857                 }
3858 
3859                 if (r < 0)
3860                         return r;
3861                 if (r == 0 && p[n] != 0) /* except the last item */
3862                         n_variable++;
3863                 n_total++;
3864 
3865                 p += n;
3866         }
3867 
3868         if (size < n_variable * sz)
3869                 return -EBADMSG;
3870 
3871         where = m->rindex + size - (n_variable * sz);
3872         r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3873         if (r < 0)
3874                 return r;
3875 
3876         v = n_variable;
3877 
3878         *offsets = new(size_t, n_total);
3879         if (!*offsets)
3880                 return -ENOMEM;
3881 
3882         *n_offsets = 0;
3883 
3884         /* Second, loop again and build an offset table */
3885         p = signature;
3886         previous = m->rindex;
3887         while (*p != 0) {
3888                 size_t n, offset;
3889                 int k;
3890 
3891                 r = signature_element_length(p, &n);
3892                 if (r < 0)
3893                         return r;
3894                 else {
3895                         char t[n+1];
3896 
3897                         memcpy(t, p, n);
3898                         t[n] = 0;
3899 
3900                         size_t align = bus_gvariant_get_alignment(t);
3901                         assert(align > 0);
3902 
3903                         /* The possible start of this member after including alignment */
3904                         size_t start = ALIGN_TO(previous, align);
3905 
3906                         k = bus_gvariant_get_size(t);
3907                         if (k < 0) {
3908                                 size_t x;
3909 
3910                                 /* Variable size */
3911                                 if (v > 0) {
3912                                         v--;
3913 
3914                                         x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3915                                         if (x >= size)
3916                                                 return -EBADMSG;
3917                                 } else
3918                                         /* The last item's end is determined
3919                                          * from the start of the offset array */
3920                                         x = size - (n_variable * sz);
3921 
3922                                 offset = m->rindex + x;
3923                                 if (offset < start)
3924                                         return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
3925                                                                "For type %s with alignment %zu, message specifies offset %zu which is smaller than previous end %zu + alignment = %zu",
3926                                                                t, align,
3927                                                                offset,
3928                                                                previous,
3929                                                                start);
3930                         } else
3931                                 /* Fixed size */
3932                                 offset = start + k;
3933                 }
3934 
3935                 previous = (*offsets)[(*n_offsets)++] = offset;
3936                 p += n;
3937         }
3938 
3939         assert(v == 0);
3940         assert(*n_offsets == n_total);
3941 
3942         *item_size = (*offsets)[0] - m->rindex;
3943         return 0;
3944 }
3945 
enter_struct_or_dict_entry(sd_bus_message * m,struct bus_container * c,const char * contents,size_t * item_size,size_t ** offsets,size_t * n_offsets)3946 static int enter_struct_or_dict_entry(
3947                 sd_bus_message *m,
3948                 struct bus_container *c,
3949                 const char *contents,
3950                 size_t *item_size,
3951                 size_t **offsets,
3952                 size_t *n_offsets) {
3953 
3954         int r;
3955 
3956         assert(m);
3957         assert(c);
3958         assert(contents);
3959         assert(item_size);
3960         assert(offsets);
3961         assert(n_offsets);
3962 
3963         if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3964 
3965                 /* dbus1 */
3966                 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3967                 if (r < 0)
3968                         return r;
3969 
3970         } else
3971                 /* gvariant with contents */
3972                 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3973 
3974         return 0;
3975 }
3976 
bus_message_enter_struct(sd_bus_message * m,struct bus_container * c,const char * contents,size_t * item_size,size_t ** offsets,size_t * n_offsets)3977 static int bus_message_enter_struct(
3978                 sd_bus_message *m,
3979                 struct bus_container *c,
3980                 const char *contents,
3981                 size_t *item_size,
3982                 size_t **offsets,
3983                 size_t *n_offsets) {
3984 
3985         size_t l;
3986         int r;
3987 
3988         assert(m);
3989         assert(c);
3990         assert(contents);
3991         assert(item_size);
3992         assert(offsets);
3993         assert(n_offsets);
3994 
3995         if (!signature_is_valid(contents, false))
3996                 return -EINVAL;
3997 
3998         if (!c->signature || c->signature[c->index] == 0)
3999                 return -ENXIO;
4000 
4001         l = strlen(contents);
4002 
4003         if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
4004             !startswith(c->signature + c->index + 1, contents) ||
4005             c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
4006                 return -ENXIO;
4007 
4008         r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4009         if (r < 0)
4010                 return r;
4011 
4012         if (c->enclosing != SD_BUS_TYPE_ARRAY)
4013                 c->index += 1 + l + 1;
4014 
4015         return 1;
4016 }
4017 
bus_message_enter_dict_entry(sd_bus_message * m,struct bus_container * c,const char * contents,size_t * item_size,size_t ** offsets,size_t * n_offsets)4018 static int bus_message_enter_dict_entry(
4019                 sd_bus_message *m,
4020                 struct bus_container *c,
4021                 const char *contents,
4022                 size_t *item_size,
4023                 size_t **offsets,
4024                 size_t *n_offsets) {
4025 
4026         size_t l;
4027         int r;
4028 
4029         assert(m);
4030         assert(c);
4031         assert(contents);
4032 
4033         if (!signature_is_pair(contents))
4034                 return -EINVAL;
4035 
4036         if (c->enclosing != SD_BUS_TYPE_ARRAY)
4037                 return -ENXIO;
4038 
4039         if (!c->signature || c->signature[c->index] == 0)
4040                 return 0;
4041 
4042         l = strlen(contents);
4043 
4044         if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
4045             !startswith(c->signature + c->index + 1, contents) ||
4046             c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
4047                 return -ENXIO;
4048 
4049         r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4050         if (r < 0)
4051                 return r;
4052 
4053         if (c->enclosing != SD_BUS_TYPE_ARRAY)
4054                 c->index += 1 + l + 1;
4055 
4056         return 1;
4057 }
4058 
sd_bus_message_enter_container(sd_bus_message * m,char type,const char * contents)4059 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
4060                                             char type,
4061                                             const char *contents) {
4062         struct bus_container *c;
4063         uint32_t *array_size = NULL;
4064         _cleanup_free_ char *signature = NULL;
4065         size_t before, end;
4066         _cleanup_free_ size_t *offsets = NULL;
4067         size_t n_offsets = 0, item_size = 0;
4068         int r;
4069 
4070         assert_return(m, -EINVAL);
4071         assert_return(m->sealed, -EPERM);
4072         assert_return(type != 0 || !contents, -EINVAL);
4073 
4074         if (type == 0 || !contents) {
4075                 const char *cc;
4076                 char tt;
4077 
4078                 /* Allow entering into anonymous containers */
4079                 r = sd_bus_message_peek_type(m, &tt, &cc);
4080                 if (r < 0)
4081                         return r;
4082 
4083                 if (type != 0 && type != tt)
4084                         return -ENXIO;
4085 
4086                 if (contents && !streq(contents, cc))
4087                         return -ENXIO;
4088 
4089                 type = tt;
4090                 contents = cc;
4091         }
4092 
4093         /*
4094          * We enforce a global limit on container depth, that is much
4095          * higher than the 32 structs and 32 arrays the specification
4096          * mandates. This is simpler to implement for us, and we need
4097          * this only to ensure our container array doesn't grow
4098          * without bounds. We are happy to return any data from a
4099          * message as long as the data itself is valid, even if the
4100          * overall message might be not.
4101          *
4102          * Note that the message signature is validated when
4103          * parsing the headers, and that validation does check the
4104          * 32/32 limit.
4105          *
4106          * Note that the specification defines no limits on the depth
4107          * of stacked variants, but we do.
4108          */
4109         if (m->n_containers >= BUS_CONTAINER_DEPTH)
4110                 return -EBADMSG;
4111 
4112         if (!GREEDY_REALLOC(m->containers, m->n_containers + 1))
4113                 return -ENOMEM;
4114 
4115         if (message_end_of_signature(m))
4116                 return -ENXIO;
4117 
4118         if (message_end_of_array(m, m->rindex))
4119                 return 0;
4120 
4121         c = message_get_last_container(m);
4122 
4123         signature = strdup(contents);
4124         if (!signature)
4125                 return -ENOMEM;
4126 
4127         c->saved_index = c->index;
4128         before = m->rindex;
4129 
4130         if (type == SD_BUS_TYPE_ARRAY)
4131                 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4132         else if (type == SD_BUS_TYPE_VARIANT)
4133                 r = bus_message_enter_variant(m, c, contents, &item_size);
4134         else if (type == SD_BUS_TYPE_STRUCT)
4135                 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4136         else if (type == SD_BUS_TYPE_DICT_ENTRY)
4137                 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4138         else
4139                 r = -EINVAL;
4140         if (r <= 0)
4141                 return r;
4142 
4143         /* OK, let's fill it in */
4144         if (BUS_MESSAGE_IS_GVARIANT(m) &&
4145             type == SD_BUS_TYPE_STRUCT &&
4146             isempty(signature))
4147                 end = m->rindex + 0;
4148         else
4149                 end = m->rindex + c->item_size;
4150 
4151         m->containers[m->n_containers++] = (struct bus_container) {
4152                  .enclosing = type,
4153                  .signature = TAKE_PTR(signature),
4154 
4155                  .before = before,
4156                  .begin = m->rindex,
4157                  /* Unary type has fixed size of 1, but virtual size of 0 */
4158                  .end = end,
4159                  .array_size = array_size,
4160                  .item_size = item_size,
4161                  .offsets = TAKE_PTR(offsets),
4162                  .n_offsets = n_offsets,
4163         };
4164 
4165         return 1;
4166 }
4167 
sd_bus_message_exit_container(sd_bus_message * m)4168 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4169         struct bus_container *c;
4170         unsigned saved;
4171         int r;
4172 
4173         assert_return(m, -EINVAL);
4174         assert_return(m->sealed, -EPERM);
4175         assert_return(m->n_containers > 0, -ENXIO);
4176 
4177         c = message_get_last_container(m);
4178 
4179         if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4180                 if (c->signature && c->signature[c->index] != 0)
4181                         return -EBUSY;
4182         }
4183 
4184         if (BUS_MESSAGE_IS_GVARIANT(m)) {
4185                 if (m->rindex < c->end)
4186                         return -EBUSY;
4187 
4188         } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4189                 uint32_t l;
4190 
4191                 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4192                 if (c->begin + l != m->rindex)
4193                         return -EBUSY;
4194         }
4195 
4196         message_free_last_container(m);
4197 
4198         c = message_get_last_container(m);
4199         saved = c->index;
4200         c->index = c->saved_index;
4201         r = container_next_item(m, c, &m->rindex);
4202         c->index = saved;
4203         if (r < 0)
4204                 return r;
4205 
4206         return 1;
4207 }
4208 
message_quit_container(sd_bus_message * m)4209 static void message_quit_container(sd_bus_message *m) {
4210         struct bus_container *c;
4211 
4212         assert(m);
4213         assert(m->sealed);
4214         assert(m->n_containers > 0);
4215 
4216         /* Undo seeks */
4217         c = message_get_last_container(m);
4218         assert(m->rindex >= c->before);
4219         m->rindex = c->before;
4220 
4221         /* Free container */
4222         message_free_last_container(m);
4223 
4224         /* Correct index of new top-level container */
4225         c = message_get_last_container(m);
4226         c->index = c->saved_index;
4227 }
4228 
sd_bus_message_peek_type(sd_bus_message * m,char * type,const char ** contents)4229 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4230         struct bus_container *c;
4231         int r;
4232 
4233         assert_return(m, -EINVAL);
4234         assert_return(m->sealed, -EPERM);
4235 
4236         if (message_end_of_signature(m))
4237                 goto eof;
4238 
4239         if (message_end_of_array(m, m->rindex))
4240                 goto eof;
4241 
4242         c = message_get_last_container(m);
4243 
4244         if (bus_type_is_basic(c->signature[c->index])) {
4245                 if (contents)
4246                         *contents = NULL;
4247                 if (type)
4248                         *type = c->signature[c->index];
4249                 return 1;
4250         }
4251 
4252         if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4253 
4254                 if (contents) {
4255                         size_t l;
4256 
4257                         r = signature_element_length(c->signature+c->index+1, &l);
4258                         if (r < 0)
4259                                 return r;
4260 
4261                         /* signature_element_length does verification internally */
4262 
4263                         /* The array element must not be empty */
4264                         assert(l >= 1);
4265                         if (free_and_strndup(&c->peeked_signature,
4266                                              c->signature + c->index + 1, l) < 0)
4267                                 return -ENOMEM;
4268 
4269                         *contents = c->peeked_signature;
4270                 }
4271 
4272                 if (type)
4273                         *type = SD_BUS_TYPE_ARRAY;
4274 
4275                 return 1;
4276         }
4277 
4278         if (IN_SET(c->signature[c->index], SD_BUS_TYPE_STRUCT_BEGIN, SD_BUS_TYPE_DICT_ENTRY_BEGIN)) {
4279 
4280                 if (contents) {
4281                         size_t l;
4282 
4283                         r = signature_element_length(c->signature+c->index, &l);
4284                         if (r < 0)
4285                                 return r;
4286 
4287                         assert(l >= 3);
4288                         if (free_and_strndup(&c->peeked_signature,
4289                                              c->signature + c->index + 1, l - 2) < 0)
4290                                 return -ENOMEM;
4291 
4292                         *contents = c->peeked_signature;
4293                 }
4294 
4295                 if (type)
4296                         *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4297 
4298                 return 1;
4299         }
4300 
4301         if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4302                 if (contents) {
4303                         void *q;
4304 
4305                         if (BUS_MESSAGE_IS_GVARIANT(m)) {
4306                                 size_t k;
4307 
4308                                 if (c->item_size < 2)
4309                                         return -EBADMSG;
4310 
4311                                 /* Look for the NUL delimiter that
4312                                    separates the payload from the
4313                                    signature. Since the body might be
4314                                    in a different part that then the
4315                                    signature we map byte by byte. */
4316 
4317                                 for (k = 2; k <= c->item_size; k++) {
4318                                         size_t where;
4319 
4320                                         where = m->rindex + c->item_size - k;
4321                                         r = message_peek_body(m, &where, 1, k, &q);
4322                                         if (r < 0)
4323                                                 return r;
4324 
4325                                         if (*(char*) q == 0)
4326                                                 break;
4327                                 }
4328 
4329                                 if (k > c->item_size)
4330                                         return -EBADMSG;
4331 
4332                                 if (free_and_strndup(&c->peeked_signature,
4333                                                      (char*) q + 1, k - 1) < 0)
4334                                         return -ENOMEM;
4335 
4336                                 if (!signature_is_valid(c->peeked_signature, true))
4337                                         return -EBADMSG;
4338 
4339                                 *contents = c->peeked_signature;
4340                         } else {
4341                                 size_t rindex, l;
4342 
4343                                 rindex = m->rindex;
4344                                 r = message_peek_body(m, &rindex, 1, 1, &q);
4345                                 if (r < 0)
4346                                         return r;
4347 
4348                                 l = *(uint8_t*) q;
4349                                 if (l == UINT8_MAX)
4350                                         /* avoid overflow right below */
4351                                         return -EBADMSG;
4352 
4353                                 r = message_peek_body(m, &rindex, 1, l+1, &q);
4354                                 if (r < 0)
4355                                         return r;
4356 
4357                                 if (!validate_signature(q, l))
4358                                         return -EBADMSG;
4359 
4360                                 *contents = q;
4361                         }
4362                 }
4363 
4364                 if (type)
4365                         *type = SD_BUS_TYPE_VARIANT;
4366 
4367                 return 1;
4368         }
4369 
4370         return -EINVAL;
4371 
4372 eof:
4373         if (type)
4374                 *type = 0;
4375         if (contents)
4376                 *contents = NULL;
4377         return 0;
4378 }
4379 
sd_bus_message_rewind(sd_bus_message * m,int complete)4380 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4381         struct bus_container *c;
4382 
4383         assert_return(m, -EINVAL);
4384         assert_return(m->sealed, -EPERM);
4385 
4386         if (complete) {
4387                 message_reset_containers(m);
4388                 m->rindex = 0;
4389 
4390                 c = message_get_last_container(m);
4391         } else {
4392                 c = message_get_last_container(m);
4393 
4394                 c->index = 0;
4395                 m->rindex = c->begin;
4396         }
4397 
4398         c->offset_index = 0;
4399         c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4400 
4401         return !isempty(c->signature);
4402 }
4403 
sd_bus_message_readv(sd_bus_message * m,const char * types,va_list ap)4404 _public_ int sd_bus_message_readv(
4405                 sd_bus_message *m,
4406                 const char *types,
4407                 va_list ap) {
4408 
4409         unsigned n_array, n_struct;
4410         TypeStack stack[BUS_CONTAINER_DEPTH];
4411         unsigned stack_ptr = 0;
4412         unsigned n_loop = 0;
4413         int r;
4414 
4415         assert_return(m, -EINVAL);
4416         assert_return(m->sealed, -EPERM);
4417         assert_return(types, -EINVAL);
4418 
4419         if (isempty(types))
4420                 return 0;
4421 
4422         /* Ideally, we'd just call ourselves recursively on every
4423          * complex type. However, the state of a va_list that is
4424          * passed to a function is undefined after that function
4425          * returns. This means we need to decode the va_list linearly
4426          * in a single stackframe. We hence implement our own
4427          * home-grown stack in an array. */
4428 
4429         n_array = UINT_MAX; /* length of current array entries */
4430         n_struct = strlen(types); /* length of current struct contents signature */
4431 
4432         for (;;) {
4433                 const char *t;
4434 
4435                 n_loop++;
4436 
4437                 if (n_array == 0 || (n_array == UINT_MAX && n_struct == 0)) {
4438                         r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4439                         if (r < 0)
4440                                 return r;
4441                         if (r == 0)
4442                                 break;
4443 
4444                         r = sd_bus_message_exit_container(m);
4445                         if (r < 0)
4446                                 return r;
4447 
4448                         continue;
4449                 }
4450 
4451                 t = types;
4452                 if (n_array != UINT_MAX)
4453                         n_array--;
4454                 else {
4455                         types++;
4456                         n_struct--;
4457                 }
4458 
4459                 switch (*t) {
4460 
4461                 case SD_BUS_TYPE_BYTE:
4462                 case SD_BUS_TYPE_BOOLEAN:
4463                 case SD_BUS_TYPE_INT16:
4464                 case SD_BUS_TYPE_UINT16:
4465                 case SD_BUS_TYPE_INT32:
4466                 case SD_BUS_TYPE_UINT32:
4467                 case SD_BUS_TYPE_INT64:
4468                 case SD_BUS_TYPE_UINT64:
4469                 case SD_BUS_TYPE_DOUBLE:
4470                 case SD_BUS_TYPE_STRING:
4471                 case SD_BUS_TYPE_OBJECT_PATH:
4472                 case SD_BUS_TYPE_SIGNATURE:
4473                 case SD_BUS_TYPE_UNIX_FD: {
4474                         void *p;
4475 
4476                         p = va_arg(ap, void*);
4477                         r = sd_bus_message_read_basic(m, *t, p);
4478                         if (r < 0)
4479                                 return r;
4480                         if (r == 0) {
4481                                 if (n_loop <= 1)
4482                                         return 0;
4483 
4484                                 return -ENXIO;
4485                         }
4486 
4487                         break;
4488                 }
4489 
4490                 case SD_BUS_TYPE_ARRAY: {
4491                         size_t k;
4492 
4493                         r = signature_element_length(t + 1, &k);
4494                         if (r < 0)
4495                                 return r;
4496 
4497                         {
4498                                 char s[k + 1];
4499                                 memcpy(s, t + 1, k);
4500                                 s[k] = 0;
4501 
4502                                 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4503                                 if (r < 0)
4504                                         return r;
4505                                 if (r == 0) {
4506                                         if (n_loop <= 1)
4507                                                 return 0;
4508 
4509                                         return -ENXIO;
4510                                 }
4511                         }
4512 
4513                         if (n_array == UINT_MAX) {
4514                                 types += k;
4515                                 n_struct -= k;
4516                         }
4517 
4518                         r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4519                         if (r < 0)
4520                                 return r;
4521 
4522                         types = t + 1;
4523                         n_struct = k;
4524                         n_array = va_arg(ap, unsigned);
4525 
4526                         break;
4527                 }
4528 
4529                 case SD_BUS_TYPE_VARIANT: {
4530                         const char *s;
4531 
4532                         s = va_arg(ap, const char *);
4533                         if (!s)
4534                                 return -EINVAL;
4535 
4536                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4537                         if (r < 0)
4538                                 return r;
4539                         if (r == 0) {
4540                                 if (n_loop <= 1)
4541                                         return 0;
4542 
4543                                 return -ENXIO;
4544                         }
4545 
4546                         r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4547                         if (r < 0)
4548                                 return r;
4549 
4550                         types = s;
4551                         n_struct = strlen(s);
4552                         n_array = UINT_MAX;
4553 
4554                         break;
4555                 }
4556 
4557                 case SD_BUS_TYPE_STRUCT_BEGIN:
4558                 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4559                         size_t k;
4560 
4561                         r = signature_element_length(t, &k);
4562                         if (r < 0)
4563                                 return r;
4564 
4565                         {
4566                                 char s[k - 1];
4567                                 memcpy(s, t + 1, k - 2);
4568                                 s[k - 2] = 0;
4569 
4570                                 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4571                                 if (r < 0)
4572                                         return r;
4573                                 if (r == 0) {
4574                                         if (n_loop <= 1)
4575                                                 return 0;
4576                                         return -ENXIO;
4577                                 }
4578                         }
4579 
4580                         if (n_array == UINT_MAX) {
4581                                 types += k - 1;
4582                                 n_struct -= k - 1;
4583                         }
4584 
4585                         r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4586                         if (r < 0)
4587                                 return r;
4588 
4589                         types = t + 1;
4590                         n_struct = k - 2;
4591                         n_array = UINT_MAX;
4592 
4593                         break;
4594                 }
4595 
4596                 default:
4597                         return -EINVAL;
4598                 }
4599         }
4600 
4601         return 1;
4602 }
4603 
sd_bus_message_read(sd_bus_message * m,const char * types,...)4604 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4605         va_list ap;
4606         int r;
4607 
4608         va_start(ap, types);
4609         r = sd_bus_message_readv(m, types, ap);
4610         va_end(ap);
4611 
4612         return r;
4613 }
4614 
sd_bus_message_skip(sd_bus_message * m,const char * types)4615 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4616         int r;
4617 
4618         assert_return(m, -EINVAL);
4619         assert_return(m->sealed, -EPERM);
4620 
4621         /* If types is NULL, read exactly one element */
4622         if (!types) {
4623                 struct bus_container *c;
4624                 size_t l;
4625 
4626                 if (message_end_of_signature(m))
4627                         return -ENXIO;
4628 
4629                 if (message_end_of_array(m, m->rindex))
4630                         return 0;
4631 
4632                 c = message_get_last_container(m);
4633 
4634                 r = signature_element_length(c->signature + c->index, &l);
4635                 if (r < 0)
4636                         return r;
4637 
4638                 types = strndupa_safe(c->signature + c->index, l);
4639         }
4640 
4641         switch (*types) {
4642 
4643         case 0: /* Nothing to drop */
4644                 return 0;
4645 
4646         case SD_BUS_TYPE_BYTE:
4647         case SD_BUS_TYPE_BOOLEAN:
4648         case SD_BUS_TYPE_INT16:
4649         case SD_BUS_TYPE_UINT16:
4650         case SD_BUS_TYPE_INT32:
4651         case SD_BUS_TYPE_UINT32:
4652         case SD_BUS_TYPE_INT64:
4653         case SD_BUS_TYPE_UINT64:
4654         case SD_BUS_TYPE_DOUBLE:
4655         case SD_BUS_TYPE_STRING:
4656         case SD_BUS_TYPE_OBJECT_PATH:
4657         case SD_BUS_TYPE_SIGNATURE:
4658         case SD_BUS_TYPE_UNIX_FD:
4659 
4660                 r = sd_bus_message_read_basic(m, *types, NULL);
4661                 if (r <= 0)
4662                         return r;
4663 
4664                 r = sd_bus_message_skip(m, types + 1);
4665                 if (r < 0)
4666                         return r;
4667 
4668                 return 1;
4669 
4670         case SD_BUS_TYPE_ARRAY: {
4671                 size_t k;
4672 
4673                 r = signature_element_length(types + 1, &k);
4674                 if (r < 0)
4675                         return r;
4676 
4677                 {
4678                         char s[k+1];
4679                         memcpy(s, types+1, k);
4680                         s[k] = 0;
4681 
4682                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4683                         if (r <= 0)
4684                                 return r;
4685 
4686                         for (;;) {
4687                                 r = sd_bus_message_skip(m, s);
4688                                 if (r < 0)
4689                                         return r;
4690                                 if (r == 0)
4691                                         break;
4692                         }
4693 
4694                         r = sd_bus_message_exit_container(m);
4695                         if (r < 0)
4696                                 return r;
4697                 }
4698 
4699                 r = sd_bus_message_skip(m, types + 1 + k);
4700                 if (r < 0)
4701                         return r;
4702 
4703                 return 1;
4704         }
4705 
4706         case SD_BUS_TYPE_VARIANT: {
4707                 const char *contents;
4708                 char x;
4709 
4710                 r = sd_bus_message_peek_type(m, &x, &contents);
4711                 if (r <= 0)
4712                         return r;
4713 
4714                 if (x != SD_BUS_TYPE_VARIANT)
4715                         return -ENXIO;
4716 
4717                 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4718                 if (r <= 0)
4719                         return r;
4720 
4721                 r = sd_bus_message_skip(m, contents);
4722                 if (r < 0)
4723                         return r;
4724                 assert(r != 0);
4725 
4726                 r = sd_bus_message_exit_container(m);
4727                 if (r < 0)
4728                         return r;
4729 
4730                 r = sd_bus_message_skip(m, types + 1);
4731                 if (r < 0)
4732                         return r;
4733 
4734                 return 1;
4735         }
4736 
4737         case SD_BUS_TYPE_STRUCT_BEGIN:
4738         case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4739                 size_t k;
4740 
4741                 r = signature_element_length(types, &k);
4742                 if (r < 0)
4743                         return r;
4744 
4745                 {
4746                         char s[k-1];
4747                         memcpy(s, types+1, k-2);
4748                         s[k-2] = 0;
4749 
4750                         r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4751                         if (r <= 0)
4752                                 return r;
4753 
4754                         r = sd_bus_message_skip(m, s);
4755                         if (r < 0)
4756                                 return r;
4757 
4758                         r = sd_bus_message_exit_container(m);
4759                         if (r < 0)
4760                                 return r;
4761                 }
4762 
4763                 r = sd_bus_message_skip(m, types + k);
4764                 if (r < 0)
4765                         return r;
4766 
4767                 return 1;
4768         }
4769 
4770         default:
4771                 return -EINVAL;
4772         }
4773 }
4774 
sd_bus_message_read_array(sd_bus_message * m,char type,const void ** ptr,size_t * size)4775 _public_ int sd_bus_message_read_array(
4776                 sd_bus_message *m,
4777                 char type,
4778                 const void **ptr,
4779                 size_t *size) {
4780 
4781         struct bus_container *c;
4782         void *p;
4783         size_t sz;
4784         ssize_t align;
4785         int r;
4786 
4787         assert_return(m, -EINVAL);
4788         assert_return(m->sealed, -EPERM);
4789         assert_return(bus_type_is_trivial(type), -EINVAL);
4790         assert_return(ptr, -EINVAL);
4791         assert_return(size, -EINVAL);
4792         assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
4793 
4794         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4795         if (r < 0)
4796                 return r;
4797         if (r == 0) {
4798                 *ptr = NULL;
4799                 *size = 0;
4800                 return 0;
4801         }
4802 
4803         c = message_get_last_container(m);
4804 
4805         if (BUS_MESSAGE_IS_GVARIANT(m)) {
4806                 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4807                 if (align < 0)
4808                         return align;
4809 
4810                 sz = c->end - c->begin;
4811         } else {
4812                 align = bus_type_get_alignment(type);
4813                 if (align < 0)
4814                         return align;
4815 
4816                 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4817         }
4818 
4819         if (sz == 0)
4820                 /* Zero length array, let's return some aligned
4821                  * pointer that is not NULL */
4822                 p = (uint8_t*) align;
4823         else {
4824                 r = message_peek_body(m, &m->rindex, align, sz, &p);
4825                 if (r < 0)
4826                         goto fail;
4827         }
4828 
4829         r = sd_bus_message_exit_container(m);
4830         if (r < 0)
4831                 goto fail;
4832 
4833         *ptr = (const void*) p;
4834         *size = sz;
4835 
4836         return 1;
4837 
4838 fail:
4839         message_quit_container(m);
4840         return r;
4841 }
4842 
message_peek_fields(sd_bus_message * m,size_t * rindex,size_t align,size_t nbytes,void ** ret)4843 static int message_peek_fields(
4844                 sd_bus_message *m,
4845                 size_t *rindex,
4846                 size_t align,
4847                 size_t nbytes,
4848                 void **ret) {
4849 
4850         assert(m);
4851         assert(rindex);
4852         assert(align > 0);
4853 
4854         return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4855 }
4856 
message_peek_field_uint32(sd_bus_message * m,size_t * ri,size_t item_size,uint32_t * ret)4857 static int message_peek_field_uint32(
4858                 sd_bus_message *m,
4859                 size_t *ri,
4860                 size_t item_size,
4861                 uint32_t *ret) {
4862 
4863         int r;
4864         void *q;
4865 
4866         assert(m);
4867         assert(ri);
4868 
4869         if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4870                 return -EBADMSG;
4871 
4872         /* identical for gvariant and dbus1 */
4873 
4874         r = message_peek_fields(m, ri, 4, 4, &q);
4875         if (r < 0)
4876                 return r;
4877 
4878         if (ret)
4879                 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4880 
4881         return 0;
4882 }
4883 
message_peek_field_uint64(sd_bus_message * m,size_t * ri,size_t item_size,uint64_t * ret)4884 static int message_peek_field_uint64(
4885                 sd_bus_message *m,
4886                 size_t *ri,
4887                 size_t item_size,
4888                 uint64_t *ret) {
4889 
4890         int r;
4891         void *q;
4892 
4893         assert(m);
4894         assert(ri);
4895 
4896         if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4897                 return -EBADMSG;
4898 
4899         /* identical for gvariant and dbus1 */
4900 
4901         r = message_peek_fields(m, ri, 8, 8, &q);
4902         if (r < 0)
4903                 return r;
4904 
4905         if (ret)
4906                 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4907 
4908         return 0;
4909 }
4910 
message_peek_field_string(sd_bus_message * m,bool (* validate)(const char * p),size_t * ri,size_t item_size,const char ** ret)4911 static int message_peek_field_string(
4912                 sd_bus_message *m,
4913                 bool (*validate)(const char *p),
4914                 size_t *ri,
4915                 size_t item_size,
4916                 const char **ret) {
4917 
4918         uint32_t l;
4919         int r;
4920         void *q;
4921 
4922         assert(m);
4923         assert(ri);
4924 
4925         if (BUS_MESSAGE_IS_GVARIANT(m)) {
4926 
4927                 if (item_size <= 0)
4928                         return -EBADMSG;
4929 
4930                 r = message_peek_fields(m, ri, 1, item_size, &q);
4931                 if (r < 0)
4932                         return r;
4933 
4934                 l = item_size - 1;
4935         } else {
4936                 r = message_peek_field_uint32(m, ri, 4, &l);
4937                 if (r < 0)
4938                         return r;
4939 
4940                 if (l == UINT32_MAX)
4941                         /* avoid overflow right below */
4942                         return -EBADMSG;
4943 
4944                 r = message_peek_fields(m, ri, 1, l+1, &q);
4945                 if (r < 0)
4946                         return r;
4947         }
4948 
4949         if (validate) {
4950                 if (!validate_nul(q, l))
4951                         return -EBADMSG;
4952 
4953                 if (!validate(q))
4954                         return -EBADMSG;
4955         } else {
4956                 if (!validate_string(q, l))
4957                         return -EBADMSG;
4958         }
4959 
4960         if (ret)
4961                 *ret = q;
4962 
4963         return 0;
4964 }
4965 
message_peek_field_signature(sd_bus_message * m,size_t * ri,size_t item_size,const char ** ret)4966 static int message_peek_field_signature(
4967                 sd_bus_message *m,
4968                 size_t *ri,
4969                 size_t item_size,
4970                 const char **ret) {
4971 
4972         size_t l;
4973         int r;
4974         void *q;
4975 
4976         assert(m);
4977         assert(ri);
4978 
4979         if (BUS_MESSAGE_IS_GVARIANT(m)) {
4980 
4981                 if (item_size <= 0)
4982                         return -EBADMSG;
4983 
4984                 r = message_peek_fields(m, ri, 1, item_size, &q);
4985                 if (r < 0)
4986                         return r;
4987 
4988                 l = item_size - 1;
4989         } else {
4990                 r = message_peek_fields(m, ri, 1, 1, &q);
4991                 if (r < 0)
4992                         return r;
4993 
4994                 l = *(uint8_t*) q;
4995                 if (l == UINT8_MAX)
4996                         /* avoid overflow right below */
4997                         return -EBADMSG;
4998 
4999                 r = message_peek_fields(m, ri, 1, l+1, &q);
5000                 if (r < 0)
5001                         return r;
5002         }
5003 
5004         if (!validate_signature(q, l))
5005                 return -EBADMSG;
5006 
5007         if (ret)
5008                 *ret = q;
5009 
5010         return 0;
5011 }
5012 
message_skip_fields(sd_bus_message * m,size_t * ri,uint32_t array_size,const char ** signature)5013 static int message_skip_fields(
5014                 sd_bus_message *m,
5015                 size_t *ri,
5016                 uint32_t array_size,
5017                 const char **signature) {
5018 
5019         size_t original_index;
5020         int r;
5021 
5022         assert(m);
5023         assert(ri);
5024         assert(signature);
5025         assert(!BUS_MESSAGE_IS_GVARIANT(m));
5026 
5027         original_index = *ri;
5028 
5029         for (;;) {
5030                 char t;
5031                 size_t l;
5032 
5033                 if (array_size != UINT32_MAX &&
5034                     array_size <= *ri - original_index)
5035                         return 0;
5036 
5037                 t = **signature;
5038                 if (!t)
5039                         return 0;
5040 
5041                 if (t == SD_BUS_TYPE_STRING) {
5042 
5043                         r = message_peek_field_string(m, NULL, ri, 0, NULL);
5044                         if (r < 0)
5045                                 return r;
5046 
5047                         (*signature)++;
5048 
5049                 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
5050 
5051                         r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
5052                         if (r < 0)
5053                                 return r;
5054 
5055                         (*signature)++;
5056 
5057                 } else if (t == SD_BUS_TYPE_SIGNATURE) {
5058 
5059                         r = message_peek_field_signature(m, ri, 0, NULL);
5060                         if (r < 0)
5061                                 return r;
5062 
5063                         (*signature)++;
5064 
5065                 } else if (bus_type_is_basic(t)) {
5066                         ssize_t align, k;
5067 
5068                         align = bus_type_get_alignment(t);
5069                         k = bus_type_get_size(t);
5070                         assert(align > 0 && k > 0);
5071 
5072                         r = message_peek_fields(m, ri, align, k, NULL);
5073                         if (r < 0)
5074                                 return r;
5075 
5076                         (*signature)++;
5077 
5078                 } else if (t == SD_BUS_TYPE_ARRAY) {
5079 
5080                         r = signature_element_length(*signature + 1, &l);
5081                         if (r < 0)
5082                                 return r;
5083 
5084                         assert(l >= 1);
5085                         {
5086                                 char sig[l + 1], *s = sig;
5087                                 uint32_t nas;
5088                                 int alignment;
5089 
5090                                 strncpy(sig, *signature + 1, l);
5091                                 sig[l] = '\0';
5092 
5093                                 alignment = bus_type_get_alignment(sig[0]);
5094                                 if (alignment < 0)
5095                                         return alignment;
5096 
5097                                 r = message_peek_field_uint32(m, ri, 0, &nas);
5098                                 if (r < 0)
5099                                         return r;
5100                                 if (nas > BUS_ARRAY_MAX_SIZE)
5101                                         return -EBADMSG;
5102 
5103                                 r = message_peek_fields(m, ri, alignment, 0, NULL);
5104                                 if (r < 0)
5105                                         return r;
5106 
5107                                 r = message_skip_fields(m, ri, nas, (const char**) &s);
5108                                 if (r < 0)
5109                                         return r;
5110                         }
5111 
5112                         (*signature) += 1 + l;
5113 
5114                 } else if (t == SD_BUS_TYPE_VARIANT) {
5115                         const char *s;
5116 
5117                         r = message_peek_field_signature(m, ri, 0, &s);
5118                         if (r < 0)
5119                                 return r;
5120 
5121                         r = message_skip_fields(m, ri, UINT32_MAX, (const char**) &s);
5122                         if (r < 0)
5123                                 return r;
5124 
5125                         (*signature)++;
5126 
5127                 } else if (IN_SET(t, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) {
5128 
5129                         r = signature_element_length(*signature, &l);
5130                         if (r < 0)
5131                                 return r;
5132 
5133                         assert(l >= 2);
5134                         {
5135                                 char sig[l + 1], *s = sig;
5136                                 strncpy(sig, *signature + 1, l);
5137                                 sig[l] = '\0';
5138 
5139                                 r = message_skip_fields(m, ri, UINT32_MAX, (const char**) &s);
5140                                 if (r < 0)
5141                                         return r;
5142                         }
5143 
5144                         *signature += l;
5145                 } else
5146                         return -EBADMSG;
5147         }
5148 }
5149 
bus_message_parse_fields(sd_bus_message * m)5150 int bus_message_parse_fields(sd_bus_message *m) {
5151         size_t ri;
5152         int r;
5153         uint32_t unix_fds = 0;
5154         bool unix_fds_set = false;
5155         void *offsets = NULL;
5156         unsigned n_offsets = 0;
5157         size_t sz = 0;
5158         unsigned i = 0;
5159 
5160         assert(m);
5161 
5162         if (BUS_MESSAGE_IS_GVARIANT(m)) {
5163                 char *p;
5164 
5165                 /* Read the signature from the end of the body variant first */
5166                 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5167                 if (m->footer_accessible < 1 + sz)
5168                         return -EBADMSG;
5169 
5170                 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5171                 for (;;) {
5172                         if (p < (char*) m->footer)
5173                                 return -EBADMSG;
5174 
5175                         if (*p == 0) {
5176                                 _cleanup_free_ char *k = NULL;
5177                                 size_t l;
5178 
5179                                 /* We found the beginning of the signature
5180                                  * string, yay! We require the body to be a
5181                                  * structure, so verify it and then strip the
5182                                  * opening/closing brackets. */
5183 
5184                                 l = (char*) m->footer + m->footer_accessible - p - (1 + sz);
5185                                 if (l < 2 ||
5186                                     p[1] != SD_BUS_TYPE_STRUCT_BEGIN ||
5187                                     p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END)
5188                                         return -EBADMSG;
5189 
5190                                 k = memdup_suffix0(p + 1 + 1, l - 2);
5191                                 if (!k)
5192                                         return -ENOMEM;
5193 
5194                                 if (!signature_is_valid(k, true))
5195                                         return -EBADMSG;
5196 
5197                                 free_and_replace(m->root_container.signature, k);
5198                                 break;
5199                         }
5200 
5201                         p--;
5202                 }
5203 
5204                 /* Calculate the actual user body size, by removing
5205                  * the trailing variant signature and struct offset
5206                  * table */
5207                 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5208 
5209                 /* Pull out the offset table for the fields array, if any */
5210                 if (m->fields_size > 0) {
5211                         sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5212                         if (sz > 0) {
5213                                 size_t framing;
5214                                 void *q;
5215 
5216                                 if (m->fields_size < sz)
5217                                         return -EBADMSG;
5218 
5219                                 ri = m->fields_size - sz;
5220                                 r = message_peek_fields(m, &ri, 1, sz, &q);
5221                                 if (r < 0)
5222                                         return r;
5223 
5224                                 framing = bus_gvariant_read_word_le(q, sz);
5225                                 if (framing >= m->fields_size - sz)
5226                                         return -EBADMSG;
5227                                 if ((m->fields_size - framing) % sz != 0)
5228                                         return -EBADMSG;
5229 
5230                                 ri = framing;
5231                                 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5232                                 if (r < 0)
5233                                         return r;
5234 
5235                                 n_offsets = (m->fields_size - framing) / sz;
5236                         }
5237                 }
5238         } else
5239                 m->user_body_size = m->body_size;
5240 
5241         ri = 0;
5242         while (ri < m->fields_size) {
5243                 _cleanup_free_ char *sig = NULL;
5244                 const char *signature;
5245                 uint64_t field_type;
5246                 size_t item_size = SIZE_MAX;
5247 
5248                 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5249                         uint64_t *u64;
5250 
5251                         if (i >= n_offsets)
5252                                 break;
5253 
5254                         if (i == 0)
5255                                 ri = 0;
5256                         else
5257                                 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5258 
5259                         r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5260                         if (r < 0)
5261                                 return r;
5262 
5263                         field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5264                 } else {
5265                         uint8_t *u8;
5266 
5267                         r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5268                         if (r < 0)
5269                                 return r;
5270 
5271                         field_type = *u8;
5272                 }
5273 
5274                 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5275                         size_t where, end;
5276                         char *b;
5277                         void *q;
5278 
5279                         end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5280 
5281                         if (end < ri)
5282                                 return -EBADMSG;
5283 
5284                         where = ri = ALIGN_TO(ri, 8);
5285                         item_size = end - ri;
5286                         r = message_peek_fields(m, &where, 1, item_size, &q);
5287                         if (r < 0)
5288                                 return r;
5289 
5290                         b = memrchr(q, 0, item_size);
5291                         if (!b)
5292                                 return -EBADMSG;
5293 
5294                         sig = memdup_suffix0(b+1, item_size - (b+1-(char*) q));
5295                         if (!sig)
5296                                 return -ENOMEM;
5297 
5298                         signature = sig;
5299                         item_size = b - (char*) q;
5300                 } else {
5301                         r = message_peek_field_signature(m, &ri, 0, &signature);
5302                         if (r < 0)
5303                                 return r;
5304                 }
5305 
5306                 switch (field_type) {
5307 
5308                 case _BUS_MESSAGE_HEADER_INVALID:
5309                         return -EBADMSG;
5310 
5311                 case BUS_MESSAGE_HEADER_PATH:
5312 
5313                         if (m->path)
5314                                 return -EBADMSG;
5315 
5316                         if (!streq(signature, "o"))
5317                                 return -EBADMSG;
5318 
5319                         r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5320                         break;
5321 
5322                 case BUS_MESSAGE_HEADER_INTERFACE:
5323 
5324                         if (m->interface)
5325                                 return -EBADMSG;
5326 
5327                         if (!streq(signature, "s"))
5328                                 return -EBADMSG;
5329 
5330                         r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5331                         break;
5332 
5333                 case BUS_MESSAGE_HEADER_MEMBER:
5334 
5335                         if (m->member)
5336                                 return -EBADMSG;
5337 
5338                         if (!streq(signature, "s"))
5339                                 return -EBADMSG;
5340 
5341                         r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5342                         break;
5343 
5344                 case BUS_MESSAGE_HEADER_ERROR_NAME:
5345 
5346                         if (m->error.name)
5347                                 return -EBADMSG;
5348 
5349                         if (!streq(signature, "s"))
5350                                 return -EBADMSG;
5351 
5352                         r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5353                         if (r >= 0)
5354                                 m->error._need_free = -1;
5355 
5356                         break;
5357 
5358                 case BUS_MESSAGE_HEADER_DESTINATION:
5359 
5360                         if (m->destination)
5361                                 return -EBADMSG;
5362 
5363                         if (!streq(signature, "s"))
5364                                 return -EBADMSG;
5365 
5366                         r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5367                         break;
5368 
5369                 case BUS_MESSAGE_HEADER_SENDER:
5370 
5371                         if (m->sender)
5372                                 return -EBADMSG;
5373 
5374                         if (!streq(signature, "s"))
5375                                 return -EBADMSG;
5376 
5377                         r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5378 
5379                         if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client) {
5380                                 m->creds.unique_name = (char*) m->sender;
5381                                 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5382                         }
5383 
5384                         break;
5385 
5386                 case BUS_MESSAGE_HEADER_SIGNATURE: {
5387                         const char *s;
5388                         char *c;
5389 
5390                         if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5391                                 return -EBADMSG;
5392 
5393                         if (m->root_container.signature)
5394                                 return -EBADMSG;
5395 
5396                         if (!streq(signature, "g"))
5397                                 return -EBADMSG;
5398 
5399                         r = message_peek_field_signature(m, &ri, item_size, &s);
5400                         if (r < 0)
5401                                 return r;
5402 
5403                         c = strdup(s);
5404                         if (!c)
5405                                 return -ENOMEM;
5406 
5407                         free_and_replace(m->root_container.signature, c);
5408                         break;
5409                 }
5410 
5411                 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5412 
5413                         if (m->reply_cookie != 0)
5414                                 return -EBADMSG;
5415 
5416                         if (BUS_MESSAGE_IS_GVARIANT(m)) {
5417                                 /* 64bit on dbus2 */
5418 
5419                                 if (!streq(signature, "t"))
5420                                         return -EBADMSG;
5421 
5422                                 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5423                                 if (r < 0)
5424                                         return r;
5425                         } else {
5426                                 /* 32bit on dbus1 */
5427                                 uint32_t serial;
5428 
5429                                 if (!streq(signature, "u"))
5430                                         return -EBADMSG;
5431 
5432                                 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5433                                 if (r < 0)
5434                                         return r;
5435 
5436                                 m->reply_cookie = serial;
5437                         }
5438 
5439                         if (m->reply_cookie == 0)
5440                                 return -EBADMSG;
5441 
5442                         break;
5443 
5444                 case BUS_MESSAGE_HEADER_UNIX_FDS:
5445                         if (unix_fds_set)
5446                                 return -EBADMSG;
5447 
5448                         if (!streq(signature, "u"))
5449                                 return -EBADMSG;
5450 
5451                         r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5452                         if (r < 0)
5453                                 return -EBADMSG;
5454 
5455                         unix_fds_set = true;
5456                         break;
5457 
5458                 default:
5459                         if (!BUS_MESSAGE_IS_GVARIANT(m))
5460                                 r = message_skip_fields(m, &ri, UINT32_MAX, (const char **) &signature);
5461                 }
5462 
5463                 if (r < 0)
5464                         return r;
5465 
5466                 i++;
5467         }
5468 
5469         if (m->n_fds != unix_fds)
5470                 return -EBADMSG;
5471 
5472         switch (m->header->type) {
5473 
5474         case SD_BUS_MESSAGE_SIGNAL:
5475                 if (!m->path || !m->interface || !m->member)
5476                         return -EBADMSG;
5477 
5478                 if (m->reply_cookie != 0)
5479                         return -EBADMSG;
5480 
5481                 break;
5482 
5483         case SD_BUS_MESSAGE_METHOD_CALL:
5484 
5485                 if (!m->path || !m->member)
5486                         return -EBADMSG;
5487 
5488                 if (m->reply_cookie != 0)
5489                         return -EBADMSG;
5490 
5491                 break;
5492 
5493         case SD_BUS_MESSAGE_METHOD_RETURN:
5494 
5495                 if (m->reply_cookie == 0)
5496                         return -EBADMSG;
5497                 break;
5498 
5499         case SD_BUS_MESSAGE_METHOD_ERROR:
5500 
5501                 if (m->reply_cookie == 0 || !m->error.name)
5502                         return -EBADMSG;
5503                 break;
5504         }
5505 
5506         /* Refuse non-local messages that claim they are local */
5507         if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5508                 return -EBADMSG;
5509         if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5510                 return -EBADMSG;
5511         if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5512                 return -EBADMSG;
5513 
5514         m->root_container.end = m->user_body_size;
5515 
5516         if (BUS_MESSAGE_IS_GVARIANT(m)) {
5517                 r = build_struct_offsets(
5518                                 m,
5519                                 m->root_container.signature,
5520                                 m->user_body_size,
5521                                 &m->root_container.item_size,
5522                                 &m->root_container.offsets,
5523                                 &m->root_container.n_offsets);
5524                 if (r == -EINVAL)
5525                         return -EBADMSG;
5526                 if (r < 0)
5527                         return r;
5528         }
5529 
5530         /* Try to read the error message, but if we can't it's a non-issue */
5531         if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5532                 (void) sd_bus_message_read(m, "s", &m->error.message);
5533 
5534         return 0;
5535 }
5536 
sd_bus_message_set_destination(sd_bus_message * m,const char * destination)5537 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5538         assert_return(m, -EINVAL);
5539         assert_return(destination, -EINVAL);
5540         assert_return(service_name_is_valid(destination), -EINVAL);
5541         assert_return(!m->sealed, -EPERM);
5542         assert_return(!m->destination, -EEXIST);
5543 
5544         return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5545 }
5546 
sd_bus_message_set_sender(sd_bus_message * m,const char * sender)5547 _public_ int sd_bus_message_set_sender(sd_bus_message *m, const char *sender) {
5548         assert_return(m, -EINVAL);
5549         assert_return(sender, -EINVAL);
5550         assert_return(service_name_is_valid(sender), -EINVAL);
5551         assert_return(!m->sealed, -EPERM);
5552         assert_return(!m->sender, -EEXIST);
5553 
5554         return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5555 }
5556 
bus_message_get_blob(sd_bus_message * m,void ** buffer,size_t * sz)5557 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5558         size_t total;
5559         void *p, *e;
5560         size_t i;
5561         struct bus_body_part *part;
5562 
5563         assert(m);
5564         assert(buffer);
5565         assert(sz);
5566 
5567         total = BUS_MESSAGE_SIZE(m);
5568 
5569         p = malloc(total);
5570         if (!p)
5571                 return -ENOMEM;
5572 
5573         e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5574         MESSAGE_FOREACH_PART(part, i, m)
5575                 e = mempcpy(e, part->data, part->size);
5576 
5577         assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5578 
5579         *buffer = p;
5580         *sz = total;
5581 
5582         return 0;
5583 }
5584 
bus_message_read_strv_extend(sd_bus_message * m,char *** l)5585 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5586         char type;
5587         const char *contents, *s;
5588         int r;
5589 
5590         assert(m);
5591         assert(l);
5592 
5593         r = sd_bus_message_peek_type(m, &type, &contents);
5594         if (r < 0)
5595                 return r;
5596 
5597         if (type != SD_BUS_TYPE_ARRAY || !STR_IN_SET(contents, "s", "o", "g"))
5598                 return -ENXIO;
5599 
5600         r = sd_bus_message_enter_container(m, 'a', NULL);
5601         if (r <= 0)
5602                 return r;
5603 
5604         /* sd_bus_message_read_basic() does content validation for us. */
5605         while ((r = sd_bus_message_read_basic(m, *contents, &s)) > 0) {
5606                 r = strv_extend(l, s);
5607                 if (r < 0)
5608                         return r;
5609         }
5610         if (r < 0)
5611                 return r;
5612 
5613         r = sd_bus_message_exit_container(m);
5614         if (r < 0)
5615                 return r;
5616 
5617         return 1;
5618 }
5619 
sd_bus_message_read_strv(sd_bus_message * m,char *** l)5620 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5621         _cleanup_strv_free_ char **strv = NULL;
5622         int r;
5623 
5624         assert_return(m, -EINVAL);
5625         assert_return(m->sealed, -EPERM);
5626         assert_return(l, -EINVAL);
5627 
5628         r = bus_message_read_strv_extend(m, &strv);
5629         if (r <= 0)
5630                 return r;
5631 
5632         *l = TAKE_PTR(strv);
5633         return 1;
5634 }
5635 
bus_message_get_arg_skip(sd_bus_message * m,unsigned i,char * _type,const char ** _contents)5636 static int bus_message_get_arg_skip(
5637                 sd_bus_message *m,
5638                 unsigned i,
5639                 char *_type,
5640                 const char **_contents) {
5641 
5642         unsigned j;
5643         int r;
5644 
5645         r = sd_bus_message_rewind(m, true);
5646         if (r < 0)
5647                 return r;
5648 
5649         for (j = 0;; j++) {
5650                 const char *contents;
5651                 char type;
5652 
5653                 r = sd_bus_message_peek_type(m, &type, &contents);
5654                 if (r < 0)
5655                         return r;
5656                 if (r == 0)
5657                         return -ENXIO;
5658 
5659                 /* Don't match against arguments after the first one we don't understand */
5660                 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5661                     !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5662                         return -ENXIO;
5663 
5664                 if (j >= i) {
5665                         if (_contents)
5666                                 *_contents = contents;
5667                         if (_type)
5668                                 *_type = type;
5669                         return 0;
5670                 }
5671 
5672                 r = sd_bus_message_skip(m, NULL);
5673                 if (r < 0)
5674                         return r;
5675         }
5676 
5677 }
5678 
bus_message_get_arg(sd_bus_message * m,unsigned i,const char ** str)5679 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) {
5680         char type;
5681         int r;
5682 
5683         assert(m);
5684         assert(str);
5685 
5686         r = bus_message_get_arg_skip(m, i, &type, NULL);
5687         if (r < 0)
5688                 return r;
5689 
5690         if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE))
5691                 return -ENXIO;
5692 
5693         return sd_bus_message_read_basic(m, type, str);
5694 }
5695 
bus_message_get_arg_strv(sd_bus_message * m,unsigned i,char *** strv)5696 int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) {
5697         const char *contents;
5698         char type;
5699         int r;
5700 
5701         assert(m);
5702         assert(strv);
5703 
5704         r = bus_message_get_arg_skip(m, i, &type, &contents);
5705         if (r < 0)
5706                 return r;
5707 
5708         if (type != SD_BUS_TYPE_ARRAY)
5709                 return -ENXIO;
5710         if (!STR_IN_SET(contents, "s", "o", "g"))
5711                 return -ENXIO;
5712 
5713         return sd_bus_message_read_strv(m, strv);
5714 }
5715 
sd_bus_message_get_errno(sd_bus_message * m)5716 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5717         assert_return(m, EINVAL);
5718 
5719         if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5720                 return 0;
5721 
5722         return sd_bus_error_get_errno(&m->error);
5723 }
5724 
sd_bus_message_get_signature(sd_bus_message * m,int complete)5725 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5726         struct bus_container *c;
5727 
5728         assert_return(m, NULL);
5729 
5730         c = complete ? &m->root_container : message_get_last_container(m);
5731         return strempty(c->signature);
5732 }
5733 
sd_bus_message_is_empty(sd_bus_message * m)5734 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5735         assert_return(m, -EINVAL);
5736 
5737         return isempty(m->root_container.signature);
5738 }
5739 
sd_bus_message_has_signature(sd_bus_message * m,const char * signature)5740 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5741         assert_return(m, -EINVAL);
5742 
5743         return streq(strempty(m->root_container.signature), strempty(signature));
5744 }
5745 
sd_bus_message_copy(sd_bus_message * m,sd_bus_message * source,int all)5746 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5747         bool done_something = false;
5748         int r;
5749 
5750         assert_return(m, -EINVAL);
5751         assert_return(source, -EINVAL);
5752         assert_return(!m->sealed, -EPERM);
5753         assert_return(source->sealed, -EPERM);
5754 
5755         do {
5756                 const char *contents;
5757                 char type;
5758                 union {
5759                         uint8_t u8;
5760                         uint16_t u16;
5761                         int16_t s16;
5762                         uint32_t u32;
5763                         int32_t s32;
5764                         uint64_t u64;
5765                         int64_t s64;
5766                         double d64;
5767                         const char *string;
5768                         int i;
5769                 } basic;
5770 
5771                 r = sd_bus_message_peek_type(source, &type, &contents);
5772                 if (r < 0)
5773                         return r;
5774                 if (r == 0)
5775                         break;
5776 
5777                 done_something = true;
5778 
5779                 if (bus_type_is_container(type) > 0) {
5780 
5781                         r = sd_bus_message_enter_container(source, type, contents);
5782                         if (r < 0)
5783                                 return r;
5784 
5785                         r = sd_bus_message_open_container(m, type, contents);
5786                         if (r < 0)
5787                                 return r;
5788 
5789                         r = sd_bus_message_copy(m, source, true);
5790                         if (r < 0)
5791                                 return r;
5792 
5793                         r = sd_bus_message_close_container(m);
5794                         if (r < 0)
5795                                 return r;
5796 
5797                         r = sd_bus_message_exit_container(source);
5798                         if (r < 0)
5799                                 return r;
5800 
5801                         continue;
5802                 }
5803 
5804                 r = sd_bus_message_read_basic(source, type, &basic);
5805                 if (r < 0)
5806                         return r;
5807 
5808                 assert(r > 0);
5809 
5810                 if (IN_SET(type, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE, SD_BUS_TYPE_STRING))
5811                         r = sd_bus_message_append_basic(m, type, basic.string);
5812                 else
5813                         r = sd_bus_message_append_basic(m, type, &basic);
5814 
5815                 if (r < 0)
5816                         return r;
5817 
5818         } while (all);
5819 
5820         return done_something;
5821 }
5822 
sd_bus_message_verify_type(sd_bus_message * m,char type,const char * contents)5823 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5824         const char *c;
5825         char t;
5826         int r;
5827 
5828         assert_return(m, -EINVAL);
5829         assert_return(m->sealed, -EPERM);
5830         assert_return(!type || bus_type_is_valid(type), -EINVAL);
5831         assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5832         assert_return(type || contents, -EINVAL);
5833         assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5834 
5835         r = sd_bus_message_peek_type(m, &t, &c);
5836         if (r <= 0)
5837                 return r;
5838 
5839         if (type != 0 && type != t)
5840                 return 0;
5841 
5842         if (contents && !streq_ptr(contents, c))
5843                 return 0;
5844 
5845         return 1;
5846 }
5847 
sd_bus_message_get_bus(sd_bus_message * m)5848 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5849         assert_return(m, NULL);
5850 
5851         return m->bus;
5852 }
5853 
bus_message_remarshal(sd_bus * bus,sd_bus_message ** m)5854 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5855         _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
5856         usec_t timeout;
5857         int r;
5858 
5859         assert(bus);
5860         assert(m);
5861         assert(*m);
5862 
5863         switch ((*m)->header->type) {
5864 
5865         case SD_BUS_MESSAGE_SIGNAL:
5866                 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5867                 if (r < 0)
5868                         return r;
5869 
5870                 break;
5871 
5872         case SD_BUS_MESSAGE_METHOD_CALL:
5873                 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5874                 if (r < 0)
5875                         return r;
5876 
5877                 break;
5878 
5879         case SD_BUS_MESSAGE_METHOD_RETURN:
5880         case SD_BUS_MESSAGE_METHOD_ERROR:
5881 
5882                 r = sd_bus_message_new(bus, &n, (*m)->header->type);
5883                 if (r < 0)
5884                         return -ENOMEM;
5885 
5886                 assert(n);
5887 
5888                 n->reply_cookie = (*m)->reply_cookie;
5889 
5890                 r = message_append_reply_cookie(n, n->reply_cookie);
5891                 if (r < 0)
5892                         return r;
5893 
5894                 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5895                         r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5896                         if (r < 0)
5897                                 return r;
5898 
5899                         n->error._need_free = -1;
5900                 }
5901 
5902                 break;
5903 
5904         default:
5905                 return -EINVAL;
5906         }
5907 
5908         if ((*m)->destination && !n->destination) {
5909                 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5910                 if (r < 0)
5911                         return r;
5912         }
5913 
5914         if ((*m)->sender && !n->sender) {
5915                 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5916                 if (r < 0)
5917                         return r;
5918         }
5919 
5920         n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5921 
5922         r = sd_bus_message_copy(n, *m, true);
5923         if (r < 0)
5924                 return r;
5925 
5926         timeout = (*m)->timeout;
5927         if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)) {
5928                 r = sd_bus_get_method_call_timeout(bus, &timeout);
5929                 if (r < 0)
5930                         return r;
5931         }
5932 
5933         r = sd_bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5934         if (r < 0)
5935                 return r;
5936 
5937         sd_bus_message_unref(*m);
5938         *m = TAKE_PTR(n);
5939 
5940         return 0;
5941 }
5942 
sd_bus_message_get_priority(sd_bus_message * m,int64_t * priority)5943 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5944         static bool warned = false;
5945 
5946         assert_return(m, -EINVAL);
5947         assert_return(priority, -EINVAL);
5948 
5949         if (!warned) {
5950                 log_debug("sd_bus_message_get_priority() is deprecated and always returns 0.");
5951                 warned = true;
5952         }
5953 
5954         *priority = 0;
5955         return 0;
5956 }
5957 
sd_bus_message_set_priority(sd_bus_message * m,int64_t priority)5958 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5959         static bool warned = false;
5960 
5961         assert_return(m, -EINVAL);
5962         assert_return(!m->sealed, -EPERM);
5963 
5964         if (!warned) {
5965                 log_debug("sd_bus_message_set_priority() is deprecated and does nothing.");
5966                 warned = true;
5967         }
5968 
5969         return 0;
5970 }
5971 
sd_bus_message_sensitive(sd_bus_message * m)5972 _public_ int sd_bus_message_sensitive(sd_bus_message *m) {
5973         assert_return(m, -EINVAL);
5974 
5975         m->sensitive = true;
5976         return 0;
5977 }
5978