Skip to content

virtiofs: update logic so querying virtiofs mount source does not require a call to the service#14380

Merged
benhillis merged 5 commits intomasterfrom
user/benhill/virtiofs_query_local
Mar 13, 2026
Merged

virtiofs: update logic so querying virtiofs mount source does not require a call to the service#14380
benhillis merged 5 commits intomasterfrom
user/benhill/virtiofs_query_local

Conversation

@benhillis
Copy link
Member

This avoids a call back to the service and will make it easier to do virtiofs to windows directory mapping. There is an upcoming change to the Linux plan9 server that will use this information to present drvfs / plan9 / virtiofs shares as symlinks so the Windows client can traverse them (current we return access denied in this case).

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates virtiofs mount-source resolution so Linux can map a virtiofs tag to its Windows source path without making a query call back into the Windows service, enabling future work to represent drvfs/plan9/virtiofs shares as symlinks for Windows traversal.

Changes:

  • Remove the LxInitMessageQueryVirtioFsDevice IPC message and its Windows service handler.
  • Persist a tag→source mapping on the Linux side via symlinks under /run/wsl/virtiofs during mount/remount.
  • Update QueryVirtiofsMountSource to resolve mount sources by reading the persisted symlink instead of calling the service.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
src/windows/service/exe/WslCoreVm.cpp Removes handling for the virtiofs “query source by tag” message.
src/shared/inc/lxinitshared.h Removes the query message type and its message struct from the shared IPC contract.
src/linux/init/drvfs.cpp Adds symlink-based persistence of virtiofs tag→source mapping and uses it to resolve mount sources locally.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +73 to +86
std::string CanonicalSource{Source};
UtilCanonicalisePathSeparator(CanonicalSource, PATH_SEP_NT);

UtilMkdirPath(VIRTIOFS_TAG_DIR, 0755);

auto LinkPath = std::format("{}/{}", VIRTIOFS_TAG_DIR, Tag);

//
// Remove any existing symlink for this tag before creating a new one.
//

