2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-29 13:38:26 +00:00

4651. [bug] Nsupdate could attempt to use a zeroed address on

server timeout. [RT #45417]

(cherry picked from commit dac36869f3ec3a097eddc393a050c804f72ce5b7)
This commit is contained in:
Mark Andrews 2017-07-19 15:35:41 +10:00
parent 6375d42bae
commit cda91a09e4
2 changed files with 48 additions and 20 deletions

View File

@ -165,7 +165,9 @@ static isc_boolean_t default_servers = ISC_TRUE;
static int ns_inuse = 0; static int ns_inuse = 0;
static int master_inuse = 0; static int master_inuse = 0;
static int ns_total = 0; static int ns_total = 0;
static int ns_alloc = 0;
static int master_total = 0; static int master_total = 0;
static int master_alloc = 0;
static isc_sockaddr_t *localaddr4 = NULL; static isc_sockaddr_t *localaddr4 = NULL;
static isc_sockaddr_t *localaddr6 = NULL; static isc_sockaddr_t *localaddr6 = NULL;
static const char *keyfile = NULL; static const char *keyfile = NULL;
@ -306,9 +308,10 @@ master_from_servers(void) {
if (master_servers != NULL && master_servers != servers) if (master_servers != NULL && master_servers != servers)
isc_mem_put(gmctx, master_servers, isc_mem_put(gmctx, master_servers,
master_total * sizeof(isc_sockaddr_t)); master_alloc * sizeof(isc_sockaddr_t));
master_servers = servers; master_servers = servers;
master_total = ns_total; master_total = ns_total;
master_alloc = ns_alloc;
master_inuse = ns_inuse; master_inuse = ns_inuse;
} }
@ -750,10 +753,10 @@ doshutdown(void) {
*/ */
if (master_servers != NULL && master_servers != servers) if (master_servers != NULL && master_servers != servers)
isc_mem_put(gmctx, master_servers, isc_mem_put(gmctx, master_servers,
master_total * sizeof(isc_sockaddr_t)); master_alloc * sizeof(isc_sockaddr_t));
if (servers != NULL) if (servers != NULL)
isc_mem_put(gmctx, servers, ns_total * sizeof(isc_sockaddr_t)); isc_mem_put(gmctx, servers, ns_alloc * sizeof(isc_sockaddr_t));
if (localaddr4 != NULL) if (localaddr4 != NULL)
isc_mem_put(gmctx, localaddr4, sizeof(isc_sockaddr_t)); isc_mem_put(gmctx, localaddr4, sizeof(isc_sockaddr_t));
@ -868,7 +871,7 @@ setup_system(void) {
if (servers != NULL) { if (servers != NULL) {
if (master_servers == servers) if (master_servers == servers)
master_servers = NULL; master_servers = NULL;
isc_mem_put(gmctx, servers, ns_total * sizeof(isc_sockaddr_t)); isc_mem_put(gmctx, servers, ns_alloc * sizeof(isc_sockaddr_t));
} }
ns_inuse = 0; ns_inuse = 0;
@ -881,8 +884,8 @@ setup_system(void) {
default_servers = !local_only; default_servers = !local_only;
ns_total = (have_ipv4 ? 1 : 0) + (have_ipv6 ? 1 : 0); ns_total = ns_alloc = (have_ipv4 ? 1 : 0) + (have_ipv6 ? 1 : 0);
servers = isc_mem_get(gmctx, ns_total * sizeof(isc_sockaddr_t)); servers = isc_mem_get(gmctx, ns_alloc * sizeof(isc_sockaddr_t));
if (servers == NULL) if (servers == NULL)
fatal("out of memory"); fatal("out of memory");
@ -897,8 +900,8 @@ setup_system(void) {
&in6, dnsport); &in6, dnsport);
} }
} else { } else {
ns_total = lwconf->nsnext; ns_total = ns_alloc = lwconf->nsnext;
servers = isc_mem_get(gmctx, ns_total * sizeof(isc_sockaddr_t)); servers = isc_mem_get(gmctx, ns_alloc * sizeof(isc_sockaddr_t));
if (servers == NULL) if (servers == NULL)
fatal("out of memory"); fatal("out of memory");
for (i = 0; i < ns_total; i++) { for (i = 0; i < ns_total; i++) {
@ -990,7 +993,7 @@ setup_system(void) {
setup_keyfile(gmctx, glctx); setup_keyfile(gmctx, glctx);
} }
static void static int
get_addresses(char *host, in_port_t port, get_addresses(char *host, in_port_t port,
isc_sockaddr_t *sockaddr, int naddrs) isc_sockaddr_t *sockaddr, int naddrs)
{ {
@ -1003,6 +1006,7 @@ get_addresses(char *host, in_port_t port,
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
fatal("couldn't get address for '%s': %s", fatal("couldn't get address for '%s': %s",
host, isc_result_totext(result)); host, isc_result_totext(result));
return (count);
} }
static void static void
@ -1465,19 +1469,19 @@ evaluate_server(char *cmdline) {
if (servers != NULL) { if (servers != NULL) {
if (master_servers == servers) if (master_servers == servers)
master_servers = NULL; master_servers = NULL;
isc_mem_put(gmctx, servers, ns_total * sizeof(isc_sockaddr_t)); isc_mem_put(gmctx, servers, ns_alloc * sizeof(isc_sockaddr_t));
} }
default_servers = ISC_FALSE; default_servers = ISC_FALSE;
ns_total = MAX_SERVERADDRS; ns_alloc = MAX_SERVERADDRS;
ns_inuse = 0; ns_inuse = 0;
servers = isc_mem_get(gmctx, ns_total * sizeof(isc_sockaddr_t)); servers = isc_mem_get(gmctx, ns_alloc * sizeof(isc_sockaddr_t));
if (servers == NULL) if (servers == NULL)
fatal("out of memory"); fatal("out of memory");
memset(servers, 0, ns_total * sizeof(isc_sockaddr_t)); memset(servers, 0, ns_alloc * sizeof(isc_sockaddr_t));
get_addresses(server, (in_port_t)port, servers, ns_total); ns_total = get_addresses(server, (in_port_t)port, servers, ns_alloc);
return (STATUS_MORE); return (STATUS_MORE);
} }
@ -2508,7 +2512,7 @@ recvsoa(isc_task_t *task, isc_event_t *event) {
FIND_TIMEOUT, 3, FIND_TIMEOUT, 3,
global_task, recvsoa, reqinfo, global_task, recvsoa, reqinfo,
&request); &request);
check_result(result, "dns_request_createvia"); check_result(result, "dns_request_createvia3");
requests++; requests++;
return; return;
} }
@ -2622,15 +2626,16 @@ recvsoa(isc_task_t *task, isc_event_t *event) {
if (master_servers != NULL && master_servers != servers) if (master_servers != NULL && master_servers != servers)
isc_mem_put(gmctx, master_servers, isc_mem_put(gmctx, master_servers,
master_total * sizeof(isc_sockaddr_t)); master_alloc * sizeof(isc_sockaddr_t));
master_total = MAX_SERVERADDRS; master_alloc = MAX_SERVERADDRS;
size = master_total * sizeof(isc_sockaddr_t); size = master_alloc * sizeof(isc_sockaddr_t);
master_servers = isc_mem_get(gmctx, size); master_servers = isc_mem_get(gmctx, size);
if (master_servers == NULL) if (master_servers == NULL)
fatal("out of memory"); fatal("out of memory");
memset(master_servers, 0, size); memset(master_servers, 0, size);
get_addresses(serverstr, dnsport, master_servers, master_total); master_total = get_addresses(serverstr, dnsport,
master_servers, master_alloc);
master_inuse = 0; master_inuse = 0;
} else } else
master_from_servers(); master_from_servers();
@ -2701,7 +2706,7 @@ sendrequest(isc_sockaddr_t *destaddr, dns_message_t *msg,
default_servers ? NULL : tsigkey, default_servers ? NULL : tsigkey,
FIND_TIMEOUT * 20, FIND_TIMEOUT, 3, FIND_TIMEOUT * 20, FIND_TIMEOUT, 3,
global_task, recvsoa, reqinfo, request); global_task, recvsoa, reqinfo, request);
check_result(result, "dns_request_createvia"); check_result(result, "dns_request_createvia3");
requests++; requests++;
} }

