Resolve the localhost name family to loopback on Android#128771
Resolve the localhost name family to loopback on Android#128771simonrozsival wants to merge 1 commit into
Conversation
|
Tagging subscribers to this area: @karelz, @dotnet/ncl |
|
/azp run runtime-android |
|
Azure Pipelines successfully started running 1 pipeline(s). |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Pull request overview
This PR adjusts name resolution behavior so the localhost name family behaves consistently with RFC 6761 expectations on Android, and adds managed normalization/fallback logic to make localhost. and *.localhost variants resolve more reliably across platforms.
Changes:
- Native (Android-only): prevents interface-address augmentation from polluting
localhostresults when Android’sgethostname()is"localhost". - Managed (all platforms): normalizes exact
"localhost."→"localhost"and falls back from*.localhostto plainlocalhostwhen the OS resolver fails or returns no addresses. - Tests: updates functional tests to require loopback for
*.localhoston Android (while still allowing Apple mobile exceptions) and adds/clarifies trailing-dot coverage.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/native/libs/System.Native/pal_networking.c | Adds ShouldAugmentWithInterfaceAddresses to skip Android augmentation for localhost, preventing non-loopback leakage. |
| src/libraries/System.Net.NameResolution/src/System/Net/Dns.cs | Normalizes localhost. and implements RFC 6761-style fallback for *.localhost when OS resolution fails/returns empty. |
| src/libraries/System.Net.NameResolution/tests/FunctionalTests/GetHostEntryTest.cs | Updates localhost-subdomain expectations (Android now requires loopback) and documents/validates localhost. behavior. |
| src/libraries/System.Net.NameResolution/tests/FunctionalTests/GetHostAddressesTest.cs | Same as above for GetHostAddresses, including trailing-dot and subdomain coverage. |
On Android the "localhost" name family did not resolve to loopback as
required by RFC 6761 Section 6.3:
- "localhost" could return non-loopback addresses because interface
addresses leaked into the result.
- "localhost." (fully-qualified form) and "*.localhost" subdomains failed
with SocketException, since Android's getaddrinfo does not strip the
trailing dot and has no /etc/hosts entry for subdomains.
Native (pal_networking.c, Android-only):
SystemNative_GetHostEntryForName augments getaddrinfo results with local
interface addresses (getifaddrs) when the queried name equals
gethostname(). On Android gethostname() can return "localhost", polluting
its resolution with non-loopback addresses. New helper
ShouldAugmentWithInterfaceAddresses skips augmentation for "localhost" on
Android only.
Managed (Dns.cs, all platforms):
- Normalize an exact "localhost." to "localhost" at both the sync and
async resolution cores so the fully-qualified form resolves identically
to "localhost". This is a no-op on glibc/Windows, which already strip
the trailing dot.
- For "*.localhost" subdomains, try the OS resolver first and fall back to
resolving plain "localhost" if it fails or returns no addresses. The
fallback target is not a subdomain, so it cannot recurse.
Tests:
Require loopback for "*.localhost" on Android, and add coverage for
"localhost." and subdomain-with-trailing-dot forms.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
bba7bfb to
9997901
Compare
System.Net Code Review — DNS / RFC 6761 localhost resolution on AndroidProtocols: DNS resolution (RFC 6761 §6.3) Summary
AnalysisThe two-layer fix is well-designed:
RFC 6761 compliance: ✅ Section 6.3 states localhost names SHOULD resolve to loopback. Both the FQDN normalization and the subdomain fallback correctly implement this. Security: ✅ The change tightens behavior — prevents non-loopback addresses from appearing in localhost resolution. Edge cases: The native Tests: ✅ Android exclusions properly removed; loopback is now asserted on Android. Verdict✅ LGTM — Clean, well-documented fix with correct RFC references and appropriate platform scoping.
|
|
/azp run runtime-android |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Note
This pull request was authored with the assistance of GitHub Copilot.
Summary
On Android, the
localhostname family did not resolve to loopback as required by RFC 6761 §6.3:localhostcould return non-loopback addresses (interface addresses leaked into the result).localhost.(fully-qualified form with a trailing dot) and*.localhostsubdomains failed withSocketExceptionbecause Android'sgetaddrinfodoes not strip the trailing dot and has no/etc/hostsentry for subdomains.This PR makes the whole
localhostfamily (localhost,localhost.,*.localhost,*.localhost.) resolve to the loopback address, consistent with desktop glibc/Windows behavior.Changes
Native (
src/native/libs/System.Native/pal_networking.c) — Android-onlySystemNative_GetHostEntryForNameaugmentsgetaddrinforesults with local interface addresses (fromgetifaddrs) when the queried name equalsgethostname(). On Android,gethostname()can itself return"localhost", which caused non-loopback interface addresses to pollutelocalhostresolution. A new helperShouldAugmentWithInterfaceAddressesskips augmentation forlocalhoston Android only.Managed (
src/libraries/System.Net.NameResolution/src/System/Net/Dns.cs) — all platformslocalhost.→localhost(NormalizeLocalhostName) at both the sync and async resolution cores, so the fully-qualified form resolves identically tolocalhost. This is platform-agnostic per the RFC; it only changes behavior on resolvers that don't strip the trailing dot themselves (Android), and is a no-op on glibc/Windows which already resolve both.*.localhostsubdomains: try the OS resolver first; if it fails or returns no addresses, fall back to resolving plainlocalhost(IsLocalhostSubdomain). The fallback targetlocalhostis not a subdomain, so the fallback cannot recurse.Tests (
tests/FunctionalTests/GetHostAddressesTest.cs,GetHostEntryTest.cs)*.localhostsubdomains now require loopback on Android (requireLoopback = !PlatformDetection.IsAppleMobile), and added/clarifiedlocalhost.-with-trailing-dot and subdomain-with-trailing-dot coverage.Validation
*_LocalhostWithTrailingDot_ReturnsLoopback(previously failing).