unlink(LinkPath.c_str());
if (symlink(CanonicalSource.c_str(), LinkPath.c_str()) < 0)
{
Copy link

Copilot AI Mar 8, 2026

Choose a reason for hiding this comment

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

SaveVirtiofsTagMapping uses Tag to build a filesystem path and then calls unlink() on it, but it never validates that Tag is a GUID/safe filename. If Tag ever contains '/' or '..' (e.g., due to a malformed/malicious host response), this can lead to path traversal and unintended file deletion outside /run/wsl/virtiofs. Validate Tag (same GUID check as QueryVirtiofsMountSource) before constructing LinkPath, and refuse to write mappings for invalid tags.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think that would be a good idea, at least we could fail if we see a / or a . in the target

Copy link
Member Author

Choose a reason for hiding this comment

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

Since we expect a GUID, I will just check for that

Copy link
Member Author

Choose a reason for hiding this comment

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

This feedback is stale, I already ensure the tag is a guid:

    //
    // Validate the tag is a GUID to prevent path traversal.
    //

    const auto Guid = wsl::shared::string::ToGuid(Tag);
    if (!Guid)
    {
        LOG_WARNING("Invalid virtiofs tag {}", Tag);
        return;
    }

@benhillis benhillis force-pushed the user/benhill/virtiofs_query_local branch 3 times, most recently from d63b77c to b05c97f Compare March 8, 2026 18:47
@benhillis benhillis requested a review from Copilot March 8, 2026 19:04
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (1)

src/windows/service/exe/WslCoreVm.cpp:2634

  • The service no longer handles the virtiofs query message. If an older guest init sends the legacy query (e.g., after host update but before guest/init update), this will now throw and tear down the request. To preserve mixed-version compatibility, consider keeping a handler that responds (even if implemented via the new mapping logic or by returning an explicit error code) rather than throwing on an unexpected MessageType.
                else
                {
                    THROW_HR_MSG(E_UNEXPECTED, "Unexpected MessageType %d", message->MessageType);
                }

You can also share your feedback on Copilot code review. Take the survey.

@benhillis benhillis force-pushed the user/benhill/virtiofs_query_local branch from b05c97f to 74f3165 Compare March 9, 2026 16:04
@benhillis benhillis requested a review from Copilot March 9, 2026 16:07
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.


You can also share your feedback on Copilot code review. Take the survey.

@benhillis benhillis force-pushed the user/benhill/virtiofs_query_local branch from 43fbefe to 8c104c7 Compare March 9, 2026 17:29
@benhillis benhillis requested a review from Copilot March 9, 2026 21:24
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (1)

src/windows/service/exe/WslCoreVm.cpp:2634

  • Dropping handling for the legacy virtiofs query message means an older guest sending LxInitMessageQueryVirtioFsDevice will now hit the "Unexpected MessageType" path and fail the request. If backwards compatibility is required, keep a handler for this message type (even if new guests no longer use it) and respond using existing in-memory share state (e.g., FindVirtioFsShare).
                else
                {
                    THROW_HR_MSG(E_UNEXPECTED, "Unexpected MessageType %d", message->MessageType);
                }

You can also share your feedback on Copilot code review. Take the survey.

OneBlue
OneBlue previously approved these changes Mar 11, 2026
Copy link
Collaborator

@OneBlue OneBlue left a comment

Choose a reason for hiding this comment

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

LGTM. I think I would have a preference for the mappings to be stored in a place where the users can't write (like a map in init), but that would be a bigger change so I think this OK

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (1)

src/windows/service/exe/WslCoreVm.cpp:2634

  • VirtioFsWorker no longer handles LxInitMessageQueryVirtioFsDevice and will now treat it as an unexpected message type. If an older guest/init (or any out-of-tree component) still sends this query, requests will start failing with E_UNEXPECTED. Consider keeping the handler for backward compatibility (even if new guests no longer use it), or at least returning a structured error response instead of throwing.
                else if (message->MessageType == LxInitMessageRemountVirtioFsDevice)
                {
                    std::wstring newTag;
                    const auto result = wil::ResultFromException([this, span, &newTag]() {
                        const auto* remountShare = gslhelpers::try_get_struct<LX_INIT_REMOUNT_VIRTIOFS_SHARE_MESSAGE>(span);
                        THROW_HR_IF(E_UNEXPECTED, !remountShare);

                        const std::string tag = wsl::shared::string::FromSpan(span, remountShare->TagOffset);
                        const auto tagWide = wsl::shared::string::MultiByteToWide(tag);
                        auto guestDeviceLock = m_guestDeviceLock.lock_exclusive();
                        const auto foundShare = FindVirtioFsShare(tagWide.c_str(), !remountShare->Admin);
                        THROW_HR_IF_MSG(E_UNEXPECTED, !foundShare.has_value(), "Unknown tag %ls", tagWide.c_str());

                        newTag = AddVirtioFsShare(remountShare->Admin, foundShare->Path.c_str(), foundShare->OptionsString().c_str());
                    });

                    respondWithTag(newTag, result);
                }
                else
                {
                    THROW_HR_MSG(E_UNEXPECTED, "Unexpected MessageType %d", message->MessageType);
                }

You can also share your feedback on Copilot code review. Take the survey.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.


You can also share your feedback on Copilot code review. Take the survey.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.


You can also share your feedback on Copilot code review. Take the survey.

Copy link
Collaborator

@OneBlue OneBlue left a comment

Choose a reason for hiding this comment

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

LGTM. One minor comment

Comment on lines +73 to +86
std::string CanonicalSource{Source};
UtilCanonicalisePathSeparator(CanonicalSource, PATH_SEP_NT);

UtilMkdirPath(VIRTIOFS_TAG_DIR, 0755);

auto LinkPath = std::format("{}/{}", VIRTIOFS_TAG_DIR, Tag);

//
// Remove any existing symlink for this tag before creating a new one.
//

unlink(LinkPath.c_str());
if (symlink(CanonicalSource.c_str(), LinkPath.c_str()) < 0)
{
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think that would be a good idea, at least we could fail if we see a / or a . in the target

@benhillis benhillis merged commit 81dc9a3 into master Mar 13, 2026
10 checks passed
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.

3 participants