Skip to content

Commit

Permalink
evdns: fix race condition in evdns_getaddrinfo()
Browse files Browse the repository at this point in the history
evdns_getaddrinfo() starts two parallel requests for A and AAAA record.
But if request is created from thread different from dns_base's, request of A record is
started immediately and may result in calling free_getaddrinfo_request() from
evdns_getaddrinfo_gotresolve() because `other_req' doesn't exist yet.

After that, request of AAAA record starts and finishes, and evdns_getaddrinfo_gotresolve()
is called again for structure that is already freed.

This commits adds locking into evdns_getaddrinfo() function.
  • Loading branch information
sfionov authored and azat committed Aug 2, 2018
1 parent e85818d commit b59525e
Showing 1 changed file with 8 additions and 1 deletion.
9 changes: 8 additions & 1 deletion evdns.c
Original file line number Diff line number Diff line change
Expand Up @@ -4637,6 +4637,7 @@ evdns_getaddrinfo(struct evdns_base *dns_base,
int err;
int port = 0;
int want_cname = 0;
int started = 0;

if (!dns_base) {
dns_base = current_base;
Expand Down Expand Up @@ -4715,6 +4716,8 @@ evdns_getaddrinfo(struct evdns_base *dns_base,
* launching those requests. (XXX we don't do that yet.)
*/

EVDNS_LOCK(dns_base);

if (hints.ai_family != PF_INET6) {
log(EVDNS_LOG_DEBUG, "Sending request for %s on ipv4 as %p",
nodename, &data->ipv4_request);
Expand All @@ -4741,7 +4744,11 @@ evdns_getaddrinfo(struct evdns_base *dns_base,
evtimer_assign(&data->timeout, dns_base->event_base,
evdns_getaddrinfo_timeout_cb, data);

if (data->ipv4_request.r || data->ipv6_request.r) {
started = (data->ipv4_request.r || data->ipv6_request.r);

EVDNS_UNLOCK(dns_base);

if (started) {
return data;
} else {
mm_free(data);
Expand Down

0 comments on commit b59525e

Please sign in to comment.