]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
[v9_10] address rpz bugs
authorEvan Hunt <each@isc.org>
Thu, 12 Jun 2014 03:01:21 +0000 (20:01 -0700)
committerEvan Hunt <each@isc.org>
Thu, 12 Jun 2014 03:01:21 +0000 (20:01 -0700)
3877. [bug] Inserting and deleting parent and child nodes
in response policy zones could trigger an assertion
failure. [RT #36272]

(cherry picked from commit 06e0d6bb126e9986f29036e671b59f48b1d2efbc)

CHANGES
bin/tests/system/rpz/clean.sh
bin/tests/system/rpz/ns5/empty.db.in [new file with mode: 0644]
bin/tests/system/rpz/ns5/named.conf
bin/tests/system/rpz/ns6/named.conf
bin/tests/system/rpz/setup.sh
bin/tests/system/rpz/tests.sh
lib/dns/rbtdb.c
lib/dns/rpz.c

diff --git a/CHANGES b/CHANGES
index 23eb12605a5702930dea5602d26323b5bdeef275..2b448a335577980ded4a340b212d709d7a1ce150 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,7 @@
+3877.  [bug]           Inserting and deleting parent and child nodes
+                       in response policy zones could trigger an assertion
+                       failure. [RT #36272]
+
 3874.  [test]          Check that only "check-names master" is needed for
                        updates to be accepted.
 
index 3a83ff2ff612ab2e2162f3039a249fb3f587406d..51f1d033ee46cf65e03fd250de58aa9bdaf764c1 100644 (file)
@@ -16,6 +16,7 @@
 
 rm -f proto.* dsset-* trusted.conf dig.out* nsupdate.tmp ns*/*tmp
 rm -f ns*/*.key ns*/*.private ns2/tld2s.db ns2/bl.tld2.db
-rm -f ns3/bl*.db ns*/*switch ns5/requests ns5/example.db ns5/bl.db ns5/*.perf
+rm -f ns3/bl*.db ns*/*switch ns*/empty.db ns*/empty.db.jnl
+rm -f ns5/requests ns5/example.db ns5/bl.db ns5/*.perf
 rm -f */named.memstats */named.run */named.stats */session.key
 rm -f */*.jnl */*.core */*.pid
diff --git a/bin/tests/system/rpz/ns5/empty.db.in b/bin/tests/system/rpz/ns5/empty.db.in
new file mode 100644 (file)
index 0000000..0d58df8
--- /dev/null
@@ -0,0 +1,24 @@
+; Copyright (C) 2014  Internet Systems Consortium, Inc. ("ISC")
+;
+; Permission to use, copy, modify, and/or distribute this software for any
+; purpose with or without fee is hereby granted, provided that the above
+; copyright notice and this permission notice appear in all copies.
+;
+; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+; AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+; PERFORMANCE OF THIS SOFTWARE.
+
+$TTL   120
+@      SOA     .  hostmaster.ns.example.tld5. ( 1 3600 1200 604800 60 )
+       NS      ns
+       NS      ns1
+       NS      ns2
+       NS      ns3
+ns     A       10.53.0.5
+ns1    A       10.53.0.5
+ns2    A       10.53.0.6
+ns3    A       10.53.0.6
index 448084d763b12368dfd1ac48b9bcadd7acc9d9eb..5735a1e5122e19cc330a1bce57972618f3001492 100644 (file)
@@ -32,7 +32,9 @@ options {
        session-keyfile "session.key";
        listen-on { 10.53.0.5; };
        listen-on-v6 { none; };
-       notify no;
+       ixfr-from-differences yes;
+       notify-delay 1;
+       notify yes;
 
        # turn rpz on or off
        include "rpz-switch";
@@ -73,3 +75,11 @@ zone "bl16."         {type master; file "bl.db"; };
 zone "bl17."           {type master; file "bl.db"; };
 zone "bl18."           {type master; file "bl.db"; };
 zone "bl19."           {type master; file "bl.db"; };
+
+zone "policy1" {
+       type master;
+       file "empty.db";
+       also-notify { 10.53.0.6; };
+       allow-update { any; };
+       allow-transfer { any; };
+};
index 5c9530b82dabe97a43751e9413d893d0c0adce45..4d396b5a55c7a5c2387e56fbde81cef98206008f 100644 (file)
@@ -24,9 +24,10 @@ options {
        session-keyfile "session.key";
        listen-on { 10.53.0.6; };
        listen-on-v6 { none; };
-       notify no;
        forward only;
        forwarders { 10.53.0.3; };
+
+        response-policy { zone "policy1"; };
 };
 
 key rndc_key {
@@ -39,3 +40,10 @@ controls {
 };
 
 include "../trusted.conf";
+
+zone "policy1" {
+       type slave;
+       masters { 10.53.0.5; };
+       file "empty.db";
+       allow-transfer  { any; };
+};
index 6db6fb2dfae06561d37d0f907a12b672e9376ab0..e44351626c866026baf7aa5fb370055ef240b98a 100644 (file)
@@ -115,3 +115,4 @@ $PERL -e 'for ($cnt = $val = 1; $cnt <= 3000; ++$cnt) {
        }' >ns5/requests
 
 cp ns2/bl.tld2.db.in ns2/bl.tld2.db
+cp ns5/empty.db.in ns5/empty.db
index 85451ce331f0f8ce54c0dd0ab42084c43b126d98..596f3eae09abc97cbccad74402ecc607466683ee 100644 (file)
@@ -606,5 +606,28 @@ $DIG +noall +answer -p 5300 @$ns3 any a3-2.tld2 > dig.out.any
 ttl=`awk '/a3-2 tld2 text/ {print $2}' dig.out.any`
 if test ${ttl:=0} -eq 0; then setret I:failed; fi
 
+echo "I:checking rpz updates/transfers with parent nodes added after children"
+# regression test for RT #36272: the success condition
+# is the slave server not crashing.
+nsd() {
+    nsupdate -p 5300 << EOF
+server $1
+ttl 300
+update $2 $3 IN CNAME .
+update $2 $4 IN CNAME .
+send
+EOF
+    sleep 2
+}
+
+for i in 1 2 3 4 5; do
+    nsd $ns5 add example.com.policy1. '*.example.com.policy1.'
+    nsd $ns5 delete example.com.policy1. '*.example.com.policy1.'
+done
+for i in 1 2 3 4 5; do
+    nsd $ns5 add '*.example.com.policy1.' example.com.policy1.
+    nsd $ns5 delete '*.example.com.policy1.' example.com.policy1.
+done
+
 echo "I:exit status: $status"
 exit $status
index b905bad90acfba317694c2c1fc0cc73695f63d26..36fd348cd6aa6f2b2073155c98e15ec4d8b17464 100644 (file)
@@ -2719,20 +2719,6 @@ findnodeintree(dns_rbtdb_t *rbtdb, dns_rbt_t *tree, dns_name_t *name,
                node = NULL;
                result = dns_rbt_addnode(tree, name, &node);
                if (result == ISC_R_SUCCESS) {
-                       if (rbtdb->rpzs != NULL && tree == rbtdb->tree) {
-                               dns_fixedname_t fnamef;
-                               dns_name_t *fname;
-
-                               dns_fixedname_init(&fnamef);
-                               fname = dns_fixedname_name(&fnamef);
-                               dns_rbt_fullnamefromnode(node, fname);
-                               result = dns_rpz_add(rbtdb->rpzs,
-                                                    rbtdb->rpz_num, fname);
-                               if (result != ISC_R_SUCCESS) {
-                                       RWUNLOCK(&rbtdb->tree_lock, locktype);
-                                       return (result);
-                               }
-                       }
                        dns_rbt_namefromnode(node, &nodename);
 #ifdef DNS_RBT_USEHASH
                        node->locknum = node->hashval % rbtdb->node_lock_count;
@@ -2763,6 +2749,33 @@ findnodeintree(dns_rbtdb_t *rbtdb, dns_rbt_t *tree, dns_name_t *name,
                INSIST(node->nsec == DNS_RBT_NSEC_NSEC3);
 
        reactivate_node(rbtdb, node, locktype);
+
+       /*
+        * Always try to add the policy zone data, because this node might
+        * already have been implicitly created by the previous addition of
+        * a longer domain.  A common example is adding *.example.com
+        * (implicitly creating example.com) followed by explicitly adding
+        * example.com.
+        */
+       if (create && rbtdb->rpzs != NULL && tree == rbtdb->tree) {
+               dns_fixedname_t fnamef;
+               dns_name_t *fname;
+
+               dns_fixedname_init(&fnamef);
+               fname = dns_fixedname_name(&fnamef);
+               dns_rbt_fullnamefromnode(node, fname);
+               result = dns_rpz_add(rbtdb->rpzs, rbtdb->rpz_num, fname);
+               if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
+                       /*
+                        * It is too late to give up, so merely complain.
+                        */
+                       isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
+                                     DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
+                                     "dns_rpz_add(): %s",
+                                     isc_result_totext(result));
+               }
+       }
+
        RWUNLOCK(&rbtdb->tree_lock, locktype);
 
        *nodep = (dns_dbnode_t *)node;
