]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: add KExecWatchdogSec option
authorLuca Boccassi <luca.boccassi@microsoft.com>
Fri, 19 Jul 2019 10:54:15 +0000 (11:54 +0100)
committerLuca Boccassi <luca.boccassi@microsoft.com>
Tue, 23 Jul 2019 19:29:03 +0000 (20:29 +0100)
Rather than always enabling the shutdown WD on kexec, which might be
dangerous in case the kernel driver and/or the hardware implementation
does not reset the wd on kexec, add a new timer, disabled by default,
to let users optionally enable the shutdown WD on kexec separately
from the runtime and reboot ones. Advise in the documentation to
also use the runtime WD in conjunction with it.

Fixes: a637d0f9ecbe ("core: set shutdown watchdog on kexec too")
man/systemd-system.conf.xml
src/core/dbus-manager.c
src/core/main.c
src/core/manager.h
src/core/system.conf.in
test/fuzz/fuzz-unit-file/directives.service

index 5b80479a0a1c85f8efea6936773381ea1c4d19fc..4dd4bf0ca8b17dc6b34961ad91107db9696e0e3a 100644 (file)
       <varlistentry>
         <term><varname>RuntimeWatchdogSec=</varname></term>
         <term><varname>ShutdownWatchdogSec=</varname></term>
