From: Lennart Poettering Date: Wed, 4 May 2016 16:57:15 +0000 (+0200) Subject: logind: enforce a limit on current user sessions X-Git-Tag: v231.3~163 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=0fa22a24e08416f3ba2278b9780990e67faf6e30 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_elogind prefixed with "-", so that the return code of pam_elogind is ignored, and the login attempt succeeds anyway. On systems like this the session will be created but is not tracked by elogind. --- diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index dba4c728f..c81592c2a 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 */ @@ -2571,6 +2592,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.h b/src/login/logind.h index 986f98ccc..3a9ccb6e5 100644 --- a/src/login/logind.h +++ b/src/login/logind.h @@ -162,6 +162,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);