index 5f4078e277de31e433bf27770636a3b6f31bf9eb..5c997721d4015c8ea8699982f283cafb068a88ac 100644 (file)
@@ -1111,6 +1111,13 @@ add_cidr(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num,
        if (result != ISC_R_SUCCESS) {
                char namebuf[DNS_NAME_FORMATSIZE];
 
+               /*
+                * Do not worry if the radix tree already exists,
+                * because diff_apply() likes to add nodes before deleting.
+                */
+               if (result == ISC_R_EXISTS)
+                       return (ISC_R_SUCCESS);
+
                /*
                 * bin/tests/system/rpz/tests.sh looks for "rpz.*failed".
                 */
@@ -1159,18 +1166,8 @@ add_nm(dns_rpz_zones_t *rpzs, dns_name_t *trig_name,
        if ((nm_data->set.qname & new_data->set.qname) != 0 ||
            (nm_data->set.ns & new_data->set.ns) != 0 ||
            (nm_data->wild.qname & new_data->wild.qname) != 0 ||
-           (nm_data->wild.ns & new_data->wild.ns) != 0) {
-               char namebuf[DNS_NAME_FORMATSIZE];
-
-               /*
-                * bin/tests/system/rpz/tests.sh looks for "rpz.*failed".
-                */
-               dns_name_format(trig_name, namebuf, sizeof(namebuf));
-               isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
-                             DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
-                             "rpz add_nm(%s): bits already set", namebuf);
+           (nm_data->wild.ns & new_data->wild.ns) != 0)
                return (ISC_R_EXISTS);
-       }
 
        nm_data->set.qname |= new_data->set.qname;
        nm_data->set.ns |= new_data->set.ns;
@@ -1188,11 +1185,26 @@ add_name(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num,
        dns_name_t *trig_name;
        isc_result_t result;
 
+       /*
+        * No need for a summary database of names with only 1 policy zone.
+        */
+       if (rpzs->p.num_zones <= 1) {
+               adj_trigger_cnt(rpzs, rpz_num, rpz_type, NULL, 0, ISC_TRUE);
+               return (ISC_R_SUCCESS);
+       }
+
        dns_fixedname_init(&trig_namef);
        trig_name = dns_fixedname_name(&trig_namef);
        name2data(rpzs, rpz_num, rpz_type, src_name, trig_name, &new_data);
 
        result = add_nm(rpzs, trig_name, &new_data);
+
+       /*
+        * Do not worry if the node already exists,
+        * because diff_apply() likes to add nodes before deleting.
+        */
+       if (result == ISC_R_EXISTS)
+               return (ISC_R_SUCCESS);
        if (result == ISC_R_SUCCESS)
                adj_trigger_cnt(rpzs, rpz_num, rpz_type, NULL, 0, ISC_TRUE);
        return (result);
@@ -1793,10 +1805,6 @@ del_name(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num,
        dns_rpz_nm_data_t *nm_data, del_data;
        isc_result_t result;
 
-       dns_fixedname_init(&trig_namef);
-       trig_name = dns_fixedname_name(&trig_namef);
-       name2data(rpzs, rpz_num, rpz_type, src_name, trig_name, &del_data);
-
        /*
         * No need for a summary database of names with only 1 policy zone.
         */
@@ -1805,6 +1813,10 @@ del_name(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num,
                return;
        }
 
+       dns_fixedname_init(&trig_namef);
+       trig_name = dns_fixedname_name(&trig_namef);
+       name2data(rpzs, rpz_num, rpz_type, src_name, trig_name, &del_data);
+
        nmnode = NULL;
        result = dns_rbt_findnode(rpzs->rbt, trig_name, NULL, &nmnode, NULL, 0,
                                  NULL, NULL);
@@ -1815,7 +1827,8 @@ del_name(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num,
                 * that were later added for (often empty) wildcards
                 * and then to the RBTDB deferred cleanup list.
                 */
-               if (result == ISC_R_NOTFOUND)
+               if (result == ISC_R_NOTFOUND ||
+                   result == DNS_R_PARTIALMATCH)
                        return;
                dns_name_format(src_name, namebuf, sizeof(namebuf));
                isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,