Skip to content

Fix various protocol parsing issues - #41637

Merged
Ben Hillis (benhillis) merged 14 commits into
masterfrom
user/oneblue/fix-parsing-bugs
Sep 18, 2026
Merged

Ben Hillis (benhillis) merged 14 commits into
masterfrom
user/oneblue/fix-parsing-bugs

Conversation

@OneBlue

@OneBlue Blue (OneBlue) commented Sep 17, 2026 •

Copy link
Copy Markdown
Collaborator

Summary of the Pull Request

This change solves 3 parsing bugs:

  1. Reject 'clientId' strings whose length extend passed the end of the message in Plan9's TGetLock / RGetLock handler

  2. Reject truncated Plan9 TRead requests

  3. Switch string arrays to using the ArrayFromSpan format instead of null separated strings. The previous implementation could read passed the message length in multiple places

This change also add a bit of logic in the plan9 entrypoint to run it ad-hoc, which allows to run unit tests on the plan9 server

PR Checklist

  • Closes: Link to issue #xxx
  • Communication: I've discussed this with core contributors already. If work hasn't been agreed, this work might be rejected
  • Tests: Added/updated if needed and all pass
  • Localization: All end user facing strings can be localized
  • Dev docs: Added/updated if needed
  • Documentation updated: If checked, please file a pull request on our docs repo and link it here: #xxx

Detailed Description of the Pull Request / Additional comments

Validation Steps Performed

Copilot AI lite review requested due to automatic review settings September 17, 2026 20:16

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Address the truncated TRead logging failure and correct the ineffective Rgetlock regression test.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Hardens Plan 9 protocol parsing and migrates process string arrays to bounded, length-prefixed serialization.

Changes:

  • Adds validation for truncated and oversized Plan 9 requests.
  • Adds TCP Plan 9 test infrastructure and regression tests.
  • Updates process-message serialization and parsing.
File summaries
File Summary
test/windows/Plan9ProtocolTests.cpp Adds protocol regression tests; one test does not exercise Rgetlock parsing, with minor wording nits.
test/windows/CMakeLists.txt Registers the new tests.
src/windows/service/exe/WslCoreInstance.cpp Uses the updated process-message layout.
src/windows/service/exe/LxssInstance.cpp Updates process-message field access.
src/windows/service/exe/LxssCreateProcess.h Implements length-prefixed serialization.
src/windows/service/exe/LxssCreateProcess.cpp Removes obsolete serialization logic.
src/shared/inc/lxinitshared.h Updates process-message structures.
src/linux/plan9/p9log.h Bounds lock-string logging.
src/linux/plan9/p9handler.cpp Validates message sizes and lock strings; logging can still terminate on truncated TRead requests.
src/linux/init/util.cpp Parses process argument arrays.
src/linux/init/plan9.h Extends Plan 9 server parameters.
src/linux/init/plan9.cpp Adds TCP server binding.
src/linux/init/init.cpp Parses revised process messages and bind options.
src/linux/init/config.h Updates environment-block APIs.
src/linux/init/config.cpp Parses environment arrays safely.
Review details

Suppressed comments (3)

test/windows/Plan9ProtocolTests.cpp:271

  • This packet cannot exercise Rgetlock parsing: HandleMessage has no Rgetlock case and returns ENOTSUP regardless of the payload, so the assertion would pass even if the malformed client-id handling were broken. Test the actual Tgetlock path, or explicitly enable verbose logging and assert that this malformed response-shaped packet does not terminate the server.
        SendMessageAndExpectResponse(
            server.client.get(), MakePlan9Message(Plan9MessageType::Rgetlock, std::move(payload)), Plan9MessageType::Rlerror);

test/windows/Plan9ProtocolTests.cpp:210

  • The comment says “return returns,” which is grammatically incorrect; please remove the duplicate verb.
    // Send a truncated tread and validate that the server return returns EINVAL.

test/windows/Plan9ProtocolTests.cpp:224

  • “Passed” is the wrong word here; the client ID extends past the end of the message.
    // Validate that the server rejects client ids that extend passed the end of the message.
  • Files reviewed: 15/15 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/linux/plan9/p9handler.cpp
Copilot AI review requested due to automatic review settings September 17, 2026 20:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Verbose Plan 9 logging can fail-fast on truncated TRead requests before validation returns an error response.

Review details

Suppressed comments (1)

src/linux/plan9/p9handler.cpp:1257

  • The new minimum-size check runs after LogMessage(). With verbose Plan9 logging enabled, TraceLogMessage parses Tread using fail-fast U64()/U32() calls, so this truncated request can terminate the server before it reaches the Rlerror path that the check is intended to provide. Move logging after this validation (or make every logging field read fallible) so malformed messages are rejected consistently regardless of log level.
        const auto messageSize = reader.U32(); // message size, already validated
        auto messageType = reader.U8();
        const auto messageTag = reader.U16();
        const SpanWriter errorWriter{response.Writer};

        LX_INT error{};

        if (const auto minimumMessageSize = GetMessageSize(static_cast<MessageType>(messageType));
            minimumMessageSize != 0 && messageSize < minimumMessageSize)
  • Files reviewed: 15/15 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI review requested due to automatic review settings September 17, 2026 21:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The tests use a fixed port and do not actually cover the truncated client-ID parsing path.

Review details

Suppressed comments (2)

Previously missed (2) — in code that hasn't changed since the last review.

