diff --git a/src/basic/log.c b/src/basic/log.c index cbc6edc95d..2250dfe927 100644 --- a/src/basic/log.c +++ b/src/basic/log.c @@ -397,7 +397,7 @@ void log_forget_fds(void) { } int log_set_max_level(int level) { - assert(level == LOG_NULL || LOG_PRI(level) == level); + assert(level == LOG_NULL || log_level_is_valid(level)); int old = log_max_level; log_max_level = level; diff --git a/src/basic/log.h b/src/basic/log.h index 3859a6c41d..02f3f509d1 100644 --- a/src/basic/log.h +++ b/src/basic/log.h @@ -34,6 +34,7 @@ typedef enum LogTarget{ /* This log level disables logging completely. It can only be passed to log_set_max_level() and cannot be * used as a regular log level. */ #define LOG_NULL (LOG_EMERG - 1) +assert_cc(LOG_NULL == -1); #define SYNTHETIC_ERRNO(num) (abs(num) | (1 << 30)) #define IS_SYNTHETIC_ERRNO(val) (((val) >> 30) == 1) diff --git a/src/core/core-varlink.c b/src/core/core-varlink.c index 4f0563a1c0..92cfd36e71 100644 --- a/src/core/core-varlink.c +++ b/src/core/core-varlink.c @@ -10,6 +10,7 @@ #include "varlink-internal.h" #include "varlink-io.systemd.UserDatabase.h" #include "varlink-io.systemd.ManagedOOM.h" +#include "varlink-io.systemd.service.h" #include "varlink-util.h" typedef struct LookupParameters { @@ -589,7 +590,8 @@ int manager_setup_varlink_server(Manager *m) { r = sd_varlink_server_add_interface_many( s, &vl_interface_io_systemd_UserDatabase, - &vl_interface_io_systemd_ManagedOOM); + &vl_interface_io_systemd_ManagedOOM, + &vl_interface_io_systemd_service); if (r < 0) return log_debug_errno(r, "Failed to add interfaces to varlink server: %m"); @@ -598,7 +600,9 @@ int manager_setup_varlink_server(Manager *m) { "io.systemd.UserDatabase.GetUserRecord", vl_method_get_user_record, "io.systemd.UserDatabase.GetGroupRecord", vl_method_get_group_record, "io.systemd.UserDatabase.GetMemberships", vl_method_get_memberships, - "io.systemd.ManagedOOM.SubscribeManagedOOMCGroups", vl_method_subscribe_managed_oom_cgroups); + "io.systemd.ManagedOOM.SubscribeManagedOOMCGroups", vl_method_subscribe_managed_oom_cgroups, + "io.systemd.service.Ping", varlink_method_ping, + "io.systemd.service.GetEnvironment", varlink_method_get_environment); if (r < 0) return log_debug_errno(r, "Failed to register varlink methods: %m"); diff --git a/src/home/homed-manager.c b/src/home/homed-manager.c index bb4ad1f99f..a0d38eb701 100644 --- a/src/home/homed-manager.c +++ b/src/home/homed-manager.c @@ -54,6 +54,7 @@ #include "user-record-util.h" #include "user-record.h" #include "user-util.h" +#include "varlink-io.systemd.service.h" #include "varlink-io.systemd.UserDatabase.h" #include "varlink-util.h" @@ -1012,7 +1013,10 @@ static int manager_bind_varlink(Manager *m) { if (r < 0) return log_error_errno(r, "Failed to allocate varlink server: %m"); - r = sd_varlink_server_add_interface(m->varlink_server, &vl_interface_io_systemd_UserDatabase); + r = sd_varlink_server_add_interface_many( + m->varlink_server, + &vl_interface_io_systemd_UserDatabase, + &vl_interface_io_systemd_service); if (r < 0) return log_error_errno(r, "Failed to add UserDatabase interface to varlink server: %m"); @@ -1020,7 +1024,10 @@ static int manager_bind_varlink(Manager *m) { m->varlink_server, "io.systemd.UserDatabase.GetUserRecord", vl_method_get_user_record, "io.systemd.UserDatabase.GetGroupRecord", vl_method_get_group_record, - "io.systemd.UserDatabase.GetMemberships", vl_method_get_memberships); + "io.systemd.UserDatabase.GetMemberships", vl_method_get_memberships, + "io.systemd.service.Ping", varlink_method_ping, + "io.systemd.service.SetLogLevel", varlink_method_set_log_level, + "io.systemd.service.GetEnvironment", varlink_method_get_environment); if (r < 0) return log_error_errno(r, "Failed to register varlink methods: %m"); diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c index 2af9c68d98..a4549da826 100644 --- a/src/hostname/hostnamed.c +++ b/src/hostname/hostnamed.c @@ -42,6 +42,7 @@ #include "user-util.h" #include "utf8.h" #include "varlink-io.systemd.Hostname.h" +#include "varlink-io.systemd.service.h" #include "varlink-util.h" #include "virt.h" @@ -1771,13 +1772,19 @@ static int connect_varlink(Context *c) { if (r < 0) return log_error_errno(r, "Failed to allocate Varlink server: %m"); - r = sd_varlink_server_add_interface(c->varlink_server, &vl_interface_io_systemd_Hostname); + r = sd_varlink_server_add_interface_many( + c->varlink_server, + &vl_interface_io_systemd_Hostname, + &vl_interface_io_systemd_service); if (r < 0) return log_error_errno(r, "Failed to add Hostname interface to Varlink server: %m"); r = sd_varlink_server_bind_method_many( c->varlink_server, - "io.systemd.Hostname.Describe", vl_method_describe); + "io.systemd.Hostname.Describe", vl_method_describe, + "io.systemd.service.Ping", varlink_method_ping, + "io.systemd.service.SetLogLevel", varlink_method_set_log_level, + "io.systemd.service.GetEnvironment", varlink_method_get_environment); if (r < 0) return log_error_errno(r, "Failed to bind Varlink method calls: %m"); diff --git a/src/import/importd.c b/src/import/importd.c index ea8257a833..72c0e4a95a 100644 --- a/src/import/importd.c +++ b/src/import/importd.c @@ -42,6 +42,7 @@ #include "syslog-util.h" #include "user-util.h" #include "varlink-io.systemd.Import.h" +#include "varlink-io.systemd.service.h" #include "varlink-util.h" #include "web-util.h" @@ -1979,14 +1980,20 @@ static int manager_connect_varlink(Manager *m) { if (r < 0) return log_error_errno(r, "Failed to allocate varlink server object: %m"); - r = sd_varlink_server_add_interface(m->varlink_server, &vl_interface_io_systemd_Import); + r = sd_varlink_server_add_interface_many( + m->varlink_server, + &vl_interface_io_systemd_Import, + &vl_interface_io_systemd_service); if (r < 0) return log_error_errno(r, "Failed to add Import interface to varlink server: %m"); r = sd_varlink_server_bind_method_many( m->varlink_server, - "io.systemd.Import.ListTransfers", vl_method_list_transfers, - "io.systemd.Import.Pull", vl_method_pull); + "io.systemd.Import.ListTransfers", vl_method_list_transfers, + "io.systemd.Import.Pull", vl_method_pull, + "io.systemd.service.Ping", varlink_method_ping, + "io.systemd.service.SetLogLevel", varlink_method_set_log_level, + "io.systemd.service.GetEnvironment", varlink_method_get_environment); if (r < 0) return log_error_errno(r, "Failed to bind Varlink method calls: %m"); diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 8fcfa0c57b..3469a90fef 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -64,6 +64,7 @@ #include "uid-classification.h" #include "user-util.h" #include "varlink-io.systemd.Journal.h" +#include "varlink-io.systemd.service.h" #include "varlink-util.h" #define USER_JOURNALS_MAX 1024 @@ -2334,16 +2335,22 @@ static int server_open_varlink(Server *s, const char *socket, int fd) { if (r < 0) return log_error_errno(r, "Failed to allocate varlink server object: %m"); - r = sd_varlink_server_add_interface(s->varlink_server, &vl_interface_io_systemd_Journal); + r = sd_varlink_server_add_interface_many( + s->varlink_server, + &vl_interface_io_systemd_Journal, + &vl_interface_io_systemd_service); if (r < 0) return log_error_errno(r, "Failed to add Journal interface to varlink server: %m"); r = sd_varlink_server_bind_method_many( s->varlink_server, - "io.systemd.Journal.Synchronize", vl_method_synchronize, - "io.systemd.Journal.Rotate", vl_method_rotate, - "io.systemd.Journal.FlushToVar", vl_method_flush_to_var, - "io.systemd.Journal.RelinquishVar", vl_method_relinquish_var); + "io.systemd.Journal.Synchronize", vl_method_synchronize, + "io.systemd.Journal.Rotate", vl_method_rotate, + "io.systemd.Journal.FlushToVar", vl_method_flush_to_var, + "io.systemd.Journal.RelinquishVar", vl_method_relinquish_var, + "io.systemd.service.Ping", varlink_method_ping, + "io.systemd.service.SetLogLevel", varlink_method_set_log_level, + "io.systemd.service.GetEnvironment", varlink_method_get_environment); if (r < 0) return r; diff --git a/src/libsystemd/sd-json/json-util.c b/src/libsystemd/sd-json/json-util.c index ea64205c14..f2d306f781 100644 --- a/src/libsystemd/sd-json/json-util.c +++ b/src/libsystemd/sd-json/json-util.c @@ -13,6 +13,7 @@ #include "path-util.h" #include "process-util.h" #include "string-util.h" +#include "syslog-util.h" #include "user-util.h" int json_dispatch_unbase64_iovec(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata) { @@ -344,8 +345,15 @@ int json_dispatch_ifindex(const char *name, sd_json_variant *variant, sd_json_di int json_dispatch_log_level(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata) { int *log_level = ASSERT_PTR(userdata), r, t; + /* If SD_JSON_STRICT is set, we'll refuse attempts to set the log level to null. If SD_JSON_RELAX is + * set we'll turn null (and any negative log level) into LOG_NULL (which when used as max log level + * means: no logging). Otherwise we turn null into LOG_INFO (which is typically our default). */ + if (sd_json_variant_is_null(variant)) { - *log_level = -1; + if (FLAGS_SET(flags, SD_JSON_STRICT)) + return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' may not be null.", strna(name)); + + *log_level = FLAGS_SET(flags, SD_JSON_RELAX) ? LOG_NULL : LOG_INFO; return 0; } @@ -353,8 +361,9 @@ int json_dispatch_log_level(const char *name, sd_json_variant *variant, sd_json_ if (r < 0) return r; - /* If SD_JSON_RELAX is set allow a zero interface index, otherwise refuse. */ - if (LOG_PRI(t) != t) + if (FLAGS_SET(flags, SD_JSON_RELAX) && t < 0) + t = LOG_NULL; + else if (!log_level_is_valid(t)) return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a valid log level.", strna(name)); *log_level = t; diff --git a/src/login/logind-varlink.c b/src/login/logind-varlink.c index a8a2542e18..a757033a55 100644 --- a/src/login/logind-varlink.c +++ b/src/login/logind-varlink.c @@ -10,6 +10,7 @@ #include "terminal-util.h" #include "user-util.h" #include "varlink-io.systemd.Login.h" +#include "varlink-io.systemd.service.h" #include "varlink-util.h" static int manager_varlink_get_session_by_peer( @@ -355,14 +356,20 @@ int manager_varlink_init(Manager *m) { sd_varlink_server_set_userdata(s, m); - r = sd_varlink_server_add_interface(s, &vl_interface_io_systemd_Login); + r = sd_varlink_server_add_interface_many( + s, + &vl_interface_io_systemd_Login, + &vl_interface_io_systemd_service); if (r < 0) return log_error_errno(r, "Failed to add Login interface to varlink server: %m"); r = sd_varlink_server_bind_method_many( s, - "io.systemd.Login.CreateSession", vl_method_create_session, - "io.systemd.Login.ReleaseSession", vl_method_release_session); + "io.systemd.Login.CreateSession", vl_method_create_session, + "io.systemd.Login.ReleaseSession", vl_method_release_session, + "io.systemd.service.Ping", varlink_method_ping, + "io.systemd.service.SetLogLevel", varlink_method_set_log_level, + "io.systemd.service.GetEnvironment", varlink_method_get_environment); if (r < 0) return log_error_errno(r, "Failed to register varlink methods: %m"); diff --git a/src/machine/machined-varlink.c b/src/machine/machined-varlink.c index dc293f5895..5beec14ccd 100644 --- a/src/machine/machined-varlink.c +++ b/src/machine/machined-varlink.c @@ -17,6 +17,7 @@ #include "varlink-io.systemd.Machine.h" #include "varlink-io.systemd.MachineImage.h" #include "varlink-io.systemd.UserDatabase.h" +#include "varlink-io.systemd.service.h" #include "varlink-util.h" typedef struct LookupParameters { @@ -776,7 +777,8 @@ static int manager_varlink_init_machine(Manager *m) { r = sd_varlink_server_add_interface_many( s, &vl_interface_io_systemd_Machine, - &vl_interface_io_systemd_MachineImage); + &vl_interface_io_systemd_MachineImage, + &vl_interface_io_systemd_service); if (r < 0) return log_error_errno(r, "Failed to add Machine and MachineImage interfaces to varlink server: %m"); @@ -798,7 +800,10 @@ static int manager_varlink_init_machine(Manager *m) { "io.systemd.MachineImage.Update", vl_method_update_image, "io.systemd.MachineImage.Clone", vl_method_clone_image, "io.systemd.MachineImage.Remove", vl_method_remove_image, - "io.systemd.MachineImage.SetPoolLimit", vl_method_set_pool_limit); + "io.systemd.MachineImage.SetPoolLimit", vl_method_set_pool_limit, + "io.systemd.service.Ping", varlink_method_ping, + "io.systemd.service.SetLogLevel", varlink_method_set_log_level, + "io.systemd.service.GetEnvironment", varlink_method_get_environment); if (r < 0) return log_error_errno(r, "Failed to register varlink methods: %m"); diff --git a/src/network/networkd-manager-varlink.c b/src/network/networkd-manager-varlink.c index b2a196c5fc..6206fb6e44 100644 --- a/src/network/networkd-manager-varlink.c +++ b/src/network/networkd-manager-varlink.c @@ -12,6 +12,7 @@ #include "networkd-manager-varlink.h" #include "stat-util.h" #include "varlink-io.systemd.Network.h" +#include "varlink-io.systemd.service.h" #include "varlink-util.h" static int vl_method_get_states(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) { @@ -269,16 +270,22 @@ int manager_connect_varlink(Manager *m) { (void) sd_varlink_server_set_description(s, "varlink-api-network"); - r = sd_varlink_server_add_interface(s, &vl_interface_io_systemd_Network); + r = sd_varlink_server_add_interface_many( + s, + &vl_interface_io_systemd_Network, + &vl_interface_io_systemd_service); if (r < 0) return log_error_errno(r, "Failed to add Network interface to varlink server: %m"); r = sd_varlink_server_bind_method_many( s, - "io.systemd.Network.GetStates", vl_method_get_states, - "io.systemd.Network.GetNamespaceId", vl_method_get_namespace_id, - "io.systemd.Network.GetLLDPNeighbors", vl_method_get_lldp_neighbors, - "io.systemd.Network.SetPersistentStorage", vl_method_set_persistent_storage); + "io.systemd.Network.GetStates", vl_method_get_states, + "io.systemd.Network.GetNamespaceId", vl_method_get_namespace_id, + "io.systemd.Network.GetLLDPNeighbors", vl_method_get_lldp_neighbors, + "io.systemd.Network.SetPersistentStorage", vl_method_set_persistent_storage, + "io.systemd.service.Ping", varlink_method_ping, + "io.systemd.service.SetLogLevel", varlink_method_set_log_level, + "io.systemd.service.GetEnvironment", varlink_method_get_environment); if (r < 0) return log_error_errno(r, "Failed to register varlink methods: %m"); diff --git a/src/oom/oomd-manager.c b/src/oom/oomd-manager.c index ce3674365a..352d558281 100644 --- a/src/oom/oomd-manager.c +++ b/src/oom/oomd-manager.c @@ -20,6 +20,7 @@ #include "path-util.h" #include "percent-util.h" #include "varlink-io.systemd.oom.h" +#include "varlink-io.systemd.service.h" #include "varlink-util.h" typedef struct ManagedOOMMessage { @@ -746,13 +747,21 @@ static int manager_varlink_init(Manager *m, int fd) { if (r < 0) return log_error_errno(r, "Failed to allocate varlink server object: %m"); - r = sd_varlink_server_add_interface(s, &vl_interface_io_systemd_oom); + r = sd_varlink_server_add_interface_many( + s, + &vl_interface_io_systemd_oom, + &vl_interface_io_systemd_service); if (r < 0) - return log_error_errno(r, "Failed to add oom interface to varlink server: %m"); + return log_error_errno(r, "Failed to add Varlink interfaces to varlink server: %m"); - r = sd_varlink_server_bind_method(s, "io.systemd.oom.ReportManagedOOMCGroups", process_managed_oom_request); + r = sd_varlink_server_bind_method_many( + s, + "io.systemd.oom.ReportManagedOOMCGroups", process_managed_oom_request, + "io.systemd.service.Ping", varlink_method_ping, + "io.systemd.service.SetLogLevel", varlink_method_set_log_level, + "io.systemd.service.GetEnvironment", varlink_method_get_environment); if (r < 0) - return log_error_errno(r, "Failed to register varlink method: %m"); + return log_error_errno(r, "Failed to register varlink methods: %m"); if (fd < 0) r = sd_varlink_server_listen_address(s, VARLINK_ADDR_PATH_MANAGED_OOM_USER, 0666); diff --git a/src/resolve/resolved-varlink.c b/src/resolve/resolved-varlink.c index 107f722e7d..c30a2a3fea 100644 --- a/src/resolve/resolved-varlink.c +++ b/src/resolve/resolved-varlink.c @@ -9,6 +9,7 @@ #include "socket-netlink.h" #include "varlink-io.systemd.Resolve.h" #include "varlink-io.systemd.Resolve.Monitor.h" +#include "varlink-io.systemd.service.h" #include "varlink-util.h" typedef struct LookupParameters { @@ -1410,7 +1411,10 @@ static int varlink_main_server_init(Manager *m) { if (r < 0) return log_error_errno(r, "Failed to allocate varlink server object: %m"); - r = sd_varlink_server_add_interface(s, &vl_interface_io_systemd_Resolve); + r = sd_varlink_server_add_interface_many( + s, + &vl_interface_io_systemd_Resolve, + &vl_interface_io_systemd_service); if (r < 0) return log_error_errno(r, "Failed to add Resolve interface to varlink server: %m"); @@ -1419,7 +1423,10 @@ static int varlink_main_server_init(Manager *m) { "io.systemd.Resolve.ResolveHostname", vl_method_resolve_hostname, "io.systemd.Resolve.ResolveAddress", vl_method_resolve_address, "io.systemd.Resolve.ResolveService", vl_method_resolve_service, - "io.systemd.Resolve.ResolveRecord", vl_method_resolve_record); + "io.systemd.Resolve.ResolveRecord", vl_method_resolve_record, + "io.systemd.service.Ping", varlink_method_ping, + "io.systemd.service.SetLogLevel", varlink_method_set_log_level, + "io.systemd.service.GetEnvironment", varlink_method_get_environment); if (r < 0) return log_error_errno(r, "Failed to register varlink methods: %m"); diff --git a/src/shared/varlink-io.systemd.service.c b/src/shared/varlink-io.systemd.service.c index f34d5cfead..dd1329f878 100644 --- a/src/shared/varlink-io.systemd.service.c +++ b/src/shared/varlink-io.systemd.service.c @@ -2,7 +2,9 @@ #include +#include "env-util.h" #include "json-util.h" +#include "strv.h" #include "varlink-io.systemd.service.h" static SD_VARLINK_DEFINE_METHOD(Ping); @@ -11,8 +13,16 @@ static SD_VARLINK_DEFINE_METHOD(Reload); static SD_VARLINK_DEFINE_METHOD( SetLogLevel, - SD_VARLINK_FIELD_COMMENT("The maximum log level."), - SD_VARLINK_DEFINE_INPUT(level, SD_VARLINK_INT, 0)); + SD_VARLINK_FIELD_COMMENT("The maximum log level, using BSD syslog log level integers."), + SD_VARLINK_DEFINE_INPUT(level, SD_VARLINK_INT, SD_VARLINK_NULLABLE)); + +static SD_VARLINK_DEFINE_METHOD( + GetEnvironment, + SD_VARLINK_FIELD_COMMENT("Returns the current environment block, i.e. the contents of environ[]."), + SD_VARLINK_DEFINE_OUTPUT(environment, SD_VARLINK_STRING, SD_VARLINK_NULLABLE|SD_VARLINK_ARRAY)); + +static SD_VARLINK_DEFINE_ERROR( + InconsistentEnvironment); SD_VARLINK_DEFINE_INTERFACE( io_systemd_service, @@ -20,16 +30,25 @@ SD_VARLINK_DEFINE_INTERFACE( SD_VARLINK_INTERFACE_COMMENT("An interface to control basic properties of systemd services."), SD_VARLINK_SYMBOL_COMMENT("Checks if the service is running."), &vl_method_Ping, - SD_VARLINK_SYMBOL_COMMENT("Reloads configurations."), + SD_VARLINK_SYMBOL_COMMENT("Reloads configuration files."), &vl_method_Reload, SD_VARLINK_SYMBOL_COMMENT("Sets the maximum log level."), - &vl_method_SetLogLevel); + &vl_method_SetLogLevel, + SD_VARLINK_SYMBOL_COMMENT("Get current environment block."), + &vl_method_GetEnvironment, + SD_VARLINK_SYMBOL_COMMENT("Returned if the environment block is currently not in a valid state."), + &vl_error_InconsistentEnvironment); + +/* Generic implementations for some of the method calls above */ int varlink_method_ping(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) { + int r; + assert(link); - if (sd_json_variant_elements(parameters) > 0) - return sd_varlink_error_invalid_parameter(link, parameters); + r = sd_varlink_dispatch(link, parameters, /* dispatch_table= */ NULL, /* userdata= */ NULL); + if (r != 0) + return r; log_debug("Received io.systemd.service.Ping"); @@ -48,11 +67,6 @@ int varlink_method_set_log_level(sd_varlink *link, sd_json_variant *parameters, assert(link); assert(parameters); - /* NOTE: The method does have 1 parameter, but we must compare to 2 here, because - * sd_json_variant_elements() breaks abstraction and exposes internal structure of JsonObject. */ - if (sd_json_variant_elements(parameters) != 2) - return sd_varlink_error_invalid_parameter(link, parameters); - r = sd_varlink_dispatch(link, parameters, dispatch_table, &level); if (r != 0) return r; @@ -70,3 +84,48 @@ int varlink_method_set_log_level(sd_varlink *link, sd_json_variant *parameters, return sd_varlink_reply(link, NULL); } + +int varlink_method_get_environment(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) { + uid_t uid; + int r; + + assert(link); + assert(parameters); + + /* This is a lot like /proc/$PID/environ, but can properly report the actual environment block as + * seen from the process itself, which might be quite different from the contents of the memory that + * was originally passed in. This is particularly relevant for cases where the environ[] block has + * been enlarged and similar. */ + + r = sd_varlink_dispatch(link, parameters, /* dispatch_table= */ NULL, /* userdata= */ NULL); + if (r != 0) + return r; + + r = sd_varlink_get_peer_uid(link, &uid); + if (r < 0) + return r; + + /* Don't hand out environment block to arbitrary clients, in some cases people might make the mistake + * of passing secrets via env vars */ + if (uid != 0 && uid != getuid()) + return sd_varlink_error(link, SD_VARLINK_ERROR_PERMISSION_DENIED, parameters); + + log_debug("Received io.systemd.service.GetEnvironment()"); + + _cleanup_strv_free_ char **l = NULL; + STRV_FOREACH(e, environ) { + if (!env_assignment_is_valid(*e)) + goto invalid; + if (!utf8_is_valid(*e)) + goto invalid; + + r = strv_env_replace_strdup(&l, *e); + if (r < 0) + return r; + } + + return sd_varlink_replybo(link, SD_JSON_BUILD_PAIR_STRV("environment", l)); + +invalid: + return sd_varlink_error(link, "io.systemd.service.InconsistentEnvironment", parameters); +} diff --git a/src/shared/varlink-io.systemd.service.h b/src/shared/varlink-io.systemd.service.h index 3f164783f5..a68d58d6d4 100644 --- a/src/shared/varlink-io.systemd.service.h +++ b/src/shared/varlink-io.systemd.service.h @@ -8,3 +8,4 @@ extern const sd_varlink_interface vl_interface_io_systemd_service; int varlink_method_ping(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); int varlink_method_set_log_level(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); +int varlink_method_get_environment(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); diff --git a/src/udev/udev-config.c b/src/udev/udev-config.c index d511691ab2..e60464360d 100644 --- a/src/udev/udev-config.c +++ b/src/udev/udev-config.c @@ -306,7 +306,7 @@ void manager_set_children_max(Manager *manager, unsigned n) { void manager_set_log_level(Manager *manager, int log_level) { assert(manager); - assert(LOG_PRI(log_level) == log_level); + assert(log_level_is_valid(log_level)); int old = log_get_max_level(); diff --git a/src/udev/udev-manager.c b/src/udev/udev-manager.c index b7f2b185c9..caa4379759 100644 --- a/src/udev/udev-manager.c +++ b/src/udev/udev-manager.c @@ -851,7 +851,7 @@ static int on_ctrl_msg(UdevCtrl *uctrl, UdevCtrlMessageType type, const UdevCtrl switch (type) { case UDEV_CTRL_SET_LOG_LEVEL: - if (LOG_PRI(value->intval) != value->intval) { + if (!log_level_is_valid(value->intval)) { log_debug("Received invalid udev control message (SET_LOG_LEVEL, %i), ignoring.", value->intval); break; } diff --git a/test/units/TEST-13-NSPAWN.importctl.sh b/test/units/TEST-13-NSPAWN.importctl.sh index be31837447..ac4a70e9b0 100755 --- a/test/units/TEST-13-NSPAWN.importctl.sh +++ b/test/units/TEST-13-NSPAWN.importctl.sh @@ -83,3 +83,10 @@ systemctl daemon-reload systemctl start import0.service cmp /var/tmp/importtest /var/lib/confexts/importtest9/importtest + +# Verify generic service calls, too +varlinkctl call --more /run/systemd/io.systemd.Import io.systemd.service.Ping '{}' +varlinkctl call --more /run/systemd/io.systemd.Import io.systemd.service.SetLogLevel '{"level":"7"}' +varlinkctl call --more /run/systemd/io.systemd.Import io.systemd.service.SetLogLevel '{"level":"1"}' +varlinkctl call --more /run/systemd/io.systemd.Import io.systemd.service.SetLogLevel '{"level":"7"}' +varlinkctl call --more /run/systemd/io.systemd.Import io.systemd.service.GetEnvironment '{}'