]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
login: limit nr_inodes for /run/user/$UID
authorTopi Miettinen <toiwoton@gmail.com>
Sat, 23 May 2020 14:00:41 +0000 (17:00 +0300)
committerLennart Poettering <lennart@poettering.net>
Sun, 24 May 2020 20:54:17 +0000 (22:54 +0200)
Limit number of inodes for tmpfs mounts on /run/user/$UID. Default is
RuntimeDirectorySize= divided by 4096.

man/logind.conf.xml
man/org.freedesktop.login1.xml
src/login/logind-core.c
src/login/logind-dbus.c
src/login/logind-gperf.gperf
src/login/logind.conf.in
src/login/logind.h
src/login/user-runtime-dir.c
test/fuzz/fuzz-unit-file/directives.service

index 4cbfd09cbf26db75774e784917decf6360f4a206..b00daf366da7971c538d541c9f210e1bba4673c2 100644 (file)
         memory as is needed.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>RuntimeDirectoryInodesMax=</varname></term>
+
+        <listitem><para>Sets the limit on number of inodes for the
+        <varname>$XDG_RUNTIME_DIR</varname> runtime directory for each
+        user who logs in. Takes a number, optionally suffixed with the
+        usual K, G, M, and T suffixes, to the base 1024 (IEC).
+        Defaults to <varname>RuntimeDirectorySize=</varname> divided
+        by 4096. Note that this size is a safety limit only.
+        As each runtime directory is a tmpfs file system, it will
+        only consume as much memory as is needed.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>InhibitorsMax=</varname></term>
 
