Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : :
3 : : #include <errno.h>
4 : : #include <pwd.h>
5 : : #include <string.h>
6 : : #include <sys/stat.h>
7 : : #include <unistd.h>
8 : :
9 : : #include "sd-device.h"
10 : : #include "sd-messages.h"
11 : :
12 : : #include "alloc-util.h"
13 : : #include "audit-util.h"
14 : : #include "bootspec.h"
15 : : #include "bus-common-errors.h"
16 : : #include "bus-error.h"
17 : : #include "bus-unit-util.h"
18 : : #include "bus-util.h"
19 : : #include "cgroup-util.h"
20 : : #include "device-util.h"
21 : : #include "dirent-util.h"
22 : : #include "efivars.h"
23 : : #include "env-util.h"
24 : : #include "escape.h"
25 : : #include "fd-util.h"
26 : : #include "fileio-label.h"
27 : : #include "fileio.h"
28 : : #include "format-util.h"
29 : : #include "fs-util.h"
30 : : #include "logind-dbus.h"
31 : : #include "logind-seat-dbus.h"
32 : : #include "logind-session-dbus.h"
33 : : #include "logind-user-dbus.h"
34 : : #include "logind.h"
35 : : #include "missing_capability.h"
36 : : #include "mkdir.h"
37 : : #include "parse-util.h"
38 : : #include "path-util.h"
39 : : #include "process-util.h"
40 : : #include "reboot-util.h"
41 : : #include "selinux-util.h"
42 : : #include "sleep-config.h"
43 : : #include "special.h"
44 : : #include "stdio-util.h"
45 : : #include "strv.h"
46 : : #include "terminal-util.h"
47 : : #include "tmpfile-util.h"
48 : : #include "unit-name.h"
49 : : #include "user-util.h"
50 : : #include "utmp-wtmp.h"
51 : : #include "virt.h"
52 : :
53 : 0 : static int get_sender_session(
54 : : Manager *m,
55 : : sd_bus_message *message,
56 : : bool consult_display,
57 : : sd_bus_error *error,
58 : : Session **ret) {
59 : :
60 : 0 : _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
61 : 0 : Session *session = NULL;
62 : : const char *name;
63 : : int r;
64 : :
65 : : /* Acquire the sender's session. This first checks if the sending process is inside a session itself,
66 : : * and returns that. If not and 'consult_display' is true, this returns the display session of the
67 : : * owning user of the caller. */
68 : :
69 [ # # ]: 0 : r = sd_bus_query_sender_creds(message,
70 : : SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT|
71 : : (consult_display ? SD_BUS_CREDS_OWNER_UID : 0), &creds);
72 [ # # ]: 0 : if (r < 0)
73 : 0 : return r;
74 : :
75 : 0 : r = sd_bus_creds_get_session(creds, &name);
76 [ # # ]: 0 : if (r < 0) {
77 [ # # ]: 0 : if (r != -ENXIO)
78 : 0 : return r;
79 : :
80 [ # # ]: 0 : if (consult_display) {
81 : : uid_t uid;
82 : :
83 : 0 : r = sd_bus_creds_get_owner_uid(creds, &uid);
84 [ # # ]: 0 : if (r < 0) {
85 [ # # ]: 0 : if (r != -ENXIO)
86 : 0 : return r;
87 : : } else {
88 : : User *user;
89 : :
90 : 0 : user = hashmap_get(m->users, UID_TO_PTR(uid));
91 [ # # ]: 0 : if (user)
92 : 0 : session = user->display;
93 : : }
94 : : }
95 : : } else
96 : 0 : session = hashmap_get(m->sessions, name);
97 : :
98 [ # # ]: 0 : if (!session)
99 [ # # ]: 0 : return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID,
100 : : consult_display ?
101 : : "Caller does not belong to any known session and doesn't own any suitable session." :
102 : : "Caller does not belong to any known session.");
103 : :
104 : 0 : *ret = session;
105 : 0 : return 0;
106 : : }
107 : :
108 : 0 : int manager_get_session_from_creds(
109 : : Manager *m,
110 : : sd_bus_message *message,
111 : : const char *name,
112 : : sd_bus_error *error,
113 : : Session **ret) {
114 : :
115 : : Session *session;
116 : :
117 [ # # ]: 0 : assert(m);
118 [ # # ]: 0 : assert(message);
119 [ # # ]: 0 : assert(ret);
120 : :
121 [ # # ]: 0 : if (SEAT_IS_SELF(name)) /* the caller's own session */
122 : 0 : return get_sender_session(m, message, false, error, ret);
123 [ # # ]: 0 : if (SEAT_IS_AUTO(name)) /* The caller's own session if they have one, otherwise their user's display session */
124 : 0 : return get_sender_session(m, message, true, error, ret);
125 : :
126 : 0 : session = hashmap_get(m->sessions, name);
127 [ # # ]: 0 : if (!session)
128 : 0 : return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
129 : :
130 : 0 : *ret = session;
131 : 0 : return 0;
132 : : }
133 : :
134 : 0 : static int get_sender_user(Manager *m, sd_bus_message *message, sd_bus_error *error, User **ret) {
135 : 0 : _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
136 : : uid_t uid;
137 : : User *user;
138 : : int r;
139 : :
140 : : /* Note that we get the owner UID of the session, not the actual client UID here! */
141 : 0 : r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
142 [ # # ]: 0 : if (r < 0)
143 : 0 : return r;
144 : :
145 : 0 : r = sd_bus_creds_get_owner_uid(creds, &uid);
146 [ # # ]: 0 : if (r < 0) {
147 [ # # ]: 0 : if (r != -ENXIO)
148 : 0 : return r;
149 : :
150 : 0 : user = NULL;
151 : : } else
152 : 0 : user = hashmap_get(m->users, UID_TO_PTR(uid));
153 : :
154 [ # # ]: 0 : if (!user)
155 : 0 : return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID,
156 : : "Caller does not belong to any logged in or lingering user");
157 : :
158 : 0 : *ret = user;
159 : 0 : return 0;
160 : : }
161 : :
162 : 0 : int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret) {
163 : : User *user;
164 : :
165 [ # # ]: 0 : assert(m);
166 [ # # ]: 0 : assert(message);
167 [ # # ]: 0 : assert(ret);
168 : :
169 [ # # ]: 0 : if (!uid_is_valid(uid))
170 : 0 : return get_sender_user(m, message, error, ret);
171 : :
172 : 0 : user = hashmap_get(m->users, UID_TO_PTR(uid));
173 [ # # ]: 0 : if (!user)
174 : 0 : return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER,
175 : : "User ID "UID_FMT" is not logged in or lingering", uid);
176 : :
177 : 0 : *ret = user;
178 : 0 : return 0;
179 : : }
180 : :
181 : 0 : int manager_get_seat_from_creds(
182 : : Manager *m,
183 : : sd_bus_message *message,
184 : : const char *name,
185 : : sd_bus_error *error,
186 : : Seat **ret) {
187 : :
188 : : Seat *seat;
189 : : int r;
190 : :
191 [ # # ]: 0 : assert(m);
192 [ # # ]: 0 : assert(message);
193 [ # # ]: 0 : assert(ret);
194 : :
195 [ # # # # ]: 0 : if (SEAT_IS_SELF(name) || SEAT_IS_AUTO(name)) {
196 : : Session *session;
197 : :
198 : : /* Use these special seat names as session names */
199 : 0 : r = manager_get_session_from_creds(m, message, name, error, &session);
200 [ # # ]: 0 : if (r < 0)
201 : 0 : return r;
202 : :
203 : 0 : seat = session->seat;
204 [ # # ]: 0 : if (!seat)
205 : 0 : return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session '%s' has no seat.", session->id);
206 : : } else {
207 : 0 : seat = hashmap_get(m->seats, name);
208 [ # # ]: 0 : if (!seat)
209 : 0 : return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
210 : : }
211 : :
212 : 0 : *ret = seat;
213 : 0 : return 0;
214 : : }
215 : :
216 : 0 : static int return_test_polkit(
217 : : sd_bus_message *message,
218 : : int capability,
219 : : const char *action,
220 : : const char **details,
221 : : uid_t good_user,
222 : : sd_bus_error *e) {
223 : :
224 : : const char *result;
225 : : bool challenge;
226 : : int r;
227 : :
228 : 0 : r = bus_test_polkit(message, capability, action, details, good_user, &challenge, e);
229 [ # # ]: 0 : if (r < 0)
230 : 0 : return r;
231 : :
232 [ # # ]: 0 : if (r > 0)
233 : 0 : result = "yes";
234 [ # # ]: 0 : else if (challenge)
235 : 0 : result = "challenge";
236 : : else
237 : 0 : result = "no";
238 : :
239 : 0 : return sd_bus_reply_method_return(message, "s", result);
240 : : }
241 : :
242 : 0 : static int property_get_idle_hint(
243 : : sd_bus *bus,
244 : : const char *path,
245 : : const char *interface,
246 : : const char *property,
247 : : sd_bus_message *reply,
248 : : void *userdata,
249 : : sd_bus_error *error) {
250 : :
251 : 0 : Manager *m = userdata;
252 : :
253 [ # # ]: 0 : assert(bus);
254 [ # # ]: 0 : assert(reply);
255 [ # # ]: 0 : assert(m);
256 : :
257 : 0 : return sd_bus_message_append(reply, "b", manager_get_idle_hint(m, NULL) > 0);
258 : : }
259 : :
260 : 0 : static int property_get_idle_since_hint(
261 : : sd_bus *bus,
262 : : const char *path,
263 : : const char *interface,
264 : : const char *property,
265 : : sd_bus_message *reply,
266 : : void *userdata,
267 : : sd_bus_error *error) {
268 : :
269 : 0 : Manager *m = userdata;
270 : 0 : dual_timestamp t = DUAL_TIMESTAMP_NULL;
271 : :
272 [ # # ]: 0 : assert(bus);
273 [ # # ]: 0 : assert(reply);
274 [ # # ]: 0 : assert(m);
275 : :
276 : 0 : manager_get_idle_hint(m, &t);
277 : :
278 [ # # ]: 0 : return sd_bus_message_append(reply, "t", streq(property, "IdleSinceHint") ? t.realtime : t.monotonic);
279 : : }
280 : :
281 : 0 : static int property_get_inhibited(
282 : : sd_bus *bus,
283 : : const char *path,
284 : : const char *interface,
285 : : const char *property,
286 : : sd_bus_message *reply,
287 : : void *userdata,
288 : : sd_bus_error *error) {
289 : :
290 : 0 : Manager *m = userdata;
291 : : InhibitWhat w;
292 : :
293 [ # # ]: 0 : assert(bus);
294 [ # # ]: 0 : assert(reply);
295 [ # # ]: 0 : assert(m);
296 : :
297 : 0 : w = manager_inhibit_what(m, streq(property, "BlockInhibited") ? INHIBIT_BLOCK : INHIBIT_DELAY);
298 : :
299 : 0 : return sd_bus_message_append(reply, "s", inhibit_what_to_string(w));
300 : : }
301 : :
302 : 0 : static int property_get_preparing(
303 : : sd_bus *bus,
304 : : const char *path,
305 : : const char *interface,
306 : : const char *property,
307 : : sd_bus_message *reply,
308 : : void *userdata,
309 : : sd_bus_error *error) {
310 : :
311 : 0 : Manager *m = userdata;
312 : : bool b;
313 : :
314 [ # # ]: 0 : assert(bus);
315 [ # # ]: 0 : assert(reply);
316 [ # # ]: 0 : assert(m);
317 : :
318 [ # # ]: 0 : if (streq(property, "PreparingForShutdown"))
319 : 0 : b = m->action_what & INHIBIT_SHUTDOWN;
320 : : else
321 : 0 : b = m->action_what & INHIBIT_SLEEP;
322 : :
323 : 0 : return sd_bus_message_append(reply, "b", b);
324 : : }
325 : :
326 : 0 : static int property_get_scheduled_shutdown(
327 : : sd_bus *bus,
328 : : const char *path,
329 : : const char *interface,
330 : : const char *property,
331 : : sd_bus_message *reply,
332 : : void *userdata,
333 : : sd_bus_error *error) {
334 : :
335 : 0 : Manager *m = userdata;
336 : : int r;
337 : :
338 [ # # ]: 0 : assert(bus);
339 [ # # ]: 0 : assert(reply);
340 [ # # ]: 0 : assert(m);
341 : :
342 : 0 : r = sd_bus_message_open_container(reply, 'r', "st");
343 [ # # ]: 0 : if (r < 0)
344 : 0 : return r;
345 : :
346 : 0 : r = sd_bus_message_append(reply, "st", m->scheduled_shutdown_type, m->scheduled_shutdown_timeout);
347 [ # # ]: 0 : if (r < 0)
348 : 0 : return r;
349 : :
350 : 0 : return sd_bus_message_close_container(reply);
351 : : }
352 : :
353 [ # # # # : 0 : static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
# # ]
354 [ # # # # : 0 : static BUS_DEFINE_PROPERTY_GET(property_get_docked, "b", Manager, manager_is_docked_or_external_displays);
# # ]
355 [ # # # # : 0 : static BUS_DEFINE_PROPERTY_GET(property_get_lid_closed, "b", Manager, manager_is_lid_closed);
# # ]
356 [ # # # # ]: 0 : static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_on_external_power, "b", manager_is_on_external_power);
357 [ # # # # ]: 0 : static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_compat_user_tasks_max, "t", CGROUP_LIMIT_MAX);
358 [ # # # # : 0 : static BUS_DEFINE_PROPERTY_GET_REF(property_get_hashmap_size, "t", Hashmap *, (uint64_t) hashmap_size);
# # ]
359 : :
360 : 0 : static int method_get_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
361 : 0 : _cleanup_free_ char *p = NULL;
362 : 0 : Manager *m = userdata;
363 : : const char *name;
364 : : Session *session;
365 : : int r;
366 : :
367 [ # # ]: 0 : assert(message);
368 [ # # ]: 0 : assert(m);
369 : :
370 : 0 : r = sd_bus_message_read(message, "s", &name);
371 [ # # ]: 0 : if (r < 0)
372 : 0 : return r;
373 : :
374 : 0 : r = manager_get_session_from_creds(m, message, name, error, &session);
375 [ # # ]: 0 : if (r < 0)
376 : 0 : return r;
377 : :
378 : 0 : p = session_bus_path(session);
379 [ # # ]: 0 : if (!p)
380 : 0 : return -ENOMEM;
381 : :
382 : 0 : return sd_bus_reply_method_return(message, "o", p);
383 : : }
384 : :
385 : : /* Get login session of a process. This is not what you are looking for these days,
386 : : * as apps may instead belong to a user service unit. This includes terminal
387 : : * emulators and hence command-line apps. */
388 : 0 : static int method_get_session_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
389 : 0 : _cleanup_free_ char *p = NULL;
390 : 0 : Session *session = NULL;
391 : 0 : Manager *m = userdata;
392 : : pid_t pid;
393 : : int r;
394 : :
395 [ # # ]: 0 : assert(message);
396 [ # # ]: 0 : assert(m);
397 : :
398 : : assert_cc(sizeof(pid_t) == sizeof(uint32_t));
399 : :
400 : 0 : r = sd_bus_message_read(message, "u", &pid);
401 [ # # ]: 0 : if (r < 0)
402 : 0 : return r;
403 [ # # ]: 0 : if (pid < 0)
404 : 0 : return -EINVAL;
405 : :
406 [ # # ]: 0 : if (pid == 0) {
407 : 0 : r = manager_get_session_from_creds(m, message, NULL, error, &session);
408 [ # # ]: 0 : if (r < 0)
409 : 0 : return r;
410 : : } else {
411 : 0 : r = manager_get_session_by_pid(m, pid, &session);
412 [ # # ]: 0 : if (r < 0)
413 : 0 : return r;
414 : :
415 [ # # ]: 0 : if (!session)
416 : 0 : return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID,
417 : : "PID "PID_FMT" does not belong to any known session", pid);
418 : : }
419 : :
420 : 0 : p = session_bus_path(session);
421 [ # # ]: 0 : if (!p)
422 : 0 : return -ENOMEM;
423 : :
424 : 0 : return sd_bus_reply_method_return(message, "o", p);
425 : : }
426 : :
427 : 0 : static int method_get_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
428 : 0 : _cleanup_free_ char *p = NULL;
429 : 0 : Manager *m = userdata;
430 : : uint32_t uid;
431 : : User *user;
432 : : int r;
433 : :
434 [ # # ]: 0 : assert(message);
435 [ # # ]: 0 : assert(m);
436 : :
437 : 0 : r = sd_bus_message_read(message, "u", &uid);
438 [ # # ]: 0 : if (r < 0)
439 : 0 : return r;
440 : :
441 : 0 : r = manager_get_user_from_creds(m, message, uid, error, &user);
442 [ # # ]: 0 : if (r < 0)
443 : 0 : return r;
444 : :
445 : 0 : p = user_bus_path(user);
446 [ # # ]: 0 : if (!p)
447 : 0 : return -ENOMEM;
448 : :
449 : 0 : return sd_bus_reply_method_return(message, "o", p);
450 : : }
451 : :
452 : 0 : static int method_get_user_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
453 : 0 : _cleanup_free_ char *p = NULL;
454 : 0 : Manager *m = userdata;
455 : 0 : User *user = NULL;
456 : : pid_t pid;
457 : : int r;
458 : :
459 [ # # ]: 0 : assert(message);
460 [ # # ]: 0 : assert(m);
461 : :
462 : : assert_cc(sizeof(pid_t) == sizeof(uint32_t));
463 : :
464 : 0 : r = sd_bus_message_read(message, "u", &pid);
465 [ # # ]: 0 : if (r < 0)
466 : 0 : return r;
467 [ # # ]: 0 : if (pid < 0)
468 : 0 : return -EINVAL;
469 : :
470 [ # # ]: 0 : if (pid == 0) {
471 : 0 : r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user);
472 [ # # ]: 0 : if (r < 0)
473 : 0 : return r;
474 : : } else {
475 : 0 : r = manager_get_user_by_pid(m, pid, &user);
476 [ # # ]: 0 : if (r < 0)
477 : 0 : return r;
478 [ # # ]: 0 : if (!user)
479 : 0 : return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID,
480 : : "PID "PID_FMT" does not belong to any logged in user or lingering user",
481 : : pid);
482 : : }
483 : :
484 : 0 : p = user_bus_path(user);
485 [ # # ]: 0 : if (!p)
486 : 0 : return -ENOMEM;
487 : :
488 : 0 : return sd_bus_reply_method_return(message, "o", p);
489 : : }
490 : :
491 : 0 : static int method_get_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
492 : 0 : _cleanup_free_ char *p = NULL;
493 : 0 : Manager *m = userdata;
494 : : const char *name;
495 : : Seat *seat;
496 : : int r;
497 : :
498 [ # # ]: 0 : assert(message);
499 [ # # ]: 0 : assert(m);
500 : :
501 : 0 : r = sd_bus_message_read(message, "s", &name);
502 [ # # ]: 0 : if (r < 0)
503 : 0 : return r;
504 : :
505 : 0 : r = manager_get_seat_from_creds(m, message, name, error, &seat);
506 [ # # ]: 0 : if (r < 0)
507 : 0 : return r;
508 : :
509 : 0 : p = seat_bus_path(seat);
510 [ # # ]: 0 : if (!p)
511 : 0 : return -ENOMEM;
512 : :
513 : 0 : return sd_bus_reply_method_return(message, "o", p);
514 : : }
515 : :
516 : 0 : static int method_list_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
517 : 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
518 : 0 : Manager *m = userdata;
519 : : Session *session;
520 : : Iterator i;
521 : : int r;
522 : :
523 [ # # ]: 0 : assert(message);
524 [ # # ]: 0 : assert(m);
525 : :
526 : 0 : r = sd_bus_message_new_method_return(message, &reply);
527 [ # # ]: 0 : if (r < 0)
528 : 0 : return r;
529 : :
530 : 0 : r = sd_bus_message_open_container(reply, 'a', "(susso)");
531 [ # # ]: 0 : if (r < 0)
532 : 0 : return r;
533 : :
534 [ # # ]: 0 : HASHMAP_FOREACH(session, m->sessions, i) {
535 [ # # ]: 0 : _cleanup_free_ char *p = NULL;
536 : :
537 : 0 : p = session_bus_path(session);
538 [ # # ]: 0 : if (!p)
539 : 0 : return -ENOMEM;
540 : :
541 : 0 : r = sd_bus_message_append(reply, "(susso)",
542 : 0 : session->id,
543 : 0 : (uint32_t) session->user->uid,
544 : 0 : session->user->name,
545 [ # # ]: 0 : session->seat ? session->seat->id : "",
546 : : p);
547 [ # # ]: 0 : if (r < 0)
548 : 0 : return r;
549 : : }
550 : :
551 : 0 : r = sd_bus_message_close_container(reply);
552 [ # # ]: 0 : if (r < 0)
553 : 0 : return r;
554 : :
555 : 0 : return sd_bus_send(NULL, reply, NULL);
556 : : }
557 : :
558 : 0 : static int method_list_users(sd_bus_message *message, void *userdata, sd_bus_error *error) {
559 : 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
560 : 0 : Manager *m = userdata;
561 : : User *user;
562 : : Iterator i;
563 : : int r;
564 : :
565 [ # # ]: 0 : assert(message);
566 [ # # ]: 0 : assert(m);
567 : :
568 : 0 : r = sd_bus_message_new_method_return(message, &reply);
569 [ # # ]: 0 : if (r < 0)
570 : 0 : return r;
571 : :
572 : 0 : r = sd_bus_message_open_container(reply, 'a', "(uso)");
573 [ # # ]: 0 : if (r < 0)
574 : 0 : return r;
575 : :
576 [ # # ]: 0 : HASHMAP_FOREACH(user, m->users, i) {
577 [ # # ]: 0 : _cleanup_free_ char *p = NULL;
578 : :
579 : 0 : p = user_bus_path(user);
580 [ # # ]: 0 : if (!p)
581 : 0 : return -ENOMEM;
582 : :
583 : 0 : r = sd_bus_message_append(reply, "(uso)",
584 : 0 : (uint32_t) user->uid,
585 : 0 : user->name,
586 : : p);
587 [ # # ]: 0 : if (r < 0)
588 : 0 : return r;
589 : : }
590 : :
591 : 0 : r = sd_bus_message_close_container(reply);
592 [ # # ]: 0 : if (r < 0)
593 : 0 : return r;
594 : :
595 : 0 : return sd_bus_send(NULL, reply, NULL);
596 : : }
597 : :
598 : 0 : static int method_list_seats(sd_bus_message *message, void *userdata, sd_bus_error *error) {
599 : 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
600 : 0 : Manager *m = userdata;
601 : : Seat *seat;
602 : : Iterator i;
603 : : int r;
604 : :
605 [ # # ]: 0 : assert(message);
606 [ # # ]: 0 : assert(m);
607 : :
608 : 0 : r = sd_bus_message_new_method_return(message, &reply);
609 [ # # ]: 0 : if (r < 0)
610 : 0 : return r;
611 : :
612 : 0 : r = sd_bus_message_open_container(reply, 'a', "(so)");
613 [ # # ]: 0 : if (r < 0)
614 : 0 : return r;
615 : :
616 [ # # ]: 0 : HASHMAP_FOREACH(seat, m->seats, i) {
617 [ # # ]: 0 : _cleanup_free_ char *p = NULL;
618 : :
619 : 0 : p = seat_bus_path(seat);
620 [ # # ]: 0 : if (!p)
621 : 0 : return -ENOMEM;
622 : :
623 : 0 : r = sd_bus_message_append(reply, "(so)", seat->id, p);
624 [ # # ]: 0 : if (r < 0)
625 : 0 : return r;
626 : : }
627 : :
628 : 0 : r = sd_bus_message_close_container(reply);
629 [ # # ]: 0 : if (r < 0)
630 : 0 : return r;
631 : :
632 : 0 : return sd_bus_send(NULL, reply, NULL);
633 : : }
634 : :
635 : 0 : static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
636 : 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
637 : 0 : Manager *m = userdata;
638 : : Inhibitor *inhibitor;
639 : : Iterator i;
640 : : int r;
641 : :
642 [ # # ]: 0 : assert(message);
643 [ # # ]: 0 : assert(m);
644 : :
645 : 0 : r = sd_bus_message_new_method_return(message, &reply);
646 [ # # ]: 0 : if (r < 0)
647 : 0 : return r;
648 : :
649 : 0 : r = sd_bus_message_open_container(reply, 'a', "(ssssuu)");
650 [ # # ]: 0 : if (r < 0)
651 : 0 : return r;
652 : :
653 [ # # ]: 0 : HASHMAP_FOREACH(inhibitor, m->inhibitors, i) {
654 : :
655 : 0 : r = sd_bus_message_append(reply, "(ssssuu)",
656 : 0 : strempty(inhibit_what_to_string(inhibitor->what)),
657 : 0 : strempty(inhibitor->who),
658 : 0 : strempty(inhibitor->why),
659 : 0 : strempty(inhibit_mode_to_string(inhibitor->mode)),
660 : 0 : (uint32_t) inhibitor->uid,
661 : 0 : (uint32_t) inhibitor->pid);
662 [ # # ]: 0 : if (r < 0)
663 : 0 : return r;
664 : : }
665 : :
666 : 0 : r = sd_bus_message_close_container(reply);
667 [ # # ]: 0 : if (r < 0)
668 : 0 : return r;
669 : :
670 : 0 : return sd_bus_send(NULL, reply, NULL);
671 : : }
672 : :
673 : 0 : static int method_create_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
674 : : const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
675 : 0 : _cleanup_free_ char *id = NULL;
676 : 0 : Session *session = NULL;
677 : 0 : uint32_t audit_id = 0;
678 : 0 : Manager *m = userdata;
679 : 0 : User *user = NULL;
680 : 0 : Seat *seat = NULL;
681 : : pid_t leader;
682 : : uid_t uid;
683 : : int remote;
684 : 0 : uint32_t vtnr = 0;
685 : : SessionType t;
686 : : SessionClass c;
687 : : int r;
688 : :
689 [ # # ]: 0 : assert(message);
690 [ # # ]: 0 : assert(m);
691 : :
692 : : assert_cc(sizeof(pid_t) == sizeof(uint32_t));
693 : : assert_cc(sizeof(uid_t) == sizeof(uint32_t));
694 : :
695 : 0 : r = sd_bus_message_read(message, "uusssssussbss",
696 : : &uid, &leader, &service, &type, &class, &desktop, &cseat,
697 : : &vtnr, &tty, &display, &remote, &remote_user, &remote_host);
698 [ # # ]: 0 : if (r < 0)
699 : 0 : return r;
700 : :
701 [ # # ]: 0 : if (!uid_is_valid(uid))
702 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UID");
703 [ # # # # : 0 : if (leader < 0 || leader == 1 || leader == getpid_cached())
# # ]
704 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
705 : :
706 [ # # ]: 0 : if (isempty(type))
707 : 0 : t = _SESSION_TYPE_INVALID;
708 : : else {
709 : 0 : t = session_type_from_string(type);
710 [ # # ]: 0 : if (t < 0)
711 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
712 : : "Invalid session type %s", type);
713 : : }
714 : :
715 [ # # ]: 0 : if (isempty(class))
716 : 0 : c = _SESSION_CLASS_INVALID;
717 : : else {
718 : 0 : c = session_class_from_string(class);
719 [ # # ]: 0 : if (c < 0)
720 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
721 : : "Invalid session class %s", class);
722 : : }
723 : :
724 [ # # ]: 0 : if (isempty(desktop))
725 : 0 : desktop = NULL;
726 : : else {
727 [ # # ]: 0 : if (!string_is_safe(desktop))
728 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
729 : : "Invalid desktop string %s", desktop);
730 : : }
731 : :
732 [ # # ]: 0 : if (isempty(cseat))
733 : 0 : seat = NULL;
734 : : else {
735 : 0 : seat = hashmap_get(m->seats, cseat);
736 [ # # ]: 0 : if (!seat)
737 : 0 : return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT,
738 : : "No seat '%s' known", cseat);
739 : : }
740 : :
741 [ # # ]: 0 : if (tty_is_vc(tty)) {
742 : : int v;
743 : :
744 [ # # ]: 0 : if (!seat)
745 : 0 : seat = m->seat0;
746 [ # # ]: 0 : else if (seat != m->seat0)
747 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
748 : : "TTY %s is virtual console but seat %s is not seat0", tty, seat->id);
749 : :
750 : 0 : v = vtnr_from_tty(tty);
751 [ # # ]: 0 : if (v <= 0)
752 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
753 : : "Cannot determine VT number from virtual console TTY %s", tty);
754 : :
755 [ # # ]: 0 : if (vtnr == 0)
756 : 0 : vtnr = (uint32_t) v;
757 [ # # ]: 0 : else if (vtnr != (uint32_t) v)
758 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
759 : : "Specified TTY and VT number do not match");
760 : :
761 [ # # ]: 0 : } else if (tty_is_console(tty)) {
762 : :
763 [ # # ]: 0 : if (!seat)
764 : 0 : seat = m->seat0;
765 [ # # ]: 0 : else if (seat != m->seat0)
766 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
767 : : "Console TTY specified but seat is not seat0");
768 : :
769 [ # # ]: 0 : if (vtnr != 0)
770 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
771 : : "Console TTY specified but VT number is not 0");
772 : : }
773 : :
774 [ # # ]: 0 : if (seat) {
775 [ # # ]: 0 : if (seat_has_vts(seat)) {
776 [ # # # # ]: 0 : if (vtnr <= 0 || vtnr > 63)
777 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
778 : : "VT number out of range");
779 : : } else {
780 [ # # ]: 0 : if (vtnr != 0)
781 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
782 : : "Seat has no VTs but VT number not 0");
783 : : }
784 : : }
785 : :
786 [ # # ]: 0 : if (t == _SESSION_TYPE_INVALID) {
787 [ # # ]: 0 : if (!isempty(display))
788 : 0 : t = SESSION_X11;
789 [ # # ]: 0 : else if (!isempty(tty))
790 : 0 : t = SESSION_TTY;
791 : : else
792 : 0 : t = SESSION_UNSPECIFIED;
793 : : }
794 : :
795 [ # # ]: 0 : if (c == _SESSION_CLASS_INVALID) {
796 [ # # ]: 0 : if (t == SESSION_UNSPECIFIED)
797 : 0 : c = SESSION_BACKGROUND;
798 : : else
799 : 0 : c = SESSION_USER;
800 : : }
801 : :
802 [ # # ]: 0 : if (leader == 0) {
803 [ # # ]: 0 : _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
804 : :
805 : 0 : r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
806 [ # # ]: 0 : if (r < 0)
807 : 0 : return r;
808 : :
809 : 0 : r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
810 [ # # ]: 0 : if (r < 0)
811 : 0 : return r;
812 : : }
813 : :
814 : : /* Check if we are already in a logind session. Or if we are in user@.service
815 : : * which is a special PAM session that avoids creating a logind session. */
816 : 0 : r = manager_get_user_by_pid(m, leader, NULL);
817 [ # # ]: 0 : if (r < 0)
818 : 0 : return r;
819 [ # # ]: 0 : if (r > 0)
820 : 0 : return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY,
821 : : "Already running in a session or user slice");
822 : :
823 : : /*
824 : : * Old gdm and lightdm start the user-session on the same VT as
825 : : * the greeter session. But they destroy the greeter session
826 : : * after the user-session and want the user-session to take
827 : : * over the VT. We need to support this for
828 : : * backwards-compatibility, so make sure we allow new sessions
829 : : * on a VT that a greeter is running on. Furthermore, to allow
830 : : * re-logins, we have to allow a greeter to take over a used VT for
831 : : * the exact same reasons.
832 : : */
833 [ # # ]: 0 : if (c != SESSION_GREETER &&
834 [ # # ]: 0 : vtnr > 0 &&
835 [ # # ]: 0 : vtnr < m->seat0->position_count &&
836 [ # # ]: 0 : m->seat0->positions[vtnr] &&
837 [ # # ]: 0 : m->seat0->positions[vtnr]->class != SESSION_GREETER)
838 : 0 : return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already occupied by a session");
839 : :
840 [ # # ]: 0 : if (hashmap_size(m->sessions) >= m->sessions_max)
841 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED,
842 : : "Maximum number of sessions (%" PRIu64 ") reached, refusing further sessions.",
843 : : m->sessions_max);
844 : :
845 : 0 : (void) audit_session_from_pid(leader, &audit_id);
846 [ # # ]: 0 : if (audit_session_is_valid(audit_id)) {
847 : : /* Keep our session IDs and the audit session IDs in sync */
848 : :
849 [ # # ]: 0 : if (asprintf(&id, "%"PRIu32, audit_id) < 0)
850 : 0 : return -ENOMEM;
851 : :
852 : : /* Wut? There's already a session by this name and we didn't find it above? Weird, then let's
853 : : * not trust the audit data and let's better register a new ID */
854 [ # # ]: 0 : if (hashmap_contains(m->sessions, id)) {
855 [ # # ]: 0 : log_warning("Existing logind session ID %s used by new audit session, ignoring.", id);
856 : 0 : audit_id = AUDIT_SESSION_INVALID;
857 : 0 : id = mfree(id);
858 : : }
859 : : }
860 : :
861 [ # # ]: 0 : if (!id) {
862 : : do {
863 : 0 : id = mfree(id);
864 : :
865 [ # # ]: 0 : if (asprintf(&id, "c%lu", ++m->session_counter) < 0)
866 : 0 : return -ENOMEM;
867 : :
868 [ # # ]: 0 : } while (hashmap_contains(m->sessions, id));
869 : : }
870 : :
871 : : /* The generated names should not clash with 'auto' or 'self' */
872 [ # # ]: 0 : assert(!SESSION_IS_SELF(id));
873 [ # # ]: 0 : assert(!SESSION_IS_AUTO(id));
874 : :
875 : : /* If we are not watching utmp already, try again */
876 : 0 : manager_reconnect_utmp(m);
877 : :
878 : 0 : r = manager_add_user_by_uid(m, uid, &user);
879 [ # # ]: 0 : if (r < 0)
880 : 0 : goto fail;
881 : :
882 : 0 : r = manager_add_session(m, id, &session);
883 [ # # ]: 0 : if (r < 0)
884 : 0 : goto fail;
885 : :
886 : 0 : session_set_user(session, user);
887 : 0 : r = session_set_leader(session, leader);
888 [ # # ]: 0 : if (r < 0)
889 : 0 : goto fail;
890 : :
891 : 0 : session->type = t;
892 : 0 : session->class = c;
893 : 0 : session->remote = remote;
894 : 0 : session->vtnr = vtnr;
895 : :
896 [ # # ]: 0 : if (!isempty(tty)) {
897 : 0 : session->tty = strdup(tty);
898 [ # # ]: 0 : if (!session->tty) {
899 : 0 : r = -ENOMEM;
900 : 0 : goto fail;
901 : : }
902 : :
903 : 0 : session->tty_validity = TTY_FROM_PAM;
904 : : }
905 : :
906 [ # # ]: 0 : if (!isempty(display)) {
907 : 0 : session->display = strdup(display);
908 [ # # ]: 0 : if (!session->display) {
909 : 0 : r = -ENOMEM;
910 : 0 : goto fail;
911 : : }
912 : : }
913 : :
914 [ # # ]: 0 : if (!isempty(remote_user)) {
915 : 0 : session->remote_user = strdup(remote_user);
916 [ # # ]: 0 : if (!session->remote_user) {
917 : 0 : r = -ENOMEM;
918 : 0 : goto fail;
919 : : }
920 : : }
921 : :
922 [ # # ]: 0 : if (!isempty(remote_host)) {
923 : 0 : session->remote_host = strdup(remote_host);
924 [ # # ]: 0 : if (!session->remote_host) {
925 : 0 : r = -ENOMEM;
926 : 0 : goto fail;
927 : : }
928 : : }
929 : :
930 [ # # ]: 0 : if (!isempty(service)) {
931 : 0 : session->service = strdup(service);
932 [ # # ]: 0 : if (!session->service) {
933 : 0 : r = -ENOMEM;
934 : 0 : goto fail;
935 : : }
936 : : }
937 : :
938 [ # # ]: 0 : if (!isempty(desktop)) {
939 : 0 : session->desktop = strdup(desktop);
940 [ # # ]: 0 : if (!session->desktop) {
941 : 0 : r = -ENOMEM;
942 : 0 : goto fail;
943 : : }
944 : : }
945 : :
946 [ # # ]: 0 : if (seat) {
947 : 0 : r = seat_attach_session(seat, session);
948 [ # # ]: 0 : if (r < 0)
949 : 0 : goto fail;
950 : : }
951 : :
952 : 0 : r = sd_bus_message_enter_container(message, 'a', "(sv)");
953 [ # # ]: 0 : if (r < 0)
954 : 0 : goto fail;
955 : :
956 : 0 : r = session_start(session, message, error);
957 [ # # ]: 0 : if (r < 0)
958 : 0 : goto fail;
959 : :
960 : 0 : r = sd_bus_message_exit_container(message);
961 [ # # ]: 0 : if (r < 0)
962 : 0 : goto fail;
963 : :
964 : 0 : session->create_message = sd_bus_message_ref(message);
965 : :
966 : : /* Now, let's wait until the slice unit and stuff got created. We send the reply back from
967 : : * session_send_create_reply(). */
968 : :
969 : 0 : return 1;
970 : :
971 : 0 : fail:
972 [ # # ]: 0 : if (session)
973 : 0 : session_add_to_gc_queue(session);
974 : :
975 [ # # ]: 0 : if (user)
976 : 0 : user_add_to_gc_queue(user);
977 : :
978 : 0 : return r;
979 : : }
980 : :
981 : 0 : static int method_release_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
982 : 0 : Manager *m = userdata;
983 : : Session *session;
984 : : const char *name;
985 : : int r;
986 : :
987 [ # # ]: 0 : assert(message);
988 [ # # ]: 0 : assert(m);
989 : :
990 : 0 : r = sd_bus_message_read(message, "s", &name);
991 [ # # ]: 0 : if (r < 0)
992 : 0 : return r;
993 : :
994 : 0 : r = manager_get_session_from_creds(m, message, name, error, &session);
995 [ # # ]: 0 : if (r < 0)
996 : 0 : return r;
997 : :
998 : 0 : r = session_release(session);
999 [ # # ]: 0 : if (r < 0)
1000 : 0 : return r;
1001 : :
1002 : 0 : return sd_bus_reply_method_return(message, NULL);
1003 : : }
1004 : :
1005 : 0 : static int method_activate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1006 : 0 : Manager *m = userdata;
1007 : : Session *session;
1008 : : const char *name;
1009 : : int r;
1010 : :
1011 [ # # ]: 0 : assert(message);
1012 [ # # ]: 0 : assert(m);
1013 : :
1014 : 0 : r = sd_bus_message_read(message, "s", &name);
1015 [ # # ]: 0 : if (r < 0)
1016 : 0 : return r;
1017 : :
1018 : 0 : r = manager_get_session_from_creds(m, message, name, error, &session);
1019 [ # # ]: 0 : if (r < 0)
1020 : 0 : return r;
1021 : :
1022 : 0 : return bus_session_method_activate(message, session, error);
1023 : : }
1024 : :
1025 : 0 : static int method_activate_session_on_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1026 : : const char *session_name, *seat_name;
1027 : 0 : Manager *m = userdata;
1028 : : Session *session;
1029 : : Seat *seat;
1030 : : int r;
1031 : :
1032 [ # # ]: 0 : assert(message);
1033 [ # # ]: 0 : assert(m);
1034 : :
1035 : : /* Same as ActivateSession() but refuses to work if the seat doesn't match */
1036 : :
1037 : 0 : r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
1038 [ # # ]: 0 : if (r < 0)
1039 : 0 : return r;
1040 : :
1041 : 0 : r = manager_get_session_from_creds(m, message, session_name, error, &session);
1042 [ # # ]: 0 : if (r < 0)
1043 : 0 : return r;
1044 : :
1045 : 0 : r = manager_get_seat_from_creds(m, message, seat_name, error, &seat);
1046 [ # # ]: 0 : if (r < 0)
1047 : 0 : return r;
1048 : :
1049 [ # # ]: 0 : if (session->seat != seat)
1050 : 0 : return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT,
1051 : : "Session %s not on seat %s", session_name, seat_name);
1052 : :
1053 : 0 : r = session_activate(session);
1054 [ # # ]: 0 : if (r < 0)
1055 : 0 : return r;
1056 : :
1057 : 0 : return sd_bus_reply_method_return(message, NULL);
1058 : : }
1059 : :
1060 : 0 : static int method_lock_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1061 : 0 : Manager *m = userdata;
1062 : : Session *session;
1063 : : const char *name;
1064 : : int r;
1065 : :
1066 [ # # ]: 0 : assert(message);
1067 [ # # ]: 0 : assert(m);
1068 : :
1069 : 0 : r = sd_bus_message_read(message, "s", &name);
1070 [ # # ]: 0 : if (r < 0)
1071 : 0 : return r;
1072 : :
1073 : 0 : r = manager_get_session_from_creds(m, message, name, error, &session);
1074 [ # # ]: 0 : if (r < 0)
1075 : 0 : return r;
1076 : :
1077 : 0 : return bus_session_method_lock(message, session, error);
1078 : : }
1079 : :
1080 : 0 : static int method_lock_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1081 : 0 : Manager *m = userdata;
1082 : : int r;
1083 : :
1084 [ # # ]: 0 : assert(message);
1085 [ # # ]: 0 : assert(m);
1086 : :
1087 : 0 : r = bus_verify_polkit_async(
1088 : : message,
1089 : : CAP_SYS_ADMIN,
1090 : : "org.freedesktop.login1.lock-sessions",
1091 : : NULL,
1092 : : false,
1093 : : UID_INVALID,
1094 : : &m->polkit_registry,
1095 : : error);
1096 [ # # ]: 0 : if (r < 0)
1097 : 0 : return r;
1098 [ # # ]: 0 : if (r == 0)
1099 : 0 : return 1; /* Will call us back */
1100 : :
1101 : 0 : r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
1102 [ # # ]: 0 : if (r < 0)
1103 : 0 : return r;
1104 : :
1105 : 0 : return sd_bus_reply_method_return(message, NULL);
1106 : : }
1107 : :
1108 : 0 : static int method_kill_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1109 : : const char *name;
1110 : 0 : Manager *m = userdata;
1111 : : Session *session;
1112 : : int r;
1113 : :
1114 [ # # ]: 0 : assert(message);
1115 [ # # ]: 0 : assert(m);
1116 : :
1117 : 0 : r = sd_bus_message_read(message, "s", &name);
1118 [ # # ]: 0 : if (r < 0)
1119 : 0 : return r;
1120 : :
1121 : 0 : r = manager_get_session_from_creds(m, message, name, error, &session);
1122 [ # # ]: 0 : if (r < 0)
1123 : 0 : return r;
1124 : :
1125 : 0 : return bus_session_method_kill(message, session, error);
1126 : : }
1127 : :
1128 : 0 : static int method_kill_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1129 : 0 : Manager *m = userdata;
1130 : : uint32_t uid;
1131 : : User *user;
1132 : : int r;
1133 : :
1134 [ # # ]: 0 : assert(message);
1135 [ # # ]: 0 : assert(m);
1136 : :
1137 : 0 : r = sd_bus_message_read(message, "u", &uid);
1138 [ # # ]: 0 : if (r < 0)
1139 : 0 : return r;
1140 : :
1141 : 0 : r = manager_get_user_from_creds(m, message, uid, error, &user);
1142 [ # # ]: 0 : if (r < 0)
1143 : 0 : return r;
1144 : :
1145 : 0 : return bus_user_method_kill(message, user, error);
1146 : : }
1147 : :
1148 : 0 : static int method_terminate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1149 : 0 : Manager *m = userdata;
1150 : : const char *name;
1151 : : Session *session;
1152 : : int r;
1153 : :
1154 [ # # ]: 0 : assert(message);
1155 [ # # ]: 0 : assert(m);
1156 : :
1157 : 0 : r = sd_bus_message_read(message, "s", &name);
1158 [ # # ]: 0 : if (r < 0)
1159 : 0 : return r;
1160 : :
1161 : 0 : r = manager_get_session_from_creds(m, message, name, error, &session);
1162 [ # # ]: 0 : if (r < 0)
1163 : 0 : return r;
1164 : :
1165 : 0 : return bus_session_method_terminate(message, session, error);
1166 : : }
1167 : :
1168 : 0 : static int method_terminate_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1169 : 0 : Manager *m = userdata;
1170 : : uint32_t uid;
1171 : : User *user;
1172 : : int r;
1173 : :
1174 [ # # ]: 0 : assert(message);
1175 [ # # ]: 0 : assert(m);
1176 : :
1177 : 0 : r = sd_bus_message_read(message, "u", &uid);
1178 [ # # ]: 0 : if (r < 0)
1179 : 0 : return r;
1180 : :
1181 : 0 : r = manager_get_user_from_creds(m, message, uid, error, &user);
1182 [ # # ]: 0 : if (r < 0)
1183 : 0 : return r;
1184 : :
1185 : 0 : return bus_user_method_terminate(message, user, error);
1186 : : }
1187 : :
1188 : 0 : static int method_terminate_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1189 : 0 : Manager *m = userdata;
1190 : : const char *name;
1191 : : Seat *seat;
1192 : : int r;
1193 : :
1194 [ # # ]: 0 : assert(message);
1195 [ # # ]: 0 : assert(m);
1196 : :
1197 : 0 : r = sd_bus_message_read(message, "s", &name);
1198 [ # # ]: 0 : if (r < 0)
1199 : 0 : return r;
1200 : :
1201 : 0 : r = manager_get_seat_from_creds(m, message, name, error, &seat);
1202 [ # # ]: 0 : if (r < 0)
1203 : 0 : return r;
1204 : :
1205 : 0 : return bus_seat_method_terminate(message, seat, error);
1206 : : }
1207 : :
1208 : 0 : static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1209 : 0 : _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
1210 : 0 : _cleanup_free_ char *cc = NULL;
1211 : 0 : Manager *m = userdata;
1212 : : int r, b, interactive;
1213 : : struct passwd *pw;
1214 : : const char *path;
1215 : : uint32_t uid, auth_uid;
1216 : :
1217 [ # # ]: 0 : assert(message);
1218 [ # # ]: 0 : assert(m);
1219 : :
1220 : 0 : r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive);
1221 [ # # ]: 0 : if (r < 0)
1222 : 0 : return r;
1223 : :
1224 : 0 : r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID |
1225 : : SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
1226 [ # # ]: 0 : if (r < 0)
1227 : 0 : return r;
1228 : :
1229 [ # # ]: 0 : if (!uid_is_valid(uid)) {
1230 : : /* Note that we get the owner UID of the session or user unit,
1231 : : * not the actual client UID here! */
1232 : 0 : r = sd_bus_creds_get_owner_uid(creds, &uid);
1233 [ # # ]: 0 : if (r < 0)
1234 : 0 : return r;
1235 : : }
1236 : :
1237 : : /* owner_uid is racy, so for authorization we must use euid */
1238 : 0 : r = sd_bus_creds_get_euid(creds, &auth_uid);
1239 [ # # ]: 0 : if (r < 0)
1240 : 0 : return r;
1241 : :
1242 : 0 : errno = 0;
1243 : 0 : pw = getpwuid(uid);
1244 [ # # ]: 0 : if (!pw)
1245 : 0 : return errno_or_else(ENOENT);
1246 : :
1247 : 0 : r = bus_verify_polkit_async(
1248 : : message,
1249 : : CAP_SYS_ADMIN,
1250 [ # # ]: 0 : uid == auth_uid ? "org.freedesktop.login1.set-self-linger" :
1251 : : "org.freedesktop.login1.set-user-linger",
1252 : : NULL,
1253 : : interactive,
1254 : : UID_INVALID,
1255 : : &m->polkit_registry,
1256 : : error);
1257 [ # # ]: 0 : if (r < 0)
1258 : 0 : return r;
1259 [ # # ]: 0 : if (r == 0)
1260 : 0 : return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1261 : :
1262 : 0 : (void) mkdir_p_label("/var/lib/systemd", 0755);
1263 : 0 : r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0, MKDIR_WARN_MODE);
1264 [ # # ]: 0 : if (r < 0)
1265 : 0 : return r;
1266 : :
1267 : 0 : cc = cescape(pw->pw_name);
1268 [ # # ]: 0 : if (!cc)
1269 : 0 : return -ENOMEM;
1270 : :
1271 [ # # # # : 0 : path = strjoina("/var/lib/systemd/linger/", cc);
# # # # #
# # # ]
1272 [ # # ]: 0 : if (b) {
1273 : : User *u;
1274 : :
1275 : 0 : r = touch(path);
1276 [ # # ]: 0 : if (r < 0)
1277 : 0 : return r;
1278 : :
1279 [ # # ]: 0 : if (manager_add_user_by_uid(m, uid, &u) >= 0)
1280 : 0 : user_start(u);
1281 : :
1282 : : } else {
1283 : : User *u;
1284 : :
1285 : 0 : r = unlink(path);
1286 [ # # # # ]: 0 : if (r < 0 && errno != ENOENT)
1287 : 0 : return -errno;
1288 : :
1289 : 0 : u = hashmap_get(m->users, UID_TO_PTR(uid));
1290 [ # # ]: 0 : if (u)
1291 : 0 : user_add_to_gc_queue(u);
1292 : : }
1293 : :
1294 : 0 : return sd_bus_reply_method_return(message, NULL);
1295 : : }
1296 : :
1297 : 0 : static int trigger_device(Manager *m, sd_device *d) {
1298 : 0 : _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
1299 : : int r;
1300 : :
1301 [ # # ]: 0 : assert(m);
1302 : :
1303 : 0 : r = sd_device_enumerator_new(&e);
1304 [ # # ]: 0 : if (r < 0)
1305 : 0 : return r;
1306 : :
1307 : 0 : r = sd_device_enumerator_allow_uninitialized(e);
1308 [ # # ]: 0 : if (r < 0)
1309 : 0 : return r;
1310 : :
1311 [ # # ]: 0 : if (d) {
1312 : 0 : r = sd_device_enumerator_add_match_parent(e, d);
1313 [ # # ]: 0 : if (r < 0)
1314 : 0 : return r;
1315 : : }
1316 : :
1317 [ # # ]: 0 : FOREACH_DEVICE(e, d) {
1318 [ # # ]: 0 : _cleanup_free_ char *t = NULL;
1319 : : const char *p;
1320 : :
1321 : 0 : r = sd_device_get_syspath(d, &p);
1322 [ # # ]: 0 : if (r < 0)
1323 : 0 : return r;
1324 : :
1325 : 0 : t = path_join(p, "uevent");
1326 [ # # ]: 0 : if (!t)
1327 : 0 : return -ENOMEM;
1328 : :
1329 : 0 : (void) write_string_file(t, "change", WRITE_STRING_FILE_DISABLE_BUFFER);
1330 : : }
1331 : :
1332 : 0 : return 0;
1333 : : }
1334 : :
1335 : 0 : static int attach_device(Manager *m, const char *seat, const char *sysfs) {
1336 : 0 : _cleanup_(sd_device_unrefp) sd_device *d = NULL;
1337 : 0 : _cleanup_free_ char *rule = NULL, *file = NULL;
1338 : : const char *id_for_seat;
1339 : : int r;
1340 : :
1341 [ # # ]: 0 : assert(m);
1342 [ # # ]: 0 : assert(seat);
1343 [ # # ]: 0 : assert(sysfs);
1344 : :
1345 : 0 : r = sd_device_new_from_syspath(&d, sysfs);
1346 [ # # ]: 0 : if (r < 0)
1347 : 0 : return r;
1348 : :
1349 [ # # ]: 0 : if (sd_device_has_tag(d, "seat") <= 0)
1350 : 0 : return -ENODEV;
1351 : :
1352 [ # # ]: 0 : if (sd_device_get_property_value(d, "ID_FOR_SEAT", &id_for_seat) < 0)
1353 : 0 : return -ENODEV;
1354 : :
1355 [ # # ]: 0 : if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0)
1356 : 0 : return -ENOMEM;
1357 : :
1358 [ # # ]: 0 : if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
1359 : 0 : return -ENOMEM;
1360 : :
1361 : 0 : (void) mkdir_p_label("/etc/udev/rules.d", 0755);
1362 : 0 : r = write_string_file_atomic_label(file, rule);
1363 [ # # ]: 0 : if (r < 0)
1364 : 0 : return r;
1365 : :
1366 : 0 : return trigger_device(m, d);
1367 : : }
1368 : :
1369 : 0 : static int flush_devices(Manager *m) {
1370 : 0 : _cleanup_closedir_ DIR *d;
1371 : :
1372 [ # # ]: 0 : assert(m);
1373 : :
1374 : 0 : d = opendir("/etc/udev/rules.d");
1375 [ # # ]: 0 : if (!d) {
1376 [ # # ]: 0 : if (errno != ENOENT)
1377 [ # # ]: 0 : log_warning_errno(errno, "Failed to open /etc/udev/rules.d: %m");
1378 : : } else {
1379 : : struct dirent *de;
1380 : :
1381 [ # # # # ]: 0 : FOREACH_DIRENT_ALL(de, d, break) {
1382 [ # # ]: 0 : if (!dirent_is_file(de))
1383 : 0 : continue;
1384 : :
1385 [ # # ]: 0 : if (!startswith(de->d_name, "72-seat-"))
1386 : 0 : continue;
1387 : :
1388 [ # # ]: 0 : if (!endswith(de->d_name, ".rules"))
1389 : 0 : continue;
1390 : :
1391 [ # # ]: 0 : if (unlinkat(dirfd(d), de->d_name, 0) < 0)
1392 [ # # ]: 0 : log_warning_errno(errno, "Failed to unlink %s: %m", de->d_name);
1393 : : }
1394 : : }
1395 : :
1396 : 0 : return trigger_device(m, NULL);
1397 : : }
1398 : :
1399 : 0 : static int method_attach_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1400 : : const char *sysfs, *seat;
1401 : 0 : Manager *m = userdata;
1402 : : int interactive, r;
1403 : :
1404 [ # # ]: 0 : assert(message);
1405 [ # # ]: 0 : assert(m);
1406 : :
1407 : 0 : r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
1408 [ # # ]: 0 : if (r < 0)
1409 : 0 : return r;
1410 : :
1411 [ # # ]: 0 : if (!path_is_normalized(sysfs))
1412 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not normalized", sysfs);
1413 [ # # ]: 0 : if (!path_startswith(sysfs, "/sys"))
1414 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
1415 : :
1416 [ # # # # ]: 0 : if (SEAT_IS_SELF(seat) || SEAT_IS_AUTO(seat)) {
1417 : : Seat *found;
1418 : :
1419 : 0 : r = manager_get_seat_from_creds(m, message, seat, error, &found);
1420 [ # # ]: 0 : if (r < 0)
1421 : 0 : return r;
1422 : :
1423 : 0 : seat = found->id;
1424 : :
1425 [ # # ]: 0 : } else if (!seat_name_is_valid(seat)) /* Note that a seat does not have to exist yet for this operation to succeed */
1426 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat name %s is not valid", seat);
1427 : :
1428 : 0 : r = bus_verify_polkit_async(
1429 : : message,
1430 : : CAP_SYS_ADMIN,
1431 : : "org.freedesktop.login1.attach-device",
1432 : : NULL,
1433 : : interactive,
1434 : : UID_INVALID,
1435 : : &m->polkit_registry,
1436 : : error);
1437 [ # # ]: 0 : if (r < 0)
1438 : 0 : return r;
1439 [ # # ]: 0 : if (r == 0)
1440 : 0 : return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1441 : :
1442 : 0 : r = attach_device(m, seat, sysfs);
1443 [ # # ]: 0 : if (r < 0)
1444 : 0 : return r;
1445 : :
1446 : 0 : return sd_bus_reply_method_return(message, NULL);
1447 : : }
1448 : :
1449 : 0 : static int method_flush_devices(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1450 : 0 : Manager *m = userdata;
1451 : : int interactive, r;
1452 : :
1453 [ # # ]: 0 : assert(message);
1454 [ # # ]: 0 : assert(m);
1455 : :
1456 : 0 : r = sd_bus_message_read(message, "b", &interactive);
1457 [ # # ]: 0 : if (r < 0)
1458 : 0 : return r;
1459 : :
1460 : 0 : r = bus_verify_polkit_async(
1461 : : message,
1462 : : CAP_SYS_ADMIN,
1463 : : "org.freedesktop.login1.flush-devices",
1464 : : NULL,
1465 : : interactive,
1466 : : UID_INVALID,
1467 : : &m->polkit_registry,
1468 : : error);
1469 [ # # ]: 0 : if (r < 0)
1470 : 0 : return r;
1471 [ # # ]: 0 : if (r == 0)
1472 : 0 : return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1473 : :
1474 : 0 : r = flush_devices(m);
1475 [ # # ]: 0 : if (r < 0)
1476 : 0 : return r;
1477 : :
1478 : 0 : return sd_bus_reply_method_return(message, NULL);
1479 : : }
1480 : :
1481 : 0 : static int have_multiple_sessions(
1482 : : Manager *m,
1483 : : uid_t uid) {
1484 : :
1485 : : Session *session;
1486 : : Iterator i;
1487 : :
1488 [ # # ]: 0 : assert(m);
1489 : :
1490 : : /* Check for other users' sessions. Greeter sessions do not
1491 : : * count, and non-login sessions do not count either. */
1492 [ # # ]: 0 : HASHMAP_FOREACH(session, m->sessions, i)
1493 [ # # ]: 0 : if (session->class == SESSION_USER &&
1494 [ # # ]: 0 : session->user->uid != uid)
1495 : 0 : return true;
1496 : :
1497 : 0 : return false;
1498 : : }
1499 : :
1500 : 0 : static int bus_manager_log_shutdown(
1501 : : Manager *m,
1502 : : const char *unit_name) {
1503 : :
1504 : : const char *p, *q;
1505 : :
1506 [ # # ]: 0 : assert(m);
1507 [ # # ]: 0 : assert(unit_name);
1508 : :
1509 [ # # ]: 0 : if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
1510 : 0 : p = "MESSAGE=System is powering down";
1511 : 0 : q = "SHUTDOWN=power-off";
1512 [ # # ]: 0 : } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
1513 : 0 : p = "MESSAGE=System is rebooting";
1514 : 0 : q = "SHUTDOWN=reboot";
1515 [ # # ]: 0 : } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
1516 : 0 : p = "MESSAGE=System is halting";
1517 : 0 : q = "SHUTDOWN=halt";
1518 [ # # ]: 0 : } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
1519 : 0 : p = "MESSAGE=System is rebooting with kexec";
1520 : 0 : q = "SHUTDOWN=kexec";
1521 : : } else {
1522 : 0 : p = "MESSAGE=System is shutting down";
1523 : 0 : q = NULL;
1524 : : }
1525 : :
1526 [ # # ]: 0 : if (isempty(m->wall_message))
1527 [ # # # # : 0 : p = strjoina(p, ".");
# # # # #
# # # ]
1528 : : else
1529 [ # # # # : 0 : p = strjoina(p, " (", m->wall_message, ").");
# # # # #
# # # ]
1530 : :
1531 : 0 : return log_struct(LOG_NOTICE,
1532 : : "MESSAGE_ID=" SD_MESSAGE_SHUTDOWN_STR,
1533 : : p,
1534 : : q);
1535 : : }
1536 : :
1537 : 0 : static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
1538 : 0 : Manager *m = userdata;
1539 : :
1540 [ # # ]: 0 : assert(e);
1541 [ # # ]: 0 : assert(m);
1542 : :
1543 : 0 : m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source);
1544 : 0 : return 0;
1545 : : }
1546 : :
1547 : 0 : int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
1548 : : int r;
1549 : :
1550 [ # # ]: 0 : assert(m);
1551 : :
1552 [ # # ]: 0 : if (until <= now(CLOCK_MONOTONIC))
1553 : 0 : return 0;
1554 : :
1555 : : /* We want to ignore the lid switch for a while after each
1556 : : * suspend, and after boot-up. Hence let's install a timer for
1557 : : * this. As long as the event source exists we ignore the lid
1558 : : * switch. */
1559 : :
1560 [ # # ]: 0 : if (m->lid_switch_ignore_event_source) {
1561 : : usec_t u;
1562 : :
1563 : 0 : r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u);
1564 [ # # ]: 0 : if (r < 0)
1565 : 0 : return r;
1566 : :
1567 [ # # ]: 0 : if (until <= u)
1568 : 0 : return 0;
1569 : :
1570 : 0 : r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until);
1571 : : } else
1572 : 0 : r = sd_event_add_time(
1573 : : m->event,
1574 : : &m->lid_switch_ignore_event_source,
1575 : : CLOCK_MONOTONIC,
1576 : : until, 0,
1577 : : lid_switch_ignore_handler, m);
1578 : :
1579 : 0 : return r;
1580 : : }
1581 : :
1582 : 0 : static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1583 : 0 : int active = _active;
1584 : :
1585 [ # # ]: 0 : assert(m);
1586 [ # # # # ]: 0 : assert(IN_SET(w, INHIBIT_SHUTDOWN, INHIBIT_SLEEP));
1587 : :
1588 [ # # ]: 0 : return sd_bus_emit_signal(m->bus,
1589 : : "/org/freedesktop/login1",
1590 : : "org.freedesktop.login1.Manager",
1591 : : w == INHIBIT_SHUTDOWN ? "PrepareForShutdown" : "PrepareForSleep",
1592 : : "b",
1593 : : active);
1594 : : }
1595 : :
1596 : 0 : static int execute_shutdown_or_sleep(
1597 : : Manager *m,
1598 : : InhibitWhat w,
1599 : : const char *unit_name,
1600 : : sd_bus_error *error) {
1601 : :
1602 : 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1603 : : const char *p;
1604 : : int r;
1605 : :
1606 [ # # ]: 0 : assert(m);
1607 [ # # ]: 0 : assert(w > 0);
1608 [ # # ]: 0 : assert(w < _INHIBIT_WHAT_MAX);
1609 [ # # ]: 0 : assert(unit_name);
1610 : :
1611 [ # # ]: 0 : if (w == INHIBIT_SHUTDOWN)
1612 : 0 : bus_manager_log_shutdown(m, unit_name);
1613 : :
1614 : 0 : r = sd_bus_call_method(
1615 : : m->bus,
1616 : : "org.freedesktop.systemd1",
1617 : : "/org/freedesktop/systemd1",
1618 : : "org.freedesktop.systemd1.Manager",
1619 : : "StartUnit",
1620 : : error,
1621 : : &reply,
1622 : : "ss", unit_name, "replace-irreversibly");
1623 [ # # ]: 0 : if (r < 0)
1624 : 0 : goto error;
1625 : :
1626 : 0 : r = sd_bus_message_read(reply, "o", &p);
1627 [ # # ]: 0 : if (r < 0)
1628 : 0 : goto error;
1629 : :
1630 : 0 : r = free_and_strdup(&m->action_job, p);
1631 [ # # ]: 0 : if (r < 0)
1632 : 0 : goto error;
1633 : :
1634 : 0 : m->action_unit = unit_name;
1635 : 0 : m->action_what = w;
1636 : :
1637 : : /* Make sure the lid switch is ignored for a while */
1638 : 0 : manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec);
1639 : :
1640 : 0 : return 0;
1641 : :
1642 : 0 : error:
1643 : : /* Tell people that they now may take a lock again */
1644 : 0 : (void) send_prepare_for(m, w, false);
1645 : :
1646 : 0 : return r;
1647 : : }
1648 : :
1649 : 0 : int manager_dispatch_delayed(Manager *manager, bool timeout) {
1650 : :
1651 : 0 : _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1652 : 0 : Inhibitor *offending = NULL;
1653 : : int r;
1654 : :
1655 [ # # ]: 0 : assert(manager);
1656 : :
1657 [ # # # # ]: 0 : if (manager->action_what == 0 || manager->action_job)
1658 : 0 : return 0;
1659 : :
1660 [ # # ]: 0 : if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
1661 [ # # # # ]: 0 : _cleanup_free_ char *comm = NULL, *u = NULL;
1662 : :
1663 [ # # ]: 0 : if (!timeout)
1664 : 0 : return 0;
1665 : :
1666 : 0 : (void) get_process_comm(offending->pid, &comm);
1667 : 0 : u = uid_to_name(offending->uid);
1668 : :
1669 [ # # ]: 0 : log_notice("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
1670 : : offending->uid, strna(u),
1671 : : offending->pid, strna(comm));
1672 : : }
1673 : :
1674 : : /* Actually do the operation */
1675 : 0 : r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
1676 [ # # ]: 0 : if (r < 0) {
1677 [ # # ]: 0 : log_warning("Error during inhibitor-delayed operation (already returned success to client): %s",
1678 : : bus_error_message(&error, r));
1679 : :
1680 : 0 : manager->action_unit = NULL;
1681 : 0 : manager->action_what = 0;
1682 : 0 : return r;
1683 : : }
1684 : :
1685 : 0 : return 1;
1686 : : }
1687 : :
1688 : 0 : static int manager_inhibit_timeout_handler(
1689 : : sd_event_source *s,
1690 : : uint64_t usec,
1691 : : void *userdata) {
1692 : :
1693 : 0 : Manager *manager = userdata;
1694 : : int r;
1695 : :
1696 [ # # ]: 0 : assert(manager);
1697 [ # # ]: 0 : assert(manager->inhibit_timeout_source == s);
1698 : :
1699 : 0 : r = manager_dispatch_delayed(manager, true);
1700 : 0 : return (r < 0) ? r : 0;
1701 : : }
1702 : :
1703 : 0 : static int delay_shutdown_or_sleep(
1704 : : Manager *m,
1705 : : InhibitWhat w,
1706 : : const char *unit_name) {
1707 : :
1708 : : int r;
1709 : : usec_t timeout_val;
1710 : :
1711 [ # # ]: 0 : assert(m);
1712 [ # # ]: 0 : assert(w >= 0);
1713 [ # # ]: 0 : assert(w < _INHIBIT_WHAT_MAX);
1714 [ # # ]: 0 : assert(unit_name);
1715 : :
1716 : 0 : timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max;
1717 : :
1718 [ # # ]: 0 : if (m->inhibit_timeout_source) {
1719 : 0 : r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val);
1720 [ # # ]: 0 : if (r < 0)
1721 [ # # ]: 0 : return log_error_errno(r, "sd_event_source_set_time() failed: %m");
1722 : :
1723 : 0 : r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT);
1724 [ # # ]: 0 : if (r < 0)
1725 [ # # ]: 0 : return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
1726 : : } else {
1727 : 0 : r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC,
1728 : : timeout_val, 0, manager_inhibit_timeout_handler, m);
1729 [ # # ]: 0 : if (r < 0)
1730 : 0 : return r;
1731 : : }
1732 : :
1733 : 0 : m->action_unit = unit_name;
1734 : 0 : m->action_what = w;
1735 : :
1736 : 0 : return 0;
1737 : : }
1738 : :
1739 : 0 : int bus_manager_shutdown_or_sleep_now_or_later(
1740 : : Manager *m,
1741 : : const char *unit_name,
1742 : : InhibitWhat w,
1743 : : sd_bus_error *error) {
1744 : :
1745 : 0 : _cleanup_free_ char *load_state = NULL;
1746 : : bool delayed;
1747 : : int r;
1748 : :
1749 [ # # ]: 0 : assert(m);
1750 [ # # ]: 0 : assert(unit_name);
1751 [ # # ]: 0 : assert(w > 0);
1752 [ # # ]: 0 : assert(w < _INHIBIT_WHAT_MAX);
1753 [ # # ]: 0 : assert(!m->action_job);
1754 : :
1755 : 0 : r = unit_load_state(m->bus, unit_name, &load_state);
1756 [ # # ]: 0 : if (r < 0)
1757 : 0 : return r;
1758 : :
1759 [ # # ]: 0 : if (!streq(load_state, "loaded"))
1760 [ # # ]: 0 : return log_notice_errno(SYNTHETIC_ERRNO(EACCES),
1761 : : "Unit %s is %s, refusing operation.",
1762 : : unit_name, load_state);
1763 : :
1764 : : /* Tell everybody to prepare for shutdown/sleep */
1765 : 0 : (void) send_prepare_for(m, w, true);
1766 : :
1767 : 0 : delayed =
1768 [ # # # # ]: 0 : m->inhibit_delay_max > 0 &&
1769 : 0 : manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
1770 : :
1771 [ # # ]: 0 : if (delayed)
1772 : : /* Shutdown is delayed, keep in mind what we
1773 : : * want to do, and start a timeout */
1774 : 0 : r = delay_shutdown_or_sleep(m, w, unit_name);
1775 : : else
1776 : : /* Shutdown is not delayed, execute it
1777 : : * immediately */
1778 : 0 : r = execute_shutdown_or_sleep(m, w, unit_name, error);
1779 : :
1780 : 0 : return r;
1781 : : }
1782 : :
1783 : 0 : static int verify_shutdown_creds(
1784 : : Manager *m,
1785 : : sd_bus_message *message,
1786 : : InhibitWhat w,
1787 : : bool interactive,
1788 : : const char *action,
1789 : : const char *action_multiple_sessions,
1790 : : const char *action_ignore_inhibit,
1791 : : sd_bus_error *error) {
1792 : :
1793 : 0 : _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
1794 : : bool multiple_sessions, blocked;
1795 : : uid_t uid;
1796 : : int r;
1797 : :
1798 [ # # ]: 0 : assert(m);
1799 [ # # ]: 0 : assert(message);
1800 [ # # ]: 0 : assert(w >= 0);
1801 [ # # ]: 0 : assert(w <= _INHIBIT_WHAT_MAX);
1802 : :
1803 : 0 : r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1804 [ # # ]: 0 : if (r < 0)
1805 : 0 : return r;
1806 : :
1807 : 0 : r = sd_bus_creds_get_euid(creds, &uid);
1808 [ # # ]: 0 : if (r < 0)
1809 : 0 : return r;
1810 : :
1811 : 0 : r = have_multiple_sessions(m, uid);
1812 [ # # ]: 0 : if (r < 0)
1813 : 0 : return r;
1814 : :
1815 : 0 : multiple_sessions = r > 0;
1816 : 0 : blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1817 : :
1818 [ # # # # ]: 0 : if (multiple_sessions && action_multiple_sessions) {
1819 : 0 : r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1820 [ # # ]: 0 : if (r < 0)
1821 : 0 : return r;
1822 [ # # ]: 0 : if (r == 0)
1823 : 0 : return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1824 : : }
1825 : :
1826 [ # # # # ]: 0 : if (blocked && action_ignore_inhibit) {
1827 : 0 : r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1828 [ # # ]: 0 : if (r < 0)
1829 : 0 : return r;
1830 [ # # ]: 0 : if (r == 0)
1831 : 0 : return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1832 : : }
1833 : :
1834 [ # # # # : 0 : if (!multiple_sessions && !blocked && action) {
# # ]
1835 : 0 : r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1836 [ # # ]: 0 : if (r < 0)
1837 : 0 : return r;
1838 [ # # ]: 0 : if (r == 0)
1839 : 0 : return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1840 : : }
1841 : :
1842 : 0 : return 0;
1843 : : }
1844 : :
1845 : 0 : static int method_do_shutdown_or_sleep(
1846 : : Manager *m,
1847 : : sd_bus_message *message,
1848 : : const char *unit_name,
1849 : : InhibitWhat w,
1850 : : const char *action,
1851 : : const char *action_multiple_sessions,
1852 : : const char *action_ignore_inhibit,
1853 : : const char *sleep_verb,
1854 : : sd_bus_error *error) {
1855 : :
1856 : : int interactive, r;
1857 : :
1858 [ # # ]: 0 : assert(m);
1859 [ # # ]: 0 : assert(message);
1860 [ # # ]: 0 : assert(unit_name);
1861 [ # # ]: 0 : assert(w >= 0);
1862 [ # # ]: 0 : assert(w <= _INHIBIT_WHAT_MAX);
1863 : :
1864 : 0 : r = sd_bus_message_read(message, "b", &interactive);
1865 [ # # ]: 0 : if (r < 0)
1866 : 0 : return r;
1867 : :
1868 : : /* Don't allow multiple jobs being executed at the same time */
1869 [ # # ]: 0 : if (m->action_what > 0)
1870 : 0 : return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS,
1871 : : "There's already a shutdown or sleep operation in progress");
1872 : :
1873 [ # # ]: 0 : if (sleep_verb) {
1874 : 0 : r = can_sleep(sleep_verb);
1875 [ # # ]: 0 : if (r == -ENOSPC)
1876 : 0 : return sd_bus_error_set(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED,
1877 : : "Not enough swap space for hibernation");
1878 [ # # ]: 0 : if (r == 0)
1879 : 0 : return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED,
1880 : : "Sleep verb \"%s\" not supported", sleep_verb);
1881 [ # # ]: 0 : if (r < 0)
1882 : 0 : return r;
1883 : : }
1884 : :
1885 : 0 : r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
1886 : : action_ignore_inhibit, error);
1887 [ # # ]: 0 : if (r != 0)
1888 : 0 : return r;
1889 : :
1890 : 0 : r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
1891 [ # # ]: 0 : if (r < 0)
1892 : 0 : return r;
1893 : :
1894 : 0 : return sd_bus_reply_method_return(message, NULL);
1895 : : }
1896 : :
1897 : 0 : static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1898 : 0 : Manager *m = userdata;
1899 : :
1900 : 0 : return method_do_shutdown_or_sleep(
1901 : : m, message,
1902 : : SPECIAL_POWEROFF_TARGET,
1903 : : INHIBIT_SHUTDOWN,
1904 : : "org.freedesktop.login1.power-off",
1905 : : "org.freedesktop.login1.power-off-multiple-sessions",
1906 : : "org.freedesktop.login1.power-off-ignore-inhibit",
1907 : : NULL,
1908 : : error);
1909 : : }
1910 : :
1911 : 0 : static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1912 : 0 : Manager *m = userdata;
1913 : :
1914 : 0 : return method_do_shutdown_or_sleep(
1915 : : m, message,
1916 : : SPECIAL_REBOOT_TARGET,
1917 : : INHIBIT_SHUTDOWN,
1918 : : "org.freedesktop.login1.reboot",
1919 : : "org.freedesktop.login1.reboot-multiple-sessions",
1920 : : "org.freedesktop.login1.reboot-ignore-inhibit",
1921 : : NULL,
1922 : : error);
1923 : : }
1924 : :
1925 : 0 : static int method_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1926 : 0 : Manager *m = userdata;
1927 : :
1928 : 0 : return method_do_shutdown_or_sleep(
1929 : : m, message,
1930 : : SPECIAL_HALT_TARGET,
1931 : : INHIBIT_SHUTDOWN,
1932 : : "org.freedesktop.login1.halt",
1933 : : "org.freedesktop.login1.halt-multiple-sessions",
1934 : : "org.freedesktop.login1.halt-ignore-inhibit",
1935 : : NULL,
1936 : : error);
1937 : : }
1938 : :
1939 : 0 : static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1940 : 0 : Manager *m = userdata;
1941 : :
1942 : 0 : return method_do_shutdown_or_sleep(
1943 : : m, message,
1944 : : SPECIAL_SUSPEND_TARGET,
1945 : : INHIBIT_SLEEP,
1946 : : "org.freedesktop.login1.suspend",
1947 : : "org.freedesktop.login1.suspend-multiple-sessions",
1948 : : "org.freedesktop.login1.suspend-ignore-inhibit",
1949 : : "suspend",
1950 : : error);
1951 : : }
1952 : :
1953 : 0 : static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1954 : 0 : Manager *m = userdata;
1955 : :
1956 : 0 : return method_do_shutdown_or_sleep(
1957 : : m, message,
1958 : : SPECIAL_HIBERNATE_TARGET,
1959 : : INHIBIT_SLEEP,
1960 : : "org.freedesktop.login1.hibernate",
1961 : : "org.freedesktop.login1.hibernate-multiple-sessions",
1962 : : "org.freedesktop.login1.hibernate-ignore-inhibit",
1963 : : "hibernate",
1964 : : error);
1965 : : }
1966 : :
1967 : 0 : static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1968 : 0 : Manager *m = userdata;
1969 : :
1970 : 0 : return method_do_shutdown_or_sleep(
1971 : : m, message,
1972 : : SPECIAL_HYBRID_SLEEP_TARGET,
1973 : : INHIBIT_SLEEP,
1974 : : "org.freedesktop.login1.hibernate",
1975 : : "org.freedesktop.login1.hibernate-multiple-sessions",
1976 : : "org.freedesktop.login1.hibernate-ignore-inhibit",
1977 : : "hybrid-sleep",
1978 : : error);
1979 : : }
1980 : :
1981 : 0 : static int method_suspend_then_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1982 : 0 : Manager *m = userdata;
1983 : :
1984 : 0 : return method_do_shutdown_or_sleep(
1985 : : m, message,
1986 : : SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET,
1987 : : INHIBIT_SLEEP,
1988 : : "org.freedesktop.login1.hibernate",
1989 : : "org.freedesktop.login1.hibernate-multiple-sessions",
1990 : : "org.freedesktop.login1.hibernate-ignore-inhibit",
1991 : : "hybrid-sleep",
1992 : : error);
1993 : : }
1994 : :
1995 : 0 : static int nologin_timeout_handler(
1996 : : sd_event_source *s,
1997 : : uint64_t usec,
1998 : : void *userdata) {
1999 : :
2000 : 0 : Manager *m = userdata;
2001 : :
2002 [ # # ]: 0 : log_info("Creating /run/nologin, blocking further logins...");
2003 : :
2004 : 0 : m->unlink_nologin =
2005 : 0 : create_shutdown_run_nologin_or_warn() >= 0;
2006 : :
2007 : 0 : return 0;
2008 : : }
2009 : :
2010 : 0 : static int update_schedule_file(Manager *m) {
2011 : 0 : _cleanup_free_ char *temp_path = NULL;
2012 : 0 : _cleanup_fclose_ FILE *f = NULL;
2013 : : int r;
2014 : :
2015 [ # # ]: 0 : assert(m);
2016 : :
2017 : 0 : r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0, MKDIR_WARN_MODE);
2018 [ # # ]: 0 : if (r < 0)
2019 [ # # ]: 0 : return log_error_errno(r, "Failed to create shutdown subdirectory: %m");
2020 : :
2021 : 0 : r = fopen_temporary("/run/systemd/shutdown/scheduled", &f, &temp_path);
2022 [ # # ]: 0 : if (r < 0)
2023 [ # # ]: 0 : return log_error_errno(r, "Failed to save information about scheduled shutdowns: %m");
2024 : :
2025 : 0 : (void) fchmod(fileno(f), 0644);
2026 : :
2027 : 0 : fprintf(f,
2028 : : "USEC="USEC_FMT"\n"
2029 : : "WARN_WALL=%i\n"
2030 : : "MODE=%s\n",
2031 : : m->scheduled_shutdown_timeout,
2032 : : m->enable_wall_messages,
2033 : : m->scheduled_shutdown_type);
2034 : :
2035 [ # # ]: 0 : if (!isempty(m->wall_message)) {
2036 [ # # ]: 0 : _cleanup_free_ char *t;
2037 : :
2038 : 0 : t = cescape(m->wall_message);
2039 [ # # ]: 0 : if (!t) {
2040 : 0 : r = -ENOMEM;
2041 : 0 : goto fail;
2042 : : }
2043 : :
2044 : 0 : fprintf(f, "WALL_MESSAGE=%s\n", t);
2045 : : }
2046 : :
2047 : 0 : r = fflush_and_check(f);
2048 [ # # ]: 0 : if (r < 0)
2049 : 0 : goto fail;
2050 : :
2051 [ # # ]: 0 : if (rename(temp_path, "/run/systemd/shutdown/scheduled") < 0) {
2052 : 0 : r = -errno;
2053 : 0 : goto fail;
2054 : : }
2055 : :
2056 : 0 : return 0;
2057 : :
2058 : 0 : fail:
2059 : 0 : (void) unlink(temp_path);
2060 : 0 : (void) unlink("/run/systemd/shutdown/scheduled");
2061 : :
2062 [ # # ]: 0 : return log_error_errno(r, "Failed to write information about scheduled shutdowns: %m");
2063 : : }
2064 : :
2065 : 0 : static void reset_scheduled_shutdown(Manager *m) {
2066 [ # # ]: 0 : assert(m);
2067 : :
2068 : 0 : m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2069 : 0 : m->wall_message_timeout_source = sd_event_source_unref(m->wall_message_timeout_source);
2070 : 0 : m->nologin_timeout_source = sd_event_source_unref(m->nologin_timeout_source);
2071 : :
2072 : 0 : m->scheduled_shutdown_type = mfree(m->scheduled_shutdown_type);
2073 : 0 : m->scheduled_shutdown_timeout = 0;
2074 : 0 : m->shutdown_dry_run = false;
2075 : :
2076 [ # # ]: 0 : if (m->unlink_nologin) {
2077 : 0 : (void) unlink_or_warn("/run/nologin");
2078 : 0 : m->unlink_nologin = false;
2079 : : }
2080 : :
2081 : 0 : (void) unlink("/run/systemd/shutdown/scheduled");
2082 : 0 : }
2083 : :
2084 : 0 : static int manager_scheduled_shutdown_handler(
2085 : : sd_event_source *s,
2086 : : uint64_t usec,
2087 : : void *userdata) {
2088 : :
2089 : 0 : _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2090 : 0 : Manager *m = userdata;
2091 : : const char *target;
2092 : : int r;
2093 : :
2094 [ # # ]: 0 : assert(m);
2095 : :
2096 [ # # ]: 0 : if (isempty(m->scheduled_shutdown_type))
2097 : 0 : return 0;
2098 : :
2099 [ # # ]: 0 : if (streq(m->scheduled_shutdown_type, "poweroff"))
2100 : 0 : target = SPECIAL_POWEROFF_TARGET;
2101 [ # # ]: 0 : else if (streq(m->scheduled_shutdown_type, "reboot"))
2102 : 0 : target = SPECIAL_REBOOT_TARGET;
2103 [ # # ]: 0 : else if (streq(m->scheduled_shutdown_type, "halt"))
2104 : 0 : target = SPECIAL_HALT_TARGET;
2105 : : else
2106 : 0 : assert_not_reached("unexpected shutdown type");
2107 : :
2108 : : /* Don't allow multiple jobs being executed at the same time */
2109 [ # # ]: 0 : if (m->action_what > 0) {
2110 : 0 : r = -EALREADY;
2111 [ # # ]: 0 : log_error("Scheduled shutdown to %s failed: shutdown or sleep operation already in progress", target);
2112 : 0 : goto error;
2113 : : }
2114 : :
2115 [ # # ]: 0 : if (m->shutdown_dry_run) {
2116 : : /* We do not process delay inhibitors here. Otherwise, we
2117 : : * would have to be considered "in progress" (like the check
2118 : : * above) for some seconds after our admin has seen the final
2119 : : * wall message. */
2120 : :
2121 : 0 : bus_manager_log_shutdown(m, target);
2122 [ # # ]: 0 : log_info("Running in dry run, suppressing action.");
2123 : 0 : reset_scheduled_shutdown(m);
2124 : :
2125 : 0 : return 0;
2126 : : }
2127 : :
2128 : 0 : r = bus_manager_shutdown_or_sleep_now_or_later(m, target, INHIBIT_SHUTDOWN, &error);
2129 [ # # ]: 0 : if (r < 0) {
2130 [ # # ]: 0 : log_error_errno(r, "Scheduled shutdown to %s failed: %m", target);
2131 : 0 : goto error;
2132 : : }
2133 : :
2134 : 0 : return 0;
2135 : :
2136 : 0 : error:
2137 : 0 : reset_scheduled_shutdown(m);
2138 : 0 : return r;
2139 : : }
2140 : :
2141 : 0 : static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2142 : 0 : Manager *m = userdata;
2143 : 0 : _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2144 : 0 : const char *action_multiple_sessions = NULL;
2145 : 0 : const char *action_ignore_inhibit = NULL;
2146 : 0 : const char *action = NULL;
2147 : : uint64_t elapse;
2148 : : char *type;
2149 : : int r;
2150 : 0 : bool dry_run = false;
2151 : :
2152 [ # # ]: 0 : assert(m);
2153 [ # # ]: 0 : assert(message);
2154 : :
2155 : 0 : r = sd_bus_message_read(message, "st", &type, &elapse);
2156 [ # # ]: 0 : if (r < 0)
2157 : 0 : return r;
2158 : :
2159 [ # # ]: 0 : if (startswith(type, "dry-")) {
2160 : 0 : type += 4;
2161 : 0 : dry_run = true;
2162 : : }
2163 : :
2164 [ # # ]: 0 : if (streq(type, "poweroff")) {
2165 : 0 : action = "org.freedesktop.login1.power-off";
2166 : 0 : action_multiple_sessions = "org.freedesktop.login1.power-off-multiple-sessions";
2167 : 0 : action_ignore_inhibit = "org.freedesktop.login1.power-off-ignore-inhibit";
2168 [ # # ]: 0 : } else if (streq(type, "reboot")) {
2169 : 0 : action = "org.freedesktop.login1.reboot";
2170 : 0 : action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions";
2171 : 0 : action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit";
2172 [ # # ]: 0 : } else if (streq(type, "halt")) {
2173 : 0 : action = "org.freedesktop.login1.halt";
2174 : 0 : action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions";
2175 : 0 : action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit";
2176 : : } else
2177 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
2178 : :
2179 : 0 : r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, false,
2180 : : action, action_multiple_sessions, action_ignore_inhibit, error);
2181 [ # # ]: 0 : if (r != 0)
2182 : 0 : return r;
2183 : :
2184 [ # # ]: 0 : if (m->scheduled_shutdown_timeout_source) {
2185 : 0 : r = sd_event_source_set_time(m->scheduled_shutdown_timeout_source, elapse);
2186 [ # # ]: 0 : if (r < 0)
2187 [ # # ]: 0 : return log_error_errno(r, "sd_event_source_set_time() failed: %m");
2188 : :
2189 : 0 : r = sd_event_source_set_enabled(m->scheduled_shutdown_timeout_source, SD_EVENT_ONESHOT);
2190 [ # # ]: 0 : if (r < 0)
2191 [ # # ]: 0 : return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
2192 : : } else {
2193 : 0 : r = sd_event_add_time(m->event, &m->scheduled_shutdown_timeout_source,
2194 : : CLOCK_REALTIME, elapse, 0, manager_scheduled_shutdown_handler, m);
2195 [ # # ]: 0 : if (r < 0)
2196 [ # # ]: 0 : return log_error_errno(r, "sd_event_add_time() failed: %m");
2197 : : }
2198 : :
2199 : 0 : r = free_and_strdup(&m->scheduled_shutdown_type, type);
2200 [ # # ]: 0 : if (r < 0) {
2201 : 0 : m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2202 : 0 : return log_oom();
2203 : : }
2204 : :
2205 : 0 : m->shutdown_dry_run = dry_run;
2206 : :
2207 [ # # ]: 0 : if (m->nologin_timeout_source) {
2208 : 0 : r = sd_event_source_set_time(m->nologin_timeout_source, elapse);
2209 [ # # ]: 0 : if (r < 0)
2210 [ # # ]: 0 : return log_error_errno(r, "sd_event_source_set_time() failed: %m");
2211 : :
2212 : 0 : r = sd_event_source_set_enabled(m->nologin_timeout_source, SD_EVENT_ONESHOT);
2213 [ # # ]: 0 : if (r < 0)
2214 [ # # ]: 0 : return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
2215 : : } else {
2216 : 0 : r = sd_event_add_time(m->event, &m->nologin_timeout_source,
2217 : : CLOCK_REALTIME, elapse - 5 * USEC_PER_MINUTE, 0, nologin_timeout_handler, m);
2218 [ # # ]: 0 : if (r < 0)
2219 [ # # ]: 0 : return log_error_errno(r, "sd_event_add_time() failed: %m");
2220 : : }
2221 : :
2222 : 0 : m->scheduled_shutdown_timeout = elapse;
2223 : :
2224 : 0 : r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
2225 [ # # ]: 0 : if (r >= 0) {
2226 : 0 : const char *tty = NULL;
2227 : :
2228 : 0 : (void) sd_bus_creds_get_uid(creds, &m->scheduled_shutdown_uid);
2229 : 0 : (void) sd_bus_creds_get_tty(creds, &tty);
2230 : :
2231 : 0 : r = free_and_strdup(&m->scheduled_shutdown_tty, tty);
2232 [ # # ]: 0 : if (r < 0) {
2233 : 0 : m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2234 : 0 : return log_oom();
2235 : : }
2236 : : }
2237 : :
2238 : 0 : r = manager_setup_wall_message_timer(m);
2239 [ # # ]: 0 : if (r < 0)
2240 : 0 : return r;
2241 : :
2242 : 0 : r = update_schedule_file(m);
2243 [ # # ]: 0 : if (r < 0)
2244 : 0 : return r;
2245 : :
2246 : 0 : return sd_bus_reply_method_return(message, NULL);
2247 : : }
2248 : :
2249 : 0 : static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2250 : 0 : Manager *m = userdata;
2251 : : bool cancelled;
2252 : :
2253 [ # # ]: 0 : assert(m);
2254 [ # # ]: 0 : assert(message);
2255 : :
2256 : 0 : cancelled = m->scheduled_shutdown_type != NULL;
2257 : 0 : reset_scheduled_shutdown(m);
2258 : :
2259 [ # # # # ]: 0 : if (cancelled && m->enable_wall_messages) {
2260 : 0 : _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2261 : 0 : _cleanup_free_ char *username = NULL;
2262 : 0 : const char *tty = NULL;
2263 : 0 : uid_t uid = 0;
2264 : : int r;
2265 : :
2266 : 0 : r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
2267 [ # # ]: 0 : if (r >= 0) {
2268 : 0 : (void) sd_bus_creds_get_uid(creds, &uid);
2269 : 0 : (void) sd_bus_creds_get_tty(creds, &tty);
2270 : : }
2271 : :
2272 : 0 : username = uid_to_name(uid);
2273 : 0 : utmp_wall("The system shutdown has been cancelled",
2274 : : username, tty, logind_wall_tty_filter, m);
2275 : : }
2276 : :
2277 : 0 : return sd_bus_reply_method_return(message, "b", cancelled);
2278 : : }
2279 : :
2280 : 0 : static int method_can_shutdown_or_sleep(
2281 : : Manager *m,
2282 : : sd_bus_message *message,
2283 : : InhibitWhat w,
2284 : : const char *action,
2285 : : const char *action_multiple_sessions,
2286 : : const char *action_ignore_inhibit,
2287 : : const char *sleep_verb,
2288 : : sd_bus_error *error) {
2289 : :
2290 : 0 : _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2291 : : HandleAction handle;
2292 : : bool multiple_sessions, challenge, blocked;
2293 : 0 : const char *result = NULL;
2294 : : uid_t uid;
2295 : : int r;
2296 : :
2297 [ # # ]: 0 : assert(m);
2298 [ # # ]: 0 : assert(message);
2299 [ # # ]: 0 : assert(w >= 0);
2300 [ # # ]: 0 : assert(w <= _INHIBIT_WHAT_MAX);
2301 [ # # ]: 0 : assert(action);
2302 [ # # ]: 0 : assert(action_multiple_sessions);
2303 [ # # ]: 0 : assert(action_ignore_inhibit);
2304 : :
2305 [ # # ]: 0 : if (sleep_verb) {
2306 : 0 : r = can_sleep(sleep_verb);
2307 [ # # # # ]: 0 : if (IN_SET(r, 0, -ENOSPC))
2308 : 0 : return sd_bus_reply_method_return(message, "s", "na");
2309 [ # # ]: 0 : if (r < 0)
2310 : 0 : return r;
2311 : : }
2312 : :
2313 : 0 : r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
2314 [ # # ]: 0 : if (r < 0)
2315 : 0 : return r;
2316 : :
2317 : 0 : r = sd_bus_creds_get_euid(creds, &uid);
2318 [ # # ]: 0 : if (r < 0)
2319 : 0 : return r;
2320 : :
2321 : 0 : r = have_multiple_sessions(m, uid);
2322 [ # # ]: 0 : if (r < 0)
2323 : 0 : return r;
2324 : :
2325 : 0 : multiple_sessions = r > 0;
2326 : 0 : blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
2327 : :
2328 : 0 : handle = handle_action_from_string(sleep_verb);
2329 [ # # ]: 0 : if (handle >= 0) {
2330 : : const char *target;
2331 : :
2332 : 0 : target = manager_target_for_action(handle);
2333 [ # # ]: 0 : if (target) {
2334 [ # # # ]: 0 : _cleanup_free_ char *load_state = NULL;
2335 : :
2336 : 0 : r = unit_load_state(m->bus, target, &load_state);
2337 [ # # ]: 0 : if (r < 0)
2338 : 0 : return r;
2339 : :
2340 [ # # ]: 0 : if (!streq(load_state, "loaded")) {
2341 : 0 : result = "no";
2342 : 0 : goto finish;
2343 : : }
2344 : : }
2345 : : }
2346 : :
2347 [ # # ]: 0 : if (multiple_sessions) {
2348 : 0 : r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, UID_INVALID, &challenge, error);
2349 [ # # ]: 0 : if (r < 0)
2350 : 0 : return r;
2351 : :
2352 [ # # ]: 0 : if (r > 0)
2353 : 0 : result = "yes";
2354 [ # # ]: 0 : else if (challenge)
2355 : 0 : result = "challenge";
2356 : : else
2357 : 0 : result = "no";
2358 : : }
2359 : :
2360 [ # # ]: 0 : if (blocked) {
2361 : 0 : r = bus_test_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, UID_INVALID, &challenge, error);
2362 [ # # ]: 0 : if (r < 0)
2363 : 0 : return r;
2364 : :
2365 [ # # ]: 0 : if (r > 0) {
2366 [ # # ]: 0 : if (!result)
2367 : 0 : result = "yes";
2368 [ # # ]: 0 : } else if (challenge) {
2369 [ # # # # ]: 0 : if (!result || streq(result, "yes"))
2370 : 0 : result = "challenge";
2371 : : } else
2372 : 0 : result = "no";
2373 : : }
2374 : :
2375 [ # # # # ]: 0 : if (!multiple_sessions && !blocked) {
2376 : : /* If neither inhibit nor multiple sessions
2377 : : * apply then just check the normal policy */
2378 : :
2379 : 0 : r = bus_test_polkit(message, CAP_SYS_BOOT, action, NULL, UID_INVALID, &challenge, error);
2380 [ # # ]: 0 : if (r < 0)
2381 : 0 : return r;
2382 : :
2383 [ # # ]: 0 : if (r > 0)
2384 : 0 : result = "yes";
2385 [ # # ]: 0 : else if (challenge)
2386 : 0 : result = "challenge";
2387 : : else
2388 : 0 : result = "no";
2389 : : }
2390 : :
2391 : 0 : finish:
2392 : 0 : return sd_bus_reply_method_return(message, "s", result);
2393 : : }
2394 : :
2395 : 0 : static int method_can_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2396 : 0 : Manager *m = userdata;
2397 : :
2398 : 0 : return method_can_shutdown_or_sleep(
2399 : : m, message,
2400 : : INHIBIT_SHUTDOWN,
2401 : : "org.freedesktop.login1.power-off",
2402 : : "org.freedesktop.login1.power-off-multiple-sessions",
2403 : : "org.freedesktop.login1.power-off-ignore-inhibit",
2404 : : NULL,
2405 : : error);
2406 : : }
2407 : :
2408 : 0 : static int method_can_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2409 : 0 : Manager *m = userdata;
2410 : :
2411 : 0 : return method_can_shutdown_or_sleep(
2412 : : m, message,
2413 : : INHIBIT_SHUTDOWN,
2414 : : "org.freedesktop.login1.reboot",
2415 : : "org.freedesktop.login1.reboot-multiple-sessions",
2416 : : "org.freedesktop.login1.reboot-ignore-inhibit",
2417 : : NULL,
2418 : : error);
2419 : : }
2420 : :
2421 : 0 : static int method_can_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2422 : 0 : Manager *m = userdata;
2423 : :
2424 : 0 : return method_can_shutdown_or_sleep(
2425 : : m, message,
2426 : : INHIBIT_SHUTDOWN,
2427 : : "org.freedesktop.login1.halt",
2428 : : "org.freedesktop.login1.halt-multiple-sessions",
2429 : : "org.freedesktop.login1.halt-ignore-inhibit",
2430 : : NULL,
2431 : : error);
2432 : : }
2433 : :
2434 : 0 : static int method_can_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2435 : 0 : Manager *m = userdata;
2436 : :
2437 : 0 : return method_can_shutdown_or_sleep(
2438 : : m, message,
2439 : : INHIBIT_SLEEP,
2440 : : "org.freedesktop.login1.suspend",
2441 : : "org.freedesktop.login1.suspend-multiple-sessions",
2442 : : "org.freedesktop.login1.suspend-ignore-inhibit",
2443 : : "suspend",
2444 : : error);
2445 : : }
2446 : :
2447 : 0 : static int method_can_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2448 : 0 : Manager *m = userdata;
2449 : :
2450 : 0 : return method_can_shutdown_or_sleep(
2451 : : m, message,
2452 : : INHIBIT_SLEEP,
2453 : : "org.freedesktop.login1.hibernate",
2454 : : "org.freedesktop.login1.hibernate-multiple-sessions",
2455 : : "org.freedesktop.login1.hibernate-ignore-inhibit",
2456 : : "hibernate",
2457 : : error);
2458 : : }
2459 : :
2460 : 0 : static int method_can_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2461 : 0 : Manager *m = userdata;
2462 : :
2463 : 0 : return method_can_shutdown_or_sleep(
2464 : : m, message,
2465 : : INHIBIT_SLEEP,
2466 : : "org.freedesktop.login1.hibernate",
2467 : : "org.freedesktop.login1.hibernate-multiple-sessions",
2468 : : "org.freedesktop.login1.hibernate-ignore-inhibit",
2469 : : "hybrid-sleep",
2470 : : error);
2471 : : }
2472 : :
2473 : 0 : static int method_can_suspend_then_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2474 : 0 : Manager *m = userdata;
2475 : :
2476 : 0 : return method_can_shutdown_or_sleep(
2477 : : m, message,
2478 : : INHIBIT_SLEEP,
2479 : : "org.freedesktop.login1.hibernate",
2480 : : "org.freedesktop.login1.hibernate-multiple-sessions",
2481 : : "org.freedesktop.login1.hibernate-ignore-inhibit",
2482 : : "suspend-then-hibernate",
2483 : : error);
2484 : : }
2485 : :
2486 : 0 : static int property_get_reboot_parameter(
2487 : : sd_bus *bus,
2488 : : const char *path,
2489 : : const char *interface,
2490 : : const char *property,
2491 : : sd_bus_message *reply,
2492 : : void *userdata,
2493 : : sd_bus_error *error) {
2494 : 0 : _cleanup_free_ char *parameter = NULL;
2495 : : int r;
2496 : :
2497 [ # # ]: 0 : assert(bus);
2498 [ # # ]: 0 : assert(reply);
2499 [ # # ]: 0 : assert(userdata);
2500 : :
2501 : 0 : r = read_reboot_parameter(¶meter);
2502 [ # # ]: 0 : if (r < 0)
2503 : 0 : return r;
2504 : :
2505 : 0 : return sd_bus_message_append(reply, "s", parameter);
2506 : : }
2507 : :
2508 : 0 : static int method_set_reboot_parameter(
2509 : : sd_bus_message *message,
2510 : : void *userdata,
2511 : : sd_bus_error *error) {
2512 : :
2513 : 0 : Manager *m = userdata;
2514 : : const char *arg;
2515 : : int r;
2516 : :
2517 [ # # ]: 0 : assert(message);
2518 [ # # ]: 0 : assert(m);
2519 : :
2520 : 0 : r = sd_bus_message_read(message, "s", &arg);
2521 [ # # ]: 0 : if (r < 0)
2522 : 0 : return r;
2523 : :
2524 : 0 : r = detect_container();
2525 [ # # ]: 0 : if (r < 0)
2526 : 0 : return r;
2527 [ # # ]: 0 : if (r > 0)
2528 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED,
2529 : : "Reboot parameter not supported in containers, refusing.");
2530 : :
2531 : 0 : r = bus_verify_polkit_async(message,
2532 : : CAP_SYS_ADMIN,
2533 : : "org.freedesktop.login1.set-reboot-parameter",
2534 : : NULL,
2535 : : false,
2536 : : UID_INVALID,
2537 : : &m->polkit_registry,
2538 : : error);
2539 [ # # ]: 0 : if (r < 0)
2540 : 0 : return r;
2541 [ # # ]: 0 : if (r == 0)
2542 : 0 : return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2543 : :
2544 : 0 : r = update_reboot_parameter_and_warn(arg, false);
2545 [ # # ]: 0 : if (r < 0)
2546 : 0 : return r;
2547 : :
2548 : 0 : return sd_bus_reply_method_return(message, NULL);
2549 : : }
2550 : :
2551 : 0 : static int method_can_reboot_parameter(
2552 : : sd_bus_message *message,
2553 : : void *userdata,
2554 : : sd_bus_error *error) {
2555 : :
2556 : 0 : Manager *m = userdata;
2557 : : int r;
2558 : :
2559 [ # # ]: 0 : assert(message);
2560 [ # # ]: 0 : assert(m);
2561 : :
2562 : 0 : r = detect_container();
2563 [ # # ]: 0 : if (r < 0)
2564 : 0 : return r;
2565 [ # # ]: 0 : if (r > 0) /* Inside containers, specifying a reboot parameter, doesn't make much sense */
2566 : 0 : return sd_bus_reply_method_return(message, "s", "na");
2567 : :
2568 : 0 : return return_test_polkit(
2569 : : message,
2570 : : CAP_SYS_ADMIN,
2571 : : "org.freedesktop.login1.set-reboot-parameter",
2572 : : NULL,
2573 : : UID_INVALID,
2574 : : error);
2575 : : }
2576 : :
2577 : 0 : static int property_get_reboot_to_firmware_setup(
2578 : : sd_bus *bus,
2579 : : const char *path,
2580 : : const char *interface,
2581 : : const char *property,
2582 : : sd_bus_message *reply,
2583 : : void *userdata,
2584 : : sd_bus_error *error) {
2585 : : int r;
2586 : :
2587 [ # # ]: 0 : assert(bus);
2588 [ # # ]: 0 : assert(reply);
2589 [ # # ]: 0 : assert(userdata);
2590 : :
2591 : 0 : r = getenv_bool("SYSTEMD_REBOOT_TO_FIRMWARE_SETUP");
2592 [ # # ]: 0 : if (r == -ENXIO) {
2593 : : /* EFI case: let's see what is currently configured in the EFI variables */
2594 : 0 : r = efi_get_reboot_to_firmware();
2595 [ # # # # ]: 0 : if (r < 0 && r != -EOPNOTSUPP)
2596 [ # # ]: 0 : log_warning_errno(r, "Failed to determine reboot-to-firmware-setup state: %m");
2597 [ # # ]: 0 : } else if (r < 0)
2598 [ # # ]: 0 : log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP: %m");
2599 [ # # ]: 0 : else if (r > 0) {
2600 : : /* Non-EFI case: let's see whether /run/systemd/reboot-to-firmware-setup exists. */
2601 [ # # ]: 0 : if (access("/run/systemd/reboot-to-firmware-setup", F_OK) < 0) {
2602 [ # # ]: 0 : if (errno != ENOENT)
2603 [ # # ]: 0 : log_warning_errno(errno, "Failed to check whether /run/systemd/reboot-to-firmware-setup exists: %m");
2604 : :
2605 : 0 : r = false;
2606 : : } else
2607 : 0 : r = true;
2608 : : }
2609 : :
2610 : 0 : return sd_bus_message_append(reply, "b", r > 0);
2611 : : }
2612 : :
2613 : 0 : static int method_set_reboot_to_firmware_setup(
2614 : : sd_bus_message *message,
2615 : : void *userdata,
2616 : : sd_bus_error *error) {
2617 : :
2618 : 0 : Manager *m = userdata;
2619 : : bool use_efi;
2620 : : int b, r;
2621 : :
2622 [ # # ]: 0 : assert(message);
2623 [ # # ]: 0 : assert(m);
2624 : :
2625 : 0 : r = sd_bus_message_read(message, "b", &b);
2626 [ # # ]: 0 : if (r < 0)
2627 : 0 : return r;
2628 : :
2629 : 0 : r = getenv_bool("SYSTEMD_REBOOT_TO_FIRMWARE_SETUP");
2630 [ # # ]: 0 : if (r == -ENXIO) {
2631 : : /* EFI case: let's see what the firmware supports */
2632 : :
2633 : 0 : r = efi_reboot_to_firmware_supported();
2634 [ # # ]: 0 : if (r == -EOPNOTSUPP)
2635 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Firmware does not support boot into firmware.");
2636 [ # # ]: 0 : if (r < 0)
2637 : 0 : return r;
2638 : :
2639 : 0 : use_efi = true;
2640 : :
2641 [ # # ]: 0 : } else if (r <= 0) {
2642 : : /* non-EFI case: $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP is set to off */
2643 : :
2644 [ # # ]: 0 : if (r < 0)
2645 [ # # ]: 0 : log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP: %m");
2646 : :
2647 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Firmware does not support boot into firmware.");
2648 : : } else
2649 : : /* non-EFI case: $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP is set to on */
2650 : 0 : use_efi = false;
2651 : :
2652 : 0 : r = bus_verify_polkit_async(message,
2653 : : CAP_SYS_ADMIN,
2654 : : "org.freedesktop.login1.set-reboot-to-firmware-setup",
2655 : : NULL,
2656 : : false,
2657 : : UID_INVALID,
2658 : : &m->polkit_registry,
2659 : : error);
2660 [ # # ]: 0 : if (r < 0)
2661 : 0 : return r;
2662 [ # # ]: 0 : if (r == 0)
2663 : 0 : return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2664 : :
2665 [ # # ]: 0 : if (use_efi) {
2666 : 0 : r = efi_set_reboot_to_firmware(b);
2667 [ # # ]: 0 : if (r < 0)
2668 : 0 : return r;
2669 : : } else {
2670 [ # # ]: 0 : if (b) {
2671 : 0 : r = touch("/run/systemd/reboot-to-firmware-setup");
2672 [ # # ]: 0 : if (r < 0)
2673 : 0 : return r;
2674 : : } else {
2675 [ # # # # ]: 0 : if (unlink("/run/systemd/reboot-to-firmware-setup") < 0 && errno != ENOENT)
2676 : 0 : return -errno;
2677 : : }
2678 : : }
2679 : :
2680 : 0 : return sd_bus_reply_method_return(message, NULL);
2681 : : }
2682 : :
2683 : 0 : static int method_can_reboot_to_firmware_setup(
2684 : : sd_bus_message *message,
2685 : : void *userdata,
2686 : : sd_bus_error *error) {
2687 : :
2688 : 0 : Manager *m = userdata;
2689 : : int r;
2690 : :
2691 [ # # ]: 0 : assert(message);
2692 [ # # ]: 0 : assert(m);
2693 : :
2694 : 0 : r = getenv_bool("SYSTEMD_REBOOT_TO_FIRMWARE_SETUP");
2695 [ # # ]: 0 : if (r == -ENXIO) {
2696 : : /* EFI case: let's see what the firmware supports */
2697 : :
2698 : 0 : r = efi_reboot_to_firmware_supported();
2699 [ # # ]: 0 : if (r < 0) {
2700 [ # # ]: 0 : if (r != -EOPNOTSUPP)
2701 [ # # ]: 0 : log_warning_errno(r, "Failed to determine whether reboot to firmware is supported: %m");
2702 : :
2703 : 0 : return sd_bus_reply_method_return(message, "s", "na");
2704 : : }
2705 : :
2706 [ # # ]: 0 : } else if (r <= 0) {
2707 : : /* Non-EFI case: let's trust $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP */
2708 : :
2709 [ # # ]: 0 : if (r < 0)
2710 [ # # ]: 0 : log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP: %m");
2711 : :
2712 : 0 : return sd_bus_reply_method_return(message, "s", "na");
2713 : : }
2714 : :
2715 : 0 : return return_test_polkit(
2716 : : message,
2717 : : CAP_SYS_ADMIN,
2718 : : "org.freedesktop.login1.set-reboot-to-firmware-setup",
2719 : : NULL,
2720 : : UID_INVALID,
2721 : : error);
2722 : : }
2723 : :
2724 : 0 : static int property_get_reboot_to_boot_loader_menu(
2725 : : sd_bus *bus,
2726 : : const char *path,
2727 : : const char *interface,
2728 : : const char *property,
2729 : : sd_bus_message *reply,
2730 : : void *userdata,
2731 : : sd_bus_error *error) {
2732 : :
2733 : 0 : uint64_t x = UINT64_MAX;
2734 : : int r;
2735 : :
2736 [ # # ]: 0 : assert(bus);
2737 [ # # ]: 0 : assert(reply);
2738 [ # # ]: 0 : assert(userdata);
2739 : :
2740 : 0 : r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU");
2741 [ # # ]: 0 : if (r == -ENXIO) {
2742 : 0 : _cleanup_free_ char *v = NULL;
2743 : :
2744 : : /* EFI case: returns the current value of LoaderConfigTimeoutOneShot. Three cases are distuingished:
2745 : : *
2746 : : * 1. Variable not set, boot into boot loader menu is not enabled (we return UINT64_MAX to the user)
2747 : : * 2. Variable set to "0", boot into boot loader menu is enabled with no timeout (we return 0 to the user)
2748 : : * 3. Variable set to numeric value formatted in ASCII, boot into boot loader menu with the specified timeout in seconds
2749 : : */
2750 : :
2751 : 0 : r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot", &v);
2752 [ # # ]: 0 : if (r < 0) {
2753 [ # # ]: 0 : if (r != -ENOENT)
2754 [ # # ]: 0 : log_warning_errno(r, "Failed to read LoaderConfigTimeoutOneShot variable: %m");
2755 : : } else {
2756 : : uint64_t sec;
2757 : :
2758 : 0 : r = safe_atou64(v, &sec);
2759 [ # # ]: 0 : if (r < 0)
2760 [ # # ]: 0 : log_warning_errno(r, "Failed to parse LoaderConfigTimeoutOneShot value '%s': %m", v);
2761 [ # # ]: 0 : else if (sec > (USEC_INFINITY / USEC_PER_SEC))
2762 [ # # ]: 0 : log_warning("LoaderConfigTimeoutOneShot too large, ignoring: %m");
2763 : : else
2764 : 0 : x = sec * USEC_PER_SEC; /* return in µs */
2765 : : }
2766 : :
2767 [ # # ]: 0 : } else if (r < 0)
2768 [ # # ]: 0 : log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU: %m");
2769 [ # # ]: 0 : else if (r > 0) {
2770 : 0 : _cleanup_free_ char *v = NULL;
2771 : :
2772 : : /* Non-EFI case, let's process /run/systemd/reboot-to-boot-loader-menu. */
2773 : :
2774 : 0 : r = read_one_line_file("/run/systemd/reboot-to-boot-loader-menu", &v);
2775 [ # # ]: 0 : if (r < 0) {
2776 [ # # ]: 0 : if (r != -ENOENT)
2777 [ # # ]: 0 : log_warning_errno(r, "Failed to read /run/systemd/reboot-to-boot-loader-menu: %m");
2778 : : } else {
2779 : 0 : r = safe_atou64(v, &x);
2780 [ # # ]: 0 : if (r < 0)
2781 [ # # ]: 0 : log_warning_errno(r, "Failed to parse /run/systemd/reboot-to-boot-loader-menu: %m");
2782 : : }
2783 : : }
2784 : :
2785 : 0 : return sd_bus_message_append(reply, "t", x);
2786 : : }
2787 : :
2788 : 0 : static int method_set_reboot_to_boot_loader_menu(
2789 : : sd_bus_message *message,
2790 : : void *userdata,
2791 : : sd_bus_error *error) {
2792 : :
2793 : 0 : Manager *m = userdata;
2794 : : bool use_efi;
2795 : : uint64_t x;
2796 : : int r;
2797 : :
2798 [ # # ]: 0 : assert(message);
2799 [ # # ]: 0 : assert(m);
2800 : :
2801 : 0 : r = sd_bus_message_read(message, "t", &x);
2802 [ # # ]: 0 : if (r < 0)
2803 : 0 : return r;
2804 : :
2805 : 0 : r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU");
2806 [ # # ]: 0 : if (r == -ENXIO) {
2807 : : uint64_t features;
2808 : :
2809 : : /* EFI case: let's see if booting into boot loader menu is supported. */
2810 : :
2811 : 0 : r = efi_loader_get_features(&features);
2812 [ # # ]: 0 : if (r < 0)
2813 [ # # ]: 0 : log_warning_errno(r, "Failed to determine whether reboot to boot loader menu is supported: %m");
2814 [ # # # # ]: 0 : if (r < 0 || !FLAGS_SET(features, EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT))
2815 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Boot loader does not support boot into boot loader menu.");
2816 : :
2817 : 0 : use_efi = true;
2818 : :
2819 [ # # ]: 0 : } else if (r <= 0) {
2820 : : /* non-EFI case: $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU is set to off */
2821 : :
2822 [ # # ]: 0 : if (r < 0)
2823 [ # # ]: 0 : log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU: %m");
2824 : :
2825 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Boot loader does not support boot into boot loader menu.");
2826 : : } else
2827 : : /* non-EFI case: $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU is set to on */
2828 : 0 : use_efi = false;
2829 : :
2830 : 0 : r = bus_verify_polkit_async(message,
2831 : : CAP_SYS_ADMIN,
2832 : : "org.freedesktop.login1.set-reboot-to-boot-loader-menu",
2833 : : NULL,
2834 : : false,
2835 : : UID_INVALID,
2836 : : &m->polkit_registry,
2837 : : error);
2838 [ # # ]: 0 : if (r < 0)
2839 : 0 : return r;
2840 [ # # ]: 0 : if (r == 0)
2841 : 0 : return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2842 : :
2843 [ # # ]: 0 : if (use_efi) {
2844 [ # # ]: 0 : if (x == UINT64_MAX)
2845 : 0 : r = efi_set_variable(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot", NULL, 0);
2846 : : else {
2847 : : char buf[DECIMAL_STR_MAX(uint64_t) + 1];
2848 [ # # ]: 0 : xsprintf(buf, "%" PRIu64, DIV_ROUND_UP(x, USEC_PER_SEC)); /* second granularity */
2849 : :
2850 : 0 : r = efi_set_variable_string(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot", buf);
2851 : : }
2852 [ # # ]: 0 : if (r < 0)
2853 : 0 : return r;
2854 : : } else {
2855 [ # # ]: 0 : if (x == UINT64_MAX) {
2856 [ # # # # ]: 0 : if (unlink("/run/systemd/reboot-to-loader-menu") < 0 && errno != ENOENT)
2857 : 0 : return -errno;
2858 : : } else {
2859 : : char buf[DECIMAL_STR_MAX(uint64_t) + 1];
2860 : :
2861 [ # # ]: 0 : xsprintf(buf, "%" PRIu64, x); /* µs granularity */
2862 : :
2863 : 0 : r = write_string_file_atomic_label("/run/systemd/reboot-to-loader-menu", buf);
2864 [ # # ]: 0 : if (r < 0)
2865 : 0 : return r;
2866 : : }
2867 : : }
2868 : :
2869 : 0 : return sd_bus_reply_method_return(message, NULL);
2870 : : }
2871 : :
2872 : 0 : static int method_can_reboot_to_boot_loader_menu(
2873 : : sd_bus_message *message,
2874 : : void *userdata,
2875 : : sd_bus_error *error) {
2876 : :
2877 : 0 : Manager *m = userdata;
2878 : : int r;
2879 : :
2880 [ # # ]: 0 : assert(message);
2881 [ # # ]: 0 : assert(m);
2882 : :
2883 : 0 : r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU");
2884 [ # # ]: 0 : if (r == -ENXIO) {
2885 : 0 : uint64_t features = 0;
2886 : :
2887 : : /* EFI case, let's see if booting into boot loader menu is supported. */
2888 : :
2889 : 0 : r = efi_loader_get_features(&features);
2890 [ # # ]: 0 : if (r < 0)
2891 [ # # ]: 0 : log_warning_errno(r, "Failed to determine whether reboot to boot loader menu is supported: %m");
2892 [ # # # # ]: 0 : if (r < 0 || !FLAGS_SET(features, EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT))
2893 : 0 : return sd_bus_reply_method_return(message, "s", "na");
2894 : :
2895 [ # # ]: 0 : } else if (r <= 0) {
2896 : : /* Non-EFI case: let's trust $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU */
2897 : :
2898 [ # # ]: 0 : if (r < 0)
2899 [ # # ]: 0 : log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU: %m");
2900 : :
2901 : 0 : return sd_bus_reply_method_return(message, "s", "na");
2902 : : }
2903 : :
2904 : 0 : return return_test_polkit(
2905 : : message,
2906 : : CAP_SYS_ADMIN,
2907 : : "org.freedesktop.login1.set-reboot-to-boot-loader-menu",
2908 : : NULL,
2909 : : UID_INVALID,
2910 : : error);
2911 : : }
2912 : :
2913 : 0 : static int property_get_reboot_to_boot_loader_entry(
2914 : : sd_bus *bus,
2915 : : const char *path,
2916 : : const char *interface,
2917 : : const char *property,
2918 : : sd_bus_message *reply,
2919 : : void *userdata,
2920 : : sd_bus_error *error) {
2921 : :
2922 : 0 : _cleanup_free_ char *v = NULL;
2923 : : int r;
2924 : :
2925 [ # # ]: 0 : assert(bus);
2926 [ # # ]: 0 : assert(reply);
2927 [ # # ]: 0 : assert(userdata);
2928 : :
2929 : 0 : r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY");
2930 [ # # ]: 0 : if (r == -ENXIO) {
2931 : : /* EFI case: let's read the LoaderEntryOneShot variable */
2932 : :
2933 : 0 : r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderEntryOneShot", &v);
2934 [ # # ]: 0 : if (r < 0) {
2935 [ # # ]: 0 : if (r != -ENOENT)
2936 [ # # ]: 0 : log_warning_errno(r, "Failed to read LoaderEntryOneShot variable: %m");
2937 [ # # ]: 0 : } else if (!efi_loader_entry_name_valid(v)) {
2938 [ # # ]: 0 : log_warning("LoaderEntryOneShot contains invalid entry name '%s', ignoring.", v);
2939 : 0 : v = mfree(v);
2940 : : }
2941 [ # # ]: 0 : } else if (r < 0)
2942 [ # # ]: 0 : log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY: %m");
2943 [ # # ]: 0 : else if (r > 0) {
2944 : :
2945 : : /* Non-EFI case, let's process /run/systemd/reboot-to-boot-loader-entry. */
2946 : :
2947 : 0 : r = read_one_line_file("/run/systemd/reboot-to-boot-loader-entry", &v);
2948 [ # # ]: 0 : if (r < 0) {
2949 [ # # ]: 0 : if (r != -ENOENT)
2950 [ # # ]: 0 : log_warning_errno(r, "Failed to read /run/systemd/reboot-to-boot-loader-entry: %m");
2951 [ # # ]: 0 : } else if (!efi_loader_entry_name_valid(v)) {
2952 [ # # ]: 0 : log_warning("/run/systemd/reboot-to-boot-loader-entry is not valid, ignoring.");
2953 : 0 : v = mfree(v);
2954 : : }
2955 : : }
2956 : :
2957 : 0 : return sd_bus_message_append(reply, "s", v);
2958 : : }
2959 : :
2960 : 0 : static int boot_loader_entry_exists(const char *id) {
2961 : 0 : _cleanup_(boot_config_free) BootConfig config = {};
2962 : : int r;
2963 : :
2964 [ # # ]: 0 : assert(id);
2965 : :
2966 : 0 : r = boot_entries_load_config_auto(NULL, NULL, &config);
2967 [ # # # # ]: 0 : if (r < 0 && r != -ENOKEY) /* don't complain if no GPT is found, hence skip ENOKEY */
2968 : 0 : return r;
2969 : :
2970 : 0 : (void) boot_entries_augment_from_loader(&config, true);
2971 : :
2972 : 0 : return boot_config_has_entry(&config, id);
2973 : : }
2974 : :
2975 : 0 : static int method_set_reboot_to_boot_loader_entry(
2976 : : sd_bus_message *message,
2977 : : void *userdata,
2978 : : sd_bus_error *error) {
2979 : :
2980 : 0 : Manager *m = userdata;
2981 : : bool use_efi;
2982 : : const char *v;
2983 : : int r;
2984 : :
2985 [ # # ]: 0 : assert(message);
2986 [ # # ]: 0 : assert(m);
2987 : :
2988 : 0 : r = sd_bus_message_read(message, "s", &v);
2989 [ # # ]: 0 : if (r < 0)
2990 : 0 : return r;
2991 : :
2992 [ # # ]: 0 : if (isempty(v))
2993 : 0 : v = NULL;
2994 [ # # ]: 0 : else if (efi_loader_entry_name_valid(v)) {
2995 : 0 : r = boot_loader_entry_exists(v);
2996 [ # # ]: 0 : if (r < 0)
2997 : 0 : return r;
2998 [ # # ]: 0 : if (r == 0)
2999 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Boot loader entry '%s' is not known.", v);
3000 : : } else
3001 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Boot loader entry name '%s' is not valid, refusing.", v);
3002 : :
3003 : 0 : r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY");
3004 [ # # ]: 0 : if (r == -ENXIO) {
3005 : : uint64_t features;
3006 : :
3007 : : /* EFI case: let's see if booting into boot loader entry is supported. */
3008 : :
3009 : 0 : r = efi_loader_get_features(&features);
3010 [ # # ]: 0 : if (r < 0)
3011 [ # # ]: 0 : log_warning_errno(r, "Failed to determine whether reboot into boot loader entry is supported: %m");
3012 [ # # # # ]: 0 : if (r < 0 || !FLAGS_SET(features, EFI_LOADER_FEATURE_ENTRY_ONESHOT))
3013 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Loader does not support boot into boot loader entry.");
3014 : :
3015 : 0 : use_efi = true;
3016 : :
3017 [ # # ]: 0 : } else if (r <= 0) {
3018 : : /* non-EFI case: $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY is set to off */
3019 : :
3020 [ # # ]: 0 : if (r < 0)
3021 [ # # ]: 0 : log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY: %m");
3022 : :
3023 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Loader does not support boot into boot loader entry.");
3024 : : } else
3025 : : /* non-EFI case: $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY is set to on */
3026 : 0 : use_efi = false;
3027 : :
3028 : 0 : r = bus_verify_polkit_async(message,
3029 : : CAP_SYS_ADMIN,
3030 : : "org.freedesktop.login1.set-reboot-to-boot-loader-entry",
3031 : : NULL,
3032 : : false,
3033 : : UID_INVALID,
3034 : : &m->polkit_registry,
3035 : : error);
3036 [ # # ]: 0 : if (r < 0)
3037 : 0 : return r;
3038 [ # # ]: 0 : if (r == 0)
3039 : 0 : return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
3040 : :
3041 [ # # ]: 0 : if (use_efi) {
3042 [ # # ]: 0 : if (isempty(v))
3043 : : /* Delete item */
3044 : 0 : r = efi_set_variable(EFI_VENDOR_LOADER, "LoaderEntryOneShot", NULL, 0);
3045 : : else
3046 : 0 : r = efi_set_variable_string(EFI_VENDOR_LOADER, "LoaderEntryOneShot", v);
3047 [ # # ]: 0 : if (r < 0)
3048 : 0 : return r;
3049 : : } else {
3050 [ # # ]: 0 : if (isempty(v)) {
3051 [ # # # # ]: 0 : if (unlink("/run/systemd/reboot-to-boot-loader-entry") < 0 && errno != ENOENT)
3052 : 0 : return -errno;
3053 : : } else {
3054 : 0 : r = write_string_file_atomic_label("/run/systemd/reboot-boot-to-loader-entry", v);
3055 [ # # ]: 0 : if (r < 0)
3056 : 0 : return r;
3057 : : }
3058 : : }
3059 : :
3060 : 0 : return sd_bus_reply_method_return(message, NULL);
3061 : : }
3062 : :
3063 : 0 : static int method_can_reboot_to_boot_loader_entry(
3064 : : sd_bus_message *message,
3065 : : void *userdata,
3066 : : sd_bus_error *error) {
3067 : :
3068 : 0 : Manager *m = userdata;
3069 : : int r;
3070 : :
3071 [ # # ]: 0 : assert(message);
3072 [ # # ]: 0 : assert(m);
3073 : :
3074 : 0 : r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY");
3075 [ # # ]: 0 : if (r == -ENXIO) {
3076 : 0 : uint64_t features = 0;
3077 : :
3078 : : /* EFI case, let's see if booting into boot loader entry is supported. */
3079 : :
3080 : 0 : r = efi_loader_get_features(&features);
3081 [ # # ]: 0 : if (r < 0)
3082 [ # # ]: 0 : log_warning_errno(r, "Failed to determine whether reboot to boot loader entry is supported: %m");
3083 [ # # # # ]: 0 : if (r < 0 || !FLAGS_SET(features, EFI_LOADER_FEATURE_ENTRY_ONESHOT))
3084 : 0 : return sd_bus_reply_method_return(message, "s", "na");
3085 : :
3086 [ # # ]: 0 : } else if (r <= 0) {
3087 : : /* Non-EFI case: let's trust $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY */
3088 : :
3089 [ # # ]: 0 : if (r < 0)
3090 [ # # ]: 0 : log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY: %m");
3091 : :
3092 : 0 : return sd_bus_reply_method_return(message, "s", "na");
3093 : : }
3094 : :
3095 : 0 : return return_test_polkit(
3096 : : message,
3097 : : CAP_SYS_ADMIN,
3098 : : "org.freedesktop.login1.set-reboot-to-boot-loader-entry",
3099 : : NULL,
3100 : : UID_INVALID,
3101 : : error);
3102 : : }
3103 : :
3104 : 0 : static int property_get_boot_loader_entries(
3105 : : sd_bus *bus,
3106 : : const char *path,
3107 : : const char *interface,
3108 : : const char *property,
3109 : : sd_bus_message *reply,
3110 : : void *userdata,
3111 : : sd_bus_error *error) {
3112 : :
3113 : 0 : _cleanup_(boot_config_free) BootConfig config = {};
3114 : : size_t i;
3115 : : int r;
3116 : :
3117 [ # # ]: 0 : assert(bus);
3118 [ # # ]: 0 : assert(reply);
3119 [ # # ]: 0 : assert(userdata);
3120 : :
3121 : 0 : r = boot_entries_load_config_auto(NULL, NULL, &config);
3122 [ # # # # ]: 0 : if (r < 0 && r != -ENOKEY) /* don't complain if there's no GPT found */
3123 : 0 : return r;
3124 : :
3125 : 0 : (void) boot_entries_augment_from_loader(&config, true);
3126 : :
3127 : 0 : r = sd_bus_message_open_container(reply, 'a', "s");
3128 [ # # ]: 0 : if (r < 0)
3129 : 0 : return r;
3130 : :
3131 [ # # ]: 0 : for (i = 0; i < config.n_entries; i++) {
3132 : 0 : BootEntry *e = config.entries + i;
3133 : :
3134 : 0 : r = sd_bus_message_append(reply, "s", e->id);
3135 [ # # ]: 0 : if (r < 0)
3136 : 0 : return r;
3137 : : }
3138 : :
3139 : 0 : return sd_bus_message_close_container(reply);
3140 : : }
3141 : :
3142 : 0 : static int method_set_wall_message(
3143 : : sd_bus_message *message,
3144 : : void *userdata,
3145 : : sd_bus_error *error) {
3146 : :
3147 : : int r;
3148 : 0 : Manager *m = userdata;
3149 : : char *wall_message;
3150 : : unsigned enable_wall_messages;
3151 : :
3152 [ # # ]: 0 : assert(message);
3153 [ # # ]: 0 : assert(m);
3154 : :
3155 : 0 : r = sd_bus_message_read(message, "sb", &wall_message, &enable_wall_messages);
3156 [ # # ]: 0 : if (r < 0)
3157 : 0 : return r;
3158 : :
3159 : 0 : r = bus_verify_polkit_async(message,
3160 : : CAP_SYS_ADMIN,
3161 : : "org.freedesktop.login1.set-wall-message",
3162 : : NULL,
3163 : : false,
3164 : : UID_INVALID,
3165 : : &m->polkit_registry,
3166 : : error);
3167 [ # # ]: 0 : if (r < 0)
3168 : 0 : return r;
3169 [ # # ]: 0 : if (r == 0)
3170 : 0 : return 1; /* Will call us back */
3171 : :
3172 : 0 : r = free_and_strdup(&m->wall_message, empty_to_null(wall_message));
3173 [ # # ]: 0 : if (r < 0)
3174 : 0 : return log_oom();
3175 : :
3176 : 0 : m->enable_wall_messages = enable_wall_messages;
3177 : :
3178 : 0 : return sd_bus_reply_method_return(message, NULL);
3179 : : }
3180 : :
3181 : 0 : static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
3182 : 0 : _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
3183 : : const char *who, *why, *what, *mode;
3184 : 0 : _cleanup_free_ char *id = NULL;
3185 : 0 : _cleanup_close_ int fifo_fd = -1;
3186 : 0 : Manager *m = userdata;
3187 : 0 : Inhibitor *i = NULL;
3188 : : InhibitMode mm;
3189 : : InhibitWhat w;
3190 : : pid_t pid;
3191 : : uid_t uid;
3192 : : int r;
3193 : :
3194 [ # # ]: 0 : assert(message);
3195 [ # # ]: 0 : assert(m);
3196 : :
3197 : 0 : r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
3198 [ # # ]: 0 : if (r < 0)
3199 : 0 : return r;
3200 : :
3201 : 0 : w = inhibit_what_from_string(what);
3202 [ # # ]: 0 : if (w <= 0)
3203 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
3204 : : "Invalid what specification %s", what);
3205 : :
3206 : 0 : mm = inhibit_mode_from_string(mode);
3207 [ # # ]: 0 : if (mm < 0)
3208 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
3209 : : "Invalid mode specification %s", mode);
3210 : :
3211 : : /* Delay is only supported for shutdown/sleep */
3212 [ # # # # ]: 0 : if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
3213 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
3214 : : "Delay inhibitors only supported for shutdown and sleep");
3215 : :
3216 : : /* Don't allow taking delay locks while we are already
3217 : : * executing the operation. We shouldn't create the impression
3218 : : * that the lock was successful if the machine is about to go
3219 : : * down/suspend any moment. */
3220 [ # # ]: 0 : if (m->action_what & w)
3221 : 0 : return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS,
3222 : : "The operation inhibition has been requested for is already running");
3223 : :
3224 [ # # ]: 0 : r = bus_verify_polkit_async(
3225 : : message,
3226 : : CAP_SYS_BOOT,
3227 [ # # ]: 0 : w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
3228 [ # # # # ]: 0 : w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
3229 [ # # ]: 0 : w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
3230 [ # # ]: 0 : w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
3231 [ # # ]: 0 : w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
3232 [ # # ]: 0 : w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
3233 : : "org.freedesktop.login1.inhibit-handle-lid-switch",
3234 : : NULL,
3235 : : false,
3236 : : UID_INVALID,
3237 : : &m->polkit_registry,
3238 : : error);
3239 [ # # ]: 0 : if (r < 0)
3240 : 0 : return r;
3241 [ # # ]: 0 : if (r == 0)
3242 : 0 : return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
3243 : :
3244 : 0 : r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
3245 [ # # ]: 0 : if (r < 0)
3246 : 0 : return r;
3247 : :
3248 : 0 : r = sd_bus_creds_get_euid(creds, &uid);
3249 [ # # ]: 0 : if (r < 0)
3250 : 0 : return r;
3251 : :
3252 : 0 : r = sd_bus_creds_get_pid(creds, &pid);
3253 [ # # ]: 0 : if (r < 0)
3254 : 0 : return r;
3255 : :
3256 [ # # ]: 0 : if (hashmap_size(m->inhibitors) >= m->inhibitors_max)
3257 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED,
3258 : : "Maximum number of inhibitors (%" PRIu64 ") reached, refusing further inhibitors.",
3259 : : m->inhibitors_max);
3260 : :
3261 : : do {
3262 : 0 : id = mfree(id);
3263 : :
3264 [ # # ]: 0 : if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
3265 : 0 : return -ENOMEM;
3266 : :
3267 [ # # ]: 0 : } while (hashmap_get(m->inhibitors, id));
3268 : :
3269 : 0 : r = manager_add_inhibitor(m, id, &i);
3270 [ # # ]: 0 : if (r < 0)
3271 : 0 : return r;
3272 : :
3273 : 0 : i->what = w;
3274 : 0 : i->mode = mm;
3275 : 0 : i->pid = pid;
3276 : 0 : i->uid = uid;
3277 : 0 : i->why = strdup(why);
3278 : 0 : i->who = strdup(who);
3279 : :
3280 [ # # # # ]: 0 : if (!i->why || !i->who) {
3281 : 0 : r = -ENOMEM;
3282 : 0 : goto fail;
3283 : : }
3284 : :
3285 : 0 : fifo_fd = inhibitor_create_fifo(i);
3286 [ # # ]: 0 : if (fifo_fd < 0) {
3287 : 0 : r = fifo_fd;
3288 : 0 : goto fail;
3289 : : }
3290 : :
3291 : 0 : r = inhibitor_start(i);
3292 [ # # ]: 0 : if (r < 0)
3293 : 0 : goto fail;
3294 : :
3295 : 0 : return sd_bus_reply_method_return(message, "h", fifo_fd);
3296 : :
3297 : 0 : fail:
3298 [ # # ]: 0 : if (i)
3299 : 0 : inhibitor_free(i);
3300 : :
3301 : 0 : return r;
3302 : : }
3303 : :
3304 : : const sd_bus_vtable manager_vtable[] = {
3305 : : SD_BUS_VTABLE_START(0),
3306 : :
3307 : : SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL, NULL, offsetof(Manager, enable_wall_messages), 0),
3308 : : SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL, NULL, offsetof(Manager, wall_message), 0),
3309 : :
3310 : : SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
3311 : : SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
3312 : : SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
3313 : : SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
3314 : : SD_BUS_PROPERTY("RebootParameter", "s", property_get_reboot_parameter, 0, 0),
3315 : : SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, 0),
3316 : : SD_BUS_PROPERTY("RebootToBootLoaderMenu", "t", property_get_reboot_to_boot_loader_menu, 0, 0),
3317 : : SD_BUS_PROPERTY("RebootToBootLoaderEntry", "s", property_get_reboot_to_boot_loader_entry, 0, 0),
3318 : : SD_BUS_PROPERTY("BootLoaderEntries", "as", property_get_boot_loader_entries, 0, SD_BUS_VTABLE_PROPERTY_CONST),
3319 : : SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
3320 : : SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
3321 : : SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
3322 : : SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
3323 : : SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
3324 : : SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
3325 : : SD_BUS_PROPERTY("UserStopDelayUSec", "t", NULL, offsetof(Manager, user_stop_delay), SD_BUS_VTABLE_PROPERTY_CONST),
3326 : : SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
3327 : : SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
3328 : : SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
3329 : : SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
3330 : : SD_BUS_PROPERTY("HandleLidSwitchExternalPower", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_ep), SD_BUS_VTABLE_PROPERTY_CONST),
3331 : : SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
3332 : : SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
3333 : : SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
3334 : : SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
3335 : : SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
3336 : : SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
3337 : : SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0),
3338 : : SD_BUS_PROPERTY("Docked", "b", property_get_docked, 0, 0),
3339 : : SD_BUS_PROPERTY("LidClosed", "b", property_get_lid_closed, 0, 0),
3340 : : SD_BUS_PROPERTY("OnExternalPower", "b", property_get_on_external_power, 0, 0),
3341 : : SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(Manager, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST),
3342 : : SD_BUS_PROPERTY("RuntimeDirectorySize", "t", NULL, offsetof(Manager, runtime_dir_size), SD_BUS_VTABLE_PROPERTY_CONST),
3343 : : SD_BUS_PROPERTY("InhibitorsMax", "t", NULL, offsetof(Manager, inhibitors_max), SD_BUS_VTABLE_PROPERTY_CONST),
3344 : : SD_BUS_PROPERTY("NCurrentInhibitors", "t", property_get_hashmap_size, offsetof(Manager, inhibitors), 0),
3345 : : SD_BUS_PROPERTY("SessionsMax", "t", NULL, offsetof(Manager, sessions_max), SD_BUS_VTABLE_PROPERTY_CONST),
3346 : : SD_BUS_PROPERTY("NCurrentSessions", "t", property_get_hashmap_size, offsetof(Manager, sessions), 0),
3347 : : SD_BUS_PROPERTY("UserTasksMax", "t", property_get_compat_user_tasks_max, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
3348 : :
3349 : : SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
3350 : : SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
3351 : : SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
3352 : : SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
3353 : : SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
3354 : : SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
3355 : : SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
3356 : : SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
3357 : : SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
3358 : : SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
3359 : : SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
3360 : : SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
3361 : : SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
3362 : : SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
3363 : : SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
3364 : : SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
3365 : : SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
3366 : : SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
3367 : : SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
3368 : : SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
3369 : : SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
3370 : : SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
3371 : : SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
3372 : : SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
3373 : : SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
3374 : : SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
3375 : : SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
3376 : : SD_BUS_METHOD("Halt", "b", NULL, method_halt, SD_BUS_VTABLE_UNPRIVILEGED),
3377 : : SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
3378 : : SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
3379 : : SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
3380 : : SD_BUS_METHOD("SuspendThenHibernate", "b", NULL, method_suspend_then_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
3381 : : SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
3382 : : SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
3383 : : SD_BUS_METHOD("CanHalt", NULL, "s", method_can_halt, SD_BUS_VTABLE_UNPRIVILEGED),
3384 : : SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
3385 : : SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
3386 : : SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
3387 : : SD_BUS_METHOD("CanSuspendThenHibernate", NULL, "s", method_can_suspend_then_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
3388 : : SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
3389 : : SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
3390 : : SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
3391 : : SD_BUS_METHOD("CanRebootParameter", NULL, "s", method_can_reboot_parameter, SD_BUS_VTABLE_UNPRIVILEGED),
3392 : : SD_BUS_METHOD("SetRebootParameter", "s", NULL, method_set_reboot_parameter, SD_BUS_VTABLE_UNPRIVILEGED),
3393 : : SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
3394 : : SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
3395 : : SD_BUS_METHOD("CanRebootToBootLoaderMenu", NULL, "s", method_can_reboot_to_boot_loader_menu, SD_BUS_VTABLE_UNPRIVILEGED),
3396 : : SD_BUS_METHOD("SetRebootToBootLoaderMenu", "t", NULL, method_set_reboot_to_boot_loader_menu, SD_BUS_VTABLE_UNPRIVILEGED),
3397 : : SD_BUS_METHOD("CanRebootToBootLoaderEntry", NULL, "s", method_can_reboot_to_boot_loader_entry, SD_BUS_VTABLE_UNPRIVILEGED),
3398 : : SD_BUS_METHOD("SetRebootToBootLoaderEntry", "s", NULL, method_set_reboot_to_boot_loader_entry, SD_BUS_VTABLE_UNPRIVILEGED),
3399 : : SD_BUS_METHOD("SetWallMessage", "sb", NULL, method_set_wall_message, SD_BUS_VTABLE_UNPRIVILEGED),
3400 : :
3401 : : SD_BUS_SIGNAL("SessionNew", "so", 0),
3402 : : SD_BUS_SIGNAL("SessionRemoved", "so", 0),
3403 : : SD_BUS_SIGNAL("UserNew", "uo", 0),
3404 : : SD_BUS_SIGNAL("UserRemoved", "uo", 0),
3405 : : SD_BUS_SIGNAL("SeatNew", "so", 0),
3406 : : SD_BUS_SIGNAL("SeatRemoved", "so", 0),
3407 : : SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
3408 : : SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
3409 : :
3410 : : SD_BUS_VTABLE_END
3411 : : };
3412 : :
3413 : 0 : static int session_jobs_reply(Session *s, const char *unit, const char *result) {
3414 [ # # ]: 0 : assert(s);
3415 [ # # ]: 0 : assert(unit);
3416 : :
3417 [ # # ]: 0 : if (!s->started)
3418 : 0 : return 0;
3419 : :
3420 [ # # # # ]: 0 : if (result && !streq(result, "done")) {
3421 : 0 : _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
3422 : :
3423 : 0 : sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED,
3424 : : "Start job for unit '%s' failed with '%s'", unit, result);
3425 : 0 : return session_send_create_reply(s, &e);
3426 : : }
3427 : :
3428 : 0 : return session_send_create_reply(s, NULL);
3429 : : }
3430 : :
3431 : 0 : int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
3432 : : const char *path, *result, *unit;
3433 : 0 : Manager *m = userdata;
3434 : : Session *session;
3435 : : uint32_t id;
3436 : : User *user;
3437 : : int r;
3438 : :
3439 [ # # ]: 0 : assert(message);
3440 [ # # ]: 0 : assert(m);
3441 : :
3442 : 0 : r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
3443 [ # # ]: 0 : if (r < 0) {
3444 [ # # ]: 0 : bus_log_parse_error(r);
3445 : 0 : return 0;
3446 : : }
3447 : :
3448 [ # # # # ]: 0 : if (m->action_job && streq(m->action_job, path)) {
3449 [ # # ]: 0 : log_info("Operation '%s' finished.", inhibit_what_to_string(m->action_what));
3450 : :
3451 : : /* Tell people that they now may take a lock again */
3452 : 0 : (void) send_prepare_for(m, m->action_what, false);
3453 : :
3454 : 0 : m->action_job = mfree(m->action_job);
3455 : 0 : m->action_unit = NULL;
3456 : 0 : m->action_what = 0;
3457 : 0 : return 0;
3458 : : }
3459 : :
3460 : 0 : session = hashmap_get(m->session_units, unit);
3461 [ # # ]: 0 : if (session) {
3462 [ # # ]: 0 : if (streq_ptr(path, session->scope_job)) {
3463 : 0 : session->scope_job = mfree(session->scope_job);
3464 : 0 : (void) session_jobs_reply(session, unit, result);
3465 : :
3466 : 0 : session_save(session);
3467 : 0 : user_save(session->user);
3468 : : }
3469 : :
3470 : 0 : session_add_to_gc_queue(session);
3471 : : }
3472 : :
3473 : 0 : user = hashmap_get(m->user_units, unit);
3474 [ # # ]: 0 : if (user) {
3475 [ # # ]: 0 : if (streq_ptr(path, user->service_job)) {
3476 : 0 : user->service_job = mfree(user->service_job);
3477 : :
3478 [ # # ]: 0 : LIST_FOREACH(sessions_by_user, session, user->sessions)
3479 : 0 : (void) session_jobs_reply(session, unit, NULL /* don't propagate user service failures to the client */);
3480 : :
3481 : 0 : user_save(user);
3482 : : }
3483 : :
3484 : 0 : user_add_to_gc_queue(user);
3485 : : }
3486 : :
3487 : 0 : return 0;
3488 : : }
3489 : :
3490 : 0 : int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
3491 : : const char *path, *unit;
3492 : 0 : Manager *m = userdata;
3493 : : Session *session;
3494 : : User *user;
3495 : : int r;
3496 : :
3497 [ # # ]: 0 : assert(message);
3498 [ # # ]: 0 : assert(m);
3499 : :
3500 : 0 : r = sd_bus_message_read(message, "so", &unit, &path);
3501 [ # # ]: 0 : if (r < 0) {
3502 [ # # ]: 0 : bus_log_parse_error(r);
3503 : 0 : return 0;
3504 : : }
3505 : :
3506 : 0 : session = hashmap_get(m->session_units, unit);
3507 [ # # ]: 0 : if (session)
3508 : 0 : session_add_to_gc_queue(session);
3509 : :
3510 : 0 : user = hashmap_get(m->user_units, unit);
3511 [ # # ]: 0 : if (user)
3512 : 0 : user_add_to_gc_queue(user);
3513 : :
3514 : 0 : return 0;
3515 : : }
3516 : :
3517 : 0 : int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
3518 : 0 : _cleanup_free_ char *unit = NULL;
3519 : 0 : Manager *m = userdata;
3520 : : const char *path;
3521 : : Session *session;
3522 : : User *user;
3523 : : int r;
3524 : :
3525 [ # # ]: 0 : assert(message);
3526 [ # # ]: 0 : assert(m);
3527 : :
3528 : 0 : path = sd_bus_message_get_path(message);
3529 [ # # ]: 0 : if (!path)
3530 : 0 : return 0;
3531 : :
3532 : 0 : r = unit_name_from_dbus_path(path, &unit);
3533 [ # # ]: 0 : if (r == -EINVAL) /* not a unit */
3534 : 0 : return 0;
3535 [ # # ]: 0 : if (r < 0) {
3536 : 0 : log_oom();
3537 : 0 : return 0;
3538 : : }
3539 : :
3540 : 0 : session = hashmap_get(m->session_units, unit);
3541 [ # # ]: 0 : if (session)
3542 : 0 : session_add_to_gc_queue(session);
3543 : :
3544 : 0 : user = hashmap_get(m->user_units, unit);
3545 [ # # ]: 0 : if (user)
3546 : 0 : user_add_to_gc_queue(user);
3547 : :
3548 : 0 : return 0;
3549 : : }
3550 : :
3551 : 0 : int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error) {
3552 : 0 : Manager *m = userdata;
3553 : : Session *session;
3554 : : Iterator i;
3555 : : int b, r;
3556 : :
3557 [ # # ]: 0 : assert(message);
3558 [ # # ]: 0 : assert(m);
3559 : :
3560 : 0 : r = sd_bus_message_read(message, "b", &b);
3561 [ # # ]: 0 : if (r < 0) {
3562 [ # # ]: 0 : bus_log_parse_error(r);
3563 : 0 : return 0;
3564 : : }
3565 : :
3566 [ # # ]: 0 : if (b)
3567 : 0 : return 0;
3568 : :
3569 : : /* systemd finished reloading, let's recheck all our sessions */
3570 [ # # ]: 0 : log_debug("System manager has been reloaded, rechecking sessions...");
3571 : :
3572 [ # # ]: 0 : HASHMAP_FOREACH(session, m->sessions, i)
3573 : 0 : session_add_to_gc_queue(session);
3574 : :
3575 : 0 : return 0;
3576 : : }
3577 : :
3578 : 0 : int manager_send_changed(Manager *manager, const char *property, ...) {
3579 : : char **l;
3580 : :
3581 [ # # ]: 0 : assert(manager);
3582 : :
3583 [ # # # # : 0 : l = strv_from_stdarg_alloca(property);
# # # # #
# ]
3584 : :
3585 : 0 : return sd_bus_emit_properties_changed_strv(
3586 : : manager->bus,
3587 : : "/org/freedesktop/login1",
3588 : : "org.freedesktop.login1.Manager",
3589 : : l);
3590 : : }
3591 : :
3592 : 0 : static int strdup_job(sd_bus_message *reply, char **job) {
3593 : : const char *j;
3594 : : char *copy;
3595 : : int r;
3596 : :
3597 : 0 : r = sd_bus_message_read(reply, "o", &j);
3598 [ # # ]: 0 : if (r < 0)
3599 : 0 : return r;
3600 : :
3601 : 0 : copy = strdup(j);
3602 [ # # ]: 0 : if (!copy)
3603 : 0 : return -ENOMEM;
3604 : :
3605 : 0 : *job = copy;
3606 : 0 : return 1;
3607 : : }
3608 : :
3609 : 0 : int manager_start_scope(
3610 : : Manager *manager,
3611 : : const char *scope,
3612 : : pid_t pid,
3613 : : const char *slice,
3614 : : const char *description,
3615 : : char **wants,
3616 : : char **after,
3617 : : const char *requires_mounts_for,
3618 : : sd_bus_message *more_properties,
3619 : : sd_bus_error *error,
3620 : : char **job) {
3621 : :
3622 : 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
3623 : : char **i;
3624 : : int r;
3625 : :
3626 [ # # ]: 0 : assert(manager);
3627 [ # # ]: 0 : assert(scope);
3628 [ # # ]: 0 : assert(pid > 1);
3629 [ # # ]: 0 : assert(job);
3630 : :
3631 : 0 : r = sd_bus_message_new_method_call(
3632 : : manager->bus,
3633 : : &m,
3634 : : "org.freedesktop.systemd1",
3635 : : "/org/freedesktop/systemd1",
3636 : : "org.freedesktop.systemd1.Manager",
3637 : : "StartTransientUnit");
3638 [ # # ]: 0 : if (r < 0)
3639 : 0 : return r;
3640 : :
3641 : 0 : r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
3642 [ # # ]: 0 : if (r < 0)
3643 : 0 : return r;
3644 : :
3645 : 0 : r = sd_bus_message_open_container(m, 'a', "(sv)");
3646 [ # # ]: 0 : if (r < 0)
3647 : 0 : return r;
3648 : :
3649 [ # # ]: 0 : if (!isempty(slice)) {
3650 : 0 : r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
3651 [ # # ]: 0 : if (r < 0)
3652 : 0 : return r;
3653 : : }
3654 : :
3655 [ # # ]: 0 : if (!isempty(description)) {
3656 : 0 : r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
3657 [ # # ]: 0 : if (r < 0)
3658 : 0 : return r;
3659 : : }
3660 : :
3661 [ # # # # ]: 0 : STRV_FOREACH(i, wants) {
3662 : 0 : r = sd_bus_message_append(m, "(sv)", "Wants", "as", 1, *i);
3663 [ # # ]: 0 : if (r < 0)
3664 : 0 : return r;
3665 : : }
3666 : :
3667 [ # # # # ]: 0 : STRV_FOREACH(i, after) {
3668 : 0 : r = sd_bus_message_append(m, "(sv)", "After", "as", 1, *i);
3669 [ # # ]: 0 : if (r < 0)
3670 : 0 : return r;
3671 : : }
3672 : :
3673 [ # # ]: 0 : if (!empty_or_root(requires_mounts_for)) {
3674 : 0 : r = sd_bus_message_append(m, "(sv)", "RequiresMountsFor", "as", 1, requires_mounts_for);
3675 [ # # ]: 0 : if (r < 0)
3676 : 0 : return r;
3677 : : }
3678 : :
3679 : : /* Make sure that the session shells are terminated with SIGHUP since bash and friends tend to ignore
3680 : : * SIGTERM */
3681 : 0 : r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
3682 [ # # ]: 0 : if (r < 0)
3683 : 0 : return r;
3684 : :
3685 : 0 : r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
3686 [ # # ]: 0 : if (r < 0)
3687 : 0 : return r;
3688 : :
3689 : : /* disable TasksMax= for the session scope, rely on the slice setting for it */
3690 : 0 : r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", (uint64_t)-1);
3691 [ # # ]: 0 : if (r < 0)
3692 [ # # ]: 0 : return bus_log_create_error(r);
3693 : :
3694 [ # # ]: 0 : if (more_properties) {
3695 : : /* If TasksMax also appears here, it will overwrite the default value set above */
3696 : 0 : r = sd_bus_message_copy(m, more_properties, true);
3697 [ # # ]: 0 : if (r < 0)
3698 : 0 : return r;
3699 : : }
3700 : :
3701 : 0 : r = sd_bus_message_close_container(m);
3702 [ # # ]: 0 : if (r < 0)
3703 : 0 : return r;
3704 : :
3705 : 0 : r = sd_bus_message_append(m, "a(sa(sv))", 0);
3706 [ # # ]: 0 : if (r < 0)
3707 : 0 : return r;
3708 : :
3709 : 0 : r = sd_bus_call(manager->bus, m, 0, error, &reply);
3710 [ # # ]: 0 : if (r < 0)
3711 : 0 : return r;
3712 : :
3713 : 0 : return strdup_job(reply, job);
3714 : : }
3715 : :
3716 : 0 : int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
3717 : 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3718 : : int r;
3719 : :
3720 [ # # ]: 0 : assert(manager);
3721 [ # # ]: 0 : assert(unit);
3722 [ # # ]: 0 : assert(job);
3723 : :
3724 : 0 : r = sd_bus_call_method(
3725 : : manager->bus,
3726 : : "org.freedesktop.systemd1",
3727 : : "/org/freedesktop/systemd1",
3728 : : "org.freedesktop.systemd1.Manager",
3729 : : "StartUnit",
3730 : : error,
3731 : : &reply,
3732 : : "ss", unit, "replace");
3733 [ # # ]: 0 : if (r < 0)
3734 : 0 : return r;
3735 : :
3736 : 0 : return strdup_job(reply, job);
3737 : : }
3738 : :
3739 : 0 : int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
3740 : 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3741 : : int r;
3742 : :
3743 [ # # ]: 0 : assert(manager);
3744 [ # # ]: 0 : assert(unit);
3745 [ # # ]: 0 : assert(job);
3746 : :
3747 : 0 : r = sd_bus_call_method(
3748 : : manager->bus,
3749 : : "org.freedesktop.systemd1",
3750 : : "/org/freedesktop/systemd1",
3751 : : "org.freedesktop.systemd1.Manager",
3752 : : "StopUnit",
3753 : : error,
3754 : : &reply,
3755 : : "ss", unit, "fail");
3756 [ # # ]: 0 : if (r < 0) {
3757 [ # # # # ]: 0 : if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
3758 : 0 : sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
3759 : :
3760 : 0 : *job = NULL;
3761 : 0 : sd_bus_error_free(error);
3762 : 0 : return 0;
3763 : : }
3764 : :
3765 : 0 : return r;
3766 : : }
3767 : :
3768 : 0 : return strdup_job(reply, job);
3769 : : }
3770 : :
3771 : 0 : int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *ret_error) {
3772 : 0 : _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3773 : 0 : _cleanup_free_ char *path = NULL;
3774 : : int r;
3775 : :
3776 [ # # ]: 0 : assert(manager);
3777 [ # # ]: 0 : assert(scope);
3778 : :
3779 : 0 : path = unit_dbus_path_from_name(scope);
3780 [ # # ]: 0 : if (!path)
3781 : 0 : return -ENOMEM;
3782 : :
3783 : 0 : r = sd_bus_call_method(
3784 : : manager->bus,
3785 : : "org.freedesktop.systemd1",
3786 : : path,
3787 : : "org.freedesktop.systemd1.Scope",
3788 : : "Abandon",
3789 : : &error,
3790 : : NULL,
3791 : : NULL);
3792 [ # # ]: 0 : if (r < 0) {
3793 [ # # # # ]: 0 : if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
3794 [ # # ]: 0 : sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED) ||
3795 : 0 : sd_bus_error_has_name(&error, BUS_ERROR_SCOPE_NOT_RUNNING))
3796 : 0 : return 0;
3797 : :
3798 : 0 : sd_bus_error_move(ret_error, &error);
3799 : 0 : return r;
3800 : : }
3801 : :
3802 : 0 : return 1;
3803 : : }
3804 : :
3805 : 0 : int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
3806 [ # # ]: 0 : assert(manager);
3807 [ # # ]: 0 : assert(unit);
3808 : :
3809 [ # # ]: 0 : return sd_bus_call_method(
3810 : : manager->bus,
3811 : : "org.freedesktop.systemd1",
3812 : : "/org/freedesktop/systemd1",
3813 : : "org.freedesktop.systemd1.Manager",
3814 : : "KillUnit",
3815 : : error,
3816 : : NULL,
3817 : : "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
3818 : : }
3819 : :
3820 : 0 : int manager_unit_is_active(Manager *manager, const char *unit, sd_bus_error *ret_error) {
3821 : 0 : _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3822 : 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3823 : 0 : _cleanup_free_ char *path = NULL;
3824 : : const char *state;
3825 : : int r;
3826 : :
3827 [ # # ]: 0 : assert(manager);
3828 [ # # ]: 0 : assert(unit);
3829 : :
3830 : 0 : path = unit_dbus_path_from_name(unit);
3831 [ # # ]: 0 : if (!path)
3832 : 0 : return -ENOMEM;
3833 : :
3834 : 0 : r = sd_bus_get_property(
3835 : : manager->bus,
3836 : : "org.freedesktop.systemd1",
3837 : : path,
3838 : : "org.freedesktop.systemd1.Unit",
3839 : : "ActiveState",
3840 : : &error,
3841 : : &reply,
3842 : : "s");
3843 [ # # ]: 0 : if (r < 0) {
3844 : : /* systemd might have dropped off momentarily, let's
3845 : : * not make this an error */
3846 [ # # # # ]: 0 : if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
3847 : 0 : sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
3848 : 0 : return true;
3849 : :
3850 : : /* If the unit is already unloaded then it's not
3851 : : * active */
3852 [ # # # # ]: 0 : if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
3853 : 0 : sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
3854 : 0 : return false;
3855 : :
3856 : 0 : sd_bus_error_move(ret_error, &error);
3857 : 0 : return r;
3858 : : }
3859 : :
3860 : 0 : r = sd_bus_message_read(reply, "s", &state);
3861 [ # # ]: 0 : if (r < 0)
3862 : 0 : return r;
3863 : :
3864 : 0 : return !STR_IN_SET(state, "inactive", "failed");
3865 : : }
3866 : :
3867 : 0 : int manager_job_is_active(Manager *manager, const char *path, sd_bus_error *ret_error) {
3868 : 0 : _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3869 : 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3870 : : int r;
3871 : :
3872 [ # # ]: 0 : assert(manager);
3873 [ # # ]: 0 : assert(path);
3874 : :
3875 : 0 : r = sd_bus_get_property(
3876 : : manager->bus,
3877 : : "org.freedesktop.systemd1",
3878 : : path,
3879 : : "org.freedesktop.systemd1.Job",
3880 : : "State",
3881 : : &error,
3882 : : &reply,
3883 : : "s");
3884 [ # # ]: 0 : if (r < 0) {
3885 [ # # # # ]: 0 : if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
3886 : 0 : sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
3887 : 0 : return true;
3888 : :
3889 [ # # ]: 0 : if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
3890 : 0 : return false;
3891 : :
3892 : 0 : sd_bus_error_move(ret_error, &error);
3893 : 0 : return r;
3894 : : }
3895 : :
3896 : : /* We don't actually care about the state really. The fact
3897 : : * that we could read the job state is enough for us */
3898 : :
3899 : 0 : return true;
3900 : : }
|