In mirrored mode, handle route update as add instead of replace
Remove usage of route update as it can overwrite routes on other interfaces. add tests that verify host routing changes are correctly reflected in Linux
---------
Co-authored-by: Catalin-Emil Fetoiu <cfetoiu@microsoft.com>
Avoid selecting the guest IPv4 address as its synthesized default gateway when the host adapter does not expose one.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
Copilot-Session: ce168659-cb9d-4f0e-8fd1-2834d065ba9d
Mirrored route tracking used an incomplete comparator that considered only route class, destination address, and metric. Distinct routes with different prefix lengths or next hops could therefore be treated as equivalent and silently omitted.
The fix preserves the existing route-class ordering while using the complete EndpointRoute comparison for route identity. Regression tests cover prefix length, next hop, metric, exact duplicates, and dependency ordering.
In the port 0 tracking logic. The seccomp filter provides the tid instead of the pid. But the pidfd_open call by default requires the first parameter to be a pid. This causes bind calls in threads not tracked by the tracker. Which further causes the local host forwarding to not work for consomme.
This PR applies the PIDFD_THREAD flag introduced in kernel 6.9 to the pidfd_open call. So, it works with non group leader threads as well.
Please note:
PIDFD_THREAD is defined in place as musl does not provide <sys/pidfd.h> and including <linux/pidfd.h> introduces conflict with musl's header files.
The test is not using a perl script since the perl in the test distro is lacking threading support.
* cap host ephemeral range usage
* cap host ephemeral port usage
* fix format
* pr feedback and add tests
* pr review
* remove extra state
---------
Co-authored-by: Catalin-Emil Fetoiu <cfetoiu@microsoft.com>
* Track implicit autobind ports from listen() in Consomme networking
WSL2's Consomme networking mode only forwards TCP/UDP ports that were
explicitly bind()'d in the guest. If an application calls listen()
without first calling bind() (relying on the kernel's implicit
autobind to an ephemeral port), the port tracker never sees it,
so the port is never forwarded to the host and the socket is
unreachable via 127.0.0.1:<port> from Windows.
The seccomp filter that traps socket syscalls for port tracking
only ever trapped bind(); this extends it to also trap listen()
across all supported architectures (x86_64, x86 compat via
socketcall, and ARM/ARM64), and dispatches it through the existing
DeferredPortLookup/ResolvePortZeroBind mechanism already used for
explicit bind(port=0).
To avoid adding latency to the overwhelmingly common bind()+listen()
sequence (where the port is already known), ParseListen first checks
getsockname() synchronously and only falls back to the deferred
resolution path for genuine implicit-autobind-via-listen() calls
(no prior bind()).
Adds ListenWithoutBindIsTracked test coverage in both Consomme and
Mirrored NetworkTests suites.
Fixes#41117
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 30cabf31-6198-44c8-b078-2a2ce1c6c56b
* Fix clang-format violation in NetworkTests.cpp
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 30cabf31-6198-44c8-b078-2a2ce1c6c56b
* Fix stale/inaccurate comments per Copilot review
- Update RegisterSeccompHook doc comment to reference SIOCSIFFLAGS
(matching the actual BPF filter) instead of the incorrect TUNSETIFF.
- Update ParseListen's comment to reflect the getsockname() fast-path
added before deferring resolution, instead of describing it as
always deferring.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 30cabf31-6198-44c8-b078-2a2ce1c6c56b
* Clarify RegisterSeccompHook doc comment scope per Copilot review
ioctl(*, SIOCSIFFLAGS, *) is only trapped in the native 64-bit BPF
block, not the 32-bit compat blocks (socketcall/ARMV7), which only
trap bind()/listen(). Clarify the routine description accordingly.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 30cabf31-6198-44c8-b078-2a2ce1c6c56b
* Fix potential port truncation race in ListenWithoutBindIsTracked test
Only parse the PORT= value once the line is terminated by a newline,
instead of stopping at the first non-digit character seen in a
partial ReadFile() buffer. This avoids truncating the port number
(e.g. reading "123" as "12") when the perl helper's output is split
across multiple reads.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 85780ea9-1bf4-4997-8732-b33920e7d6b8
* Move network namespace read_symlink() into try block in ParseListen
If the target process exits between the seccomp trap and this call,
read_symlink() could throw outside of the try block, routing through
the outer GetCallInfo catch/log path with a bind()-focused error
message instead of the intended 'not an IP socket, let it through'
handling used by the rest of ParseListen.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 10ce6d20-f8ca-4204-92a2-48e23bb6ee66
---------
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 30cabf31-6198-44c8-b078-2a2ce1c6c56b
Copilot-Session: 85780ea9-1bf4-4997-8732-b33920e7d6b8
Copilot-Session: 10ce6d20-f8ca-4204-92a2-48e23bb6ee66
* Rename VirtioProxy networking mode to Consomme
Rename the VirtioProxy networking mode to Consomme across the C++/IDL/Linux
symbols and the networking engine class/files (VirtioNetworking ->
ConsommeNetworking). The .wslconfig networkingMode parser still accepts the
legacy "virtioproxy" string as an alias. Adds a docs section linking to
OpenVMM's consomme project, where the name comes from.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address PR feedback: scrub remaining virtio proxy refs, doc path, locked string
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* virtiofs port mapping poc
* Format
* Save state
* save state
* save state
* save state
* Save state
* Format
* Save state
* Save state
* Save state
* Save state
* Save state
* Save state
* Save state
* Format
* Restore workaround
* Save state
* Save state
* merge
* Save state
* Disable ipv6 DAD in virtionet mode
* Apply PR feedback
* Cleanup diff
* Save state
* Don't set the localhost flag is the legacy relay is requested
* Cleanup diff
* Format
* Update tests
* Format
* Remove GH comment
* Apply PR feedback
* Apply PR feedback
* Restore netmask
* Fix winrt test
* Save state
* Use client_ip=127.0.0.1 for WSL
* Update comment
* wip
* works
* edit comments
* add test
* use unique_handle
* fix lookup to be efficient
* simplify ListAllocatedPorts
* remove include
* edits
* pass networking mode to port tracker
* add keepalive
* add bound check after parsing
* default to none before parsing
* exit early on invalid mode
---------
Co-authored-by: Catalin-Emil Fetoiu <cfetoiu@microsoft.com>
* Remove DnsTunnelingSocket flag from VirtioNetworking
Drops the DnsTunnelingSocket virtio networking flag (and the dedicated DNS
hvsocket plumbing it carried) in favor of the in-built DnsTunneling path.
In virtio proxy mode, DNS queries are now always forwarded by the host
virtio proxy itself: Linux's /etc/resolv.conf points at the eth0 gateway IP
rather than the listener IP, no DNS hvsocket is opened, and the Linux init
does not start a DnsTunnelingManager.
Changes:
- VirtioNetworking: remove DnsTunnelingSocket enum value, dnsHvsocket
constructor parameter, m_dnsTunnelingResolver field, and the
DnsResolver.h include. RefreshGuestConnection now uses only the
in-built DnsTunneling path.
- WslCoreVm: virtio proxy branch unconditionally sets the DnsTunneling
flag when DNS tunneling is enabled. message->EnableDnsTunneling is
suppressed for virtio proxy mode so Linux init won't open the DNS
hvsocket. The pre-accepted dnsTunnelingSocket is dropped on the
NAT->VirtioProxy fallback path.
- HcsVirtualMachine: WSLC virtio proxy branch likewise switches to the
DnsTunneling flag and discards the unused dnsSocketHandle.
- Tests: add VirtioProxyTests::DnsTunnelingResolvConfUsesGateway which
asserts resolv.conf contains the gateway IP and not the legacy
listener IP, confirming the in-built path is in use.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Validate DNS hvsocket before DnsResolver support check
Reorder ConfigureNetworking so the caller-provided DnsSocket is validated against the requested feature flag before the LoadDnsResolverMethods call may clear it. Avoids E_INVALIDARG in NAT mode when the support check fails.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Format VirtioNetworking constructor parameter list
Wrap the constructor declaration/definition parameter list per the repo's
BinPackParameters: false / 130-column style.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Revert manual wrapping; clang-format prefers single-line constructor
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* VirtioProxy: rely on wsldevicehost default MAC addresses and fix DNS tunneling assert
Setting MAC addresses through the virtio-proxy guest connection options has
proven problematic, so stop forwarding client_mac, gateway_mac, and
gateway_mac_ipv6 from VirtioNetworking::RefreshGuestConnection() and let
wsldevicehost fall back to its default values.
Also extend the WI_ASSERT in WslCoreVm::IsDnsTunnelingSupported() to accept
NetworkingMode::VirtioProxy. The VirtioProxy case was missed when the wslc
feature branch was merged into main, causing the assert to fire in debug
builds when DNS tunneling support is queried under that mode.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Remove dead NetworkSettings::GetBestGatewayMacAddress
The previous commit dropped the only callers of GetBestGatewayMacAddress
when virtio-proxy stopped pushing MAC addresses to wsldevicehost. Remove
the now-unused declaration and definition.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* add unit test
---------
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Make port 0 resolution inline
* reduce retry delay to 10ms
* add e2e test
* resolve comments
* resolve comments
* [wip] add test debug info
* copy the new binary to test stage
* switch to using inline perl sript instead of linux binary
---------
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
* Fallback to NAT when IPv6 is disabled via registry for mirrored networking
When the registry key HKLM\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters
has DisabledComponents set to 0xFF (all IPv6 components disabled), mirrored
networking mode cannot mirror host interfaces. This adds a check in
ValidateNetworkingMode() that detects this condition and falls back to NAT
networking mode with a user-facing warning.
Only mirrored networking mode is affected by this registry key; other
networking modes (NAT, Bridged, VirtioProxy) are not checked.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* add registry check
* pr review
* remove shutdown
* re-add shutdown
---------
Co-authored-by: Catalin-Emil Fetoiu <cfetoiu@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* route fixes from protonvpn testing
* add unit test, fix log
* ai code review
* format with vs 2022
* review
* remove optional has_value checks
* harden contracts for to, via having or not having values
* update IsOnlink check
* fix constructor parameters
* fix build
---------
Co-authored-by: Catalin-Emil Fetoiu <cfetoiu@microsoft.com>
Cherry-pick WSL1/WSL2 test changes from 9c4dba91 (feature/wsl-for-apps).
Replace runtime WSL1_TEST_ONLY()/WSL2_TEST_ONLY() skip macros with
WSL1_TEST_METHOD()/WSL2_TEST_METHOD() TAEF metadata macros. This moves
version filtering to the test runner level via /select: queries, so
inapplicable tests are excluded entirely instead of appearing as skipped.
Updated files:
- test/windows/Common.h: New macros + removed old skip macros
- test/windows/*.cpp: Converted all test methods
- tools/test/run-tests.ps1: Auto-add /select: when no user filter
- cloudtest/TestGroup.xml.in: Add version filter to TAEF args
- test/README.md: Document new macros
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Allow VirtioProxy to keep EnableDnsTunneling=true in config, but clear
socket-specific options (BestEffortDnsParsing, DnsTunnelingIpAddress)
- Suppress dedicated DNS tunneling hvsocket for VirtioProxy; tunneling
is handled through the VirtioNetworking device host instead
- Set DnsTunneling flag on VirtioNetworkingFlags so the device host
knows to tunnel DNS
- Expand SWIOTLB kernel cmdline to cover VirtioFs and VirtioProxy
- Bump DeviceHost package to 1.1.39-0
- Add VirtioProxy DNS test coverage for tunneling on/off
- Skip GuestPortIsReleasedV6 on Windows 10
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
* Initial work
* .
* pr feedback and add unit test
* minor tweaks an fix use after free in logging statement
* implement PR feedback
* hopefully final pr feedback
* pr feedback in test function
* Address PR feedback: add try/catch to TrackPort and PortZeroBind queue push
---------
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
* VirtioProxy: Add IPv6 address, gateway, and route support
- Add PreferredIpv6Address field and GetBestGatewayV6* methods to NetworkSettings
- Extend GetHostEndpointSettings() to discover IPv6 unicast address and gateway
- Add UpdateIpv6Address() using ModifyGuestEndpointSettingRequest<IPAddress>
- Push IPv6 default route to guest via UpdateDefaultRoute(AF_INET6)
- Remove AF_INET6 early return in ModifyOpenPorts, use INETADDR_PORT()
- Add EndpointRoute::DefaultRoute() static factory
- Pass client_ip_ipv6 in devicehost options (not yet parsed by devicehost)
- Remove gateway_ip from devicehost options (only needed for DHCP)
- Include IPv6 DNS servers in non-tunneling DNS settings
- Add ConfigurationV6 and DnsResolutionAAAA tests
* cleanup and add more ipv6 tests
* added test coverage and minor updates
* clang format
* pr feedback
* format source
* pr feedback
* test fixes
---------
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
* DNS: Simplify dns logic and switch to using 'search' instead of 'domain'
which is obsolete.
* add optional header for natnetworking
* format
* extend configuration test for virtioproxy networking mode
---------
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
* TEST: Add testcases to validated bridged networking connectivity
* minor bridged test updates
---------
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
* test: extend coverage of virtioproxy networking mode
* test: add dns test variations to all networking classes
* remove bridged dns variations
* pr feedback
---------
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
* Clean up localhost relay implementation to not rely on procfs parsing.
* pr feedback
---------
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
* test: add simple virtio proxy networking tests
* move mirrored tests to their own class
* fix failing mirrored variation
* use different port for HostUdpBindDoesNotPreventGuestTcpBind
---------
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
Many Microsoft employees have contributed to the Windows Subsystem for Linux, this commit is the result of their work since 2016.
The entire history of the Windows Subsystem for Linux can't be shared here, but here's an overview of WSL's history after it moved to it own repository in 2021:
Number of commits on the main branch: 2930
Number of contributors: 31
Head over https://github.com/microsoft/WSL/releases for a more detailed history of the features added to WSL since 2021.