]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/emergency-action.c
Merge pull request #11823 from keszybz/more-fuzz-coverage
[thirdparty/systemd.git] / src / core / emergency-action.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
2928b0a8
LP
2
3#include <sys/reboot.h>
2928b0a8 4
2928b0a8 5#include "bus-error.h"
8b43440b 6#include "bus-util.h"
87a47f99 7#include "emergency-action.h"
c52a937b 8#include "raw-reboot.h"
e3631d1c 9#include "reboot-util.h"
8b43440b
LP
10#include "special.h"
11#include "string-table.h"
288a74cc 12#include "terminal-util.h"
a400bd8c 13#include "virt.h"
2928b0a8 14
c7adcb1a
ZJS
15static void log_and_status(Manager *m, bool warn, const char *message, const char *reason) {
16 log_full(warn ? LOG_WARNING : LOG_DEBUG, "%s: %s", message, reason);
17 if (warn)
18 manager_status_printf(m, STATUS_TYPE_EMERGENCY,
19 ANSI_HIGHLIGHT_RED " !! " ANSI_NORMAL,
20 "%s: %s", message, reason);
ebc5788e
ZJS
21}
22
87a47f99 23int emergency_action(
2928b0a8 24 Manager *m,
87a47f99 25 EmergencyAction action,
1710d4be 26 EmergencyActionFlags options,
87a47f99 27 const char *reboot_arg,
7af67e9a 28 int exit_status,
87a47f99 29 const char *reason) {
2928b0a8 30
2928b0a8
LP
31 assert(m);
32 assert(action >= 0);
87a47f99 33 assert(action < _EMERGENCY_ACTION_MAX);
2928b0a8 34
87a47f99 35 if (action == EMERGENCY_ACTION_NONE)
f07756bf 36 return -ECANCELED;
2928b0a8 37
1710d4be 38 if (FLAGS_SET(options, EMERGENCY_ACTION_IS_WATCHDOG) && !m->service_watchdogs) {
2a12e32e
JK
39 log_warning("Watchdog disabled! Not acting on: %s", reason);
40 return -ECANCELED;
41 }
42
c7adcb1a
ZJS
43 bool warn = FLAGS_SET(options, EMERGENCY_ACTION_WARN);
44
f07756bf 45 switch (action) {
2928b0a8 46
87a47f99 47 case EMERGENCY_ACTION_REBOOT:
c7adcb1a 48 log_and_status(m, warn, "Rebooting", reason);
2928b0a8 49
27c06cb5
LP
50 (void) update_reboot_parameter_and_warn(reboot_arg);
51 (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL);
2928b0a8
LP
52
53 break;
2928b0a8 54
87a47f99 55 case EMERGENCY_ACTION_REBOOT_FORCE:
c7adcb1a 56 log_and_status(m, warn, "Forcibly rebooting", reason);
ebc5788e 57
27c06cb5 58 (void) update_reboot_parameter_and_warn(reboot_arg);
af41e508 59 m->objective = MANAGER_REBOOT;
27c06cb5 60
2928b0a8
LP
61 break;
62
87a47f99 63 case EMERGENCY_ACTION_REBOOT_IMMEDIATE:
c7adcb1a 64 log_and_status(m, warn, "Rebooting immediately", reason);
2928b0a8
LP
65
66 sync();
67
27c06cb5 68 if (!isempty(reboot_arg)) {
2928b0a8 69 log_info("Rebooting with argument '%s'.", reboot_arg);
c52a937b 70 (void) raw_reboot(LINUX_REBOOT_CMD_RESTART2, reboot_arg);
27c06cb5 71 log_warning_errno(errno, "Failed to reboot with parameter, retrying without: %m");
2928b0a8
LP
72 }
73
74 log_info("Rebooting.");
118cf952 75 (void) reboot(RB_AUTOBOOT);
2928b0a8
LP
76 break;
77
54fcb619 78 case EMERGENCY_ACTION_EXIT:
7af67e9a
LP
79
80 if (exit_status >= 0)
81 m->return_value = exit_status;
82
a400bd8c 83 if (MANAGER_IS_USER(m) || detect_container() > 0) {
c7adcb1a 84 log_and_status(m, warn, "Exiting", reason);
a400bd8c
ZJS
85 (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_EXIT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL);
86 break;
87 }
54fcb619 88
a400bd8c
ZJS
89 log_notice("Doing \"poweroff\" action instead of an \"exit\" emergency action.");
90 _fallthrough_;
54fcb619 91
87a47f99 92 case EMERGENCY_ACTION_POWEROFF:
c7adcb1a 93 log_and_status(m, warn, "Powering off", reason);
27c06cb5 94 (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_POWEROFF_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL);
f07756bf 95 break;
f07756bf 96
54fcb619 97 case EMERGENCY_ACTION_EXIT_FORCE:
7af67e9a
LP
98
99 if (exit_status >= 0)
100 m->return_value = exit_status;
101
a400bd8c 102 if (MANAGER_IS_USER(m) || detect_container() > 0) {
c7adcb1a 103 log_and_status(m, warn, "Exiting immediately", reason);
a400bd8c
ZJS
104 m->objective = MANAGER_EXIT;
105 break;
106 }
54fcb619 107
a400bd8c
ZJS
108 log_notice("Doing \"poweroff-force\" action instead of an \"exit-force\" emergency action.");
109 _fallthrough_;
54fcb619 110
87a47f99 111 case EMERGENCY_ACTION_POWEROFF_FORCE:
c7adcb1a 112 log_and_status(m, warn, "Forcibly powering off", reason);
af41e508 113 m->objective = MANAGER_POWEROFF;
f07756bf
LP
114 break;
115
87a47f99 116 case EMERGENCY_ACTION_POWEROFF_IMMEDIATE:
c7adcb1a 117 log_and_status(m, warn, "Powering off immediately", reason);
f07756bf
LP
118
119 sync();
120
121 log_info("Powering off.");
118cf952 122 (void) reboot(RB_POWER_OFF);
f07756bf
LP
123 break;
124
2928b0a8 125 default:
87a47f99 126 assert_not_reached("Unknown emergency action");
2928b0a8
LP
127 }
128
129 return -ECANCELED;
130}
131
87a47f99
LN
132static const char* const emergency_action_table[_EMERGENCY_ACTION_MAX] = {
133 [EMERGENCY_ACTION_NONE] = "none",
134 [EMERGENCY_ACTION_REBOOT] = "reboot",
135 [EMERGENCY_ACTION_REBOOT_FORCE] = "reboot-force",
136 [EMERGENCY_ACTION_REBOOT_IMMEDIATE] = "reboot-immediate",
137 [EMERGENCY_ACTION_POWEROFF] = "poweroff",
138 [EMERGENCY_ACTION_POWEROFF_FORCE] = "poweroff-force",
54fcb619
ZJS
139 [EMERGENCY_ACTION_POWEROFF_IMMEDIATE] = "poweroff-immediate",
140 [EMERGENCY_ACTION_EXIT] = "exit",
141 [EMERGENCY_ACTION_EXIT_FORCE] = "exit-force",
2928b0a8 142};
87a47f99 143DEFINE_STRING_TABLE_LOOKUP(emergency_action, EmergencyAction);
54fcb619
ZJS
144
145int parse_emergency_action(
146 const char *value,
147 bool system,
148 EmergencyAction *ret) {
149
150 EmergencyAction x;
151
152 x = emergency_action_from_string(value);
153 if (x < 0)
154 return -EINVAL;
155
a400bd8c 156 if (!system && x != EMERGENCY_ACTION_NONE && x < _EMERGENCY_ACTION_FIRST_USER_ACTION)
54fcb619
ZJS
157 return -EOPNOTSUPP;
158
159 *ret = x;
160 return 0;
161}