Compute qpzone_get_lock(elem->node) into a local variable while the
heap lock is still held, rather than dereferencing the stale elem
pointer after releasing the lock. A concurrent thread running
setsigningtime() (e.g. via IXFR apply on a worker thread) could free
the top-of-heap element between the heap lock release and the
dereference, causing a use-after-free.
LOCK(&qpdb->heap->lock);
elem = isc_heap_element(qpdb->heap->heap, 1);
- if (elem != NULL && qpzone_get_lock(elem->node) != nlock) {
+ isc_rwlock_t *new_nlock = (elem != NULL) ? qpzone_get_lock(elem->node)
+ : NULL;
+ if (new_nlock != NULL && new_nlock != nlock) {
UNLOCK(&qpdb->heap->lock);
NODE_UNLOCK(nlock, &nlocktype);
- nlock = qpzone_get_lock(elem->node);
+ nlock = new_nlock;
goto again;
}