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