]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
2474. [bug] ACL structures could be allocated with insufficient
authorEvan Hunt <each@isc.org>
Fri, 24 Oct 2008 02:28:55 +0000 (02:28 +0000)
committerEvan Hunt <each@isc.org>
Fri, 24 Oct 2008 02:28:55 +0000 (02:28 +0000)
space, causing an array overrun. [RT #18765]

CHANGES
lib/isccfg/aclconf.c

diff --git a/CHANGES b/CHANGES
index 7ea770698516bcc6b28a9a491f27a7cadb399c89..099d3ca434fcf03d547aef002e4cbcfa8962c3cf 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+2474.  [bug]           ACL structures could be allocated with insufficient
+                       space, causing an array overrun. [RT #18765]
+
 2473.  [port]          linux: raise the limit on open files to the possible
                        maximum value before spawning threads; 'files'
                        specified in named.conf doesn't seem to work with
index ead4a70f9ac5f54adc23e1a8367274184188edcb..b0472bce742348a07c44ab1b2b50e6af781ad608 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: aclconf.c,v 1.21 2008/09/01 05:36:00 marka Exp $ */
+/* $Id: aclconf.c,v 1.22 2008/10/24 02:28:55 each Exp $ */
 
 #include <config.h>
 
@@ -160,6 +160,51 @@ convert_keyname(const cfg_obj_t *keyobj, isc_log_t *lctx, isc_mem_t *mctx,
        return (dns_name_dup(dns_fixedname_name(&fixname), mctx, dnsname));
 }
 
+/*
+ * Recursively pre-parse an ACL definition to find the total number
+ * of non-IP-prefix elements (localhost, localnets, key) in all nested
+ * ACLs, so that the parent will have enough space allocated for the
+ * elements table after all the nested ACLs have been merged in to the
+ * parent.
+ */
+static int
+count_acl_elements(const cfg_obj_t *caml, const cfg_obj_t *cctx)
+{
+       const cfg_listelt_t *elt;
+       const cfg_obj_t *cacl = NULL;
+       isc_result_t result;
+       int n = 0;
+
+       for (elt = cfg_list_first(caml);
+            elt != NULL;
+            elt = cfg_list_next(elt)) {
+               const cfg_obj_t *ce = cfg_listelt_value(elt);
+
+               /* negated element; just get the value. */
+               if (cfg_obj_istuple(ce))
+                       ce = cfg_tuple_get(ce, "value");
+
+               if (cfg_obj_istype(ce, &cfg_type_keyref)) {
+                       n++;
+               } else if (cfg_obj_islist(ce)) {
+                       n += count_acl_elements(ce, cctx);
+               } else if (cfg_obj_isstring(ce)) {
+                       const char *name = cfg_obj_asstring(ce);
+                       if (strcasecmp(name, "localhost") == 0 ||
+                           strcasecmp(name, "localnets") == 0) {
+                               n++;
+                       } else if (strcasecmp(name, "any") != 0 &&
+                                  strcasecmp(name, "none") != 0) {
+                               result = get_acl_def(cctx, name, &cacl);
+                               if (result == ISC_R_SUCCESS)
+                                       n += count_acl_elements(cacl, cctx) + 1;
+                       }
+               }
+       }
+
+       return n;
+}
+
 isc_result_t
 cfg_acl_fromconfig(const cfg_obj_t *caml,
                   const cfg_obj_t *cctx,
@@ -194,14 +239,18 @@ cfg_acl_fromconfig(const cfg_obj_t *caml,
        } else {
                /*
                 * Need to allocate a new ACL structure.  Count the items
-                * in the ACL definition and allocate space for that many
-                * elements (even though some or all of them may end up in
-                * the iptable instead of the element array).
+                * in the ACL definition that will require space in the
+                * elemnts table.  (Note that if nest_level is nonzero,
+                * *everything* goes in the elements table.)
                 */
-               isc_boolean_t recurse = ISC_TF(nest_level == 0);
-               result = dns_acl_create(mctx,
-                                       cfg_list_length(caml, recurse),
-                                       &dacl);
+               int nelem;
+
+               if (nest_level == 0)
+                       nelem = count_acl_elements(caml, cctx);
+               else
+                       nelem = cfg_list_length(caml, ISC_FALSE);
+
+               result = dns_acl_create(mctx, nelem, &dacl);
                if (result != ISC_R_SUCCESS)
                        return (result);
        }
@@ -209,8 +258,7 @@ cfg_acl_fromconfig(const cfg_obj_t *caml,
        de = dacl->elements;
        for (elt = cfg_list_first(caml);
             elt != NULL;
-            elt = cfg_list_next(elt))
-       {
+            elt = cfg_list_next(elt)) {
                const cfg_obj_t *ce = cfg_listelt_value(elt);
                isc_boolean_t   neg;