test/windows/Plan9ProtocolTests.cpp:29

  • Using a fixed port makes these integration tests nondeterministically fail whenever another process or parallel test already owns 1234. Bind an ephemeral/dynamically selected port and report the actual port to the client test instead of hard-coding one.
    test/windows/Plan9ProtocolTests.cpp:278
  • This appends all 4096 bytes declared by the length field, so TryString() succeeds and the test only exercises the separate > 40 limit. It does not cover the claimed truncated-clientId case where the declared length extends past the message; add a request whose length exceeds the remaining payload while retaining a separate max-length test.
  • Files reviewed: 15/15 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI review requested due to automatic review settings September 17, 2026 21:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Three moderate issues remain unresolved: socket-path validation, failure-safe malformed-message logging, and hard-coded test-port allocation.

Review details

Suppressed comments (3)

src/linux/init/init.cpp:3386

  • --socket-path is accepted together with --bind, even though that path is only meaningful for the supplied server-fd mode. RunPlan9Server still retains the value and may unlink it during shutdown, so reject this combination (or clear the path) instead of silently accepting an invalid and potentially destructive configuration.
    if (BindPort.has_value() == static_cast<bool>(ServerFd) ||
        (BindPort.has_value() && (*BindPort <= 0 || *BindPort > std::numeric_limits<uint16_t>::max())))

src/linux/plan9/p9handler.cpp:1262

  • This logging call still runs outside the try block, and TraceLogMessage parses many variable-length fields with SpanReader::String(), whose bounds failure is FAIL_FAST() (for example a truncated Tversion). Thus a malformed message with a truncated string can terminate the Plan 9 server before it returns Rlerror, even though the handler is intended to reject malformed requests. Move logging inside the exception boundary or make every logger parse failure-safe before logging untrusted messages.
            LogMessage(reader.Span());

test/windows/Plan9ProtocolTests.cpp:29

  • This test always binds 127.0.0.1:1234, so it will fail whenever another process or concurrently running test owns that port. Please allocate a test-specific free port (and pass/observe that value) instead of relying on a hard-coded port.
    constexpr uint16_t c_plan9Port = 1234;
  • Files reviewed: 15/15 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI review requested due to automatic review settings September 17, 2026 22:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Unresolved moderate findings affect request logging and test reliability, and lock-handler coverage is incomplete.

Review details

Suppressed comments (4)

src/linux/plan9/p9handler.cpp:750

  • The new regression test only exercises HandleGetLock, while this change also adds the same truncated-string path to HandleLock. Add a malformed Tlock request assertion here so the second handler is protected from regressing independently.
        const auto clientId = reader.TryString();
        if (!clientId.Success)
        {
            return LX_EINVAL;
        }

src/linux/plan9/p9handler.cpp:1264

  • LogMessage still parses every variable-length field with SpanReader::String(), whose bounds failure calls FAIL_FAST() rather than throwing. A malformed request such as a truncated Tversion can satisfy the new fixed minimum-size check, reach this call, and abort the Plan 9 server before it can return Rlerror; make the logging parser bounds-safe (or otherwise validate dynamic fields before logging).
                LogMessage(reader.Span());

test/windows/Plan9ProtocolTests.cpp:29

  • This test always binds the distro's loopback port 1234, so it fails whenever another process or concurrently running test already owns that port. Please allocate an available port (for example, bind ephemerally and report the actual port) or otherwise reserve a collision-free endpoint for the test.
    constexpr uint16_t c_plan9Port = 1234;

test/windows/Plan9ProtocolTests.cpp:138

  • The bound port marker is printed immediately after the guest bind, but the WSL2 loopback relay can take time to expose that port to the host. Existing host-to-guest tests retry connect for this race (for example, test/windows/NetworkTests.cpp:1864-1881); making one connection attempt here can produce intermittent WSAECONNREFUSED failures in CI. Retry the connection with a bounded timeout after the marker.
        THROW_LAST_ERROR_IF(connect(server.client.get(), reinterpret_cast<SOCKADDR*>(&address), sizeof(address)) == SOCKET_ERROR);
  • Files reviewed: 15/15 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI review requested due to automatic review settings September 17, 2026 23:25

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Moderate issues remain around process-array coverage and collision-free test-port allocation.

Review details

Suppressed comments (4)

src/linux/init/config.cpp:1595

  • The function signature no longer accepts Common, but the routine header below still documents Common as its argument and omits the new buffer and offset parameters. Please update the parameter documentation so callers can understand which message regions each offset refers to.
EnvironmentBlock ConfigCreateEnvironmentBlock(
    gsl::span<gsl::byte> Buffer,
    unsigned int EnvironmentOffset,
    unsigned int NtEnvironmentOffset,
    unsigned int NtPathOffset,
    const wsl::linux::WslDistributionConfig& Config)

src/linux/init/init.cpp:927

  • This templated parser now receives a Message pointer, but its routine header still documents only Parsed, Buffer, and Config. That leaves the new source of the offsets and fixed fields undocumented; please add the Message parameter and update the description of Buffer accordingly.
template <typename TMessage>
int CreateProcessParseCommon(PCREATE_PROCESS_PARSED_COMMON Parsed, gsl::span<gsl::byte> Buffer, const TMessage* Message, const wsl::linux::WslDistributionConfig& Config)

