2020-11-09 05:23:58 +01:00
|
|
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
2013-03-19 20:03:16 +01:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <byteswap.h>
|
2015-10-24 22:58:24 +02:00
|
|
|
#include <stdbool.h>
|
2015-02-24 00:42:13 +01:00
|
|
|
#include <sys/socket.h>
|
2013-03-19 20:03:16 +01:00
|
|
|
|
|
|
|
#include "sd-bus.h"
|
2015-10-24 22:58:24 +02:00
|
|
|
|
2013-11-28 17:50:02 +01:00
|
|
|
#include "bus-creds.h"
|
2013-12-03 18:13:48 +01:00
|
|
|
#include "bus-protocol.h"
|
2015-10-24 22:58:24 +02:00
|
|
|
#include "macro.h"
|
|
|
|
#include "time-util.h"
|
2013-03-19 20:03:16 +01:00
|
|
|
|
|
|
|
struct bus_container {
|
|
|
|
char enclosing;
|
2013-12-09 23:03:21 +01:00
|
|
|
bool need_offsets:1;
|
2013-03-19 20:03:16 +01:00
|
|
|
|
2013-12-09 23:03:21 +01:00
|
|
|
/* Indexes into the signature string */
|
2013-05-09 20:00:51 +02:00
|
|
|
unsigned index, saved_index;
|
2013-05-15 19:45:05 +02:00
|
|
|
char *signature;
|
|
|
|
|
2013-12-09 23:03:21 +01:00
|
|
|
size_t before, begin, end;
|
2013-12-05 02:46:54 +01:00
|
|
|
|
2013-12-09 23:03:21 +01:00
|
|
|
/* dbus1: pointer to the array size value, if this is a value */
|
|
|
|
uint32_t *array_size;
|
2013-12-05 02:46:54 +01:00
|
|
|
|
2013-12-09 23:03:21 +01:00
|
|
|
/* gvariant: list of offsets to end of children if this is struct/dict entry/array */
|
2013-12-16 20:00:25 +01:00
|
|
|
size_t *offsets, n_offsets, offsets_allocated, offset_index;
|
2013-12-09 23:03:21 +01:00
|
|
|
size_t item_size;
|
2013-12-24 03:02:49 +01:00
|
|
|
|
|
|
|
char *peeked_signature;
|
2013-03-19 20:03:16 +01:00
|
|
|
};
|
|
|
|
|
2013-05-14 22:24:26 +02:00
|
|
|
struct bus_body_part {
|
2013-05-15 19:45:05 +02:00
|
|
|
struct bus_body_part *next;
|
2013-05-14 22:24:26 +02:00
|
|
|
void *data;
|
2014-12-09 18:07:46 +01:00
|
|
|
void *mmap_begin;
|
2013-05-14 22:24:26 +02:00
|
|
|
size_t size;
|
|
|
|
size_t mapped;
|
2013-12-18 18:46:23 +01:00
|
|
|
size_t allocated;
|
2014-12-09 18:07:46 +01:00
|
|
|
uint64_t memfd_offset;
|
2013-05-14 22:24:26 +02:00
|
|
|
int memfd;
|
|
|
|
bool free_this:1;
|
2013-05-15 19:45:05 +02:00
|
|
|
bool munmap_this:1;
|
2013-05-14 22:24:26 +02:00
|
|
|
bool sealed:1;
|
2013-05-15 19:45:05 +02:00
|
|
|
bool is_zero:1;
|
2013-05-14 22:24:26 +02:00
|
|
|
};
|
|
|
|
|
2013-03-19 20:03:16 +01:00
|
|
|
struct sd_bus_message {
|
bus-message: introduce two kinds of references to bus messages
Before this commit bus messages had a single reference count: when it
reached zero the message would be freed. This simple approach meant a
cyclic dependency was typically seen: a message that was enqueued in a
bus connection object would reference the bus connection object but also
itself be referenced by the bus connection object. So far out strategy
to avoid cases like this was: make sure to process the bus connection
regularly so that messages don#t stay queued, and at exit flush/close
the connection so that the message queued would be emptied, and thus the
cyclic dependencies resolved. Im many cases this isn't done properly
however.
With this change, let's address the issue more systematically: let's
break the reference cycle. Specifically, there are now two types of
references to a bus message:
1. A regular one, which keeps both the message and the bus object it is
associated with pinned.
2. A "queue" reference, which is weaker: it pins the message, but not
the bus object it is associated with.
The idea is then that regular user handling uses regular references, but
when a message is enqueued on its connection, then this takes a "queue"
reference instead. This then means that a queued message doesn't imply
the connection itself remains pinned, only regular references to the
connection or a message associated with it do. Thus, if we end up in the
situation where a user allocates a bus and a message and enqueues the
latter in the former and drops all refs to both, then this will detect
this case and free both.
Note that this scheme isn't perfect, it only covers references between
messages and the busses they are associated with. If OTOH a bus message
is enqueued on a different bus than it is associated with cyclic deps
cannot be recognized with this simple algorithm, and thus if you enqueue
a message associated with a bus A on a bus B, and another message
associated with bus B on a bus A, a cyclic ref will be in effect and not
be discovered. However, given that this is an exotic case (though one
that happens, consider systemd-bus-stdio-bridge), it should be OK not to
cover with this, and people have to explicit flush all queues on exit in
that case.
Note that this commit only establishes the separate reference counters
per message. A follow-up commit will start making use of this from the
bus connection object.
2019-01-17 18:18:54 +01:00
|
|
|
/* Caveat: a message can be referenced in two different ways: the main (user-facing) way will also
|
|
|
|
* pin the bus connection object the message is associated with. The secondary way ("queued") is used
|
|
|
|
* when a message is in the read or write queues of the bus connection object, which will not pin the
|
|
|
|
* bus connection object. This is necessary so that we don't have to have a pair of cyclic references
|
|
|
|
* between a message that is queued and its connection: as soon as a message is only referenced by
|
|
|
|
* the connection (by means of being queued) and the connection itself has no other references it
|
|
|
|
* will be freed. */
|
|
|
|
|
|
|
|
unsigned n_ref; /* Counter of references that pin the connection */
|
|
|
|
unsigned n_queued; /* Counter of references that do not pin the connection */
|
2013-03-19 20:03:16 +01:00
|
|
|
|
2013-05-10 03:36:55 +02:00
|
|
|
sd_bus *bus;
|
|
|
|
|
2014-03-13 20:33:22 +01:00
|
|
|
uint64_t reply_cookie;
|
2013-03-19 20:03:16 +01:00
|
|
|
|
|
|
|
const char *path;
|
|
|
|
const char *interface;
|
|
|
|
const char *member;
|
|
|
|
const char *destination;
|
|
|
|
const char *sender;
|
|
|
|
|
|
|
|
sd_bus_error error;
|
|
|
|
|
2013-11-28 17:50:02 +01:00
|
|
|
sd_bus_creds creds;
|
|
|
|
|
2013-04-13 21:53:11 +02:00
|
|
|
usec_t monotonic;
|
|
|
|
usec_t realtime;
|
2014-01-22 10:57:12 +01:00
|
|
|
uint64_t seqnum;
|
2014-10-22 14:41:53 +02:00
|
|
|
uint64_t verify_destination_id;
|
2013-03-19 20:03:16 +01:00
|
|
|
|
|
|
|
bool sealed:1;
|
2013-03-24 22:02:05 +01:00
|
|
|
bool dont_send:1;
|
|
|
|
bool allow_fds:1;
|
2013-03-19 20:03:16 +01:00
|
|
|
bool free_header:1;
|
2013-03-24 22:02:05 +01:00
|
|
|
bool free_fds:1;
|
2013-05-14 22:24:26 +02:00
|
|
|
bool poisoned:1;
|
2019-08-19 20:28:34 +02:00
|
|
|
bool sensitive:1;
|
2013-03-19 20:03:16 +01:00
|
|
|
|
2015-02-13 17:32:38 +01:00
|
|
|
/* The first and last bytes of the message */
|
2013-03-19 20:03:16 +01:00
|
|
|
struct bus_header *header;
|
2015-02-13 17:32:38 +01:00
|
|
|
void *footer;
|
|
|
|
|
|
|
|
/* How many bytes are accessible in the above pointers */
|
|
|
|
size_t header_accessible;
|
|
|
|
size_t footer_accessible;
|
|
|
|
|
|
|
|
size_t fields_size;
|
|
|
|
size_t body_size;
|
|
|
|
size_t user_body_size;
|
|
|
|
|
2013-05-14 22:24:26 +02:00
|
|
|
struct bus_body_part body;
|
|
|
|
struct bus_body_part *body_end;
|
|
|
|
unsigned n_body_parts;
|
2013-03-19 20:03:16 +01:00
|
|
|
|
2013-03-20 03:15:03 +01:00
|
|
|
size_t rindex;
|
2013-05-14 22:24:26 +02:00
|
|
|
struct bus_body_part *cached_rindex_part;
|
|
|
|
size_t cached_rindex_part_begin;
|
2013-03-20 03:15:03 +01:00
|
|
|
|
2013-03-19 20:03:16 +01:00
|
|
|
uint32_t n_fds;
|
|
|
|
int *fds;
|
|
|
|
|
2013-03-20 03:15:03 +01:00
|
|
|
struct bus_container root_container, *containers;
|
2015-02-13 17:32:38 +01:00
|
|
|
size_t n_containers;
|
2013-12-16 20:00:25 +01:00
|
|
|
size_t containers_allocated;
|
2013-03-19 20:03:16 +01:00
|
|
|
|
2013-05-14 22:24:26 +02:00
|
|
|
struct iovec *iovec;
|
2013-05-15 02:56:45 +02:00
|
|
|
struct iovec iovec_fixed[2];
|
2013-03-19 20:03:16 +01:00
|
|
|
unsigned n_iovec;
|
2013-03-20 03:15:03 +01:00
|
|
|
|
|
|
|
char *peeked_signature;
|
2013-04-11 23:09:29 +02:00
|
|
|
|
2013-12-02 15:28:20 +01:00
|
|
|
/* If set replies to this message must carry the signature
|
|
|
|
* specified here to successfully seal. This is initialized
|
|
|
|
* from the vtable data */
|
|
|
|
const char *enforced_reply_signature;
|
|
|
|
|
2013-04-11 23:09:29 +02:00
|
|
|
usec_t timeout;
|
2013-04-12 20:17:00 +02:00
|
|
|
|
2013-12-05 02:46:54 +01:00
|
|
|
size_t header_offsets[_BUS_MESSAGE_HEADER_MAX];
|
|
|
|
unsigned n_header_offsets;
|
2019-03-29 15:40:56 +01:00
|
|
|
|
|
|
|
uint64_t read_counter;
|
2013-03-19 20:03:16 +01:00
|
|
|
};
|
|
|
|
|
2015-02-13 17:32:38 +01:00
|
|
|
static inline bool BUS_MESSAGE_NEED_BSWAP(sd_bus_message *m) {
|
|
|
|
return m->header->endian != BUS_NATIVE_ENDIAN;
|
|
|
|
}
|
2013-03-19 20:03:16 +01:00
|
|
|
|
2013-03-20 03:15:03 +01:00
|
|
|
static inline uint16_t BUS_MESSAGE_BSWAP16(sd_bus_message *m, uint16_t u) {
|
|
|
|
return BUS_MESSAGE_NEED_BSWAP(m) ? bswap_16(u) : u;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline uint32_t BUS_MESSAGE_BSWAP32(sd_bus_message *m, uint32_t u) {
|
2013-03-19 20:03:16 +01:00
|
|
|
return BUS_MESSAGE_NEED_BSWAP(m) ? bswap_32(u) : u;
|
|
|
|
}
|
|
|
|
|
2013-03-20 03:15:03 +01:00
|
|
|
static inline uint64_t BUS_MESSAGE_BSWAP64(sd_bus_message *m, uint64_t u) {
|
|
|
|
return BUS_MESSAGE_NEED_BSWAP(m) ? bswap_64(u) : u;
|
|
|
|
}
|
|
|
|
|
2014-03-13 20:33:22 +01:00
|
|
|
static inline uint64_t BUS_MESSAGE_COOKIE(sd_bus_message *m) {
|
2015-02-13 17:32:38 +01:00
|
|
|
if (m->header->version == 2)
|
|
|
|
return BUS_MESSAGE_BSWAP64(m, m->header->dbus2.cookie);
|
2013-03-19 20:03:16 +01:00
|
|
|
|
2015-02-13 17:32:38 +01:00
|
|
|
return BUS_MESSAGE_BSWAP32(m, m->header->dbus1.serial);
|
2013-03-19 20:03:16 +01:00
|
|
|
}
|
|
|
|
|
2015-02-13 17:32:38 +01:00
|
|
|
static inline size_t BUS_MESSAGE_SIZE(sd_bus_message *m) {
|
2013-04-11 23:09:29 +02:00
|
|
|
return
|
|
|
|
sizeof(struct bus_header) +
|
2015-02-13 17:32:38 +01:00
|
|
|
ALIGN8(m->fields_size) +
|
|
|
|
m->body_size;
|
2013-04-11 23:09:29 +02:00
|
|
|
}
|
|
|
|
|
2015-02-13 17:32:38 +01:00
|
|
|
static inline size_t BUS_MESSAGE_BODY_BEGIN(sd_bus_message *m) {
|
2013-05-15 02:56:45 +02:00
|
|
|
return
|
|
|
|
sizeof(struct bus_header) +
|
2015-02-13 17:32:38 +01:00
|
|
|
ALIGN8(m->fields_size);
|
2013-05-15 02:56:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void* BUS_MESSAGE_FIELDS(sd_bus_message *m) {
|
|
|
|
return (uint8_t*) m->header + sizeof(struct bus_header);
|
|
|
|
}
|
|
|
|
|
2013-12-09 23:03:21 +01:00
|
|
|
static inline bool BUS_MESSAGE_IS_GVARIANT(sd_bus_message *m) {
|
|
|
|
return m->header->version == 2;
|
|
|
|
}
|
|
|
|
|
2013-03-19 20:03:16 +01:00
|
|
|
int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz);
|
2013-03-20 22:56:25 +01:00
|
|
|
int bus_message_read_strv_extend(sd_bus_message *m, char ***l);
|
2013-03-24 22:02:05 +01:00
|
|
|
|
2013-04-11 23:09:29 +02:00
|
|
|
int bus_message_from_header(
|
2013-11-21 01:51:16 +01:00
|
|
|
sd_bus *bus,
|
2013-04-11 23:09:29 +02:00
|
|
|
void *header,
|
2015-02-13 17:32:38 +01:00
|
|
|
size_t header_accessible,
|
|
|
|
void *footer,
|
|
|
|
size_t footer_accessible,
|
|
|
|
size_t message_size,
|
2013-04-11 23:09:29 +02:00
|
|
|
int *fds,
|
tree-wide: be more careful with the type of array sizes
Previously we were a bit sloppy with the index and size types of arrays,
we'd regularly use unsigned. While I don't think this ever resulted in
real issues I think we should be more careful there and follow a
stricter regime: unless there's a strong reason not to use size_t for
array sizes and indexes, size_t it should be. Any allocations we do
ultimately will use size_t anyway, and converting forth and back between
unsigned and size_t will always be a source of problems.
Note that on 32bit machines "unsigned" and "size_t" are equivalent, and
on 64bit machines our arrays shouldn't grow that large anyway, and if
they do we have a problem, however that kind of overly large allocation
we have protections for usually, but for overflows we do not have that
so much, hence let's add it.
So yeah, it's a story of the current code being already "good enough",
but I think some extra type hygiene is better.
This patch tries to be comprehensive, but it probably isn't and I missed
a few cases. But I guess we can cover that later as we notice it. Among
smaller fixes, this changes:
1. strv_length()' return type becomes size_t
2. the unit file changes array size becomes size_t
3. DNS answer and query array sizes become size_t
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=76745
2018-04-27 14:09:31 +02:00
|
|
|
size_t n_fds,
|
2013-04-11 23:09:29 +02:00
|
|
|
const char *label,
|
|
|
|
size_t extra,
|
|
|
|
sd_bus_message **ret);
|
|
|
|
|
2013-03-24 22:02:05 +01:00
|
|
|
int bus_message_from_malloc(
|
2013-11-21 01:51:16 +01:00
|
|
|
sd_bus *bus,
|
2013-03-24 22:02:05 +01:00
|
|
|
void *buffer,
|
|
|
|
size_t length,
|
|
|
|
int *fds,
|
tree-wide: be more careful with the type of array sizes
Previously we were a bit sloppy with the index and size types of arrays,
we'd regularly use unsigned. While I don't think this ever resulted in
real issues I think we should be more careful there and follow a
stricter regime: unless there's a strong reason not to use size_t for
array sizes and indexes, size_t it should be. Any allocations we do
ultimately will use size_t anyway, and converting forth and back between
unsigned and size_t will always be a source of problems.
Note that on 32bit machines "unsigned" and "size_t" are equivalent, and
on 64bit machines our arrays shouldn't grow that large anyway, and if
they do we have a problem, however that kind of overly large allocation
we have protections for usually, but for overflows we do not have that
so much, hence let's add it.
So yeah, it's a story of the current code being already "good enough",
but I think some extra type hygiene is better.
This patch tries to be comprehensive, but it probably isn't and I missed
a few cases. But I guess we can cover that later as we notice it. Among
smaller fixes, this changes:
1. strv_length()' return type becomes size_t
2. the unit file changes array size becomes size_t
3. DNS answer and query array sizes become size_t
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=76745
2018-04-27 14:09:31 +02:00
|
|
|
size_t n_fds,
|
2013-03-24 22:02:05 +01:00
|
|
|
const char *label,
|
|
|
|
sd_bus_message **ret);
|
2013-03-31 16:16:37 +02:00
|
|
|
|
2015-08-25 19:28:30 +02:00
|
|
|
int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str);
|
|
|
|
int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv);
|
2013-04-05 04:15:39 +02:00
|
|
|
|
2013-04-11 23:09:29 +02:00
|
|
|
int bus_message_parse_fields(sd_bus_message *m);
|
|
|
|
|
2013-05-14 22:24:26 +02:00
|
|
|
struct bus_body_part *message_append_part(sd_bus_message *m);
|
2013-05-15 01:43:15 +02:00
|
|
|
|
|
|
|
#define MESSAGE_FOREACH_PART(part, i, m) \
|
|
|
|
for ((i) = 0, (part) = &(m)->body; (i) < (m)->n_body_parts; (i)++, (part) = (part)->next)
|
2013-05-16 02:04:13 +02:00
|
|
|
|
|
|
|
int bus_body_part_map(struct bus_body_part *part);
|
|
|
|
void bus_body_part_unmap(struct bus_body_part *part);
|
2013-05-16 21:14:56 +02:00
|
|
|
|
|
|
|
int bus_message_to_errno(sd_bus_message *m);
|
|
|
|
|
|
|
|
int bus_message_new_synthetic_error(sd_bus *bus, uint64_t serial, const sd_bus_error *e, sd_bus_message **m);
|
2013-12-17 02:43:45 +01:00
|
|
|
|
|
|
|
int bus_message_remarshal(sd_bus *bus, sd_bus_message **m);
|
2013-12-23 02:59:03 +01:00
|
|
|
|
2015-01-07 20:25:30 +01:00
|
|
|
void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m);
|
|
|
|
void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m);
|
bus-message: introduce two kinds of references to bus messages
Before this commit bus messages had a single reference count: when it
reached zero the message would be freed. This simple approach meant a
cyclic dependency was typically seen: a message that was enqueued in a
bus connection object would reference the bus connection object but also
itself be referenced by the bus connection object. So far out strategy
to avoid cases like this was: make sure to process the bus connection
regularly so that messages don#t stay queued, and at exit flush/close
the connection so that the message queued would be emptied, and thus the
cyclic dependencies resolved. Im many cases this isn't done properly
however.
With this change, let's address the issue more systematically: let's
break the reference cycle. Specifically, there are now two types of
references to a bus message:
1. A regular one, which keeps both the message and the bus object it is
associated with pinned.
2. A "queue" reference, which is weaker: it pins the message, but not
the bus object it is associated with.
The idea is then that regular user handling uses regular references, but
when a message is enqueued on its connection, then this takes a "queue"
reference instead. This then means that a queued message doesn't imply
the connection itself remains pinned, only regular references to the
connection or a message associated with it do. Thus, if we end up in the
situation where a user allocates a bus and a message and enqueues the
latter in the former and drops all refs to both, then this will detect
this case and free both.
Note that this scheme isn't perfect, it only covers references between
messages and the busses they are associated with. If OTOH a bus message
is enqueued on a different bus than it is associated with cyclic deps
cannot be recognized with this simple algorithm, and thus if you enqueue
a message associated with a bus A on a bus B, and another message
associated with bus B on a bus A, a cyclic ref will be in effect and not
be discovered. However, given that this is an exotic case (though one
that happens, consider systemd-bus-stdio-bridge), it should be OK not to
cover with this, and people have to explicit flush all queues on exit in
that case.
Note that this commit only establishes the separate reference counters
per message. A follow-up commit will start making use of this from the
bus connection object.
2019-01-17 18:18:54 +01:00
|
|
|
|
|
|
|
sd_bus_message* bus_message_ref_queued(sd_bus_message *m, sd_bus *bus);
|
|
|
|
sd_bus_message* bus_message_unref_queued(sd_bus_message *m, sd_bus *bus);
|