]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/login/logind-session.c
Merge pull request #11827 from keszybz/pkgconfig-variables
[thirdparty/systemd.git] / src / login / logind-session.c
index 85ee93ca567ad9e4f530fc704b717faaafa77007..90a9108566637c39e8eb1ae0349de6793ece171e 100644 (file)
@@ -16,6 +16,7 @@
 #include "audit-util.h"
 #include "bus-error.h"
 #include "bus-util.h"
+#include "env-file.h"
 #include "escape.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "parse-util.h"
 #include "path-util.h"
 #include "process-util.h"
+#include "serialize.h"
 #include "string-table.h"
 #include "strv.h"
 #include "terminal-util.h"
+#include "tmpfile-util.h"
 #include "user-util.h"
 #include "util.h"
 
 #define RELEASE_USEC (20*USEC_PER_SEC)
 
 static void session_remove_fifo(Session *s);
+static void session_restore_vt(Session *s);
 
 int session_new(Session **ret, Manager *m, const char *id) {
         _cleanup_(session_freep) Session *s = NULL;
@@ -56,6 +60,7 @@ int session_new(Session **ret, Manager *m, const char *id) {
                 .fifo_fd = -1,
                 .vtfd = -1,
                 .audit_id = AUDIT_SESSION_INVALID,
+                .tty_validity = _TTY_VALIDITY_INVALID,
         };
 
         s->state_file = strappend("/run/systemd/sessions/", id);
@@ -101,6 +106,8 @@ Session* session_free(Session *s) {
 
                 if (s->user->display == s)
                         s->user->display = NULL;
+
+                user_update_last_session_timer(s->user);
         }
 
         if (s->seat) {
@@ -118,6 +125,9 @@ Session* session_free(Session *s) {
                 free(s->scope);
         }
 
+        if (pid_is_valid(s->leader))
+                (void) hashmap_remove_value(s->manager->sessions_by_leader, PID_TO_PTR(s->leader), s);
+
         free(s->scope_job);
 
         sd_bus_message_unref(s->create_message);
@@ -142,6 +152,32 @@ void session_set_user(Session *s, User *u) {
 
         s->user = u;
         LIST_PREPEND(sessions_by_user, u->sessions, s);
+
+        user_update_last_session_timer(u);
+}
+
+int session_set_leader(Session *s, pid_t pid) {
+        int r;
+
+        assert(s);
+
+        if (!pid_is_valid(pid))
+                return -EINVAL;
+
+        if (s->leader == pid)
+                return 0;
+
+        r = hashmap_put(s->manager->sessions_by_leader, PID_TO_PTR(pid), s);
+        if (r < 0)
+                return r;
+
+        if (pid_is_valid(s->leader))
+                (void) hashmap_remove_value(s->manager->sessions_by_leader, PID_TO_PTR(s->leader), s);
+
+        s->leader = pid;
+        (void) audit_session_from_pid(pid, &s->audit_id);
+
+        return 1;
 }
 
 static void session_save_devices(Session *s, FILE *f) {
@@ -215,6 +251,9 @@ int session_save(Session *s) {
         if (s->tty)
                 fprintf(f, "TTY=%s\n", s->tty);
 
+        if (s->tty_validity >= 0)
+                fprintf(f, "TTY_VALIDITY=%s\n", tty_validity_to_string(s->tty_validity));
+
         if (s->display)
                 fprintf(f, "DISPLAY=%s\n", s->display);
 
@@ -351,6 +390,7 @@ static int session_load_devices(Session *s, const char *devices) {
 int session_load(Session *s) {
         _cleanup_free_ char *remote = NULL,
                 *seat = NULL,
+                *tty_validity = NULL,
                 *vtnr = NULL,
                 *state = NULL,
                 *position = NULL,
@@ -369,13 +409,14 @@ int session_load(Session *s) {
 
         assert(s);
 
-        r = parse_env_file(NULL, s->state_file, NEWLINE,
+        r = parse_env_file(NULL, s->state_file,
                            "REMOTE",         &remote,
                            "SCOPE",          &s->scope,
                            "SCOPE_JOB",      &s->scope_job,
                            "FIFO",           &s->fifo_path,
                            "SEAT",           &seat,
                            "TTY",            &s->tty,
+                           "TTY_VALIDITY",   &tty_validity,
                            "DISPLAY",        &s->display,
                            "REMOTE_HOST",    &s->remote_host,
                            "REMOTE_USER",    &s->remote_user,
@@ -393,8 +434,7 @@ int session_load(Session *s) {
                            "CONTROLLER",     &controller,
                            "ACTIVE",         &active,
                            "DEVICES",        &devices,
-                           "IS_DISPLAY",     &is_display,
-                           NULL);
+                           "IS_DISPLAY",     &is_display);
 
         if (r < 0)
                 return log_error_errno(r, "Failed to read %s: %m", s->state_file);
@@ -403,10 +443,10 @@ int session_load(Session *s) {
                 uid_t u;
                 User *user;
 
-                if (!uid) {
-                        log_error("UID not specified for session %s", s->id);
-                        return -ENOENT;
-                }
+                if (!uid)
+                        return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
+                                               "UID not specified for session %s",
+                                               s->id);
 
                 r = parse_uid(uid, &u);
                 if (r < 0)  {
@@ -415,10 +455,10 @@ int session_load(Session *s) {
                 }
 
                 user = hashmap_get(s->manager->users, UID_TO_PTR(u));
-                if (!user) {
-                        log_error("User of session %s not known.", s->id);
-                        return -ENOENT;
-                }
+                if (!user)
+                        return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
+                                               "User of session %s not known.",
+                                               s->id);
 
                 session_set_user(s, user);
         }
@@ -446,15 +486,33 @@ int session_load(Session *s) {
                 s->vtnr = 0;
 
         if (position && s->seat) {
-                unsigned int npos;
+                unsigned npos;
 
                 safe_atou(position, &npos);
                 seat_claim_position(s->seat, s, npos);
         }
 
+        if (tty_validity) {
+                TTYValidity v;
+
+                v = tty_validity_from_string(tty_validity);
+                if (v < 0)
+                        log_debug("Failed to parse TTY validity: %s", tty_validity);
+                else
+                        s->tty_validity = v;
+        }
+
         if (leader) {
-                if (parse_pid(leader, &s->leader) >= 0)
-                        (void) audit_session_from_pid(s->leader, &s->audit_id);
+                pid_t pid;
+
+                r = parse_pid(leader, &pid);
+                if (r < 0)
+                        log_debug_errno(r, "Failed to parse leader PID of session: %s", leader);
+                else {
+                        r = session_set_leader(s, pid);
+                        if (r < 0)
+                                log_warning_errno(r, "Failed to set session leader PID, ignoring: %m");
+                }
         }
 
         if (type) {
@@ -491,9 +549,9 @@ int session_load(Session *s) {
         }
 
         if (realtime)
-                timestamp_deserialize(realtime, &s->timestamp.realtime);
+                (void) deserialize_usec(realtime, &s->timestamp.realtime);
         if (monotonic)
-                timestamp_deserialize(monotonic, &s->timestamp.monotonic);
+                (void) deserialize_usec(monotonic, &s->timestamp.monotonic);
 
         if (active) {
                 k = parse_boolean(active);
@@ -525,7 +583,7 @@ int session_load(Session *s) {
 }
 
 int session_activate(Session *s) {
-        unsigned int num_pending;
+        unsigned num_pending;
 
         assert(s);
         assert(s->user);
@@ -587,6 +645,7 @@ static int session_start_scope(Session *s, sd_bus_message *properties, sd_bus_er
                                 description,
                                 STRV_MAKE(s->user->runtime_dir_service, s->user->service), /* These two have StopWhenUnneeded= set, hence add a dep towards them */
                                 STRV_MAKE("systemd-logind.service", "systemd-user-sessions.service", s->user->runtime_dir_service, s->user->service), /* And order us after some more */
+                                s->user->home,
                                 properties,
                                 error,
                                 &s->scope_job);
@@ -889,7 +948,7 @@ int session_get_idle_hint(Session *s, dual_timestamp *t) {
 
         /* For sessions with a leader but no explicitly configured
          * tty, let's check the controlling tty of the leader */
-        if (s->leader > 0) {
+        if (pid_is_valid(s->leader)) {
                 r = get_process_ctty_atime(s->leader, &atime);
                 if (r >= 0)
                         goto found_atime;
@@ -1167,13 +1226,8 @@ error:
         return r;
 }
 
-void session_restore_vt(Session *s) {
-
-        static const struct vt_mode mode = {
-                .mode = VT_AUTO,
-        };
-
-        int vt, old_fd;
+static void session_restore_vt(Session *s) {
+        int r, vt, old_fd;
 
         /* We need to get a fresh handle to the virtual terminal,
          * since the old file-descriptor is potentially in a hung-up
@@ -1189,12 +1243,9 @@ void session_restore_vt(Session *s) {
         if (vt < 0)
                 return;
 
-        (void) ioctl(vt, KDSETMODE, KD_TEXT);
-
-        (void) vt_reset_keyboard(vt);
-
-        (void) ioctl(vt, VT_SETMODE, &mode);
-        (void) fchown(vt, 0, (gid_t) -1);
+        r = vt_restore(vt);
+        if (r < 0)
+                log_warning_errno(r, "Failed to restore VT, ignoring: %m");
 
         s->vtfd = safe_close(s->vtfd);
 }
@@ -1219,9 +1270,9 @@ void session_leave_vt(Session *s) {
                 return;
 
         session_device_pause_all(s);
-        r = ioctl(s->vtfd, VT_RELDISP, 1);
+        r = vt_release(s->vtfd, false);
         if (r < 0)
-                log_debug_errno(errno, "Cannot release VT of session %s: %m", s->id);
+                log_debug_errno(r, "Cannot release VT of session %s: %m", s->id);
 }
 
 bool session_is_controller(Session *s, const char *sender) {
@@ -1359,3 +1410,11 @@ static const char* const kill_who_table[_KILL_WHO_MAX] = {
 };
 
 DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);
+
+static const char* const tty_validity_table[_TTY_VALIDITY_MAX] = {
+        [TTY_FROM_PAM] = "from-pam",
+        [TTY_FROM_UTMP] = "from-utmp",
+        [TTY_UTMP_INCONSISTENT] = "utmp-inconsistent",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(tty_validity, TTYValidity);