teknoraver / rpms / systemd

Forked from rpms/systemd a month ago
Clone

Blame SOURCES/0339-logind-add-option-to-stop-idle-sessions-after-specif.patch

594167
From a8980738c4ef8fba4fd8995ab69669d438ad7a9f Mon Sep 17 00:00:00 2001
594167
From: Michal Sekletar <msekleta@redhat.com>
594167
Date: Mon, 8 Aug 2022 09:13:50 +0200
594167
Subject: [PATCH] logind: add option to stop idle sessions after specified
594167
 timeout
594167
594167
Thanks to Jan Pazdziora <jpazdziora@redhat.com> for providing a patch
594167
which implemeted a PoC of this feature.
594167
594167
(cherry picked from commit 82325af3ae41bc7efb3d5cd8f56a4652fef498c2)
594167
594167
Resolves: #2100464
594167
---
594167
 man/logind.conf.xml            | 11 ++++++
594167
 man/org.freedesktop.login1.xml |  6 +++
594167
 src/login/logind-core.c        |  2 +
594167
 src/login/logind-dbus.c        |  1 +
594167
 src/login/logind-gperf.gperf   |  1 +
594167
 src/login/logind-session.c     | 67 ++++++++++++++++++++++++++++++++--
594167
 src/login/logind-session.h     |  2 +
594167
 src/login/logind.conf.in       |  1 +
594167
 src/login/logind.h             |  2 +
594167
 9 files changed, 90 insertions(+), 3 deletions(-)
594167
594167
diff --git a/man/logind.conf.xml b/man/logind.conf.xml
594167
index 96fa076239..c37fd97be1 100644
594167
--- a/man/logind.conf.xml
594167
+++ b/man/logind.conf.xml
594167
@@ -357,6 +357,17 @@
594167
         are excluded from the effect of this setting. Defaults to <literal>no</literal>.</para></listitem>
594167
       </varlistentry>
594167
 
594167
+      <varlistentry>
594167
+        <term><varname>StopIdleSessionSec=</varname></term>
594167
+
594167
+        <listitem><para>Specifies a timeout in seconds, or a time span value after which
594167
+        <filename>systemd-logind</filename> checks the idle state of all sessions. Every session that is idle for
594167
+        longer then the timeout will be stopped. Defaults to <literal>infinity</literal>
594167
+        (<filename>systemd-logind</filename> is not checking the idle state of sessions). For details about the syntax
594167
+        of time spans, see
594167
+        <citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
594167
+        </para></listitem>
594167
+      </varlistentry>
594167
     </variablelist>
594167
   </refsect1>
594167
 
594167
diff --git a/man/org.freedesktop.login1.xml b/man/org.freedesktop.login1.xml
594167
index c11324ee3b..0ebcfb84ab 100644
594167
--- a/man/org.freedesktop.login1.xml
594167
+++ b/man/org.freedesktop.login1.xml
594167
@@ -235,6 +235,8 @@ node /org/freedesktop/login1 {
594167
       readonly t SessionsMax = ...;
594167
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
594167
       readonly t NCurrentSessions = ...;
594167
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
594167
+      readonly t StopIdleSessionUSec = ...;
594167
   };
594167
   interface org.freedesktop.DBus.Peer { ... };
594167
   interface org.freedesktop.DBus.Introspectable { ... };
594167
@@ -242,6 +244,8 @@ node /org/freedesktop/login1 {
594167
 };
594167
     </programlisting>
594167
 
594167
+    
594167
+
594167
     
594167
 
594167
     <variablelist class="dbus-interface" generated="True" extra-ref="org.freedesktop.login1.Manager"/>
