a19bc6
From be9fad86ae9ab721cd295210962da85706b839e9 Mon Sep 17 00:00:00 2001
a19bc6
From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Nykr=C3=BDn?= <lnykryn@redhat.com>
a19bc6
Date: Fri, 7 Oct 2016 03:08:21 +0200
a19bc6
Subject: [PATCH] core: add possibility to set action for ctrl-alt-del burst
a19bc6
 (#4105)
a19bc6
a19bc6
For some certification, it should not be possible to reboot the machine through ctrl-alt-delete. Currently we suggest our customers to mask the ctrl-alt-delete target, but that is obviously not enough.
a19bc6
a19bc6
Patching the keymaps to disable that is really not a way to go for them, because the settings need to be easily checked by some SCAP tools.
a19bc6
a19bc6
Cherry-picked from: 24dd31c19ede505143833346ff850af942694aa6
a19bc6
Resolves: #1353028
a19bc6
---
a19bc6
 man/systemd-system.conf.xml | 11 ++++++++++
a19bc6
 src/core/main.c             |  5 +++++
a19bc6
 src/core/manager.c          | 51 +++++++++++++++++++++++++++++++++------------
a19bc6
 src/core/manager.h          | 14 ++++++++++++-
a19bc6
 src/core/system.conf        |  1 +
a19bc6
 5 files changed, 68 insertions(+), 14 deletions(-)
a19bc6
a19bc6
diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml
a19bc6
index 39d19bc..236c20d 100644
a19bc6
--- a/man/systemd-system.conf.xml
a19bc6
+++ b/man/systemd-system.conf.xml
a19bc6
@@ -102,6 +102,17 @@
a19bc6
       </varlistentry>
a19bc6
 
a19bc6
       <varlistentry>
a19bc6
+        <term><varname>CtrlAltDelBurstAction=</varname></term>
a19bc6
+
a19bc6
+        <listitem><para>Defines what action will be performed
a19bc6
+        if user presses Ctr-Alt-Delete more than 7 times in 2s.
a19bc6
+        Can be set to <literal>reboot-force</literal>, <literal>poweroff-force</literal>
a19bc6
+        or disabled with <literal>ignore</literal>. Defaults to
a19bc6
+        <literal>reboot-force</literal>.
a19bc6
+        </para></listitem>
a19bc6
+      </varlistentry>
a19bc6
+
a19bc6
+      <varlistentry>
a19bc6
         <term><varname>CPUAffinity=</varname></term>
a19bc6
 
a19bc6
         <listitem><para>Configures the initial CPU affinity for the
a19bc6
diff --git a/src/core/main.c b/src/core/main.c
a19bc6
index c9d8ce4..6ac9c9d 100644
a19bc6
--- a/src/core/main.c
a19bc6
+++ b/src/core/main.c
a19bc6
@@ -115,6 +115,7 @@ static FILE* arg_serialization = NULL;
a19bc6
 static bool arg_default_cpu_accounting = false;
a19bc6
 static bool arg_default_blockio_accounting = false;
a19bc6
 static bool arg_default_memory_accounting = false;
a19bc6
+static CADBurstAction arg_cad_burst_action = CAD_BURST_ACTION_REBOOT;
a19bc6
 
a19bc6
 static void nop_handler(int sig) {}
a19bc6
 
a19bc6
@@ -625,6 +626,8 @@ static int config_parse_join_controllers(const char *unit,
a19bc6
         return 0;
a19bc6
 }
a19bc6
 
a19bc6
+static DEFINE_CONFIG_PARSE_ENUM(config_parse_cad_burst_action, cad_burst_action, CADBurstAction, "Failed to parse service restart specifier");
a19bc6
+
a19bc6
 static int parse_config_file(void) {
a19bc6
 
a19bc6
         const ConfigTableItem items[] = {
a19bc6
@@ -673,6 +676,7 @@ static int parse_config_file(void) {
a19bc6
                 { "Manager", "DefaultCPUAccounting",      config_parse_bool,             0, &arg_default_cpu_accounting            },
a19bc6
                 { "Manager", "DefaultBlockIOAccounting",  config_parse_bool,             0, &arg_default_blockio_accounting        },
a19bc6
                 { "Manager", "DefaultMemoryAccounting",   config_parse_bool,             0, &arg_default_memory_accounting         },
a19bc6
+                { "Manager", "CtrlAltDelBurstAction",     config_parse_cad_burst_action, 0, &arg_cad_burst_action},
a19bc6
                 {}
a19bc6
         };
a19bc6
 
a19bc6
@@ -1690,6 +1694,7 @@ int main(int argc, char *argv[]) {
a19bc6
         m->initrd_timestamp = initrd_timestamp;
a19bc6
         m->security_start_timestamp = security_start_timestamp;
a19bc6
         m->security_finish_timestamp = security_finish_timestamp;
a19bc6
+        m->cad_burst_action = arg_cad_burst_action;
a19bc6
 
a19bc6
         manager_set_default_rlimits(m, arg_default_rlimit);
a19bc6
         manager_environment_add(m, NULL, arg_default_environment);
a19bc6
diff --git a/src/core/manager.c b/src/core/manager.c
a19bc6
index 6d045fd..9048dde 100644
a19bc6
--- a/src/core/manager.c
a19bc6
+++ b/src/core/manager.c
a19bc6
@@ -1859,6 +1859,35 @@ static int manager_start_target(Manager *m, const char *name, JobMode mode) {
a19bc6
         return r;
a19bc6
 }
a19bc6
 
a19bc6
+static void manager_handle_ctrl_alt_del(Manager *m) {
a19bc6
+        /* If the user presses C-A-D more than
a19bc6
+         * 7 times within 2s, we reboot/shutdown immediately,
a19bc6
+         * unless it was disabled in system.conf */
a19bc6
+
a19bc6
+        if (ratelimit_test(&m->ctrl_alt_del_ratelimit) || m->cad_burst_action == CAD_BURST_ACTION_IGNORE)
a19bc6
+                manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE_IRREVERSIBLY);
a19bc6
+        else {
a19bc6
+                switch (m->cad_burst_action) {
a19bc6
+
a19bc6
+                case CAD_BURST_ACTION_REBOOT:
a19bc6
+                        m->exit_code = MANAGER_REBOOT;
a19bc6
+                        break;
a19bc6
+
a19bc6
+                case CAD_BURST_ACTION_POWEROFF:
a19bc6
+                        m->exit_code = MANAGER_POWEROFF;
a19bc6
+                        break;
a19bc6
+
a19bc6
+                default:
a19bc6
+                        assert_not_reached("Unknown action.");
a19bc6
+                }
a19bc6
+
a19bc6
+                log_notice("Ctrl-Alt-Del was pressed more than 7 times within 2s, performing immediate %s.",
a19bc6
+                                cad_burst_action_to_string(m->cad_burst_action));
a19bc6
+                status_printf(NULL, true, false, "Ctrl-Alt-Del was pressed more than 7 times within 2s, performing immediate %s.",
a19bc6
+                                cad_burst_action_to_string(m->cad_burst_action));
a19bc6
+        }
a19bc6
+}
a19bc6
+
a19bc6
 static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
a19bc6
         Manager *m = userdata;
a19bc6
         ssize_t n;
a19bc6
@@ -1909,19 +1938,7 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t
a19bc6
 
a19bc6
                 case SIGINT:
a19bc6
                         if (m->running_as == SYSTEMD_SYSTEM) {
a19bc6
-
a19bc6
-                                /* If the user presses C-A-D more than
a19bc6
-                                 * 7 times within 2s, we reboot
a19bc6
-                                 * immediately. */
a19bc6
-
a19bc6
-                                if (ratelimit_test(&m->ctrl_alt_del_ratelimit))
a19bc6
-                                        manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE_IRREVERSIBLY);
a19bc6
-                                else {
a19bc6
-                                        log_notice("Ctrl-Alt-Del was pressed more than 7 times within 2s, rebooting immediately.");
a19bc6
-                                        status_printf(NULL, true, false, "Ctrl-Alt-Del was pressed more than 7 times within 2s, rebooting immediately.");
a19bc6
-                                        m->exit_code = MANAGER_REBOOT;
a19bc6
-                                }
a19bc6
-
a19bc6
+                                manager_handle_ctrl_alt_del(m);
a19bc6
                                 break;
a19bc6
                         }
a19bc6
 
a19bc6
@@ -3319,3 +3336,11 @@ static const char *const manager_state_table[_MANAGER_STATE_MAX] = {
a19bc6
 };
a19bc6
 
a19bc6
 DEFINE_STRING_TABLE_LOOKUP(manager_state, ManagerState);
a19bc6
+
a19bc6
+static const char *const cad_burst_action_table[_CAD_BURST_ACTION_MAX] = {
a19bc6
+        [CAD_BURST_ACTION_IGNORE] = "ignore",
a19bc6
+        [CAD_BURST_ACTION_REBOOT] = "reboot-force",
a19bc6
+        [CAD_BURST_ACTION_POWEROFF] = "poweroff-force",
a19bc6
+};
a19bc6
+
a19bc6
+DEFINE_STRING_TABLE_LOOKUP(cad_burst_action, CADBurstAction);
a19bc6
diff --git a/src/core/manager.h b/src/core/manager.h
a19bc6
index 3e855db..42be1fc 100644
a19bc6
--- a/src/core/manager.h
a19bc6
+++ b/src/core/manager.h
a19bc6
@@ -64,6 +64,14 @@ typedef enum ManagerExitCode {
a19bc6
         _MANAGER_EXIT_CODE_INVALID = -1
a19bc6
 } ManagerExitCode;
a19bc6
 
a19bc6
+typedef enum CADBurstAction {
a19bc6
+        CAD_BURST_ACTION_IGNORE,
a19bc6
+        CAD_BURST_ACTION_REBOOT,
a19bc6
+        CAD_BURST_ACTION_POWEROFF,
a19bc6
+        _CAD_BURST_ACTION_MAX,
a19bc6
+        _CAD_BURST_ACTION_INVALID = -1
a19bc6
+} CADBurstAction;
a19bc6
+
a19bc6
 typedef enum StatusType {
a19bc6
         STATUS_TYPE_EPHEMERAL,
a19bc6
         STATUS_TYPE_NORMAL,
a19bc6
@@ -300,8 +308,9 @@ struct Manager {
a19bc6
         /* Used for processing polkit authorization responses */
a19bc6
         Hashmap *polkit_registry;
a19bc6
 
a19bc6
-        /* When the user hits C-A-D more than 7 times per 2s, reboot immediately... */
a19bc6
+        /* When the user hits C-A-D more than 7 times per 2s, do something immediately... */
a19bc6
         RateLimit ctrl_alt_del_ratelimit;
a19bc6
+        CADBurstAction cad_burst_action;
a19bc6
 };
a19bc6
 
a19bc6
 int manager_new(SystemdRunningAs running_as, bool test_run, Manager **m);
a19bc6
@@ -372,3 +381,6 @@ ManagerState manager_state(Manager *m);
a19bc6
 
a19bc6
 const char *manager_state_to_string(ManagerState m) _const_;
a19bc6
 ManagerState manager_state_from_string(const char *s) _pure_;
a19bc6
+
a19bc6
+const char *cad_burst_action_to_string(CADBurstAction a) _const_;
a19bc6
+CADBurstAction cad_burst_action_from_string(const char *s) _pure_;
a19bc6
diff --git a/src/core/system.conf b/src/core/system.conf
a19bc6
index 2316090..a11f599 100644
a19bc6
--- a/src/core/system.conf
a19bc6
+++ b/src/core/system.conf
a19bc6
@@ -20,6 +20,7 @@
a19bc6
 #CrashShell=no
a19bc6
 #ShowStatus=yes
a19bc6
 #CrashChVT=1
a19bc6
+#CtrlAltDelBurstAction=reboot-force
a19bc6
 #CPUAffinity=1 2
a19bc6
 #JoinControllers=cpu,cpuacct net_cls,net_prio
a19bc6
 #RuntimeWatchdogSec=0