From: Luca Boccassi Date: Wed, 24 Jun 2026 12:43:14 +0000 (+0100) Subject: resolved: fix potential use-after-free when freeing DNS extra stub listeners X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a6e2bfe533a80e3ddc03312fd8c2d87614f7a02f;p=thirdparty%2Fsystemd.git resolved: fix potential use-after-free when freeing DNS extra stub listeners dns_stub_listener_extra_free() frees the listener while DnsQuery and DnsStream objects still keep pointers to it. On a reload the extra listeners are freed before dns_stream_disconnect_all() and dns_query_free() run, and dns_query_free() then dereferences those pointers. --- diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index 91ea30e0e2f..4a4c3f00157 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -102,6 +102,19 @@ DnsStubListenerExtra *dns_stub_listener_extra_free(DnsStubListenerExtra *p) { 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); + assert(p->manager); + + /* Detach the raw back-pointers that DnsStream and DnsQuery objects keep to this listener before we + * free it. Otherwise a later dns_stream_complete()/dns_query_free() during the same reload would + * dereference the freed slab: dns_query_free() reads q->stub_listener_extra->queries_by_packet. */ + LIST_FOREACH(streams, s, p->manager->dns_streams) + if (s->stub_listener_extra == p) + s->stub_listener_extra = NULL; + + LIST_FOREACH(queries, q, p->manager->dns_queries) + if (q->stub_listener_extra == p) + q->stub_listener_extra = NULL; + hashmap_free(p->queries_by_packet); return mfree(p);