resolve: fix use-after-free of the service browser in mDNS maintenance
mdns_maintenance_query_complete() takes a reference on query->dnsservice_request and never drops it, so every successful mDNS maintenance query leaks one reference to the discovered service. The leak alone would be benign, but the service owns the one-shot event source that drives its maintenance schedule, and it only borrows a plain pointer to its service browser. Once the extra reference is outstanding, dns_service_browser_free() -> dns_remove_service() only drops the list's reference, so dns_service_free() never runs, the maintenance timer is never disabled, and the service outlives the browser it points at. The next time the timer fires, mdns_maintenance_query() dereferences the freed DnsServiceBrowser to reach the manager's event loop and to issue the query. Reaching it only takes a browse subscription whose record lives long enough for one maintenance query to be answered, followed by the subscription going away. Make the reference a _cleanup_ one, the way the sibling mdns_browse_service_query_complete() below already handles the reference it takes on the service browser.
This commit is contained in:
committed by
Yu Watanabe
parent
a019396d2c
commit
2451b1a9c4
@@ -79,9 +79,9 @@ static usec_t mdns_maintenance_jitter(uint32_t ttl) {
|
||||
}
|
||||
|
||||
static void mdns_maintenance_query_complete(DnsQuery *q) {
|
||||
_cleanup_(dnssd_discovered_service_unrefp) DnssdDiscoveredService *service = NULL;
|
||||
_cleanup_(dns_service_browser_unrefp) DnsServiceBrowser *sb = NULL;
|
||||
_cleanup_(dns_query_freep) DnsQuery *query = q;
|
||||
DnssdDiscoveredService *service = NULL;
|
||||
int r;
|
||||
|
||||
assert(query);
|
||||
|
||||
Reference in New Issue
Block a user