From: Mike Yuan Date: Thu, 24 Jul 2025 13:55:29 +0000 (+0200) Subject: core/dbus-manager: validate unit type before calling into service-specific methods X-Git-Tag: v258-rc2~96^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=39a8029f4e267f1e7c128c96672f035e62d02ee7;p=thirdparty%2Fsystemd.git core/dbus-manager: validate unit type before calling into service-specific methods Fixes #38320 --- diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index f40f2f7b36e..26104423844 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -765,6 +765,7 @@ static int method_generic_unit_operation( sd_bus_message *message, Manager *m, sd_bus_error *error, + UnitType type, sd_bus_message_handler_t handler, GenericUnitOperationFlags flags) { @@ -790,6 +791,11 @@ static int method_generic_unit_operation( if (r < 0) return r; + if (type != _UNIT_TYPE_INVALID && u->type != type) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, + "%s operation is not supported for unit type '%s'", + sd_bus_message_get_member(message), unit_type_to_string(u->type)); + if (FLAGS_SET(flags, GENERIC_UNIT_VALIDATE_LOADED)) { r = bus_unit_validate_load_state(u, error); if (r < 0) @@ -801,7 +807,7 @@ static int method_generic_unit_operation( static int method_enqueue_unit_job(sd_bus_message *message, void *userdata, sd_bus_error *error) { /* We don't bother with GENERIC_UNIT_VALIDATE_LOADED here, as the job logic validates that anyway */ - return method_generic_unit_operation(message, userdata, error, bus_unit_method_enqueue_job, GENERIC_UNIT_LOAD); + return method_generic_unit_operation(message, userdata, error, _UNIT_TYPE_INVALID, bus_unit_method_enqueue_job, GENERIC_UNIT_LOAD); } static int method_start_unit_replace(sd_bus_message *message, void *userdata, sd_bus_error *error) { @@ -828,61 +834,61 @@ static int method_start_unit_replace(sd_bus_message *message, void *userdata, sd static int method_kill_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { /* We don't bother with GENERIC_UNIT_LOAD or GENERIC_UNIT_VALIDATE_LOADED here, as it shouldn't * matter whether a unit is loaded for killing any processes in the unit's cgroup. */ - return method_generic_unit_operation(message, userdata, error, bus_unit_method_kill, 0); + return method_generic_unit_operation(message, userdata, error, _UNIT_TYPE_INVALID, bus_unit_method_kill, /* flags = */ 0); } static int method_kill_unit_subgroup(sd_bus_message *message, void *userdata, sd_bus_error *error) { /* We don't bother with GENERIC_UNIT_LOAD or GENERIC_UNIT_VALIDATE_LOADED here, as it shouldn't * matter whether a unit is loaded for killing any processes in the unit's cgroup. */ - return method_generic_unit_operation(message, userdata, error, bus_unit_method_kill_subgroup, 0); + return method_generic_unit_operation(message, userdata, error, _UNIT_TYPE_INVALID, bus_unit_method_kill_subgroup, /* flags = */ 0); } static int method_clean_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { /* Load the unit if necessary, in order to load it, and insist on the unit being loaded to be * cleaned */ - return method_generic_unit_operation(message, userdata, error, bus_unit_method_clean, GENERIC_UNIT_LOAD|GENERIC_UNIT_VALIDATE_LOADED); + return method_generic_unit_operation(message, userdata, error, _UNIT_TYPE_INVALID, bus_unit_method_clean, GENERIC_UNIT_LOAD|GENERIC_UNIT_VALIDATE_LOADED); } static int method_freeze_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { /* Only active units can be frozen, which must be properly loaded already */ - return method_generic_unit_operation(message, userdata, error, bus_unit_method_freeze, GENERIC_UNIT_VALIDATE_LOADED); + return method_generic_unit_operation(message, userdata, error, _UNIT_TYPE_INVALID, bus_unit_method_freeze, GENERIC_UNIT_VALIDATE_LOADED); } static int method_thaw_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { /* Same as freeze above */ - return method_generic_unit_operation(message, userdata, error, bus_unit_method_thaw, GENERIC_UNIT_VALIDATE_LOADED); + return method_generic_unit_operation(message, userdata, error, _UNIT_TYPE_INVALID, bus_unit_method_thaw, GENERIC_UNIT_VALIDATE_LOADED); } static int method_reset_failed_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { /* Don't load the unit (because unloaded units can't be in failed state), and don't insist on the * unit to be loaded properly (since a failed unit might have its unit file disappeared) */ - return method_generic_unit_operation(message, userdata, error, bus_unit_method_reset_failed, 0); + return method_generic_unit_operation(message, userdata, error, _UNIT_TYPE_INVALID, bus_unit_method_reset_failed, /* flags = */ 0); } static int method_set_unit_properties(sd_bus_message *message, void *userdata, sd_bus_error *error) { /* Only change properties on fully loaded units, and load them in order to set properties */ - return method_generic_unit_operation(message, userdata, error, bus_unit_method_set_properties, GENERIC_UNIT_LOAD|GENERIC_UNIT_VALIDATE_LOADED); + return method_generic_unit_operation(message, userdata, error, _UNIT_TYPE_INVALID, bus_unit_method_set_properties, GENERIC_UNIT_LOAD|GENERIC_UNIT_VALIDATE_LOADED); } static int method_bind_mount_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { /* Only add mounts on fully loaded units */ - return method_generic_unit_operation(message, userdata, error, bus_service_method_bind_mount, GENERIC_UNIT_VALIDATE_LOADED); + return method_generic_unit_operation(message, userdata, error, UNIT_SERVICE, bus_service_method_bind_mount, GENERIC_UNIT_VALIDATE_LOADED); } static int method_mount_image_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { /* Only add mounts on fully loaded units */ - return method_generic_unit_operation(message, userdata, error, bus_service_method_mount_image, GENERIC_UNIT_VALIDATE_LOADED); + return method_generic_unit_operation(message, userdata, error, UNIT_SERVICE, bus_service_method_mount_image, GENERIC_UNIT_VALIDATE_LOADED); } static int method_ref_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { /* Only allow reffing of fully loaded units, and make sure reffing a unit loads it. */ - return method_generic_unit_operation(message, userdata, error, bus_unit_method_ref, GENERIC_UNIT_LOAD|GENERIC_UNIT_VALIDATE_LOADED); + return method_generic_unit_operation(message, userdata, error, _UNIT_TYPE_INVALID, bus_unit_method_ref, GENERIC_UNIT_LOAD|GENERIC_UNIT_VALIDATE_LOADED); } static int method_unref_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { /* Dropping a ref OTOH should not require the unit to still be loaded. And since a reffed unit is a * loaded unit there's no need to load the unit for unreffing it. */ - return method_generic_unit_operation(message, userdata, error, bus_unit_method_unref, 0); + return method_generic_unit_operation(message, userdata, error, _UNIT_TYPE_INVALID, bus_unit_method_unref, /* flags = */ 0); } static int reply_unit_info(sd_bus_message *reply, Unit *u) { @@ -961,20 +967,20 @@ static int method_get_unit_processes(sd_bus_message *message, void *userdata, sd /* Don't load a unit actively (since it won't have any processes if it's not loaded), but don't * insist on the unit being loaded either (because even improperly loaded units might still have * processes around). */ - return method_generic_unit_operation(message, userdata, error, bus_unit_method_get_processes, /* flags = */ 0); + return method_generic_unit_operation(message, userdata, error, _UNIT_TYPE_INVALID, bus_unit_method_get_processes, /* flags = */ 0); } static int method_attach_processes_to_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { /* Don't allow attaching new processes to units that aren't loaded. Don't bother with loading a unit * for this purpose though, as an unloaded unit is a stopped unit, and we don't allow attaching * processes to stopped units anyway. */ - return method_generic_unit_operation(message, userdata, error, bus_unit_method_attach_processes, GENERIC_UNIT_VALIDATE_LOADED); + return method_generic_unit_operation(message, userdata, error, _UNIT_TYPE_INVALID, bus_unit_method_attach_processes, GENERIC_UNIT_VALIDATE_LOADED); } static int method_remove_subgroup_from_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { /* Don't allow removal of subgroups from units that aren't loaded. But allow loading the unit, since * this is clean-up work, that is OK to do when the unit is stopped already. */ - return method_generic_unit_operation(message, userdata, error, bus_unit_method_remove_subgroup, GENERIC_UNIT_LOAD|GENERIC_UNIT_VALIDATE_LOADED); + return method_generic_unit_operation(message, userdata, error, _UNIT_TYPE_INVALID, bus_unit_method_remove_subgroup, GENERIC_UNIT_LOAD|GENERIC_UNIT_VALIDATE_LOADED); } static int transient_unit_from_message( @@ -2821,7 +2827,7 @@ static int method_set_show_status(sd_bus_message *message, void *userdata, sd_bu } static int method_dump_unit_descriptor_store(sd_bus_message *message, void *userdata, sd_bus_error *error) { - return method_generic_unit_operation(message, userdata, error, bus_service_method_dump_file_descriptor_store, GENERIC_UNIT_VALIDATE_LOADED); + return method_generic_unit_operation(message, userdata, error, UNIT_SERVICE, bus_service_method_dump_file_descriptor_store, GENERIC_UNIT_VALIDATE_LOADED); } static int method_start_aux_scope(sd_bus_message *message, void *userdata, sd_bus_error *error) {