]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
4321. [bug] Zones using mapped files containing out-of-zone data
authorMark Andrews <marka@isc.org>
Wed, 24 Feb 2016 00:13:24 +0000 (11:13 +1100)
committerMark Andrews <marka@isc.org>
Wed, 24 Feb 2016 00:13:24 +0000 (11:13 +1100)
                        could return SERVFAIL instead of the expected NODATA
                        or NXDOMAIN results. [RT #41596]

CHANGES
bin/tests/system/xfer/clean.sh
bin/tests/system/xfer/knowngood.mapped [new file with mode: 0644]
bin/tests/system/xfer/ns2/mapped.db.in [new file with mode: 0644]
bin/tests/system/xfer/ns2/named.conf
bin/tests/system/xfer/ns3/named.conf
bin/tests/system/xfer/setup.sh
bin/tests/system/xfer/tests.sh
lib/dns/rbtdb.c

diff --git a/CHANGES b/CHANGES
index 325b5fd45d2c2930468edf5cf9dfac4363423af4..e26cad63c29b983b3a70972e4a63ee1b61d4fdc3 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,7 @@
+4321.  [bug]           Zones using mapped files containing out-of-zone data
+                       could return SERVFAIL instead of the expected NODATA
+                       or NXDOMAIN results. [RT #41596]
+
 4320.  [bug]           Insufficient memory allocation when handling
                        "none" ACL could cause an assertion failure in
                        named when parsing ACL configuration. [RT #41745]
index 41d5284015fe2c725ccbef68be310f704d687617..807b8fe405f8b6ba8943abe414533ef68a3abc2b 100644 (file)
@@ -40,3 +40,6 @@ rm -f */named.memstats
 rm -f */named.run
 rm -f */ans.run
 rm -f ns*/named.lock
+rm -f ns2/mapped.db
+rm -f ns3/mapped.bk
+rm -f dig.out.?.*
diff --git a/bin/tests/system/xfer/knowngood.mapped b/bin/tests/system/xfer/knowngood.mapped
new file mode 100644 (file)
index 0000000..5fcd00b
--- /dev/null
@@ -0,0 +1,26 @@
+
+; <<>> DiG 9.10.2-P3 <<>> -p 5300 axfr mapped @10.53.0.3
+;; global options: +cmd
+mapped.                        3600    IN      SOA     . . 0 0 0 2147483647 0
+example.aa.            3600    IN      A       1.2.3.4
+example1.aa.           3600    IN      A       1.2.3.4
+example.bb.            3600    IN      A       1.2.3.4
+example1.bb.           3600    IN      A       1.2.3.4
+example.com.           3600    IN      A       1.2.3.4
+example1.com.          3600    IN      A       1.2.3.4
+bar.dd.                        3600    IN      A       1.2.3.4
+foo.ee.                        3600    IN      A       1.2.3.4
+foo.ff.                        3600    IN      A       1.2.3.4
+foo.gg.                        3600    IN      A       1.2.3.4
+foo.hh.                        3600    IN      A       1.2.3.4
+foo.ii.                        3600    IN      A       1.2.3.4
+foo.jj.                        3600    IN      A       1.2.3.4
+foo.kk.                        3600    IN      A       1.2.3.4
+foo.ll.                        3600    IN      A       1.2.3.4
+mapped.                        3600    IN      NS      .
+mapped.                        3600    IN      SOA     . . 0 0 0 2147483647 0
+;; Query time: 4 msec
+;; SERVER: 10.53.0.3#5300(10.53.0.3)
+;; WHEN: Tue Feb 16 14:38:25 EST 2016
+;; XFR size: 18 records (messages 1, bytes 468)
+
diff --git a/bin/tests/system/xfer/ns2/mapped.db.in b/bin/tests/system/xfer/ns2/mapped.db.in
new file mode 100644 (file)
index 0000000..66e4f1c
--- /dev/null
@@ -0,0 +1,17 @@
+mapped.                 3600    IN      SOA     . . 0 0 0 2147483647 0
+example.aa.             3600    IN      A       1.2.3.4
+example1.aa.            3600    IN      A       1.2.3.4
+example.bb.             3600    IN      A       1.2.3.4
+example1.bb.            3600    IN      A       1.2.3.4
+example.com.            3600    IN      A       1.2.3.4
+example1.com.           3600    IN      A       1.2.3.4
+bar.dd.                 3600    IN      A       1.2.3.4
+foo.ee.                 3600    IN      A       1.2.3.4
+foo.ff.                 3600    IN      A       1.2.3.4
+foo.gg.                 3600    IN      A       1.2.3.4
+foo.hh.                 3600    IN      A       1.2.3.4
+foo.ii.                 3600    IN      A       1.2.3.4
+foo.jj.                 3600    IN      A       1.2.3.4
+foo.kk.                 3600    IN      A       1.2.3.4
+foo.ll.                 3600    IN      A       1.2.3.4
+mapped.                 3600    IN      NS      .
index 03b06c2c6c345d316f41feb3a221cfe395c5ad71..1ab566b30ccbf8b7f51e63cecc6ab51c1c3d30c7 100644 (file)
@@ -66,3 +66,10 @@ zone "slave" {
        masters { 10.53.0.1; };
        masterfile-format text;
 };
+
+zone "mapped" {
+       type slave;
+       file "mapped.db";
+       masterfile-format text;
+       masters { 10.53.0.100; };
+};
index 2671c9b0f61fc81e2d96dde97e4a00b0733b70aa..a8afbb5932c62f15701873e0de46b21973dd929f 100644 (file)
@@ -74,4 +74,9 @@ zone "tsigzone" {
        allow-transfer { key tsigzone.; };
 };
 
-
+zone "mapped" {
+       type slave;
+       masters { 10.53.0.2; };
+       masterfile-format map;
+       file "mapped.bk";
+};
index 0745f2f24d5db989f817065ad85029233290a21f..2e89bb4f3d43ffb7274fc09cc496ca34dab58219 100644 (file)
@@ -35,5 +35,7 @@ cp -f ns4/named.conf.base ns4/named.conf
 cp ns2/slave.db.in ns2/slave.db
 touch -t 200101010000 ns2/slave.db
 
+cp ns2/mapped.db.in ns2/mapped.db
+
 $PERL -e 'for ($i=0;$i<4096;$i++){ printf("name%u 259200 A 1.2.3.4\nname%u 259200 TXT \"Hello World %u\"\n", $i, $i, $i);}' > ns8/small.db
 $PERL -e 'printf("large IN TYPE45234 \\# 48000 "); for ($i=0;$i<16*3000;$i++) { printf("%02x", $i % 256); } printf("\n");' > ns8/large.db
index 1c1c040f1c15189e37ae5dbd9fbce7343b8b436f..7928d7d9badeb7aaf37b8cb40fc2de7a35e2c76c 100644 (file)
@@ -23,7 +23,9 @@ SYSTEMTESTTOP=..
 DIGOPTS="+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd"
 
 status=0
+n=0
 
+n=`expr $n + 1`
 echo "I:testing basic zone transfer functionality"
 $DIG $DIGOPTS example. \
        @10.53.0.2 axfr -p 5300 > dig.out.ns2 || status=1
@@ -49,6 +51,7 @@ $PERL ../digcomp.pl dig1.good dig.out.ns2 || status=1
 
 $PERL ../digcomp.pl dig1.good dig.out.ns3 || status=1
 
+n=`expr $n + 1`
 echo "I:testing TSIG signed zone transfers"
 $DIG $DIGOPTS tsigzone. \
        @10.53.0.2 axfr -y tsigzone.:1234abcd8765 -p 5300 \
@@ -124,6 +127,7 @@ grep "1397051952 ; serial" ns2/slave.db > /dev/null 2>&1 || tmp=1
 if test $tmp != 0 ; then echo "I:failed"; fi
 status=`expr $status + $tmp`
 
+n=`expr $n + 1`
 echo "I:testing ixfr-from-differences yes;"
 tmp=0
 for i in 0 1 2 3 4 5 6 7 8 9
@@ -146,6 +150,7 @@ test -f ns3/example.bk.jnl || tmp=1
 if test $tmp != 0 ; then echo "I:failed"; fi
 status=`expr $status + $tmp`
 
+n=`expr $n + 1`
 echo "I:testing ixfr-from-differences master; (master zone)"
 tmp=0
 
@@ -166,6 +171,7 @@ test -f ns3/master.bk.jnl || tmp=1
 if test $tmp != 0 ; then echo "I:failed"; fi
 status=`expr $status + $tmp`
 
+n=`expr $n + 1`
 echo "I:testing ixfr-from-differences master; (slave zone)"
 tmp=0
 
@@ -186,6 +192,7 @@ test -f ns6/slave.bk.jnl && tmp=1
 if test $tmp != 0 ; then echo "I:failed"; fi
 status=`expr $status + $tmp`
 
+n=`expr $n + 1`
 echo "I:testing ixfr-from-differences slave; (master zone)"
 tmp=0
 
@@ -195,6 +202,8 @@ test -f ns7/master2.db.jnl && tmp=1
 
 if test $tmp != 0 ; then echo "I:failed"; fi
 status=`expr $status + $tmp`
+
+n=`expr $n + 1`
 echo "I:testing ixfr-from-differences slave; (slave zone)"
 tmp=0
 
@@ -368,7 +377,8 @@ $DIGCMD nil. TXT | grep 'incorrect key AXFR' >/dev/null && {
     status=1
 }
 
-echo "I:check that we ask for and get a EDNS EXPIRE response"
+n=`expr $n + 1`
+echo "I:check that we ask for and get a EDNS EXPIRE response ($n)"
 # force a refresh query
 $RNDC -s 10.53.0.7 -p 9953 -c ../common/rndc.conf refresh edns-expire 2>&1 | sed 's/^/I:ns7 /'
 sleep 10
@@ -380,7 +390,8 @@ test ${expire:-0} -gt 0 -a ${expire:-0} -lt 1814400 || {
     status=1
 }
 
-echo "I:test smaller transfer TCP message size"
+n=`expr $n + 1`
+echo "I:test smaller transfer TCP message size ($n)"
 $DIG $DIGOPTS example. @10.53.0.8 axfr -p 5300 \
        -y key1.:1234abcd8765 > dig.out.msgsize || status=1
 
@@ -396,5 +407,19 @@ if [ $num_messages -le 300 ]; then
        status=1
 fi
 
+n=`expr $n + 1`
+echo "I:test mapped zone with out of zone data ($n)"
+tmp=0
+$DIG -p 5300 txt mapped @10.53.0.3 > dig.out.1.$n
+grep "status: NOERROR," dig.out.1.$n > /dev/null || tmp=1
+$PERL $SYSTEMTESTTOP/stop.pl . ns3
+$PERL $SYSTEMTESTTOP/start.pl --noclean --restart . ns3
+$DIG -p 5300 txt mapped @10.53.0.3 > dig.out.2.$n
+grep "status: NOERROR," dig.out.2.$n > /dev/null || tmp=1
+$DIG -p 5300 axfr mapped @10.53.0.3 > dig.out.3.$n
+$PERL ../digcomp.pl knowngood.mapped dig.out.3.$n || tmp=1
+if test $tmp != 0 ; then echo "I:failed"; fi
+status=`expr $status + $tmp`
+
 echo "I:exit status: $status"
 exit $status
index c7168cb9f06e5b2c790af877ed8c42f4990a6961..7b10aa2d109650e7e2549e153e7aaebde776077d 100644 (file)
@@ -7282,8 +7282,9 @@ deserialize32(void *arg, FILE *f, off_t offset) {
        int fd;
        off_t filesize = 0;
        char *base;
-       dns_rbt_t *temporary_rbt = NULL;
+       dns_rbt_t *tree = NULL, *nsec = NULL, *nsec3 = NULL;
        int protect, flags;
+       dns_rbtnode_t *origin_node = NULL;
 
        REQUIRE(VALID_RBTDB(rbtdb));
 
@@ -7308,28 +7309,21 @@ deserialize32(void *arg, FILE *f, off_t offset) {
 
        header = (rbtdb_file_header_t *)(base + offset);
 
-       rbtdb->mmap_location = base;
-       rbtdb->mmap_size = (size_t) filesize;
-       rbtdb->origin_node = NULL;
-
        if (header->tree != 0) {
                result = dns_rbt_deserialize_tree(base, filesize,
                                                  (off_t) header->tree,
                                                  rbtdb->common.mctx,
                                                  delete_callback, rbtdb,
                                                  rbt_datafixer, rbtdb,
-                                                 &rbtdb->origin_node,
-                                                 &temporary_rbt);
-               if (temporary_rbt != NULL) {
-                       dns_rbt_destroy(&rbtdb->tree);
-                       rbtdb->tree = temporary_rbt;
-                       temporary_rbt = NULL;
-
-                       rbtdb->origin_node =
-                               (dns_rbtnode_t *)(header->tree + base + 1024);
-               }
+                                                 NULL, &tree);
                if (result != ISC_R_SUCCESS)
-                       return (result);
+                       goto cleanup;
+
+               result = dns_rbt_findnode(tree, &rbtdb->common.origin, NULL,
+                                         &origin_node, NULL,
+                                         DNS_RBTFIND_EMPTYDATA, NULL, NULL);
+               if (result != ISC_R_SUCCESS)
+                       goto cleanup;
        }
 
        if (header->nsec != 0) {
@@ -7338,14 +7332,9 @@ deserialize32(void *arg, FILE *f, off_t offset) {
                                                  rbtdb->common.mctx,
                                                  delete_callback, rbtdb,
                                                  rbt_datafixer, rbtdb,
-                                                 NULL, &temporary_rbt);
-               if (temporary_rbt != NULL) {
-                       dns_rbt_destroy(&rbtdb->nsec);
-                       rbtdb->nsec = temporary_rbt;
-                       temporary_rbt = NULL;
-               }
+                                                 NULL, &nsec);
                if (result != ISC_R_SUCCESS)
-                       return (result);
+                       goto cleanup;
        }
 
        if (header->nsec3 != 0) {
@@ -7354,17 +7343,46 @@ deserialize32(void *arg, FILE *f, off_t offset) {
                                                  rbtdb->common.mctx,
                                                  delete_callback, rbtdb,
                                                  rbt_datafixer, rbtdb,
-                                                 NULL, &temporary_rbt);
-               if (temporary_rbt != NULL) {
-                       dns_rbt_destroy(&rbtdb->nsec3);
-                       rbtdb->nsec3 = temporary_rbt;
-                       temporary_rbt = NULL;
-               }
+                                                 NULL, &nsec3);
                if (result != ISC_R_SUCCESS)
-                       return (result);
+                       goto cleanup;
+       }
+
+       /*
+        * We have a successfully loaded all the rbt trees now update
+        * rbtdb to use them.
+        */
+
+       rbtdb->mmap_location = base;
+       rbtdb->mmap_size = (size_t) filesize;
+
+       if (tree != NULL) {
+               dns_rbt_destroy(&rbtdb->tree);
+               rbtdb->tree = tree;
+               rbtdb->origin_node = origin_node;
+       }
+
+       if (nsec != NULL) {
+               dns_rbt_destroy(&rbtdb->nsec);
+               rbtdb->nsec = nsec;
+       }
+
+       if (nsec3 != NULL) {
+               dns_rbt_destroy(&rbtdb->nsec3);
+               rbtdb->nsec3 = nsec3;
        }
 
        return (ISC_R_SUCCESS);
+
+ cleanup:
+       if (tree != NULL)
+               dns_rbt_destroy(&tree);
+       if (nsec != NULL)
+               dns_rbt_destroy(&nsec);
+       if (nsec3 != NULL)
+               dns_rbt_destroy(&nsec3);
+       isc_file_munmap(base, (size_t) filesize);
+       return (result);
 }
 
 static isc_result_t