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