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