Prevent idnsVCClosed segfaults during shutdown or reconfiguration. idnsShutdown() schedules comm_close and then frees nameservers[] by calling idnsFreeNameservers. The closing handler tried to access freed nameservers[]. The patch prevents access to the freed nameservers[] array in idnsVCClosed and other functions. TODO: Nameservers[] array management should be rewritten. The array should not be freed while there are nameservers using it. It should be freed when the last entry is gone. === modified file 'src/dns_internal.cc' --- src/dns_internal.cc 2009-12-14 18:53:50 +0000 +++ src/dns_internal.cc 2010-01-08 17:46:12 +0000 @@ -699,13 +699,15 @@ } static void -idnsInitVCConnected(int fd, const DnsLookupDetails &, comm_err_t status, int xerrno, void *data) +idnsInitVCConnected(int fd, const DnsLookupDetails &details, comm_err_t status, int xerrno, void *data) { nsvc * vc = (nsvc *)data; if (status != COMM_OK) { - char buf[MAX_IPSTRLEN]; - debugs(78, 1, "idnsInitVCConnected: Failed to connect to nameserver " << nameservers[vc->ns].S.NtoA(buf,MAX_IPSTRLEN) << " using TCP!"); + char buf[MAX_IPSTRLEN] = ""; + if (vc->ns < nns) + nameservers[vc->ns].S.NtoA(buf,MAX_IPSTRLEN); + debugs(78, 1, HERE << "Failed to connect to nameserver " << buf << " using TCP: " << details); comm_close(fd); return; } @@ -721,7 +723,8 @@ nsvc * vc = (nsvc *)data; delete vc->queue; delete vc->msg; - nameservers[vc->ns].vc = NULL; + if (vc->ns < nns) // XXX: idnsShutdown may have freed nameservers[] + nameservers[vc->ns].vc = NULL; cbdataFree(vc); } @@ -731,6 +734,7 @@ char buf[MAX_IPSTRLEN]; nsvc *vc = cbdataAlloc(nsvc); + assert(ns < nns); nameservers[ns].vc = vc; vc->ns = ns; @@ -764,6 +768,7 @@ static void idnsSendQueryVC(idns_query * q, int ns) { + assert(ns < nns); if (nameservers[ns].vc == NULL) idnsInitVC(ns); @@ -1254,6 +1259,7 @@ return; } + assert(vc->ns < nns); debugs(78, 3, "idnsReadVC: FD " << fd << ": received " << (int) vc->msg->contentSize() << " bytes via tcp from " << nameservers[vc->ns].S << "."); @@ -1410,6 +1416,7 @@ } } + // XXX: vcs are not closed/freed yet and may try to access nameservers[] idnsFreeNameservers(); idnsFreeSearchpath();