diff --git a/src/fuzz/fuzz-varlink.c b/src/fuzz/fuzz-varlink.c index 2342e34d8f..2497fe3b9e 100644 --- a/src/fuzz/fuzz-varlink.c +++ b/src/fuzz/fuzz-varlink.c @@ -102,6 +102,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { /* Test one: write the data as method call to a server */ assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, server_pair) >= 0); assert_se(sd_varlink_server_new(&s, 0) >= 0); + assert_se(sd_varlink_server_set_info(s, "Vendor", "Product", "Version", "URL") >= 0); assert_se(sd_varlink_server_set_description(s, "myserver") >= 0); assert_se(sd_varlink_server_attach_event(s, e, 0) >= 0); assert_se(sd_varlink_server_add_connection(s, server_pair[0], NULL) >= 0); diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index 0b948b86a2..a76dc7e4ae 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -1037,6 +1037,7 @@ global: sd_varlink_server_set_connections_max; sd_varlink_server_set_connections_per_uid_max; sd_varlink_server_set_description; + sd_varlink_server_set_info; sd_varlink_server_set_exit_on_idle; sd_varlink_server_set_userdata; sd_varlink_server_shutdown; diff --git a/src/libsystemd/sd-varlink/sd-varlink.c b/src/libsystemd/sd-varlink/sd-varlink.c index 150ce4edda..5e9999deaf 100644 --- a/src/libsystemd/sd-varlink/sd-varlink.c +++ b/src/libsystemd/sd-varlink/sd-varlink.c @@ -31,7 +31,6 @@ #include "varlink-internal.h" #include "varlink-io.systemd.h" #include "varlink-org.varlink.service.h" -#include "version.h" #define VARLINK_DEFAULT_CONNECTIONS_MAX 4096U #define VARLINK_DEFAULT_CONNECTIONS_PER_UID_MAX 1024U @@ -1193,20 +1192,16 @@ static int generic_method_get_info( void *userdata) { _cleanup_strv_free_ char **interfaces = NULL; - _cleanup_free_ char *product = NULL; int r; assert(link); + assert(link->server); if (sd_json_variant_elements(parameters) != 0) return sd_varlink_error_invalid_parameter(link, parameters); - product = strjoin("systemd (", program_invocation_short_name, ")"); - if (!product) - return -ENOMEM; - sd_varlink_interface *interface; - HASHMAP_FOREACH(interface, ASSERT_PTR(link->server)->interfaces) { + HASHMAP_FOREACH(interface, link->server->interfaces) { r = strv_extend(&interfaces, interface->name); if (r < 0) return r; @@ -1216,10 +1211,10 @@ static int generic_method_get_info( return sd_varlink_replybo( link, - SD_JSON_BUILD_PAIR_STRING("vendor", "The systemd Project"), - SD_JSON_BUILD_PAIR_STRING("product", product), - SD_JSON_BUILD_PAIR_STRING("version", PROJECT_VERSION_FULL " (" GIT_VERSION ")"), - SD_JSON_BUILD_PAIR_STRING("url", "https://systemd.io/"), + SD_JSON_BUILD_PAIR_STRING("vendor", strempty(link->server->vendor)), + SD_JSON_BUILD_PAIR_STRING("product", strempty(link->server->product)), + SD_JSON_BUILD_PAIR_STRING("version", strempty(link->server->version)), + SD_JSON_BUILD_PAIR_STRING("url", strempty(link->server->url)), SD_JSON_BUILD_PAIR_STRV("interfaces", interfaces)); } @@ -3262,12 +3257,41 @@ static sd_varlink_server* varlink_server_destroy(sd_varlink_server *s) { sd_event_unref(s->event); free(s->description); + free(s->vendor); + free(s->product); + free(s->version); + free(s->url); return mfree(s); } DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_varlink_server, sd_varlink_server, varlink_server_destroy); +_public_ int sd_varlink_server_set_info( + sd_varlink_server *s, + const char *vendor, + const char *product, + const char *version, + const char *url) { + + assert_return(s, -EINVAL); + + _cleanup_free_ char + *a = vendor ? strdup(vendor) : NULL, + *b = product ? strdup(product) : NULL, + *c = version ? strdup(version) : NULL, + *d = url ? strdup(url) : NULL; + if ((vendor && !a) || (product && !b) || (version && !c) || (url && !d)) + return log_oom_debug(); + + free_and_replace(s->vendor, a); + free_and_replace(s->product, b); + free_and_replace(s->version, c); + free_and_replace(s->url, d); + + return 0; +} + static int validate_connection(sd_varlink_server *server, const struct ucred *ucred) { int allowed = -1; diff --git a/src/libsystemd/sd-varlink/varlink-internal.h b/src/libsystemd/sd-varlink/varlink-internal.h index b184ac7754..377f8cfae4 100644 --- a/src/libsystemd/sd-varlink/varlink-internal.h +++ b/src/libsystemd/sd-varlink/varlink-internal.h @@ -222,7 +222,12 @@ struct sd_varlink_server { Hashmap *by_uid; /* UID_TO_PTR(uid) → UINT_TO_PTR(n_connections) */ void *userdata; + char *description; + char *vendor; + char *product; + char *version; + char *url; unsigned connections_max; unsigned connections_per_uid_max; diff --git a/src/systemd/sd-varlink.h b/src/systemd/sd-varlink.h index fbf575ffdf..833977d8b2 100644 --- a/src/systemd/sd-varlink.h +++ b/src/systemd/sd-varlink.h @@ -219,6 +219,13 @@ int sd_varlink_server_new(sd_varlink_server **ret, sd_varlink_server_flags_t fla sd_varlink_server* sd_varlink_server_ref(sd_varlink_server *s); sd_varlink_server* sd_varlink_server_unref(sd_varlink_server *s); +int sd_varlink_server_set_info( + sd_varlink_server *s, + const char *vendor, + const char *product, + const char *version, + const char *url); + /* Add addresses or fds to listen on */ int sd_varlink_server_listen_address(sd_varlink_server *s, const char *address, mode_t mode); int sd_varlink_server_listen_fd(sd_varlink_server *s, int fd);