594167
@@ -460,6 +464,8 @@ node /org/freedesktop/login1 {
594167
 
594167
     <variablelist class="dbus-property" generated="True" extra-ref="NCurrentSessions"/>
594167
 
594167
+    <variablelist class="dbus-property" generated="True" extra-ref="StopIdleSessionUSec"/>
594167
+
594167
     
594167
 
594167
     <refsect2>
594167
diff --git a/src/login/logind-core.c b/src/login/logind-core.c
594167
index 616c08132a..9807c85b8c 100644
594167
--- a/src/login/logind-core.c
594167
+++ b/src/login/logind-core.c
594167
@@ -71,6 +71,8 @@ void manager_reset_config(Manager *m) {
594167
 
594167
         m->kill_only_users = strv_free(m->kill_only_users);
594167
         m->kill_exclude_users = strv_free(m->kill_exclude_users);
594167
+
594167
+        m->stop_idle_session_usec = USEC_INFINITY;
594167
 }
594167
 
594167
 int manager_parse_config_file(Manager *m) {
594167
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
594167
index 31a41bd271..c97a89c37d 100644
594167
--- a/src/login/logind-dbus.c
594167
+++ b/src/login/logind-dbus.c
594167
@@ -3389,6 +3389,7 @@ static const sd_bus_vtable manager_vtable[] = {
594167
         SD_BUS_PROPERTY("SessionsMax", "t", NULL, offsetof(Manager, sessions_max), SD_BUS_VTABLE_PROPERTY_CONST),
594167
         SD_BUS_PROPERTY("NCurrentSessions", "t", property_get_hashmap_size, offsetof(Manager, sessions), 0),
594167
         SD_BUS_PROPERTY("UserTasksMax", "t", property_get_compat_user_tasks_max, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
594167
+        SD_BUS_PROPERTY("StopIdleSessionUSec", "t", NULL, offsetof(Manager, stop_idle_session_usec), SD_BUS_VTABLE_PROPERTY_CONST),
594167
 
594167
         SD_BUS_METHOD_WITH_ARGS("GetSession",
594167
                                 SD_BUS_ARGS("s", session_id),
594167
diff --git a/src/login/logind-gperf.gperf b/src/login/logind-gperf.gperf
594167
index 867db36533..300d56542d 100644
594167
--- a/src/login/logind-gperf.gperf
594167
+++ b/src/login/logind-gperf.gperf
594167
@@ -50,3 +50,4 @@ Login.RemoveIPC,                    config_parse_bool,                  0, offse
594167
 Login.InhibitorsMax,                config_parse_uint64,                0, offsetof(Manager, inhibitors_max)
594167
 Login.SessionsMax,                  config_parse_uint64,                0, offsetof(Manager, sessions_max)
594167
 Login.UserTasksMax,                 config_parse_compat_user_tasks_max, 0, 0
594167
+Login.StopIdleSessionSec,           config_parse_sec_fix_0,             0, offsetof(Manager, stop_idle_session_usec)
594167
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
594167
index a052596e57..a110b6f1c1 100644
594167
--- a/src/login/logind-session.c
594167
+++ b/src/login/logind-session.c
594167
@@ -150,6 +150,8 @@ Session* session_free(Session *s) {
594167
         free(s->state_file);
594167
         free(s->fifo_path);
594167
 
594167
+        sd_event_source_unref(s->stop_on_idle_event_source);
594167
+
594167
         return mfree(s);
594167
 }
594167
 
594167
@@ -687,6 +689,55 @@ static int session_start_scope(Session *s, sd_bus_message *properties, sd_bus_er
594167
         return 0;
594167
 }
594167
 
594167
+static int session_dispatch_stop_on_idle(sd_event_source *source, uint64_t t, void *userdata) {
594167
+        Session *s = userdata;
594167
+        dual_timestamp ts;
594167
+        int r, idle;
594167
+
594167
+        assert(s);
594167
+
594167
+        if (s->stopping)
594167
+                return 0;
594167
+
594167
+        idle = session_get_idle_hint(s, &ts);
594167
+        if (idle) {
594167
+                log_debug("Session \"%s\" of user \"%s\" is idle, stopping.", s->id, s->user->user_record->user_name);
594167
+
594167
+                return session_stop(s, /* force */ true);
594167
+        }
594167
+
594167
+        r = sd_event_source_set_time(source, usec_add(ts.monotonic, s->manager->stop_idle_session_usec));
594167
+        if (r < 0)
594167
+                return log_error_errno(r, "Failed to configure stop on idle session event source: %m");
594167
+
594167
+        r = sd_event_source_set_enabled(source, SD_EVENT_ONESHOT);
594167
+        if (r < 0)
594167
+                return log_error_errno(r, "Failed to enable stop on idle session event source: %m");
594167
+
594167
+        return 1;
594167
+}
594167
+
594167
+static int session_setup_stop_on_idle_timer(Session *s) {
594167
+        int r;
594167
+
594167
+        assert(s);
594167
+
594167
+        if (s->manager->stop_idle_session_usec == USEC_INFINITY)
594167
+                return 0;
594167
+
594167
+        r = sd_event_add_time_relative(
594167
+                        s->manager->event,
594167
+                        &s->stop_on_idle_event_source,
594167
+                        CLOCK_MONOTONIC,
594167
+                        s->manager->stop_idle_session_usec,
594167
+                        0,
594167
+                        session_dispatch_stop_on_idle, s);
594167
+        if (r < 0)
594167
+                return log_error_errno(r, "Failed to add stop on idle session event source: %m");
594167
+
594167
+        return 0;
594167
+}
594167
+
594167
 int session_start(Session *s, sd_bus_message *properties, sd_bus_error *error) {
594167
         int r;
594167
 
594167
@@ -709,6 +760,10 @@ int session_start(Session *s, sd_bus_message *properties, sd_bus_error *error) {
594167
         if (r < 0)
594167
                 return r;
594167
 
594167
+        r = session_setup_stop_on_idle_timer(s);
594167
+        if (r < 0)
594167
+                return r;
594167
+
594167
         log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
594167
                    "MESSAGE_ID=" SD_MESSAGE_SESSION_START_STR,
594167
                    "SESSION_ID=%s", s->id,
594167
@@ -949,7 +1004,7 @@ static int get_process_ctty_atime(pid_t pid, usec_t *atime) {
594167
 }
594167
 
594167
 int session_get_idle_hint(Session *s, dual_timestamp *t) {
594167
-        usec_t atime = 0;
594167
+        usec_t atime = 0, dtime = 0;
594167
         int r;
594167
 
594167
         assert(s);
594167
@@ -986,10 +1041,16 @@ found_atime:
594167
         if (t)
594167
                 dual_timestamp_from_realtime(t, atime);
594167
 
594167
-        if (s->manager->idle_action_usec <= 0)
594167
+        if (s->manager->idle_action_usec > 0 && s->manager->stop_idle_session_usec != USEC_INFINITY)
594167
+                dtime = MIN(s->manager->idle_action_usec, s->manager->stop_idle_session_usec);
594167
+        else if (s->manager->idle_action_usec > 0)
594167
+                dtime = s->manager->idle_action_usec;
594167
+        else if (s->manager->stop_idle_session_usec != USEC_INFINITY)
594167
+                dtime = s->manager->stop_idle_session_usec;
594167
+        else
594167
                 return false;
594167
 
594167
-        return usec_add(atime, s->manager->idle_action_usec) <= now(CLOCK_REALTIME);
594167
+        return usec_add(atime, dtime) <= now(CLOCK_REALTIME);
594167
 }
594167
 
594167
 int session_set_idle_hint(Session *s, bool b) {
594167
diff --git a/src/login/logind-session.h b/src/login/logind-session.h
594167
index 6b6ac2d573..4c28607986 100644
594167
--- a/src/login/logind-session.h
594167
+++ b/src/login/logind-session.h
594167
@@ -115,6 +115,8 @@ struct Session {
594167
         Hashmap *devices;
594167
         sd_bus_track *track;
594167
 
594167
+        sd_event_source *stop_on_idle_event_source;
594167
+
594167
         LIST_FIELDS(Session, sessions_by_user);
594167
         LIST_FIELDS(Session, sessions_by_seat);
594167
 
594167
diff --git a/src/login/logind.conf.in b/src/login/logind.conf.in
594167
index 79d685b3de..fcdbad58c7 100644
594167
--- a/src/login/logind.conf.in
594167
+++ b/src/login/logind.conf.in
594167
@@ -43,3 +43,4 @@
594167
 #RemoveIPC=no
594167
 #InhibitorsMax=8192
594167
 #SessionsMax=8192
594167
+#StopIdleSessionSec=infinity
594167
diff --git a/src/login/logind.h b/src/login/logind.h
594167
index 730c14a46a..e5c68a74cb 100644
594167
--- a/src/login/logind.h
594167
+++ b/src/login/logind.h
594167
@@ -101,6 +101,8 @@ struct Manager {
594167
         usec_t idle_action_not_before_usec;
594167
         HandleAction idle_action;
594167
 
594167
+        usec_t stop_idle_session_usec;
594167
+
594167
         HandleAction handle_power_key;
594167
         HandleAction handle_power_key_long_press;
594167
         HandleAction handle_reboot_key;