diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml index e6611d04e7..88f13d05b6 100644 --- a/man/systemd-system.conf.xml +++ b/man/systemd-system.conf.xml @@ -624,10 +624,12 @@ ReloadLimitIntervalSec= ReloadLimitBurst= - Rate limiting for daemon-reload requests. Default to unset, and any number of daemon-reload - operations can be requested at any time. ReloadLimitIntervalSec= takes a value in seconds - to configure the rate limit window, and ReloadLimitBurst= takes a positive integer to - configure the maximum allowed number of reloads within the configured time window. + Rate limiting for daemon-reload and (since v256) daemon-reexec requests. The setting + applies to both operations, but the rate limits are tracked separately. Defaults to unset, and any + number of operations can be requested at any time. ReloadLimitIntervalSec= takes + a value in seconds to configure the rate limit window, and ReloadLimitBurst= + takes a positive integer to configure the maximum allowed number of operations within the configured + time window. diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index bba466b900..fa85a5e698 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -1599,7 +1599,7 @@ static int method_reload(sd_bus_message *message, void *userdata, sd_bus_error * log_caller(message, m, "Reloading"); /* Check the rate limit after the authorization succeeds, to avoid denial-of-service issues. */ - if (!ratelimit_below(&m->reload_ratelimit)) { + if (!ratelimit_below(&m->reload_reexec_ratelimit)) { log_warning("Reloading request rejected due to rate limit."); return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, @@ -1644,6 +1644,14 @@ static int method_reexecute(sd_bus_message *message, void *userdata, sd_bus_erro /* Write a log message noting the unit or process who requested the Reexecute() */ log_caller(message, m, "Reexecuting"); + /* Check the rate limit after the authorization succeeds, to avoid denial-of-service issues. */ + if (!ratelimit_below(&m->reload_reexec_ratelimit)) { + log_warning("Reexecuting request rejected due to rate limit."); + return sd_bus_error_setf(error, + SD_BUS_ERROR_LIMITS_EXCEEDED, + "Reexecute() request rejected due to rate limit."); + } + /* We don't send a reply back here, the client should * just wait for us disconnecting. */ diff --git a/src/core/main.c b/src/core/main.c index 1aeab10ddb..6f91a15b22 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -810,8 +810,8 @@ static void set_manager_settings(Manager *m) { m->cad_burst_action = arg_cad_burst_action; /* Note that we don't do structured initialization here, otherwise it will reset the rate limit * counter on every daemon-reload. */ - m->reload_ratelimit.interval = arg_reload_limit_interval_sec; - m->reload_ratelimit.burst = arg_reload_limit_burst; + m->reload_reexec_ratelimit.interval = arg_reload_limit_interval_sec; + m->reload_reexec_ratelimit.burst = arg_reload_limit_burst; manager_set_watchdog(m, WATCHDOG_RUNTIME, arg_runtime_watchdog); manager_set_watchdog(m, WATCHDOG_REBOOT, arg_reboot_watchdog); diff --git a/src/core/manager-serialize.c b/src/core/manager-serialize.c index 284f4987a2..884332b324 100644 --- a/src/core/manager-serialize.c +++ b/src/core/manager-serialize.c @@ -156,6 +156,7 @@ int manager_serialize( } (void) serialize_ratelimit(f, "dump-ratelimit", &m->dump_ratelimit); + (void) serialize_ratelimit(f, "reload-reexec-ratelimit", &m->reload_reexec_ratelimit); bus_track_serialize(m->subscribed, f, "subscribed"); @@ -519,6 +520,8 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { (void) varlink_server_deserialize_one(m->varlink_server, val, fds); } else if ((val = startswith(l, "dump-ratelimit="))) deserialize_ratelimit(&m->dump_ratelimit, "dump-ratelimit", val); + else if ((val = startswith(l, "reload-reexec-ratelimit="))) + deserialize_ratelimit(&m->reload_reexec_ratelimit, "reload-reexec-ratelimit", val); else if ((val = startswith(l, "soft-reboots-count="))) { unsigned n; diff --git a/src/core/manager.h b/src/core/manager.h index 0e2531a4a7..9541a5e0b4 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -491,8 +491,8 @@ struct Manager { /* Reference to RestrictFileSystems= BPF program */ struct restrict_fs_bpf *restrict_fs; - /* Allow users to configure a rate limit for Reload() operations */ - RateLimit reload_ratelimit; + /* Allow users to configure a rate limit for Reload()/Reexecute() operations */ + RateLimit reload_reexec_ratelimit; /* Dump*() are slow, so always rate limit them to 10 per 10 minutes */ RateLimit dump_ratelimit; diff --git a/test/units/testsuite-59.sh b/test/units/testsuite-59.sh index 61564dc166..0e044037b8 100755 --- a/test/units/testsuite-59.sh +++ b/test/units/testsuite-59.sh @@ -104,6 +104,14 @@ sleep 10 systemctl daemon-reload +# Same test for reexec, but we wait here +timeout 15 bash -c 'while systemctl daemon-reexec; do true; done' + +# Rate limit should reset after 9s +sleep 10 + +systemctl daemon-reexec + # Let's now test the notify-reload logic cat >/run/notify-reload-test.sh <