+        <term><varname>KExecWatchdogSec=</varname></term>
 
         <listitem><para>Configure the hardware watchdog at runtime and at reboot. Takes a timeout value in seconds (or
         in other time units if suffixed with <literal>ms</literal>, <literal>min</literal>, <literal>h</literal>,
         phase of system shutdown, configure <varname>JobTimeoutSec=</varname> and <varname>JobTimeoutAction=</varname>
         in the <literal>[Unit]</literal> section of the <filename>shutdown.target</filename> unit. By default
         <varname>RuntimeWatchdogSec=</varname> defaults to 0 (off), and <varname>ShutdownWatchdogSec=</varname> to
-        10min. These settings have no effect if a hardware watchdog is not available.</para></listitem>
+        10min. <varname>KExecWatchdogSec=</varname> may be used to additionally enable the watchdog when kexec
+        is being executed rather than when rebooting. Note that if the kernel does not reset the watchdog on kexec (depending
+        on the specific hardware and/or driver), in this case the watchdog might not get disabled after kexec succeeds
+        and thus the system might get rebooted, unless <varname>RuntimeWatchdogSec=</varname> is also enabled at the same time.
+        For this reason it is recommended to enable <varname>KExecWatchdogSec=</varname> only if
+        <varname>RuntimeWatchdogSec=</varname> is also enabled.
+        These settings have no effect if a hardware watchdog is not available.</para></listitem>
       </varlistentry>
 
       <varlistentry>
index 9fb3ed516a9784c6c01a94fb29d992cec4d61116..e70c1e132a7f1007b91c33ad64bf7d302ed9a99f 100644 (file)
@@ -2410,6 +2410,7 @@ const sd_bus_vtable bus_manager_vtable[] = {
         SD_BUS_PROPERTY("DefaultStandardError", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogUSec", "t", bus_property_get_usec, property_set_runtime_watchdog, offsetof(Manager, runtime_watchdog), 0),
         SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, shutdown_watchdog), 0),
+        SD_BUS_WRITABLE_PROPERTY("KExecWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, kexec_watchdog), 0),
         SD_BUS_WRITABLE_PROPERTY("ServiceWatchdogs", "b", bus_property_get_bool, bus_property_set_bool, offsetof(Manager, service_watchdogs), 0),
         SD_BUS_PROPERTY("ControlGroup", "s", NULL, offsetof(Manager, cgroup_root), 0),
         SD_BUS_PROPERTY("SystemState", "s", property_get_system_state, 0, 0),
index 8de3d4753d6ca1d8d265e2eb25fb99ea5f512ce8..ccfa22c814d1403f0834376ad785f6a79ef841df 100644 (file)
@@ -122,6 +122,7 @@ static usec_t arg_default_start_limit_interval;
 static unsigned arg_default_start_limit_burst;
 static usec_t arg_runtime_watchdog;
 static usec_t arg_shutdown_watchdog;
+static usec_t arg_kexec_watchdog;
 static char *arg_early_core_pattern;
 static char *arg_watchdog_device;
 static char **arg_default_environment;
@@ -555,6 +556,7 @@ static int parse_config_file(void) {
                 { "Manager", "JoinControllers",              config_parse_warn_compat,        DISABLED_CONFIGURATION, NULL              },
                 { "Manager", "RuntimeWatchdogSec",           config_parse_sec,                0, &arg_runtime_watchdog                  },
                 { "Manager", "ShutdownWatchdogSec",          config_parse_sec,                0, &arg_shutdown_watchdog                 },
+                { "Manager", "KExecWatchdogSec",             config_parse_sec,                0, &arg_kexec_watchdog                    },
                 { "Manager", "WatchdogDevice",               config_parse_path,               0, &arg_watchdog_device                   },
                 { "Manager", "CapabilityBoundingSet",        config_parse_capability_set,     0, &arg_capability_bounding_set           },
                 { "Manager", "NoNewPrivileges",              config_parse_bool,               0, &arg_no_new_privs                      },
@@ -674,6 +676,7 @@ static void set_manager_settings(Manager *m) {
         m->service_watchdogs = arg_service_watchdogs;
         m->runtime_watchdog = arg_runtime_watchdog;
         m->shutdown_watchdog = arg_shutdown_watchdog;
+        m->kexec_watchdog = arg_kexec_watchdog;
         m->cad_burst_action = arg_cad_burst_action;
 
         manager_set_show_status(m, arg_show_status);
@@ -1356,6 +1359,7 @@ static int become_shutdown(
         _cleanup_strv_free_ char **env_block = NULL;
         size_t pos = 7;
         int r;
+        usec_t watchdog_timer = 0;
 
         assert(shutdown_verb);
         assert(!command_line[pos]);
@@ -1396,20 +1400,23 @@ static int become_shutdown(
 
         assert(pos < ELEMENTSOF(command_line));
 
-        if (STR_IN_SET(shutdown_verb, "reboot", "kexec") &&
-            arg_shutdown_watchdog > 0 &&
-            arg_shutdown_watchdog != USEC_INFINITY) {
+        if (streq(shutdown_verb, "reboot"))
+                watchdog_timer = arg_shutdown_watchdog;
+        else if (streq(shutdown_verb, "kexec"))
+                watchdog_timer = arg_kexec_watchdog;
+
+        if (watchdog_timer > 0 && watchdog_timer != USEC_INFINITY) {
 
                 char *e;
 
-                /* If we reboot let's set the shutdown
+                /* If we reboot or kexec let's set the shutdown
                  * watchdog and tell the shutdown binary to
                  * repeatedly ping it */
-                r = watchdog_set_timeout(&arg_shutdown_watchdog);
+                r = watchdog_set_timeout(&watchdog_timer);
                 watchdog_close(r < 0);
 
                 /* Tell the binary how often to ping, ignore failure */
-                if (asprintf(&e, "WATCHDOG_USEC="USEC_FMT, arg_shutdown_watchdog) > 0)
+                if (asprintf(&e, "WATCHDOG_USEC="USEC_FMT, watchdog_timer) > 0)
                         (void) strv_consume(&env_block, e);
 
                 if (arg_watchdog_device &&
@@ -2100,6 +2107,7 @@ static void reset_arguments(void) {
         arg_default_start_limit_burst = DEFAULT_START_LIMIT_BURST;
         arg_runtime_watchdog = 0;
         arg_shutdown_watchdog = 10 * USEC_PER_MINUTE;
+        arg_kexec_watchdog = 0;
         arg_early_core_pattern = NULL;
         arg_watchdog_device = NULL;
 
@@ -2639,6 +2647,7 @@ finish:
 
         if (m) {
                 arg_shutdown_watchdog = m->shutdown_watchdog;
+                arg_kexec_watchdog = m->kexec_watchdog;
                 m = manager_free(m);
         }
 
index 9f2b5a0eb0b5c61283ac3edf0720bf9fa652d22e..9600ab5144629564c745b7a4071d1ebf829672e1 100644 (file)
@@ -229,6 +229,7 @@ struct Manager {
 
         usec_t runtime_watchdog;
         usec_t shutdown_watchdog;
+        usec_t kexec_watchdog;
 
         dual_timestamp timestamps[_MANAGER_TIMESTAMP_MAX];
 
index 8617ec20aa8239d6fb1862754a2a223a78e5170c..af6e5d9f62ae237d446de70caf32696b3a15f118 100644 (file)
@@ -27,6 +27,7 @@
 #NUMAMask=
 #RuntimeWatchdogSec=0
 #ShutdownWatchdogSec=10min
+#KExecWatchdogSec=0
 #WatchdogDevice=
 #CapabilityBoundingSet=
 #NoNewPrivileges=no
index 2f59585671f863c3085cf1c88c0d3a27ac657df5..d19610fc55c471c2ce53678276b9196b28466d58 100644 (file)
@@ -703,6 +703,7 @@ LogTarget=
 RuntimeWatchdogSec=
 ShowStatus=
 ShutdownWatchdogSec=
+KExecWatchdogSec=
 SuspendMode=
 SuspendState=
 SystemCallArchitectures=