src/windows/service/exe/LxssCreateProcess.h:116

  • The new array encoding is used for every normal and utility-VM process launch, but the added tests exercise only Plan 9 messages and do not cover creating/parsing an LX_INIT_CREATE_PROCESS message with command-line and environment entries. A serialization mismatch here would break all process launches while existing end-to-end launch tests may not identify which array is malformed; please add a focused round-trip/integration case covering multiple and empty arrays.
        message.WriteStringArray(message->CommandLineOffset, commandLine.data(), commandLine.size());
        message.WriteStringArray(message->EnvironmentOffset, environment.data(), environment.size());
        message.WriteStringArray(message->NtEnvironmentOffset, ntEnvironment.data(), ntEnvironment.size());

test/windows/Plan9ProtocolTests.cpp:29

  • This test always binds the ad-hoc server to guest port 1234. Any process already using that port makes bind() fail, so the test then waits for a startup line that can never be emitted and fails nondeterministically on shared or busy test environments. Please use an ephemeral/allocated port (and report the actual bound port to the test) or otherwise reserve a collision-free port for each test instance.
    constexpr uint16_t c_plan9Port = 1234;
  • Files reviewed: 16/16 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI review requested due to automatic review settings September 17, 2026 23:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The protocol tests use a fixed port, causing failures when that port is already occupied.

Review details

Suppressed comments (1)

test/windows/Plan9ProtocolTests.cpp:29

  • This test hard-codes 127.0.0.1:1234, so it fails whenever another process or concurrently running WSL test owns that port. Please allocate an ephemeral port (and report/use the port returned by bind) or otherwise choose a free port so the protocol tests do not depend on the host environment.
    constexpr uint16_t c_plan9Port = 1234;
  • Files reviewed: 16/16 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@OneBlue

Copy link
Copy Markdown
Collaborator Author
  • This test hard-codes 127.0.0.1:1234, so it fails whenever another process or concurrently running WSL test owns that port. Please allocate an ephemeral port (and report/use the port returned by bind) or otherwise choose a free port so the protocol tests do not depend on the host environment.

That's fine, the tests do this in many places

@OneBlue
Blue (OneBlue) marked this pull request as ready for review September 17, 2026 23:45
@OneBlue
Blue (OneBlue) requested a review from a team as a code owner September 17, 2026 23:45
wsl::shared::MessageWriter<CREATE_PROCESS_MESSAGE> message(LxInitCreateProcess);
message.WriteString(message->PathIndex, Path);
gsl::copy(as_bytes(gsl::span(ArgumentsData)), message.InsertBuffer(message->CommandLineIndex, ArgumentsData.size()));
message.WriteStringArray(message->CommandLineIndex, Arguments, argumentCount);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks a lot simpler than the former code!

