[PATCH 1/2] dbus: Better search for matching rules in the filter tree
by Andrew Zaborowski
When adding new filter rules, perform a more complete search for
existing rules that already cover the rule being added by removing the
requierement that levels in the tree are ordered by the match type.
This may add overhead to adding new rules in some situations but will
reduce the number of server-side rules being used and the number of
requests. This covers a scenario where first a watch is added for:
type=signal, path=/
followed by
type=signal, sender=org.test, path=/
I believe there are some more tricky scenarios which are not covered
specifically when more than one child of an existing node matches some
condition of the rule being added.
---
ell/dbus-filter.c | 67 +++++++++++++++++++++++++++++++++++++++++++-----------
ell/dbus-private.h | 8 +++----
2 files changed, 58 insertions(+), 17 deletions(-)
diff --git a/ell/dbus-filter.c b/ell/dbus-filter.c
index 42755a9..9e3cad5 100644
--- a/ell/dbus-filter.c
+++ b/ell/dbus-filter.c
@@ -234,34 +234,63 @@ static bool remove_recurse(struct _dbus_filter *filter,
}
unsigned int _dbus_filter_add_rule(struct _dbus_filter *filter,
- struct _dbus_filter_condition *rule,
- int rule_len,
- l_dbus_message_func_t signal_func,
- void *user_data)
+ const struct _dbus_filter_condition *rule,
+ int rule_len,
+ l_dbus_message_func_t signal_func,
+ void *user_data)
{
struct filter_node **node_ptr = &filter->root;
struct filter_node *node;
struct filter_node *parent = filter->root;
bool remote_rule = false;
- struct _dbus_filter_condition *condition, *end = rule + rule_len;
-
- qsort(rule, rule_len, sizeof(*rule), condition_compare);
-
- for (condition = rule; condition < end; condition++) {
- /* See if this condition is already a child of the node */
+ struct _dbus_filter_condition sorted[rule_len];
+ struct _dbus_filter_condition *unused, *condition;
+ struct _dbus_filter_condition *end = sorted + rule_len;
+
+ memcpy(sorted, rule, sizeof(sorted));
+ qsort(sorted, rule_len, sizeof(*condition), condition_compare);
+
+ /*
+ * Find or create a path in the tree with a node for each
+ * condition in the rule, loop until all conditions have been
+ * used.
+ */
+ unused = sorted;
+ while (unused < end) {
+ /*
+ * Find a child of the node that matches any unused
+ * condition. Note there could be multiple matches, we're
+ * happy with the first we can find.
+ */
while (*node_ptr) {
node = *node_ptr;
- if (node->type == condition->type &&
- !strcmp(node->match.value,
+ for (condition = unused; condition < end; condition++) {
+ if (condition->type > node->type) {
+ condition = end;
+ break;
+ }
+
+ if (condition->type < node->type ||
+ condition->type ==
+ L_DBUS_MATCH_NONE)
+ continue;
+
+ if (!strcmp(node->match.value,
condition->value))
+ break;
+ }
+
+ if (condition < end)
break;
node_ptr = &node->next;
}
- /* Add one */
+ /* Add a node */
if (!*node_ptr) {
+ condition = unused;
+
node = l_new(struct filter_node, 1);
node->type = condition->type;
node->match.value = l_strdup(condition->value);
@@ -278,6 +307,18 @@ unsigned int _dbus_filter_add_rule(struct _dbus_filter *filter,
}
+ /*
+ * Mark the condition used. We do this by setting
+ * condition->type to an invalid value unless it is the
+ * first condition left in which case we can push the
+ * rule start. Another option is to always push the rule
+ * start and memmove the still unused conditions by one
+ * if necessary.
+ */
+ condition->type = L_DBUS_MATCH_NONE;
+ while (unused < end && unused[0].type == L_DBUS_MATCH_NONE)
+ unused++;
+
node_ptr = &node->match.children;
parent = node;
diff --git a/ell/dbus-private.h b/ell/dbus-private.h
index ab52895..f4209b8 100644
--- a/ell/dbus-private.h
+++ b/ell/dbus-private.h
@@ -320,10 +320,10 @@ struct _dbus_filter *_dbus_filter_new(struct l_dbus *dbus,
void _dbus_filter_free(struct _dbus_filter *filter);
unsigned int _dbus_filter_add_rule(struct _dbus_filter *filter,
- struct _dbus_filter_condition *rule,
- int rule_len,
- l_dbus_message_func_t signal_func,
- void *user_data);
+ const struct _dbus_filter_condition *rule,
+ int rule_len,
+ l_dbus_message_func_t signal_func,
+ void *user_data);
bool _dbus_filter_remove_rule(struct _dbus_filter *filter, unsigned int id);
char *_dbus_filter_rule_to_str(const struct _dbus_filter_condition *rule,
--
2.5.0
6 years
[PATCH 1/5] dbus: Handle the 'h' type in append_arguments
by Andrew Zaborowski
FD values can't be handled same as int32 values ('i' and 'u').
---
ell/dbus-message.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/ell/dbus-message.c b/ell/dbus-message.c
index 6089295..038d44d 100644
--- a/ell/dbus-message.c
+++ b/ell/dbus-message.c
@@ -1140,7 +1140,6 @@ static bool append_arguments(struct l_dbus_message *message,
}
case 'i':
case 'u':
- case 'h':
{
uint32_t u = va_arg(args, uint32_t);
@@ -1149,6 +1148,20 @@ static bool append_arguments(struct l_dbus_message *message,
break;
}
+ case 'h':
+ {
+ int fd = va_arg(args, int);
+
+ if (!driver->append_basic(builder, *s,
+ &message->num_fds))
+ goto error;
+
+ if (message->num_fds < L_ARRAY_SIZE(message->fds))
+ message->fds[message->num_fds++] =
+ fcntl(fd, F_DUPFD_CLOEXEC, 3);
+
+ break;
+ }
case 'x':
case 't':
{
--
2.5.0
6 years
[PATCH] timeout: Clearified the ruturn behavior in comments
by Tim Kourt
---
ell/timeout.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/ell/timeout.c b/ell/timeout.c
index 499c6d6..4ba4e6e 100644
--- a/ell/timeout.c
+++ b/ell/timeout.c
@@ -103,7 +103,8 @@ static inline int timeout_set(int fd, unsigned int seconds, long nanoseconds)
* The timeout will on fire once. The timeout handling needs to be rearmed
* with l_timeout_modify() to trigger again.
*
- * Returns: a newly allocated #l_timeout object
+ * Returns: a newly allocated #l_timeout object. On failure, the function
+ * returns NULL.
**/
LIB_EXPORT struct l_timeout *l_timeout_create(unsigned int seconds,
l_timeout_notify_cb_t callback,
@@ -126,7 +127,8 @@ LIB_EXPORT struct l_timeout *l_timeout_create(unsigned int seconds,
* The timeout will on fire once. The timeout handling needs to be rearmed
* with l_timeout_modify_with_nanoseconds() to trigger again.
*
- * Returns: a newly allocated #l_timeout object
+ * Returns: a newly allocated #l_timeout object. On failure, the function
+ * returns NULL.
**/
LIB_EXPORT struct l_timeout *l_timeout_create_with_nanoseconds(unsigned int seconds,
long nanoseconds, l_timeout_notify_cb_t callback,
--
2.5.0
6 years
[PATCH] dbus: Handle kdbus KDBUS_ITEM_REPLY_TIMEOUT / _DEAD
by Andrew Zaborowski
Generate DBus1-like error messages on kernel error notifications.
---
ell/dbus-kernel.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/ell/dbus-kernel.c b/ell/dbus-kernel.c
index b5a07a5..4fd2f29 100644
--- a/ell/dbus-kernel.c
+++ b/ell/dbus-kernel.c
@@ -559,6 +559,7 @@ int _dbus_kernel_recv(int fd, void *kdbus_pool,
struct kdbus_item *item;
int r;
size_t min_size;
+ const char *error;
memset(&recv_cmd, 0, sizeof(recv_cmd));
@@ -601,6 +602,23 @@ int _dbus_kernel_recv(int fd, void *kdbus_pool,
user_data);
break;
+ case KDBUS_ITEM_REPLY_TIMEOUT:
+ case KDBUS_ITEM_REPLY_DEAD:
+ if (item->type == KDBUS_ITEM_REPLY_TIMEOUT)
+ error = "Did not receive a reply.";
+ else
+ error = "Message recipient disconnected from "
+ "message bus without replying.";
+
+ dbus_msg = _dbus_message_new_error(
+ 2, msg->cookie_reply, NULL,
+ "org.freedesktop.DBus.Error.NoReply",
+ error);
+ if (dbus_msg)
+ message_func(dbus_msg, user_data);
+
+ break;
+
default:
break;
}
--
2.5.0
6 years
[PATCH v2 1/2] util: Add suffix check for a string
by Tim Kourt
---
ell/util.c | 32 ++++++++++++++++++++++++++++++++
ell/util.h | 1 +
2 files changed, 33 insertions(+)
diff --git a/ell/util.c b/ell/util.c
index f920895..98916e5 100644
--- a/ell/util.c
+++ b/ell/util.c
@@ -444,6 +444,38 @@ LIB_EXPORT bool l_str_has_prefix(const char *str, const char *prefix)
}
/**
+ * l_str_has_suffix:
+ * @str: A string to be examined
+ * @suffix: Suffix string
+ *
+ * Determines if the string given by @str ends with the specified @suffix.
+ *
+ * Returns: True if @str ends with the specified @suffix. False otherwise.
+ */
+LIB_EXPORT bool l_str_has_suffix(const char *str, const char *suffix)
+{
+ size_t str_len;
+ size_t suffix_len;
+ size_t len_diff;
+
+ if (unlikely(!str))
+ return false;
+
+ if (unlikely(!suffix))
+ return false;
+
+ str_len = strlen(str);
+ suffix_len = strlen(suffix);
+
+ if (str_len < suffix_len)
+ return false;
+
+ len_diff = str_len - suffix_len;
+
+ return !strcmp(&str[len_diff], suffix);
+}
+
+/**
* l_util_hexstring:
* @buf: buffer pointer
* @len: length of buffer
diff --git a/ell/util.h b/ell/util.h
index f6a88a0..92e7c8a 100644
--- a/ell/util.h
+++ b/ell/util.h
@@ -208,6 +208,7 @@ char **l_strsplit_set(const char *str, const char *separators);
char *l_strjoinv(char **str_array, const char delim);
bool l_str_has_prefix(const char *str, const char *prefix);
+bool l_str_has_suffix(const char *str, const char *suffix);
char *l_util_hexstring(const unsigned char *buf, size_t len);
unsigned char *l_util_from_hexstring(const char *str, size_t *out_len);
--
2.5.0
6 years
[PATCH 1/2] util: Add suffix check for a string
by Tim Kourt
---
ell/util.c | 27 +++++++++++++++++++++++++++
ell/util.h | 1 +
2 files changed, 28 insertions(+)
diff --git a/ell/util.c b/ell/util.c
index f920895..895f95f 100644
--- a/ell/util.c
+++ b/ell/util.c
@@ -444,6 +444,33 @@ LIB_EXPORT bool l_str_has_prefix(const char *str, const char *prefix)
}
/**
+ * l_str_has_suffix:
+ * @str: A string to be examined
+ * @suffix: Suffix string
+ *
+ * Determines if the string given by @str ends with the specified @suffix.
+ *
+ * Returns: True if @str ends with the specified @suffix. False otherwise.
+ */
+LIB_EXPORT bool l_str_has_suffix(const char *str, const char *suffix)
+{
+ int str_len_diff;
+
+ if (unlikely(!str))
+ return false;
+
+ if (unlikely(!suffix))
+ return false;
+
+ str_len_diff = strlen(str) - strlen(suffix);
+
+ if (str_len_diff < 0)
+ return false;
+
+ return !strcmp(&str[str_len_diff], suffix);
+}
+
+/**
* l_util_hexstring:
* @buf: buffer pointer
* @len: length of buffer
diff --git a/ell/util.h b/ell/util.h
index f6a88a0..92e7c8a 100644
--- a/ell/util.h
+++ b/ell/util.h
@@ -208,6 +208,7 @@ char **l_strsplit_set(const char *str, const char *separators);
char *l_strjoinv(char **str_array, const char delim);
bool l_str_has_prefix(const char *str, const char *prefix);
+bool l_str_has_suffix(const char *str, const char *suffix);
char *l_util_hexstring(const unsigned char *buf, size_t len);
unsigned char *l_util_from_hexstring(const char *str, size_t *out_len);
--
2.5.0
6 years
[PATCH v3 1/9] dbus: Update GVariant message header format
by Andrew Zaborowski
In the current GVariant message format since about Jan 2015 there's no
body size field (it is reserved and must be sent as 0) or header size
information or signature. The message needs to be parsed as a single
GVariant blob if we want to split it into a header and a body.
---
ell/dbus-kernel.c | 3 -
ell/dbus-message.c | 167 ++++++++++++++++++++++++++++++++++++++---------------
ell/dbus-private.h | 16 ++++-
ell/dbus-util.c | 4 +-
ell/dbus.c | 4 +-
5 files changed, 137 insertions(+), 57 deletions(-)
diff --git a/ell/dbus-kernel.c b/ell/dbus-kernel.c
index 09721c2..4a3aed0 100644
--- a/ell/dbus-kernel.c
+++ b/ell/dbus-kernel.c
@@ -551,9 +551,6 @@ static int _dbus_kernel_make_message(struct kdbus_msg *kmsg,
if (hdr->version != 2)
return -EPROTO;
- if (hdr->body_length != body_size)
- return -EBADMSG;
-
r = collect_body_parts(kmsg, header_size, &header,
body_size, &body);
if (r < 0)
diff --git a/ell/dbus-message.c b/ell/dbus-message.c
index 3bc52ea..9fdc0ff 100644
--- a/ell/dbus-message.c
+++ b/ell/dbus-message.c
@@ -58,7 +58,8 @@ struct l_dbus_message {
int refcount;
void *header;
size_t header_size;
- const char *signature;
+ size_t header_end;
+ char *signature;
void *body;
size_t body_size;
char *path;
@@ -74,6 +75,7 @@ struct l_dbus_message {
bool sealed : 1;
bool kdbus_sender : 1;
bool kdbus_destination : 1;
+ bool signature_free : 1;
};
struct l_dbus_message_builder {
@@ -109,14 +111,20 @@ void _dbus_message_set_serial(struct l_dbus_message *msg, uint32_t serial)
{
struct dbus_header *hdr = msg->header;
- hdr->serial = serial;
+ if (_dbus_message_is_gvariant(msg))
+ hdr->kdbus.cookie = serial;
+ else
+ hdr->dbus1.serial = serial;
}
uint32_t _dbus_message_get_serial(struct l_dbus_message *msg)
{
struct dbus_header *hdr = msg->header;
- return hdr->serial;
+ if (_dbus_message_is_gvariant(msg))
+ return hdr->kdbus.cookie;
+ else
+ return hdr->dbus1.serial;
}
LIB_EXPORT bool l_dbus_message_set_no_reply(struct l_dbus_message *msg, bool on)
@@ -196,10 +204,12 @@ static struct l_dbus_message *message_new_common(uint8_t type, uint8_t flags,
/*
* We allocate the header with the initial 12 bytes (up to the field
- * length) so that we can store the basic information here
+ * length) so that we can store the basic information here. For
+ * GVariant we need 16 bytes.
*/
- message->header = l_realloc(NULL, 12);
- message->header_size = 12;
+ message->header_size = version == 1 ? 12 : 16;
+ message->header_end = message->header_size;
+ message->header = l_realloc(NULL, message->header_size);
hdr = message->header;
hdr->endian = DBUS_NATIVE_ENDIAN;
@@ -290,7 +300,7 @@ LIB_EXPORT struct l_dbus_message *l_dbus_message_new_method_return(
DBUS_MESSAGE_FLAG_NO_REPLY_EXPECTED,
hdr->version);
- message->reply_serial = hdr->serial;
+ message->reply_serial = _dbus_message_get_serial(method_call);
sender = l_dbus_message_get_sender(method_call);
if (sender)
@@ -317,7 +327,7 @@ LIB_EXPORT struct l_dbus_message *l_dbus_message_new_error_valist(
DBUS_MESSAGE_FLAG_NO_REPLY_EXPECTED,
hdr->version);
- reply->reply_serial = hdr->serial;
+ reply->reply_serial = _dbus_message_get_serial(method_call);
sender = l_dbus_message_get_sender(method_call);
if (sender)
@@ -387,6 +397,9 @@ LIB_EXPORT void l_dbus_message_unref(struct l_dbus_message *message)
if (message->kdbus_destination)
l_free(message->destination);
+ if (message->signature_free)
+ l_free(message->signature);
+
l_free(message->header);
l_free(message->body);
l_free(message);
@@ -567,20 +580,11 @@ static bool get_header_field_from_iter_valist(struct l_dbus_message *message,
return false;
if (_dbus_message_is_gvariant(message)) {
- uint32_t header_length;
uint64_t field_type;
- if (!_gvariant_iter_init(&header, message, "yyyyuuu", NULL,
- message->header, message->header_size))
- return false;
-
- if (!message_iter_next_entry(&header, &endian, &message_type,
- &flags, &version, &body_length,
- &serial, &header_length))
- return false;
-
if (!_gvariant_iter_init(&header, message, "a(tv)", NULL,
- message->header + 16, header_length))
+ message->header + 16,
+ message->header_end - 16))
return false;
if (!_gvariant_iter_enter_array(&header, &array))
@@ -643,8 +647,14 @@ static bool valid_header(const struct dbus_header *hdr)
if (hdr->version != 1 && hdr->version != 2)
return false;
- if (hdr->serial == 0)
- return false;
+ if (hdr->version == 1) {
+ if (hdr->dbus1.serial == 0)
+ return false;
+ } else {
+ /* We don't support 64-bit GVariant cookies */
+ if (hdr->kdbus.cookie == 0 || (hdr->kdbus.cookie >> 32))
+ return false;
+ }
return true;
}
@@ -653,6 +663,7 @@ struct l_dbus_message *dbus_message_from_blob(const void *data, size_t size)
{
const struct dbus_header *hdr = data;
struct l_dbus_message *message;
+ size_t body_pos;
if (unlikely(size < DBUS_HEADER_SIZE))
return NULL;
@@ -661,28 +672,66 @@ struct l_dbus_message *dbus_message_from_blob(const void *data, size_t size)
message->refcount = 1;
- message->header_size = align_len(DBUS_HEADER_SIZE +
- hdr->field_length, 8);
- message->body_size = hdr->body_length;
+ if (hdr->version == 1) {
+ message->header_size = align_len(DBUS_HEADER_SIZE +
+ hdr->dbus1.field_length, 8);
+ message->body_size = hdr->dbus1.body_length;
- if (message->header_size + message->body_size < size) {
- l_free(message);
- return NULL;
+ if (message->header_size + message->body_size < size)
+ goto free;
+
+ body_pos = message->header_size;
+ } else {
+ struct l_dbus_message_iter iter;
+ struct l_dbus_message_iter header, variant, body;
+
+ /*
+ * GVariant message structure as per
+ * https://wiki.gnome.org/Projects/GLib/GDBus/Version2
+ * is "(yyyyuta{tv}v)". As noted this is equivalent to
+ * some other types, this one lets us get iterators for
+ * the header and the body in the fewest steps.
+ */
+ if (!_gvariant_iter_init(&iter, message, "(yyyyuta{tv})v",
+ NULL, data, size))
+ goto free;
+
+ if (!_gvariant_iter_enter_struct(&iter, &header))
+ goto free;
+
+ if (!_gvariant_iter_enter_variant(&iter, &variant))
+ goto free;
+
+ if (!_gvariant_iter_enter_struct(&variant, &body))
+ goto free;
+
+ message->header_size = align_len(header.len - header.pos, 8);
+ message->body_size = body.len - body.pos;
+ message->signature = l_strndup(body.sig_start + body.sig_pos,
+ body.sig_len - body.sig_pos);
+ message->signature_free = true;
+ message->header_end = header.len;
+ body_pos = body.data + body.pos - data;
}
message->header = l_malloc(message->header_size);
message->body = l_malloc(message->body_size);
memcpy(message->header, data, message->header_size);
- memcpy(message->body, data + message->header_size, message->body_size);
+ memcpy(message->body, data + body_pos, message->body_size);
message->sealed = true;
/* If the field is absent message->signature will remain NULL */
- get_header_field(message, DBUS_MESSAGE_FIELD_SIGNATURE, 'g',
- &message->signature);
+ if (hdr->version == 1)
+ get_header_field(message, DBUS_MESSAGE_FIELD_SIGNATURE,
+ 'g', &message->signature);
return message;
+
+free:
+ l_free(message);
+ return NULL;
}
struct l_dbus_message *dbus_message_build(void *header, size_t header_size,
@@ -698,6 +747,13 @@ struct l_dbus_message *dbus_message_build(void *header, size_t header_size,
if (unlikely(!valid_header(hdr)))
return NULL;
+ /*
+ * With GVariant we need to know the signature, use
+ * dbus_message_from_blob instead.
+ */
+ if (unlikely(hdr->version != 1))
+ return NULL;
+
message = l_new(struct l_dbus_message, 1);
message->refcount = 1;
@@ -825,23 +881,19 @@ static void build_header(struct l_dbus_message *message, const char *signature)
struct dbus_builder *builder;
struct builder_driver *driver;
char *generated_signature;
- struct dbus_header *hdr;
size_t header_size;
+ bool gvariant;
- if (_dbus_message_is_gvariant(message))
+ gvariant = _dbus_message_is_gvariant(message);
+
+ if (gvariant)
driver = &gvariant_driver;
else
driver = &dbus1_driver;
builder = driver->new(message->header, message->header_size);
- if (_dbus_message_is_gvariant(message)) {
- uint32_t field_length = 0;
- driver->append_basic(builder, 'u', &field_length);
- }
-
- driver->enter_array(builder, _dbus_message_is_gvariant(message) ?
- "(tv)" : "(yv)");
+ driver->enter_array(builder, gvariant ? "(tv)" : "(yv)");
if (message->path) {
add_field(builder, driver, DBUS_MESSAGE_FIELD_PATH,
@@ -879,8 +931,18 @@ static void build_header(struct l_dbus_message *message, const char *signature)
}
if (message->reply_serial != 0) {
- add_field(builder, driver, DBUS_MESSAGE_FIELD_REPLY_SERIAL,
+ if (gvariant) {
+ uint64_t reply_serial = message->reply_serial;
+
+ add_field(builder, driver,
+ DBUS_MESSAGE_FIELD_REPLY_SERIAL,
+ "t", &reply_serial);
+ } else {
+ add_field(builder, driver,
+ DBUS_MESSAGE_FIELD_REPLY_SERIAL,
"u", &message->reply_serial);
+ }
+
message->reply_serial = 0;
}
@@ -903,18 +965,18 @@ static void build_header(struct l_dbus_message *message, const char *signature)
driver->free(builder);
- hdr = message->header;
-
- if (_dbus_message_is_gvariant(message))
- hdr->field_length = header_size - 16;
+ if (!_dbus_message_is_gvariant(message)) {
+ struct dbus_header *hdr = message->header;
- hdr->body_length = message->body_size;
+ hdr->dbus1.body_length = message->body_size;
+ }
/* We must align the end of the header to an 8-byte boundary */
message->header_size = align_len(header_size, 8);
message->header = l_realloc(message->header, message->header_size);
memset(message->header + header_size, 0,
message->header_size - header_size);
+ message->header_end = header_size;
}
struct container {
@@ -1313,9 +1375,20 @@ uint32_t _dbus_message_get_reply_serial(struct l_dbus_message *message)
if (unlikely(!message))
return 0;
- if (message->reply_serial == 0)
- get_header_field(message, DBUS_MESSAGE_FIELD_REPLY_SERIAL, 'u',
+ if (message->reply_serial == 0) {
+ if (_dbus_message_is_gvariant(message)) {
+ uint64_t reply_serial;
+
+ get_header_field(message,
+ DBUS_MESSAGE_FIELD_REPLY_SERIAL, 't',
+ &reply_serial);
+
+ message->reply_serial = reply_serial;
+ } else
+ get_header_field(message,
+ DBUS_MESSAGE_FIELD_REPLY_SERIAL, 'u',
&message->reply_serial);
+ }
return message->reply_serial;
}
diff --git a/ell/dbus-private.h b/ell/dbus-private.h
index 764ed42..6a4ea96 100644
--- a/ell/dbus-private.h
+++ b/ell/dbus-private.h
@@ -49,9 +49,19 @@ struct dbus_header {
uint8_t message_type;
uint8_t flags;
uint8_t version;
- uint32_t body_length;
- uint32_t serial;
- uint32_t field_length;
+
+ union {
+ struct {
+ uint32_t body_length;
+ uint32_t serial;
+ uint32_t field_length;
+ } __attribute__ ((packed)) dbus1;
+
+ struct {
+ uint32_t reserved1;
+ uint64_t cookie;
+ } __attribute__ ((packed)) kdbus;
+ };
} __attribute__ ((packed));
#define DBUS_HEADER_SIZE 16
diff --git a/ell/dbus-util.c b/ell/dbus-util.c
index ab0600a..900b71b 100644
--- a/ell/dbus-util.c
+++ b/ell/dbus-util.c
@@ -423,9 +423,9 @@ bool _dbus_header_is_valid(void *data, size_t size)
hdr = data;
if (hdr->endian != DBUS_NATIVE_ENDIAN)
- header_len = bswap_32(hdr->field_length);
+ header_len = bswap_32(hdr->dbus1.field_length);
else
- header_len = hdr->field_length;
+ header_len = hdr->dbus1.field_length;
header_len += sizeof(struct dbus_header);
return size >= header_len;
diff --git a/ell/dbus.c b/ell/dbus.c
index 81a7f9e..9bb47ae 100644
--- a/ell/dbus.c
+++ b/ell/dbus.c
@@ -613,10 +613,10 @@ static struct l_dbus_message *classic_recv_message(struct l_dbus *dbus)
if (len != DBUS_HEADER_SIZE)
return NULL;
- header_size = align_len(DBUS_HEADER_SIZE + hdr.field_length, 8);
+ header_size = align_len(DBUS_HEADER_SIZE + hdr.dbus1.field_length, 8);
header = l_malloc(header_size);
- body_size = hdr.body_length;
+ body_size = hdr.dbus1.body_length;
body = l_malloc(body_size);
iov[0].iov_base = header;
--
2.5.0
6 years
[PATCH 1/2] dbus: Make _dbus_num_children a dbus-private function
by Andrew Zaborowski
---
ell/dbus-private.h | 1 +
ell/dbus-util.c | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/ell/dbus-private.h b/ell/dbus-private.h
index 6f39a2d..be43aba 100644
--- a/ell/dbus-private.h
+++ b/ell/dbus-private.h
@@ -156,6 +156,7 @@ const char *_dbus_signature_end(const char *signature);
bool _dbus_valid_object_path(const char *path);
bool _dbus_valid_signature(const char *sig);
+int _dbus_num_children(const char *sig);
bool _dbus_valid_interface(const char *interface);
bool _dbus_valid_method(const char *method);
bool _dbus_parse_unique_name(const char *name, uint64_t *out_id);
diff --git a/ell/dbus-util.c b/ell/dbus-util.c
index 4d79d11..6414216 100644
--- a/ell/dbus-util.c
+++ b/ell/dbus-util.c
@@ -249,7 +249,7 @@ bool _dbus_valid_signature(const char *sig)
return true;
}
-static int _dbus_num_children(const char *sig)
+int _dbus_num_children(const char *sig)
{
const char *s = sig;
int num_children = 0;
--
2.5.0
6 years
[PATCH 1/2] dbus: Add private _dbus_message_new_error
by Andrew Zaborowski
---
ell/dbus-message.c | 47 +++++++++++++++++++++++++++++++----------------
ell/dbus-private.h | 5 +++++
2 files changed, 36 insertions(+), 16 deletions(-)
diff --git a/ell/dbus-message.c b/ell/dbus-message.c
index a409e53..86cec96 100644
--- a/ell/dbus-message.c
+++ b/ell/dbus-message.c
@@ -328,33 +328,32 @@ LIB_EXPORT struct l_dbus_message *l_dbus_message_new_method_return(
return message;
}
-LIB_EXPORT struct l_dbus_message *l_dbus_message_new_error_valist(
- struct l_dbus_message *method_call,
- const char *name,
- const char *format, va_list args)
+struct l_dbus_message *_dbus_message_new_error(uint8_t version,
+ uint32_t reply_serial,
+ const char *destination,
+ const char *name,
+ const char *error)
{
- char str[1024];
struct l_dbus_message *reply;
- struct dbus_header *hdr = method_call->header;
- const char *sender;
+ bool r;
if (!_dbus_valid_interface(name))
return NULL;
- vsnprintf(str, sizeof(str), format, args);
reply = message_new_common(DBUS_MESSAGE_TYPE_ERROR,
DBUS_MESSAGE_FLAG_NO_REPLY_EXPECTED,
- hdr->version);
-
- reply->reply_serial = _dbus_message_get_serial(method_call);
-
- sender = l_dbus_message_get_sender(method_call);
- if (sender)
- reply->destination = l_strdup(sender);
+ version);
reply->error_name = l_strdup(name);
+ reply->destination = l_strdup(destination);
+ reply->reply_serial = reply_serial;
- if (!l_dbus_message_set_arguments(reply, "s", str)) {
+ if (error)
+ r = l_dbus_message_set_arguments(reply, "s", error);
+ else
+ r = l_dbus_message_set_arguments(reply, "");
+
+ if (!r) {
l_dbus_message_unref(reply);
return NULL;
}
@@ -362,6 +361,22 @@ LIB_EXPORT struct l_dbus_message *l_dbus_message_new_error_valist(
return reply;
}
+LIB_EXPORT struct l_dbus_message *l_dbus_message_new_error_valist(
+ struct l_dbus_message *method_call,
+ const char *name,
+ const char *format, va_list args)
+{
+ char str[1024];
+ struct dbus_header *hdr = method_call->header;
+
+ vsnprintf(str, sizeof(str), format, args);
+
+ return _dbus_message_new_error(hdr->version,
+ _dbus_message_get_serial(method_call),
+ l_dbus_message_get_sender(method_call),
+ name, str);
+}
+
LIB_EXPORT struct l_dbus_message *l_dbus_message_new_error(
struct l_dbus_message *method_call,
const char *name,
diff --git a/ell/dbus-private.h b/ell/dbus-private.h
index 63c239b..030ce0b 100644
--- a/ell/dbus-private.h
+++ b/ell/dbus-private.h
@@ -141,6 +141,11 @@ struct l_dbus_message *_dbus_message_new_signal(uint8_t version,
const char *path,
const char *interface,
const char *name);
+struct l_dbus_message *_dbus_message_new_error(uint8_t version,
+ uint32_t reply_serial,
+ const char *destination,
+ const char *name,
+ const char *error);
struct l_dbus_message *dbus_message_from_blob(const void *data, size_t size);
struct l_dbus_message *dbus_message_build(void *header, size_t header_size,
--
2.5.0
6 years
[PATCH RESEND] build: Add sanitizer options
by Mat Martineau
Build using Address Sanitizer (asan), Leak Sanitizer (lsan), or
Undefined Behavior Sanitizer (ubsan) by using one of these options for
the configure script:
--enable-asan
--enable-lsan
--enable-ubsan
For each of these to work, the compiler must support the requested
sanitizer and the requisite libraries must be installed (libasan,
liblsan, libubsan).
---
acinclude.m4 | 36 ++++++++++++++++++++++++++++++++++++
configure.ac | 45 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 81 insertions(+)
diff --git a/acinclude.m4 b/acinclude.m4
index 0ba4287..8aab4ee 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -10,6 +10,42 @@ AC_DEFUN([AC_PROG_CC_PIE], [
])
])
+AC_DEFUN([AC_PROG_CC_ASAN], [
+ AC_CACHE_CHECK([whether ${CC-cc} accepts -fsanitize=address], ac_cv_prog_cc_asan, [
+ echo 'void f(){}' > conftest.c
+ if test -z "`${CC-cc} -fsanitize=address -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_asan=yes
+ else
+ ac_cv_prog_cc_asan=no
+ fi
+ rm -rf conftest*
+ ])
+])
+
+AC_DEFUN([AC_PROG_CC_LSAN], [
+ AC_CACHE_CHECK([whether ${CC-cc} accepts -fsanitize=leak], ac_cv_prog_cc_lsan, [
+ echo 'void f(){}' > conftest.c
+ if test -z "`${CC-cc} -fsanitize=leak -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_lsan=yes
+ else
+ ac_cv_prog_cc_lsan=no
+ fi
+ rm -rf conftest*
+ ])
+])
+
+AC_DEFUN([AC_PROG_CC_UBSAN], [
+ AC_CACHE_CHECK([whether ${CC-cc} accepts -fsanitize=undefined], ac_cv_prog_cc_ubsan, [
+ echo 'void f(){}' > conftest.c
+ if test -z "`${CC-cc} -fsanitize=undefined -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_ubsan=yes
+ else
+ ac_cv_prog_cc_ubsan=no
+ fi
+ rm -rf conftest*
+ ])
+])
+
AC_DEFUN([COMPILER_FLAGS], [
if (test "${CFLAGS}" = ""); then
CFLAGS="-Wall -O2 -fsigned-char"
diff --git a/configure.ac b/configure.ac
index 39755fe..e4ca5b2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -20,6 +20,9 @@ AC_LANG_C
AC_PROG_CC
AC_PROG_CC_PIE
+AC_PROG_CC_ASAN
+AC_PROG_CC_LSAN
+AC_PROG_CC_UBSAN
AC_PROG_INSTALL
AC_C_CHAR_UNSIGNED
@@ -54,6 +57,48 @@ AC_ARG_ENABLE(pie, AC_HELP_STRING([--enable-pie],
fi
])
+save_LIBS=$LIBS
+AC_CHECK_LIB(asan, __sanitizer_cov_init)
+LIBS=$save_LIBS
+
+AC_ARG_ENABLE(asan, AC_HELP_STRING([--enable-asan],
+ [enable linking with address sanitizer]), [
+ if (test "${enableval}" = "yes" &&
+ test "${ac_cv_lib_asan___sanitizer_cov_init}" = "yes" &&
+ test "${ac_cv_prog_cc_asan}" = "yes"); then
+ CFLAGS="$CFLAGS -fsanitize=address";
+ LDFLAGS="$LDFLAGS -fsanitize=address"
+ fi
+])
+
+save_LIBS=$LIBS
+AC_CHECK_LIB(lsan, __sanitizer_cov_init)
+LIBS=$save_LIBS
+
+AC_ARG_ENABLE(lsan, AC_HELP_STRING([--enable-lsan],
+ [enable linking with leak sanitizer]), [
+ if (test "${enableval}" = "yes" &&
+ test "${ac_cv_lib_lsan___sanitizer_cov_init}" = "yes" &&
+ test "${ac_cv_prog_cc_lsan}" = "yes"); then
+ CFLAGS="$CFLAGS -fsanitize=leak";
+ LDFLAGS="$LDFLAGS -fsanitize=leak"
+ fi
+])
+
+save_LIBS=$LIBS
+AC_CHECK_LIB(ubsan, __sanitizer_cov_init)
+LIBS=$save_LIBS
+
+AC_ARG_ENABLE(ubsan, AC_HELP_STRING([--enable-ubsan],
+ [enable linking with undefined behavior sanitizer]), [
+ if (test "${enableval}" = "yes" &&
+ test "${ac_cv_lib_ubsan___sanitizer_cov_init}" = "yes" &&
+ test "${ac_cv_prog_cc_ubsan}" = "yes"); then
+ CFLAGS="$CFLAGS -fsanitize=undefined";
+ LDFLAGS="$LDFLAGS -fsanitize=undefined"
+ fi
+])
+
AC_CHECK_FUNC(signalfd, dummy=yes,
AC_MSG_ERROR(signalfd support is required))
--
2.8.1
6 years, 1 month