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.
This commit is contained in:
Lennart Poettering 2016-05-04 18:57:15 +02:00
parent 37818090c9
commit 183e073842
6 changed files with 36 additions and 0 deletions

View File

@ -296,6 +296,15 @@
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>

View 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),

View 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)

View 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;

View File

@ -32,4 +32,5 @@
#IdleActionSec=30min
#RuntimeDirectorySize=10%
#RemoveIPC=yes
#SessionsMax=8192
#UserTasksMax=12288

View 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);