1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-22 17:35:35 +03:00

sd-varlink: add sd_varlink_server_set_info

Fixes https://github.com/systemd/systemd/issues/35508.

As reported in the bug, the values were hardcoded for the systemd project.
https://varlink.org/Service lists vendor, product, version, url, and interfaces
as the mandatory parameters, so add an interface to set the first four. The
last field is set automatically based on the registered interfaces as before.

If the values are not filled in, we return empty strings. With NULL,
'varlinkctl info' would say:
  (string):1:25: Object field 'vendor' has wrong type null, expected string.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2024-12-09 20:08:33 +01:00
parent fbee22c237
commit 29f63c67b0
5 changed files with 49 additions and 11 deletions

View File

@ -102,6 +102,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
/* Test one: write the data as method call to a server */ /* Test one: write the data as method call to a server */
assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, server_pair) >= 0); 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_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_set_description(s, "myserver") >= 0);
assert_se(sd_varlink_server_attach_event(s, e, 0) >= 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); assert_se(sd_varlink_server_add_connection(s, server_pair[0], NULL) >= 0);

View File

@ -1037,6 +1037,7 @@ global:
sd_varlink_server_set_connections_max; sd_varlink_server_set_connections_max;
sd_varlink_server_set_connections_per_uid_max; sd_varlink_server_set_connections_per_uid_max;
sd_varlink_server_set_description; sd_varlink_server_set_description;
sd_varlink_server_set_info;
sd_varlink_server_set_exit_on_idle; sd_varlink_server_set_exit_on_idle;
sd_varlink_server_set_userdata; sd_varlink_server_set_userdata;
sd_varlink_server_shutdown; sd_varlink_server_shutdown;

View File

@ -31,7 +31,6 @@
#include "varlink-internal.h" #include "varlink-internal.h"
#include "varlink-io.systemd.h" #include "varlink-io.systemd.h"
#include "varlink-org.varlink.service.h" #include "varlink-org.varlink.service.h"
#include "version.h"
#define VARLINK_DEFAULT_CONNECTIONS_MAX 4096U #define VARLINK_DEFAULT_CONNECTIONS_MAX 4096U
#define VARLINK_DEFAULT_CONNECTIONS_PER_UID_MAX 1024U #define VARLINK_DEFAULT_CONNECTIONS_PER_UID_MAX 1024U
@ -1193,20 +1192,16 @@ static int generic_method_get_info(
void *userdata) { void *userdata) {
_cleanup_strv_free_ char **interfaces = NULL; _cleanup_strv_free_ char **interfaces = NULL;
_cleanup_free_ char *product = NULL;
int r; int r;
assert(link); assert(link);
assert(link->server);
if (sd_json_variant_elements(parameters) != 0) if (sd_json_variant_elements(parameters) != 0)
return sd_varlink_error_invalid_parameter(link, parameters); return sd_varlink_error_invalid_parameter(link, parameters);
product = strjoin("systemd (", program_invocation_short_name, ")");
if (!product)
return -ENOMEM;
sd_varlink_interface *interface; sd_varlink_interface *interface;
HASHMAP_FOREACH(interface, ASSERT_PTR(link->server)->interfaces) { HASHMAP_FOREACH(interface, link->server->interfaces) {
r = strv_extend(&interfaces, interface->name); r = strv_extend(&interfaces, interface->name);
if (r < 0) if (r < 0)
return r; return r;
@ -1216,10 +1211,10 @@ static int generic_method_get_info(
return sd_varlink_replybo( return sd_varlink_replybo(
link, link,
SD_JSON_BUILD_PAIR_STRING("vendor", "The systemd Project"), SD_JSON_BUILD_PAIR_STRING("vendor", strempty(link->server->vendor)),
SD_JSON_BUILD_PAIR_STRING("product", product), SD_JSON_BUILD_PAIR_STRING("product", strempty(link->server->product)),
SD_JSON_BUILD_PAIR_STRING("version", PROJECT_VERSION_FULL " (" GIT_VERSION ")"), SD_JSON_BUILD_PAIR_STRING("version", strempty(link->server->version)),
SD_JSON_BUILD_PAIR_STRING("url", "https://systemd.io/"), SD_JSON_BUILD_PAIR_STRING("url", strempty(link->server->url)),
SD_JSON_BUILD_PAIR_STRV("interfaces", interfaces)); 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); sd_event_unref(s->event);
free(s->description); free(s->description);
free(s->vendor);
free(s->product);
free(s->version);
free(s->url);
return mfree(s); return mfree(s);
} }
DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_varlink_server, sd_varlink_server, varlink_server_destroy); 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) { static int validate_connection(sd_varlink_server *server, const struct ucred *ucred) {
int allowed = -1; int allowed = -1;

View File

@ -222,7 +222,12 @@ struct sd_varlink_server {
Hashmap *by_uid; /* UID_TO_PTR(uid) → UINT_TO_PTR(n_connections) */ Hashmap *by_uid; /* UID_TO_PTR(uid) → UINT_TO_PTR(n_connections) */
void *userdata; void *userdata;
char *description; char *description;
char *vendor;
char *product;
char *version;
char *url;
unsigned connections_max; unsigned connections_max;
unsigned connections_per_uid_max; unsigned connections_per_uid_max;

View File

@ -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_ref(sd_varlink_server *s);
sd_varlink_server* sd_varlink_server_unref(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 */ /* 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_address(sd_varlink_server *s, const char *address, mode_t mode);
int sd_varlink_server_listen_fd(sd_varlink_server *s, int fd); int sd_varlink_server_listen_fd(sd_varlink_server *s, int fd);