diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2021-03-01 23:10:06 +0100 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2021-03-12 18:25:25 +0100 |
commit | c94ad6f6c3841d69a0eb3bf6ae524df60b9f70f2 (patch) | |
tree | 20a311dd5bd77cc1cdba4f99de74b24f9bb9f4a1 | |
parent | 28fa0e508a0fa544c47d18f1f17213bf7da6b4c7 (diff) | |
download | systemd-c94ad6f6c3841d69a0eb3bf6ae524df60b9f70f2.tar.gz |
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)
(cherry picked from commit 78a43c33c8847ebbc2d3cf530ebe304924c58b32)
-rw-r--r-- | src/resolve/resolved-dns-query.c | 2 | ||||
-rw-r--r-- | src/resolve/resolved-dns-scope.c | 8 | ||||
-rw-r--r-- | src/resolve/resolved-dns-stream.c | 4 | ||||
-rw-r--r-- | src/resolve/resolved-dns-stub.c | 4 | ||||
-rw-r--r-- | src/resolve/resolved-dns-transaction.c | 5 | ||||
-rw-r--r-- | src/resolve/resolved-llmnr.c | 8 | ||||
-rw-r--r-- | src/resolve/resolved-mdns.c | 4 |
7 files changed, 18 insertions, 17 deletions
diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c index 9272ece369..a238275238 100644 --- a/src/resolve/resolved-dns-query.c +++ b/src/resolve/resolved-dns-query.c @@ -298,7 +298,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 a03bac6eae..8fe668dac5 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); @@ -1034,7 +1034,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; @@ -1240,7 +1240,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 d4c49e673e..ea6c131ce0 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 edbcf54247..7af2233008 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -570,8 +570,8 @@ 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); m->dns_stub_udp_fd = safe_close(m->dns_stub_udp_fd); m->dns_stub_tcp_fd = safe_close(m->dns_stub_tcp_fd); diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index 7c9cfcd788..b376cab85a 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 61e50343e5..5ffa98477e 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 921720febf..15c3263920 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); } |