1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
13 #include "sd-messages.h"
14 #include "sd-varlink.h"
16 #include "alloc-util.h"
17 #include "audit-util.h"
18 #include "bus-error.h"
20 #include "daemon-util.h"
21 #include "devnum-util.h"
23 #include "errno-util.h"
24 #include "extract-word.h"
26 #include "format-util.h"
29 #include "login-util.h"
31 #include "logind-dbus.h"
32 #include "logind-seat.h"
33 #include "logind-seat-dbus.h"
34 #include "logind-session.h"
35 #include "logind-session-dbus.h"
36 #include "logind-session-device.h"
37 #include "logind-user.h"
38 #include "logind-user-dbus.h"
39 #include "logind-varlink.h"
40 #include "mkdir-label.h"
41 #include "parse-util.h"
42 #include "path-util.h"
43 #include "process-util.h"
44 #include "serialize.h"
45 #include "string-table.h"
46 #include "terminal-util.h"
47 #include "tmpfile-util.h"
48 #include "user-record.h"
49 #include "user-util.h"
51 #define RELEASE_USEC (20*USEC_PER_SEC)
53 static void session_restore_vt(Session
*s
);
55 int session_new(Manager
*m
, const char *id
, Session
**ret
) {
56 _cleanup_(session_freep
) Session
*s
= NULL
;
63 if (!session_id_valid(id
))
73 .state_file
= path_join("/run/systemd/sessions/", id
),
75 .audit_id
= AUDIT_SESSION_INVALID
,
76 .tty_validity
= _TTY_VALIDITY_INVALID
,
77 .leader
= PIDREF_NULL
,
79 if (!s
->id
|| !s
->state_file
)
82 s
->devices
= hashmap_new(&devt_hash_ops
);
86 r
= hashmap_put(m
->sessions
, s
->id
, s
);
94 static int session_dispatch_leader_pidfd(sd_event_source
*es
, int fd
, uint32_t revents
, void *userdata
) {
95 Session
*s
= ASSERT_PTR(userdata
);
97 assert(s
->leader
.fd
== fd
);
99 s
->leader_pidfd_event_source
= sd_event_source_unref(s
->leader_pidfd_event_source
);
101 session_stop(s
, /* force= */ false);
103 session_add_to_gc_queue(s
);
108 static int session_watch_pidfd(Session
*s
) {
113 assert(pidref_is_set(&s
->leader
));
114 assert(s
->leader
.fd
>= 0);
115 assert(!s
->leader_pidfd_event_source
);
117 r
= sd_event_add_io(s
->manager
->event
, &s
->leader_pidfd_event_source
, s
->leader
.fd
, EPOLLIN
, session_dispatch_leader_pidfd
, s
);
121 r
= sd_event_source_set_priority(s
->leader_pidfd_event_source
, SD_EVENT_PRIORITY_IMPORTANT
);
125 (void) sd_event_source_set_description(s
->leader_pidfd_event_source
, "session-pidfd");
130 static void session_reset_leader(Session
*s
, bool keep_fdstore
) {
134 /* Clear fdstore if we're asked to, no matter if s->leader is set or not, so that when
135 * initially deserializing leader fd we clear the old fd too. */
136 (void) notify_remove_fd_warnf("session-%s-leader-fd", s
->id
);
137 s
->leader_fd_saved
= false;
140 if (!pidref_is_set(&s
->leader
))
143 s
->leader_pidfd_event_source
= sd_event_source_disable_unref(s
->leader_pidfd_event_source
);
145 (void) hashmap_remove_value(s
->manager
->sessions_by_leader
, &s
->leader
, s
);
147 return pidref_done(&s
->leader
);
150 Session
* session_free(Session
*s
) {
156 sd_event_source_unref(s
->stop_on_idle_event_source
);
158 if (s
->in_gc_queue
) {
160 LIST_REMOVE(gc_queue
, s
->manager
->session_gc_queue
, s
);
163 sd_event_source_unref(s
->timer_event_source
);
165 session_drop_controller(s
);
167 while ((sd
= hashmap_first(s
->devices
)))
168 session_device_free(sd
);
170 hashmap_free(s
->devices
);
173 LIST_REMOVE(sessions_by_user
, s
->user
->sessions
, s
);
175 if (s
->user
->display
== s
)
176 s
->user
->display
= NULL
;
178 user_update_last_session_timer(s
->user
);
182 if (s
->seat
->active
== s
)
183 s
->seat
->active
= NULL
;
184 if (s
->seat
->pending_switch
== s
)
185 s
->seat
->pending_switch
= NULL
;
187 seat_evict_position(s
->seat
, s
);
188 LIST_REMOVE(sessions_by_seat
, s
->seat
->sessions
, s
);
192 hashmap_remove(s
->manager
->session_units
, s
->scope
);
198 session_reset_leader(s
, /* keep_fdstore = */ true);
200 sd_bus_message_unref(s
->create_message
);
201 sd_bus_message_unref(s
->upgrade_message
);
203 sd_varlink_unref(s
->create_link
);
207 free(s
->remote_host
);
208 free(s
->remote_user
);
212 hashmap_remove(s
->manager
->sessions
, s
->id
);
214 /* Note that we don't remove the state file here, since it's supposed to survive daemon restarts */
221 void session_set_user(Session
*s
, User
*u
) {
226 LIST_PREPEND(sessions_by_user
, u
->sessions
, s
);
228 user_update_last_session_timer(u
);
231 int session_set_leader_consume(Session
*s
, PidRef _leader
) {
232 _cleanup_(pidref_done
) PidRef pidref
= _leader
;
236 assert(pidref_is_set(&pidref
));
237 assert(pidref
.fd
>= 0);
239 if (pidref_equal(&s
->leader
, &pidref
))
242 session_reset_leader(s
, /* keep_fdstore = */ false);
244 s
->leader
= TAKE_PIDREF(pidref
);
246 r
= session_watch_pidfd(s
);
248 return log_error_errno(r
, "Failed to watch leader pidfd for session '%s': %m", s
->id
);
250 r
= hashmap_ensure_put(&s
->manager
->sessions_by_leader
, &pidref_hash_ops
, &s
->leader
, s
);
255 if (s
->leader
.fd
>= 0) {
256 r
= notify_push_fdf(s
->leader
.fd
, "session-%s-leader-fd", s
->id
);
258 log_warning_errno(r
, "Failed to push leader pidfd for session '%s', ignoring: %m", s
->id
);
260 s
->leader_fd_saved
= true;
263 (void) audit_session_from_pid(&s
->leader
, &s
->audit_id
);
268 static void session_save_devices(Session
*s
, FILE *f
) {
271 if (!hashmap_isempty(s
->devices
)) {
272 fprintf(f
, "DEVICES=");
273 HASHMAP_FOREACH(sd
, s
->devices
)
274 fprintf(f
, DEVNUM_FORMAT_STR
" ", DEVNUM_FORMAT_VAL(sd
->dev
));
279 int session_save(Session
*s
) {
290 r
= mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, MKDIR_WARN_MODE
);
292 return log_error_errno(r
, "Failed to create /run/systemd/sessions/: %m");
294 _cleanup_(unlink_and_freep
) char *temp_path
= NULL
;
295 _cleanup_fclose_
FILE *f
= NULL
;
296 r
= fopen_tmpfile_linkable(s
->state_file
, O_WRONLY
|O_CLOEXEC
, &temp_path
, &f
);
298 return log_error_errno(r
, "Failed to create state file '%s': %m", s
->state_file
);
300 if (fchmod(fileno(f
), 0644) < 0)
301 return log_error_errno(errno
, "Failed to set access mode for state file '%s' to 0644: %m", s
->state_file
);
304 "# This is private data. Do not parse.\n"
310 "LEADER_FD_SAVED=%s\n",
311 s
->user
->user_record
->uid
,
312 one_zero(session_is_active(s
)),
313 one_zero(s
->user
->display
== s
),
314 session_state_to_string(session_get_state(s
)),
316 one_zero(s
->leader_fd_saved
));
318 env_file_fputs_assignment(f
, "USER=", s
->user
->user_record
->user_name
);
321 fprintf(f
, "TYPE=%s\n", session_type_to_string(s
->type
));
323 if (s
->original_type
>= 0)
324 fprintf(f
, "ORIGINAL_TYPE=%s\n", session_type_to_string(s
->original_type
));
327 fprintf(f
, "CLASS=%s\n", session_class_to_string(s
->class));
329 env_file_fputs_assignment(f
, "SCOPE=", s
->scope
);
330 env_file_fputs_assignment(f
, "SCOPE_JOB=", s
->scope_job
);
332 env_file_fputs_assignment(f
, "SEAT=", s
->seat
->id
);
333 env_file_fputs_assignment(f
, "TTY=", s
->tty
);
335 if (s
->tty_validity
>= 0)
336 fprintf(f
, "TTY_VALIDITY=%s\n", tty_validity_to_string(s
->tty_validity
));
338 env_file_fputs_assignment(f
, "DISPLAY=", s
->display
);
339 env_file_fputs_assignment(f
, "REMOTE_HOST=", s
->remote_host
);
340 env_file_fputs_assignment(f
, "REMOTE_USER=", s
->remote_user
);
341 env_file_fputs_assignment(f
, "SERVICE=", s
->service
);
342 env_file_fputs_assignment(f
, "DESKTOP=", s
->desktop
);
345 if (!seat_has_vts(s
->seat
))
346 fprintf(f
, "POSITION=%u\n", s
->position
);
347 else if (s
->vtnr
> 0)
348 fprintf(f
, "VTNR=%u\n", s
->vtnr
);
351 if (pidref_is_set(&s
->leader
)) {
352 fprintf(f
, "LEADER="PID_FMT
"\n", s
->leader
.pid
);
353 (void) pidref_acquire_pidfd_id(&s
->leader
);
354 if (s
->leader
.fd_id
!= 0)
355 fprintf(f
, "LEADER_PIDFDID=%" PRIu64
"\n", s
->leader
.fd_id
);
358 if (audit_session_is_valid(s
->audit_id
))
359 fprintf(f
, "AUDIT=%"PRIu32
"\n", s
->audit_id
);
361 if (dual_timestamp_is_set(&s
->timestamp
))
363 "REALTIME="USEC_FMT
"\n"
364 "MONOTONIC="USEC_FMT
"\n",
365 s
->timestamp
.realtime
,
366 s
->timestamp
.monotonic
);
369 env_file_fputs_assignment(f
, "CONTROLLER=", s
->controller
);
370 session_save_devices(s
, f
);
373 r
= flink_tmpfile(f
, temp_path
, s
->state_file
, LINK_TMPFILE_REPLACE
);
375 return log_error_errno(r
, "Failed to move '%s' into place: %m", s
->state_file
);
377 temp_path
= mfree(temp_path
); /* disarm auto-destroy: temporary file does not exist anymore */
381 static int session_load_devices(Session
*s
, const char *devices
) {
386 for (const char *p
= devices
;;) {
387 _cleanup_free_
char *word
= NULL
;
391 k
= extract_first_word(&p
, &word
, NULL
, 0);
397 k
= parse_devnum(word
, &dev
);
403 /* The file descriptors for loaded devices will be reattached later. */
404 RET_GATHER(r
, session_device_new(s
, dev
, /* open_device = */ false, /* ret = */ NULL
));
408 log_error_errno(r
, "Failed to load some session devices for session '%s': %m", s
->id
);
412 int session_load(Session
*s
) {
413 _cleanup_free_
char *remote
= NULL
,
415 *tty_validity
= NULL
,
420 *leader_fd_saved
= NULL
,
422 *original_type
= NULL
,
431 *fifo_path
= NULL
; /* compat only, not used */
437 r
= parse_env_file(NULL
, s
->state_file
,
440 "SCOPE_JOB", &s
->scope_job
,
444 "TTY_VALIDITY", &tty_validity
,
445 "DISPLAY", &s
->display
,
446 "REMOTE_HOST", &s
->remote_host
,
447 "REMOTE_USER", &s
->remote_user
,
448 "SERVICE", &s
->service
,
449 "DESKTOP", &s
->desktop
,
452 "POSITION", &position
,
453 "LEADER", &leader_pid
,
454 "LEADER_FD_SAVED", &leader_fd_saved
,
456 "ORIGINAL_TYPE", &original_type
,
459 "REALTIME", &realtime
,
460 "MONOTONIC", &monotonic
,
461 "CONTROLLER", &controller
,
464 "IS_DISPLAY", &is_display
);
466 return log_error_errno(r
, "Failed to read %s: %m", s
->state_file
);
473 return log_error_errno(SYNTHETIC_ERRNO(ENOENT
),
474 "UID not specified for session %s",
477 r
= parse_uid(uid
, &u
);
479 log_error("Failed to parse UID value %s for session %s.", uid
, s
->id
);
483 user
= hashmap_get(s
->manager
->users
, UID_TO_PTR(u
));
485 return log_error_errno(SYNTHETIC_ERRNO(ENOENT
),
486 "User of session %s not known.",
489 session_set_user(s
, user
);
493 k
= parse_boolean(remote
);
499 (void) safe_atou(vtnr
, &s
->vtnr
);
501 if (seat
&& !s
->seat
) {
504 o
= hashmap_get(s
->manager
->seats
, seat
);
506 r
= seat_attach_session(o
, s
);
508 log_error("Cannot attach session %s to seat %s", s
->id
, seat
);
511 if (!s
->seat
|| !seat_has_vts(s
->seat
))
514 if (position
&& s
->seat
) {
517 (void) safe_atou(position
, &npos
);
518 seat_claim_position(s
->seat
, s
, npos
);
524 v
= tty_validity_from_string(tty_validity
);
526 log_debug("Failed to parse TTY validity: %s", tty_validity
);
534 t
= session_type_from_string(type
);
542 ot
= session_type_from_string(original_type
);
544 s
->original_type
= ot
;
546 /* Pre-v246 compat: initialize original_type if not set in the state file */
547 s
->original_type
= s
->type
;
552 c
= session_class_from_string(class);
557 if (streq_ptr(state
, "closing"))
560 /* logind before v258 used a fifo for session close notification. Since v258 we fully employ
561 * pidfd for the job, hence just unlink the legacy fifo. */
563 (void) unlink(fifo_path
);
566 (void) deserialize_usec(realtime
, &s
->timestamp
.realtime
);
568 (void) deserialize_usec(monotonic
, &s
->timestamp
.monotonic
);
571 k
= parse_boolean(active
);
577 /* Note that when enumerating users are loaded before sessions, hence the display session to use is
578 * something we have to store along with the session and not the user, as in that case we couldn't
579 * apply it at the time we load the user. */
581 k
= parse_boolean(is_display
);
583 log_warning_errno(k
, "Failed to parse IS_DISPLAY session property: %m");
585 s
->user
->display
= s
;
589 if (bus_name_has_owner(s
->manager
->bus
, controller
, NULL
) > 0) {
590 session_set_controller(s
, controller
, false, false);
591 session_load_devices(s
, devices
);
593 session_restore_vt(s
);
597 assert(!pidref_is_set(&s
->leader
));
599 r
= parse_pid(leader_pid
, &s
->deserialized_pid
);
601 return log_error_errno(r
, "Failed to parse LEADER=%s: %m", leader_pid
);
603 if (leader_fd_saved
) {
604 r
= parse_boolean(leader_fd_saved
);
606 return log_error_errno(r
, "Failed to parse LEADER_FD_SAVED=%s: %m", leader_fd_saved
);
607 s
->leader_fd_saved
= r
> 0;
609 if (s
->leader_fd_saved
)
610 /* The leader fd will be acquired from fdstore later */
614 _cleanup_(pidref_done
) PidRef p
= PIDREF_NULL
;
616 r
= pidref_set_pid(&p
, s
->deserialized_pid
);
618 return log_error_errno(r
, "Failed to deserialize leader PID for session '%s': %m", s
->id
);
620 return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE
),
621 "Failed to acquire pidfd for session leader '" PID_FMT
"', refusing.",
624 r
= session_set_leader_consume(s
, TAKE_PIDREF(p
));
626 return log_error_errno(r
, "Failed to set leader PID for session '%s': %m", s
->id
);
632 int session_activate(Session
*s
) {
633 unsigned num_pending
;
641 if (s
->seat
->active
== s
)
644 /* on seats with VTs, we let VTs manage session-switching */
645 if (seat_has_vts(s
->seat
)) {
649 return chvt(s
->vtnr
);
652 /* On seats without VTs, we implement session-switching in logind. We
653 * try to pause all session-devices and wait until the session
654 * controller acknowledged them. Once all devices are asleep, we simply
655 * switch the active session and be done.
656 * We save the session we want to switch to in seat->pending_switch and
657 * seat_complete_switch() will perform the final switch. */
659 s
->seat
->pending_switch
= s
;
661 /* if no devices are running, immediately perform the session switch */
662 num_pending
= session_device_try_pause_all(s
);
664 seat_complete_switch(s
->seat
);
669 static int session_start_scope(Session
*s
, sd_bus_message
*properties
, sd_bus_error
*error
) {
670 _cleanup_free_
char *scope
= NULL
;
671 const char *description
;
677 if (!SESSION_CLASS_WANTS_SCOPE(s
->class))
683 s
->scope_job
= mfree(s
->scope_job
);
685 scope
= strjoin("session-", s
->id
, ".scope");
689 description
= strjoina("Session ", s
->id
, " of User ", s
->user
->user_record
->user_name
);
691 r
= manager_start_scope(
695 /* allow_pidfd = */ true,
698 /* These should have been pulled in explicitly in user_start(). Just to be sure. */
699 /* requires = */ STRV_MAKE_CONST(s
->user
->runtime_dir_unit
),
700 /* wants = */ STRV_MAKE_CONST(SESSION_CLASS_WANTS_SERVICE_MANAGER(s
->class) ? s
->user
->service_manager_unit
: NULL
),
701 /* We usually want to order session scopes after systemd-user-sessions.service
702 * since the unit is used as login session barrier for unprivileged users. However
703 * the barrier doesn't apply for root as sysadmin should always be able to log in
704 * (and without waiting for any timeout to expire) in case something goes wrong
705 * during the boot process. */
706 /* extra_after = */ STRV_MAKE_CONST("systemd-logind.service",
707 SESSION_CLASS_IS_EARLY(s
->class) ? NULL
: "systemd-user-sessions.service"),
708 user_record_home_directory(s
->user
->user_record
),
713 return log_error_errno(r
, "Failed to start session scope %s: %s",
714 scope
, bus_error_message(error
, r
));
716 s
->scope
= TAKE_PTR(scope
);
719 (void) hashmap_put(s
->manager
->session_units
, s
->scope
, s
);
723 static int session_dispatch_stop_on_idle(sd_event_source
*source
, uint64_t t
, void *userdata
) {
724 Session
*s
= userdata
;
733 idle
= session_get_idle_hint(s
, &ts
);
735 log_info("Session \"%s\" of user \"%s\" is idle, stopping.", s
->id
, s
->user
->user_record
->user_name
);
737 return session_stop(s
, /* force */ true);
740 r
= sd_event_source_set_time(
742 usec_add(dual_timestamp_is_set(&ts
) ? ts
.monotonic
: now(CLOCK_MONOTONIC
),
743 s
->manager
->stop_idle_session_usec
));
745 return log_error_errno(r
, "Failed to configure stop on idle session event source: %m");
747 r
= sd_event_source_set_enabled(source
, SD_EVENT_ONESHOT
);
749 return log_error_errno(r
, "Failed to enable stop on idle session event source: %m");
754 static int session_setup_stop_on_idle_timer(Session
*s
) {
759 if (s
->manager
->stop_idle_session_usec
== USEC_INFINITY
|| !SESSION_CLASS_CAN_STOP_ON_IDLE(s
->class))
762 r
= sd_event_add_time_relative(
764 &s
->stop_on_idle_event_source
,
766 s
->manager
->stop_idle_session_usec
,
768 session_dispatch_stop_on_idle
, s
);
770 return log_error_errno(r
, "Failed to add stop on idle session event source: %m");
775 int session_start(Session
*s
, sd_bus_message
*properties
, sd_bus_error
*error
) {
789 r
= user_start(s
->user
);
793 r
= session_start_scope(s
, properties
, error
);
797 r
= session_setup_stop_on_idle_timer(s
);
801 log_struct(s
->class == SESSION_BACKGROUND
? LOG_DEBUG
: LOG_INFO
,
802 LOG_MESSAGE_ID(SD_MESSAGE_SESSION_START_STR
),
803 LOG_ITEM("SESSION_ID=%s", s
->id
),
804 LOG_ITEM("USER_ID=%s", s
->user
->user_record
->user_name
),
805 LOG_ITEM("LEADER="PID_FMT
, s
->leader
.pid
),
806 LOG_ITEM("CLASS=%s", session_class_to_string(s
->class)),
807 LOG_ITEM("TYPE=%s", session_type_to_string(s
->type
)),
808 LOG_MESSAGE("New session '%s' of user '%s' with class '%s' and type '%s'.",
810 s
->user
->user_record
->user_name
,
811 session_class_to_string(s
->class),
812 session_type_to_string(s
->type
)));
814 if (!dual_timestamp_is_set(&s
->timestamp
))
815 dual_timestamp_now(&s
->timestamp
);
818 seat_read_active_vt(s
->seat
);
822 user_elect_display(s
->user
);
825 (void) session_save(s
);
826 (void) user_save(s
->user
);
828 (void) seat_save(s
->seat
);
831 session_send_signal(s
, true);
832 user_send_changed(s
->user
, "Display");
834 if (s
->seat
&& s
->seat
->active
== s
)
835 (void) seat_send_changed(s
->seat
, "ActiveSession");
840 static int session_stop_scope(Session
*s
, bool force
) {
841 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
849 /* Let's always abandon the scope first. This tells systemd that we are not interested anymore, and everything
850 * that is left in the scope is "left-over". Informing systemd about this has the benefit that it will log
851 * when killing any processes left after this point. */
852 r
= manager_abandon_scope(s
->manager
, s
->scope
, &error
);
854 log_warning_errno(r
, "Failed to abandon session scope, ignoring: %s", bus_error_message(&error
, r
));
855 sd_bus_error_free(&error
);
858 s
->scope_job
= mfree(s
->scope_job
);
860 /* Optionally, let's kill everything that's left now. */
862 (s
->user
->user_record
->kill_processes
!= 0 &&
863 (s
->user
->user_record
->kill_processes
> 0 ||
864 manager_shall_kill(s
->manager
, s
->user
->user_record
->user_name
)))) {
866 r
= manager_stop_unit(s
->manager
, s
->scope
, force
? "replace" : "fail", &error
, &s
->scope_job
);
869 return log_error_errno(r
, "Failed to stop session scope: %s", bus_error_message(&error
, r
));
871 log_warning_errno(r
, "Failed to stop session scope, ignoring: %s", bus_error_message(&error
, r
));
875 /* With no killing, this session is allowed to persist in "closing" state indefinitely.
876 * Therefore session stop and session removal may be two distinct events.
877 * Session stop is quite significant on its own, let's log it. */
878 log_struct(s
->class == SESSION_BACKGROUND
? LOG_DEBUG
: LOG_INFO
,
879 LOG_ITEM("SESSION_ID=%s", s
->id
),
880 LOG_ITEM("USER_ID=%s", s
->user
->user_record
->user_name
),
881 LOG_ITEM("LEADER="PID_FMT
, s
->leader
.pid
),
882 LOG_MESSAGE("Session %s logged out. Waiting for processes to exit.", s
->id
));
888 int session_stop(Session
*s
, bool force
) {
893 /* This is called whenever we begin with tearing down a session record. It's called in four cases: explicit API
894 * request via the bus (either directly for the session object or for the seat or user object this session
895 * belongs to; 'force' is true), or due to automatic GC (i.e. scope vanished; 'force' is false), or because the
896 * session FIFO saw an EOF ('force' is false), or because the release timer hit ('force' is false). */
905 s
->timer_event_source
= sd_event_source_unref(s
->timer_event_source
);
908 seat_evict_position(s
->seat
, s
);
911 r
= session_stop_scope(s
, force
);
915 user_elect_display(s
->user
);
917 (void) session_save(s
);
918 (void) user_save(s
->user
);
923 int session_finalize(Session
*s
) {
932 log_struct(s
->class == SESSION_BACKGROUND
? LOG_DEBUG
: LOG_INFO
,
933 LOG_MESSAGE_ID(SD_MESSAGE_SESSION_STOP_STR
),
934 LOG_ITEM("SESSION_ID=%s", s
->id
),
935 LOG_ITEM("USER_ID=%s", s
->user
->user_record
->user_name
),
936 LOG_ITEM("LEADER="PID_FMT
, s
->leader
.pid
),
937 LOG_MESSAGE("Removed session %s.", s
->id
));
939 s
->timer_event_source
= sd_event_source_unref(s
->timer_event_source
);
942 seat_evict_position(s
->seat
, s
);
944 /* Kill session devices */
945 while ((sd
= hashmap_first(s
->devices
)))
946 session_device_free(sd
);
948 (void) unlink(s
->state_file
);
949 session_add_to_gc_queue(s
);
950 user_add_to_gc_queue(s
->user
);
953 session_send_signal(s
, false);
958 if (s
->seat
->active
== s
)
959 seat_set_active(s
->seat
, NULL
);
964 session_reset_leader(s
, /* keep_fdstore = */ false);
966 (void) user_save(s
->user
);
967 (void) user_send_changed(s
->user
, "Display");
972 static int release_timeout_callback(sd_event_source
*es
, uint64_t usec
, void *userdata
) {
973 Session
*s
= ASSERT_PTR(userdata
);
977 session_stop(s
, /* force = */ false);
981 int session_release(Session
*s
) {
984 if (!s
->started
|| s
->stopping
)
987 if (s
->timer_event_source
)
990 return sd_event_add_time_relative(
992 &s
->timer_event_source
,
995 release_timeout_callback
, s
);
998 bool session_is_active(Session
*s
) {
1004 return s
->seat
->active
== s
;
1007 static int get_tty_atime(const char *tty
, usec_t
*atime
) {
1008 _cleanup_free_
char *p
= NULL
;
1014 if (!path_is_absolute(tty
)) {
1015 p
= path_join("/dev", tty
);
1020 } else if (!path_startswith(tty
, "/dev/"))
1023 if (lstat(tty
, &st
) < 0)
1026 *atime
= timespec_load(&st
.st_atim
);
1030 static int get_process_ctty_atime(pid_t pid
, usec_t
*atime
) {
1031 _cleanup_free_
char *p
= NULL
;
1037 r
= get_ctty(pid
, NULL
, &p
);
1041 return get_tty_atime(p
, atime
);
1044 int session_get_idle_hint(Session
*s
, dual_timestamp
*t
) {
1045 usec_t atime
= 0, dtime
= 0;
1050 if (!SESSION_CLASS_CAN_IDLE(s
->class))
1053 /* Graphical sessions have an explicit idle hint */
1054 if (SESSION_TYPE_IS_GRAPHICAL(s
->type
)) {
1056 *t
= s
->idle_hint_timestamp
;
1058 return s
->idle_hint
;
1061 if (s
->type
== SESSION_TTY
) {
1062 /* For sessions with an explicitly configured tty, let's check its atime */
1064 r
= get_tty_atime(s
->tty
, &atime
);
1069 /* For sessions with a leader but no explicitly configured tty, let's check the controlling tty of
1071 if (pidref_is_set(&s
->leader
)) {
1072 r
= get_process_ctty_atime(s
->leader
.pid
, &atime
);
1079 *t
= DUAL_TIMESTAMP_NULL
;
1085 dual_timestamp_from_realtime(t
, atime
);
1087 if (s
->manager
->idle_action_usec
> 0 && s
->manager
->stop_idle_session_usec
!= USEC_INFINITY
)
1088 dtime
= MIN(s
->manager
->idle_action_usec
, s
->manager
->stop_idle_session_usec
);
1089 else if (s
->manager
->idle_action_usec
> 0)
1090 dtime
= s
->manager
->idle_action_usec
;
1091 else if (s
->manager
->stop_idle_session_usec
!= USEC_INFINITY
)
1092 dtime
= s
->manager
->stop_idle_session_usec
;
1096 return usec_add(atime
, dtime
) <= now(CLOCK_REALTIME
);
1099 int session_set_idle_hint(Session
*s
, bool b
) {
1102 if (!SESSION_CLASS_CAN_IDLE(s
->class)) /* Only some session classes know the idle concept at all */
1104 if (!SESSION_TYPE_IS_GRAPHICAL(s
->type
)) /* And only graphical session types can set the field explicitly */
1107 if (s
->idle_hint
== b
)
1111 dual_timestamp_now(&s
->idle_hint_timestamp
);
1113 session_send_changed(s
, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic");
1116 seat_send_changed(s
->seat
, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic");
1118 user_send_changed(s
->user
, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic");
1119 manager_send_changed(s
->manager
, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic");
1124 int session_get_locked_hint(Session
*s
) {
1127 return s
->locked_hint
;
1130 int session_set_locked_hint(Session
*s
, bool b
) {
1133 if (!SESSION_CLASS_CAN_LOCK(s
->class))
1136 if (s
->locked_hint
== b
)
1140 (void) session_save(s
);
1141 (void) session_send_changed(s
, "LockedHint");
1146 void session_set_type(Session
*s
, SessionType t
) {
1153 (void) session_save(s
);
1154 (void) session_send_changed(s
, "Type");
1157 void session_set_class(Session
*s
, SessionClass c
) {
1164 (void) session_save(s
);
1165 (void) session_send_changed(s
, "Class");
1167 /* This class change might mean we need the per-user session manager now. Try to start it. */
1168 (void) user_start_service_manager(s
->user
);
1171 int session_set_display(Session
*s
, const char *display
) {
1177 r
= free_and_strdup(&s
->display
, display
);
1178 if (r
<= 0) /* 0 means the strings were equal */
1181 (void) session_save(s
);
1182 (void) session_send_changed(s
, "Display");
1187 int session_set_tty(Session
*s
, const char *tty
) {
1193 r
= free_and_strdup(&s
->tty
, tty
);
1194 if (r
<= 0) /* 0 means the strings were equal */
1197 (void) session_save(s
);
1198 (void) session_send_changed(s
, "TTY");
1203 bool session_may_gc(Session
*s
, bool drop_not_started
) {
1208 if (drop_not_started
&& !s
->started
)
1214 r
= pidref_is_alive(&s
->leader
);
1216 /* Session has no leader. This is probably because the leader vanished before deserializing
1217 * pidfd from FD store. */
1220 log_debug_errno(r
, "Unable to determine if leader PID " PID_FMT
" is still alive, assuming not: %m", s
->leader
.pid
);
1225 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1227 r
= manager_job_is_active(s
->manager
, s
->scope_job
, &error
);
1229 log_debug_errno(r
, "Failed to determine whether job '%s' is pending, ignoring: %s", s
->scope_job
, bus_error_message(&error
, r
));
1235 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1237 r
= manager_unit_is_active(s
->manager
, s
->scope
, &error
);
1239 log_debug_errno(r
, "Failed to determine whether unit '%s' is active, ignoring: %s", s
->scope
, bus_error_message(&error
, r
));
1247 void session_add_to_gc_queue(Session
*s
) {
1253 LIST_PREPEND(gc_queue
, s
->manager
->session_gc_queue
, s
);
1254 s
->in_gc_queue
= true;
1257 SessionState
session_get_state(Session
*s
) {
1260 /* always check closing first */
1261 if (s
->stopping
|| s
->timer_event_source
)
1262 return SESSION_CLOSING
;
1264 if (s
->scope_job
|| !pidref_is_set(&s
->leader
))
1265 return SESSION_OPENING
;
1267 if (session_is_active(s
))
1268 return SESSION_ACTIVE
;
1270 return SESSION_ONLINE
;
1273 int session_kill(Session
*s
, KillWhom whom
, int signo
, sd_bus_error
*error
) {
1279 if (!SESSION_CLASS_WANTS_SCOPE(s
->class))
1280 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
,
1281 "Session '%s' has no associated scope", s
->id
);
1284 return sd_bus_error_set_errnof(error
, ESRCH
, "Scope for session '%s' not active", s
->id
);
1286 return manager_kill_unit(s
->manager
, s
->scope
, KILL_ALL
, signo
, error
);
1289 return pidref_kill(&s
->leader
, signo
);
1292 assert_not_reached();
1296 static int session_open_vt(Session
*s
, bool reopen
) {
1297 _cleanup_close_
int fd
= -EBADF
;
1298 char path
[sizeof("/dev/tty") + DECIMAL_STR_MAX(s
->vtnr
)];
1305 if (!reopen
&& s
->vtfd
>= 0)
1308 sprintf(path
, "/dev/tty%u", s
->vtnr
);
1310 fd
= open_terminal(path
, O_RDWR
| O_CLOEXEC
| O_NONBLOCK
| O_NOCTTY
);
1312 return log_error_errno(fd
, "Cannot open VT %s of session %s: %m", path
, s
->id
);
1314 close_and_replace(s
->vtfd
, fd
);
1318 static int session_prepare_vt(Session
*s
) {
1320 struct vt_mode mode
= {};
1327 vt
= session_open_vt(s
, /* reopen = */ false);
1331 r
= fchown(vt
, s
->user
->user_record
->uid
, -1);
1333 r
= log_error_errno(errno
,
1334 "Cannot change owner of /dev/tty%u: %m",
1339 r
= ioctl(vt
, KDSKBMODE
, K_OFF
);
1341 r
= log_error_errno(errno
,
1342 "Cannot set K_OFF on /dev/tty%u: %m",
1347 r
= ioctl(vt
, KDSETMODE
, KD_GRAPHICS
);
1349 r
= log_error_errno(errno
,
1350 "Cannot set KD_GRAPHICS on /dev/tty%u: %m",
1355 /* Oh, thanks to the VT layer, VT_AUTO does not work with KD_GRAPHICS.
1356 * So we need a dummy handler here which just acknowledges *all* VT
1357 * switch requests. */
1358 mode
.mode
= VT_PROCESS
;
1359 mode
.relsig
= SIGRTMIN
;
1360 mode
.acqsig
= SIGRTMIN
+ 1;
1361 r
= ioctl(vt
, VT_SETMODE
, &mode
);
1363 r
= log_error_errno(errno
,
1364 "Cannot set VT_PROCESS on /dev/tty%u: %m",
1372 session_restore_vt(s
);
1376 static void session_restore_vt(Session
*s
) {
1384 r
= vt_restore(s
->vtfd
);
1386 /* It might happen if the controlling process exited before or while we were
1387 * restoring the VT as it would leave the old file-descriptor in a hung-up
1388 * state. In this case let's retry with a fresh handle to the virtual terminal. */
1390 /* We do a little dance to avoid having the terminal be available
1391 * for reuse before we've cleaned it up. */
1393 int fd
= session_open_vt(s
, /* reopen = */ true);
1398 log_warning_errno(r
, "Failed to restore VT, ignoring: %m");
1400 s
->vtfd
= safe_close(s
->vtfd
);
1403 void session_leave_vt(Session
*s
) {
1408 /* This is called whenever we get a VT-switch signal from the kernel.
1409 * We acknowledge all of them unconditionally. Note that session are
1410 * free to overwrite those handlers and we only register them for
1411 * sessions with controllers. Legacy sessions are not affected.
1412 * However, if we switch from a non-legacy to a legacy session, we must
1413 * make sure to pause all device before acknowledging the switch. We
1414 * process the real switch only after we are notified via sysfs, so the
1415 * legacy session might have already started using the devices. If we
1416 * don't pause the devices before the switch, we might confuse the
1417 * session we switch to. */
1422 session_device_pause_all(s
);
1423 r
= vt_release(s
->vtfd
, /* restore = */ false);
1425 /* Handle the same VT hung-up case as in session_restore_vt */
1427 int fd
= session_open_vt(s
, /* reopen = */ true);
1429 r
= vt_release(fd
, /* restore = */ false);
1432 log_debug_errno(r
, "Cannot release VT of session %s: %m", s
->id
);
1435 bool session_is_controller(Session
*s
, const char *sender
) {
1436 return streq_ptr(ASSERT_PTR(s
)->controller
, sender
);
1439 static void session_release_controller(Session
*s
, bool notify
) {
1440 _unused_ _cleanup_free_
char *name
= NULL
;
1448 name
= s
->controller
;
1450 /* By resetting the controller before releasing the devices, we won't send notification signals.
1451 * This avoids sending useless notifications if the controller is released on disconnects. */
1453 s
->controller
= NULL
;
1455 while ((sd
= hashmap_first(s
->devices
)))
1456 session_device_free(sd
);
1458 s
->controller
= NULL
;
1459 s
->track
= sd_bus_track_unref(s
->track
);
1462 static int on_bus_track(sd_bus_track
*track
, void *userdata
) {
1463 Session
*s
= ASSERT_PTR(userdata
);
1467 session_drop_controller(s
);
1472 int session_set_controller(Session
*s
, const char *sender
, bool force
, bool prepare
) {
1473 _cleanup_free_
char *name
= NULL
;
1479 if (session_is_controller(s
, sender
))
1481 if (s
->controller
&& !force
)
1484 name
= strdup(sender
);
1488 s
->track
= sd_bus_track_unref(s
->track
);
1489 r
= sd_bus_track_new(s
->manager
->bus
, &s
->track
, on_bus_track
, s
);
1493 r
= sd_bus_track_add_name(s
->track
, name
);
1497 /* When setting a session controller, we forcibly mute the VT and set
1498 * it into graphics-mode. Applications can override that by changing
1499 * VT state after calling TakeControl(). However, this serves as a good
1500 * default and well-behaving controllers can now ignore VTs entirely.
1501 * Note that we reset the VT on ReleaseControl() and if the controller
1503 * If logind crashes/restarts, we restore the controller during restart
1504 * (without preparing the VT since the controller has probably overridden
1505 * VT state by now) or reset the VT in case it crashed/exited, too. */
1507 r
= session_prepare_vt(s
);
1509 s
->track
= sd_bus_track_unref(s
->track
);
1514 session_release_controller(s
, true);
1515 s
->controller
= TAKE_PTR(name
);
1516 (void) session_save(s
);
1521 void session_drop_controller(Session
*s
) {
1527 s
->track
= sd_bus_track_unref(s
->track
);
1528 session_set_type(s
, s
->original_type
);
1529 session_release_controller(s
, false);
1530 (void) session_save(s
);
1531 session_restore_vt(s
);
1534 bool session_job_pending(Session
*s
) {
1538 /* Check if we have some jobs enqueued and not finished yet. Each time we get JobRemoved signal about
1539 * relevant units, session_send_create_reply and hence us is called (see match_job_removed).
1540 * Note that we don't care about job result here. */
1542 return s
->scope_job
||
1543 s
->user
->runtime_dir_job
||
1544 (SESSION_CLASS_WANTS_SERVICE_MANAGER(s
->class) && s
->user
->service_manager_job
);
1547 int session_send_create_reply(Session
*s
, const sd_bus_error
*error
) {
1552 /* If error occurred, return it immediately. Otherwise let's wait for all jobs to finish before
1554 if (!sd_bus_error_is_set(error
) && session_job_pending(s
))
1558 RET_GATHER(r
, session_send_create_reply_bus(s
, error
));
1559 RET_GATHER(r
, session_send_create_reply_varlink(s
, error
));
1563 bool session_is_self(const char *name
) {
1564 return isempty(name
) || streq(name
, "self");
1567 bool session_is_auto(const char *name
) {
1568 return streq_ptr(name
, "auto");
1571 static const char* const session_state_table
[_SESSION_STATE_MAX
] = {
1572 [SESSION_OPENING
] = "opening",
1573 [SESSION_ONLINE
] = "online",
1574 [SESSION_ACTIVE
] = "active",
1575 [SESSION_CLOSING
] = "closing",
1578 DEFINE_STRING_TABLE_LOOKUP(session_state
, SessionState
);
1580 static const char* const session_type_table
[_SESSION_TYPE_MAX
] = {
1581 [SESSION_UNSPECIFIED
] = "unspecified",
1582 [SESSION_TTY
] = "tty",
1583 [SESSION_X11
] = "x11",
1584 [SESSION_WAYLAND
] = "wayland",
1585 [SESSION_MIR
] = "mir",
1586 [SESSION_WEB
] = "web",
1589 DEFINE_STRING_TABLE_LOOKUP(session_type
, SessionType
);
1591 static const char* const session_class_table
[_SESSION_CLASS_MAX
] = {
1592 [SESSION_USER
] = "user",
1593 [SESSION_USER_EARLY
] = "user-early",
1594 [SESSION_USER_INCOMPLETE
] = "user-incomplete",
1595 [SESSION_USER_LIGHT
] = "user-light",
1596 [SESSION_USER_EARLY_LIGHT
] = "user-early-light",
1597 [SESSION_GREETER
] = "greeter",
1598 [SESSION_LOCK_SCREEN
] = "lock-screen",
1599 [SESSION_BACKGROUND
] = "background",
1600 [SESSION_BACKGROUND_LIGHT
] = "background-light",
1601 [SESSION_MANAGER
] = "manager",
1602 [SESSION_MANAGER_EARLY
] = "manager-early",
1603 [SESSION_NONE
] = "none",
1606 DEFINE_STRING_TABLE_LOOKUP(session_class
, SessionClass
);
1608 static const char* const kill_whom_table
[_KILL_WHOM_MAX
] = {
1609 [KILL_LEADER
] = "leader",
1613 DEFINE_STRING_TABLE_LOOKUP(kill_whom
, KillWhom
);
1615 static const char* const tty_validity_table
[_TTY_VALIDITY_MAX
] = {
1616 [TTY_FROM_PAM
] = "from-pam",
1617 [TTY_FROM_UTMP
] = "from-utmp",
1618 [TTY_UTMP_INCONSISTENT
] = "utmp-inconsistent",
1621 DEFINE_STRING_TABLE_LOOKUP(tty_validity
, TTYValidity
);