resolved: fix refcounting DnsScope's conflict_queue

Refcounting for a RR's key is done separately from refcounting
for the RR itself, but in dns_scope_notify_conflict() we don't
do that. This may lead to a situation when a RR key put in the
conflict_queue hash as a value's key gets freed upon
cache reduction when it's still referenced by the hash.

Thus increase refcount for the key when putting it into the hash
and unreference it upon removing from the hash.

Closes #6456
This commit is contained in:
Dmitry Rozhkov 2018-01-03 14:26:53 +02:00
parent 8481e3e71e
commit 432d108c25

View file

@ -885,13 +885,17 @@ static int on_conflict_dispatch(sd_event_source *es, usec_t usec, void *userdata
scope->conflict_event_source = sd_event_source_unref(scope->conflict_event_source);
for (;;) {
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
rr = ordered_hashmap_steal_first(scope->conflict_queue);
if (!rr)
key = ordered_hashmap_first_key(scope->conflict_queue);
if (!key)
break;
rr = ordered_hashmap_remove(scope->conflict_queue, key);
assert(rr);
r = dns_scope_make_conflict_packet(scope, rr, &p);
if (r < 0) {
log_error_errno(r, "Failed to make conflict packet: %m");
@ -930,6 +934,7 @@ int dns_scope_notify_conflict(DnsScope *scope, DnsResourceRecord *rr) {
if (r < 0)
return log_debug_errno(r, "Failed to queue conflicting RR: %m");
dns_resource_key_ref(rr->key);
dns_resource_record_ref(rr);
if (scope->conflict_event_source)