@benhillis
Ben Hillis (benhillis) merged commit d49f455 into master Sep 18, 2026
12 checks passed
@benhillis
Ben Hillis (benhillis) deleted the user/oneblue/fix-parsing-bugs branch September 18, 2026 21:42
Blue (OneBlue) added a commit that referenced this pull request Sep 22, 2026
* Fix tracked routes being collapsed by incomplete comparison (#41393)

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.

* Add github issue suggestion in user visible error (#41432)

This PR adds a "search or file issue on github" suggestion in all user visible errors to:
Help users find solutions faster.
Collect more user reported issues to help reliability improvements.

This PR also updates all tests checking the error message to use a unified function for creating the expected error message.

* Match Docker output for prune operations and container inspection (#41430)

Cleanup various miscellaneous output divergences

Co-authored-by: Copilot <[email protected]>

* CLI: Mount PR followup & fix two docker parser bugs (#41436)

* Invalid the TestImageRegistry cache after running prune --all (#41442)

* Fix unit test build failure on arm64 (#41437)

* Solve various issues found by verifier (#41445)

* Save state

* Save state

* Save state

* Cleanup diff

* Add a command line option to run the tests under verifier  (#41440)

* Save state

* Save state

* Save state

* Add a /verifier option to run-tests.ps1 to run the test under verifier

* Localization change from build: 155859879 (#41450)

Co-authored-by: WSL localization <[email protected]>

* Fix various arm64 test failures (#41444)

* Fix various arm64 test failures

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

* Fix LF

* Format

* Cleanup diff

---------

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

* Fix unity build ODR collisions on duplicate file-local constants (#41446)

* CLI: Align alias listing with docker, Apple and other CLIs (#41439)

* Align container list format with Docker specifications (#41375)

wslc: match column order, status text, and json shape for container list


Co-authored-by: Copilot <[email protected]>

* Localization change from build: 156161979 (#41479)

Co-authored-by: WSL localization <[email protected]>

* wslc: alias -f to --format on inspect commands for docker parity (#41463)

Co-authored-by: Copilot <[email protected]>

* CLI: Add explicit per-command argument overrides (#41478)

* archlinux: Release 2026.09.01.176721 (#41493)

This is an automated release [1].

[1] https://gitlab.archlinux.org/archlinux/archlinux-wsl/-/blob/main/.gitlab-ci.yml

* Fix WSLC parser unit test argument overrides (#41496)

Update the remaining parser test call site to use ArgumentOverrides after the Argument::Create API change.

Co-authored-by: Copilot <[email protected]>

Co-authored-by: Ben Hillis <[email protected]>
Copilot-Session: eb7946ff-cc0b-4ff1-a059-571334b1c988

* Fix systemd-tmpfiles failure on systemd v261+ with systemd boot disabled (#41491)

In systemd v261, the systemd's tmpfiles.d/x11.conf was changed from D! to D. systemd/systemd@5474cad.
This means the systemd-tmpfiles command will try to execute it when called out of the boot sequence. In the linked issue's case, it's called by the post install script by dpkg. This will fail as the wsl override is not in place when systemd is disabled.

This PR enables the wsl override file generation for all distros with wslg enabled, regardless of if the distro boots with systemd.

* Fix unvalidated TerminalProfileSize during distribution import (#41495)

* Fix unvalidated TerminalProfileSize when importing a distribution

_ProcessImportResultMessage constructed the terminal profile string_view
using the message-supplied TerminalProfileSize without validating it
against the received buffer length. Use the bounds-checked two-argument
span::subspan() overload (matching the existing ShortcutIconSize handling
a few lines above) so an inconsistent size value throws instead of
producing a string_view that runs past the end of the buffer.

Co-authored-by: Copilot <[email protected]>
Copilot-Session: 35281c30-3d08-4f05-8c84-2ce4711023d5

* format source

---------

Co-authored-by: Ben Hillis <[email protected]>
Co-authored-by: Copilot <[email protected]>
Copilot-Session: 35281c30-3d08-4f05-8c84-2ce4711023d5

* Bump WSL DeviceHost to 1.2.62 (#41499)

* Bump WSL DeviceHost to 1.2.62

Co-authored-by: damanm24 <[email protected]>

* Correct WSL DeviceHost version to 1.2.62-0

Co-authored-by: damanm24 <[email protected]>

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: damanm24 <[email protected]>

* Enable unity build repo-wide via WSL_UNITY_BATCH_SIZE (#41441)

Enable unity build repo-wide via WSL_UNITY_BATCH_SIZE

Co-authored-by: Copilot <[email protected]>

* Add wslc system info command (#41408)

* updated source code paths in the wslservice tab (#41509)

Co-authored-by: Tega Ajise <[email protected]>

* Harden Windows macros against dangling-else ambiguity (#41513)

* Harden Windows macros against dangling-else ambiguity

* Harden Windows macros against dangling-else ambiguity

* Fix dangling-else bugs in FAIL_FAST_IF and EMIT_USER_WARNING macros (#41504)

* Fix dangling-else bugs in FAIL_FAST_IF and EMIT_USER_WARNING macros  

Both macros were bare if-statements without do/while(0) guards, causing
the dangling else problem when used as a single statement under an if.

* Fix dangling-else bugs in FAIL_FAST_IF and EMIT_USER_WARNING macros

* harden EMIT_USER_WARNING macro on Windows against dangling-else

* Fix dangling-else bugs in FAIL_FAST_IF and EMIT_USER_WARNING macros

* Fix intermittent ImportDistroInvalidTar test failures (#41490)

* Fix test to be more resilient

* Make WSL1 more lenient, make WSL2 exact

* Wslc events (#40971)

* Revert "Mount plugin folders on behalf of the user owning the wsl session" (#41331) (#41515)

Temporarily reverting the identity-based plugin folder mount change
(both the WslCoreVm.cpp behavior change and the accompanying
MountFolderAccess test coverage) introduced in #41331.

This reverts commit 78b9cf2.

Co-authored-by: Ben Hillis <[email protected]>
Co-authored-by: Copilot <[email protected]>

* Add container restart runtime support (#41454)

* Fix p9 drvfs read only mount regression (#41487)

#41129 introduces a regression where the ";ro" option is passed to the host for p9 shares. However, that option is not supported by the p9 server and causes the mount to fail.

This PR removes the special handling of "ro" in the common parser. And use MountParseFlags to add the required virtio option.

* Fix WSLC Plan9 mount and image-build failures (#41535)

* Fix WSLC Plan9 mounts using a per-user server

* remove debug code

* wslc: add --size to inspect for docker parity (#41489)

Co-authored-by: Copilot <[email protected]>

* Bump actions/deploy-pages in the github-actions group (#41537)

Bumps the github-actions group with 1 update: [actions/deploy-pages](https://github.com/actions/deploy-pages).


Updates `actions/deploy-pages` from 5.0.0 to 5.0.1
- [Release notes](https://github.com/actions/deploy-pages/releases)
- [Commits](actions/deploy-pages@cd2ce8f...368f825)

---
updated-dependencies:
- dependency-name: actions/deploy-pages
  dependency-version: 5.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Add wslc container restart command (#41435)

* init: fix dhcpcd option name in bridged-mode config (#41538)

* init: fix dhcpcd option name in bridged-mode config

dhcpcd has no option named "broadcast"; option 28 is "broadcast_address".
dhcpcd 10 rejects the whole "option" line, so DNS servers, domain, search
list, hostname and MTU were never requested from the DHCP server, leaving
/mnt/wsl/resolv.conf without nameservers on servers that honour the PRL.

* init: apply clang-format to dhcpcd config string

The longer broadcast_address option name pushed the literal past the
130-column limit in .clang-format. Split it as clang-format does; the
concatenated value is unchanged.

* Update SLE15SP7 [QU5] (#41506)

* Host plugin Plan9 shares as the session user (#41548)

* Host plugin Plan9 shares as the session user

Use a dedicated per-user Plan9 server for plugin folder mounts so host filesystem permissions are preserved without relying on HCS-managed share identity.

Co-authored-by: Copilot <[email protected]>

Copilot-Session: c20b1da0-c613-489d-92a3-9c27527c0c54

* Simplify plugin Plan9 port plumbing

Use the fixed plugin port directly in mini_init and mirror the existing per-user Plan9 server lifecycle.

Co-authored-by: Copilot <[email protected]>

Copilot-Session: c20b1da0-c613-489d-92a3-9c27527c0c54

* Recreate stopped plugin Plan9 servers

Recreate the per-user server before adding a share when its process is no longer running.

Co-authored-by: Copilot <[email protected]>

Copilot-Session: c20b1da0-c613-489d-92a3-9c27527c0c54

---------

Co-authored-by: Ben Hillis <[email protected]>
Copilot-Session: c20b1da0-c613-489d-92a3-9c27527c0c54

* Fix virtiofs bind mounts exposing files as root-owned (#40719) (#40733)

* Fix virtiofs bind mounts exposing files as root-owned (#40719)

Add the 'metadata' option to virtiofs shares created via
HcsVirtualMachine::AddShare (the WSLC/Docker container path). Without
this option, the virtiofs device host cannot persist per-file uid/gid
in NTFS extended attributes, so all files default to uid=0/gid=0
regardless of the creating user.

This matches the behavior of the regular distro mount path
(WslCoreVm::AddVirtioFsShare) which receives metadata/uid/gid options
from the Linux init's ConvertDrvfsMountOptionsToPlan9.

Also adds a regression test (WindowsMountsVirtioFsFileOwnership) that
verifies file ownership is preserved on virtiofs mounts.

Fixes #40719

Co-authored-by: Copilot <[email protected]>

* Address code review feedback

- Add inline comment explaining why 'metadata' is required
- Use unique mount point (/virtiofs-ownership-test) to avoid test interference
- Use numeric UID (su '#65534') instead of username to avoid environment dependency

Co-authored-by: Copilot <[email protected]>

* test: use 'nobody' user instead of numeric UID in virtiofs ownership test

The su command with numeric UID syntax ('#65534') requires the user to
exist in /etc/passwd. Use the 'nobody' account directly since it is
already available in the test VHD.

Co-authored-by: Copilot <[email protected]>

* fix: wrap long test command strings to satisfy clang-format 130-col limit

Co-authored-by: Copilot <[email protected]>

* test: unmount inline with VERIFY_SUCCEEDED to match file convention

Replace the scope_exit unmount cleanup with an inline VERIFY_SUCCEEDED
call at the end of the test, matching every other mount test in this
file (e.g. WindowsMountsVirtioFsShareReuse). This also asserts the
unmount HRESULT rather than silently swallowing it.

Co-authored-by: Copilot <[email protected]>
Copilot-Session: 9213b7da-c5c8-4d9c-89ab-e80048d288a2

* Fix Windows mount test API calls

Co-authored-by: Copilot <[email protected]>

---------

Co-authored-by: Copilot <[email protected]>
Co-authored-by: Blue <[email protected]>
Copilot-Session: 9213b7da-c5c8-4d9c-89ab-e80048d288a2

* wslc: match docker prune semantics (confirmation prompt, -f aliases --force) (#41455)

Co-authored-by: Copilot <[email protected]>

* wslc: add --all to image list for docker parity (#41456)

Co-authored-by: Copilot <[email protected]>

* wslc: add --details to container logs for docker parity (#41467)

Co-authored-by: Copilot <[email protected]>
Co-authored-by: JohnMcPMS <[email protected]>

* Localization change from build: 157218885 (#41559)

Co-authored-by: WSL localization <[email protected]>

* Don't fail the installation if DeprovisionMsix() fails (#41453)

* Don't fail the installation if DeprovisionMsix() fails

* Apply PR feedback

* Notice change from build: 157227119 (#41564)

Co-authored-by: WSL notice <[email protected]>

* wslc: add --size to container list for docker parity (#41477)

Co-authored-by: Copilot <[email protected]>

* wslc: add --all-tags to push for docker parity (#41500)

Co-authored-by: Copilot <[email protected]>

* Fix build issue for wslsettings, and add more logging to the pipelines (#40388)

* Validate variable-length message strings (#41567)

Co-authored-by: Copilot <[email protected]>

Co-authored-by: Ben Hillis <[email protected]>
Copilot-Session: 3086bdaf-bc43-4fed-88d1-3a95a21fd14e

* Fix WSLC fallback gateway collision (#41547)

Avoid selecting the guest IPv4 address as its synthesized default gateway when the host adapter does not expose one.

Co-authored-by: Copilot <[email protected]>

Co-authored-by: Ben Hillis <[email protected]>
Copilot-Session: ce168659-cb9d-4f0e-8fd1-2834d065ba9d

* Reduce distro termination log noise (#41541)

Co-authored-by: Copilot <[email protected]>

Co-authored-by: Ben Hillis <[email protected]>
Copilot-Session: adf24228-67c0-452e-9cc2-c698a8d7b3b7

* Localization change from build: 157277214 (#41571)

Co-authored-by: WSL localization <[email protected]>

* CLI: Add global options to root help, adjust options usage (#41534)

* Add global options to root help, adjust options usage to match CLI conventions

* Trim some unnecessary test code

* Localization change from build: 157310027 (#41574)

Co-authored-by: WSL localization <[email protected]>

* wslc: add docker --quiet to image load, image push and container cp (#41466)

Co-authored-by: Copilot <[email protected]>

* Tear down the stale plugin Plan9 server before recreating it (#41565)

When the per-user plugin Plan9 server is no longer running, the previous instance was dropped without a Teardown call, so it could still hold the Plan9 port when the replacement tries to bind it.

Co-authored-by: Ben Hillis <[email protected]>
Co-authored-by: Copilot <[email protected]>
Copilot-Session: 0d028ad4-fe5e-4ef1-9832-18ee0e4825cc

* Use a locally imported version of docker/dockerfile instead of downloading it from the default registry (#41575)

* Use a locally imported version of docker/dockerfile instead of downloading it from the default registry

* Cleanup diff

* Use canonical path in VolumeMount_Parse_ReturnExpectedResult (#41577)

* Document WSL security model (#41556)

* Document WSL security model

Clarify WSL trust boundaries and explain that configuration settings do not establish a sandbox.

Co-authored-by: Copilot <[email protected]>

Copilot-Session: c77eaf09-799a-416e-b4b4-19f37a4201ef

* Update WSL security model explanation

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

* Clarify WSL isolation guidance

Distinguish functional distribution separation from a security boundary and recommend a separately managed VM for untrusted workloads.

Co-authored-by: Copilot <[email protected]>

Copilot-Session: c77eaf09-799a-416e-b4b4-19f37a4201ef

* Document shared WSL VM trust model

Clarify that elevated and non-elevated sessions can share utility VM state and are not separate guest security boundaries.

Co-authored-by: Copilot <[email protected]>

Copilot-Session: c77eaf09-799a-416e-b4b4-19f37a4201ef

---------

Co-authored-by: Ben Hillis <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
Copilot-Session: c77eaf09-799a-416e-b4b4-19f37a4201ef

* Bump GitPython to 3.1.59 (#41580)

Resolves open Dependabot alerts for GitPython <= 3.1.58 in
distributions/requirements.txt and tools/devops/requirements.txt.

Co-authored-by: Ben Hillis <[email protected]>
Co-authored-by: Copilot <[email protected]>
Copilot-Session: 6fcfe0f1-6be5-4913-ab36-71823443cc36

* Remove two noisy warnings from the distro validation scripts (#41579)

* Remove two noisy warnings from the distro validation scripts

* Cleanup diff

* Fix formatting of USR_SHARE_WSL assignment

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

---------

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

* Fix activating a stopping service treated as OOM (#41460)

The current factory function for LxssUserSession and WSLCSessionManager translates the error code CO_E_SERVER_STOPPING to S_FALSE. Which combined with *ppCreated == NULL causes COM to treat this as an OOM. Leading to error messages like this when activating a stopping service:

Not enough memory resources are available to complete this operation.
Error code: Wsl/E_OUTOFMEMORY
This PR removes this conversion. So, COM actually retries when the service is stopping. And returns CO_E_SERVER_EXEC_FAILURE if the retry times out.

* Set distributionStartTimeout to 2 minutes in the tests to solve distribution start timeouts errors (#41583)

* Set distributionStartTimeout to 2 minutes in the tests to solve distribution start timeouts errors

* Update tests

* Localization change from build: 157504221 (#41602)

Co-authored-by: WSL localization <[email protected]>

* Enable RedirectionGuard process mitigation (#41542)

Co-authored-by: Ben Hillis <[email protected]>
Co-authored-by: Copilot <[email protected]>

* Updates Ubuntu latest LTS images (#41465)

* Updates Ubuntu 26.04 to the .1 release

Just announced today.
Also published the up-to-date Ubuntu package to MS Store,
but I'm not referencing it here.

* Updates the 24.04.5 images just released today.

* Use the cdimages.u.c host for consistency

---------

Co-authored-by: Carlos Nihelton <[email protected]>

* diagnostics: improve collect-wsl-logs for analysis (summary.json, README, profile info, WSL/guest state) (#40776)

* diagnostics: record capture profile in collected logs

collect-wsl-logs.ps1 did not record which WPR profile was used for a
capture. When analyzing an archive (e.g. a networking-only capture that
lacks the WSL core trace providers), there was no way to tell which
profile produced it without inferring it from the provider mix.

Write a collection-info.txt into the log folder capturing the selected
LogProfile, the mapped WPRP profile and file, the Dump and
RestartWslReproMode switches, and the collection timestamp.

Co-authored-by: Copilot <[email protected]>

* diagnostics: collect WSL version, guest state, and drop empty dumps

Add three further debugging improvements to collect-wsl-logs.ps1:

- Collect wsl --version / --status / --list --verbose into wsl-info.txt
  instead of forcing analyzers to infer the version and distro layout
  from the appx package and registry.
- Collect guest-side state (dmesg, free, uptime, ulimit, pid_max,
  threads-max, process/thread counts, top RSS) into linux_diagnostics.log
  after the repro. This is the data needed to diagnose in-distro failures
  such as 'Resource temporarily unavailable' (EAGAIN) from resource limits.
- Remove 0-byte dump files left behind when MiniDumpWriteDump fails, so
  the archive only contains real dumps.

Also set WSL_UTF8 and the console output encoding so wsl.exe output is
captured to the log files readably.

Co-authored-by: Copilot <[email protected]>

* diagnostics: add summary.json and README.md to log archive

Make collected log archives easier to analyze (by a human or an agent)
without having to run tools or infer state from individual artifacts:

- summary.json: machine-readable overview of the capture - profile,
  WSL/Windows versions, networking mode, installed distributions and
  their state, .wslconfig presence, and an inventory of non-empty dumps.
- README.md: an index of the archive contents describing each file, plus
  a note on how to decode logs.etl and how to tell when a non-default
  log profile was used.

Co-authored-by: Copilot <[email protected]>

* diagnostics: address PR feedback (utf8 wsl-info, wsl.exe timeouts, slimmer summary.json)

- Write wsl-info.txt as UTF-8 instead of the PS5.1 default UTF-16LE.
- Guard every newly-added wsl.exe call (wsl-info and guest diagnostics) with a
  timeout via a background job so a deadlocked service or bad VM state cannot
  hang log collection.
- Drop the duplicated distro-registry enumeration and .wslconfig networkingMode
  parsing from summary.json; that state is readily derived from HKCU.txt and the
  archived .wslconfig.

Co-authored-by: Copilot <[email protected]>

* diagnostics: drop wsl-info.txt and guest diagnostics collection

Remove the unconditional wsl.exe calls this PR introduced (wsl-info.txt and
linux_diagnostics.log) along with the now-unused timeout helper, per review
feedback that the log collection script should not call wsl.exe (which can hang
if the service is deadlocked or the VM is in a bad state). Pre-existing
networking-profile wsl.exe calls are left untouched.

Co-authored-by: Copilot <[email protected]>

* collect-wsl-logs: drop bundled summary.json and README per review

OneBlue noted the agent-readable index and the summary values are redundant
in every archive (an analyzer can derive them from the archive contents).
Keep only collection-info.txt, which records non-derivable capture provenance
(which WPR profile/switches were used).

Co-authored-by: Copilot <[email protected]>

---------

Co-authored-by: Ben Hillis <[email protected]>
Co-authored-by: Copilot <[email protected]>

* Move security model under technical documentation (#41605)

* Move security model under technical documentation

Co-authored-by: Copilot <[email protected]>

Copilot-Session: 43c7b692-ffc5-43bf-88b9-ecc927a1aa55

* Move security model into technical documentation

Co-authored-by: Copilot <[email protected]>

Copilot-Session: 43c7b692-ffc5-43bf-88b9-ecc927a1aa55

---------

Co-authored-by: Ben Hillis <[email protected]>
Copilot-Session: 43c7b692-ffc5-43bf-88b9-ecc927a1aa55

* Fix typos (#41589)

* Don't stop parsing linux config files on invalid lines (#41606)

* wslc: add --all-tags to pull for docker parity (#41494)

Co-authored-by: Copilot <[email protected]>

* Added WSL container to OOBE (#41402)

* Pre merge Localization strings prior to GA (#41585)

Co-authored-by: Copilot <[email protected]>

* wslc: keep image list json CreatedSince locale-invariant (#41609)

Co-authored-by: Copilot <[email protected]>

* Localization change from build: 157621275 (#41610)

Co-authored-by: WSL localization <[email protected]>

* Warn on an escaped CR in wsl.conf instead of dropping it silently (#41591)

`case '\r': break;` made a backslash before a CR the only unrecognised
escape the parser accepts without a diagnostic. In a CRLF file that left
the value truncated at the backslash and the remainder parsed as its own
line, with nothing reported.

Letting it fall into the default case gives the same
MessageConfigInvalidEscape warning as any other bad escape. As with those,
the line is then discarded rather than kept truncated.

* Localization change from build: 157667513 (#41614)

Co-authored-by: WSL localization <[email protected]>

* Set a restricted ephemeral port range for test case ConsommeTests::PortZeroBindIsTracked (#41616)

* repo: modify CODEOWNERS to change wsl-maintainers to wsl-reviewers team (#41617)

Co-authored-by: Ben Hillis <[email protected]>

* Localization change from build: 157736413 (#41621)

Co-authored-by: WSL localization <[email protected]>

* CLI: Global option scopes for nested commands (related to compose support) (#41546)

* Change default relay  buffer size to 64KiB (#41603)

The current logic uses a fixed 4KiB buffer for stdio relay on the Windows side. And uses an initial 4KiB buffer for stdio relay on the Linux side, which grows only if the message won't fit. This can severely limit the relay performance in some situations. For example, in #41572, when redirecting stdout to a SMB share.

This PR increases thedefault relay buffer size to 64KiB. Which shows significant performance improvements according to buffer size tests.

* Fix redirect stdout and stderror to the same file overlapping (#41611)

Currently the stdout and stderr relay tracks the output offset separately. And when redirected to the same file, the writes could overlap.

This PR uses the append mode for overlap io writes instead of the separate offsets in the relay. So, the file write offset is correctly tracked by the system.

* move installer log collection after repro (#41620)

The installer log files were collected before the log collection starts. Which will miss the user repro.

This PR moves it after the user repro.

* wslc: add --digests to image list for docker parity (#41457)

Co-authored-by: Copilot <[email protected]>

* Localization change from build: 157843092 (#41630)

Co-authored-by: WSL localization <[email protected]>

* Explicitely return SOCKET from WSLCPluginAPI_ProcessGetFd() (#41626)

* In mirrored mode, handle route update as add instead of replace (#41391)

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 <[email protected]>

* Add wslc events command (#41608)

* Don't fail the UnitTests::Warnings test case if GlobalSecureAccess VPN is running (#41638)

* Don't fail the UnitTests::Warnings test case if GlobalSecureAccess VPN is running

* Cleanup diff

* Fix test

* Wait for wslservice to be started when running tests (#41639)

* Wait for wslservice to be started when running tests

* Fail on timeout

* Improve check

* Format

* Create new namespaces for distro cgroups (#41512)

In 2.9.8, the distro processes are separated into their own cgroups. But they remain in the same cgroup namespace. That caused compatibility issues with softwares that assume a fixed systemd cgroup layout. For example, rootless docker and nerdctl.
Fixes on Moby and nertctl are being worked on. However, to avoid issues with other software, WSL's cgroup handling should also be improved.

This PR creates new cgroup namespaces for the distros. So, to the non-critical distro processes, the systemd cgroup layout stays the same as before.
This PR also introduces a cgroup structure change to accomplish this. The systemd init is moved from wsl-user/distro-N/systemd to wsl-user/distro-N. And the initialization of the distro-N controllers is handled by systemd instead.
The processes are also moved into the non-systemd cgroup in systemdless distros. This makes sure that sub-group controllers can be enabled in the distro root.
Cgroup v2 is now enforced when distro isolation is enabled. Instead of constructing an unusable cgroup v1 layout when cgroup v1 and distro isolation are both enabled.

* Fix unnecessary delay in the port tracking loop (#41472)

Before this change, an additional 10ms delay was added in the port tracker loop presumably to make the main loop slower than the worker loop. So, the worker result does not get super dated. This is not reliable. And the 10ms delay also slows down every consecutive bind call.

This PR refactors the thread synchronization method. So, the timing between those two loops is more deterministic. And removes the performance penalty for all bind calls.

* Localization change from build: 157954210 (#41643)

Co-authored-by: WSL localization <[email protected]>

* wslc: add --follow-link to cp (#41501)

Co-authored-by: Copilot <[email protected]>

* Disable unstable bind cap test and re-enable Loopback test that was incorrectly disabled- #41648 (#41648)

Co-authored-by: Catalin-Emil Fetoiu <[email protected]>

* Move objects shared by wslc.exe and the tests to src/windows/common (#41619)

* Move objects shared by wslc.exe and the tests to src/windows/common

Co-authored-by: Copilot <[email protected]>

* Link yaml-cpp, advapi32 and Crypt32 into common

Co-authored-by: Copilot <[email protected]>

* Drop yaml-cpp, advapi32 and crypt32 from wslclib now that common provides them

Co-authored-by: Copilot <[email protected]>

* Move wslc code in common under common/wslc and namespace CLI types as wslc::cli

Co-authored-by: Copilot <[email protected]>

---------

Co-authored-by: Copilot <[email protected]>

* Fix various protocol parsing issues (#41637)

* Save state

* Use proper arrays

* Format

* Add new tests

* Cleanup tests

* Cleanup diff

* Format

* Apply PR feedback

* Apply PR feedback

* Format

* Apply PR feedback

* Move logging call

* Apply PR feedback

* Apply PR feedback

* Localization change from build: 157980831 (#41647)

Co-authored-by: WSL localization <[email protected]>

* Add WSLC network lifecycle events (#41576)

* Add WSLC network lifecycle events

* Localize pending network prune errors

* Fix network operation wait ownership and cleanup ordering

* Fix prune event correlation after timed-out

* Fix network event rollback and timeout recovery

* Format

* Forward Docker network events directly

* Restore lock_guard after removing event waits

* fix test

* align event stream test helpers after merge

* feedback

* Fix potential out of bound access when pretty-printing string field in init messages (#41664)

* Localization change from build: 158197536 (#41662)

Co-authored-by: WSL localization <[email protected]>

---------

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: Feng Wang <[email protected]>
Co-authored-by: ggarzia-MSFT <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: David Bennett <[email protected]>
Co-authored-by: WSL localization <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
Co-authored-by: beena352 <[email protected]>
Co-authored-by: Arch Linux Technical User <[email protected]>
Co-authored-by: Ben Hillis <[email protected]>
Co-authored-by: Ben Hillis <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: damanm24 <[email protected]>
Co-authored-by: tega-ajise <[email protected]>
Co-authored-by: Tega Ajise <[email protected]>
Co-authored-by: Eamon <[email protected]>
Co-authored-by: Kevin Vega <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: DesertRatUa <[email protected]>
Co-authored-by: Scott Bradnick <[email protected]>
Co-authored-by: Stephen Halter <[email protected]>
Co-authored-by: JohnMcPMS <[email protected]>
Co-authored-by: Flor Chacón <[email protected]>
Co-authored-by: Carlos Nihelton <[email protected]>
Co-authored-by: Carlos Nihelton <[email protected]>
Co-authored-by: Anton Kesy <[email protected]>
Co-authored-by: Craig Loewen <[email protected]>
Co-authored-by: Leo Camus <[email protected]>
Co-authored-by: FetoiuCatalin <[email protected]>
Co-authored-by: Catalin-Emil Fetoiu <[email protected]>
Copilot-Session: eb7946ff-cc0b-4ff1-a059-571334b1c988
Copilot-Session: 35281c30-3d08-4f05-8c84-2ce4711023d5
Copilot-Session: c20b1da0-c613-489d-92a3-9c27527c0c54
Copilot-Session: 9213b7da-c5c8-4d9c-89ab-e80048d288a2
Copilot-Session: 3086bdaf-bc43-4fed-88d1-3a95a21fd14e
Copilot-Session: ce168659-cb9d-4f0e-8fd1-2834d065ba9d
Copilot-Session: adf24228-67c0-452e-9cc2-c698a8d7b3b7
Copilot-Session: 0d028ad4-fe5e-4ef1-9832-18ee0e4825cc
Copilot-Session: c77eaf09-799a-416e-b4b4-19f37a4201ef
Copilot-Session: 6fcfe0f1-6be5-4913-ab36-71823443cc36
Copilot-Session: 43c7b692-ffc5-43bf-88b9-ecc927a1aa55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants