]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
logind: enforce a limit on current user sessions
authorLennart Poettering <lennart@poettering.net>
Wed, 4 May 2016 16:57:15 +0000 (18:57 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 5 May 2016 20:50:09 +0000 (22:50 +0200)
We really should put limits on all resources we manage, hence add one to the
number of concurrent sessions, too. This was previously unbounded, hence set a
relatively high limit of 8K by default.

Note that most PAM setups will actually invoke pam_systemd prefixed with "-",
so that the return code of pam_systemd is ignored, and the login attempt
succeeds anyway. On systems like this the session will be created but is not
tracked by systemd.

man/logind.conf.xml
src/login/logind-dbus.c
src/login/logind-gperf.gperf
src/login/logind.c
src/login/logind.conf.in
src/login/logind.h

index 6ba35414befa8f2a8ac2b6fab5dccd2a0988deb6..405dcf904142a22b182a410cd32ef74f12748ec1 100644 (file)
         memory as is needed.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>SessionsMax=</varname></term>
+
+        <listitem><para>Controls the maximum number of concurrent user sessions to manage. Defaults to 8192
+        (8K). Depending on how the <filename>pam_systemd.so</filename> module is included in the PAM stack
+        configuration, further login sessions will either be refused, or permitted but not tracked by
+        <filename>systemd-logind</filename>.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>UserTasksMax=</varname></term>
 
index a281f99a343199c3526d945d69e79a65b5158e3a..5067e5d1a840ed0039488b79b1e36ac8319b3ebf 100644 (file)
@@ -265,6 +265,24 @@ static int property_get_docked(
         return sd_bus_message_append(reply, "b", manager_is_docked_or_external_displays(m));
 }
 
+static int property_get_current_sessions(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+        Manager *m = userdata;
+
+        assert(bus);
+        assert(reply);
+        assert(m);
+
+        return sd_bus_message_append(reply, "t", (uint64_t) hashmap_size(m->sessions));
+}
+
 static int method_get_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_free_ char *p = NULL;
         Manager *m = userdata;
@@ -725,6 +743,9 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
             m->seat0->positions[vtnr]->class != SESSION_GREETER)
                 return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already occupied by a session");
 
+        if (hashmap_size(m->sessions) >= m->sessions_max)
+                return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Maximum number of sessions (%" PRIu64 ") reached, refusing further sessions.", m->sessions_max);
+
         audit_session_from_pid(leader, &audit_id);
         if (audit_id > 0) {
                 /* Keep our session IDs and the audit session IDs in sync */
@@ -2512,6 +2533,8 @@ const sd_bus_vtable manager_vtable[] = {
         SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
         SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0),
         SD_BUS_PROPERTY("Docked", "b", property_get_docked, 0, 0),
+        SD_BUS_PROPERTY("SessionsMax", "t", NULL, offsetof(Manager, sessions_max), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("NCurrentSessions", "t", property_get_current_sessions, 0, 0),
 
         SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
index 8552c464ccaf4cdb8a7d4226554452f5d6acb12e..1d576812608c03ab146dd9ec4611477e1871afd2 100644 (file)
@@ -34,4 +34,5 @@ Login.IdleAction,                  config_parse_handle_action, 0, offsetof(Manag
 Login.IdleActionSec,               config_parse_sec,           0, offsetof(Manager, idle_action_usec)
 Login.RuntimeDirectorySize,        config_parse_tmpfs_size,    0, offsetof(Manager, runtime_dir_size)
 Login.RemoveIPC,                   config_parse_bool,          0, offsetof(Manager, remove_ipc)
+Login.SessionsMax,                 config_parse_uint64,        0, offsetof(Manager, sessions_max)
 Login.UserTasksMax,                config_parse_uint64,        0, offsetof(Manager, user_tasks_max)
index a48e2fc61ec3d9a9eac57e8250ec1d350ba45ad0..39f53cab360ac62c220f7f1e7dc9eca964c043ef 100644 (file)
@@ -63,6 +63,7 @@ static void manager_reset_config(Manager *m) {
 
         m->runtime_dir_size = PAGE_ALIGN((size_t) (physical_memory() / 10)); /* 10% */
         m->user_tasks_max = UINT64_C(12288);
+        m->sessions_max = UINT64_C(8192);
 
         m->kill_user_processes = KILL_USER_PROCESSES;
 
index 3c96def45d941eb92040f8d59c473e17a936f69c..6284218625501c53458e80aa4ed13476f0b6bad5 100644 (file)
@@ -32,4 +32,5 @@
 #IdleActionSec=30min
 #RuntimeDirectorySize=10%
 #RemoveIPC=yes
+#SessionsMax=8192
 #UserTasksMax=12288
index 6748af3c07eecbe6d1cba038b75e046c51925bd4..23c3e2963a62fa2fb65d9134cc4dcdcb71d04fd0 100644 (file)
@@ -133,6 +133,7 @@ struct Manager {
 
         size_t runtime_dir_size;
         uint64_t user_tasks_max;
+        uint64_t sessions_max;
 };
 
 int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_device);