From 432d108c25a9705f1564d7620c38cdf890df40ba Mon Sep 17 00:00:00 2001 From: Dmitry Rozhkov Date: Wed, 3 Jan 2018 14:26:53 +0200 Subject: [PATCH] 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 --- src/resolve/resolved-dns-scope.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index ea4459a89a3..9247bb34e6d 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -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)