logind: enforce a limit on inhibitors we hand out
authorLennart Poettering <lennart@poettering.net>
Wed, 4 May 2016 17:40:05 +0000 (19:40 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 5 May 2016 20:50:09 +0000 (22:50 +0200)
For similar reasons as the recent addition of a limit on sessions.

Note that we don't enforce a limit on inhibitors per-user currently, but
there's an implicit one, since each inhibitor takes up one fd, and fds are
limited via RLIMIT_NOFILE, and the limit on the number of processes per user.

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 405dcf9..fe92277 100644 (file)
       </varlistentry>
 
       <varlistentry>
+        <term><varname>InhibitorsMax=</varname></term>
+
+        <listitem><para>Controls the maximum number of concurrent inhibitors to permit. Defaults to 8192
+        (8K).</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
         <term><varname>SessionsMax=</varname></term>
 
         <listitem><para>Controls the maximum number of concurrent user sessions to manage. Defaults to 8192
index d249bff..0a84d75 100644 (file)
@@ -283,6 +283,24 @@ static int property_get_current_sessions(
         return sd_bus_message_append(reply, "t", (uint64_t) hashmap_size(m->sessions));
 }
 
+static int property_get_current_inhibitors(
+                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->inhibitors));
+}
+
 static int method_get_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_free_ char *p = NULL;
         Manager *m = userdata;
@@ -2463,6 +2481,9 @@ static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error
         if (r < 0)
                 return r;
 
+        if (hashmap_size(m->inhibitors) >= m->inhibitors_max)
+                return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Maximum number of inhibitors (%" PRIu64 ") reached, refusing further inhibitors.", m->inhibitors_max);
+
         do {
                 id = mfree(id);
 
@@ -2535,6 +2556,8 @@ const sd_bus_vtable manager_vtable[] = {
         SD_BUS_PROPERTY("Docked", "b", property_get_docked, 0, 0),
         SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(Manager, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("RuntimeDirectorySize", "t", bus_property_get_size, offsetof(Manager, runtime_dir_size), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("InhibitorsMax", "t", NULL, offsetof(Manager, inhibitors_max), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("NCurrentInhibitors", "t", property_get_current_inhibitors, 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_PROPERTY("UserTasksMax", "t", NULL, offsetof(Manager, user_tasks_max), SD_BUS_VTABLE_PROPERTY_CONST),
index 1d57681..6bd08ad 100644 (file)
@@ -34,5 +34,6 @@ 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.InhibitorsMax,               config_parse_uint64,        0, offsetof(Manager, inhibitors_max)
 Login.SessionsMax,                 config_parse_uint64,        0, offsetof(Manager, sessions_max)
 Login.UserTasksMax,                config_parse_uint64,        0, offsetof(Manager, user_tasks_max)
index 64bd1ca..1cbc8f9 100644 (file)
@@ -64,6 +64,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->inhibitors_max = UINT64_C(8192);
 
         m->kill_user_processes = KILL_USER_PROCESSES;
 
index 6284218..32c0844 100644 (file)
@@ -32,5 +32,6 @@
 #IdleActionSec=30min
 #RuntimeDirectorySize=10%
 #RemoveIPC=yes
+#InhibitorsMax=8192
 #SessionsMax=8192
 #UserTasksMax=12288
index 23c3e29..90431eb 100644 (file)
@@ -134,6 +134,7 @@ struct Manager {
         size_t runtime_dir_size;
         uint64_t user_tasks_max;
         uint64_t sessions_max;
+        uint64_t inhibitors_max;
 };
 
 int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_device);