index 44ad033752d526b56c36640415a684fa919ff807..0292288d3a6402b5162c8bcf4a93b5de3c5cf924 100644 (file)
@@ -217,6 +217,8 @@ node /org/freedesktop/login1 {
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly t RuntimeDirectorySize = ...;
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+      readonly t RuntimeDirectoryInodesMax = ...;
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly t InhibitorsMax = ...;
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
       readonly t NCurrentInhibitors = ...;
@@ -425,6 +427,8 @@ node /org/freedesktop/login1 {
 
     <variablelist class="dbus-property" generated="True" extra-ref="RuntimeDirectorySize"/>
 
+    <variablelist class="dbus-property" generated="True" extra-ref="RuntimeDirectoryInodesMax"/>
+
     <variablelist class="dbus-property" generated="True" extra-ref="InhibitorsMax"/>
 
     <variablelist class="dbus-property" generated="True" extra-ref="NCurrentInhibitors"/>
@@ -623,7 +627,8 @@ node /org/freedesktop/login1 {
       <varname>HandleLidSwitchExternalPower</varname>, <varname>HandleLidSwitchDocked</varname>,
       <varname>IdleActionUSec</varname>, <varname>HoldoffTimeoutUSec</varname>,
       <varname>RemoveIPC</varname>, <varname>RuntimeDirectorySize</varname>,
-      <varname>InhibitorsMax</varname>, and <varname>SessionsMax</varname>.
+      <varname>RuntimeDirectoryInodesMax</varname>, <varname>InhibitorsMax</varname>, and
+      <varname>SessionsMax</varname>.
       </para>
 
       <para>The <varname>IdleHint</varname> property reflects the idle hint state of the system. If the
index a9006d746a0df4615d7ac232ef383852abab844c..c160f546bca7cc95e96eb5d0505d0781c0fdac3e 100644 (file)
@@ -55,6 +55,7 @@ void manager_reset_config(Manager *m) {
         m->idle_action = HANDLE_IGNORE;
 
         m->runtime_dir_size = physical_memory_scale(10U, 100U); /* 10% */
+        m->runtime_dir_inodes = DIV_ROUND_UP(m->runtime_dir_size, 4096); /* 4k per inode */
         m->sessions_max = 8192;
         m->inhibitors_max = 8192;
 
index 451fe2875487a04b19a6ac5f7116cfe57aae0b89..a88605232c40428c8441604e681ab38719184059 100644 (file)
@@ -3359,6 +3359,7 @@ static const sd_bus_vtable manager_vtable[] = {
         SD_BUS_PROPERTY("OnExternalPower", "b", property_get_on_external_power, 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", NULL, offsetof(Manager, runtime_dir_size), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("RuntimeDirectoryInodesMax", "t", NULL, offsetof(Manager, runtime_dir_inodes), 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_hashmap_size, offsetof(Manager, inhibitors), 0),
         SD_BUS_PROPERTY("SessionsMax", "t", NULL, offsetof(Manager, sessions_max), SD_BUS_VTABLE_PROPERTY_CONST),
index 983795da40d598a93f8ce33aac902c77a56e4bb6..73d96ff4367c6a7c4e739c8af94e20c68e37bed6 100644 (file)
@@ -38,6 +38,7 @@ Login.HoldoffTimeoutSec,            config_parse_sec,                   0, offse
 Login.IdleAction,                   config_parse_handle_action,         0, offsetof(Manager, idle_action)
 Login.IdleActionSec,                config_parse_sec,                   0, offsetof(Manager, idle_action_usec)
 Login.RuntimeDirectorySize,         config_parse_tmpfs_size,            0, offsetof(Manager, runtime_dir_size)
+Login.RuntimeDirectoryInodesMax,    config_parse_uint64,                0, offsetof(Manager, runtime_dir_inodes)
 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)
index 1029e29bc73565f064fc521b0caf63051fbff354..ed1084b06e295578a628fda374716cbc73b1f80b 100644 (file)
@@ -32,6 +32,7 @@
 #IdleAction=ignore
 #IdleActionSec=30min
 #RuntimeDirectorySize=10%
+#RuntimeDirectoryInodes=400k
 #RemoveIPC=yes
 #InhibitorsMax=8192
 #SessionsMax=8192
index d3f5b28078e83d271e3db433df495eac56b5c06a..e1d57277fa1bd20adea1fc90a3b79d292119d924 100644 (file)
@@ -120,6 +120,7 @@ struct Manager {
         sd_event_source *lid_switch_ignore_event_source;
 
         uint64_t runtime_dir_size;
+        uint64_t runtime_dir_inodes;
         uint64_t sessions_max;
         uint64_t inhibitors_max;
 };
index 1f98898b695e778a3bfe206741aa6a5d04a83e2d..4055c910c2d468fe840b35f1cfb5ec46eaa067c0 100644 (file)
@@ -22,7 +22,7 @@
 #include "strv.h"
 #include "user-util.h"
 
-static int acquire_runtime_dir_size(uint64_t *ret) {
+static int acquire_runtime_dir_properties(uint64_t *size, uint64_t *inodes) {
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         int r;
@@ -31,10 +31,14 @@ static int acquire_runtime_dir_size(uint64_t *ret) {
         if (r < 0)
                 return log_error_errno(r, "Failed to connect to system bus: %m");
 
-        r = sd_bus_get_property_trivial(bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "RuntimeDirectorySize", &error, 't', ret);
+        r = sd_bus_get_property_trivial(bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "RuntimeDirectorySize", &error, 't', size);
         if (r < 0)
                 return log_error_errno(r, "Failed to acquire runtime directory size: %s", bus_error_message(&error, r));
 
+        r = sd_bus_get_property_trivial(bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "RuntimeDirectoryInodesMax", &error, 't', inodes);
+        if (r < 0)
+                return log_error_errno(r, "Failed to acquire number of inodes for runtime directory: %s", bus_error_message(&error, r));
+
         return 0;
 }
 
@@ -42,7 +46,8 @@ static int user_mkdir_runtime_path(
                 const char *runtime_path,
                 uid_t uid,
                 gid_t gid,
-                uint64_t runtime_dir_size) {
+                uint64_t runtime_dir_size,
+                uint64_t runtime_dir_inodes) {
 
         int r;
 
@@ -58,14 +63,15 @@ static int user_mkdir_runtime_path(
         if (path_is_mount_point(runtime_path, NULL, 0) >= 0)
                 log_debug("%s is already a mount point", runtime_path);
         else {
-                char options[sizeof("mode=0700,uid=,gid=,size=,smackfsroot=*")
+                char options[sizeof("mode=0700,uid=,gid=,size=,nr_inodes=,smackfsroot=*")
                              + DECIMAL_STR_MAX(uid_t)
                              + DECIMAL_STR_MAX(gid_t)
+                             + DECIMAL_STR_MAX(uint64_t)
                              + DECIMAL_STR_MAX(uint64_t)];
 
                 xsprintf(options,
-                         "mode=0700,uid=" UID_FMT ",gid=" GID_FMT ",size=%" PRIu64 "%s",
-                         uid, gid, runtime_dir_size,
+                         "mode=0700,uid=" UID_FMT ",gid=" GID_FMT ",size=%" PRIu64 ",nr_inodes=%" PRIu64 "%s",
+                         uid, gid, runtime_dir_size, runtime_dir_inodes,
                          mac_smack_use() ? ",smackfsroot=*" : "");
 
                 (void) mkdir_label(runtime_path, 0700);
@@ -127,7 +133,7 @@ static int user_remove_runtime_path(const char *runtime_path) {
 
 static int do_mount(const char *user) {
         char runtime_path[sizeof("/run/user") + DECIMAL_STR_MAX(uid_t)];
-        uint64_t runtime_dir_size;
+        uint64_t runtime_dir_size, runtime_dir_inodes;
         uid_t uid;
         gid_t gid;
         int r;
@@ -140,14 +146,14 @@ static int do_mount(const char *user) {
                                                     : "Failed to look up user \"%s\": %m",
                                        user);
 
-        r = acquire_runtime_dir_size(&runtime_dir_size);
+        r = acquire_runtime_dir_properties(&runtime_dir_size, &runtime_dir_inodes);
         if (r < 0)
                 return r;
 
         xsprintf(runtime_path, "/run/user/" UID_FMT, uid);
 
         log_debug("Will mount %s owned by "UID_FMT":"GID_FMT, runtime_path, uid, gid);
-        return user_mkdir_runtime_path(runtime_path, uid, gid, runtime_dir_size);
+        return user_mkdir_runtime_path(runtime_path, uid, gid, runtime_dir_size, runtime_dir_inodes);
 }
 
 static int do_umount(const char *user) {
index 6fa96e1d588457c9787344058c1dcc0f7531ba26..048bd34e9e2b05894508ad1cd6ffbfc8c6b100a1 100644 (file)
@@ -865,6 +865,7 @@ RestrictNamespaces=
 RestrictRealtime=
 RestrictSUIDSGID=
 RuntimeDirectory=
+RuntimeDirectoryInodesMax=
 RuntimeDirectoryMode=
 RuntimeDirectoryPreserve=
 RuntimeDirectorySize=