From 00313c505079c0a93ceb9e26bce1a5be298062ef Mon Sep 17 00:00:00 2001 From: Azat Khuzhin Date: Mon, 23 Nov 2015 15:05:19 +0300 Subject: [PATCH] evdns: evdns_base_free(): fix UAF of evdns_base with @fail_requests If you call evdns_base_free() with @fail_requests == 1, then it will defer callback with DNS_ERR_SHUTDOWN, but that callback (internal) uses data->evdns_base, but we already freed that evdns base, so we can't do this, fix this by checking @result to DNS_ERR_SHUTDOWN. Fixes: regress dns/client_fail_requests_getaddrinfo Fixes: #269 --- evdns.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/evdns.c b/evdns.c index 38cfd783..0955a289 100644 --- a/evdns.c +++ b/evdns.c @@ -4403,17 +4403,23 @@ evdns_getaddrinfo_gotresolve(int result, char type, int count, other_req = &data->ipv4_request; } - EVDNS_LOCK(data->evdns_base); - if (evdns_result_is_answer(result)) { - if (req->type == DNS_IPv4_A) - ++data->evdns_base->getaddrinfo_ipv4_answered; - else - ++data->evdns_base->getaddrinfo_ipv6_answered; + /** Called from evdns_base_free() with @fail_requests == 1 */ + if (result != DNS_ERR_SHUTDOWN) { + EVDNS_LOCK(data->evdns_base); + if (evdns_result_is_answer(result)) { + if (req->type == DNS_IPv4_A) + ++data->evdns_base->getaddrinfo_ipv4_answered; + else + ++data->evdns_base->getaddrinfo_ipv6_answered; + } + user_canceled = data->user_canceled; + if (other_req->r == NULL) + data->request_done = 1; + EVDNS_UNLOCK(data->evdns_base); + } else { + data->evdns_base = NULL; + user_canceled = data->user_canceled; } - user_canceled = data->user_canceled; - if (other_req->r == NULL) - data->request_done = 1; - EVDNS_UNLOCK(data->evdns_base); req->r = NULL; @@ -4447,7 +4453,9 @@ evdns_getaddrinfo_gotresolve(int result, char type, int count, /* The other request is still working; maybe it will * succeed. */ /* XXXX handle failure from set_timeout */ - evdns_getaddrinfo_set_timeout(data->evdns_base, data); + if (result != DNS_ERR_SHUTDOWN) { + evdns_getaddrinfo_set_timeout(data->evdns_base, data); + } data->pending_error = err; return; } -- 2.40.0