summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2016-05-04 18:57:15 +0200
committerLennart Poettering <lennart@poettering.net>2016-05-05 22:50:09 +0200
commit183e0738427b83667512276a3e8c10274c0824cc (patch)
treecc0267b812b7b5d70694468cc25e51c96c588880
parent37818090c99871577c0cfd8171901eb7e2050be9 (diff)
logind: enforce a limit on current user sessions
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.
-rw-r--r--man/logind.conf.xml9
-rw-r--r--src/login/logind-dbus.c23
-rw-r--r--src/login/logind-gperf.gperf1
-rw-r--r--src/login/logind.c1
-rw-r--r--src/login/logind.conf.in1
-rw-r--r--src/login/logind.h1
6 files changed, 36 insertions, 0 deletions
diff --git a/man/logind.conf.xml b/man/logind.conf.xml
index 6ba35414be..405dcf9041 100644
--- a/man/logind.conf.xml
+++ b/man/logind.conf.xml
@@ -297,6 +297,15 @@
</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>
<listitem><para>Sets the maximum number of OS tasks each user
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index a281f99a34..5067e5d1a8 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -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),
diff --git a/src/login/logind-gperf.gperf b/src/login/logind-gperf.gperf
index 8552c464cc..1d57681260 100644
--- a/src/login/logind-gperf.gperf
+++ b/src/login/logind-gperf.gperf
@@ -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)
diff --git a/src/login/logind.c b/src/login/logind.c
index a48e2fc61e..39f53cab36 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -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;
diff --git a/src/login/logind.conf.in b/src/login/logind.conf.in
index 3c96def45d..6284218625 100644
--- a/src/login/logind.conf.in
+++ b/src/login/logind.conf.in
@@ -32,4 +32,5 @@
#IdleActionSec=30min
#RuntimeDirectorySize=10%
#RemoveIPC=yes
+#SessionsMax=8192
#UserTasksMax=12288
diff --git a/src/login/logind.h b/src/login/logind.h
index 6748af3c07..23c3e2963a 100644
--- a/src/login/logind.h
+++ b/src/login/logind.h
@@ -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);