summaryrefslogtreecommitdiff
path: root/src/libsystemd/sd-bus
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsystemd/sd-bus')
-rw-r--r--src/libsystemd/sd-bus/bus-control.c16
-rw-r--r--src/libsystemd/sd-bus/bus-message.c17
-rw-r--r--src/libsystemd/sd-bus/bus-objects.c2
-rw-r--r--src/libsystemd/sd-bus/bus-socket.c20
-rw-r--r--src/libsystemd/sd-bus/test-bus-marshal.c21
-rw-r--r--src/libsystemd/sd-bus/test-bus-proxy.c109
6 files changed, 170 insertions, 15 deletions
diff --git a/src/libsystemd/sd-bus/bus-control.c b/src/libsystemd/sd-bus/bus-control.c
index a38c5c50fc..c53666ddd0 100644
--- a/src/libsystemd/sd-bus/bus-control.c
+++ b/src/libsystemd/sd-bus/bus-control.c
@@ -1131,7 +1131,7 @@ static int add_name_change_match(sd_bus *bus,
/* If the old name is unset or empty, then
* this can match against added names */
- if (!old_owner || old_owner[0] == 0) {
+ if (isempty(old_owner)) {
item->type = KDBUS_ITEM_NAME_ADD;
r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
@@ -1141,7 +1141,7 @@ static int add_name_change_match(sd_bus *bus,
/* If the new name is unset or empty, then
* this can match against removed names */
- if (!new_owner || new_owner[0] == 0) {
+ if (isempty(new_owner)) {
item->type = KDBUS_ITEM_NAME_REMOVE;
r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
@@ -1185,8 +1185,10 @@ static int add_name_change_match(sd_bus *bus,
/* If the old name is unset or empty, then this can
* match against added ids */
- if (!old_owner || old_owner[0] == 0) {
+ if (isempty(old_owner)) {
item->type = KDBUS_ITEM_ID_ADD;
+ if (!isempty(new_owner))
+ item->id_change.id = new_owner_id;
r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
if (r < 0)
@@ -1195,8 +1197,10 @@ static int add_name_change_match(sd_bus *bus,
/* If thew new name is unset or empty, then this can
* match against removed ids */
- if (!new_owner || new_owner[0] == 0) {
+ if (isempty(new_owner)) {
item->type = KDBUS_ITEM_ID_REMOVE;
+ if (!isempty(old_owner))
+ item->id_change.id = old_owner_id;
r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
if (r < 0)
@@ -1345,6 +1349,10 @@ int bus_add_match_internal_kernel(
else if (r > 0)
sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
+ /* if not a broadcast, it cannot be a name-change */
+ if (r <= 0 || dst_id != KDBUS_DST_ID_BROADCAST)
+ matches_name_change = false;
+
break;
}
diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c
index 983e2f62cd..18685be8ff 100644
--- a/src/libsystemd/sd-bus/bus-message.c
+++ b/src/libsystemd/sd-bus/bus-message.c
@@ -2161,6 +2161,7 @@ static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c)
}
static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
+ bool fixed_size = true;
size_t n_variable = 0;
unsigned i = 0;
const char *p;
@@ -2196,6 +2197,8 @@ static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c,
/* We need to add an offset for each item that has a
* variable size and that is not the last one in the
* list */
+ if (r == 0)
+ fixed_size = false;
if (r == 0 && p[n] != 0)
n_variable++;
@@ -2207,7 +2210,19 @@ static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c,
assert(c->need_offsets || n_variable == 0);
if (n_variable <= 0) {
- a = message_extend_body(m, 1, 0, add_offset, false);
+ int alignment = 1;
+
+ /* Structures with fixed-size members only have to be
+ * fixed-size themselves. But gvariant requires all fixed-size
+ * elements to be sized a multiple of their alignment. Hence,
+ * we must *always* add final padding after the last member so
+ * the overall size of the structure is properly aligned. */
+ if (fixed_size)
+ alignment = bus_gvariant_get_alignment(strempty(c->signature));
+
+ assert(alignment > 0);
+
+ a = message_extend_body(m, alignment, 0, add_offset, false);
if (!a)
return -ENOMEM;
} else {
diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c
index b3cc28ee9b..cbdf6552f9 100644
--- a/src/libsystemd/sd-bus/bus-objects.c
+++ b/src/libsystemd/sd-bus/bus-objects.c
@@ -1416,7 +1416,7 @@ static struct node *bus_node_allocate(sd_bus *bus, const char *path) {
e = strrchr(path, '/');
assert(e);
- p = strndupa(path, MAX(1, path - e));
+ p = strndupa(path, MAX(1, e - path));
parent = bus_node_allocate(bus, p);
if (!parent)
diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c
index 322d57ddbb..735a775cb4 100644
--- a/src/libsystemd/sd-bus/bus-socket.c
+++ b/src/libsystemd/sd-bus/bus-socket.c
@@ -264,6 +264,8 @@ static bool line_begins(const char *s, size_t m, const char *word) {
static int verify_anonymous_token(sd_bus *b, const char *p, size_t l) {
_cleanup_free_ char *token = NULL;
+ size_t len;
+ int r;
if (!b->anonymous_auth)
return 0;
@@ -276,11 +278,12 @@ static int verify_anonymous_token(sd_bus *b, const char *p, size_t l) {
if (l % 2 != 0)
return 0;
- token = unhexmem(p, l);
- if (!token)
- return -ENOMEM;
- if (memchr(token, 0, l/2))
+ r = unhexmem(p, l, (void **) &token, &len);
+ if (r < 0)
+ return 0;
+
+ if (memchr(token, 0, len))
return 0;
return !!utf8_is_valid(token);
@@ -288,6 +291,7 @@ static int verify_anonymous_token(sd_bus *b, const char *p, size_t l) {
static int verify_external_token(sd_bus *b, const char *p, size_t l) {
_cleanup_free_ char *token = NULL;
+ size_t len;
uid_t u;
int r;
@@ -307,11 +311,11 @@ static int verify_external_token(sd_bus *b, const char *p, size_t l) {
if (l % 2 != 0)
return 0;
- token = unhexmem(p, l);
- if (!token)
- return -ENOMEM;
+ r = unhexmem(p, l, (void**) &token, &len);
+ if (r < 0)
+ return 0;
- if (memchr(token, 0, l/2))
+ if (memchr(token, 0, len))
return 0;
r = parse_uid(token, &u);
diff --git a/src/libsystemd/sd-bus/test-bus-marshal.c b/src/libsystemd/sd-bus/test-bus-marshal.c
index a866a56179..59deaea89f 100644
--- a/src/libsystemd/sd-bus/test-bus-marshal.c
+++ b/src/libsystemd/sd-bus/test-bus-marshal.c
@@ -131,6 +131,9 @@ int main(int argc, char *argv[]) {
r = sd_bus_message_append(m, "a{yv}", 2, 3, "s", "foo", 5, "s", "waldo");
assert_se(r >= 0);
+ r = sd_bus_message_append(m, "y(ty)y(yt)y", 8, 777ULL, 7, 9, 77, 7777ULL, 10);
+ assert_se(r >= 0);
+
r = sd_bus_message_append(m, "ba(ss)", 255, 3, "aaa", "1", "bbb", "2", "ccc", "3");
assert_se(r >= 0);
@@ -252,6 +255,22 @@ int main(int argc, char *argv[]) {
assert_se(v == 5);
assert_se(streq(y, "waldo"));
+ r = sd_bus_message_read(m, "y(ty)", &v, &u64, &u);
+ assert_se(r > 0);
+ assert_se(v == 8);
+ assert_se(u64 == 777);
+ assert_se(u == 7);
+
+ r = sd_bus_message_read(m, "y(yt)", &v, &u, &u64);
+ assert_se(r > 0);
+ assert_se(v == 9);
+ assert_se(u == 77);
+ assert_se(u64 == 7777);
+
+ r = sd_bus_message_read(m, "y", &v);
+ assert_se(r > 0);
+ assert_se(v == 10);
+
r = sd_bus_message_read(m, "ba(ss)", &boolean, 3, &x, &y, &a, &b, &c, &d);
assert_se(r > 0);
assert_se(boolean);
@@ -331,7 +350,7 @@ int main(int argc, char *argv[]) {
assert_se(sd_bus_message_verify_type(m, 'a', "{yv}") > 0);
- r = sd_bus_message_skip(m, "a{yv}");
+ r = sd_bus_message_skip(m, "a{yv}y(ty)y(yt)y");
assert_se(r >= 0);
assert_se(sd_bus_message_verify_type(m, 'b', NULL) > 0);
diff --git a/src/libsystemd/sd-bus/test-bus-proxy.c b/src/libsystemd/sd-bus/test-bus-proxy.c
new file mode 100644
index 0000000000..369c2f331c
--- /dev/null
+++ b/src/libsystemd/sd-bus/test-bus-proxy.c
@@ -0,0 +1,109 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2015 David Herrmann <dh.herrmann@gmail.com>
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+
+#include "util.h"
+#include "log.h"
+
+#include "sd-bus.h"
+#include "bus-kernel.h"
+#include "bus-util.h"
+#include "bus-dump.h"
+
+typedef struct {
+ const char *sender;
+ int matched_acquired;
+} TestProxyMatch;
+
+static int test_proxy_acquired(sd_bus_message *m, void *userdata, sd_bus_error *error) {
+ TestProxyMatch *match = userdata;
+ const char *name;
+ int r;
+
+ r = sd_bus_message_read(m, "s", &name);
+ assert_se(r >= 0);
+
+ if (!streq_ptr(match->sender, name))
+ return 0;
+
+ ++match->matched_acquired;
+ return 1;
+}
+
+static void test_proxy_matched(void) {
+ _cleanup_bus_flush_close_unref_ sd_bus *a = NULL;
+ TestProxyMatch match = {};
+ int r;
+
+ /* open bus 'a' */
+
+ r = sd_bus_new(&a);
+ assert_se(r >= 0);
+
+ r = sd_bus_set_address(a, "unix:path=/var/run/dbus/system_bus_socket");
+ assert_se(r >= 0);
+
+ r = sd_bus_set_bus_client(a, true);
+ assert_se(r >= 0);
+
+ r = sd_bus_start(a);
+ assert_se(r >= 0);
+
+ r = sd_bus_add_match(a, NULL,
+ "type='signal',"
+ "member='NameAcquired'",
+ test_proxy_acquired, &match);
+ assert_se(r >= 0);
+
+ r = sd_bus_get_unique_name(a, &match.sender);
+ assert_se(r >= 0);
+
+ /* barrier to guarantee proxy/dbus-daemon handled the previous data */
+ r = sd_bus_call_method(a,
+ "org.freedesktop.DBus",
+ "/org/freedesktop/DBus",
+ "org.freedesktop.DBus",
+ "GetId",
+ NULL, NULL, NULL);
+ assert_se(r >= 0);
+
+ /* now we can be sure the Name* signals were sent */
+ do {
+ r = sd_bus_process(a, NULL);
+ } while (r > 0);
+ assert_se(r == 0);
+
+ assert_se(match.matched_acquired == 1);
+}
+
+int main(int argc, char **argv) {
+ if (access("/var/run/dbus/system_bus_socket", F_OK) < 0)
+ return EXIT_TEST_SKIP;
+
+ log_parse_environment();
+
+ test_proxy_matched();
+
+ return EXIT_SUCCESS;
+}