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