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-bloom.c10
-rw-r--r--src/libsystemd/sd-bus/bus-control.c23
-rw-r--r--src/libsystemd/sd-bus/bus-internal.c30
-rw-r--r--src/libsystemd/sd-bus/test-bus-kernel-bloom.c25
-rw-r--r--src/libsystemd/sd-bus/test-bus-signature.c13
5 files changed, 80 insertions, 21 deletions
diff --git a/src/libsystemd/sd-bus/bus-bloom.c b/src/libsystemd/sd-bus/bus-bloom.c
index 3556774074..91fab90cb0 100644
--- a/src/libsystemd/sd-bus/bus-bloom.c
+++ b/src/libsystemd/sd-bus/bus-bloom.c
@@ -116,11 +116,19 @@ void bloom_add_prefixes(uint64_t filter[], size_t size, unsigned k, const char *
p = stpcpy(stpcpy(c, a), ":");
strcpy(p, b);
+ bloom_add_data(filter, size, k, c, n);
+
for (;;) {
char *e;
e = strrchr(p, sep);
- if (!e || e == p)
+ if (!e)
+ break;
+
+ *(e + 1) = 0;
+ bloom_add_data(filter, size, k, c, e - c + 1);
+
+ if (e == p)
break;
*e = 0;
diff --git a/src/libsystemd/sd-bus/bus-control.c b/src/libsystemd/sd-bus/bus-control.c
index 1103903358..7a59702cb2 100644
--- a/src/libsystemd/sd-bus/bus-control.c
+++ b/src/libsystemd/sd-bus/bus-control.c
@@ -1291,10 +1291,8 @@ int bus_add_match_internal_kernel(
break;
case BUS_MATCH_PATH_NAMESPACE:
- if (!streq(c->value_str, "/")) {
- bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
- using_bloom = true;
- }
+ bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
+ using_bloom = true;
break;
case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
@@ -1310,11 +1308,18 @@ int bus_add_match_internal_kernel(
}
case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
- char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
-
- xsprintf(buf, "arg%i-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
- bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
- using_bloom = true;
+ /*
+ * XXX: DBus spec defines arg[0..63]path= matching to be
+ * a two-way glob. That is, if either string is a prefix
+ * of the other, it matches.
+ * This is really hard to realize in bloom-filters, as
+ * we would have to create a bloom-match for each prefix
+ * of @c->value_str. This is excessive, hence we just
+ * ignore all those matches and accept everything from
+ * the kernel. People should really avoid those matches.
+ * If they're used in real-life some day, we will have
+ * to properly support multiple-matches here.
+ */
break;
}
diff --git a/src/libsystemd/sd-bus/bus-internal.c b/src/libsystemd/sd-bus/bus-internal.c
index 91b288cd25..37793e48ed 100644
--- a/src/libsystemd/sd-bus/bus-internal.c
+++ b/src/libsystemd/sd-bus/bus-internal.c
@@ -211,6 +211,17 @@ bool member_name_is_valid(const char *p) {
return true;
}
+/*
+ * Complex pattern match
+ * This checks whether @a is a 'complex-prefix' of @b, or @b is a
+ * 'complex-prefix' of @a, based on strings that consist of labels with @c as
+ * spearator. This function returns true if:
+ * - both strings are equal
+ * - either is a prefix of the other and ends with @c
+ * The second rule makes sure that either string needs to be fully included in
+ * the other, and the string which is considered the prefix needs to end with a
+ * separator.
+ */
static bool complex_pattern_check(char c, const char *a, const char *b) {
bool separator = false;
@@ -222,9 +233,7 @@ static bool complex_pattern_check(char c, const char *a, const char *b) {
for (;;) {
if (*a != *b)
- return (separator && (*a == 0 || *b == 0)) ||
- (*a == 0 && *b == c && b[1] == 0) ||
- (*b == 0 && *a == c && a[1] == 0);
+ return (separator && (*a == 0 || *b == 0));
if (*a == 0)
return true;
@@ -243,7 +252,18 @@ bool path_complex_pattern(const char *pattern, const char *value) {
return complex_pattern_check('/', pattern, value);
}
+/*
+ * Simple pattern match
+ * This checks whether @a is a 'simple-prefix' of @b, based on strings that
+ * consist of labels with @c as separator. This function returns true, if:
+ * - if @a and @b are equal
+ * - if @a is a prefix of @b, and the first following character in @b (or the
+ * last character in @a) is @c
+ * The second rule basically makes sure that if @a is a prefix of @b, then @b
+ * must follow with a new label separated by @c. It cannot extend the label.
+ */
static bool simple_pattern_check(char c, const char *a, const char *b) {
+ bool separator = false;
if (!a && !b)
return true;
@@ -253,11 +273,13 @@ static bool simple_pattern_check(char c, const char *a, const char *b) {
for (;;) {
if (*a != *b)
- return *a == 0 && *b == c;
+ return *a == 0 && (*b == c || separator);
if (*a == 0)
return true;
+ separator = *a == c;
+
a++, b++;
}
}
diff --git a/src/libsystemd/sd-bus/test-bus-kernel-bloom.c b/src/libsystemd/sd-bus/test-bus-kernel-bloom.c
index b11c43bd7b..90eb1f2a33 100644
--- a/src/libsystemd/sd-bus/test-bus-kernel-bloom.c
+++ b/src/libsystemd/sd-bus/test-bus-kernel-bloom.c
@@ -26,6 +26,14 @@
#include "bus-kernel.h"
#include "bus-util.h"
+static int test_match(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
+ int *found = userdata;
+
+ *found = 1;
+
+ return 0;
+}
+
static void test_one(
const char *path,
const char *interface,
@@ -39,7 +47,7 @@ static void test_one(
_cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL;
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
sd_bus *a, *b;
- int r;
+ int r, found = 0;
assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid()) >= 0);
@@ -71,7 +79,7 @@ static void test_one(
assert_se(r >= 0);
log_debug("match");
- r = sd_bus_add_match(b, NULL, match, NULL, NULL);
+ r = sd_bus_add_match(b, NULL, match, test_match, &found);
assert_se(r >= 0);
log_debug("signal");
@@ -83,7 +91,7 @@ static void test_one(
assert_se(r >= 0);
r = sd_bus_process(b, &m);
- assert_se(r >= 0 && (good == !!m));
+ assert_se(r >= 0 && good == !!found);
sd_bus_unref(a);
sd_bus_unref(b);
@@ -115,6 +123,17 @@ int main(int argc, char *argv[]) {
test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo'", true);
test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/'", true);
test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/quux'", false);
+ test_one("/", "waldo.com", "Piep", false, "foobar", "path_namespace='/'", true);
+
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo/'", false);
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/'", false);
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo/bar/waldo/'", false);
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo/'", true);
+
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "/foo/bar/waldo", "arg0path='/foo/'", true);
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "/foo", "arg0path='/foo'", true);
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "/foo", "arg0path='/foo/bar/waldo'", false);
+ test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "/foo/", "arg0path='/foo/bar/waldo'", true);
return 0;
}
diff --git a/src/libsystemd/sd-bus/test-bus-signature.c b/src/libsystemd/sd-bus/test-bus-signature.c
index 4165c9273a..17c6188ca0 100644
--- a/src/libsystemd/sd-bus/test-bus-signature.c
+++ b/src/libsystemd/sd-bus/test-bus-signature.c
@@ -95,23 +95,28 @@ int main(int argc, char *argv[]) {
assert_se(!namespace_complex_pattern("foo.", ""));
assert_se(path_complex_pattern("", ""));
- assert_se(path_complex_pattern("", "/"));
- assert_se(path_complex_pattern("/", ""));
+ assert_se(!path_complex_pattern("", "/"));
+ assert_se(!path_complex_pattern("/", ""));
assert_se(path_complex_pattern("/", "/"));
assert_se(path_complex_pattern("/foobar/", "/"));
- assert_se(path_complex_pattern("/foobar/", "/foobar"));
+ assert_se(!path_complex_pattern("/foobar/", "/foobar"));
assert_se(path_complex_pattern("/foobar", "/foobar"));
- assert_se(path_complex_pattern("/foobar", "/foobar/"));
+ assert_se(!path_complex_pattern("/foobar", "/foobar/"));
assert_se(!path_complex_pattern("/foobar", "/foobar/waldo"));
assert_se(path_complex_pattern("/foobar/", "/foobar/waldo"));
+ assert_se(path_complex_pattern("/foobar/waldo", "/foobar/"));
+
+ assert_se(path_simple_pattern("/foo/", "/foo/bar/waldo"));
assert_se(namespace_simple_pattern("", ""));
+ assert_se(namespace_simple_pattern("", ".foobar"));
assert_se(namespace_simple_pattern("foobar", "foobar"));
assert_se(namespace_simple_pattern("foobar.waldo", "foobar.waldo"));
assert_se(namespace_simple_pattern("foobar", "foobar.waldo"));
assert_se(!namespace_simple_pattern("foobar.waldo", "foobar"));
assert_se(!namespace_simple_pattern("", "foo"));
assert_se(!namespace_simple_pattern("foo", ""));
+ assert_se(namespace_simple_pattern("foo.", "foo.bar.waldo"));
assert_se(streq(object_path_startswith("/foo/bar", "/foo"), "bar"));
assert_se(streq(object_path_startswith("/foo", "/foo"), ""));