summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukáš Nykrýn <lnykryn@redhat.com>2016-10-07 03:08:21 +0200
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2016-10-06 21:08:21 -0400
commit24dd31c19ede505143833346ff850af942694aa6 (patch)
tree77ec6c98761c378793d96afe04bdf7443b41be5c
parent36264e0de596d9b0264ae08b53832495a78c779c (diff)
core: add possibility to set action for ctrl-alt-del burst (#4105)
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. 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.
-rw-r--r--man/systemd-system.conf.xml11
-rw-r--r--src/core/main.c5
-rw-r--r--src/core/manager.c51
-rw-r--r--src/core/manager.h14
-rw-r--r--src/core/system.conf1
5 files changed, 68 insertions, 14 deletions
diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml
index 1bb40fd234..a268397d09 100644
--- a/man/systemd-system.conf.xml
+++ b/man/systemd-system.conf.xml
@@ -106,6 +106,17 @@
</varlistentry>
<varlistentry>
+ <term><varname>CtrlAltDelBurstAction=</varname></term>
+
+ <listitem><para>Defines what action will be performed
+ if user presses Ctr-Alt-Delete more than 7 times in 2s.
+ Can be set to <literal>reboot-force</literal>, <literal>poweroff-force</literal>
+ or disabled with <literal>ignore</literal>. Defaults to
+ <literal>reboot-force</literal>.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>CPUAffinity=</varname></term>
<listitem><para>Configures the initial CPU affinity for the
diff --git a/src/core/main.c b/src/core/main.c
index be0cb0b6d1..6fe440277e 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -131,6 +131,7 @@ static bool arg_default_memory_accounting = false;
static bool arg_default_tasks_accounting = true;
static uint64_t arg_default_tasks_max = UINT64_MAX;
static sd_id128_t arg_machine_id = {};
+static CADBurstAction arg_cad_burst_action = CAD_BURST_ACTION_REBOOT;
noreturn static void freeze_or_reboot(void) {
@@ -648,6 +649,8 @@ static int config_parse_join_controllers(const char *unit,
return 0;
}
+static DEFINE_CONFIG_PARSE_ENUM(config_parse_cad_burst_action, cad_burst_action, CADBurstAction, "Failed to parse service restart specifier");
+
static int parse_config_file(void) {
const ConfigTableItem items[] = {
@@ -702,6 +705,7 @@ static int parse_config_file(void) {
{ "Manager", "DefaultMemoryAccounting", config_parse_bool, 0, &arg_default_memory_accounting },
{ "Manager", "DefaultTasksAccounting", config_parse_bool, 0, &arg_default_tasks_accounting },
{ "Manager", "DefaultTasksMax", config_parse_tasks_max, 0, &arg_default_tasks_max },
+ { "Manager", "CtrlAltDelBurstAction", config_parse_cad_burst_action, 0, &arg_cad_burst_action},
{}
};
@@ -1794,6 +1798,7 @@ int main(int argc, char *argv[]) {
m->initrd_timestamp = initrd_timestamp;
m->security_start_timestamp = security_start_timestamp;
m->security_finish_timestamp = security_finish_timestamp;
+ m->cad_burst_action = arg_cad_burst_action;
manager_set_defaults(m);
manager_set_show_status(m, arg_show_status);
diff --git a/src/core/manager.c b/src/core/manager.c
index dd0d1fa984..5253cb3712 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -1894,6 +1894,35 @@ static int manager_start_target(Manager *m, const char *name, JobMode mode) {
return r;
}
+static void manager_handle_ctrl_alt_del(Manager *m) {
+ /* If the user presses C-A-D more than
+ * 7 times within 2s, we reboot/shutdown immediately,
+ * unless it was disabled in system.conf */
+
+ if (ratelimit_test(&m->ctrl_alt_del_ratelimit) || m->cad_burst_action == CAD_BURST_ACTION_IGNORE)
+ manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE_IRREVERSIBLY);
+ else {
+ switch (m->cad_burst_action) {
+
+ case CAD_BURST_ACTION_REBOOT:
+ m->exit_code = MANAGER_REBOOT;
+ break;
+
+ case CAD_BURST_ACTION_POWEROFF:
+ m->exit_code = MANAGER_POWEROFF;
+ break;
+
+ default:
+ assert_not_reached("Unknown action.");
+ }
+
+ log_notice("Ctrl-Alt-Del was pressed more than 7 times within 2s, performing immediate %s.",
+ cad_burst_action_to_string(m->cad_burst_action));
+ status_printf(NULL, true, false, "Ctrl-Alt-Del was pressed more than 7 times within 2s, performing immediate %s.",
+ cad_burst_action_to_string(m->cad_burst_action));
+ }
+}
+
static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
Manager *m = userdata;
ssize_t n;
@@ -1945,19 +1974,7 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t
case SIGINT:
if (MANAGER_IS_SYSTEM(m)) {
-
- /* If the user presses C-A-D more than
- * 7 times within 2s, we reboot
- * immediately. */
-
- if (ratelimit_test(&m->ctrl_alt_del_ratelimit))
- manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE_IRREVERSIBLY);
- else {
- log_notice("Ctrl-Alt-Del was pressed more than 7 times within 2s, rebooting immediately.");
- status_printf(NULL, true, false, "Ctrl-Alt-Del was pressed more than 7 times within 2s, rebooting immediately.");
- m->exit_code = MANAGER_REBOOT;
- }
-
+ manager_handle_ctrl_alt_del(m);
break;
}
@@ -3544,3 +3561,11 @@ static const char *const manager_state_table[_MANAGER_STATE_MAX] = {
};
DEFINE_STRING_TABLE_LOOKUP(manager_state, ManagerState);
+
+static const char *const cad_burst_action_table[_CAD_BURST_ACTION_MAX] = {
+ [CAD_BURST_ACTION_IGNORE] = "ignore",
+ [CAD_BURST_ACTION_REBOOT] = "reboot-force",
+ [CAD_BURST_ACTION_POWEROFF] = "poweroff-force",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(cad_burst_action, CADBurstAction);
diff --git a/src/core/manager.h b/src/core/manager.h
index a592f1cb94..495440b446 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -62,6 +62,14 @@ typedef enum ManagerExitCode {
_MANAGER_EXIT_CODE_INVALID = -1
} ManagerExitCode;
+typedef enum CADBurstAction {
+ CAD_BURST_ACTION_IGNORE,
+ CAD_BURST_ACTION_REBOOT,
+ CAD_BURST_ACTION_POWEROFF,
+ _CAD_BURST_ACTION_MAX,
+ _CAD_BURST_ACTION_INVALID = -1
+} CADBurstAction;
+
typedef enum StatusType {
STATUS_TYPE_EPHEMERAL,
STATUS_TYPE_NORMAL,
@@ -304,8 +312,9 @@ struct Manager {
Hashmap *uid_refs;
Hashmap *gid_refs;
- /* When the user hits C-A-D more than 7 times per 2s, reboot immediately... */
+ /* When the user hits C-A-D more than 7 times per 2s, do something immediately... */
RateLimit ctrl_alt_del_ratelimit;
+ CADBurstAction cad_burst_action;
const char *unit_log_field;
const char *unit_log_format_string;
@@ -398,3 +407,6 @@ void manager_deserialize_gid_refs_one(Manager *m, const char *value);
const char *manager_state_to_string(ManagerState m) _const_;
ManagerState manager_state_from_string(const char *s) _pure_;
+
+const char *cad_burst_action_to_string(CADBurstAction a) _const_;
+CADBurstAction cad_burst_action_from_string(const char *s) _pure_;
diff --git a/src/core/system.conf b/src/core/system.conf
index c6bb050aac..746572b7ff 100644
--- a/src/core/system.conf
+++ b/src/core/system.conf
@@ -21,6 +21,7 @@
#CrashChangeVT=no
#CrashShell=no
#CrashReboot=no
+#CtrlAltDelBurstAction=reboot-force
#CPUAffinity=1 2
#JoinControllers=cpu,cpuacct net_cls,net_prio
#RuntimeWatchdogSec=0