From: Zbigniew Jędrzejewski-Szmek Date: Mon, 1 Mar 2021 22:10:06 +0000 (+0100) Subject: resolved: disable event sources before unreffing them X-Git-Tag: v247.4~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=78a43c33c8847ebbc2d3cf530ebe304924c58b32;p=thirdparty%2Fsystemd.git resolved: disable event sources before unreffing them We generally operate on the assumption that a source is "gone" as soon as we unref it. This is generally true because we have the only reference. But if something else holds the reference, our unref doesn't really stop the source and it could fire again. In particular, on_query_timeout() is called with DnsQuery* as userdata, and it calls dns_query_stop() which invalidates that pointer. If it was ever called again, we'd be accessing already-freed memory. I don't see what would hold the reference. sd-event takes a temporary reference, but on the sd_event object, not on the individual sources. And our sources are non-floating, so there is no reference from the sd_event object to the sources. For #18427. (cherry picked from commit 97935302283729c9206b84f5e00b1aff0f78ad19) --- diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c index 8ee4fd83093..f6ff3b5388e 100644 --- a/src/resolve/resolved-dns-query.c +++ b/src/resolve/resolved-dns-query.c @@ -297,7 +297,7 @@ static void dns_query_stop(DnsQuery *q) { assert(q); - q->timeout_event_source = sd_event_source_unref(q->timeout_event_source); + q->timeout_event_source = sd_event_source_disable_unref(q->timeout_event_source); LIST_FOREACH(candidates_by_query, c, q->candidates) dns_query_candidate_stop(c); diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index 509a2060e88..2063f0a2b6e 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -110,9 +110,9 @@ DnsScope* dns_scope_free(DnsScope *s) { hashmap_free(s->transactions_by_key); ordered_hashmap_free_with_destructor(s->conflict_queue, dns_resource_record_unref); - sd_event_source_unref(s->conflict_event_source); + sd_event_source_disable_unref(s->conflict_event_source); - sd_event_source_unref(s->announce_event_source); + sd_event_source_disable_unref(s->announce_event_source); dns_cache_flush(&s->cache); dns_zone_flush(&s->zone); @@ -980,7 +980,7 @@ static int on_conflict_dispatch(sd_event_source *es, usec_t usec, void *userdata assert(es); assert(scope); - scope->conflict_event_source = sd_event_source_unref(scope->conflict_event_source); + scope->conflict_event_source = sd_event_source_disable_unref(scope->conflict_event_source); for (;;) { _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; @@ -1191,7 +1191,7 @@ static int on_announcement_timeout(sd_event_source *s, usec_t usec, void *userda assert(s); - scope->announce_event_source = sd_event_source_unref(scope->announce_event_source); + scope->announce_event_source = sd_event_source_disable_unref(scope->announce_event_source); (void) dns_scope_announce(scope, false); return 0; diff --git a/src/resolve/resolved-dns-stream.c b/src/resolve/resolved-dns-stream.c index 1aab0899347..1471628fc32 100644 --- a/src/resolve/resolved-dns-stream.c +++ b/src/resolve/resolved-dns-stream.c @@ -18,8 +18,8 @@ static void dns_stream_stop(DnsStream *s) { assert(s); - s->io_event_source = sd_event_source_unref(s->io_event_source); - s->timeout_event_source = sd_event_source_unref(s->timeout_event_source); + s->io_event_source = sd_event_source_disable_unref(s->io_event_source); + s->timeout_event_source = sd_event_source_disable_unref(s->timeout_event_source); s->fd = safe_close(s->fd); /* Disconnect us from the server object if we are now not usable anymore */ diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index 6a3dc9901ae..5043c607cf7 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -79,8 +79,8 @@ DnsStubListenerExtra *dns_stub_listener_extra_free(DnsStubListenerExtra *p) { if (!p) return NULL; - p->udp_event_source = sd_event_source_unref(p->udp_event_source); - p->tcp_event_source = sd_event_source_unref(p->tcp_event_source); + p->udp_event_source = sd_event_source_disable_unref(p->udp_event_source); + p->tcp_event_source = sd_event_source_disable_unref(p->tcp_event_source); return mfree(p); } @@ -763,12 +763,12 @@ int manager_dns_stub_start(Manager *m) { void manager_dns_stub_stop(Manager *m) { assert(m); - m->dns_stub_udp_event_source = sd_event_source_unref(m->dns_stub_udp_event_source); - m->dns_stub_tcp_event_source = sd_event_source_unref(m->dns_stub_tcp_event_source); + m->dns_stub_udp_event_source = sd_event_source_disable_unref(m->dns_stub_udp_event_source); + m->dns_stub_tcp_event_source = sd_event_source_disable_unref(m->dns_stub_tcp_event_source); } static const char* const dns_stub_listener_mode_table[_DNS_STUB_LISTENER_MODE_MAX] = { - [DNS_STUB_LISTENER_NO] = "no", + [DNS_STUB_LISTENER_NO] = "no", [DNS_STUB_LISTENER_UDP] = "udp", [DNS_STUB_LISTENER_TCP] = "tcp", [DNS_STUB_LISTENER_YES] = "yes", diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index 37f0ddde6c4..8cf4a9637ad 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -59,14 +59,15 @@ static void dns_transaction_close_connection(DnsTransaction *t) { t->stream = dns_stream_unref(t->stream); } - t->dns_udp_event_source = sd_event_source_unref(t->dns_udp_event_source); + t->dns_udp_event_source = sd_event_source_disable_unref(t->dns_udp_event_source); + t->dns_udp_fd = safe_close(t->dns_udp_fd); } static void dns_transaction_stop_timeout(DnsTransaction *t) { assert(t); - t->timeout_event_source = sd_event_source_unref(t->timeout_event_source); + t->timeout_event_source = sd_event_source_disable_unref(t->timeout_event_source); } DnsTransaction* dns_transaction_free(DnsTransaction *t) { diff --git a/src/resolve/resolved-llmnr.c b/src/resolve/resolved-llmnr.c index 2ddf08815ad..ad359162685 100644 --- a/src/resolve/resolved-llmnr.c +++ b/src/resolve/resolved-llmnr.c @@ -11,16 +11,16 @@ void manager_llmnr_stop(Manager *m) { assert(m); - m->llmnr_ipv4_udp_event_source = sd_event_source_unref(m->llmnr_ipv4_udp_event_source); + m->llmnr_ipv4_udp_event_source = sd_event_source_disable_unref(m->llmnr_ipv4_udp_event_source); m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd); - m->llmnr_ipv6_udp_event_source = sd_event_source_unref(m->llmnr_ipv6_udp_event_source); + m->llmnr_ipv6_udp_event_source = sd_event_source_disable_unref(m->llmnr_ipv6_udp_event_source); m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd); - m->llmnr_ipv4_tcp_event_source = sd_event_source_unref(m->llmnr_ipv4_tcp_event_source); + m->llmnr_ipv4_tcp_event_source = sd_event_source_disable_unref(m->llmnr_ipv4_tcp_event_source); m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd); - m->llmnr_ipv6_tcp_event_source = sd_event_source_unref(m->llmnr_ipv6_tcp_event_source); + m->llmnr_ipv6_tcp_event_source = sd_event_source_disable_unref(m->llmnr_ipv6_tcp_event_source); m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd); } diff --git a/src/resolve/resolved-mdns.c b/src/resolve/resolved-mdns.c index 3996fcab2ef..aee7bf7e475 100644 --- a/src/resolve/resolved-mdns.c +++ b/src/resolve/resolved-mdns.c @@ -15,10 +15,10 @@ void manager_mdns_stop(Manager *m) { assert(m); - m->mdns_ipv4_event_source = sd_event_source_unref(m->mdns_ipv4_event_source); + m->mdns_ipv4_event_source = sd_event_source_disable_unref(m->mdns_ipv4_event_source); m->mdns_ipv4_fd = safe_close(m->mdns_ipv4_fd); - m->mdns_ipv6_event_source = sd_event_source_unref(m->mdns_ipv6_event_source); + m->mdns_ipv6_event_source = sd_event_source_disable_unref(m->mdns_ipv6_event_source); m->mdns_ipv6_fd = safe_close(m->mdns_ipv6_fd); }