]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Use minimal-sized caches for non-recursive views
authorMichał Kępień <michal@isc.org>
Tue, 22 Jun 2021 13:28:31 +0000 (15:28 +0200)
committerMichał Kępień <michal@isc.org>
Tue, 22 Jun 2021 13:28:31 +0000 (15:28 +0200)
Currently the implicit default for the "max-cache-size" option is "90%".
As this option is inherited by all configured views, using multiple
views can lead to memory exhaustion over time due to overcommitment.
The "max-cache-size 90%;" default also causes cache RBT hash tables to
be preallocated for every configured view, which does not really make
sense for views which do not allow recursion.

To limit this problem's potential for causing operational issues, use a
minimal-sized cache for views which do not allow recursion and do not
have "max-cache-size" explicitly set (either in global configuration or
in view configuration).

For configurations which include multiple views allowing recursion,
adjusting "max-cache-size" appropriately is still left to the operator.

bin/named/server.c

index ba0757348eb995d2451fb5c9943d72f14f2a0f49..b426c94be2d83bf41373ddd6e4f8a9cf6a2ca1b9 100644 (file)
@@ -3971,6 +3971,42 @@ register_one_plugin(const cfg_obj_t *config, const cfg_obj_t *obj,
        return (result);
 }
 
+/*
+ * Determine if a minimal-sized cache can be used for a given view, according
+ * to 'maps' (implicit defaults, global options, view options) and 'optionmaps'
+ * (global options, view options).  This is only allowed for views which have
+ * recursion disabled and do not have "max-cache-size" set explicitly.  Using
+ * minimal-sized caches prevents a situation in which all explicitly configured
+ * and built-in views inherit the default "max-cache-size 90%;" setting, which
+ * could lead to memory exhaustion with multiple views configured.
+ */
+static bool
+minimal_cache_allowed(const cfg_obj_t *maps[4],
+                     const cfg_obj_t *optionmaps[3]) {
+       const cfg_obj_t *obj;
+
+       /*
+        * Do not use a minimal-sized cache for a view with recursion enabled.
+        */
+       obj = NULL;
+       (void)named_config_get(maps, "recursion", &obj);
+       INSIST(obj != NULL);
+       if (cfg_obj_asboolean(obj)) {
+               return (false);
+       }
+
+       /*
+        * Do not use a minimal-sized cache if a specific size was requested.
+        */
+       obj = NULL;
+       (void)named_config_get(optionmaps, "max-cache-size", &obj);
+       if (obj != NULL) {
+               return (false);
+       }
+
+       return (true);
+}
+
 /*
  * Configure 'view' according to 'vconfig', taking defaults from
  * 'config' where values are missing in 'vconfig'.
@@ -4236,6 +4272,12 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
         */
        if (named_g_maxcachesize != 0) {
                max_cache_size = named_g_maxcachesize;
+       } else if (minimal_cache_allowed(maps, optionmaps)) {
+               /*
+                * dns_cache_setcachesize() will adjust this to the smallest
+                * allowed value.
+                */
+               max_cache_size = 1;
        } else if (cfg_obj_isstring(obj)) {
                str = cfg_obj_asstring(obj);
                INSIST(strcasecmp(str, "unlimited") == 0);