1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2024-11-23 01:49:53 +03:00

Mayaqua/DNS: Fix memory safety in DNS operation threads

Fix #1329
This commit is contained in:
Yihong Wu 2021-12-12 17:00:03 +08:00
parent 2a40d21ef9
commit b91d9af5e3
3 changed files with 95 additions and 43 deletions

View File

@ -318,10 +318,10 @@ bool DnsResolve(IP *ipv6, IP *ipv4, const char *hostname, UINT timeout, volatile
return false; return false;
} }
LIST *iplist_v6 = NewListFast(NULL); LIST *iplist_v6 = NULL;
LIST *iplist_v4 = NewListFast(NULL); LIST *iplist_v4 = NULL;
bool ret = DnsResolveEx(iplist_v6, iplist_v4, hostname, timeout, cancel_flag); bool ret = DnsResolveEx(&iplist_v6, &iplist_v4, hostname, timeout, cancel_flag);
if (ipv6 != NULL && LIST_NUM(iplist_v6) > 0) if (ipv6 != NULL && LIST_NUM(iplist_v6) > 0)
{ {
@ -348,7 +348,7 @@ bool DnsResolve(IP *ipv6, IP *ipv4, const char *hostname, UINT timeout, volatile
return ret; return ret;
} }
bool DnsResolveEx(LIST *iplist_v6, LIST *iplist_v4, const char *hostname, UINT timeout, volatile const bool *cancel_flag) bool DnsResolveEx(LIST **iplist_v6, LIST **iplist_v4, const char *hostname, UINT timeout, volatile const bool *cancel_flag)
{ {
if (iplist_v6 == NULL || iplist_v4 == NULL || IsEmptyStr(hostname)) if (iplist_v6 == NULL || iplist_v4 == NULL || IsEmptyStr(hostname))
{ {
@ -360,8 +360,10 @@ bool DnsResolveEx(LIST *iplist_v6, LIST *iplist_v4, const char *hostname, UINT t
IP ipv6, ipv4; IP ipv6, ipv4;
GetLocalHostIP6(&ipv6); GetLocalHostIP6(&ipv6);
GetLocalHostIP4(&ipv4); GetLocalHostIP4(&ipv4);
AddHostIPAddressToList(iplist_v6, &ipv6); *iplist_v6 = NewListFast(NULL);
AddHostIPAddressToList(iplist_v4, &ipv4); *iplist_v4 = NewListFast(NULL);
AddHostIPAddressToList(*iplist_v6, &ipv6);
AddHostIPAddressToList(*iplist_v4, &ipv4);
return true; return true;
} }
@ -370,12 +372,14 @@ bool DnsResolveEx(LIST *iplist_v6, LIST *iplist_v4, const char *hostname, UINT t
{ {
if (IsIP6(&ip)) if (IsIP6(&ip))
{ {
AddHostIPAddressToList(iplist_v6, &ip); *iplist_v6 = NewListFast(NULL);
AddHostIPAddressToList(*iplist_v6, &ip);
return true; return true;
} }
else else
{ {
AddHostIPAddressToList(iplist_v4, &ip); *iplist_v4 = NewListFast(NULL);
AddHostIPAddressToList(*iplist_v4, &ip);
return true; return true;
} }
@ -402,13 +406,14 @@ bool DnsResolveEx(LIST *iplist_v6, LIST *iplist_v4, const char *hostname, UINT t
Inc(threads_counter); Inc(threads_counter);
DNS_RESOLVER resolver; DNS_RESOLVER *resolver;
Zero(&resolver, sizeof(resolver)); resolver = ZeroMalloc(sizeof(DNS_RESOLVER));
resolver.IPList_v6 = iplist_v6; resolver->Ref = NewRef();
resolver.IPList_v4 = iplist_v4; resolver->IPList_v6 = NewListFast(NULL);
resolver.Hostname = hostname; resolver->IPList_v4 = NewListFast(NULL);
resolver->Hostname = CopyStr(hostname);
THREAD *worker = NewThread(DnsResolver, &resolver); THREAD *worker = NewThread(DnsResolver, resolver);
WaitThreadInit(worker); WaitThreadInit(worker);
if (cancel_flag == NULL) if (cancel_flag == NULL)
@ -439,12 +444,20 @@ bool DnsResolveEx(LIST *iplist_v6, LIST *iplist_v4, const char *hostname, UINT t
Dec(threads_counter); Dec(threads_counter);
if (resolver.OK) if (resolver->OK)
{ {
DnsCacheUpdateEx(hostname, iplist_v6, iplist_v4); *iplist_v6 = resolver->IPList_v6;
*iplist_v4 = resolver->IPList_v4;
resolver->IPList_v6 = NULL;
resolver->IPList_v4 = NULL;
DnsCacheUpdateEx(hostname, *iplist_v6, *iplist_v4);
ReleaseDnsResolver(resolver);
return true; return true;
} }
ReleaseDnsResolver(resolver);
CACHE: CACHE:
Debug("DnsResolve(): Could not resolve \"%s\". Searching for it in the cache...\n", hostname); Debug("DnsResolve(): Could not resolve \"%s\". Searching for it in the cache...\n", hostname);
@ -454,19 +467,8 @@ CACHE:
return false; return false;
} }
UINT i; *iplist_v6 = CloneIPAddressList(cached->IPList_v6);
*iplist_v4 = CloneIPAddressList(cached->IPList_v4);
for (i = 0; i < LIST_NUM(cached->IPList_v6); ++i)
{
IP *ip = LIST_DATA(cached->IPList_v6, i);
AddHostIPAddressToList(iplist_v6, ip);
}
for (i = 0; i < LIST_NUM(cached->IPList_v4); ++i)
{
IP *ip = LIST_DATA(cached->IPList_v4, i);
AddHostIPAddressToList(iplist_v4, ip);
}
return true; return true;
} }
@ -480,6 +482,8 @@ void DnsResolver(THREAD *t, void *param)
DNS_RESOLVER *resolver = param; DNS_RESOLVER *resolver = param;
AddRef(resolver->Ref);
NoticeThreadInit(t); NoticeThreadInit(t);
AddWaitThread(t); AddWaitThread(t);
@ -542,6 +546,8 @@ void DnsResolver(THREAD *t, void *param)
Debug("DnsResolver(): getaddrinfo() failed with error %d!\n", ret); Debug("DnsResolver(): getaddrinfo() failed with error %d!\n", ret);
} }
ReleaseDnsResolver(resolver);
DelWaitThread(t); DelWaitThread(t);
} }
@ -572,11 +578,12 @@ bool DnsResolveReverse(char *dst, const UINT size, const IP *ip, UINT timeout, v
Inc(threads_counter); Inc(threads_counter);
DNS_RESOLVER_REVERSE resolver; DNS_RESOLVER_REVERSE *resolver;
Zero(&resolver, sizeof(resolver)); resolver = ZeroMalloc(sizeof(DNS_RESOLVER_REVERSE));
Copy(&resolver.IP, ip, sizeof(resolver.IP)); resolver->Ref = NewRef();
Copy(&resolver->IP, ip, sizeof(resolver->IP));
THREAD *worker = NewThread(DnsResolverReverse, &resolver); THREAD *worker = NewThread(DnsResolverReverse, resolver);
WaitThreadInit(worker); WaitThreadInit(worker);
if (cancel_flag == NULL) if (cancel_flag == NULL)
@ -607,15 +614,17 @@ bool DnsResolveReverse(char *dst, const UINT size, const IP *ip, UINT timeout, v
Dec(threads_counter); Dec(threads_counter);
if (resolver.OK) if (resolver->OK)
{ {
StrCpy(dst, size, resolver.Hostname); StrCpy(dst, size, resolver->Hostname);
Free(resolver.Hostname);
DnsCacheReverseUpdate(ip, dst); DnsCacheReverseUpdate(ip, dst);
ReleaseDnsResolverReverse(resolver);
return true; return true;
} }
ReleaseDnsResolverReverse(resolver);
CACHE: CACHE:
Debug("DnsResolveReverse(): Could not resolve \"%r\". Searching for it in the cache...\n", ip); Debug("DnsResolveReverse(): Could not resolve \"%r\". Searching for it in the cache...\n", ip);
@ -639,6 +648,8 @@ void DnsResolverReverse(THREAD *t, void *param)
DNS_RESOLVER_REVERSE *resolver = param; DNS_RESOLVER_REVERSE *resolver = param;
AddRef(resolver->Ref);
NoticeThreadInit(t); NoticeThreadInit(t);
AddWaitThread(t); AddWaitThread(t);
@ -659,6 +670,8 @@ void DnsResolverReverse(THREAD *t, void *param)
Debug("DnsResolverReverse(): getnameinfo() failed with error %d!\n", ret); Debug("DnsResolverReverse(): getnameinfo() failed with error %d!\n", ret);
} }
ReleaseDnsResolverReverse(resolver);
DelWaitThread(t); DelWaitThread(t);
} }
@ -688,3 +701,37 @@ bool GetIPEx(IP *ip, const char *hostname, UINT timeout, volatile const bool *ca
return false; return false;
} }
// Release of the parameters of the DNS Resolver thread
void ReleaseDnsResolver(DNS_RESOLVER *p)
{
// Validate arguments
if (p == NULL)
{
return;
}
if (Release(p->Ref) == 0)
{
FreeHostIPAddressList(p->IPList_v6);
FreeHostIPAddressList(p->IPList_v4);
Free(p->Hostname);
Free(p);
}
}
// Release of the parameters of the DNS Resolver Reverse thread
void ReleaseDnsResolverReverse(DNS_RESOLVER_REVERSE *p)
{
// Validate arguments
if (p == NULL)
{
return;
}
if (Release(p->Ref) == 0)
{
Free(p->Hostname);
Free(p);
}
}

