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