mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-01 15:05:23 +00:00
Use the statslock for more xfrin members
The 'end_serial' and some other members of the 'dns_xfrin_t' structure can be accessed by the statistics channel, causing a data race with the zone transfer process. Use the existing 'statslock' mutex for protecting those members.
This commit is contained in:
committed by
Arаm Sаrgsyаn
parent
0d85492f6b
commit
5067b83116
@@ -92,7 +92,7 @@ dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
isc_time_t
|
isc_time_t
|
||||||
dns_xfrin_getstarttime(const dns_xfrin_t *xfr);
|
dns_xfrin_getstarttime(dns_xfrin_t *xfr);
|
||||||
/*%<
|
/*%<
|
||||||
* Get the start time of the xfrin object.
|
* Get the start time of the xfrin object.
|
||||||
*
|
*
|
||||||
@@ -120,7 +120,7 @@ dns_xfrin_getstate(const dns_xfrin_t *xfr, const char **statestr,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
dns_xfrin_getendserial(const dns_xfrin_t *xfr);
|
dns_xfrin_getendserial(dns_xfrin_t *xfr);
|
||||||
/*%<
|
/*%<
|
||||||
* Get the 'end_serial' of the xfrin object.
|
* Get the 'end_serial' of the xfrin object.
|
||||||
*
|
*
|
||||||
@@ -182,7 +182,7 @@ dns_xfrin_gettransporttype(const dns_xfrin_t *xfr);
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
dns_transport_type_t
|
dns_transport_type_t
|
||||||
dns_xfrin_getsoatransporttype(const dns_xfrin_t *xfr);
|
dns_xfrin_getsoatransporttype(dns_xfrin_t *xfr);
|
||||||
/*%<
|
/*%<
|
||||||
* Get the SOA request's trnasport type of the xfrin object.
|
* Get the SOA request's trnasport type of the xfrin object.
|
||||||
*
|
*
|
||||||
|
@@ -142,29 +142,28 @@ struct dns_xfrin {
|
|||||||
int difflen; /*%< Number of pending tuples */
|
int difflen; /*%< Number of pending tuples */
|
||||||
|
|
||||||
_Atomic xfrin_state_t state;
|
_Atomic xfrin_state_t state;
|
||||||
uint32_t end_serial;
|
|
||||||
uint32_t expireopt;
|
uint32_t expireopt;
|
||||||
bool edns, expireoptset;
|
bool edns, expireoptset;
|
||||||
atomic_bool is_ixfr;
|
atomic_bool is_ixfr;
|
||||||
|
|
||||||
isc_mutex_t statslock;
|
isc_mutex_t statslock;
|
||||||
/* Locked by statslock. */
|
/* Locked by statslock; can be accessed from the statistics channel. */
|
||||||
unsigned int nmsg; /*%< Number of messages recvd */
|
unsigned int nmsg; /*%< Number of messages recvd */
|
||||||
unsigned int nrecs; /*%< Number of records recvd */
|
unsigned int nrecs; /*%< Number of records recvd */
|
||||||
uint64_t nbytes; /*%< Number of bytes received */
|
uint64_t nbytes; /*%< Number of bytes received */
|
||||||
|
isc_time_t start; /*%< Start time of the transfer */
|
||||||
|
isc_time_t end; /*%< End time of the transfer */
|
||||||
|
dns_transport_type_t soa_transport_type;
|
||||||
|
uint32_t end_serial;
|
||||||
|
|
||||||
unsigned int maxrecords; /*%< The maximum number of
|
unsigned int maxrecords; /*%< The maximum number of
|
||||||
* records set for the zone */
|
* records set for the zone */
|
||||||
|
|
||||||
isc_time_t start; /*%< Start time of the transfer */
|
|
||||||
isc_time_t end; /*%< End time of the transfer */
|
|
||||||
|
|
||||||
dns_tsigkey_t *tsigkey; /*%< Key used to create TSIG */
|
dns_tsigkey_t *tsigkey; /*%< Key used to create TSIG */
|
||||||
isc_buffer_t *lasttsig; /*%< The last TSIG */
|
isc_buffer_t *lasttsig; /*%< The last TSIG */
|
||||||
dst_context_t *tsigctx; /*%< TSIG verification context */
|
dst_context_t *tsigctx; /*%< TSIG verification context */
|
||||||
unsigned int sincetsig; /*%< recvd since the last TSIG */
|
unsigned int sincetsig; /*%< recvd since the last TSIG */
|
||||||
|
|
||||||
dns_transport_type_t soa_transport_type;
|
|
||||||
dns_transport_t *transport;
|
dns_transport_t *transport;
|
||||||
|
|
||||||
dns_xfrindone_t done;
|
dns_xfrindone_t done;
|
||||||
@@ -534,7 +533,9 @@ redo:
|
|||||||
"non-SOA response to SOA query");
|
"non-SOA response to SOA query");
|
||||||
FAIL(DNS_R_FORMERR);
|
FAIL(DNS_R_FORMERR);
|
||||||
}
|
}
|
||||||
|
LOCK(&xfr->statslock);
|
||||||
xfr->end_serial = dns_soa_getserial(rdata);
|
xfr->end_serial = dns_soa_getserial(rdata);
|
||||||
|
UNLOCK(&xfr->statslock);
|
||||||
if (!DNS_SERIAL_GT(xfr->end_serial, xfr->ixfr.request_serial) &&
|
if (!DNS_SERIAL_GT(xfr->end_serial, xfr->ixfr.request_serial) &&
|
||||||
!dns_zone_isforced(xfr->zone))
|
!dns_zone_isforced(xfr->zone))
|
||||||
{
|
{
|
||||||
@@ -563,7 +564,9 @@ redo:
|
|||||||
* Remember the serial number in the initial SOA.
|
* Remember the serial number in the initial SOA.
|
||||||
* We need it to recognize the end of an IXFR.
|
* We need it to recognize the end of an IXFR.
|
||||||
*/
|
*/
|
||||||
|
LOCK(&xfr->statslock);
|
||||||
xfr->end_serial = dns_soa_getserial(rdata);
|
xfr->end_serial = dns_soa_getserial(rdata);
|
||||||
|
UNLOCK(&xfr->statslock);
|
||||||
if (xfr->reqtype == dns_rdatatype_ixfr &&
|
if (xfr->reqtype == dns_rdatatype_ixfr &&
|
||||||
!DNS_SERIAL_GT(xfr->end_serial, xfr->ixfr.request_serial) &&
|
!DNS_SERIAL_GT(xfr->end_serial, xfr->ixfr.request_serial) &&
|
||||||
!dns_zone_isforced(xfr->zone))
|
!dns_zone_isforced(xfr->zone))
|
||||||
@@ -772,10 +775,16 @@ xfrin_idledout(void *xfr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isc_time_t
|
isc_time_t
|
||||||
dns_xfrin_getstarttime(const dns_xfrin_t *xfr) {
|
dns_xfrin_getstarttime(dns_xfrin_t *xfr) {
|
||||||
|
isc_time_t start;
|
||||||
|
|
||||||
REQUIRE(VALID_XFRIN(xfr));
|
REQUIRE(VALID_XFRIN(xfr));
|
||||||
|
|
||||||
return (xfr->start);
|
LOCK(&xfr->statslock);
|
||||||
|
start = xfr->start;
|
||||||
|
UNLOCK(&xfr->statslock);
|
||||||
|
|
||||||
|
return (start);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -824,10 +833,16 @@ dns_xfrin_getstate(const dns_xfrin_t *xfr, const char **statestr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
dns_xfrin_getendserial(const dns_xfrin_t *xfr) {
|
dns_xfrin_getendserial(dns_xfrin_t *xfr) {
|
||||||
|
uint32_t end_serial;
|
||||||
|
|
||||||
REQUIRE(VALID_XFRIN(xfr));
|
REQUIRE(VALID_XFRIN(xfr));
|
||||||
|
|
||||||
return (xfr->end_serial);
|
LOCK(&xfr->statslock);
|
||||||
|
end_serial = xfr->end_serial;
|
||||||
|
UNLOCK(&xfr->statslock);
|
||||||
|
|
||||||
|
return (end_serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -869,10 +884,16 @@ dns_xfrin_gettransporttype(const dns_xfrin_t *xfr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dns_transport_type_t
|
dns_transport_type_t
|
||||||
dns_xfrin_getsoatransporttype(const dns_xfrin_t *xfr) {
|
dns_xfrin_getsoatransporttype(dns_xfrin_t *xfr) {
|
||||||
|
dns_transport_type_t soa_transport_type;
|
||||||
|
|
||||||
REQUIRE(VALID_XFRIN(xfr));
|
REQUIRE(VALID_XFRIN(xfr));
|
||||||
|
|
||||||
return (xfr->soa_transport_type);
|
LOCK(&xfr->statslock);
|
||||||
|
soa_transport_type = xfr->soa_transport_type;
|
||||||
|
UNLOCK(&xfr->statslock);
|
||||||
|
|
||||||
|
return (soa_transport_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
const dns_name_t *
|
const dns_name_t *
|
||||||
@@ -1112,7 +1133,9 @@ xfrin_start(dns_xfrin_t *xfr) {
|
|||||||
* The "SOA before" mode is used, where the SOA request is
|
* The "SOA before" mode is used, where the SOA request is
|
||||||
* using the same transport as the XFR.
|
* using the same transport as the XFR.
|
||||||
*/
|
*/
|
||||||
|
LOCK(&xfr->statslock);
|
||||||
xfr->soa_transport_type = dns_xfrin_gettransporttype(xfr);
|
xfr->soa_transport_type = dns_xfrin_gettransporttype(xfr);
|
||||||
|
UNLOCK(&xfr->statslock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the maximum timer */
|
/* Set the maximum timer */
|
||||||
@@ -1412,8 +1435,8 @@ xfrin_send_request(dns_xfrin_t *xfr) {
|
|||||||
xfr->nmsg = 0;
|
xfr->nmsg = 0;
|
||||||
xfr->nrecs = 0;
|
xfr->nrecs = 0;
|
||||||
xfr->nbytes = 0;
|
xfr->nbytes = 0;
|
||||||
UNLOCK(&xfr->statslock);
|
|
||||||
xfr->start = isc_time_now();
|
xfr->start = isc_time_now();
|
||||||
|
UNLOCK(&xfr->statslock);
|
||||||
msg->id = xfr->id;
|
msg->id = xfr->id;
|
||||||
if (xfr->tsigctx != NULL) {
|
if (xfr->tsigctx != NULL) {
|
||||||
dst_context_destroy(&xfr->tsigctx);
|
dst_context_destroy(&xfr->tsigctx);
|
||||||
@@ -1876,12 +1899,12 @@ xfrin_destroy(dns_xfrin_t *xfr) {
|
|||||||
* Calculate the length of time the transfer took,
|
* Calculate the length of time the transfer took,
|
||||||
* and print a log message with the bytes and rate.
|
* and print a log message with the bytes and rate.
|
||||||
*/
|
*/
|
||||||
|
LOCK(&xfr->statslock);
|
||||||
xfr->end = isc_time_now();
|
xfr->end = isc_time_now();
|
||||||
msecs = isc_time_microdiff(&xfr->end, &xfr->start) / 1000;
|
msecs = isc_time_microdiff(&xfr->end, &xfr->start) / 1000;
|
||||||
if (msecs == 0) {
|
if (msecs == 0) {
|
||||||
msecs = 1;
|
msecs = 1;
|
||||||
}
|
}
|
||||||
LOCK(&xfr->statslock);
|
|
||||||
persec = (xfr->nbytes * 1000) / msecs;
|
persec = (xfr->nbytes * 1000) / msecs;
|
||||||
xfrin_log(xfr, ISC_LOG_INFO,
|
xfrin_log(xfr, ISC_LOG_INFO,
|
||||||
"Transfer completed: %d messages, %d records, "
|
"Transfer completed: %d messages, %d records, "
|
||||||
|
Reference in New Issue
Block a user