From 89102b02047d0220766f55ec041c8fc46234cf69 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Tue, 20 Feb 2018 20:18:38 -0700 Subject: [PATCH] Fix heap corruption on Windows exposed by the use-after free fix. reset_address_cache() could call free_known_addresses() on a struct addrinfo * that was returned by getaddrinfo(). It seems safest to just make a copy of the addresses returned by getaddrinfo() so we can always use free_known_addresses() instead of trying to determine whether or not we need to use freeaddrinfo(). --- src/address_cache.c | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/src/address_cache.c b/src/address_cache.c index 381ae78..2fa9baf 100644 --- a/src/address_cache.c +++ b/src/address_cache.c @@ -169,6 +169,27 @@ const sockaddr_t *get_recent_address(address_cache_t *cache) { } cache->aip = cache->ai = str2addrinfo(address, port, SOCK_STREAM); + + if(cache->ai) { + struct addrinfo *ai = NULL; + + for(; cache->aip; cache->aip = cache->aip->ai_next) { + struct addrinfo *oai = ai; + + ai = xzalloc(sizeof(*ai)); + ai->ai_family = cache->aip->ai_family; + ai->ai_socktype = cache->aip->ai_socktype; + ai->ai_protocol = cache->aip->ai_protocol; + ai->ai_addrlen = cache->aip->ai_addrlen; + ai->ai_addr = xmalloc(ai->ai_addrlen); + memcpy(ai->ai_addr, cache->aip->ai_addr, ai->ai_addrlen); + ai->ai_next = oai; + } + + freeaddrinfo(cache->ai); + cache->aip = cache->ai = ai; + } + free(address); free(port); @@ -182,7 +203,7 @@ const sockaddr_t *get_recent_address(address_cache_t *cache) { cache->aip = cache->aip->ai_next; return sa; } else { - freeaddrinfo(cache->ai); + free_known_addresses(cache->ai); cache->ai = NULL; } } @@ -234,11 +255,7 @@ void reset_address_cache(address_cache_t *cache, const sockaddr_t *sa) { } if(cache->ai) { - if(cache->tried == cache->data.used) { - free_known_addresses(cache->ai); - } else { - freeaddrinfo(cache->ai); - } + free_known_addresses(cache->ai); } cache->config_tree = NULL; @@ -254,11 +271,7 @@ void close_address_cache(address_cache_t *cache) { } if(cache->ai) { - if(cache->tried == cache->data.used) { - free_known_addresses(cache->ai); - } else { - freeaddrinfo(cache->ai); - } + free_known_addresses(cache->ai); } free(cache); -- 2.25.1