mirror of
https://github.com/isc-projects/bind9.git
synced 2026-04-27 00:58:39 -04:00
Address races in dns_tsigkey_find()
1) Restart the process with a write lock if we discover an expired key while holding the read lock. 2) Move incrementing the key reference inside the lock block of code.
This commit is contained in:
parent
9074bfa38d
commit
d2ba96488e
1 changed files with 15 additions and 9 deletions
|
|
@ -1539,38 +1539,44 @@ isc_result_t
|
|||
dns_tsigkey_find(dns_tsigkey_t **tsigkey, const dns_name_t *name,
|
||||
const dns_name_t *algorithm, dns_tsigkeyring_t *ring) {
|
||||
dns_tsigkey_t *key = NULL;
|
||||
isc_stdtime_t now = isc_stdtime_now();
|
||||
isc_result_t result;
|
||||
isc_rwlocktype_t locktype = isc_rwlocktype_read;
|
||||
isc_stdtime_t now = isc_stdtime_now();
|
||||
|
||||
REQUIRE(name != NULL);
|
||||
REQUIRE(VALID_TSIGKEYRING(ring));
|
||||
REQUIRE(tsigkey != NULL && *tsigkey == NULL);
|
||||
|
||||
RWLOCK(&ring->lock, isc_rwlocktype_read);
|
||||
again:
|
||||
RWLOCK(&ring->lock, locktype);
|
||||
result = isc_hashmap_find(ring->keys, dns_name_hash(name), tkey_match,
|
||||
name, (void **)&key);
|
||||
if (result == ISC_R_NOTFOUND) {
|
||||
RWUNLOCK(&ring->lock, isc_rwlocktype_read);
|
||||
RWUNLOCK(&ring->lock, locktype);
|
||||
return (result);
|
||||
}
|
||||
if (algorithm != NULL && !dns_name_equal(key->algorithm, algorithm)) {
|
||||
RWUNLOCK(&ring->lock, isc_rwlocktype_read);
|
||||
RWUNLOCK(&ring->lock, locktype);
|
||||
return (ISC_R_NOTFOUND);
|
||||
}
|
||||
if (key->inception != key->expire && isc_serial_lt(key->expire, now)) {
|
||||
/*
|
||||
* The key has expired.
|
||||
*/
|
||||
RWUNLOCK(&ring->lock, isc_rwlocktype_read);
|
||||
RWLOCK(&ring->lock, isc_rwlocktype_write);
|
||||
if (locktype == isc_rwlocktype_read) {
|
||||
RWUNLOCK(&ring->lock, locktype);
|
||||
locktype = isc_rwlocktype_write;
|
||||
key = NULL;
|
||||
goto again;
|
||||
}
|
||||
rm_lru(key);
|
||||
rm_hashmap(key);
|
||||
RWUNLOCK(&ring->lock, isc_rwlocktype_write);
|
||||
RWUNLOCK(&ring->lock, locktype);
|
||||
return (ISC_R_NOTFOUND);
|
||||
}
|
||||
RWUNLOCK(&ring->lock, isc_rwlocktype_read);
|
||||
adjust_lru(key);
|
||||
dns_tsigkey_ref(key);
|
||||
RWUNLOCK(&ring->lock, locktype);
|
||||
adjust_lru(key);
|
||||
*tsigkey = key;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue