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 @@ -296,6 +296,15 @@ memory as is needed. + + SessionsMax= + + Controls the maximum number of concurrent user sessions to manage. Defaults to 8192 + (8K). Depending on how the pam_systemd.so module is included in the PAM stack + configuration, further login sessions will either be refused, or permitted but not tracked by + systemd-logind. + + UserTasksMax= 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);