View File

@ -196,6 +196,7 @@ grep "status: NOERROR" dig.out.ns1.$n > /dev/null || ret=1
[ $ret = 0 ] || { echo I:failed; status=1; } [ $ret = 0 ] || { echo I:failed; status=1; }
n=`expr $n + 1` n=`expr $n + 1`
ret=0
echo "I:check that TYPE=0 additional data is handled ($n)" echo "I:check that TYPE=0 additional data is handled ($n)"
echo "a0e4280000010000000000010000060001c00c000000fe000000000000" | echo "a0e4280000010000000000010000060001c00c000000fe000000000000" |
$PERL ../packet.pl -a 10.53.0.1 -p 5300 -t tcp > /dev/null $PERL ../packet.pl -a 10.53.0.1 -p 5300 -t tcp > /dev/null
@ -204,6 +205,7 @@ grep "status: NOERROR" dig.out.ns1.$n > /dev/null || ret=1
[ $ret = 0 ] || { echo I:failed; status=1; } [ $ret = 0 ] || { echo I:failed; status=1; }
n=`expr $n + 1` n=`expr $n + 1`
ret=0
echo "I:check that update to undefined class is handled ($n)" echo "I:check that update to undefined class is handled ($n)"
echo "a0e4280000010001000000000000060101c00c000000fe000000000000" | echo "a0e4280000010001000000000000060101c00c000000fe000000000000" |
$PERL ../packet.pl -a 10.53.0.1 -p 5300 -t tcp > /dev/null $PERL ../packet.pl -a 10.53.0.1 -p 5300 -t tcp > /dev/null
@ -212,6 +214,7 @@ grep "status: NOERROR" dig.out.ns1.$n > /dev/null || ret=1
[ $ret = 0 ] || { echo I:failed; status=1; } [ $ret = 0 ] || { echo I:failed; status=1; }
n=`expr $n + 1` n=`expr $n + 1`
ret=0
echo "I:check that address family mismatch is handled ($n)" echo "I:check that address family mismatch is handled ($n)"
$NSUPDATE <<END > /dev/null 2>&1 && ret=1 $NSUPDATE <<END > /dev/null 2>&1 && ret=1
server ::1 server ::1
@ -223,6 +226,7 @@ END
n=`expr $n + 1` n=`expr $n + 1`
ret=0
echo "I:check that unixtime serial number is correctly generated ($n)" echo "I:check that unixtime serial number is correctly generated ($n)"
oldserial=`$DIG +short unixtime.nil. soa @10.53.0.1 -p 5300 | awk '{print $3}'` || ret=1 oldserial=`$DIG +short unixtime.nil. soa @10.53.0.1 -p 5300 | awk '{print $3}'` || ret=1
$NSUPDATE <<END > /dev/null 2>&1 || ret=1 $NSUPDATE <<END > /dev/null 2>&1 || ret=1
@ -254,6 +258,7 @@ $DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil.\
@10.53.0.1 axfr -p 5300 > dig.out.ns1 || ret=1 @10.53.0.1 axfr -p 5300 > dig.out.ns1 || ret=1
[ $ret = 0 ] || { echo I:failed; status=1; } [ $ret = 0 ] || { echo I:failed; status=1; }
ret=0
echo "I:fetching second copy of test zone" echo "I:fetching second copy of test zone"
$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil.\ $DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil.\
@10.53.0.2 axfr -p 5300 > dig.out.ns2 || ret=1 @10.53.0.2 axfr -p 5300 > dig.out.ns2 || ret=1
@ -432,6 +437,7 @@ if [ $ret != 0 ] ; then echo "I: failed"; status=`expr $ret + $status`; fi
ret=0
echo "I:testing that rndc stop updates the master file" echo "I:testing that rndc stop updates the master file"
$NSUPDATE -k ns1/ddns.key <<END > /dev/null || ret=1 $NSUPDATE -k ns1/ddns.key <<END > /dev/null || ret=1
server 10.53.0.1 5300 server 10.53.0.1 5300
@ -740,10 +746,24 @@ grep "status: NXDOMAIN" dig.out.ns3.test$n > /dev/null || ret=1
grep "records in zone (4) exceeds max-records (3)" ns3/named.run > /dev/null || ret=1 grep "records in zone (4) exceeds max-records (3)" ns3/named.run > /dev/null || ret=1
[ $ret = 0 ] || { echo I:failed; status=1; } [ $ret = 0 ] || { echo I:failed; status=1; }
n=`expr $n + 1`
ret=0
echo "I:check whether valid addresses are used for master failover ($n)"
$NSUPDATE -t 1 <<END > nsupdate.out-$n 2>&1 && ret=1
server 10.53.0.4 5300
zone unreachable.
update add unreachable. 600 A 192.0.2.1
send
END
grep "; Communication with 10.53.0.4#5300 failed: timed out" nsupdate.out-$n > /dev/null 2>&1 || ret=1
grep "not implemented" nsupdate.out-$n > /dev/null 2>&1 && ret=1
[ $ret = 0 ] || { echo I:failed; status=1; }
# #
# Add client library tests here # Add client library tests here
# #
n=`expr $n + 1` n=`expr $n + 1`
ret=0
echo "I:check that dns_client_update handles prerequisite NXDOMAIN failure ($n)" echo "I:check that dns_client_update handles prerequisite NXDOMAIN failure ($n)"
$SAMPLEUPDATE -P 5300 -a 10.53.0.1 -a 10.53.0.2 -p "nxdomain exists.sample" \ $SAMPLEUPDATE -P 5300 -a 10.53.0.1 -a 10.53.0.2 -p "nxdomain exists.sample" \
add "nxdomain-exists.sample 0 in a 1.2.3.4" > update.out.test$n 2>&1 add "nxdomain-exists.sample 0 in a 1.2.3.4" > update.out.test$n 2>&1
@ -760,6 +780,7 @@ grep "status: NOERROR" check.out.ns2.test$n > /dev/null || ret=1
[ $ret = 0 ] || { echo I:failed; status=1; } [ $ret = 0 ] || { echo I:failed; status=1; }
n=`expr $n + 1` n=`expr $n + 1`
ret=0
echo "I:check that dns_client_update handles prerequisite YXDOMAIN failure ($n)" echo "I:check that dns_client_update handles prerequisite YXDOMAIN failure ($n)"
$SAMPLEUPDATE -P 5300 -a 10.53.0.1 -a 10.53.0.2 -p "yxdomain nxdomain.sample" \ $SAMPLEUPDATE -P 5300 -a 10.53.0.1 -a 10.53.0.2 -p "yxdomain nxdomain.sample" \
add "yxdomain-nxdomain.sample 0 in a 1.2.3.4" > update.out.test$n 2>&1 add "yxdomain-nxdomain.sample 0 in a 1.2.3.4" > update.out.test$n 2>&1
@ -776,6 +797,7 @@ grep "status: NOERROR" check.out.ns2.test$n > /dev/null || ret=1
[ $ret = 0 ] || { echo I:failed; status=1; } [ $ret = 0 ] || { echo I:failed; status=1; }
n=`expr $n + 1` n=`expr $n + 1`
ret=0
echo "I:check that dns_client_update handles prerequisite NXRRSET failure ($n)" echo "I:check that dns_client_update handles prerequisite NXRRSET failure ($n)"
$SAMPLEUPDATE -P 5300 -a 10.53.0.1 -a 10.53.0.2 -p "nxrrset exists.sample TXT This RRset exists." \ $SAMPLEUPDATE -P 5300 -a 10.53.0.1 -a 10.53.0.2 -p "nxrrset exists.sample TXT This RRset exists." \
add "nxrrset-exists.sample 0 in a 1.2.3.4" > update.out.test$n 2>&1 add "nxrrset-exists.sample 0 in a 1.2.3.4" > update.out.test$n 2>&1
@ -792,6 +814,7 @@ grep "status: NOERROR" check.out.ns2.test$n > /dev/null || ret=1
[ $ret = 0 ] || { echo I:failed; status=1; } [ $ret = 0 ] || { echo I:failed; status=1; }
n=`expr $n + 1` n=`expr $n + 1`
ret=0
echo "I:check that dns_client_update handles prerequisite YXRRSET failure ($n)" echo "I:check that dns_client_update handles prerequisite YXRRSET failure ($n)"
$SAMPLEUPDATE -s -P 5300 -a 10.53.0.1 -a 10.53.0.2 \ $SAMPLEUPDATE -s -P 5300 -a 10.53.0.1 -a 10.53.0.2 \
-p "yxrrset no-txt.sample TXT" \ -p "yxrrset no-txt.sample TXT" \