]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/login/logind-session.c
polkit: turn "interactive" flag to polkit APIs into a proper flags field (#31715)
[thirdparty/systemd.git] / src / login / logind-session.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <linux/kd.h>
6 #include <linux/vt.h>
7 #include <signal.h>
8 #include <sys/ioctl.h>
9 #include <sys/stat.h>
10 #include <unistd.h>
11
12 #include "sd-messages.h"
13
14 #include "alloc-util.h"
15 #include "audit-util.h"
16 #include "bus-error.h"
17 #include "bus-util.h"
18 #include "daemon-util.h"
19 #include "devnum-util.h"
20 #include "env-file.h"
21 #include "escape.h"
22 #include "fd-util.h"
23 #include "fileio.h"
24 #include "format-util.h"
25 #include "fs-util.h"
26 #include "io-util.h"
27 #include "logind-dbus.h"
28 #include "logind-seat-dbus.h"
29 #include "logind-session-dbus.h"
30 #include "logind-session.h"
31 #include "logind-user-dbus.h"
32 #include "mkdir-label.h"
33 #include "parse-util.h"
34 #include "path-util.h"
35 #include "process-util.h"
36 #include "serialize.h"
37 #include "string-table.h"
38 #include "strv.h"
39 #include "terminal-util.h"
40 #include "tmpfile-util.h"
41 #include "uid-classification.h"
42 #include "user-util.h"
43
44 #define RELEASE_USEC (20*USEC_PER_SEC)
45
46 static void session_remove_fifo(Session *s);
47 static void session_restore_vt(Session *s);
48
49 int session_new(Manager *m, const char *id, Session **ret) {
50 _cleanup_(session_freep) Session *s = NULL;
51 int r;
52
53 assert(m);
54 assert(id);
55 assert(ret);
56
57 if (!session_id_valid(id))
58 return -EINVAL;
59
60 s = new(Session, 1);
61 if (!s)
62 return -ENOMEM;
63
64 *s = (Session) {
65 .manager = m,
66 .id = strdup(id),
67 .state_file = path_join("/run/systemd/sessions/", id),
68 .fifo_fd = -EBADF,
69 .vtfd = -EBADF,
70 .audit_id = AUDIT_SESSION_INVALID,
71 .tty_validity = _TTY_VALIDITY_INVALID,
72 .leader = PIDREF_NULL,
73 };
74 if (!s->id || !s->state_file)
75 return -ENOMEM;
76
77 s->devices = hashmap_new(&devt_hash_ops);
78 if (!s->devices)
79 return -ENOMEM;
80
81 r = hashmap_put(m->sessions, s->id, s);
82 if (r < 0)
83 return r;
84
85 *ret = TAKE_PTR(s);
86 return 0;
87 }
88
89 static int session_dispatch_leader_pidfd(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
90 Session *s = ASSERT_PTR(userdata);
91
92 assert(s->leader.fd == fd);
93 session_stop(s, /* force= */ false);
94
95 return 1;
96 }
97
98 static int session_watch_pidfd(Session *s) {
99 int r;
100
101 assert(s);
102 assert(s->manager);
103 assert(pidref_is_set(&s->leader));
104
105 if (s->leader.fd < 0)
106 return 0;
107
108 r = sd_event_add_io(s->manager->event, &s->leader_pidfd_event_source, s->leader.fd, EPOLLIN, session_dispatch_leader_pidfd, s);
109 if (r < 0)
110 return r;
111
112 r = sd_event_source_set_priority(s->leader_pidfd_event_source, SD_EVENT_PRIORITY_IMPORTANT);
113 if (r < 0)
114 return r;
115
116 (void) sd_event_source_set_description(s->leader_pidfd_event_source, "session-pidfd");
117
118 return 0;
119 }
120
121 static void session_reset_leader(Session *s, bool keep_fdstore) {
122 assert(s);
123
124 if (!keep_fdstore) {
125 /* Clear fdstore if we're asked to, no matter if s->leader is set or not, so that when
126 * initially deserializing leader fd we clear the old fd too. */
127 (void) notify_remove_fd_warnf("session-%s-leader-fd", s->id);
128 s->leader_fd_saved = false;
129 }
130
131 if (!pidref_is_set(&s->leader))
132 return;
133
134 s->leader_pidfd_event_source = sd_event_source_disable_unref(s->leader_pidfd_event_source);
135
136 (void) hashmap_remove_value(s->manager->sessions_by_leader, &s->leader, s);
137
138 return pidref_done(&s->leader);
139 }
140
141 Session* session_free(Session *s) {
142 SessionDevice *sd;
143
144 if (!s)
145 return NULL;
146
147 sd_event_source_unref(s->stop_on_idle_event_source);
148
149 if (s->in_gc_queue)
150 LIST_REMOVE(gc_queue, s->manager->session_gc_queue, s);
151
152 sd_event_source_unref(s->timer_event_source);
153
154 session_drop_controller(s);
155
156 while ((sd = hashmap_first(s->devices)))
157 session_device_free(sd);
158
159 hashmap_free(s->devices);
160
161 if (s->user) {
162 LIST_REMOVE(sessions_by_user, s->user->sessions, s);
163
164 if (s->user->display == s)
165 s->user->display = NULL;
166
167 user_update_last_session_timer(s->user);
168 }
169
170 if (s->seat) {
171 if (s->seat->active == s)
172 s->seat->active = NULL;
173 if (s->seat->pending_switch == s)
174 s->seat->pending_switch = NULL;
175
176 seat_evict_position(s->seat, s);
177 LIST_REMOVE(sessions_by_seat, s->seat->sessions, s);
178 }
179
180 if (s->scope) {
181 hashmap_remove(s->manager->session_units, s->scope);
182 free(s->scope);
183 }
184
185 free(s->scope_job);
186
187 session_reset_leader(s, /* keep_fdstore = */ true);
188
189 sd_bus_message_unref(s->create_message);
190 sd_bus_message_unref(s->upgrade_message);
191
192 free(s->tty);
193 free(s->display);
194 free(s->remote_host);
195 free(s->remote_user);
196 free(s->service);
197 free(s->desktop);
198
199 hashmap_remove(s->manager->sessions, s->id);
200
201 sd_event_source_unref(s->fifo_event_source);
202 safe_close(s->fifo_fd);
203
204 /* Note that we remove neither the state file nor the fifo path here, since we want both to survive
205 * daemon restarts */
206 free(s->fifo_path);
207 free(s->state_file);
208 free(s->id);
209
210 return mfree(s);
211 }
212
213 void session_set_user(Session *s, User *u) {
214 assert(s);
215 assert(!s->user);
216
217 s->user = u;
218 LIST_PREPEND(sessions_by_user, u->sessions, s);
219
220 user_update_last_session_timer(u);
221 }
222
223 int session_set_leader_consume(Session *s, PidRef _leader) {
224 _cleanup_(pidref_done) PidRef pidref = _leader;
225 int r;
226
227 assert(s);
228 assert(pidref_is_set(&pidref));
229
230 if (pidref_equal(&s->leader, &pidref))
231 return 0;
232
233 session_reset_leader(s, /* keep_fdstore = */ false);
234
235 s->leader = TAKE_PIDREF(pidref);
236
237 r = session_watch_pidfd(s);
238 if (r < 0)
239 return log_error_errno(r, "Failed to watch leader pidfd for session '%s': %m", s->id);
240
241 r = hashmap_ensure_put(&s->manager->sessions_by_leader, &pidref_hash_ops, &s->leader, s);
242 if (r < 0)
243 return r;
244 assert(r > 0);
245
246 if (s->leader.fd >= 0) {
247 r = notify_push_fdf(s->leader.fd, "session-%s-leader-fd", s->id);
248 if (r < 0)
249 log_warning_errno(r, "Failed to push leader pidfd for session '%s', ignoring: %m", s->id);
250 else
251 s->leader_fd_saved = true;
252 }
253
254 (void) audit_session_from_pid(s->leader.pid, &s->audit_id);
255
256 return 1;
257 }
258
259 static void session_save_devices(Session *s, FILE *f) {
260 SessionDevice *sd;
261
262 if (!hashmap_isempty(s->devices)) {
263 fprintf(f, "DEVICES=");
264 HASHMAP_FOREACH(sd, s->devices)
265 fprintf(f, DEVNUM_FORMAT_STR " ", DEVNUM_FORMAT_VAL(sd->dev));
266 fprintf(f, "\n");
267 }
268 }
269
270 int session_save(Session *s) {
271 _cleanup_(unlink_and_freep) char *temp_path = NULL;
272 _cleanup_fclose_ FILE *f = NULL;
273 int r;
274
275 assert(s);
276
277 if (!s->user)
278 return -ESTALE;
279
280 if (!s->started)
281 return 0;
282
283 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, MKDIR_WARN_MODE);
284 if (r < 0)
285 goto fail;
286
287 r = fopen_temporary(s->state_file, &f, &temp_path);
288 if (r < 0)
289 goto fail;
290
291 (void) fchmod(fileno(f), 0644);
292
293 fprintf(f,
294 "# This is private data. Do not parse.\n"
295 "UID="UID_FMT"\n"
296 "USER=%s\n"
297 "ACTIVE=%s\n"
298 "IS_DISPLAY=%s\n"
299 "STATE=%s\n"
300 "REMOTE=%s\n"
301 "LEADER_FD_SAVED=%s\n",
302 s->user->user_record->uid,
303 s->user->user_record->user_name,
304 one_zero(session_is_active(s)),
305 one_zero(s->user->display == s),
306 session_state_to_string(session_get_state(s)),
307 one_zero(s->remote),
308 one_zero(s->leader_fd_saved));
309
310 if (s->type >= 0)
311 fprintf(f, "TYPE=%s\n", session_type_to_string(s->type));
312
313 if (s->original_type >= 0)
314 fprintf(f, "ORIGINAL_TYPE=%s\n", session_type_to_string(s->original_type));
315
316 if (s->class >= 0)
317 fprintf(f, "CLASS=%s\n", session_class_to_string(s->class));
318
319 if (s->scope)
320 fprintf(f, "SCOPE=%s\n", s->scope);
321 if (s->scope_job)
322 fprintf(f, "SCOPE_JOB=%s\n", s->scope_job);
323
324 if (s->fifo_path)
325 fprintf(f, "FIFO=%s\n", s->fifo_path);
326
327 if (s->seat)
328 fprintf(f, "SEAT=%s\n", s->seat->id);
329
330 if (s->tty)
331 fprintf(f, "TTY=%s\n", s->tty);
332
333 if (s->tty_validity >= 0)
334 fprintf(f, "TTY_VALIDITY=%s\n", tty_validity_to_string(s->tty_validity));
335
336 if (s->display)
337 fprintf(f, "DISPLAY=%s\n", s->display);
338
339 if (s->remote_host) {
340 _cleanup_free_ char *escaped = NULL;
341
342 escaped = cescape(s->remote_host);
343 if (!escaped) {
344 r = -ENOMEM;
345 goto fail;
346 }
347
348 fprintf(f, "REMOTE_HOST=%s\n", escaped);
349 }
350
351 if (s->remote_user) {
352 _cleanup_free_ char *escaped = NULL;
353
354 escaped = cescape(s->remote_user);
355 if (!escaped) {
356 r = -ENOMEM;
357 goto fail;
358 }
359
360 fprintf(f, "REMOTE_USER=%s\n", escaped);
361 }
362
363 if (s->service) {
364 _cleanup_free_ char *escaped = NULL;
365
366 escaped = cescape(s->service);
367 if (!escaped) {
368 r = -ENOMEM;
369 goto fail;
370 }
371
372 fprintf(f, "SERVICE=%s\n", escaped);
373 }
374
375 if (s->desktop) {
376 _cleanup_free_ char *escaped = NULL;
377
378 escaped = cescape(s->desktop);
379 if (!escaped) {
380 r = -ENOMEM;
381 goto fail;
382 }
383
384 fprintf(f, "DESKTOP=%s\n", escaped);
385 }
386
387 if (s->seat && seat_has_vts(s->seat))
388 fprintf(f, "VTNR=%u\n", s->vtnr);
389
390 if (!s->vtnr)
391 fprintf(f, "POSITION=%u\n", s->position);
392
393 if (pidref_is_set(&s->leader))
394 fprintf(f, "LEADER="PID_FMT"\n", s->leader.pid);
395
396 if (audit_session_is_valid(s->audit_id))
397 fprintf(f, "AUDIT=%"PRIu32"\n", s->audit_id);
398
399 if (dual_timestamp_is_set(&s->timestamp))
400 fprintf(f,
401 "REALTIME="USEC_FMT"\n"
402 "MONOTONIC="USEC_FMT"\n",
403 s->timestamp.realtime,
404 s->timestamp.monotonic);
405
406 if (s->controller) {
407 fprintf(f, "CONTROLLER=%s\n", s->controller);
408 session_save_devices(s, f);
409 }
410
411 r = fflush_and_check(f);
412 if (r < 0)
413 goto fail;
414
415 if (rename(temp_path, s->state_file) < 0) {
416 r = -errno;
417 goto fail;
418 }
419
420 temp_path = mfree(temp_path);
421 return 0;
422
423 fail:
424 (void) unlink(s->state_file);
425
426 return log_error_errno(r, "Failed to save session data %s: %m", s->state_file);
427 }
428
429 static int session_load_devices(Session *s, const char *devices) {
430 int r = 0;
431
432 assert(s);
433
434 for (const char *p = devices;;) {
435 _cleanup_free_ char *word = NULL;
436 dev_t dev;
437 int k;
438
439 k = extract_first_word(&p, &word, NULL, 0);
440 if (k <= 0) {
441 RET_GATHER(r, k);
442 break;
443 }
444
445 k = parse_devnum(word, &dev);
446 if (k < 0) {
447 RET_GATHER(r, k);
448 continue;
449 }
450
451 /* The file descriptors for loaded devices will be reattached later. */
452 RET_GATHER(r, session_device_new(s, dev, /* open_device = */ false, /* ret = */ NULL));
453 }
454
455 if (r < 0)
456 log_error_errno(r, "Failed to load some session devices for session '%s': %m", s->id);
457 return r;
458 }
459
460 int session_load(Session *s) {
461 _cleanup_free_ char *remote = NULL,
462 *seat = NULL,
463 *tty_validity = NULL,
464 *vtnr = NULL,
465 *state = NULL,
466 *position = NULL,
467 *leader_pid = NULL,
468 *leader_fd_saved = NULL,
469 *type = NULL,
470 *original_type = NULL,
471 *class = NULL,
472 *uid = NULL,
473 *realtime = NULL,
474 *monotonic = NULL,
475 *controller = NULL,
476 *active = NULL,
477 *devices = NULL,
478 *is_display = NULL;
479
480 int k, r;
481
482 assert(s);
483
484 r = parse_env_file(NULL, s->state_file,
485 "REMOTE", &remote,
486 "SCOPE", &s->scope,
487 "SCOPE_JOB", &s->scope_job,
488 "FIFO", &s->fifo_path,
489 "SEAT", &seat,
490 "TTY", &s->tty,
491 "TTY_VALIDITY", &tty_validity,
492 "DISPLAY", &s->display,
493 "REMOTE_HOST", &s->remote_host,
494 "REMOTE_USER", &s->remote_user,
495 "SERVICE", &s->service,
496 "DESKTOP", &s->desktop,
497 "VTNR", &vtnr,
498 "STATE", &state,
499 "POSITION", &position,
500 "LEADER", &leader_pid,
501 "LEADER_FD_SAVED", &leader_fd_saved,
502 "TYPE", &type,
503 "ORIGINAL_TYPE", &original_type,
504 "CLASS", &class,
505 "UID", &uid,
506 "REALTIME", &realtime,
507 "MONOTONIC", &monotonic,
508 "CONTROLLER", &controller,
509 "ACTIVE", &active,
510 "DEVICES", &devices,
511 "IS_DISPLAY", &is_display);
512 if (r < 0)
513 return log_error_errno(r, "Failed to read %s: %m", s->state_file);
514
515 if (!s->user) {
516 uid_t u;
517 User *user;
518
519 if (!uid)
520 return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
521 "UID not specified for session %s",
522 s->id);
523
524 r = parse_uid(uid, &u);
525 if (r < 0) {
526 log_error("Failed to parse UID value %s for session %s.", uid, s->id);
527 return r;
528 }
529
530 user = hashmap_get(s->manager->users, UID_TO_PTR(u));
531 if (!user)
532 return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
533 "User of session %s not known.",
534 s->id);
535
536 session_set_user(s, user);
537 }
538
539 if (remote) {
540 k = parse_boolean(remote);
541 if (k >= 0)
542 s->remote = k;
543 }
544
545 if (vtnr)
546 safe_atou(vtnr, &s->vtnr);
547
548 if (seat && !s->seat) {
549 Seat *o;
550
551 o = hashmap_get(s->manager->seats, seat);
552 if (o)
553 r = seat_attach_session(o, s);
554 if (!o || r < 0)
555 log_error("Cannot attach session %s to seat %s", s->id, seat);
556 }
557
558 if (!s->seat || !seat_has_vts(s->seat))
559 s->vtnr = 0;
560
561 if (position && s->seat) {
562 unsigned npos;
563
564 safe_atou(position, &npos);
565 seat_claim_position(s->seat, s, npos);
566 }
567
568 if (tty_validity) {
569 TTYValidity v;
570
571 v = tty_validity_from_string(tty_validity);
572 if (v < 0)
573 log_debug("Failed to parse TTY validity: %s", tty_validity);
574 else
575 s->tty_validity = v;
576 }
577
578 if (type) {
579 SessionType t;
580
581 t = session_type_from_string(type);
582 if (t >= 0)
583 s->type = t;
584 }
585
586 if (original_type) {
587 SessionType ot;
588
589 ot = session_type_from_string(original_type);
590 if (ot >= 0)
591 s->original_type = ot;
592 } else
593 /* Pre-v246 compat: initialize original_type if not set in the state file */
594 s->original_type = s->type;
595
596 if (class) {
597 SessionClass c;
598
599 c = session_class_from_string(class);
600 if (c >= 0)
601 s->class = c;
602 }
603
604 if (streq_ptr(state, "closing"))
605 s->stopping = true;
606
607 if (s->fifo_path) {
608 int fd;
609
610 /* If we open an unopened pipe for reading we will not
611 get an EOF. to trigger an EOF we hence open it for
612 writing, but close it right away which then will
613 trigger the EOF. This will happen immediately if no
614 other process has the FIFO open for writing, i. e.
615 when the session died before logind (re)started. */
616
617 fd = session_create_fifo(s);
618 safe_close(fd);
619 }
620
621 if (realtime)
622 (void) deserialize_usec(realtime, &s->timestamp.realtime);
623 if (monotonic)
624 (void) deserialize_usec(monotonic, &s->timestamp.monotonic);
625
626 if (active) {
627 k = parse_boolean(active);
628 if (k >= 0)
629 s->was_active = k;
630 }
631
632 if (is_display) {
633 /* Note that when enumerating users are loaded before sessions, hence the display session to use is
634 * something we have to store along with the session and not the user, as in that case we couldn't
635 * apply it at the time we load the user. */
636
637 k = parse_boolean(is_display);
638 if (k < 0)
639 log_warning_errno(k, "Failed to parse IS_DISPLAY session property: %m");
640 else if (k > 0)
641 s->user->display = s;
642 }
643
644 if (controller) {
645 if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0) {
646 session_set_controller(s, controller, false, false);
647 session_load_devices(s, devices);
648 } else
649 session_restore_vt(s);
650 }
651
652 if (leader_pid) {
653 assert(!pidref_is_set(&s->leader));
654
655 r = parse_pid(leader_pid, &s->deserialized_pid);
656 if (r < 0)
657 return log_error_errno(r, "Failed to parse LEADER=%s: %m", leader_pid);
658
659 if (leader_fd_saved) {
660 r = parse_boolean(leader_fd_saved);
661 if (r < 0)
662 return log_error_errno(r, "Failed to parse LEADER_FD_SAVED=%s: %m", leader_fd_saved);
663 s->leader_fd_saved = r > 0;
664
665 if (s->leader_fd_saved)
666 /* The leader fd will be acquired from fdstore later */
667 return 0;
668 }
669
670 _cleanup_(pidref_done) PidRef p = PIDREF_NULL;
671
672 r = pidref_set_pid(&p, s->deserialized_pid);
673 if (r >= 0)
674 r = session_set_leader_consume(s, TAKE_PIDREF(p));
675 if (r < 0)
676 log_warning_errno(r, "Failed to set leader PID for session '%s': %m", s->id);
677 }
678
679 return r;
680 }
681
682 int session_activate(Session *s) {
683 unsigned num_pending;
684
685 assert(s);
686 assert(s->user);
687
688 if (!s->seat)
689 return -EOPNOTSUPP;
690
691 if (s->seat->active == s)
692 return 0;
693
694 /* on seats with VTs, we let VTs manage session-switching */
695 if (seat_has_vts(s->seat)) {
696 if (s->vtnr == 0)
697 return -EOPNOTSUPP;
698
699 return chvt(s->vtnr);
700 }
701
702 /* On seats without VTs, we implement session-switching in logind. We
703 * try to pause all session-devices and wait until the session
704 * controller acknowledged them. Once all devices are asleep, we simply
705 * switch the active session and be done.
706 * We save the session we want to switch to in seat->pending_switch and
707 * seat_complete_switch() will perform the final switch. */
708
709 s->seat->pending_switch = s;
710
711 /* if no devices are running, immediately perform the session switch */
712 num_pending = session_device_try_pause_all(s);
713 if (!num_pending)
714 seat_complete_switch(s->seat);
715
716 return 0;
717 }
718
719 static int session_start_scope(Session *s, sd_bus_message *properties, sd_bus_error *error) {
720 _cleanup_free_ char *scope = NULL;
721 const char *description;
722 int r;
723
724 assert(s);
725 assert(s->user);
726
727 if (!SESSION_CLASS_WANTS_SCOPE(s->class))
728 return 0;
729
730 if (s->scope)
731 goto finish;
732
733 s->scope_job = mfree(s->scope_job);
734
735 scope = strjoin("session-", s->id, ".scope");
736 if (!scope)
737 return log_oom();
738
739 description = strjoina("Session ", s->id, " of User ", s->user->user_record->user_name);
740
741 r = manager_start_scope(
742 s->manager,
743 scope,
744 &s->leader,
745 s->user->slice,
746 description,
747 /* These should have been pulled in explicitly in user_start(). Just to be sure. */
748 STRV_MAKE_CONST(s->user->runtime_dir_unit,
749 SESSION_CLASS_WANTS_SERVICE_MANAGER(s->class) ? s->user->service_manager_unit : NULL),
750 /* We usually want to order session scopes after systemd-user-sessions.service
751 * since the unit is used as login session barrier for unprivileged users. However
752 * the barrier doesn't apply for root as sysadmin should always be able to log in
753 * (and without waiting for any timeout to expire) in case something goes wrong
754 * during the boot process. */
755 STRV_MAKE_CONST("systemd-logind.service",
756 SESSION_CLASS_IS_EARLY(s->class) ? NULL : "systemd-user-sessions.service"),
757 user_record_home_directory(s->user->user_record),
758 properties,
759 error,
760 &s->scope_job);
761 if (r < 0)
762 return log_error_errno(r, "Failed to start session scope %s: %s",
763 scope, bus_error_message(error, r));
764
765 s->scope = TAKE_PTR(scope);
766
767 finish:
768 (void) hashmap_put(s->manager->session_units, s->scope, s);
769 return 0;
770 }
771
772 static int session_dispatch_stop_on_idle(sd_event_source *source, uint64_t t, void *userdata) {
773 Session *s = userdata;
774 dual_timestamp ts;
775 int r, idle;
776
777 assert(s);
778
779 if (s->stopping)
780 return 0;
781
782 idle = session_get_idle_hint(s, &ts);
783 if (idle) {
784 log_info("Session \"%s\" of user \"%s\" is idle, stopping.", s->id, s->user->user_record->user_name);
785
786 return session_stop(s, /* force */ true);
787 }
788
789 r = sd_event_source_set_time(
790 source,
791 usec_add(dual_timestamp_is_set(&ts) ? ts.monotonic : now(CLOCK_MONOTONIC),
792 s->manager->stop_idle_session_usec));
793 if (r < 0)
794 return log_error_errno(r, "Failed to configure stop on idle session event source: %m");
795
796 r = sd_event_source_set_enabled(source, SD_EVENT_ONESHOT);
797 if (r < 0)
798 return log_error_errno(r, "Failed to enable stop on idle session event source: %m");
799
800 return 1;
801 }
802
803 static int session_setup_stop_on_idle_timer(Session *s) {
804 int r;
805
806 assert(s);
807
808 if (s->manager->stop_idle_session_usec == USEC_INFINITY || !SESSION_CLASS_CAN_STOP_ON_IDLE(s->class))
809 return 0;
810
811 r = sd_event_add_time_relative(
812 s->manager->event,
813 &s->stop_on_idle_event_source,
814 CLOCK_MONOTONIC,
815 s->manager->stop_idle_session_usec,
816 0,
817 session_dispatch_stop_on_idle, s);
818 if (r < 0)
819 return log_error_errno(r, "Failed to add stop on idle session event source: %m");
820
821 return 0;
822 }
823
824 int session_start(Session *s, sd_bus_message *properties, sd_bus_error *error) {
825 int r;
826
827 assert(s);
828
829 if (!s->user)
830 return -ESTALE;
831
832 if (s->stopping)
833 return -EINVAL;
834
835 if (s->started)
836 return 0;
837
838 r = user_start(s->user);
839 if (r < 0)
840 return r;
841
842 r = session_start_scope(s, properties, error);
843 if (r < 0)
844 return r;
845
846 r = session_setup_stop_on_idle_timer(s);
847 if (r < 0)
848 return r;
849
850 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
851 "MESSAGE_ID=" SD_MESSAGE_SESSION_START_STR,
852 "SESSION_ID=%s", s->id,
853 "USER_ID=%s", s->user->user_record->user_name,
854 "LEADER="PID_FMT, s->leader.pid,
855 LOG_MESSAGE("New session %s of user %s.", s->id, s->user->user_record->user_name));
856
857 if (!dual_timestamp_is_set(&s->timestamp))
858 dual_timestamp_now(&s->timestamp);
859
860 if (s->seat)
861 seat_read_active_vt(s->seat);
862
863 s->started = true;
864
865 user_elect_display(s->user);
866
867 /* Save data */
868 (void) session_save(s);
869 (void) user_save(s->user);
870 if (s->seat)
871 (void) seat_save(s->seat);
872
873 /* Send signals */
874 session_send_signal(s, true);
875 user_send_changed(s->user, "Display", NULL);
876
877 if (s->seat && s->seat->active == s)
878 (void) seat_send_changed(s->seat, "ActiveSession", NULL);
879
880 return 0;
881 }
882
883 static int session_stop_scope(Session *s, bool force) {
884 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
885 int r;
886
887 assert(s);
888
889 if (!s->scope)
890 return 0;
891
892 /* Let's always abandon the scope first. This tells systemd that we are not interested anymore, and everything
893 * that is left in the scope is "left-over". Informing systemd about this has the benefit that it will log
894 * when killing any processes left after this point. */
895 r = manager_abandon_scope(s->manager, s->scope, &error);
896 if (r < 0) {
897 log_warning_errno(r, "Failed to abandon session scope, ignoring: %s", bus_error_message(&error, r));
898 sd_bus_error_free(&error);
899 }
900
901 s->scope_job = mfree(s->scope_job);
902
903 /* Optionally, let's kill everything that's left now. */
904 if (force ||
905 (s->user->user_record->kill_processes != 0 &&
906 (s->user->user_record->kill_processes > 0 ||
907 manager_shall_kill(s->manager, s->user->user_record->user_name)))) {
908
909 r = manager_stop_unit(s->manager, s->scope, force ? "replace" : "fail", &error, &s->scope_job);
910 if (r < 0) {
911 if (force)
912 return log_error_errno(r, "Failed to stop session scope: %s", bus_error_message(&error, r));
913
914 log_warning_errno(r, "Failed to stop session scope, ignoring: %s", bus_error_message(&error, r));
915 }
916 } else {
917
918 /* With no killing, this session is allowed to persist in "closing" state indefinitely.
919 * Therefore session stop and session removal may be two distinct events.
920 * Session stop is quite significant on its own, let's log it. */
921 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
922 "SESSION_ID=%s", s->id,
923 "USER_ID=%s", s->user->user_record->user_name,
924 "LEADER="PID_FMT, s->leader.pid,
925 LOG_MESSAGE("Session %s logged out. Waiting for processes to exit.", s->id));
926 }
927
928 return 0;
929 }
930
931 int session_stop(Session *s, bool force) {
932 int r;
933
934 assert(s);
935
936 /* This is called whenever we begin with tearing down a session record. It's called in four cases: explicit API
937 * request via the bus (either directly for the session object or for the seat or user object this session
938 * belongs to; 'force' is true), or due to automatic GC (i.e. scope vanished; 'force' is false), or because the
939 * session FIFO saw an EOF ('force' is false), or because the release timer hit ('force' is false). */
940
941 if (!s->user)
942 return -ESTALE;
943 if (!s->started)
944 return 0;
945 if (s->stopping)
946 return 0;
947
948 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
949 s->leader_pidfd_event_source = sd_event_source_unref(s->leader_pidfd_event_source);
950
951 if (s->seat)
952 seat_evict_position(s->seat, s);
953
954 /* We are going down, don't care about FIFOs anymore */
955 session_remove_fifo(s);
956
957 /* Kill cgroup */
958 r = session_stop_scope(s, force);
959
960 s->stopping = true;
961
962 user_elect_display(s->user);
963
964 (void) session_save(s);
965 (void) user_save(s->user);
966
967 return r;
968 }
969
970 int session_finalize(Session *s) {
971 SessionDevice *sd;
972
973 assert(s);
974
975 if (!s->user)
976 return -ESTALE;
977
978 if (s->started)
979 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
980 "MESSAGE_ID=" SD_MESSAGE_SESSION_STOP_STR,
981 "SESSION_ID=%s", s->id,
982 "USER_ID=%s", s->user->user_record->user_name,
983 "LEADER="PID_FMT, s->leader.pid,
984 LOG_MESSAGE("Removed session %s.", s->id));
985
986 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
987
988 if (s->seat)
989 seat_evict_position(s->seat, s);
990
991 /* Kill session devices */
992 while ((sd = hashmap_first(s->devices)))
993 session_device_free(sd);
994
995 (void) unlink(s->state_file);
996 session_add_to_gc_queue(s);
997 user_add_to_gc_queue(s->user);
998
999 if (s->started) {
1000 session_send_signal(s, false);
1001 s->started = false;
1002 }
1003
1004 if (s->seat) {
1005 if (s->seat->active == s)
1006 seat_set_active(s->seat, NULL);
1007
1008 seat_save(s->seat);
1009 }
1010
1011 session_reset_leader(s, /* keep_fdstore = */ false);
1012
1013 (void) user_save(s->user);
1014 (void) user_send_changed(s->user, "Display", NULL);
1015
1016 return 0;
1017 }
1018
1019 static int release_timeout_callback(sd_event_source *es, uint64_t usec, void *userdata) {
1020 Session *s = ASSERT_PTR(userdata);
1021
1022 assert(es);
1023
1024 session_stop(s, /* force = */ false);
1025 return 0;
1026 }
1027
1028 int session_release(Session *s) {
1029 assert(s);
1030
1031 if (!s->started || s->stopping)
1032 return 0;
1033
1034 if (s->timer_event_source)
1035 return 0;
1036
1037 return sd_event_add_time_relative(
1038 s->manager->event,
1039 &s->timer_event_source,
1040 CLOCK_MONOTONIC,
1041 RELEASE_USEC, 0,
1042 release_timeout_callback, s);
1043 }
1044
1045 bool session_is_active(Session *s) {
1046 assert(s);
1047
1048 if (!s->seat)
1049 return true;
1050
1051 return s->seat->active == s;
1052 }
1053
1054 static int get_tty_atime(const char *tty, usec_t *atime) {
1055 _cleanup_free_ char *p = NULL;
1056 struct stat st;
1057
1058 assert(tty);
1059 assert(atime);
1060
1061 if (!path_is_absolute(tty)) {
1062 p = path_join("/dev", tty);
1063 if (!p)
1064 return -ENOMEM;
1065
1066 tty = p;
1067 } else if (!path_startswith(tty, "/dev/"))
1068 return -ENOENT;
1069
1070 if (lstat(tty, &st) < 0)
1071 return -errno;
1072
1073 *atime = timespec_load(&st.st_atim);
1074 return 0;
1075 }
1076
1077 static int get_process_ctty_atime(pid_t pid, usec_t *atime) {
1078 _cleanup_free_ char *p = NULL;
1079 int r;
1080
1081 assert(pid > 0);
1082 assert(atime);
1083
1084 r = get_ctty(pid, NULL, &p);
1085 if (r < 0)
1086 return r;
1087
1088 return get_tty_atime(p, atime);
1089 }
1090
1091 int session_get_idle_hint(Session *s, dual_timestamp *t) {
1092 usec_t atime = 0, dtime = 0;
1093 int r;
1094
1095 assert(s);
1096
1097 /* Graphical sessions have an explicit idle hint */
1098 if (SESSION_TYPE_IS_GRAPHICAL(s->type)) {
1099 if (t)
1100 *t = s->idle_hint_timestamp;
1101
1102 return s->idle_hint;
1103 }
1104
1105 if (s->type == SESSION_TTY) {
1106 /* For sessions with an explicitly configured tty, let's check its atime */
1107 if (s->tty) {
1108 r = get_tty_atime(s->tty, &atime);
1109 if (r >= 0)
1110 goto found_atime;
1111 }
1112
1113 /* For sessions with a leader but no explicitly configured tty, let's check the controlling tty of
1114 * the leader */
1115 if (pidref_is_set(&s->leader)) {
1116 r = get_process_ctty_atime(s->leader.pid, &atime);
1117 if (r >= 0)
1118 goto found_atime;
1119 }
1120 }
1121
1122 if (t)
1123 *t = DUAL_TIMESTAMP_NULL;
1124
1125 return false;
1126
1127 found_atime:
1128 if (t)
1129 dual_timestamp_from_realtime(t, atime);
1130
1131 if (s->manager->idle_action_usec > 0 && s->manager->stop_idle_session_usec != USEC_INFINITY)
1132 dtime = MIN(s->manager->idle_action_usec, s->manager->stop_idle_session_usec);
1133 else if (s->manager->idle_action_usec > 0)
1134 dtime = s->manager->idle_action_usec;
1135 else if (s->manager->stop_idle_session_usec != USEC_INFINITY)
1136 dtime = s->manager->stop_idle_session_usec;
1137 else
1138 return false;
1139
1140 return usec_add(atime, dtime) <= now(CLOCK_REALTIME);
1141 }
1142
1143 int session_set_idle_hint(Session *s, bool b) {
1144 assert(s);
1145
1146 if (!SESSION_CLASS_CAN_IDLE(s->class)) /* Only some session classes know the idle concept at all */
1147 return -ENOTTY;
1148 if (!SESSION_TYPE_IS_GRAPHICAL(s->type)) /* And only graphical session types can set the field explicitly */
1149 return -ENOTTY;
1150
1151 if (s->idle_hint == b)
1152 return 0;
1153
1154 s->idle_hint = b;
1155 dual_timestamp_now(&s->idle_hint_timestamp);
1156
1157 session_send_changed(s, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
1158
1159 if (s->seat)
1160 seat_send_changed(s->seat, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
1161
1162 user_send_changed(s->user, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
1163 manager_send_changed(s->manager, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
1164
1165 return 1;
1166 }
1167
1168 int session_get_locked_hint(Session *s) {
1169 assert(s);
1170
1171 return s->locked_hint;
1172 }
1173
1174 int session_set_locked_hint(Session *s, bool b) {
1175 assert(s);
1176
1177 if (!SESSION_CLASS_CAN_LOCK(s->class))
1178 return -ENOTTY;
1179
1180 if (s->locked_hint == b)
1181 return 0;
1182
1183 s->locked_hint = b;
1184 (void) session_save(s);
1185 (void) session_send_changed(s, "LockedHint", NULL);
1186
1187 return 1;
1188 }
1189
1190 void session_set_type(Session *s, SessionType t) {
1191 assert(s);
1192
1193 if (s->type == t)
1194 return;
1195
1196 s->type = t;
1197 (void) session_save(s);
1198 (void) session_send_changed(s, "Type", NULL);
1199 }
1200
1201 void session_set_class(Session *s, SessionClass c) {
1202 assert(s);
1203
1204 if (s->class == c)
1205 return;
1206
1207 s->class = c;
1208 (void) session_save(s);
1209 (void) session_send_changed(s, "Class", NULL);
1210
1211 /* This class change might mean we need the per-user session manager now. Try to start it. */
1212 (void) user_start_service_manager(s->user);
1213 }
1214
1215 int session_set_display(Session *s, const char *display) {
1216 int r;
1217
1218 assert(s);
1219 assert(display);
1220
1221 r = free_and_strdup(&s->display, display);
1222 if (r <= 0) /* 0 means the strings were equal */
1223 return r;
1224
1225 (void) session_save(s);
1226 (void) session_send_changed(s, "Display", NULL);
1227
1228 return 1;
1229 }
1230
1231 int session_set_tty(Session *s, const char *tty) {
1232 int r;
1233
1234 assert(s);
1235 assert(tty);
1236
1237 r = free_and_strdup(&s->tty, tty);
1238 if (r <= 0) /* 0 means the strings were equal */
1239 return r;
1240
1241 (void) session_save(s);
1242 (void) session_send_changed(s, "TTY", NULL);
1243
1244 return 1;
1245 }
1246
1247 static int session_dispatch_fifo(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
1248 Session *s = ASSERT_PTR(userdata);
1249
1250 assert(s->fifo_fd == fd);
1251
1252 /* EOF on the FIFO means the session died abnormally. */
1253
1254 session_remove_fifo(s);
1255 session_stop(s, /* force = */ false);
1256
1257 return 1;
1258 }
1259
1260 int session_create_fifo(Session *s) {
1261 int r;
1262
1263 assert(s);
1264
1265 /* Create FIFO */
1266 if (!s->fifo_path) {
1267 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, MKDIR_WARN_MODE);
1268 if (r < 0)
1269 return r;
1270
1271 s->fifo_path = strjoin("/run/systemd/sessions/", s->id, ".ref");
1272 if (!s->fifo_path)
1273 return -ENOMEM;
1274
1275 if (mkfifo(s->fifo_path, 0600) < 0 && errno != EEXIST)
1276 return -errno;
1277 }
1278
1279 /* Open reading side */
1280 if (s->fifo_fd < 0) {
1281 s->fifo_fd = open(s->fifo_path, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
1282 if (s->fifo_fd < 0)
1283 return -errno;
1284 }
1285
1286 if (!s->fifo_event_source) {
1287 r = sd_event_add_io(s->manager->event, &s->fifo_event_source, s->fifo_fd, 0, session_dispatch_fifo, s);
1288 if (r < 0)
1289 return r;
1290
1291 /* Let's make sure we noticed dead sessions before we process new bus requests (which might
1292 * create new sessions). */
1293 r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_NORMAL-10);
1294 if (r < 0)
1295 return r;
1296 }
1297
1298 /* Open writing side */
1299 return RET_NERRNO(open(s->fifo_path, O_WRONLY|O_CLOEXEC|O_NONBLOCK));
1300 }
1301
1302 static void session_remove_fifo(Session *s) {
1303 assert(s);
1304
1305 s->fifo_event_source = sd_event_source_unref(s->fifo_event_source);
1306 s->fifo_fd = safe_close(s->fifo_fd);
1307 s->fifo_path = unlink_and_free(s->fifo_path);
1308 }
1309
1310 bool session_may_gc(Session *s, bool drop_not_started) {
1311 int r;
1312
1313 assert(s);
1314
1315 if (drop_not_started && !s->started)
1316 return true;
1317
1318 if (!s->user)
1319 return true;
1320
1321 r = pidref_is_alive(&s->leader);
1322 if (r == -ESRCH)
1323 /* Session has no leader. This is probably because the leader vanished before deserializing
1324 * pidfd from FD store. */
1325 return true;
1326 if (r < 0)
1327 log_debug_errno(r, "Unable to determine if leader PID " PID_FMT " is still alive, assuming not: %m", s->leader.pid);
1328 if (r > 0)
1329 return false;
1330
1331 if (s->fifo_fd >= 0 && pipe_eof(s->fifo_fd) <= 0)
1332 return false;
1333
1334 if (s->scope_job) {
1335 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1336
1337 r = manager_job_is_active(s->manager, s->scope_job, &error);
1338 if (r < 0)
1339 log_debug_errno(r, "Failed to determine whether job '%s' is pending, ignoring: %s", s->scope_job, bus_error_message(&error, r));
1340 if (r != 0)
1341 return false;
1342 }
1343
1344 if (s->scope) {
1345 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1346
1347 r = manager_unit_is_active(s->manager, s->scope, &error);
1348 if (r < 0)
1349 log_debug_errno(r, "Failed to determine whether unit '%s' is active, ignoring: %s", s->scope, bus_error_message(&error, r));
1350 if (r != 0)
1351 return false;
1352 }
1353
1354 return true;
1355 }
1356
1357 void session_add_to_gc_queue(Session *s) {
1358 assert(s);
1359
1360 if (s->in_gc_queue)
1361 return;
1362
1363 LIST_PREPEND(gc_queue, s->manager->session_gc_queue, s);
1364 s->in_gc_queue = true;
1365 }
1366
1367 SessionState session_get_state(Session *s) {
1368 assert(s);
1369
1370 /* always check closing first */
1371 if (s->stopping || s->timer_event_source)
1372 return SESSION_CLOSING;
1373
1374 if (s->scope_job || (!pidref_is_set(&s->leader) && s->fifo_fd < 0))
1375 return SESSION_OPENING;
1376
1377 if (session_is_active(s))
1378 return SESSION_ACTIVE;
1379
1380 return SESSION_ONLINE;
1381 }
1382
1383 int session_kill(Session *s, KillWho who, int signo) {
1384 assert(s);
1385
1386 if (!s->scope)
1387 return -ESRCH;
1388
1389 return manager_kill_unit(s->manager, s->scope, who, signo, NULL);
1390 }
1391
1392 static int session_open_vt(Session *s, bool reopen) {
1393 _cleanup_close_ int fd = -EBADF;
1394 char path[sizeof("/dev/tty") + DECIMAL_STR_MAX(s->vtnr)];
1395
1396 assert(s);
1397
1398 if (s->vtnr < 1)
1399 return -ENODEV;
1400
1401 if (!reopen && s->vtfd >= 0)
1402 return s->vtfd;
1403
1404 sprintf(path, "/dev/tty%u", s->vtnr);
1405
1406 fd = open_terminal(path, O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
1407 if (fd < 0)
1408 return log_error_errno(fd, "Cannot open VT %s of session %s: %m", path, s->id);
1409
1410 close_and_replace(s->vtfd, fd);
1411 return s->vtfd;
1412 }
1413
1414 static int session_prepare_vt(Session *s) {
1415 int vt, r;
1416 struct vt_mode mode = {};
1417
1418 assert(s);
1419
1420 if (s->vtnr < 1)
1421 return 0;
1422
1423 vt = session_open_vt(s, /* reopen = */ false);
1424 if (vt < 0)
1425 return vt;
1426
1427 r = fchown(vt, s->user->user_record->uid, -1);
1428 if (r < 0) {
1429 r = log_error_errno(errno,
1430 "Cannot change owner of /dev/tty%u: %m",
1431 s->vtnr);
1432 goto error;
1433 }
1434
1435 r = ioctl(vt, KDSKBMODE, K_OFF);
1436 if (r < 0) {
1437 r = log_error_errno(errno,
1438 "Cannot set K_OFF on /dev/tty%u: %m",
1439 s->vtnr);
1440 goto error;
1441 }
1442
1443 r = ioctl(vt, KDSETMODE, KD_GRAPHICS);
1444 if (r < 0) {
1445 r = log_error_errno(errno,
1446 "Cannot set KD_GRAPHICS on /dev/tty%u: %m",
1447 s->vtnr);
1448 goto error;
1449 }
1450
1451 /* Oh, thanks to the VT layer, VT_AUTO does not work with KD_GRAPHICS.
1452 * So we need a dummy handler here which just acknowledges *all* VT
1453 * switch requests. */
1454 mode.mode = VT_PROCESS;
1455 mode.relsig = SIGRTMIN;
1456 mode.acqsig = SIGRTMIN + 1;
1457 r = ioctl(vt, VT_SETMODE, &mode);
1458 if (r < 0) {
1459 r = log_error_errno(errno,
1460 "Cannot set VT_PROCESS on /dev/tty%u: %m",
1461 s->vtnr);
1462 goto error;
1463 }
1464
1465 return 0;
1466
1467 error:
1468 session_restore_vt(s);
1469 return r;
1470 }
1471
1472 static void session_restore_vt(Session *s) {
1473 int r;
1474
1475 assert(s);
1476
1477 if (s->vtfd < 0)
1478 return;
1479
1480 r = vt_restore(s->vtfd);
1481 if (r == -EIO) {
1482 /* It might happen if the controlling process exited before or while we were
1483 * restoring the VT as it would leave the old file-descriptor in a hung-up
1484 * state. In this case let's retry with a fresh handle to the virtual terminal. */
1485
1486 /* We do a little dance to avoid having the terminal be available
1487 * for reuse before we've cleaned it up. */
1488
1489 int fd = session_open_vt(s, /* reopen = */ true);
1490 if (fd >= 0)
1491 r = vt_restore(fd);
1492 }
1493 if (r < 0)
1494 log_warning_errno(r, "Failed to restore VT, ignoring: %m");
1495
1496 s->vtfd = safe_close(s->vtfd);
1497 }
1498
1499 void session_leave_vt(Session *s) {
1500 int r;
1501
1502 assert(s);
1503
1504 /* This is called whenever we get a VT-switch signal from the kernel.
1505 * We acknowledge all of them unconditionally. Note that session are
1506 * free to overwrite those handlers and we only register them for
1507 * sessions with controllers. Legacy sessions are not affected.
1508 * However, if we switch from a non-legacy to a legacy session, we must
1509 * make sure to pause all device before acknowledging the switch. We
1510 * process the real switch only after we are notified via sysfs, so the
1511 * legacy session might have already started using the devices. If we
1512 * don't pause the devices before the switch, we might confuse the
1513 * session we switch to. */
1514
1515 if (s->vtfd < 0)
1516 return;
1517
1518 session_device_pause_all(s);
1519 r = vt_release(s->vtfd, /* restore = */ false);
1520 if (r == -EIO) {
1521 /* Handle the same VT hung-up case as in session_restore_vt */
1522
1523 int fd = session_open_vt(s, /* reopen = */ true);
1524 if (fd >= 0)
1525 r = vt_release(fd, /* restore = */ false);
1526 }
1527 if (r < 0)
1528 log_debug_errno(r, "Cannot release VT of session %s: %m", s->id);
1529 }
1530
1531 bool session_is_controller(Session *s, const char *sender) {
1532 return streq_ptr(ASSERT_PTR(s)->controller, sender);
1533 }
1534
1535 static void session_release_controller(Session *s, bool notify) {
1536 _unused_ _cleanup_free_ char *name = NULL;
1537 SessionDevice *sd;
1538
1539 assert(s);
1540
1541 if (!s->controller)
1542 return;
1543
1544 name = s->controller;
1545
1546 /* By resetting the controller before releasing the devices, we won't send notification signals.
1547 * This avoids sending useless notifications if the controller is released on disconnects. */
1548 if (!notify)
1549 s->controller = NULL;
1550
1551 while ((sd = hashmap_first(s->devices)))
1552 session_device_free(sd);
1553
1554 s->controller = NULL;
1555 s->track = sd_bus_track_unref(s->track);
1556 }
1557
1558 static int on_bus_track(sd_bus_track *track, void *userdata) {
1559 Session *s = ASSERT_PTR(userdata);
1560
1561 assert(track);
1562
1563 session_drop_controller(s);
1564
1565 return 0;
1566 }
1567
1568 int session_set_controller(Session *s, const char *sender, bool force, bool prepare) {
1569 _cleanup_free_ char *name = NULL;
1570 int r;
1571
1572 assert(s);
1573 assert(sender);
1574
1575 if (session_is_controller(s, sender))
1576 return 0;
1577 if (s->controller && !force)
1578 return -EBUSY;
1579
1580 name = strdup(sender);
1581 if (!name)
1582 return -ENOMEM;
1583
1584 s->track = sd_bus_track_unref(s->track);
1585 r = sd_bus_track_new(s->manager->bus, &s->track, on_bus_track, s);
1586 if (r < 0)
1587 return r;
1588
1589 r = sd_bus_track_add_name(s->track, name);
1590 if (r < 0)
1591 return r;
1592
1593 /* When setting a session controller, we forcibly mute the VT and set
1594 * it into graphics-mode. Applications can override that by changing
1595 * VT state after calling TakeControl(). However, this serves as a good
1596 * default and well-behaving controllers can now ignore VTs entirely.
1597 * Note that we reset the VT on ReleaseControl() and if the controller
1598 * exits.
1599 * If logind crashes/restarts, we restore the controller during restart
1600 * (without preparing the VT since the controller has probably overridden
1601 * VT state by now) or reset the VT in case it crashed/exited, too. */
1602 if (prepare) {
1603 r = session_prepare_vt(s);
1604 if (r < 0) {
1605 s->track = sd_bus_track_unref(s->track);
1606 return r;
1607 }
1608 }
1609
1610 session_release_controller(s, true);
1611 s->controller = TAKE_PTR(name);
1612 (void) session_save(s);
1613
1614 return 0;
1615 }
1616
1617 void session_drop_controller(Session *s) {
1618 assert(s);
1619
1620 if (!s->controller)
1621 return;
1622
1623 s->track = sd_bus_track_unref(s->track);
1624 session_set_type(s, s->original_type);
1625 session_release_controller(s, false);
1626 (void) session_save(s);
1627 session_restore_vt(s);
1628 }
1629
1630 static const char* const session_state_table[_SESSION_STATE_MAX] = {
1631 [SESSION_OPENING] = "opening",
1632 [SESSION_ONLINE] = "online",
1633 [SESSION_ACTIVE] = "active",
1634 [SESSION_CLOSING] = "closing",
1635 };
1636
1637 DEFINE_STRING_TABLE_LOOKUP(session_state, SessionState);
1638
1639 static const char* const session_type_table[_SESSION_TYPE_MAX] = {
1640 [SESSION_UNSPECIFIED] = "unspecified",
1641 [SESSION_TTY] = "tty",
1642 [SESSION_X11] = "x11",
1643 [SESSION_WAYLAND] = "wayland",
1644 [SESSION_MIR] = "mir",
1645 [SESSION_WEB] = "web",
1646 };
1647
1648 DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType);
1649
1650 static const char* const session_class_table[_SESSION_CLASS_MAX] = {
1651 [SESSION_USER] = "user",
1652 [SESSION_USER_EARLY] = "user-early",
1653 [SESSION_USER_INCOMPLETE] = "user-incomplete",
1654 [SESSION_GREETER] = "greeter",
1655 [SESSION_LOCK_SCREEN] = "lock-screen",
1656 [SESSION_BACKGROUND] = "background",
1657 [SESSION_BACKGROUND_LIGHT] = "background-light",
1658 [SESSION_MANAGER] = "manager",
1659 [SESSION_MANAGER_EARLY] = "manager-early",
1660 };
1661
1662 DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass);
1663
1664 static const char* const kill_who_table[_KILL_WHO_MAX] = {
1665 [KILL_LEADER] = "leader",
1666 [KILL_ALL] = "all",
1667 };
1668
1669 DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);
1670
1671 static const char* const tty_validity_table[_TTY_VALIDITY_MAX] = {
1672 [TTY_FROM_PAM] = "from-pam",
1673 [TTY_FROM_UTMP] = "from-utmp",
1674 [TTY_UTMP_INCONSISTENT] = "utmp-inconsistent",
1675 };
1676
1677 DEFINE_STRING_TABLE_LOOKUP(tty_validity, TTYValidity);