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