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