diff --git a/TODO b/TODO index 7675d3d8ab..96d57861bd 100644 --- a/TODO +++ b/TODO @@ -4,9 +4,6 @@ Bugfixes: manager or system manager can be always set. It would be better to reject them when parsing config. -* busctl prints errors to stdout: - busctl tree org.freedesktop.systemd1 /org/freedesktop/systemd1 - External: * Fedora: add an rpmlint check that verifies that all unit files in the RPM are listed in %systemd_post macros. diff --git a/man/rules/meson.build b/man/rules/meson.build index 941e248d72..78440e6e91 100644 --- a/man/rules/meson.build +++ b/man/rules/meson.build @@ -267,6 +267,12 @@ manpages = [ ['sd_bus_get_n_queued_read', '3', ['sd_bus_get_n_queued_write'], ''], ['sd_bus_get_name_creds', '3', ['sd_bus_get_owner_creds'], ''], ['sd_bus_get_name_machine_id', '3', [], ''], + ['sd_bus_interface_name_is_valid', + '3', + ['sd_bus_member_name_is_valid', + 'sd_bus_object_path_is_valid', + 'sd_bus_service_name_is_valid'], + ''], ['sd_bus_is_open', '3', ['sd_bus_is_ready'], ''], ['sd_bus_list_names', '3', [], ''], ['sd_bus_message_append', '3', ['sd_bus_message_appendv'], ''], diff --git a/man/sd-bus.xml b/man/sd-bus.xml index 24999337c8..0938255d5c 100644 --- a/man/sd-bus.xml +++ b/man/sd-bus.xml @@ -89,6 +89,7 @@ sd_bus_get_scope3, sd_bus_get_tid3, sd_bus_get_unique_name3, +sd_bus_interface_name_is_valid3, sd_bus_is_monitor3, sd_bus_is_bus_client3, sd_bus_is_server3, diff --git a/man/sd_bus_interface_name_is_valid.xml b/man/sd_bus_interface_name_is_valid.xml new file mode 100644 index 0000000000..73c0ba1bf1 --- /dev/null +++ b/man/sd_bus_interface_name_is_valid.xml @@ -0,0 +1,98 @@ + + + + + + + sd_bus_interface_name_is_valid + systemd + + + + sd_bus_interface_name_is_valid + 3 + + + + sd_bus_interface_name_is_valid + sd_bus_service_name_is_valid + sd_bus_member_name_is_valid + sd_bus_object_path_is_valid + + Check if a string is a valid bus name or object path + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_interface_name_is_valid + const char* p + + + + int sd_bus_service_name_is_valid + const char* p + + + + int sd_bus_member_name_is_valid + const char* p + + + + int sd_bus_object_path_is_valid + const char* p + + + + + + Description + + sd_bus_interface_name_is_valid() checks if a given string + p is a syntactically valid bus interface name. Similarly, + sd_bus_service_name_is_valid() checks if the argument is a valid bus service name, + sd_bus_member_name_is_valid() checks if the argument is a valid bus interface member + name, and sd_bus_object_path_is_valid() checks if the argument is a valid bus object + path. Those functions generally check that only allowed characters are used and that the length of the + string is within limits. + + + + Return Value + + Those functions return 1 if the argument is a valid interface / service / member name or object + path, and 0 if it is not. If the argument is NULL, an error is returned. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + The p parameter is + NULL. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_message_call_method3 + + + + diff --git a/src/busctl/busctl.c b/src/busctl/busctl.c index 7aceb1796f..8e000ee119 100644 --- a/src/busctl/busctl.c +++ b/src/busctl/busctl.c @@ -110,13 +110,10 @@ static int acquire_bus(bool set_monitor, sd_bus **ret) { switch (arg_transport) { case BUS_TRANSPORT_LOCAL: - if (arg_user) { - bus->is_user = true; + if (arg_user) r = bus_set_address_user(bus); - } else { - bus->is_system = true; + else r = bus_set_address_system(bus); - } break; case BUS_TRANSPORT_REMOTE: @@ -427,29 +424,15 @@ static void print_subtree(const char *prefix, const char *path, char **l) { } } -static void print_tree(const char *prefix, char **l) { - - prefix = strempty(prefix); - - if (arg_list) { - char **i; - - STRV_FOREACH(i, l) - printf("%s%s\n", prefix, *i); - return; - } - - if (strv_isempty(l)) { +static void print_tree(char **l) { + if (arg_list) + strv_print(l); + else if (strv_isempty(l)) printf("No objects discovered.\n"); - return; - } - - if (streq(l[0], "/") && !l[1]) { + else if (streq(l[0], "/") && !l[1]) printf("Only root object discovered.\n"); - return; - } - - print_subtree(prefix, "/", l); + else + print_subtree("", "/", l); } static int on_path(const char *path, void *userdata) { @@ -465,7 +448,7 @@ static int on_path(const char *path, void *userdata) { return 0; } -static int find_nodes(sd_bus *bus, const char *service, const char *path, Set *paths, bool many) { +static int find_nodes(sd_bus *bus, const char *service, const char *path, Set *paths) { static const XMLIntrospectOps ops = { .on_path = on_path, }; @@ -479,12 +462,10 @@ static int find_nodes(sd_bus *bus, const char *service, const char *path, Set *p "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, ""); if (r < 0) { - if (many) - printf("Failed to introspect object %s of service %s: %s\n", - path, service, bus_error_message(&error, r)); - else - log_error_errno(r, "Failed to introspect object %s of service %s: %s", - path, service, bus_error_message(&error, r)); + printf("%sFailed to introspect object %s of service %s: %s%s\n", + ansi_highlight_red(), + path, service, bus_error_message(&error, r), + ansi_normal()); return r; } @@ -495,34 +476,23 @@ static int find_nodes(sd_bus *bus, const char *service, const char *path, Set *p return parse_xml_introspect(path, xml, &ops, paths); } -static int tree_one(sd_bus *bus, const char *service, const char *prefix, bool many) { - _cleanup_set_free_free_ Set *paths = NULL, *done = NULL, *failed = NULL; +static int tree_one(sd_bus *bus, const char *service) { + _cleanup_set_free_ Set *paths = NULL, *done = NULL, *failed = NULL; _cleanup_free_ char **l = NULL; - char *m; int r; - paths = set_new(&string_hash_ops); - if (!paths) + r = set_put_strdup(&paths, "/"); + if (r < 0) return log_oom(); - done = set_new(&string_hash_ops); + done = set_new(&string_hash_ops_free); if (!done) return log_oom(); - failed = set_new(&string_hash_ops); + failed = set_new(&string_hash_ops_free); if (!failed) return log_oom(); - m = strdup("/"); - if (!m) - return log_oom(); - - r = set_put(paths, m); - if (r < 0) { - free(m); - return log_oom(); - } - for (;;) { _cleanup_free_ char *p = NULL; int q; @@ -535,20 +505,14 @@ static int tree_one(sd_bus *bus, const char *service, const char *prefix, bool m set_contains(failed, p)) continue; - q = find_nodes(bus, service, p, paths, many); - if (q < 0) { - if (r >= 0) - r = q; - - q = set_put(failed, p); - } else - q = set_put(done, p); + q = find_nodes(bus, service, p, paths); + if (q < 0 && r >= 0) + r = q; + q = set_consume(q < 0 ? failed : done, TAKE_PTR(p)); + assert(q != 0); if (q < 0) return log_oom(); - - assert(q != 0); - p = NULL; } (void) pager_open(arg_pager_flags); @@ -558,7 +522,7 @@ static int tree_one(sd_bus *bus, const char *service, const char *prefix, bool m return log_oom(); strv_sort(l); - print_tree(prefix, l); + print_tree(l); fflush(stdout); @@ -570,6 +534,12 @@ static int tree(int argc, char **argv, void *userdata) { char **i; int r = 0; + /* Do superficial verification of arguments before even opening the bus */ + STRV_FOREACH(i, strv_skip(argv, 1)) + if (!sd_bus_service_name_is_valid(*i)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid bus service name: %s", *i); + if (!arg_unique && !arg_acquired) arg_acquired = true; @@ -601,14 +571,14 @@ static int tree(int argc, char **argv, void *userdata) { printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_normal()); - q = tree_one(bus, *i, NULL, true); + q = tree_one(bus, *i); if (q < 0 && r >= 0) r = q; not_first = true; } - } else { - STRV_FOREACH(i, argv+1) { + } else + STRV_FOREACH(i, strv_skip(argv, 1)) { int q; if (i > argv+1) @@ -619,11 +589,10 @@ static int tree(int argc, char **argv, void *userdata) { printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_normal()); } - q = tree_one(bus, *i, NULL, !!argv[2]); + q = tree_one(bus, *i); if (q < 0 && r >= 0) r = q; } - } return r; } @@ -1291,7 +1260,7 @@ static int monitor(int argc, char **argv, int (*dump)(sd_bus_message *m, FILE *f STRV_FOREACH(i, argv+1) { _cleanup_free_ char *m = NULL; - if (!service_name_is_valid(*i)) + if (!sd_bus_service_name_is_valid(*i)) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid service name '%s'", *i); m = strjoin("sender='", *i, "'"); @@ -2608,7 +2577,6 @@ static int parse_argv(int argc, char *argv[]) { } static int busctl_main(int argc, char *argv[]) { - static const Verb verbs[] = { { "list", VERB_ANY, 1, VERB_DEFAULT, list_bus_names }, { "status", VERB_ANY, 2, 0, status }, diff --git a/src/core/dbus-scope.c b/src/core/dbus-scope.c index 84d91dcfa3..2d877a8c55 100644 --- a/src/core/dbus-scope.c +++ b/src/core/dbus-scope.c @@ -2,7 +2,6 @@ #include "alloc-util.h" #include "bus-common-errors.h" -#include "bus-internal.h" #include "bus-util.h" #include "dbus-cgroup.h" #include "dbus-kill.h" @@ -140,7 +139,7 @@ static int bus_scope_set_transient_property( if (r < 0) return r; - if (!isempty(controller) && !service_name_is_valid(controller)) + if (!isempty(controller) && !sd_bus_service_name_is_valid(controller)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Controller '%s' is not a valid bus name.", controller); if (!UNIT_WRITE_FLAGS_NOOP(flags)) { diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c index 5cf9b21890..984ef2459e 100644 --- a/src/core/dbus-service.c +++ b/src/core/dbus-service.c @@ -4,7 +4,6 @@ #include "alloc-util.h" #include "async.h" -#include "bus-internal.h" #include "bus-util.h" #include "dbus-cgroup.h" #include "dbus-execute.h" @@ -258,7 +257,7 @@ static BUS_DEFINE_SET_TRANSIENT_PARSE(notify_access, NotifyAccess, notify_access static BUS_DEFINE_SET_TRANSIENT_PARSE(service_type, ServiceType, service_type_from_string); static BUS_DEFINE_SET_TRANSIENT_PARSE(service_restart, ServiceRestart, service_restart_from_string); static BUS_DEFINE_SET_TRANSIENT_PARSE(oom_policy, OOMPolicy, oom_policy_from_string); -static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(bus_name, service_name_is_valid); +static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(bus_name, sd_bus_service_name_is_valid); static int bus_service_set_transient_property( Service *s, diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index e420239e15..352798fd6a 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -1948,7 +1948,7 @@ int config_parse_bus_name( return 0; } - if (!service_name_is_valid(k)) { + if (!sd_bus_service_name_is_valid(k)) { log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid bus name, ignoring: %s", k); return 0; } diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index 1cfe355089..cc396780ce 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -700,6 +700,11 @@ global: LIBSYSTEMD_246 { global: + sd_bus_interface_name_is_valid; + sd_bus_service_name_is_valid; + sd_bus_member_name_is_valid; + sd_bus_object_path_is_valid; + sd_bus_call_methodv; sd_bus_call_method_asyncv; sd_bus_emit_signalv; @@ -707,6 +712,7 @@ global: sd_bus_reply_method_errorfv; sd_bus_reply_method_returnv; sd_bus_set_propertyv; + sd_path_lookup; sd_path_lookup_strv; } LIBSYSTEMD_245; diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h index 352a419e25..7e13f4f73b 100644 --- a/src/libsystemd/sd-bus/bus-internal.h +++ b/src/libsystemd/sd-bus/bus-internal.h @@ -354,6 +354,7 @@ bool interface_name_is_valid(const char *p) _pure_; bool service_name_is_valid(const char *p) _pure_; bool member_name_is_valid(const char *p) _pure_; bool object_path_is_valid(const char *p) _pure_; + char *object_path_startswith(const char *a, const char *b) _pure_; bool namespace_complex_pattern(const char *pattern, const char *value) _pure_; diff --git a/src/libsystemd/sd-bus/bus-type.c b/src/libsystemd/sd-bus/bus-type.c index 18564a5383..585f8424b3 100644 --- a/src/libsystemd/sd-bus/bus-type.c +++ b/src/libsystemd/sd-bus/bus-type.c @@ -4,6 +4,7 @@ #include "sd-bus.h" +#include "bus-internal.h" #include "bus-type.h" bool bus_type_is_valid(char c) { @@ -135,3 +136,27 @@ int bus_type_get_size(char c) { return -EINVAL; } + +_public_ int sd_bus_interface_name_is_valid(const char *p) { + assert_return(p, -EINVAL); + + return interface_name_is_valid(p); +} + +_public_ int sd_bus_service_name_is_valid(const char *p) { + assert_return(p, -EINVAL); + + return service_name_is_valid(p); +} + +_public_ int sd_bus_member_name_is_valid(const char *p) { + assert_return(p, -EINVAL); + + return member_name_is_valid(p); +} + +_public_ int sd_bus_object_path_is_valid(const char *p) { + assert_return(p, -EINVAL); + + return object_path_is_valid(p); +} diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index 366f36645a..cd1a79a256 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -1266,10 +1266,16 @@ _public_ int sd_bus_open(sd_bus **ret) { int bus_set_address_system(sd_bus *b) { const char *e; + int r; + assert(b); e = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS"); - return sd_bus_set_address(b, e ?: DEFAULT_SYSTEM_BUS_ADDRESS); + + r = sd_bus_set_address(b, e ?: DEFAULT_SYSTEM_BUS_ADDRESS); + if (r >= 0) + b->is_system = true; + return r; } _public_ int sd_bus_open_system_with_description(sd_bus **ret, const char *description) { @@ -1293,7 +1299,6 @@ _public_ int sd_bus_open_system_with_description(sd_bus **ret, const char *descr return r; b->bus_client = true; - b->is_system = true; /* Let's do per-method access control on the system bus. We * need the caller's UID and capability set for that. */ @@ -1316,6 +1321,7 @@ _public_ int sd_bus_open_system(sd_bus **ret) { int bus_set_address_user(sd_bus *b) { const char *a; _cleanup_free_ char *_a = NULL; + int r; assert(b); @@ -1337,7 +1343,10 @@ int bus_set_address_user(sd_bus *b) { a = _a; } - return sd_bus_set_address(b, a); + r = sd_bus_set_address(b, a); + if (r >= 0) + b->is_user = true; + return r; } _public_ int sd_bus_open_user_with_description(sd_bus **ret, const char *description) { @@ -1361,7 +1370,6 @@ _public_ int sd_bus_open_user_with_description(sd_bus **ret, const char *descrip return r; b->bus_client = true; - b->is_user = true; /* We don't do any per-method access control on the user bus. */ b->trusted = true; diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index 379aecf730..a61f8e70da 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -1156,7 +1156,7 @@ int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, int r; assert_return(b || (sender_id && external_id), -EINVAL); - assert_return(object_path_is_valid(prefix), -EINVAL); + assert_return(sd_bus_object_path_is_valid(prefix), -EINVAL); assert_return(ret_path, -EINVAL); if (!sender_id) { @@ -1208,8 +1208,8 @@ int bus_path_decode_unique(const char *path, const char *prefix, char **ret_send const char *p, *q; char *sender, *external; - assert(object_path_is_valid(path)); - assert(object_path_is_valid(prefix)); + assert(sd_bus_object_path_is_valid(path)); + assert(sd_bus_object_path_is_valid(prefix)); assert(ret_sender); assert(ret_external); @@ -1670,7 +1670,7 @@ int bus_introspect_implementations( } struct introspect intro = {}; - bool is_interface = interface_name_is_valid(pattern); + bool is_interface = sd_bus_interface_name_is_valid(pattern); impl = find_implementation(pattern, bus_objects); if (!impl) diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h index 61b5a493c7..d4b6befc8c 100644 --- a/src/systemd/sd-bus.h +++ b/src/systemd/sd-bus.h @@ -124,6 +124,13 @@ typedef _sd_destroy_t sd_bus_destroy_t; #include "sd-bus-protocol.h" #include "sd-bus-vtable.h" +/* Naming */ + +int sd_bus_interface_name_is_valid(const char *p); +int sd_bus_service_name_is_valid(const char *p); +int sd_bus_member_name_is_valid(const char *p); +int sd_bus_object_path_is_valid(const char *p); + /* Connections */ int sd_bus_default(sd_bus **ret);