[PATCH v4 0/1] MR9085: iphlpapi: Give GetBestRoute2 a SOCKETADDR_INET.
Found by ASan. -- v4: iphlpapi: Give GetBestRoute2 a SOCKETADDR_INET. https://gitlab.winehq.org/wine/wine/-/merge_requests/9085
From: Yuxuan Shui <yshui(a)codeweavers.com> In this call chain: GetBestInterface -> GetBestInterfaceEx -> GetBestRoute2, we cast a socketaddr_in * (16 bytes) is to SOCKETADDR_INET * (28 bytes) before passing it to GetBestRoute2, but GetBestRoute2 will access all of the 28 bytes, leading to out-of-bound access. So we create a local SOCKETADDR_INET in GetBestInterfaceEx. Found by ASan. --- dlls/iphlpapi/iphlpapi_main.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c index 83c6e8b53b8..849ab0b0dbc 100644 --- a/dlls/iphlpapi/iphlpapi_main.c +++ b/dlls/iphlpapi/iphlpapi_main.c @@ -1392,14 +1392,20 @@ DWORD WINAPI GetBestInterface(IPAddr dwDestAddr, PDWORD pdwBestIfIndex) DWORD WINAPI GetBestInterfaceEx( struct sockaddr *dst, DWORD *best_index ) { SOCKADDR_INET best_address; + SOCKADDR_INET dst_address; MIB_IPFORWARD_ROW2 row; DWORD ret; TRACE( "dst %p, best_index %p\n", dst, best_index ); if (!dst || !best_index) return ERROR_INVALID_PARAMETER; + if (dst->sa_family != AF_INET && dst->sa_family != AF_INET6) return ERROR_INVALID_PARAMETER; - ret = GetBestRoute2( NULL, 0, NULL, (const SOCKADDR_INET *)dst, 0, &row, &best_address ); + dst_address.si_family = dst->sa_family; + if (dst->sa_family == AF_INET6) dst_address.Ipv6 = *(struct sockaddr_in6 *)dst; + else dst_address.Ipv4 = *(struct sockaddr_in *)dst; + + ret = GetBestRoute2( NULL, 0, NULL, &dst_address, 0, &row, &best_address ); if (!ret) *best_index = row.InterfaceIndex; TRACE( "returning %ld\n", ret ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9085
On Fri Oct 3 16:30:29 2025 +0000, Paul Gofman wrote:
Uh, sorry, I missed here that 'struct sockaddr' is actually not a generic address but just ipv4 address and shorter than SOCKADDR_INET. What contributes to confusion is that GetBestInterfaceEx() actually supports ipv6 addresses (that is in tests). MS docs specify the argument as 'sockaddr *' [1] which assumes different handling based on protocol, while the actual headers definition (also in Windows SDK) has 'struct sockaddr *'. I guess then we must leave GetBestInterface() alone and instead fill local SOCKADDR_INET in GetBestInterfaceEx() to pass to GetBestRoute2(). 1. https://learn.microsoft.com/en-us/windows/win32/winsock/sockaddr-2 updated, is this what you meant?
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/9085#note_118211
This merge request was approved by Huw Davies. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9085
participants (3)
-
Huw Davies (@huw) -
Yuxuan Shui -
Yuxuan Shui (@yshui)