View File

@ -38,6 +38,7 @@ struct DNS_CACHE_REVERSE
struct DNS_RESOLVER struct DNS_RESOLVER
{ {
REF *Ref;
const char *Hostname; const char *Hostname;
LIST *IPList_v4; LIST *IPList_v4;
LIST *IPList_v6; LIST *IPList_v6;
@ -46,6 +47,7 @@ struct DNS_RESOLVER
struct DNS_RESOLVER_REVERSE struct DNS_RESOLVER_REVERSE
{ {
REF *Ref;
IP IP; IP IP;
char *Hostname; char *Hostname;
bool OK; bool OK;
@ -69,7 +71,7 @@ DNS_CACHE_REVERSE *DnsCacheReverseFind(const IP *ip);
DNS_CACHE_REVERSE *DnsCacheReverseUpdate(const IP *ip, const char *hostname); DNS_CACHE_REVERSE *DnsCacheReverseUpdate(const IP *ip, const char *hostname);
bool DnsResolve(IP *ipv6, IP *ipv4, const char *hostname, UINT timeout, volatile const bool *cancel_flag); bool DnsResolve(IP *ipv6, IP *ipv4, const char *hostname, UINT timeout, volatile const bool *cancel_flag);
bool DnsResolveEx(LIST *iplist_v6, LIST *iplist_v4, const char *hostname, UINT timeout, volatile const bool *cancel_flag); bool DnsResolveEx(LIST **iplist_v6, LIST **iplist_v4, const char *hostname, UINT timeout, volatile const bool *cancel_flag);
void DnsResolver(THREAD *t, void *param); void DnsResolver(THREAD *t, void *param);
bool DnsResolveReverse(char *dst, const UINT size, const IP *ip, UINT timeout, volatile const bool *cancel_flag); bool DnsResolveReverse(char *dst, const UINT size, const IP *ip, UINT timeout, volatile const bool *cancel_flag);
@ -77,4 +79,7 @@ void DnsResolverReverse(THREAD *t, void *param);
bool GetIPEx(IP *ip, const char *hostname, UINT timeout, volatile const bool *cancel_flag); bool GetIPEx(IP *ip, const char *hostname, UINT timeout, volatile const bool *cancel_flag);
void ReleaseDnsResolver(DNS_RESOLVER *p);
void ReleaseDnsResolverReverse(DNS_RESOLVER_REVERSE *p);
#endif #endif

View File

@ -14484,18 +14484,20 @@ SOCK *ConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha
StrCpy(hostname_original, sizeof(hostname_original), hostname); StrCpy(hostname_original, sizeof(hostname_original), hostname);
} }
LIST *iplist_v6 = NewListFast(NULL); LIST *iplist_v6 = NULL;
LIST *iplist_v4 = NewListFast(NULL); LIST *iplist_v4 = NULL;
if (IsZeroIp(ret_ip) == false) if (IsZeroIp(ret_ip) == false)
{ {
// Skip name resolution // Skip name resolution
if (IsIP6(ret_ip)) if (IsIP6(ret_ip))
{ {
iplist_v6 = NewListFast(NULL);
AddHostIPAddressToList(iplist_v6, ret_ip); AddHostIPAddressToList(iplist_v6, ret_ip);
} }
else else
{ {
iplist_v4 = NewListFast(NULL);
AddHostIPAddressToList(iplist_v4, ret_ip); AddHostIPAddressToList(iplist_v4, ret_ip);
} }
@ -14504,10 +14506,8 @@ SOCK *ConnectEx4(char *hostname, UINT port, UINT timeout, bool *cancel_flag, cha
else else
{ {
// Forward resolution // Forward resolution
if (DnsResolveEx(iplist_v6, iplist_v4, hostname_original, 0, cancel_flag) == false) if (DnsResolveEx(&iplist_v6, &iplist_v4, hostname_original, 0, cancel_flag) == false)
{ {
FreeHostIPAddressList(iplist_v6);
FreeHostIPAddressList(iplist_v4);
return NULL; return NULL;
} }
} }