From f0eb27c40207e71449f3a253c97f4e8b1cb691ef Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Wed, 24 Feb 2016 11:13:24 +1100 Subject: [PATCH] 4321. [bug] Zones using mapped files containing out-of-zone data could return SERVFAIL instead of the expected NODATA or NXDOMAIN results. [RT #41596] (cherry picked from commit f9da4a8e543cf895b6171773e75d343b2914a7e7) --- CHANGES | 4 ++ bin/tests/system/xfer/clean.sh | 3 + bin/tests/system/xfer/knowngood.mapped | 26 +++++++++ bin/tests/system/xfer/ns2/mapped.db.in | 17 ++++++ bin/tests/system/xfer/ns2/named.conf | 7 +++ bin/tests/system/xfer/ns3/named.conf | 7 ++- bin/tests/system/xfer/setup.sh | 2 + bin/tests/system/xfer/tests.sh | 23 ++++++++ lib/dns/rbtdb.c | 78 ++++++++++++++++---------- 9 files changed, 136 insertions(+), 31 deletions(-) create mode 100644 bin/tests/system/xfer/knowngood.mapped create mode 100644 bin/tests/system/xfer/ns2/mapped.db.in diff --git a/CHANGES b/CHANGES index 9a2f32863c..22b38d232f 100644 --- 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] diff --git a/bin/tests/system/xfer/clean.sh b/bin/tests/system/xfer/clean.sh index 48aa159137..8b96f29f4b 100644 --- a/bin/tests/system/xfer/clean.sh +++ b/bin/tests/system/xfer/clean.sh @@ -36,3 +36,6 @@ rm -f ns7/*.db ns7/*.bk ns7/*.jnl rm -f */named.memstats rm -f */named.run rm -f */ans.run +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 index 0000000000..5fcd00b511 --- /dev/null +++ b/bin/tests/system/xfer/knowngood.mapped @@ -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 index 0000000000..66e4f1ca2f --- /dev/null +++ b/bin/tests/system/xfer/ns2/mapped.db.in @@ -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 . diff --git a/bin/tests/system/xfer/ns2/named.conf b/bin/tests/system/xfer/ns2/named.conf index 03b06c2c6c..1ab566b30c 100644 --- a/bin/tests/system/xfer/ns2/named.conf +++ b/bin/tests/system/xfer/ns2/named.conf @@ -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; }; +}; diff --git a/bin/tests/system/xfer/ns3/named.conf b/bin/tests/system/xfer/ns3/named.conf index 2671c9b0f6..a8afbb5932 100644 --- a/bin/tests/system/xfer/ns3/named.conf +++ b/bin/tests/system/xfer/ns3/named.conf @@ -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"; +}; diff --git a/bin/tests/system/xfer/setup.sh b/bin/tests/system/xfer/setup.sh index 56ca9018ec..6b13924aed 100644 --- a/bin/tests/system/xfer/setup.sh +++ b/bin/tests/system/xfer/setup.sh @@ -33,3 +33,5 @@ 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 diff --git a/bin/tests/system/xfer/tests.sh b/bin/tests/system/xfer/tests.sh index d65657cf74..52541e141f 100644 --- a/bin/tests/system/xfer/tests.sh +++ b/bin/tests/system/xfer/tests.sh @@ -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,5 +377,19 @@ $DIGCMD nil. TXT | grep 'incorrect key AXFR' >/dev/null && { status=1 } +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 diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index b8f334dbfb..e6281d2a28 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -7227,8 +7227,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)); @@ -7253,28 +7254,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) { @@ -7283,14 +7277,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) { @@ -7299,17 +7288,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