1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
28 #include <sys/ioctl.h>
32 #include "sd-messages.h"
36 #include "path-util.h"
40 #include "bus-error.h"
41 #include "logind-session.h"
43 #define RELEASE_USEC (20*USEC_PER_SEC)
45 static void session_remove_fifo(Session *s);
47 static unsigned long devt_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) {
48 uint64_t u = *(const dev_t*)p;
50 return uint64_hash_func(&u, hash_key);
53 static int devt_compare_func(const void *_a, const void *_b) {
56 a = *(const dev_t*) _a;
57 b = *(const dev_t*) _b;
59 return a < b ? -1 : (a > b ? 1 : 0);
62 Session* session_new(Manager *m, const char *id) {
67 assert(session_id_valid(id));
73 s->state_file = strappend("/run/systemd/sessions/", id);
79 s->devices = hashmap_new(devt_hash_func, devt_compare_func);
86 s->id = basename(s->state_file);
88 if (hashmap_put(m->sessions, s->id, s) < 0) {
89 hashmap_free(s->devices);
102 void session_free(Session *s) {
108 LIST_REMOVE(gc_queue, s->manager->session_gc_queue, s);
110 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
112 session_remove_fifo(s);
114 session_drop_controller(s);
116 while ((sd = hashmap_first(s->devices)))
117 session_device_free(sd);
119 hashmap_free(s->devices);
122 LIST_REMOVE(sessions_by_user, s->user->sessions, s);
124 if (s->user->display == s)
125 s->user->display = NULL;
129 if (s->seat->active == s)
130 s->seat->active = NULL;
131 if (s->seat->pending_switch == s)
132 s->seat->pending_switch = NULL;
134 seat_evict_position(s->seat, s);
135 LIST_REMOVE(sessions_by_seat, s->seat->sessions, s);
139 hashmap_remove(s->manager->session_units, s->scope);
145 sd_bus_message_unref(s->create_message);
149 free(s->remote_host);
150 free(s->remote_user);
154 hashmap_remove(s->manager->sessions, s->id);
156 s->vt_source = sd_event_source_unref(s->vt_source);
162 void session_set_user(Session *s, User *u) {
167 LIST_PREPEND(sessions_by_user, u->sessions, s);
170 int session_save(Session *s) {
171 _cleanup_free_ char *temp_path = NULL;
172 _cleanup_fclose_ FILE *f = NULL;
183 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
187 r = fopen_temporary(s->state_file, &f, &temp_path);
193 fchmod(fileno(f), 0644);
196 "# This is private data. Do not parse.\n"
204 session_is_active(s),
205 session_state_to_string(session_get_state(s)),
209 fprintf(f, "TYPE=%s\n", session_type_to_string(s->type));
212 fprintf(f, "CLASS=%s\n", session_class_to_string(s->class));
215 fprintf(f, "SCOPE=%s\n", s->scope);
218 fprintf(f, "SCOPE_JOB=%s\n", s->scope_job);
221 fprintf(f, "FIFO=%s\n", s->fifo_path);
224 fprintf(f, "SEAT=%s\n", s->seat->id);
227 fprintf(f, "TTY=%s\n", s->tty);
230 fprintf(f, "DISPLAY=%s\n", s->display);
233 fprintf(f, "REMOTE_HOST=%s\n", s->remote_host);
236 fprintf(f, "REMOTE_USER=%s\n", s->remote_user);
239 fprintf(f, "SERVICE=%s\n", s->service);
242 fprintf(f, "DESKTOP=%s\n", s->desktop);
244 if (s->seat && seat_has_vts(s->seat))
245 fprintf(f, "VTNR=%u\n", s->vtnr);
248 fprintf(f, "POS=%u\n", s->pos);
251 fprintf(f, "LEADER="PID_FMT"\n", s->leader);
254 fprintf(f, "AUDIT=%"PRIu32"\n", s->audit_id);
256 if (dual_timestamp_is_set(&s->timestamp))
258 "REALTIME="USEC_FMT"\n"
259 "MONOTONIC="USEC_FMT"\n",
260 s->timestamp.realtime,
261 s->timestamp.monotonic);
264 fprintf(f, "CONTROLLER=%s\n", s->controller);
268 if (ferror(f) || rename(temp_path, s->state_file) < 0) {
270 unlink(s->state_file);
276 log_error("Failed to save session data %s: %s", s->state_file, strerror(-r));
281 int session_load(Session *s) {
282 _cleanup_free_ char *remote = NULL,
298 r = parse_env_file(s->state_file, NEWLINE,
301 "SCOPE_JOB", &s->scope_job,
302 "FIFO", &s->fifo_path,
305 "DISPLAY", &s->display,
306 "REMOTE_HOST", &s->remote_host,
307 "REMOTE_USER", &s->remote_user,
308 "SERVICE", &s->service,
309 "DESKTOP", &s->desktop,
316 "REALTIME", &realtime,
317 "MONOTONIC", &monotonic,
318 "CONTROLLER", &controller,
322 log_error("Failed to read %s: %s", s->state_file, strerror(-r));
331 log_error("UID not specified for session %s", s->id);
335 r = parse_uid(uid, &u);
337 log_error("Failed to parse UID value %s for session %s.", uid, s->id);
341 user = hashmap_get(s->manager->users, ULONG_TO_PTR((unsigned long) u));
343 log_error("User of session %s not known.", s->id);
347 session_set_user(s, user);
351 k = parse_boolean(remote);
357 safe_atou(vtnr, &s->vtnr);
359 if (seat && !s->seat) {
362 o = hashmap_get(s->manager->seats, seat);
364 r = seat_attach_session(o, s);
366 log_error("Cannot attach session %s to seat %s", s->id, seat);
369 if (!s->seat || !seat_has_vts(s->seat))
372 if (pos && s->seat) {
375 safe_atou(pos, &npos);
376 seat_claim_position(s->seat, s, npos);
380 k = parse_pid(leader, &s->leader);
382 audit_session_from_pid(s->leader, &s->audit_id);
388 t = session_type_from_string(type);
396 c = session_class_from_string(class);
404 /* If we open an unopened pipe for reading we will not
405 get an EOF. to trigger an EOF we hence open it for
406 reading, but close it right-away which then will
409 fd = session_create_fifo(s);
414 unsigned long long l;
415 if (sscanf(realtime, "%llu", &l) > 0)
416 s->timestamp.realtime = l;
420 unsigned long long l;
421 if (sscanf(monotonic, "%llu", &l) > 0)
422 s->timestamp.monotonic = l;
426 if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0)
427 session_set_controller(s, controller, false);
429 session_restore_vt(s);
435 int session_activate(Session *s) {
436 unsigned int num_pending;
444 if (s->seat->active == s)
447 /* on seats with VTs, we let VTs manage session-switching */
448 if (seat_has_vts(s->seat)) {
452 return chvt(s->vtnr);
455 /* On seats without VTs, we implement session-switching in logind. We
456 * try to pause all session-devices and wait until the session
457 * controller acknowledged them. Once all devices are asleep, we simply
458 * switch the active session and be done.
459 * We save the session we want to switch to in seat->pending_switch and
460 * seat_complete_switch() will perform the final switch. */
462 s->seat->pending_switch = s;
464 /* if no devices are running, immediately perform the session switch */
465 num_pending = session_device_try_pause_all(s);
467 seat_complete_switch(s->seat);
472 static int session_start_scope(Session *s) {
477 assert(s->user->slice);
480 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
481 _cleanup_free_ char *description = NULL;
482 char *scope, *job = NULL;
484 description = strjoin("Session ", s->id, " of user ", s->user->name, NULL);
488 scope = strjoin("session-", s->id, ".scope", NULL);
492 r = manager_start_scope(s->manager, scope, s->leader, s->user->slice, description, "systemd-logind.service", "systemd-user-sessions.service", &error, &job);
494 log_error("Failed to start session scope %s: %s %s",
495 scope, bus_error_message(&error, r), error.name);
507 hashmap_put(s->manager->session_units, s->scope, s);
512 int session_start(Session *s) {
523 r = user_start(s->user);
528 r = session_start_scope(s);
532 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
533 MESSAGE_ID(SD_MESSAGE_SESSION_START),
534 "SESSION_ID=%s", s->id,
535 "USER_ID=%s", s->user->name,
536 "LEADER=%lu", (unsigned long) s->leader,
537 "MESSAGE=New session %s of user %s.", s->id, s->user->name,
540 if (!dual_timestamp_is_set(&s->timestamp))
541 dual_timestamp_get(&s->timestamp);
544 seat_read_active_vt(s->seat);
555 session_send_signal(s, true);
556 user_send_changed(s->user, "Sessions", NULL);
558 if (s->seat->active == s)
559 seat_send_changed(s->seat, "Sessions", "ActiveSession", NULL);
561 seat_send_changed(s->seat, "Sessions", NULL);
567 static int session_stop_scope(Session *s, bool force) {
568 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
577 if (force || manager_shall_kill(s->manager, s->user->name)) {
578 r = manager_stop_unit(s->manager, s->scope, &error, &job);
580 log_error("Failed to stop session scope: %s", bus_error_message(&error, r));
587 r = manager_abandon_scope(s->manager, s->scope, &error);
589 log_error("Failed to abandon session scope: %s", bus_error_message(&error, r));
597 int session_stop(Session *s, bool force) {
605 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
607 /* We are going down, don't care about FIFOs anymore */
608 session_remove_fifo(s);
611 r = session_stop_scope(s, force);
621 int session_finalize(Session *s) {
631 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
632 MESSAGE_ID(SD_MESSAGE_SESSION_STOP),
633 "SESSION_ID=%s", s->id,
634 "USER_ID=%s", s->user->name,
635 "LEADER=%lu", (unsigned long) s->leader,
636 "MESSAGE=Removed session %s.", s->id,
639 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
641 /* Kill session devices */
642 while ((sd = hashmap_first(s->devices)))
643 session_device_free(sd);
645 unlink(s->state_file);
646 session_add_to_gc_queue(s);
647 user_add_to_gc_queue(s->user);
650 session_send_signal(s, false);
655 if (s->seat->active == s)
656 seat_set_active(s->seat, NULL);
659 seat_send_changed(s->seat, "Sessions", NULL);
663 user_send_changed(s->user, "Sessions", NULL);
668 static int release_timeout_callback(sd_event_source *es, uint64_t usec, void *userdata) {
669 Session *s = userdata;
674 session_stop(s, false);
678 void session_release(Session *s) {
681 if (!s->started || s->stopping)
684 if (!s->timer_event_source)
685 sd_event_add_time(s->manager->event,
686 &s->timer_event_source,
688 now(CLOCK_MONOTONIC) + RELEASE_USEC, 0,
689 release_timeout_callback, s);
692 bool session_is_active(Session *s) {
698 return s->seat->active == s;
701 static int get_tty_atime(const char *tty, usec_t *atime) {
702 _cleanup_free_ char *p = NULL;
708 if (!path_is_absolute(tty)) {
709 p = strappend("/dev/", tty);
714 } else if (!path_startswith(tty, "/dev/"))
717 if (lstat(tty, &st) < 0)
720 *atime = timespec_load(&st.st_atim);
724 static int get_process_ctty_atime(pid_t pid, usec_t *atime) {
725 _cleanup_free_ char *p = NULL;
731 r = get_ctty(pid, NULL, &p);
735 return get_tty_atime(p, atime);
738 int session_get_idle_hint(Session *s, dual_timestamp *t) {
744 /* Explicit idle hint is set */
747 *t = s->idle_hint_timestamp;
752 /* Graphical sessions should really implement a real
757 /* For sessions with an explicitly configured tty, let's check
760 r = get_tty_atime(s->tty, &atime);
765 /* For sessions with a leader but no explicitly configured
766 * tty, let's check the controlling tty of the leader */
768 r = get_process_ctty_atime(s->leader, &atime);
775 *t = s->idle_hint_timestamp;
781 dual_timestamp_from_realtime(t, atime);
783 n = now(CLOCK_REALTIME);
785 if (s->manager->idle_action_usec <= 0)
788 return atime + s->manager->idle_action_usec <= n;
791 void session_set_idle_hint(Session *s, bool b) {
794 if (s->idle_hint == b)
798 dual_timestamp_get(&s->idle_hint_timestamp);
800 session_send_changed(s, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
803 seat_send_changed(s->seat, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
805 user_send_changed(s->user, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
806 manager_send_changed(s->manager, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
809 static int session_dispatch_fifo(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
810 Session *s = userdata;
813 assert(s->fifo_fd == fd);
815 /* EOF on the FIFO means the session died abnormally. */
817 session_remove_fifo(s);
818 session_stop(s, false);
823 int session_create_fifo(Session *s) {
830 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
834 if (asprintf(&s->fifo_path, "/run/systemd/sessions/%s.ref", s->id) < 0)
837 if (mkfifo(s->fifo_path, 0600) < 0 && errno != EEXIST)
841 /* Open reading side */
842 if (s->fifo_fd < 0) {
843 s->fifo_fd = open(s->fifo_path, O_RDONLY|O_CLOEXEC|O_NDELAY);
849 if (!s->fifo_event_source) {
850 r = sd_event_add_io(s->manager->event, &s->fifo_event_source, s->fifo_fd, 0, session_dispatch_fifo, s);
854 r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_IDLE);
859 /* Open writing side */
860 r = open(s->fifo_path, O_WRONLY|O_CLOEXEC|O_NDELAY);
867 static void session_remove_fifo(Session *s) {
870 s->fifo_event_source = sd_event_source_unref(s->fifo_event_source);
871 s->fifo_fd = safe_close(s->fifo_fd);
874 unlink(s->fifo_path);
880 bool session_check_gc(Session *s, bool drop_not_started) {
883 if (drop_not_started && !s->started)
889 if (s->fifo_fd >= 0) {
890 if (pipe_eof(s->fifo_fd) <= 0)
894 if (s->scope_job && manager_job_is_active(s->manager, s->scope_job))
897 if (s->scope && manager_unit_is_active(s->manager, s->scope))
903 void session_add_to_gc_queue(Session *s) {
909 LIST_PREPEND(gc_queue, s->manager->session_gc_queue, s);
910 s->in_gc_queue = true;
913 SessionState session_get_state(Session *s) {
916 /* always check closing first */
917 if (s->stopping || s->timer_event_source)
918 return SESSION_CLOSING;
920 if (s->scope_job || s->fifo_fd < 0)
921 return SESSION_OPENING;
923 if (session_is_active(s))
924 return SESSION_ACTIVE;
926 return SESSION_ONLINE;
929 int session_kill(Session *s, KillWho who, int signo) {
935 return manager_kill_unit(s->manager, s->scope, who, signo, NULL);
938 static int session_open_vt(Session *s) {
939 char path[sizeof("/dev/tty") + DECIMAL_STR_MAX(s->vtnr)];
947 sprintf(path, "/dev/tty%u", s->vtnr);
948 s->vtfd = open(path, O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
950 log_error("cannot open VT %s of session %s: %m", path, s->id);
957 static int session_vt_fn(sd_event_source *source, const struct signalfd_siginfo *si, void *data) {
961 ioctl(s->vtfd, VT_RELDISP, 1);
966 void session_prepare_vt(Session *s) {
968 struct vt_mode mode = { 0 };
971 vt = session_open_vt(s);
975 r = fchown(vt, s->user->uid, -1);
979 r = ioctl(vt, KDSKBMODE, K_OFF);
983 r = ioctl(vt, KDSETMODE, KD_GRAPHICS);
988 sigaddset(&mask, SIGUSR1);
989 sigprocmask(SIG_BLOCK, &mask, NULL);
991 r = sd_event_add_signal(s->manager->event, &s->vt_source, SIGUSR1, session_vt_fn, s);
995 /* Oh, thanks to the VT layer, VT_AUTO does not work with KD_GRAPHICS.
996 * So we need a dummy handler here which just acknowledges *all* VT
997 * switch requests. */
998 mode.mode = VT_PROCESS;
999 mode.relsig = SIGUSR1;
1000 mode.acqsig = SIGUSR1;
1001 r = ioctl(vt, VT_SETMODE, &mode);
1008 log_error("cannot mute VT %u for session %s (%d/%d)", s->vtnr, s->id, r, errno);
1009 session_restore_vt(s);
1012 void session_restore_vt(Session *s) {
1013 _cleanup_free_ char *utf8 = NULL;
1014 int vt, kb = K_XLATE;
1015 struct vt_mode mode = { 0 };
1017 vt = session_open_vt(s);
1021 s->vt_source = sd_event_source_unref(s->vt_source);
1023 ioctl(vt, KDSETMODE, KD_TEXT);
1025 if (read_one_line_file("/sys/module/vt/parameters/default_utf8", &utf8) >= 0 && *utf8 == '1')
1028 ioctl(vt, KDSKBMODE, kb);
1030 mode.mode = VT_AUTO;
1031 ioctl(vt, VT_SETMODE, &mode);
1035 s->vtfd = safe_close(s->vtfd);
1038 bool session_is_controller(Session *s, const char *sender) {
1041 return streq_ptr(s->controller, sender);
1044 static void session_swap_controller(Session *s, char *name) {
1047 if (s->controller) {
1048 manager_drop_busname(s->manager, s->controller);
1049 free(s->controller);
1050 s->controller = NULL;
1052 /* Drop all devices as they're now unused. Do that after the
1053 * controller is released to avoid sending out useles
1055 while ((sd = hashmap_first(s->devices)))
1056 session_device_free(sd);
1059 session_restore_vt(s);
1062 s->controller = name;
1066 int session_set_controller(Session *s, const char *sender, bool force) {
1073 if (session_is_controller(s, sender))
1075 if (s->controller && !force)
1082 r = manager_watch_busname(s->manager, sender);
1088 session_swap_controller(s, t);
1090 /* When setting a session controller, we forcibly mute the VT and set
1091 * it into graphics-mode. Applications can override that by changing
1092 * VT state after calling TakeControl(). However, this serves as a good
1093 * default and well-behaving controllers can now ignore VTs entirely.
1094 * Note that we reset the VT on ReleaseControl() and if the controller
1096 * If logind crashes/restarts, we restore the controller during restart
1097 * or reset the VT in case it crashed/exited, too. */
1098 session_prepare_vt(s);
1103 void session_drop_controller(Session *s) {
1109 session_swap_controller(s, NULL);
1112 static const char* const session_state_table[_SESSION_STATE_MAX] = {
1113 [SESSION_OPENING] = "opening",
1114 [SESSION_ONLINE] = "online",
1115 [SESSION_ACTIVE] = "active",
1116 [SESSION_CLOSING] = "closing"
1119 DEFINE_STRING_TABLE_LOOKUP(session_state, SessionState);
1121 static const char* const session_type_table[_SESSION_TYPE_MAX] = {
1122 [SESSION_UNSPECIFIED] = "unspecified",
1123 [SESSION_TTY] = "tty",
1124 [SESSION_X11] = "x11",
1125 [SESSION_WAYLAND] = "wayland",
1126 [SESSION_MIR] = "mir",
1129 DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType);
1131 static const char* const session_class_table[_SESSION_CLASS_MAX] = {
1132 [SESSION_USER] = "user",
1133 [SESSION_GREETER] = "greeter",
1134 [SESSION_LOCK_SCREEN] = "lock-screen",
1135 [SESSION_BACKGROUND] = "background"
1138 DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass);
1140 static const char* const kill_who_table[_KILL_WHO_MAX] = {
1141 [KILL_LEADER] = "leader",
1145 DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);