From 58764450160b12913bd66fe89901f0a37dec2774 Mon Sep 17 00:00:00 2001 From: Sven Eden Date: Wed, 4 Jan 2017 06:40:46 +0100 Subject: [PATCH] Prep v225: Applying various fixes and changes to src/libelogind/sd-bus that got lost during git am transfer. --- src/libelogind/sd-bus/bus-control.c | 23 ++-- src/libelogind/sd-bus/bus-convenience.c | 146 +++++++++++++++--------- src/libelogind/sd-bus/bus-internal.h | 6 + src/libelogind/sd-bus/bus-introspect.c | 11 +- src/libelogind/sd-bus/bus-kernel.c | 27 ++++- src/libelogind/sd-bus/bus-match.c | 78 ++++++++----- src/libelogind/sd-bus/bus-match.h | 2 + src/libelogind/sd-bus/bus-message.c | 65 ++++++++--- src/libelogind/sd-bus/bus-message.h | 3 +- src/libelogind/sd-bus/bus-objects.c | 10 +- src/libelogind/sd-bus/bus-socket.c | 20 ++-- src/libelogind/sd-bus/sd-bus.c | 107 +++++++++++------ 12 files changed, 331 insertions(+), 167 deletions(-) diff --git a/src/libelogind/sd-bus/bus-control.c b/src/libelogind/sd-bus/bus-control.c index feed51cd9..356772ca5 100644 --- a/src/libelogind/sd-bus/bus-control.c +++ b/src/libelogind/sd-bus/bus-control.c @@ -1129,7 +1129,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); @@ -1139,7 +1139,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); @@ -1183,7 +1183,7 @@ 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; @@ -1195,7 +1195,7 @@ 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; @@ -1309,7 +1309,16 @@ int bus_add_match_internal_kernel( break; } - case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: { + case BUS_MATCH_ARG_HAS...BUS_MATCH_ARG_HAS_LAST: { + char buf[sizeof("arg")-1 + 2 + sizeof("-has")]; + + xsprintf(buf, "arg%i-has", c->type - BUS_MATCH_ARG_HAS); + bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str); + using_bloom = true; + break; + } + + case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: /* * XXX: DBus spec defines arg[0..63]path= matching to be * a two-way glob. That is, if either string is a prefix @@ -1323,7 +1332,6 @@ int bus_add_match_internal_kernel( * to properly support multiple-matches here. */ break; - } case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: { char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")]; @@ -1334,7 +1342,7 @@ int bus_add_match_internal_kernel( break; } - case BUS_MATCH_DESTINATION: { + case BUS_MATCH_DESTINATION: /* * Kernel only supports matching on destination IDs, but * not on destination names. So just skip the @@ -1352,7 +1360,6 @@ int bus_add_match_internal_kernel( matches_name_change = false; break; - } case BUS_MATCH_ROOT: case BUS_MATCH_VALUE: diff --git a/src/libelogind/sd-bus/bus-convenience.c b/src/libelogind/sd-bus/bus-convenience.c index 59c7c86ae..b72049ef0 100644 --- a/src/libelogind/sd-bus/bus-convenience.c +++ b/src/libelogind/sd-bus/bus-convenience.c @@ -111,15 +111,17 @@ _public_ int sd_bus_call_method( _cleanup_bus_message_unref_ sd_bus_message *m = NULL; int r; - assert_return(bus, -EINVAL); - assert_return(!bus_pid_changed(bus), -ECHILD); + bus_assert_return(bus, -EINVAL, error); + bus_assert_return(!bus_pid_changed(bus), -ECHILD, error); - if (!BUS_IS_OPEN(bus->state)) - return -ENOTCONN; + if (!BUS_IS_OPEN(bus->state)) { + r = -ENOTCONN; + goto fail; + } r = sd_bus_message_new_method_call(bus, &m, destination, path, interface, member); if (r < 0) - return r; + goto fail; if (!isempty(types)) { va_list ap; @@ -128,10 +130,13 @@ _public_ int sd_bus_call_method( r = bus_message_append_ap(m, types, ap); va_end(ap); if (r < 0) - return r; + goto fail; } return sd_bus_call(bus, m, 0, error, reply); + +fail: + return sd_bus_error_set_errno(error, r); } _public_ int sd_bus_reply_method_return( @@ -296,15 +301,17 @@ _public_ int sd_bus_get_property( sd_bus_message *rep = NULL; int r; - assert_return(bus, -EINVAL); - assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL); - assert_return(member_name_is_valid(member), -EINVAL); - assert_return(reply, -EINVAL); - assert_return(signature_is_single(type, false), -EINVAL); - assert_return(!bus_pid_changed(bus), -ECHILD); + bus_assert_return(bus, -EINVAL, error); + bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error); + bus_assert_return(member_name_is_valid(member), -EINVAL, error); + bus_assert_return(reply, -EINVAL, error); + bus_assert_return(signature_is_single(type, false), -EINVAL, error); + bus_assert_return(!bus_pid_changed(bus), -ECHILD, error); - if (!BUS_IS_OPEN(bus->state)) - return -ENOTCONN; + if (!BUS_IS_OPEN(bus->state)) { + r = -ENOTCONN; + goto fail; + } r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &rep, "ss", strempty(interface), member); if (r < 0) @@ -313,11 +320,14 @@ _public_ int sd_bus_get_property( r = sd_bus_message_enter_container(rep, 'v', type); if (r < 0) { sd_bus_message_unref(rep); - return r; + goto fail; } *reply = rep; return 0; + +fail: + return sd_bus_error_set_errno(error, r); } /// UNNEEDED by elogind @@ -334,15 +344,17 @@ _public_ int sd_bus_get_property_trivial( _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; int r; - assert_return(bus, -EINVAL); - assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL); - assert_return(member_name_is_valid(member), -EINVAL); - assert_return(bus_type_is_trivial(type), -EINVAL); - assert_return(ptr, -EINVAL); - assert_return(!bus_pid_changed(bus), -ECHILD); + bus_assert_return(bus, -EINVAL, error); + bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error); + bus_assert_return(member_name_is_valid(member), -EINVAL, error); + bus_assert_return(bus_type_is_trivial(type), -EINVAL, error); + bus_assert_return(ptr, -EINVAL, error); + bus_assert_return(!bus_pid_changed(bus), -ECHILD, error); - if (!BUS_IS_OPEN(bus->state)) - return -ENOTCONN; + if (!BUS_IS_OPEN(bus->state)) { + r = -ENOTCONN; + goto fail; + } r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member); if (r < 0) @@ -350,13 +362,16 @@ _public_ int sd_bus_get_property_trivial( r = sd_bus_message_enter_container(reply, 'v', CHAR_TO_STR(type)); if (r < 0) - return r; + goto fail; r = sd_bus_message_read_basic(reply, type, ptr); if (r < 0) - return r; + goto fail; return 0; + +fail: + return sd_bus_error_set_errno(error, r); } #endif // 0 @@ -374,14 +389,16 @@ _public_ int sd_bus_get_property_string( char *n; int r; - assert_return(bus, -EINVAL); - assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL); - assert_return(member_name_is_valid(member), -EINVAL); - assert_return(ret, -EINVAL); - assert_return(!bus_pid_changed(bus), -ECHILD); + bus_assert_return(bus, -EINVAL, error); + bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error); + bus_assert_return(member_name_is_valid(member), -EINVAL, error); + bus_assert_return(ret, -EINVAL, error); + bus_assert_return(!bus_pid_changed(bus), -ECHILD, error); - if (!BUS_IS_OPEN(bus->state)) - return -ENOTCONN; + if (!BUS_IS_OPEN(bus->state)) { + r = -ENOTCONN; + goto fail; + } r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member); if (r < 0) @@ -389,18 +406,23 @@ _public_ int sd_bus_get_property_string( r = sd_bus_message_enter_container(reply, 'v', "s"); if (r < 0) - return r; + goto fail; r = sd_bus_message_read_basic(reply, 's', &s); if (r < 0) - return r; + goto fail; n = strdup(s); - if (!n) - return -ENOMEM; + if (!n) { + r = -ENOMEM; + goto fail; + } *ret = n; return 0; + +fail: + return sd_bus_error_set_errno(error, r); } /// UNNEEDED by elogind @@ -417,14 +439,16 @@ _public_ int sd_bus_get_property_strv( _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; int r; - assert_return(bus, -EINVAL); - assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL); - assert_return(member_name_is_valid(member), -EINVAL); - assert_return(ret, -EINVAL); - assert_return(!bus_pid_changed(bus), -ECHILD); + bus_assert_return(bus, -EINVAL, error); + bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error); + bus_assert_return(member_name_is_valid(member), -EINVAL, error); + bus_assert_return(ret, -EINVAL, error); + bus_assert_return(!bus_pid_changed(bus), -ECHILD, error); - if (!BUS_IS_OPEN(bus->state)) - return -ENOTCONN; + if (!BUS_IS_OPEN(bus->state)) { + r = -ENOTCONN; + goto fail; + } r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member); if (r < 0) @@ -432,13 +456,16 @@ _public_ int sd_bus_get_property_strv( r = sd_bus_message_enter_container(reply, 'v', NULL); if (r < 0) - return r; + goto fail; r = sd_bus_message_read_strv(reply, ret); if (r < 0) - return r; + goto fail; return 0; + +fail: + return sd_bus_error_set_errno(error, r); } _public_ int sd_bus_set_property( @@ -454,38 +481,43 @@ _public_ int sd_bus_set_property( va_list ap; int r; - assert_return(bus, -EINVAL); - assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL); - assert_return(member_name_is_valid(member), -EINVAL); - assert_return(signature_is_single(type, false), -EINVAL); - assert_return(!bus_pid_changed(bus), -ECHILD); + bus_assert_return(bus, -EINVAL, error); + bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error); + bus_assert_return(member_name_is_valid(member), -EINVAL, error); + bus_assert_return(signature_is_single(type, false), -EINVAL, error); + bus_assert_return(!bus_pid_changed(bus), -ECHILD, error); - if (!BUS_IS_OPEN(bus->state)) - return -ENOTCONN; + if (!BUS_IS_OPEN(bus->state)) { + r = -ENOTCONN; + goto fail; + } r = sd_bus_message_new_method_call(bus, &m, destination, path, "org.freedesktop.DBus.Properties", "Set"); if (r < 0) - return r; + goto fail; r = sd_bus_message_append(m, "ss", strempty(interface), member); if (r < 0) - return r; + goto fail; r = sd_bus_message_open_container(m, 'v', type); if (r < 0) - return r; + goto fail; va_start(ap, type); r = bus_message_append_ap(m, type, ap); va_end(ap); if (r < 0) - return r; + goto fail; r = sd_bus_message_close_container(m); if (r < 0) - return r; + goto fail; return sd_bus_call(bus, m, 0, error, NULL); + +fail: + return sd_bus_error_set_errno(error, r); } #endif // 0 diff --git a/src/libelogind/sd-bus/bus-internal.h b/src/libelogind/sd-bus/bus-internal.h index 05dae42b2..efee735b9 100644 --- a/src/libelogind/sd-bus/bus-internal.h +++ b/src/libelogind/sd-bus/bus-internal.h @@ -393,3 +393,9 @@ int bus_set_address_system_machine(sd_bus *b, const char *machine); int bus_get_root_path(sd_bus *bus); int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error); + +#define bus_assert_return(expr, r, error) \ + do { \ + if (!assert_log(expr)) \ + return sd_bus_error_set_errno(error, r); \ + } while (false) diff --git a/src/libelogind/sd-bus/bus-introspect.c b/src/libelogind/sd-bus/bus-introspect.c index e2f4550c7..24aa21dfd 100644 --- a/src/libelogind/sd-bus/bus-introspect.c +++ b/src/libelogind/sd-bus/bus-introspect.c @@ -81,6 +81,9 @@ static void introspect_write_flags(struct introspect *i, int type, int flags) { fputs(" \n", i->f); if (type == _SD_BUS_VTABLE_PROPERTY || type == _SD_BUS_VTABLE_WRITABLE_PROPERTY) { + if (flags & SD_BUS_VTABLE_PROPERTY_EXPLICIT) + fputs(" \n", i->f); + if (flags & SD_BUS_VTABLE_PROPERTY_CONST) fputs(" \n", i->f); else if (flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION) @@ -179,10 +182,10 @@ int introspect_finish(struct introspect *i, sd_bus *bus, sd_bus_message *m, sd_b assert(reply); fputs("\n", i->f); - fflush(i->f); - if (ferror(i->f)) - return -ENOMEM; + r = fflush_and_check(i->f); + if (r < 0) + return r; r = sd_bus_message_new_method_return(m, &q); if (r < 0) @@ -204,8 +207,6 @@ void introspect_free(struct introspect *i) { if (i->f) fclose(i->f); - if (i->introspection) free(i->introspection); - zero(*i); } diff --git a/src/libelogind/sd-bus/bus-kernel.c b/src/libelogind/sd-bus/bus-kernel.c index e5d8a2cc5..25fc4ba80 100644 --- a/src/libelogind/sd-bus/bus-kernel.c +++ b/src/libelogind/sd-bus/bus-kernel.c @@ -168,6 +168,27 @@ static void add_bloom_arg(void *data, size_t size, unsigned n_hash, unsigned i, bloom_add_prefixes(data, size, n_hash, buf, t, '/'); } +static void add_bloom_arg_has(void *data, size_t size, unsigned n_hash, unsigned i, const char *t) { + char buf[sizeof("arg")-1 + 2 + sizeof("-has")]; + char *e; + + assert(data); + assert(size > 0); + assert(i < 64); + assert(t); + + e = stpcpy(buf, "arg"); + if (i < 10) + *(e++) = '0' + (char) i; + else { + *(e++) = '0' + (char) (i / 10); + *(e++) = '0' + (char) (i % 10); + } + + strcpy(e, "-has"); + bloom_add_pair(data, size, n_hash, buf, t); +} + static int bus_message_setup_bloom(sd_bus_message *m, struct kdbus_bloom_filter *bloom) { void *data; unsigned i; @@ -212,7 +233,9 @@ static int bus_message_setup_bloom(sd_bus_message *m, struct kdbus_bloom_filter return r; add_bloom_arg(data, m->bus->bloom_size, m->bus->bloom_n_hash, i, t); - } if (type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")) { + } + + if (type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")) { /* As well as array of simple strings of any kinds */ r = sd_bus_message_enter_container(m, type, contents); @@ -220,7 +243,7 @@ static int bus_message_setup_bloom(sd_bus_message *m, struct kdbus_bloom_filter return r; while ((r = sd_bus_message_read_basic(m, contents[0], &t)) > 0) - add_bloom_arg(data, m->bus->bloom_size, m->bus->bloom_n_hash, i, t); + add_bloom_arg_has(data, m->bus->bloom_size, m->bus->bloom_n_hash, i, t); if (r < 0) return r; diff --git a/src/libelogind/sd-bus/bus-match.c b/src/libelogind/sd-bus/bus-match.c index 53c231331..8ef30f55e 100644 --- a/src/libelogind/sd-bus/bus-match.c +++ b/src/libelogind/sd-bus/bus-match.c @@ -62,12 +62,13 @@ */ static inline bool BUS_MATCH_IS_COMPARE(enum bus_match_node_type t) { - return t >= BUS_MATCH_SENDER && t <= BUS_MATCH_ARG_NAMESPACE_LAST; + return t >= BUS_MATCH_SENDER && t <= BUS_MATCH_ARG_HAS_LAST; } static inline bool BUS_MATCH_CAN_HASH(enum bus_match_node_type t) { return (t >= BUS_MATCH_MESSAGE_TYPE && t <= BUS_MATCH_PATH) || - (t >= BUS_MATCH_ARG && t <= BUS_MATCH_ARG_LAST); + (t >= BUS_MATCH_ARG && t <= BUS_MATCH_ARG_LAST) || + (t >= BUS_MATCH_ARG_HAS && t <= BUS_MATCH_ARG_HAS_LAST); } static void bus_match_node_free(struct bus_match_node *node) { @@ -179,12 +180,16 @@ static bool value_node_test( case BUS_MATCH_INTERFACE: case BUS_MATCH_MEMBER: case BUS_MATCH_PATH: - case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST: { - char **i; + case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST: if (value_str) return streq_ptr(node->value.str, value_str); + return false; + + case BUS_MATCH_ARG_HAS ... BUS_MATCH_ARG_HAS_LAST: { + char **i; + STRV_FOREACH(i, value_strv) if (streq_ptr(node->value.str, *i)) return true; @@ -192,33 +197,20 @@ static bool value_node_test( return false; } - case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST: { - char **i; - + case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST: if (value_str) return namespace_simple_pattern(node->value.str, value_str); - STRV_FOREACH(i, value_strv) - if (namespace_simple_pattern(node->value.str, *i)) - return true; return false; - } case BUS_MATCH_PATH_NAMESPACE: return path_simple_pattern(node->value.str, value_str); - case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST: { - char **i; - + case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST: if (value_str) return path_complex_pattern(node->value.str, value_str); - STRV_FOREACH(i, value_strv) - if (path_complex_pattern(node->value.str, *i)) - return true; - return false; - } default: assert_not_reached("Invalid node type"); @@ -249,6 +241,7 @@ static bool value_node_same( case BUS_MATCH_MEMBER: case BUS_MATCH_PATH: case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST: + case BUS_MATCH_ARG_HAS ... BUS_MATCH_ARG_HAS_LAST: case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST: case BUS_MATCH_PATH_NAMESPACE: case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST: @@ -372,15 +365,19 @@ int bus_match_run( break; case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST: - (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG, &test_str, &test_strv); + (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG, &test_str); break; case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST: - (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG_PATH, &test_str, &test_strv); + (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG_PATH, &test_str); break; case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST: - (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG_NAMESPACE, &test_str, &test_strv); + (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG_NAMESPACE, &test_str); + break; + + case BUS_MATCH_ARG_HAS ... BUS_MATCH_ARG_HAS_LAST: + (void) bus_message_get_arg_strv(m, node->type - BUS_MATCH_ARG_HAS, &test_strv); break; default: @@ -743,6 +740,32 @@ enum bus_match_node_type bus_match_node_type_from_string(const char *k, size_t n return t; } + if (n == 7 && startswith(k, "arg") && startswith(k + 4, "has")) { + int j; + + j = undecchar(k[3]); + if (j < 0) + return -EINVAL; + + return BUS_MATCH_ARG_HAS + j; + } + + if (n == 8 && startswith(k, "arg") && startswith(k + 5, "has")) { + enum bus_match_node_type t; + int a, b; + + a = undecchar(k[3]); + b = undecchar(k[4]); + if (a <= 0 || b < 0) + return -EINVAL; + + t = BUS_MATCH_ARG_HAS + a * 10 + b; + if (t > BUS_MATCH_ARG_HAS_LAST) + return -EINVAL; + + return t; + } + return -EINVAL; } @@ -861,8 +884,7 @@ int bus_match_parse( if (r < 0) goto fail; - free(value); - value = NULL; + value = mfree(value); } else u = 0; @@ -944,8 +966,8 @@ char *bus_match_to_string(struct bus_match_component *components, unsigned n_com fputc('\'', f); } - fflush(f); - if (ferror(f)) + r = fflush_and_check(f); + if (r < 0) return NULL; return buffer; @@ -1114,6 +1136,10 @@ const char* bus_match_node_type_to_string(enum bus_match_node_type t, char buf[] snprintf(buf, l, "arg%inamespace", t - BUS_MATCH_ARG_NAMESPACE); return buf; + case BUS_MATCH_ARG_HAS ... BUS_MATCH_ARG_HAS_LAST: + snprintf(buf, l, "arg%ihas", t - BUS_MATCH_ARG_HAS); + return buf; + default: return NULL; } diff --git a/src/libelogind/sd-bus/bus-match.h b/src/libelogind/sd-bus/bus-match.h index cefb87e08..8b72a4f7c 100644 --- a/src/libelogind/sd-bus/bus-match.h +++ b/src/libelogind/sd-bus/bus-match.h @@ -44,6 +44,8 @@ enum bus_match_node_type { BUS_MATCH_ARG_PATH_LAST = BUS_MATCH_ARG_PATH + 63, BUS_MATCH_ARG_NAMESPACE, BUS_MATCH_ARG_NAMESPACE_LAST = BUS_MATCH_ARG_NAMESPACE + 63, + BUS_MATCH_ARG_HAS, + BUS_MATCH_ARG_HAS_LAST = BUS_MATCH_ARG_HAS + 63, _BUS_MATCH_NODE_TYPE_MAX, _BUS_MATCH_NODE_TYPE_INVALID = -1 }; diff --git a/src/libelogind/sd-bus/bus-message.c b/src/libelogind/sd-bus/bus-message.c index 85882c181..dad6db8af 100644 --- a/src/libelogind/sd-bus/bus-message.c +++ b/src/libelogind/sd-bus/bus-message.c @@ -2706,7 +2706,7 @@ _public_ int sd_bus_message_append_array_memfd( int r; assert_return(m, -EINVAL); - assert_return(memfd >= 0, -EINVAL); + assert_return(memfd >= 0, -EBADF); assert_return(bus_type_is_trivial(type), -EINVAL); assert_return(size > 0, -EINVAL); assert_return(!m->sealed, -EPERM); @@ -2782,7 +2782,7 @@ _public_ int sd_bus_message_append_string_memfd( int r; assert_return(m, -EINVAL); - assert_return(memfd >= 0, -EINVAL); + assert_return(memfd >= 0, -EBADF); assert_return(size > 0, -EINVAL); assert_return(!m->sealed, -EPERM); assert_return(!m->poisoned, -ESTALE); @@ -5642,21 +5642,23 @@ _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) { return 1; } -int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char ***strv) { - const char *contents; +static int bus_message_get_arg_skip( + sd_bus_message *m, + unsigned i, + char *_type, + const char **_contents) { + unsigned j; - char type; int r; - assert(m); - assert(str); - assert(strv); - r = sd_bus_message_rewind(m, true); if (r < 0) return r; for (j = 0;; j++) { + const char *contents; + char type; + r = sd_bus_message_peek_type(m, &type, &contents); if (r < 0) return r; @@ -5668,31 +5670,56 @@ int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char ** !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g"))) return -ENXIO; - if (j >= i) - break; + if (j >= i) { + if (_contents) + *_contents = contents; + if (_type) + *_type = type; + return 0; + } r = sd_bus_message_skip(m, NULL); if (r < 0) return r; } - if (type == SD_BUS_TYPE_ARRAY) { +} + +int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) { + char type; + int r; + + assert(m); + assert(str); - r = sd_bus_message_read_strv(m, strv); + r = bus_message_get_arg_skip(m, i, &type, NULL); if (r < 0) return r; - *str = NULL; + if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) + return -ENXIO; - } else { - r = sd_bus_message_read_basic(m, type, str); + return sd_bus_message_read_basic(m, type, str); +} + +int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) { + const char *contents; + char type; + int r; + + assert(m); + assert(strv); + + r = bus_message_get_arg_skip(m, i, &type, &contents); if (r < 0) return r; - *strv = NULL; - } + if (type != SD_BUS_TYPE_ARRAY) + return -ENXIO; + if (!STR_IN_SET(contents, "s", "o", "g")) + return -ENXIO; - return 0; + return sd_bus_message_read_strv(m, strv); } _public_ int sd_bus_message_get_errno(sd_bus_message *m) { diff --git a/src/libelogind/sd-bus/bus-message.h b/src/libelogind/sd-bus/bus-message.h index 2f338ff6f..9b0044641 100644 --- a/src/libelogind/sd-bus/bus-message.h +++ b/src/libelogind/sd-bus/bus-message.h @@ -218,7 +218,8 @@ int bus_message_from_malloc( const char *label, sd_bus_message **ret); -int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char ***strv); +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); int bus_message_append_ap(sd_bus_message *m, const char *types, va_list ap); diff --git a/src/libelogind/sd-bus/bus-objects.c b/src/libelogind/sd-bus/bus-objects.c index a3d9e552d..fa5c8ab22 100644 --- a/src/libelogind/sd-bus/bus-objects.c +++ b/src/libelogind/sd-bus/bus-objects.c @@ -750,6 +750,9 @@ static int vtable_append_all_properties( if (v->flags & SD_BUS_VTABLE_HIDDEN) continue; + if (v->flags & SD_BUS_VTABLE_PROPERTY_EXPLICIT) + continue; + r = vtable_append_one_property(bus, reply, path, c, v, userdata, error); if (r < 0) return r; @@ -1176,10 +1179,6 @@ static int process_get_managed_objects( if (bus->nodes_modified) return 0; - r = set_put_strdup(s, m->path); - if (r < 0) - return r; - r = sd_bus_message_new_method_return(m, &reply); if (r < 0) return r; @@ -1745,8 +1744,9 @@ static int add_object_vtable_internal( if (!member_name_is_valid(v->x.property.member) || !signature_is_single(v->x.property.signature, false) || !(v->x.property.get || bus_type_is_basic(v->x.property.signature[0]) || streq(v->x.property.signature, "as")) || - v->flags & SD_BUS_VTABLE_METHOD_NO_REPLY || + (v->flags & SD_BUS_VTABLE_METHOD_NO_REPLY) || (!!(v->flags & SD_BUS_VTABLE_PROPERTY_CONST) + !!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE) + !!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION)) > 1 || + ((v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE) && (v->flags & SD_BUS_VTABLE_PROPERTY_EXPLICIT)) || (v->flags & SD_BUS_VTABLE_UNPRIVILEGED && v->type == _SD_BUS_VTABLE_PROPERTY)) { r = -EINVAL; goto fail; diff --git a/src/libelogind/sd-bus/bus-socket.c b/src/libelogind/sd-bus/bus-socket.c index 322d57ddb..735a775cb 100644 --- a/src/libelogind/sd-bus/bus-socket.c +++ b/src/libelogind/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/libelogind/sd-bus/sd-bus.c b/src/libelogind/sd-bus/sd-bus.c index d2a96f87b..957d43745 100644 --- a/src/libelogind/sd-bus/sd-bus.c +++ b/src/libelogind/sd-bus/sd-bus.c @@ -33,6 +33,7 @@ #include "missing.h" #include "def.h" #include "cgroup-util.h" +#include "hostname-util.h" #include "bus-label.h" #include "sd-bus.h" @@ -214,8 +215,8 @@ _public_ int sd_bus_set_address(sd_bus *bus, const char *address) { _public_ int sd_bus_set_fd(sd_bus *bus, int input_fd, int output_fd) { assert_return(bus, -EINVAL); assert_return(bus->state == BUS_UNSET, -EPERM); - assert_return(input_fd >= 0, -EINVAL); - assert_return(output_fd >= 0, -EINVAL); + assert_return(input_fd >= 0, -EBADF); + assert_return(output_fd >= 0, -EBADF); assert_return(!bus_pid_changed(bus), -ECHILD); bus->input_fd = input_fd; @@ -899,10 +900,9 @@ static int parse_container_kernel_address(sd_bus *b, const char **p, char **guid } else b->nspid = 0; - free(b->kernel); - b->kernel = strdup("/sys/fs/kdbus/0-system/bus"); - if (!b->kernel) - return -ENOMEM; + r = free_and_strdup(&b->kernel, "/sys/fs/kdbus/0-system/bus"); + if (r < 0) + return r; return 0; } @@ -1011,6 +1011,8 @@ static int bus_parse_next_address(sd_bus *b) { } static int bus_start_address(sd_bus *b) { + bool container_kdbus_available = false; + bool kdbus_available = false; int r; assert(b); @@ -1020,17 +1022,31 @@ static int bus_start_address(sd_bus *b) { bus_close_fds(b); + /* + * Usually, if you provide multiple different bus-addresses, we + * try all of them in order. We use the first one that + * succeeds. However, if you mix kernel and unix addresses, we + * never try unix-addresses if a previous kernel address was + * tried and kdbus was available. This is required to prevent + * clients to fallback to the bus-proxy if kdbus is available + * but failed (eg., too many connections). + */ + if (b->exec_path) r = bus_socket_exec(b); #if 0 - else if ((b->nspid > 0 || b->machine) && b->kernel) + else if ((b->nspid > 0 || b->machine) && b->kernel) { r = bus_container_connect_kernel(b); - else if ((b->nspid > 0 || b->machine) && b->sockaddr.sa.sa_family != AF_UNSPEC) + if (r < 0 && !IN_SET(r, -ENOENT, -ESOCKTNOSUPPORT)) + container_kdbus_available = true; + } else if (!container_kdbus_available && (b->nspid > 0 || b->machine) && b->sockaddr.sa.sa_family != AF_UNSPEC) r = bus_container_connect_socket(b); #endif // 0 - else if (b->kernel) + else if (b->kernel) { r = bus_kernel_connect(b); - else if (b->sockaddr.sa.sa_family != AF_UNSPEC) + if (r < 0 && !IN_SET(r, -ENOENT, -ESOCKTNOSUPPORT)) + kdbus_available = true; + } else if (!kdbus_available && b->sockaddr.sa.sa_family != AF_UNSPEC) r = bus_socket_connect(b); else skipped = true; @@ -1143,6 +1159,9 @@ _public_ int sd_bus_open(sd_bus **ret) { e = secure_getenv("DBUS_STARTER_ADDRESS"); if (!e) { + if (cg_pid_get_owner_uid(0, NULL) >= 0) + return sd_bus_open_user(ret); + else return sd_bus_open_system(ret); } @@ -1963,37 +1982,39 @@ _public_ int sd_bus_call( unsigned i; int r; - assert_return(m, -EINVAL); - assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL); - assert_return(!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED), -EINVAL); - assert_return(!bus_error_is_dirty(error), -EINVAL); + bus_assert_return(m, -EINVAL, error); + bus_assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL, error); + bus_assert_return(!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED), -EINVAL, error); + bus_assert_return(!bus_error_is_dirty(error), -EINVAL, error); if (!bus) bus = m->bus; - assert_return(!bus_pid_changed(bus), -ECHILD); - assert_return(!bus->is_kernel || !(bus->hello_flags & KDBUS_HELLO_MONITOR), -EROFS); + bus_assert_return(!bus_pid_changed(bus), -ECHILD, error); + bus_assert_return(!bus->is_kernel || !(bus->hello_flags & KDBUS_HELLO_MONITOR), -EROFS, error); - if (!BUS_IS_OPEN(bus->state)) - return -ENOTCONN; + if (!BUS_IS_OPEN(bus->state)) { + r = -ENOTCONN; + goto fail; + } r = bus_ensure_running(bus); if (r < 0) - return r; + goto fail; i = bus->rqueue_size; r = bus_seal_message(bus, m, usec); if (r < 0) - return r; + goto fail; r = bus_remarshal_message(bus, &m); if (r < 0) - return r; + goto fail; r = bus_send_internal(bus, m, &cookie, true); if (r < 0) - return r; + goto fail; timeout = calc_elapse(m->timeout); @@ -2024,14 +2045,17 @@ _public_ int sd_bus_call( } r = sd_bus_error_setf(error, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptors which I couldn't accept. Sorry."); + sd_bus_message_unref(incoming); + return r; - } else if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR) + } else if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR) { r = sd_bus_error_copy(error, &incoming->error); - else - r = -EIO; - sd_bus_message_unref(incoming); return r; + } else { + r = -EIO; + goto fail; + } } else if (BUS_MESSAGE_COOKIE(incoming) == cookie && bus->unique_name && @@ -2047,7 +2071,8 @@ _public_ int sd_bus_call( * immediately. */ sd_bus_message_unref(incoming); - return -ELOOP; + r = -ELOOP; + goto fail; } /* Try to read more, right-away */ @@ -2058,10 +2083,10 @@ _public_ int sd_bus_call( if (r < 0) { if (r == -ENOTCONN || r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) { bus_enter_closing(bus); - return -ECONNRESET; + r = -ECONNRESET; } - return r; + goto fail; } if (r > 0) continue; @@ -2070,8 +2095,10 @@ _public_ int sd_bus_call( usec_t n; n = now(CLOCK_MONOTONIC); - if (n >= timeout) - return -ETIMEDOUT; + if (n >= timeout) { + r = -ETIMEDOUT; + goto fail; + } left = timeout - n; } else @@ -2079,20 +2106,25 @@ _public_ int sd_bus_call( r = bus_poll(bus, true, left); if (r < 0) - return r; - if (r == 0) - return -ETIMEDOUT; + goto fail; + if (r == 0) { + r = -ETIMEDOUT; + goto fail; + } r = dispatch_wqueue(bus); if (r < 0) { if (r == -ENOTCONN || r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) { bus_enter_closing(bus); - return -ECONNRESET; + r = -ECONNRESET; } - return r; + goto fail; } } + +fail: + return sd_bus_error_set_errno(error, r); } _public_ int sd_bus_get_fd(sd_bus *bus) { @@ -3371,6 +3403,9 @@ _public_ int sd_bus_default(sd_bus **ret) { /* Finally, if nothing is set use the cached connection for * the right scope */ + if (cg_pid_get_owner_uid(0, NULL) >= 0) + return sd_bus_default_user(ret); + else return sd_bus_default_system(ret); } -- 2.30.2