From: Luca Boccassi Date: Fri, 29 Mar 2024 01:29:07 +0000 (+0000) Subject: core: apply ReloadLimit to reexec too X-Git-Tag: v256-rc1~355^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8312b17a2979758a5e90d67786736bd9ddd4b856;p=thirdparty%2Fsystemd.git core: apply ReloadLimit to reexec too Same reason as the reload, reexec is disruptive and it requires the same privileges, so if somebody wants to limit reloads, they'll also want to limit reexecs, so use the same setting. --- diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml index e6611d04e7a..88f13d05b61 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 bba466b9008..fa85a5e6980 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 1aeab10ddbc..6f91a15b22b 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 d3382084cbf..884332b3249 100644 --- a/src/core/manager-serialize.c +++ b/src/core/manager-serialize.c @@ -156,7 +156,7 @@ int manager_serialize( } (void) serialize_ratelimit(f, "dump-ratelimit", &m->dump_ratelimit); - (void) serialize_ratelimit(f, "reload-ratelimit", &m->reload_ratelimit); + (void) serialize_ratelimit(f, "reload-reexec-ratelimit", &m->reload_reexec_ratelimit); bus_track_serialize(m->subscribed, f, "subscribed"); @@ -520,8 +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-ratelimit="))) - deserialize_ratelimit(&m->reload_ratelimit, "reload-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 0e2531a4a7d..9541a5e0b46 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 61564dc1664..0e044037b85 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 <