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