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