resolve: anchor the service browser from mDNS maintenance queries

mdns_maintenance_query() takes a ref on the browser's varlink link but
never installs itself as that link's userdata. dns_query_free() then
unconditionally runs sd_varlink_set_userdata(varlink_request, NULL),
so freeing any maintenance query wipes the browse query's registration
on the shared sb->link slot, disabling the abort paths in
vl_on_disconnect() and dns_service_browser_free(). The maintenance
query also never takes a reference on the DnsServiceBrowser, so a client
disconnect could free the browser while a maintenance query was still
in flight, leaving the per-service schedule_event timer and the raw
service->service_browser back-pointer dangling (use-after-free on the
next timer tick or query completion).

Take a service_browser_request reference instead, matching the browse
query path. dns_query_free() already drops it. The browser now outlives
its in-flight maintenance queries.

Follow-up for 8458b7fb91

(cherry picked from commit 46c15e88e0)
(cherry picked from commit 9e41763ec9)
(cherry picked from commit b428e7bfa1)
This commit is contained in:
Luca Boccassi
2026-07-02 22:20:31 +01:00
parent 21bb745303
commit 447d803001

View File

@@ -126,7 +126,7 @@ static int mdns_maintenance_query(sd_event_source *s, uint64_t usec, void *userd
return log_error_errno(r, "Failed to create mDNS query for maintenance: %m");
q->complete = mdns_maintenance_query_complete;
q->varlink_request = sd_varlink_ref(service->service_browser->link);
q->service_browser_request = dns_service_browser_ref(service->service_browser);
q->dnsservice_request = dnssd_discovered_service_ref(service);
/* Schedule the next maintenance query based on the TTL */