1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <unistd.h>
4
5 #include "sd-login.h"
6
7 #include "bus-error.h"
8 #include "bus-locator.h"
9 #include "login-util.h"
10 #include "process-util.h"
11 #include "systemctl-logind.h"
12 #include "systemctl-start-unit.h"
13 #include "systemctl-util.h"
14 #include "systemctl.h"
15 #include "terminal-util.h"
16 #include "user-util.h"
17
logind_set_wall_message(void)18 int logind_set_wall_message(void) {
19 #if ENABLE_LOGIND
20 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
21 sd_bus *bus;
22 _cleanup_free_ char *m = NULL;
23 int r;
24
25 r = acquire_bus(BUS_FULL, &bus);
26 if (r < 0)
27 return r;
28
29 m = strv_join(arg_wall, " ");
30 if (!m)
31 return log_oom();
32
33 log_debug("%s wall message \"%s\".", arg_dry_run ? "Would set" : "Setting", m);
34 if (arg_dry_run)
35 return 0;
36
37 r = bus_call_method(bus, bus_login_mgr, "SetWallMessage", &error, NULL, "sb", m, !arg_no_wall);
38 if (r < 0)
39 return log_warning_errno(r, "Failed to set wall message, ignoring: %s", bus_error_message(&error, r));
40 #endif
41 return 0;
42 }
43
44 /* Ask systemd-logind, which might grant access to unprivileged users through polkit */
logind_reboot(enum action a)45 int logind_reboot(enum action a) {
46 #if ENABLE_LOGIND
47 static const struct {
48 const char *method;
49 const char *description;
50 } actions[_ACTION_MAX] = {
51 [ACTION_POWEROFF] = { "PowerOff", "power off system" },
52 [ACTION_REBOOT] = { "Reboot", "reboot system" },
53 [ACTION_KEXEC] = { "Reboot", "kexec reboot system" },
54 [ACTION_HALT] = { "Halt", "halt system" },
55 [ACTION_SUSPEND] = { "Suspend", "suspend system" },
56 [ACTION_HIBERNATE] = { "Hibernate", "hibernate system" },
57 [ACTION_HYBRID_SLEEP] = { "HybridSleep", "put system into hybrid sleep" },
58 [ACTION_SUSPEND_THEN_HIBERNATE] = { "SuspendThenHibernate", "suspend system, hibernate later" },
59 };
60
61 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
62 const char *method_with_flags;
63 uint64_t flags = 0;
64 sd_bus *bus;
65 int r;
66
67 if (a < 0 || a >= _ACTION_MAX || !actions[a].method)
68 return -EINVAL;
69
70 r = acquire_bus(BUS_FULL, &bus);
71 if (r < 0)
72 return r;
73
74 polkit_agent_open_maybe();
75 (void) logind_set_wall_message();
76
77 log_debug("%s org.freedesktop.login1.Manager %s dbus call.", arg_dry_run ? "Would execute" : "Executing", actions[a].method);
78
79 if (arg_dry_run)
80 return 0;
81
82 SET_FLAG(flags, SD_LOGIND_ROOT_CHECK_INHIBITORS, arg_check_inhibitors > 0);
83 SET_FLAG(flags, SD_LOGIND_REBOOT_VIA_KEXEC, a == ACTION_KEXEC);
84
85 method_with_flags = strjoina(actions[a].method, "WithFlags");
86
87 r = bus_call_method(bus, bus_login_mgr, method_with_flags, &error, NULL, "t", flags);
88 if (r >= 0)
89 return 0;
90 if (!sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD))
91 return log_error_errno(r, "Failed to %s via logind: %s", actions[a].description, bus_error_message(&error, r));
92
93 /* Fallback to original methods in case there is older version of systemd-logind */
94 log_debug("Method %s not available: %s. Falling back to %s", method_with_flags, bus_error_message(&error, r), actions[a].method);
95 sd_bus_error_free(&error);
96
97 r = bus_call_method(bus, bus_login_mgr, actions[a].method, &error, NULL, "b", arg_ask_password);
98 if (r < 0)
99 return log_error_errno(r, "Failed to %s via logind: %s", actions[a].description, bus_error_message(&error, r));
100
101 return 0;
102 #else
103 return -ENOSYS;
104 #endif
105 }
106
logind_check_inhibitors(enum action a)107 int logind_check_inhibitors(enum action a) {
108 #if ENABLE_LOGIND
109 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
110 _cleanup_strv_free_ char **sessions = NULL;
111 const char *what, *who, *why, *mode;
112 uint32_t uid, pid;
113 sd_bus *bus;
114 unsigned c = 0;
115 int r;
116
117 if (arg_check_inhibitors == 0 || arg_force > 0)
118 return 0;
119
120 if (arg_when > 0)
121 return 0;
122
123 if (arg_check_inhibitors < 0) {
124 if (geteuid() == 0)
125 return 0;
126
127 if (!on_tty())
128 return 0;
129 }
130
131 if (arg_transport != BUS_TRANSPORT_LOCAL)
132 return 0;
133
134 r = acquire_bus(BUS_FULL, &bus);
135 if (r < 0)
136 return r;
137
138 r = bus_call_method(bus, bus_login_mgr, "ListInhibitors", NULL, &reply, NULL);
139 if (r < 0)
140 /* If logind is not around, then there are no inhibitors... */
141 return 0;
142
143 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
144 if (r < 0)
145 return bus_log_parse_error(r);
146
147 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
148 _cleanup_free_ char *comm = NULL, *user = NULL;
149 _cleanup_strv_free_ char **sv = NULL;
150
151 if (!streq(mode, "block"))
152 continue;
153
154 sv = strv_split(what, ":");
155 if (!sv)
156 return log_oom();
157
158 if (!pid_is_valid((pid_t) pid))
159 return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Invalid PID "PID_FMT".", (pid_t) pid);
160
161 if (!strv_contains(sv,
162 IN_SET(a,
163 ACTION_HALT,
164 ACTION_POWEROFF,
165 ACTION_REBOOT,
166 ACTION_KEXEC) ? "shutdown" : "sleep"))
167 continue;
168
169 (void) get_process_comm(pid, &comm);
170 user = uid_to_name(uid);
171
172 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
173 who, (pid_t) pid, strna(comm), strna(user), why);
174
175 c++;
176 }
177 if (r < 0)
178 return bus_log_parse_error(r);
179
180 r = sd_bus_message_exit_container(reply);
181 if (r < 0)
182 return bus_log_parse_error(r);
183
184 /* Check for current sessions */
185 sd_get_sessions(&sessions);
186 STRV_FOREACH(s, sessions) {
187 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
188
189 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
190 continue;
191
192 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
193 continue;
194
195 if (sd_session_get_type(*s, &type) < 0 || !STR_IN_SET(type, "x11", "wayland", "tty", "mir"))
196 continue;
197
198 sd_session_get_tty(*s, &tty);
199 sd_session_get_seat(*s, &seat);
200 sd_session_get_service(*s, &service);
201 user = uid_to_name(uid);
202
203 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
204 c++;
205 }
206
207 if (c <= 0)
208 return 0;
209
210 return log_error_errno(SYNTHETIC_ERRNO(EPERM),
211 "Please retry operation after closing inhibitors and logging out other users.\n"
212 "Alternatively, ignore inhibitors and users with 'systemctl %s -i'.",
213 action_table[a].verb);
214 #else
215 return 0;
216 #endif
217 }
218
prepare_firmware_setup(void)219 int prepare_firmware_setup(void) {
220
221 if (!arg_firmware_setup)
222 return 0;
223
224 #if ENABLE_LOGIND
225 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
226 sd_bus *bus;
227 int r;
228
229 r = acquire_bus(BUS_FULL, &bus);
230 if (r < 0)
231 return r;
232
233 r = bus_call_method(bus, bus_login_mgr, "SetRebootToFirmwareSetup", &error, NULL, "b", true);
234 if (r < 0)
235 return log_error_errno(r, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error, r));
236
237 return 0;
238 #else
239 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),
240 "Booting into firmware setup not supported.");
241 #endif
242 }
243
prepare_boot_loader_menu(void)244 int prepare_boot_loader_menu(void) {
245
246 if (arg_boot_loader_menu == USEC_INFINITY)
247 return 0;
248
249 #if ENABLE_LOGIND
250 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
251 sd_bus *bus;
252 int r;
253
254 r = acquire_bus(BUS_FULL, &bus);
255 if (r < 0)
256 return r;
257
258 r = bus_call_method(bus, bus_login_mgr, "SetRebootToBootLoaderMenu", &error, NULL, "t", arg_boot_loader_menu);
259 if (r < 0)
260 return log_error_errno(r, "Cannot indicate to boot loader to enter boot loader entry menu: %s", bus_error_message(&error, r));
261
262 return 0;
263 #else
264 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),
265 "Booting into boot loader menu not supported.");
266 #endif
267 }
268
prepare_boot_loader_entry(void)269 int prepare_boot_loader_entry(void) {
270
271 if (!arg_boot_loader_entry)
272 return 0;
273
274 #if ENABLE_LOGIND
275 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
276 sd_bus *bus;
277 int r;
278
279 r = acquire_bus(BUS_FULL, &bus);
280 if (r < 0)
281 return r;
282
283 r = bus_call_method(bus, bus_login_mgr, "SetRebootToBootLoaderEntry", &error, NULL, "s", arg_boot_loader_entry);
284 if (r < 0)
285 return log_error_errno(r, "Cannot set boot into loader entry '%s': %s", arg_boot_loader_entry, bus_error_message(&error, r));
286
287 return 0;
288 #else
289 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),
290 "Booting into boot loader entry not supported.");
291 #endif
292 }
293
logind_schedule_shutdown(void)294 int logind_schedule_shutdown(void) {
295
296 #if ENABLE_LOGIND
297 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
298 const char *action;
299 sd_bus *bus;
300 int r;
301
302 r = acquire_bus(BUS_FULL, &bus);
303 if (r < 0)
304 return r;
305
306 action = action_table[arg_action].verb;
307 if (!action)
308 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Scheduling not supported for this action.");
309
310 if (arg_dry_run)
311 action = strjoina("dry-", action);
312
313 (void) logind_set_wall_message();
314
315 r = bus_call_method(bus, bus_login_mgr, "ScheduleShutdown", &error, NULL, "st", action, arg_when);
316 if (r < 0)
317 return log_warning_errno(r, "Failed to schedule shutdown: %s", bus_error_message(&error, r));
318
319 if (!arg_quiet)
320 logind_show_shutdown();
321
322 return 0;
323 #else
324 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),
325 "Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
326 #endif
327 }
328
logind_cancel_shutdown(void)329 int logind_cancel_shutdown(void) {
330 #if ENABLE_LOGIND
331 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
332 sd_bus *bus;
333 int r;
334
335 r = acquire_bus(BUS_FULL, &bus);
336 if (r < 0)
337 return r;
338
339 (void) logind_set_wall_message();
340
341 r = bus_call_method(bus, bus_login_mgr, "CancelScheduledShutdown", &error, NULL, NULL);
342 if (r < 0)
343 return log_warning_errno(r, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error, r));
344
345 return 0;
346 #else
347 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),
348 "Not compiled with logind support, cannot cancel scheduled shutdowns.");
349 #endif
350 }
351
logind_show_shutdown(void)352 int logind_show_shutdown(void) {
353 #if ENABLE_LOGIND
354 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
355 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
356 sd_bus *bus;
357 const char *action = NULL;
358 uint64_t elapse;
359 int r;
360
361 r = acquire_bus(BUS_FULL, &bus);
362 if (r < 0)
363 return r;
364
365 r = bus_get_property(bus, bus_login_mgr, "ScheduledShutdown", &error, &reply, "(st)");
366 if (r < 0)
367 return log_error_errno(r, "Failed to query scheduled shutdown: %s", bus_error_message(&error, r));
368
369 r = sd_bus_message_read(reply, "(st)", &action, &elapse);
370 if (r < 0)
371 return r;
372
373 if (isempty(action))
374 return log_error_errno(SYNTHETIC_ERRNO(ENODATA), "No scheduled shutdown.");
375
376 if (STR_IN_SET(action, "halt", "poweroff", "exit"))
377 action = "Shutdown";
378 else if (streq(action, "kexec"))
379 action = "Reboot via kexec";
380 else if (streq(action, "reboot"))
381 action = "Reboot";
382
383 /* If we don't recognize the action string, we'll show it as-is */
384
385 log_info("%s scheduled for %s, use 'shutdown -c' to cancel.",
386 action,
387 FORMAT_TIMESTAMP_STYLE(elapse, arg_timestamp_style));
388
389 return 0;
390 #else
391 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),
392 "Not compiled with logind support, cannot show scheduled shutdowns.");
393 #endif
394 }
395
help_boot_loader_entry(void)396 int help_boot_loader_entry(void) {
397 #if ENABLE_LOGIND
398 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
399 _cleanup_strv_free_ char **l = NULL;
400 sd_bus *bus;
401 int r;
402
403 r = acquire_bus(BUS_FULL, &bus);
404 if (r < 0)
405 return r;
406
407 r = bus_get_property_strv(bus, bus_login_mgr, "BootLoaderEntries", &error, &l);
408 if (r < 0)
409 return log_error_errno(r, "Failed to enumerate boot loader entries: %s", bus_error_message(&error, r));
410
411 if (strv_isempty(l))
412 return log_error_errno(SYNTHETIC_ERRNO(ENODATA), "No boot loader entries discovered.");
413
414 STRV_FOREACH(i, l)
415 puts(*i);
416
417 return 0;
418 #else
419 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),
420 "Not compiled with logind support, cannot display boot loader entries.");
421 #endif
422 }
423