]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/login/logind-session.c
test-network: add test for advertised hop limit
[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(Session **ret, Manager *m, const char *id) {
50 _cleanup_(session_freep) Session *s = NULL;
51 int r;
52
53 assert(ret);
54 assert(m);
55 assert(id);
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 .fifo_fd = -EBADF,
67 .vtfd = -EBADF,
68 .audit_id = AUDIT_SESSION_INVALID,
69 .tty_validity = _TTY_VALIDITY_INVALID,
70 .leader = PIDREF_NULL,
71 };
72
73 s->state_file = path_join("/run/systemd/sessions", id);
74 if (!s->state_file)
75 return -ENOMEM;
76
77 s->id = basename(s->state_file);
78
79 s->devices = hashmap_new(&devt_hash_ops);
80 if (!s->devices)
81 return -ENOMEM;
82
83 r = hashmap_put(m->sessions, s->id, s);
84 if (r < 0)
85 return r;
86
87 *ret = TAKE_PTR(s);
88 return 0;
89 }
90
91 static int session_dispatch_leader_pidfd(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
92 Session *s = ASSERT_PTR(userdata);
93
94 assert(s->leader.fd == fd);
95 session_stop(s, /* force= */ false);
96
97 return 1;
98 }
99
100 static int session_watch_pidfd(Session *s) {
101 int r;
102
103 assert(s);
104 assert(s->manager);
105 assert(pidref_is_set(&s->leader));
106
107 if (s->leader.fd < 0)
108 return 0;
109
110 r = sd_event_add_io(s->manager->event, &s->leader_pidfd_event_source, s->leader.fd, EPOLLIN, session_dispatch_leader_pidfd, s);
111 if (r < 0)
112 return r;
113
114 r = sd_event_source_set_priority(s->leader_pidfd_event_source, SD_EVENT_PRIORITY_IMPORTANT);
115 if (r < 0)
116 return r;
117
118 (void) sd_event_source_set_description(s->leader_pidfd_event_source, "session-pidfd");
119
120 return 0;
121 }
122
123 static void session_reset_leader(Session *s, bool keep_fdstore) {
124 assert(s);
125
126 if (!keep_fdstore) {
127 /* Clear fdstore if we're asked to, no matter if s->leader is set or not, so that when
128 * initially deserializing leader fd we clear the old fd too. */
129 (void) notify_remove_fd_warnf("session-%s-leader-fd", s->id);
130 s->leader_fd_saved = false;
131 }
132
133 if (!pidref_is_set(&s->leader))
134 return;
135
136 s->leader_pidfd_event_source = sd_event_source_disable_unref(s->leader_pidfd_event_source);
137
138 (void) hashmap_remove_value(s->manager->sessions_by_leader, &s->leader, s);
139
140 return pidref_done(&s->leader);
141 }
142
143 Session* session_free(Session *s) {
144 SessionDevice *sd;
145
146 if (!s)
147 return NULL;
148
149 if (s->in_gc_queue)
150 LIST_REMOVE(gc_queue, s->manager->session_gc_queue, s);
151
152 s->timer_event_source = 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
191 free(s->tty);
192 free(s->display);
193 free(s->remote_host);
194 free(s->remote_user);
195 free(s->service);
196 free(s->desktop);
197
198 hashmap_remove(s->manager->sessions, s->id);
199
200 sd_event_source_unref(s->fifo_event_source);
201 safe_close(s->fifo_fd);
202
203 /* Note that we remove neither the state file nor the fifo path here, since we want both to survive
204 * daemon restarts */
205 free(s->state_file);
206 free(s->fifo_path);
207
208 sd_event_source_unref(s->stop_on_idle_event_source);
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 int r;
721
722 assert(s);
723 assert(s->user);
724
725 if (!SESSION_CLASS_WANTS_SCOPE(s->class))
726 return 0;
727
728 if (!s->scope) {
729 _cleanup_strv_free_ char **wants = NULL, **after = NULL;
730 _cleanup_free_ char *scope = NULL;
731 const char *description;
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 /* These two have StopWhenUnneeded= set, hence add a dep towards them */
742 wants = strv_new(s->user->runtime_dir_service,
743 SESSION_CLASS_WANTS_SERVICE_MANAGER(s->class) ? s->user->service : STRV_IGNORE);
744 if (!wants)
745 return log_oom();
746
747 /* We usually want to order session scopes after systemd-user-sessions.service since the
748 * latter unit is used as login session barrier for unprivileged users. However the barrier
749 * doesn't apply for root as sysadmin should always be able to log in (and without waiting
750 * for any timeout to expire) in case something goes wrong during the boot process. Since
751 * ordering after systemd-user-sessions.service and the user instance is optional we make use
752 * of STRV_IGNORE with strv_new() to skip these order constraints when needed. */
753 after = strv_new("systemd-logind.service",
754 s->user->runtime_dir_service,
755 SESSION_CLASS_IS_EARLY(s->class) ? STRV_IGNORE : "systemd-user-sessions.service",
756 s->user->service);
757 if (!after)
758 return log_oom();
759
760 r = manager_start_scope(
761 s->manager,
762 scope,
763 &s->leader,
764 s->user->slice,
765 description,
766 wants,
767 after,
768 user_record_home_directory(s->user->user_record),
769 properties,
770 error,
771 &s->scope_job);
772 if (r < 0)
773 return log_error_errno(r, "Failed to start session scope %s: %s",
774 scope, bus_error_message(error, r));
775
776 s->scope = TAKE_PTR(scope);
777 }
778
779 (void) hashmap_put(s->manager->session_units, s->scope, s);
780
781 return 0;
782 }
783
784 static int session_dispatch_stop_on_idle(sd_event_source *source, uint64_t t, void *userdata) {
785 Session *s = userdata;
786 dual_timestamp ts;
787 int r, idle;
788
789 assert(s);
790
791 if (s->stopping)
792 return 0;
793
794 idle = session_get_idle_hint(s, &ts);
795 if (idle) {
796 log_info("Session \"%s\" of user \"%s\" is idle, stopping.", s->id, s->user->user_record->user_name);
797
798 return session_stop(s, /* force */ true);
799 }
800
801 r = sd_event_source_set_time(
802 source,
803 usec_add(dual_timestamp_is_set(&ts) ? ts.monotonic : now(CLOCK_MONOTONIC),
804 s->manager->stop_idle_session_usec));
805 if (r < 0)
806 return log_error_errno(r, "Failed to configure stop on idle session event source: %m");
807
808 r = sd_event_source_set_enabled(source, SD_EVENT_ONESHOT);
809 if (r < 0)
810 return log_error_errno(r, "Failed to enable stop on idle session event source: %m");
811
812 return 1;
813 }
814
815 static int session_setup_stop_on_idle_timer(Session *s) {
816 int r;
817
818 assert(s);
819
820 if (s->manager->stop_idle_session_usec == USEC_INFINITY || !SESSION_CLASS_CAN_STOP_ON_IDLE(s->class))
821 return 0;
822
823 r = sd_event_add_time_relative(
824 s->manager->event,
825 &s->stop_on_idle_event_source,
826 CLOCK_MONOTONIC,
827 s->manager->stop_idle_session_usec,
828 0,
829 session_dispatch_stop_on_idle, s);
830 if (r < 0)
831 return log_error_errno(r, "Failed to add stop on idle session event source: %m");
832
833 return 0;
834 }
835
836 int session_start(Session *s, sd_bus_message *properties, sd_bus_error *error) {
837 int r;
838
839 assert(s);
840
841 if (!s->user)
842 return -ESTALE;
843
844 if (s->stopping)
845 return -EINVAL;
846
847 if (s->started)
848 return 0;
849
850 r = user_start(s->user);
851 if (r < 0)
852 return r;
853
854 r = session_start_scope(s, properties, error);
855 if (r < 0)
856 return r;
857
858 r = session_setup_stop_on_idle_timer(s);
859 if (r < 0)
860 return r;
861
862 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
863 "MESSAGE_ID=" SD_MESSAGE_SESSION_START_STR,
864 "SESSION_ID=%s", s->id,
865 "USER_ID=%s", s->user->user_record->user_name,
866 "LEADER="PID_FMT, s->leader.pid,
867 LOG_MESSAGE("New session %s of user %s.", s->id, s->user->user_record->user_name));
868
869 if (!dual_timestamp_is_set(&s->timestamp))
870 dual_timestamp_now(&s->timestamp);
871
872 if (s->seat)
873 seat_read_active_vt(s->seat);
874
875 s->started = true;
876
877 user_elect_display(s->user);
878
879 /* Save data */
880 (void) session_save(s);
881 (void) user_save(s->user);
882 if (s->seat)
883 (void) seat_save(s->seat);
884
885 /* Send signals */
886 session_send_signal(s, true);
887 user_send_changed(s->user, "Display", NULL);
888
889 if (s->seat && s->seat->active == s)
890 (void) seat_send_changed(s->seat, "ActiveSession", NULL);
891
892 return 0;
893 }
894
895 static int session_stop_scope(Session *s, bool force) {
896 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
897 int r;
898
899 assert(s);
900
901 if (!s->scope)
902 return 0;
903
904 /* Let's always abandon the scope first. This tells systemd that we are not interested anymore, and everything
905 * that is left in the scope is "left-over". Informing systemd about this has the benefit that it will log
906 * when killing any processes left after this point. */
907 r = manager_abandon_scope(s->manager, s->scope, &error);
908 if (r < 0) {
909 log_warning_errno(r, "Failed to abandon session scope, ignoring: %s", bus_error_message(&error, r));
910 sd_bus_error_free(&error);
911 }
912
913 s->scope_job = mfree(s->scope_job);
914
915 /* Optionally, let's kill everything that's left now. */
916 if (force ||
917 (s->user->user_record->kill_processes != 0 &&
918 (s->user->user_record->kill_processes > 0 ||
919 manager_shall_kill(s->manager, s->user->user_record->user_name)))) {
920
921 r = manager_stop_unit(s->manager, s->scope, force ? "replace" : "fail", &error, &s->scope_job);
922 if (r < 0) {
923 if (force)
924 return log_error_errno(r, "Failed to stop session scope: %s", bus_error_message(&error, r));
925
926 log_warning_errno(r, "Failed to stop session scope, ignoring: %s", bus_error_message(&error, r));
927 }
928 } else {
929
930 /* With no killing, this session is allowed to persist in "closing" state indefinitely.
931 * Therefore session stop and session removal may be two distinct events.
932 * Session stop is quite significant on its own, let's log it. */
933 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
934 "SESSION_ID=%s", s->id,
935 "USER_ID=%s", s->user->user_record->user_name,
936 "LEADER="PID_FMT, s->leader.pid,
937 LOG_MESSAGE("Session %s logged out. Waiting for processes to exit.", s->id));
938 }
939
940 return 0;
941 }
942
943 int session_stop(Session *s, bool force) {
944 int r;
945
946 assert(s);
947
948 /* This is called whenever we begin with tearing down a session record. It's called in four cases: explicit API
949 * request via the bus (either directly for the session object or for the seat or user object this session
950 * belongs to; 'force' is true), or due to automatic GC (i.e. scope vanished; 'force' is false), or because the
951 * session FIFO saw an EOF ('force' is false), or because the release timer hit ('force' is false). */
952
953 if (!s->user)
954 return -ESTALE;
955 if (!s->started)
956 return 0;
957 if (s->stopping)
958 return 0;
959
960 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
961 s->leader_pidfd_event_source = sd_event_source_unref(s->leader_pidfd_event_source);
962
963 if (s->seat)
964 seat_evict_position(s->seat, s);
965
966 /* We are going down, don't care about FIFOs anymore */
967 session_remove_fifo(s);
968
969 /* Kill cgroup */
970 r = session_stop_scope(s, force);
971
972 s->stopping = true;
973
974 user_elect_display(s->user);
975
976 (void) session_save(s);
977 (void) user_save(s->user);
978
979 return r;
980 }
981
982 int session_finalize(Session *s) {
983 SessionDevice *sd;
984
985 assert(s);
986
987 if (!s->user)
988 return -ESTALE;
989
990 if (s->started)
991 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
992 "MESSAGE_ID=" SD_MESSAGE_SESSION_STOP_STR,
993 "SESSION_ID=%s", s->id,
994 "USER_ID=%s", s->user->user_record->user_name,
995 "LEADER="PID_FMT, s->leader.pid,
996 LOG_MESSAGE("Removed session %s.", s->id));
997
998 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
999
1000 if (s->seat)
1001 seat_evict_position(s->seat, s);
1002
1003 /* Kill session devices */
1004 while ((sd = hashmap_first(s->devices)))
1005 session_device_free(sd);
1006
1007 (void) unlink(s->state_file);
1008 session_add_to_gc_queue(s);
1009 user_add_to_gc_queue(s->user);
1010
1011 if (s->started) {
1012 session_send_signal(s, false);
1013 s->started = false;
1014 }
1015
1016 if (s->seat) {
1017 if (s->seat->active == s)
1018 seat_set_active(s->seat, NULL);
1019
1020 seat_save(s->seat);
1021 }
1022
1023 session_reset_leader(s, /* keep_fdstore = */ false);
1024
1025 (void) user_save(s->user);
1026 (void) user_send_changed(s->user, "Display", NULL);
1027
1028 return 0;
1029 }
1030
1031 static int release_timeout_callback(sd_event_source *es, uint64_t usec, void *userdata) {
1032 Session *s = ASSERT_PTR(userdata);
1033
1034 assert(es);
1035
1036 session_stop(s, /* force = */ false);
1037 return 0;
1038 }
1039
1040 int session_release(Session *s) {
1041 assert(s);
1042
1043 if (!s->started || s->stopping)
1044 return 0;
1045
1046 if (s->timer_event_source)
1047 return 0;
1048
1049 return sd_event_add_time_relative(
1050 s->manager->event,
1051 &s->timer_event_source,
1052 CLOCK_MONOTONIC,
1053 RELEASE_USEC, 0,
1054 release_timeout_callback, s);
1055 }
1056
1057 bool session_is_active(Session *s) {
1058 assert(s);
1059
1060 if (!s->seat)
1061 return true;
1062
1063 return s->seat->active == s;
1064 }
1065
1066 static int get_tty_atime(const char *tty, usec_t *atime) {
1067 _cleanup_free_ char *p = NULL;
1068 struct stat st;
1069
1070 assert(tty);
1071 assert(atime);
1072
1073 if (!path_is_absolute(tty)) {
1074 p = path_join("/dev", tty);
1075 if (!p)
1076 return -ENOMEM;
1077
1078 tty = p;
1079 } else if (!path_startswith(tty, "/dev/"))
1080 return -ENOENT;
1081
1082 if (lstat(tty, &st) < 0)
1083 return -errno;
1084
1085 *atime = timespec_load(&st.st_atim);
1086 return 0;
1087 }
1088
1089 static int get_process_ctty_atime(pid_t pid, usec_t *atime) {
1090 _cleanup_free_ char *p = NULL;
1091 int r;
1092
1093 assert(pid > 0);
1094 assert(atime);
1095
1096 r = get_ctty(pid, NULL, &p);
1097 if (r < 0)
1098 return r;
1099
1100 return get_tty_atime(p, atime);
1101 }
1102
1103 int session_get_idle_hint(Session *s, dual_timestamp *t) {
1104 usec_t atime = 0, dtime = 0;
1105 int r;
1106
1107 assert(s);
1108
1109 /* Graphical sessions have an explicit idle hint */
1110 if (SESSION_TYPE_IS_GRAPHICAL(s->type)) {
1111 if (t)
1112 *t = s->idle_hint_timestamp;
1113
1114 return s->idle_hint;
1115 }
1116
1117 if (s->type == SESSION_TTY) {
1118 /* For sessions with an explicitly configured tty, let's check its atime */
1119 if (s->tty) {
1120 r = get_tty_atime(s->tty, &atime);
1121 if (r >= 0)
1122 goto found_atime;
1123 }
1124
1125 /* For sessions with a leader but no explicitly configured tty, let's check the controlling tty of
1126 * the leader */
1127 if (pidref_is_set(&s->leader)) {
1128 r = get_process_ctty_atime(s->leader.pid, &atime);
1129 if (r >= 0)
1130 goto found_atime;
1131 }
1132 }
1133
1134 if (t)
1135 *t = DUAL_TIMESTAMP_NULL;
1136
1137 return false;
1138
1139 found_atime:
1140 if (t)
1141 dual_timestamp_from_realtime(t, atime);
1142
1143 if (s->manager->idle_action_usec > 0 && s->manager->stop_idle_session_usec != USEC_INFINITY)
1144 dtime = MIN(s->manager->idle_action_usec, s->manager->stop_idle_session_usec);
1145 else if (s->manager->idle_action_usec > 0)
1146 dtime = s->manager->idle_action_usec;
1147 else if (s->manager->stop_idle_session_usec != USEC_INFINITY)
1148 dtime = s->manager->stop_idle_session_usec;
1149 else
1150 return false;
1151
1152 return usec_add(atime, dtime) <= now(CLOCK_REALTIME);
1153 }
1154
1155 int session_set_idle_hint(Session *s, bool b) {
1156 assert(s);
1157
1158 if (!SESSION_CLASS_CAN_IDLE(s->class)) /* Only some session classes know the idle concept at all */
1159 return -ENOTTY;
1160 if (!SESSION_TYPE_IS_GRAPHICAL(s->type)) /* And only graphical session types can set the field explicitly */
1161 return -ENOTTY;
1162
1163 if (s->idle_hint == b)
1164 return 0;
1165
1166 s->idle_hint = b;
1167 dual_timestamp_now(&s->idle_hint_timestamp);
1168
1169 session_send_changed(s, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
1170
1171 if (s->seat)
1172 seat_send_changed(s->seat, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
1173
1174 user_send_changed(s->user, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
1175 manager_send_changed(s->manager, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
1176
1177 return 1;
1178 }
1179
1180 int session_get_locked_hint(Session *s) {
1181 assert(s);
1182
1183 return s->locked_hint;
1184 }
1185
1186 int session_set_locked_hint(Session *s, bool b) {
1187 assert(s);
1188
1189 if (!SESSION_CLASS_CAN_LOCK(s->class))
1190 return -ENOTTY;
1191
1192 if (s->locked_hint == b)
1193 return 0;
1194
1195 s->locked_hint = b;
1196 (void) session_save(s);
1197 (void) session_send_changed(s, "LockedHint", NULL);
1198
1199 return 1;
1200 }
1201
1202 void session_set_type(Session *s, SessionType t) {
1203 assert(s);
1204
1205 if (s->type == t)
1206 return;
1207
1208 s->type = t;
1209 (void) session_save(s);
1210 (void) session_send_changed(s, "Type", NULL);
1211 }
1212
1213 int session_set_display(Session *s, const char *display) {
1214 int r;
1215
1216 assert(s);
1217 assert(display);
1218
1219 r = free_and_strdup(&s->display, display);
1220 if (r <= 0) /* 0 means the strings were equal */
1221 return r;
1222
1223 (void) session_save(s);
1224 (void) session_send_changed(s, "Display", NULL);
1225
1226 return 1;
1227 }
1228
1229 int session_set_tty(Session *s, const char *tty) {
1230 int r;
1231
1232 assert(s);
1233 assert(tty);
1234
1235 r = free_and_strdup(&s->tty, tty);
1236 if (r <= 0) /* 0 means the strings were equal */
1237 return r;
1238
1239 (void) session_save(s);
1240 (void) session_send_changed(s, "TTY", NULL);
1241
1242 return 1;
1243 }
1244
1245 static int session_dispatch_fifo(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
1246 Session *s = ASSERT_PTR(userdata);
1247
1248 assert(s->fifo_fd == fd);
1249
1250 /* EOF on the FIFO means the session died abnormally. */
1251
1252 session_remove_fifo(s);
1253 session_stop(s, /* force = */ false);
1254
1255 return 1;
1256 }
1257
1258 int session_create_fifo(Session *s) {
1259 int r;
1260
1261 assert(s);
1262
1263 /* Create FIFO */
1264 if (!s->fifo_path) {
1265 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, MKDIR_WARN_MODE);
1266 if (r < 0)
1267 return r;
1268
1269 s->fifo_path = strjoin("/run/systemd/sessions/", s->id, ".ref");
1270 if (!s->fifo_path)
1271 return -ENOMEM;
1272
1273 if (mkfifo(s->fifo_path, 0600) < 0 && errno != EEXIST)
1274 return -errno;
1275 }
1276
1277 /* Open reading side */
1278 if (s->fifo_fd < 0) {
1279 s->fifo_fd = open(s->fifo_path, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
1280 if (s->fifo_fd < 0)
1281 return -errno;
1282 }
1283
1284 if (!s->fifo_event_source) {
1285 r = sd_event_add_io(s->manager->event, &s->fifo_event_source, s->fifo_fd, 0, session_dispatch_fifo, s);
1286 if (r < 0)
1287 return r;
1288
1289 /* Let's make sure we noticed dead sessions before we process new bus requests (which might
1290 * create new sessions). */
1291 r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_NORMAL-10);
1292 if (r < 0)
1293 return r;
1294 }
1295
1296 /* Open writing side */
1297 return RET_NERRNO(open(s->fifo_path, O_WRONLY|O_CLOEXEC|O_NONBLOCK));
1298 }
1299
1300 static void session_remove_fifo(Session *s) {
1301 assert(s);
1302
1303 s->fifo_event_source = sd_event_source_unref(s->fifo_event_source);
1304 s->fifo_fd = safe_close(s->fifo_fd);
1305 s->fifo_path = unlink_and_free(s->fifo_path);
1306 }
1307
1308 bool session_may_gc(Session *s, bool drop_not_started) {
1309 int r;
1310
1311 assert(s);
1312
1313 if (drop_not_started && !s->started)
1314 return true;
1315
1316 if (!s->user)
1317 return true;
1318
1319 r = pidref_is_alive(&s->leader);
1320 if (r == -ESRCH)
1321 /* Session has no leader. This is probably because the leader vanished before deserializing
1322 * pidfd from FD store. */
1323 return true;
1324 if (r < 0)
1325 log_debug_errno(r, "Unable to determine if leader PID " PID_FMT " is still alive, assuming not: %m", s->leader.pid);
1326 if (r > 0)
1327 return false;
1328
1329 if (s->fifo_fd >= 0 && pipe_eof(s->fifo_fd) <= 0)
1330 return false;
1331
1332 if (s->scope_job) {
1333 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1334
1335 r = manager_job_is_active(s->manager, s->scope_job, &error);
1336 if (r < 0)
1337 log_debug_errno(r, "Failed to determine whether job '%s' is pending, ignoring: %s", s->scope_job, bus_error_message(&error, r));
1338 if (r != 0)
1339 return false;
1340 }
1341
1342 if (s->scope) {
1343 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1344
1345 r = manager_unit_is_active(s->manager, s->scope, &error);
1346 if (r < 0)
1347 log_debug_errno(r, "Failed to determine whether unit '%s' is active, ignoring: %s", s->scope, bus_error_message(&error, r));
1348 if (r != 0)
1349 return false;
1350 }
1351
1352 return true;
1353 }
1354
1355 void session_add_to_gc_queue(Session *s) {
1356 assert(s);
1357
1358 if (s->in_gc_queue)
1359 return;
1360
1361 LIST_PREPEND(gc_queue, s->manager->session_gc_queue, s);
1362 s->in_gc_queue = true;
1363 }
1364
1365 SessionState session_get_state(Session *s) {
1366 assert(s);
1367
1368 /* always check closing first */
1369 if (s->stopping || s->timer_event_source)
1370 return SESSION_CLOSING;
1371
1372 if (s->scope_job || (!pidref_is_set(&s->leader) && s->fifo_fd < 0))
1373 return SESSION_OPENING;
1374
1375 if (session_is_active(s))
1376 return SESSION_ACTIVE;
1377
1378 return SESSION_ONLINE;
1379 }
1380
1381 int session_kill(Session *s, KillWho who, int signo) {
1382 assert(s);
1383
1384 if (!s->scope)
1385 return -ESRCH;
1386
1387 return manager_kill_unit(s->manager, s->scope, who, signo, NULL);
1388 }
1389
1390 static int session_open_vt(Session *s, bool reopen) {
1391 _cleanup_close_ int fd = -EBADF;
1392 char path[sizeof("/dev/tty") + DECIMAL_STR_MAX(s->vtnr)];
1393
1394 assert(s);
1395
1396 if (s->vtnr < 1)
1397 return -ENODEV;
1398
1399 if (!reopen && s->vtfd >= 0)
1400 return s->vtfd;
1401
1402 sprintf(path, "/dev/tty%u", s->vtnr);
1403
1404 fd = open_terminal(path, O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
1405 if (fd < 0)
1406 return log_error_errno(fd, "Cannot open VT %s of session %s: %m", path, s->id);
1407
1408 close_and_replace(s->vtfd, fd);
1409 return s->vtfd;
1410 }
1411
1412 static int session_prepare_vt(Session *s) {
1413 int vt, r;
1414 struct vt_mode mode = {};
1415
1416 assert(s);
1417
1418 if (s->vtnr < 1)
1419 return 0;
1420
1421 vt = session_open_vt(s, /* reopen = */ false);
1422 if (vt < 0)
1423 return vt;
1424
1425 r = fchown(vt, s->user->user_record->uid, -1);
1426 if (r < 0) {
1427 r = log_error_errno(errno,
1428 "Cannot change owner of /dev/tty%u: %m",
1429 s->vtnr);
1430 goto error;
1431 }
1432
1433 r = ioctl(vt, KDSKBMODE, K_OFF);
1434 if (r < 0) {
1435 r = log_error_errno(errno,
1436 "Cannot set K_OFF on /dev/tty%u: %m",
1437 s->vtnr);
1438 goto error;
1439 }
1440
1441 r = ioctl(vt, KDSETMODE, KD_GRAPHICS);
1442 if (r < 0) {
1443 r = log_error_errno(errno,
1444 "Cannot set KD_GRAPHICS on /dev/tty%u: %m",
1445 s->vtnr);
1446 goto error;
1447 }
1448
1449 /* Oh, thanks to the VT layer, VT_AUTO does not work with KD_GRAPHICS.
1450 * So we need a dummy handler here which just acknowledges *all* VT
1451 * switch requests. */
1452 mode.mode = VT_PROCESS;
1453 mode.relsig = SIGRTMIN;
1454 mode.acqsig = SIGRTMIN + 1;
1455 r = ioctl(vt, VT_SETMODE, &mode);
1456 if (r < 0) {
1457 r = log_error_errno(errno,
1458 "Cannot set VT_PROCESS on /dev/tty%u: %m",
1459 s->vtnr);
1460 goto error;
1461 }
1462
1463 return 0;
1464
1465 error:
1466 session_restore_vt(s);
1467 return r;
1468 }
1469
1470 static void session_restore_vt(Session *s) {
1471 int r;
1472
1473 assert(s);
1474
1475 if (s->vtfd < 0)
1476 return;
1477
1478 r = vt_restore(s->vtfd);
1479 if (r == -EIO) {
1480 /* It might happen if the controlling process exited before or while we were
1481 * restoring the VT as it would leave the old file-descriptor in a hung-up
1482 * state. In this case let's retry with a fresh handle to the virtual terminal. */
1483
1484 /* We do a little dance to avoid having the terminal be available
1485 * for reuse before we've cleaned it up. */
1486
1487 int fd = session_open_vt(s, /* reopen = */ true);
1488 if (fd >= 0)
1489 r = vt_restore(fd);
1490 }
1491 if (r < 0)
1492 log_warning_errno(r, "Failed to restore VT, ignoring: %m");
1493
1494 s->vtfd = safe_close(s->vtfd);
1495 }
1496
1497 void session_leave_vt(Session *s) {
1498 int r;
1499
1500 assert(s);
1501
1502 /* This is called whenever we get a VT-switch signal from the kernel.
1503 * We acknowledge all of them unconditionally. Note that session are
1504 * free to overwrite those handlers and we only register them for
1505 * sessions with controllers. Legacy sessions are not affected.
1506 * However, if we switch from a non-legacy to a legacy session, we must
1507 * make sure to pause all device before acknowledging the switch. We
1508 * process the real switch only after we are notified via sysfs, so the
1509 * legacy session might have already started using the devices. If we
1510 * don't pause the devices before the switch, we might confuse the
1511 * session we switch to. */
1512
1513 if (s->vtfd < 0)
1514 return;
1515
1516 session_device_pause_all(s);
1517 r = vt_release(s->vtfd, /* restore = */ false);
1518 if (r == -EIO) {
1519 /* Handle the same VT hung-up case as in session_restore_vt */
1520
1521 int fd = session_open_vt(s, /* reopen = */ true);
1522 if (fd >= 0)
1523 r = vt_release(fd, /* restore = */ false);
1524 }
1525 if (r < 0)
1526 log_debug_errno(r, "Cannot release VT of session %s: %m", s->id);
1527 }
1528
1529 bool session_is_controller(Session *s, const char *sender) {
1530 return streq_ptr(ASSERT_PTR(s)->controller, sender);
1531 }
1532
1533 static void session_release_controller(Session *s, bool notify) {
1534 _unused_ _cleanup_free_ char *name = NULL;
1535 SessionDevice *sd;
1536
1537 assert(s);
1538
1539 if (!s->controller)
1540 return;
1541
1542 name = s->controller;
1543
1544 /* By resetting the controller before releasing the devices, we won't send notification signals.
1545 * This avoids sending useless notifications if the controller is released on disconnects. */
1546 if (!notify)
1547 s->controller = NULL;
1548
1549 while ((sd = hashmap_first(s->devices)))
1550 session_device_free(sd);
1551
1552 s->controller = NULL;
1553 s->track = sd_bus_track_unref(s->track);
1554 }
1555
1556 static int on_bus_track(sd_bus_track *track, void *userdata) {
1557 Session *s = ASSERT_PTR(userdata);
1558
1559 assert(track);
1560
1561 session_drop_controller(s);
1562
1563 return 0;
1564 }
1565
1566 int session_set_controller(Session *s, const char *sender, bool force, bool prepare) {
1567 _cleanup_free_ char *name = NULL;
1568 int r;
1569
1570 assert(s);
1571 assert(sender);
1572
1573 if (session_is_controller(s, sender))
1574 return 0;
1575 if (s->controller && !force)
1576 return -EBUSY;
1577
1578 name = strdup(sender);
1579 if (!name)
1580 return -ENOMEM;
1581
1582 s->track = sd_bus_track_unref(s->track);
1583 r = sd_bus_track_new(s->manager->bus, &s->track, on_bus_track, s);
1584 if (r < 0)
1585 return r;
1586
1587 r = sd_bus_track_add_name(s->track, name);
1588 if (r < 0)
1589 return r;
1590
1591 /* When setting a session controller, we forcibly mute the VT and set
1592 * it into graphics-mode. Applications can override that by changing
1593 * VT state after calling TakeControl(). However, this serves as a good
1594 * default and well-behaving controllers can now ignore VTs entirely.
1595 * Note that we reset the VT on ReleaseControl() and if the controller
1596 * exits.
1597 * If logind crashes/restarts, we restore the controller during restart
1598 * (without preparing the VT since the controller has probably overridden
1599 * VT state by now) or reset the VT in case it crashed/exited, too. */
1600 if (prepare) {
1601 r = session_prepare_vt(s);
1602 if (r < 0) {
1603 s->track = sd_bus_track_unref(s->track);
1604 return r;
1605 }
1606 }
1607
1608 session_release_controller(s, true);
1609 s->controller = TAKE_PTR(name);
1610 (void) session_save(s);
1611
1612 return 0;
1613 }
1614
1615 void session_drop_controller(Session *s) {
1616 assert(s);
1617
1618 if (!s->controller)
1619 return;
1620
1621 s->track = sd_bus_track_unref(s->track);
1622 session_set_type(s, s->original_type);
1623 session_release_controller(s, false);
1624 (void) session_save(s);
1625 session_restore_vt(s);
1626 }
1627
1628 static const char* const session_state_table[_SESSION_STATE_MAX] = {
1629 [SESSION_OPENING] = "opening",
1630 [SESSION_ONLINE] = "online",
1631 [SESSION_ACTIVE] = "active",
1632 [SESSION_CLOSING] = "closing",
1633 };
1634
1635 DEFINE_STRING_TABLE_LOOKUP(session_state, SessionState);
1636
1637 static const char* const session_type_table[_SESSION_TYPE_MAX] = {
1638 [SESSION_UNSPECIFIED] = "unspecified",
1639 [SESSION_TTY] = "tty",
1640 [SESSION_X11] = "x11",
1641 [SESSION_WAYLAND] = "wayland",
1642 [SESSION_MIR] = "mir",
1643 [SESSION_WEB] = "web",
1644 };
1645
1646 DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType);
1647
1648 static const char* const session_class_table[_SESSION_CLASS_MAX] = {
1649 [SESSION_USER] = "user",
1650 [SESSION_USER_EARLY] = "user-early",
1651 [SESSION_GREETER] = "greeter",
1652 [SESSION_LOCK_SCREEN] = "lock-screen",
1653 [SESSION_BACKGROUND] = "background",
1654 [SESSION_BACKGROUND_LIGHT] = "background-light",
1655 [SESSION_MANAGER] = "manager",
1656 [SESSION_MANAGER_EARLY] = "manager-early",
1657 };
1658
1659 DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass);
1660
1661 static const char* const kill_who_table[_KILL_WHO_MAX] = {
1662 [KILL_LEADER] = "leader",
1663 [KILL_ALL] = "all",
1664 };
1665
1666 DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);
1667
1668 static const char* const tty_validity_table[_TTY_VALIDITY_MAX] = {
1669 [TTY_FROM_PAM] = "from-pam",
1670 [TTY_FROM_UTMP] = "from-utmp",
1671 [TTY_UTMP_INCONSISTENT] = "utmp-inconsistent",
1672 };
1673
1674 DEFINE_STRING_TABLE_LOOKUP(tty_validity, TTYValidity);