From 1bdb3625c76ea238571793e09def750291a434d8 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 26 Mar 2026 12:46:56 +0100 Subject: [PATCH 1/5] core: drop `_manager()` from new vl_method to shutdown Drop the _manager suffix for vl_method_{poweroff,{soft,}reboot, halt,kexec}_manager. They're unambiguous enough and the power mgmt operations are not manager-wide but system-wide. Thanks to @YHNdnzj for suggesting this. --- src/core/varlink-manager.c | 10 +++++----- src/core/varlink-manager.h | 11 ++++++----- src/core/varlink.c | 10 +++++----- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/core/varlink-manager.c b/src/core/varlink-manager.c index bad3720632..16b640591b 100644 --- a/src/core/varlink-manager.c +++ b/src/core/varlink-manager.c @@ -458,22 +458,22 @@ static int manager_do_set_objective(sd_varlink *link, sd_json_variant *parameter return sd_varlink_reply(link, NULL); } -int vl_method_poweroff_manager(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) { +int vl_method_poweroff(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) { return manager_do_set_objective(link, parameters, MANAGER_POWEROFF, "halt", /* can_do_root= */ false); } -int vl_method_reboot_manager(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) { +int vl_method_reboot(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) { return manager_do_set_objective(link, parameters, MANAGER_REBOOT, "reboot", /* can_do_root= */ false); } -int vl_method_halt_manager(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) { +int vl_method_halt(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) { return manager_do_set_objective(link, parameters, MANAGER_HALT, "halt", /* can_do_root= */ false); } -int vl_method_kexec_manager(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) { +int vl_method_kexec(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) { return manager_do_set_objective(link, parameters, MANAGER_KEXEC, "reboot", /* can_do_root= */ false); } -int vl_method_soft_reboot_manager(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) { +int vl_method_soft_reboot(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) { return manager_do_set_objective(link, parameters, MANAGER_SOFT_REBOOT, "reboot", /* can_do_root= */ true); } diff --git a/src/core/varlink-manager.h b/src/core/varlink-manager.h index 0e477e761b..46c737f9a9 100644 --- a/src/core/varlink-manager.h +++ b/src/core/varlink-manager.h @@ -9,8 +9,9 @@ int vl_method_describe_manager(sd_varlink *link, sd_json_variant *parameters, sd int vl_method_reexecute_manager(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); int vl_method_reload_manager(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); int vl_method_enqueue_marked_jobs_manager(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); -int vl_method_poweroff_manager(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); -int vl_method_reboot_manager(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); -int vl_method_halt_manager(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); -int vl_method_kexec_manager(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); -int vl_method_soft_reboot_manager(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); + +int vl_method_poweroff(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); +int vl_method_reboot(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); +int vl_method_halt(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); +int vl_method_kexec(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); +int vl_method_soft_reboot(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); diff --git a/src/core/varlink.c b/src/core/varlink.c index 77b2d3bd82..533d1061b8 100644 --- a/src/core/varlink.c +++ b/src/core/varlink.c @@ -390,11 +390,11 @@ int manager_setup_varlink_server(Manager *m) { "io.systemd.Manager.Reexecute", vl_method_reexecute_manager, "io.systemd.Manager.Reload", vl_method_reload_manager, "io.systemd.Manager.EnqueueMarkedJobs", vl_method_enqueue_marked_jobs_manager, - "io.systemd.Manager.PowerOff", vl_method_poweroff_manager, - "io.systemd.Manager.Reboot", vl_method_reboot_manager, - "io.systemd.Manager.Halt", vl_method_halt_manager, - "io.systemd.Manager.KExec", vl_method_kexec_manager, - "io.systemd.Manager.SoftReboot", vl_method_soft_reboot_manager, + "io.systemd.Manager.PowerOff", vl_method_poweroff, + "io.systemd.Manager.Reboot", vl_method_reboot, + "io.systemd.Manager.Halt", vl_method_halt, + "io.systemd.Manager.KExec", vl_method_kexec, + "io.systemd.Manager.SoftReboot", vl_method_soft_reboot, "io.systemd.Unit.List", vl_method_list_units, "io.systemd.Unit.SetProperties", vl_method_set_unit_properties, "io.systemd.service.Ping", varlink_method_ping, From 34eec125d63ee99559bb5528ac479c0ace65173c Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 26 Mar 2026 13:16:57 +0100 Subject: [PATCH 2/5] core: simplify manager_do_set_objective `root` path handling The manager_do_set_objective() was doing a bunch of work to check the `root` path that can already be done via `json_dispatch_path` so instead of duplicating use the helper. Thanks to @YHNdnzj for suggesting this. --- src/core/varlink-manager.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/core/varlink-manager.c b/src/core/varlink-manager.c index 16b640591b..ce7f0599de 100644 --- a/src/core/varlink-manager.c +++ b/src/core/varlink-manager.c @@ -405,8 +405,7 @@ int vl_method_enqueue_marked_jobs_manager(sd_varlink *link, sd_json_variant *par static int manager_do_set_objective(sd_varlink *link, sd_json_variant *parameters, ManagerObjective objective, const char *selinux_permission, bool can_do_root) { Manager *m = ASSERT_PTR(sd_varlink_get_userdata(link)); - _cleanup_free_ char *rt = NULL; - const char *root = NULL; + _cleanup_free_ char *root = NULL; int r; assert(link); @@ -417,7 +416,7 @@ static int manager_do_set_objective(sd_varlink *link, sd_json_variant *parameter if (can_do_root) { static const sd_json_dispatch_field dispatch_table[] = { - { "root", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, 0, 0 }, + { "root", SD_JSON_VARIANT_STRING, json_dispatch_path, 0, 0 }, {} }; @@ -438,21 +437,15 @@ static int manager_do_set_objective(sd_varlink *link, sd_json_variant *parameter if (r < 0) return r; - if (!isempty(root)) { - if (!path_is_valid(root)) - return sd_varlink_error_invalid_parameter_name(link, "root"); - if (!path_is_absolute(root)) - return sd_varlink_error_invalid_parameter_name(link, "root"); - - r = path_simplify_alloc(root, &rt); - if (r < 0) - return r; + if (root) { + assert(can_do_root); + path_simplify(root); } varlink_log_caller(link, m, manager_objective_to_string(objective)); if (can_do_root) - free_and_replace(m->switch_root, rt); + free_and_replace(m->switch_root, root); m->objective = objective; return sd_varlink_reply(link, NULL); From 21b25d84709d124df68253061ca2a7a0e04628d9 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 26 Mar 2026 12:55:54 +0100 Subject: [PATCH 3/5] core: add assert(selinux_permission) to manager_do_set_objective Thanks to @YHNdnzj for suggesting this. --- src/core/varlink-manager.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/varlink-manager.c b/src/core/varlink-manager.c index ce7f0599de..5528c2f8ef 100644 --- a/src/core/varlink-manager.c +++ b/src/core/varlink-manager.c @@ -410,6 +410,7 @@ static int manager_do_set_objective(sd_varlink *link, sd_json_variant *parameter assert(link); assert(parameters); + assert(selinux_permission); if (!MANAGER_IS_SYSTEM(m)) return sd_varlink_error(link, SD_VARLINK_ERROR_METHOD_NOT_IMPLEMENTED, NULL); From 1e9f0d76fb2a984c53adc4ddb7b481ae8f3f9b90 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 26 Mar 2026 13:25:02 +0100 Subject: [PATCH 4/5] core: drop incorrect comment about SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT) The comment about `SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)` is incorrect. To quote @YHNdnzj: ``` nah, the capability-based permission model is a legacy from kdbus. We cannot do it race-freely without it. Please simply drop the comment. ``` Thanks to @YHNdnzj for suggesting this. --- src/core/varlink-manager.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/core/varlink-manager.c b/src/core/varlink-manager.c index 5528c2f8ef..8082b000aa 100644 --- a/src/core/varlink-manager.c +++ b/src/core/varlink-manager.c @@ -431,9 +431,6 @@ static int manager_do_set_objective(sd_varlink *link, sd_json_variant *parameter if (r < 0) return r; - /* dbus uses SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT) in its checking. We cannot do the same - * because reading capabilities from /proc is racy (TOCTOU). So we use the stricter check - * TODO: figure out a way to check for CAP_SYS_BOOT */ r = varlink_check_privileged_peer(link); if (r < 0) return r; From 31b9f451d73e19a43a0f0ead495ee525adc45fbd Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 26 Mar 2026 12:51:23 +0100 Subject: [PATCH 5/5] core: always call manager_log_caller() even without pidref Its fine if `manager_log_caller()` with an empty pidref, it will log an unknown caller. Thanks to @YHNdnzj for suggesting this. --- src/core/dbus-manager.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index fec53341ca..088d6c508e 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -1543,17 +1543,20 @@ static int method_refuse_snapshot(sd_bus_message *message, void *userdata, sd_bu static void log_caller(sd_bus_message *message, Manager *manager, const char *method) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; + int r; assert(message); assert(manager); assert(method); - if (sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID|SD_BUS_CREDS_PIDFD|SD_BUS_CREDS_AUGMENT, &creds) < 0) - return; - - /* We need at least the PID, otherwise there's nothing to log, the rest is optional. */ - if (bus_creds_get_pidref(creds, &pidref) < 0) - return; + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID|SD_BUS_CREDS_PIDFD|SD_BUS_CREDS_AUGMENT, &creds); + if (r < 0) + log_debug_errno(r, "Failed to get dbus sender creds, ignoring: %m"); + else { + r = bus_creds_get_pidref(creds, &pidref); + if (r < 0) + log_debug_errno(r, "Failed to get peer pidref, ignoring: %m"); + } manager_log_caller(manager, &pidref, method); }