diff --git a/src/windows/common/CMakeLists.txt b/src/windows/common/CMakeLists.txt index 90c50d0..a254469 100644 --- a/src/windows/common/CMakeLists.txt +++ b/src/windows/common/CMakeLists.txt @@ -63,10 +63,10 @@ set(HEADERS disk.hpp Distribution.h filesystem.hpp + HandleConsoleProgressBar.h hcs.hpp hcs_schema.h helpers.hpp - HandleConsoleProgressBar.h interop.hpp ExecutionContext.h socket.hpp diff --git a/src/windows/common/wslutil.h b/src/windows/common/wslutil.h index 41d4b7c..fab4c98 100644 --- a/src/windows/common/wslutil.h +++ b/src/windows/common/wslutil.h @@ -78,6 +78,22 @@ void CoInitializeSecurity(); void ConfigureCrt(); +/// +/// Creates a COM server with user impersonation. +/// +template +wil::com_ptr_t CreateComServerAsUser(_In_ REFCLSID RefClsId, _In_ HANDLE UserToken) +{ + auto revert = wil::impersonate_token(UserToken); + return wil::CoCreateInstance(RefClsId, (CLSCTX_LOCAL_SERVER | CLSCTX_ENABLE_CLOAKING | CLSCTX_ENABLE_AAA)); +} + +template +wil::com_ptr_t CreateComServerAsUser(_In_ HANDLE UserToken) +{ + return CreateComServerAsUser(__uuidof(Class), UserToken); +} + std::wstring ConstructPipePath(_In_ std::wstring_view PipeName); GUID CreateV5Uuid(const GUID& namespaceGuid, const std::span name); diff --git a/src/windows/service/exe/CMakeLists.txt b/src/windows/service/exe/CMakeLists.txt index f6962b8..c1e49a2 100644 --- a/src/windows/service/exe/CMakeLists.txt +++ b/src/windows/service/exe/CMakeLists.txt @@ -17,6 +17,7 @@ set(SOURCES GnsChannel.cpp GnsPortTrackerChannel.cpp GnsRpcServer.cpp + GuestDeviceManager.cpp GuestTelemetryLogger.cpp Lifetime.cpp LxssConsoleManager.cpp @@ -56,6 +57,7 @@ set(HEADERS GnsChannel.h GnsPortTrackerChannel.h GnsRpcServer.h + GuestDeviceManager.h GuestTelemetryLogger.h INetworkingEngine.h IMirroredNetworkManager.h diff --git a/src/windows/service/exe/GuestDeviceManager.cpp b/src/windows/service/exe/GuestDeviceManager.cpp new file mode 100644 index 0000000..73426ab --- /dev/null +++ b/src/windows/service/exe/GuestDeviceManager.cpp @@ -0,0 +1,149 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. + +#include "precomp.h" +#include "GuestDeviceManager.h" +#include "DeviceHostProxy.h" + +GuestDeviceManager::GuestDeviceManager(_In_ const std::wstring& machineId, _In_ const GUID& runtimeId) : + m_machineId(machineId), m_deviceHostSupport(wil::MakeOrThrow(machineId, runtimeId)) +{ +} + +_Requires_lock_not_held_(m_lock) +GUID GuestDeviceManager::AddGuestDevice( + _In_ const GUID& DeviceId, _In_ const GUID& ImplementationClsid, _In_ PCWSTR AccessName, _In_opt_ PCWSTR Options, _In_ PCWSTR Path, _In_ UINT32 Flags, _In_ HANDLE UserToken) +{ + auto guestDeviceLock = m_lock.lock_exclusive(); + return AddHdvShareWithOptions(DeviceId, ImplementationClsid, AccessName, Options, Path, Flags, UserToken); +} + +_Requires_lock_held_(m_lock) +GUID GuestDeviceManager::AddHdvShareWithOptions( + _In_ const GUID& DeviceId, _In_ const GUID& ImplementationClsid, _In_ PCWSTR AccessName, _In_opt_ PCWSTR Options, _In_ PCWSTR Path, _In_ UINT32 Flags, _In_ HANDLE UserToken) +{ + wil::com_ptr server; + + // Options are appended to the name with a semi-colon separator. + // "name;key1=value1;key2=value2" + // The AddSharePath implementation is responsible for separating them out and interpreting them. + std::wstring nameWithOptions{AccessName}; + if (ARGUMENT_PRESENT(Options)) + { + nameWithOptions += L";"; + nameWithOptions += Options; + } + + { + auto revert = wil::impersonate_token(UserToken); + + server = GetRemoteFileSystem(ImplementationClsid, c_defaultDeviceTag); + if (!server) + { + server = wil::CoCreateInstance(ImplementationClsid, (CLSCTX_LOCAL_SERVER | CLSCTX_ENABLE_CLOAKING | CLSCTX_ENABLE_AAA)); + AddRemoteFileSystem(ImplementationClsid, c_defaultDeviceTag.c_str(), server); + } + + THROW_IF_FAILED(server->AddSharePath(nameWithOptions.c_str(), Path, Flags)); + } + + // This requires more privileges than the user may have, so impersonation is disabled. + return AddNewDevice(DeviceId, server, AccessName); +} + +GUID GuestDeviceManager::AddNewDevice(_In_ const GUID& deviceId, _In_ const wil::com_ptr& server, _In_ PCWSTR tag) +{ + THROW_HR_IF(E_NOT_VALID_STATE, !m_deviceHostSupport); + return m_deviceHostSupport->AddNewDevice(deviceId, server, tag); +} + +void GuestDeviceManager::AddRemoteFileSystem(_In_ REFCLSID clsid, _In_ PCWSTR tag, _In_ const wil::com_ptr& server) +{ + THROW_HR_IF(E_NOT_VALID_STATE, !m_deviceHostSupport); + m_deviceHostSupport->AddRemoteFileSystem(clsid, tag, server); +} + +void GuestDeviceManager::AddSharedMemoryDevice(_In_ const GUID& ImplementationClsid, _In_ PCWSTR Tag, _In_ PCWSTR Path, _In_ UINT32 SizeMb, _In_ HANDLE UserToken) +{ + auto guestDeviceLock = m_lock.lock_exclusive(); + auto objectLifetime = CreateSectionObjectRoot(Path, UserToken); + + // For virtiofs hdv, the flags parameter has been overloaded. Flags are placed in the lower + // 16 bits, while the shared memory size in megabytes are placed in the upper 16 bits. + static constexpr auto VIRTIO_FS_FLAGS_SHMEM_SIZE_SHIFT = 16; + UINT32 flags = (SizeMb << VIRTIO_FS_FLAGS_SHMEM_SIZE_SHIFT); + WI_SetFlag(flags, VIRTIO_FS_FLAGS_TYPE_SECTIONS); + (void)AddHdvShareWithOptions(VIRTIO_VIRTIOFS_DEVICE_ID, ImplementationClsid, Tag, {}, objectLifetime.Path.c_str(), flags, UserToken); + m_objectDirectories.emplace_back(std::move(objectLifetime)); +} + +GuestDeviceManager::DirectoryObjectLifetime GuestDeviceManager::CreateSectionObjectRoot(_In_ std::wstring_view RelativeRootPath, _In_ HANDLE UserToken) const +{ + auto revert = wil::impersonate_token(UserToken); + DWORD sessionId; + DWORD bytesWritten; + THROW_LAST_ERROR_IF(!GetTokenInformation(GetCurrentThreadToken(), TokenSessionId, &sessionId, sizeof(sessionId), &bytesWritten)); + + // /Sessions/1/BaseNamedObjects/WSL// + std::wstringstream sectionPathBuilder; + sectionPathBuilder << L"\\Sessions\\" << sessionId << L"\\BaseNamedObjects" << L"\\WSL\\" << m_machineId << L"\\" << RelativeRootPath; + auto sectionPath = sectionPathBuilder.str(); + + UNICODE_STRING ntPath{}; + OBJECT_ATTRIBUTES attributes{}; + attributes.Length = sizeof(OBJECT_ATTRIBUTES); + attributes.ObjectName = &ntPath; + std::vector directoryHierarchy; + auto remainingPath = std::wstring_view(sectionPath.data(), sectionPath.length()); + while (remainingPath.length() > 0) + { + // Find the next path substring, ignoring the root path backslash. + auto nextDir = remainingPath; + const auto separatorPos = nextDir.find(L"\\", remainingPath[0] == L'\\' ? 1 : 0); + if (separatorPos != std::wstring_view::npos) + { + nextDir = nextDir.substr(0, separatorPos); + remainingPath = remainingPath.substr(separatorPos + 1, std::wstring_view::npos); + + // Skip concurrent backslashes. + while (remainingPath.length() > 0 && remainingPath[0] == L'\\') + { + remainingPath = remainingPath.substr(1, std::wstring_view::npos); + } + } + else + { + remainingPath = remainingPath.substr(remainingPath.length(), std::wstring_view::npos); + } + + attributes.RootDirectory = directoryHierarchy.size() > 0 ? directoryHierarchy.back().get() : nullptr; + ntPath.Buffer = const_cast(nextDir.data()); + ntPath.Length = sizeof(WCHAR) * gsl::narrow_cast(nextDir.length()); + ntPath.MaximumLength = ntPath.Length; + wil::unique_handle nextHandle; + NTSTATUS status = ZwCreateDirectoryObject(&nextHandle, DIRECTORY_ALL_ACCESS, &attributes); + if (status == STATUS_OBJECT_NAME_COLLISION) + { + status = NtOpenDirectoryObject(&nextHandle, MAXIMUM_ALLOWED, &attributes); + } + THROW_IF_NTSTATUS_FAILED(status); + directoryHierarchy.emplace_back(std::move(nextHandle)); + } + + return {std::move(sectionPath), std::move(directoryHierarchy)}; +} + +wil::com_ptr GuestDeviceManager::GetRemoteFileSystem(_In_ REFCLSID clsid, _In_ std::wstring_view tag) +{ + THROW_HR_IF(E_NOT_VALID_STATE, !m_deviceHostSupport); + return m_deviceHostSupport->GetRemoteFileSystem(clsid, tag); +} + +void GuestDeviceManager::Shutdown() +try +{ + if (m_deviceHostSupport) + { + m_deviceHostSupport->Shutdown(); + } +} +CATCH_LOG() diff --git a/src/windows/service/exe/GuestDeviceManager.h b/src/windows/service/exe/GuestDeviceManager.h new file mode 100644 index 0000000..f1afa99 --- /dev/null +++ b/src/windows/service/exe/GuestDeviceManager.h @@ -0,0 +1,72 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. + +#pragma once + +#include "DeviceHostProxy.h" + +// Flags for virtiofs vdev device creation. +#define VIRTIO_FS_FLAGS_TYPE_FILES 0x8000 +#define VIRTIO_FS_FLAGS_TYPE_SECTIONS 0x4000 + +// {872270E1-A899-4AF6-B454-7193634435AD} +DEFINE_GUID(VIRTIO_VIRTIOFS_DEVICE_ID, 0x872270E1, 0xA899, 0x4AF6, 0xB4, 0x54, 0x71, 0x93, 0x63, 0x44, 0x35, 0xAD); + +// {ABB755FC-1B86-4255-83E2-E5787ABCF6C2} +DEFINE_GUID(VIRTIO_PMEM_CLASS_ID, 0xABB755FC, 0x1B86, 0x4255, 0x83, 0xe2, 0xe5, 0x78, 0x7a, 0xbc, 0xf6, 0xc2); + +inline const std::wstring c_defaultDeviceTag = L"default"; + +// +// Provides synchronized access to guest device operations. +// +class GuestDeviceManager +{ +public: + GuestDeviceManager(_In_ const std::wstring& machineId, _In_ const GUID& runtimeId); + + _Requires_lock_not_held_(m_lock) + GUID AddGuestDevice( + _In_ const GUID& DeviceId, + _In_ const GUID& ImplementationClsid, + _In_ PCWSTR AccessName, + _In_opt_ PCWSTR Options, + _In_ PCWSTR Path, + _In_ UINT32 Flags, + _In_ HANDLE UserToken); + + GUID AddNewDevice(_In_ const GUID& deviceId, _In_ const wil::com_ptr& server, _In_ PCWSTR tag); + + void AddRemoteFileSystem(_In_ REFCLSID clsid, _In_ PCWSTR tag, _In_ const wil::com_ptr& server); + + void AddSharedMemoryDevice(_In_ const GUID& ImplementationClsid, _In_ PCWSTR Tag, _In_ PCWSTR Path, _In_ UINT32 SizeMb, _In_ HANDLE UserToken); + + wil::com_ptr GetRemoteFileSystem(_In_ REFCLSID clsid, _In_ std::wstring_view tag); + + void Shutdown(); + +private: + _Requires_lock_held_(m_lock) + GUID AddHdvShareWithOptions( + _In_ const GUID& DeviceId, + _In_ const GUID& ImplementationClsid, + _In_ PCWSTR AccessName, + _In_opt_ PCWSTR Options, + _In_ PCWSTR Path, + _In_ UINT32 Flags, + _In_ HANDLE UserToken); + + struct DirectoryObjectLifetime + { + std::wstring Path; + // Directory objects are temporary, even if they have children, so need to keep + // any created handles open in order for the directory to remain accessible. + std::vector HierarchyLifetimes; + }; + + DirectoryObjectLifetime CreateSectionObjectRoot(_In_ std::wstring_view RelativeRootPath, _In_ HANDLE UserToken) const; + + wil::srwlock m_lock; + std::wstring m_machineId; + wil::com_ptr m_deviceHostSupport; + _Guarded_by_(m_lock) std::vector m_objectDirectories; +}; diff --git a/src/windows/service/exe/VirtioNetworking.cpp b/src/windows/service/exe/VirtioNetworking.cpp index 1d48b03..cb69244 100644 --- a/src/windows/service/exe/VirtioNetworking.cpp +++ b/src/windows/service/exe/VirtioNetworking.cpp @@ -2,6 +2,7 @@ #include "precomp.h" #include "VirtioNetworking.h" +#include "GuestDeviceManager.h" #include "Stringify.h" #include "stringshared.h" @@ -13,15 +14,10 @@ using wsl::core::VirtioNetworking; static constexpr auto c_loopbackDeviceName = TEXT(LX_INIT_LOOPBACK_DEVICE_NAME); VirtioNetworking::VirtioNetworking( - GnsChannel&& gnsChannel, - bool enableLocalhostRelay, - AddGuestDeviceCallback addGuestDeviceCallback, - ModifyOpenPortsCallback modifyOpenPortsCallback, - GuestInterfaceStateChangeCallback guestInterfaceStateChangeCallback) : - m_addGuestDeviceCallback(std::move(addGuestDeviceCallback)), + GnsChannel&& gnsChannel, bool enableLocalhostRelay, std::shared_ptr guestDeviceManager, wil::shared_handle userToken) : + m_guestDeviceManager(std::move(guestDeviceManager)), + m_userToken(std::move(userToken)), m_gnsChannel(std::move(gnsChannel)), - m_modifyOpenPortsCallback(std::move(modifyOpenPortsCallback)), - m_guestInterfaceStateChangeCallback(std::move(guestInterfaceStateChangeCallback)), m_enableLocalhostRelay(enableLocalhostRelay) { } @@ -72,11 +68,12 @@ try device_options << L"nameservers=" << dns_servers; } - // Add virtio net adapter to guest - m_adapterId = m_addGuestDeviceCallback(c_virtioNetworkClsid, c_virtioNetworkDeviceId, L"eth0", device_options.str().c_str()); - auto lock = m_lock.lock_exclusive(); + // Add virtio net adapter to guest + m_adapterId = m_guestDeviceManager->AddGuestDevice( + c_virtioNetworkDeviceId, c_virtioNetworkClsid, L"eth0", nullptr, device_options.str().c_str(), 0, m_userToken.get()); + hns::HNSEndpoint endpointProperties; endpointProperties.ID = m_adapterId; endpointProperties.IPAddress = m_networkSettings->PreferredIpAddress.AddressString; @@ -121,8 +118,14 @@ CATCH_LOG() void VirtioNetworking::SetupLoopbackDevice() { - m_localhostAdapterId = m_addGuestDeviceCallback( - c_virtioNetworkClsid, c_virtioNetworkDeviceId, c_loopbackDeviceName, L"client_ip=127.0.0.1;client_mac=00:11:22:33:44:55"); + m_localhostAdapterId = m_guestDeviceManager->AddGuestDevice( + c_virtioNetworkDeviceId, + c_virtioNetworkClsid, + c_loopbackDeviceName, + nullptr, + L"client_ip=127.0.0.1;client_mac=00:11:22:33:44:55", + 0, + m_userToken.get()); hns::HNSEndpoint endpointProperties; endpointProperties.ID = m_localhostAdapterId; @@ -151,7 +154,7 @@ void VirtioNetworking::StartPortTracker(wil::unique_socket&& socket) m_gnsPortTrackerChannel.emplace( std::move(socket), [&](const SOCKADDR_INET& addr, int protocol, bool allocate) { return HandlePortNotification(addr, protocol, allocate); }, - [&](_In_ const std::string& interfaceName, _In_ bool up) { m_guestInterfaceStateChangeCallback(interfaceName, up); }); + [](const std::string&, bool) {}); // TODO: reconsider if InterfaceStateCallback is needed. } HRESULT VirtioNetworking::HandlePortNotification(const SOCKADDR_INET& addr, int protocol, bool allocate) const noexcept @@ -185,21 +188,65 @@ HRESULT VirtioNetworking::HandlePortNotification(const SOCKADDR_INET& addr, int localAddr.Ipv6.sin6_port = addr.Ipv6.sin6_port; } } - result = m_modifyOpenPortsCallback(c_virtioNetworkClsid, c_loopbackDeviceName, localAddr, protocol, allocate); + result = ModifyOpenPorts(c_virtioNetworkClsid, c_loopbackDeviceName, localAddr, protocol, allocate); LOG_HR_IF_MSG(E_FAIL, result != S_OK, "Failure adding localhost relay port %d", localAddr.Ipv4.sin_port); } + if (!loopback) { - const int localResult = m_modifyOpenPortsCallback(c_virtioNetworkClsid, L"eth0", addr, protocol, allocate); + const int localResult = ModifyOpenPorts(c_virtioNetworkClsid, L"eth0", addr, protocol, allocate); LOG_HR_IF_MSG(E_FAIL, localResult != S_OK, "Failure adding relay port %d", addr.Ipv4.sin_port); if (result == 0) { result = localResult; } } + return result; } +int VirtioNetworking::ModifyOpenPorts(_In_ const GUID& clsid, _In_ PCWSTR tag, _In_ const SOCKADDR_INET& addr, _In_ int protocol, _In_ bool isOpen) const +{ + if (protocol != IPPROTO_TCP && protocol != IPPROTO_UDP) + { + LOG_HR_MSG(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), "Unsupported bind protocol %d", protocol); + return 0; + } + else if (addr.si_family == AF_INET6) + { + // The virtio net adapter does not yet support IPv6 packets, so any traffic would arrive via + // IPv4. If the caller wants IPv4 they will also likely listen on an IPv4 address, which will + // be handled as a separate callback to this same code. + return 0; + } + + auto lock = m_lock.lock_exclusive(); + const auto server = m_guestDeviceManager->GetRemoteFileSystem(clsid, c_defaultDeviceTag); + if (server) + { + std::wstring portString = std::format(L"tag={};port_number={}", tag, addr.Ipv4.sin_port); + if (protocol == IPPROTO_UDP) + { + portString += L";udp"; + } + + if (!isOpen) + { + portString += L";allocate=false"; + } + else + { + wchar_t addrStr[16]; // "000.000.000.000" + null terminator + RtlIpv4AddressToStringW(&addr.Ipv4.sin_addr, addrStr); + portString += std::format(L";listen_addr={}", addrStr); + } + + LOG_IF_FAILED(server->AddShare(portString.c_str(), nullptr, 0)); + } + + return 0; +} + void NETIOAPI_API_ VirtioNetworking::OnNetworkConnectivityChange(PVOID context, NL_NETWORK_CONNECTIVITY_HINT hint) { static_cast(context)->RefreshGuestConnection(hint); diff --git a/src/windows/service/exe/VirtioNetworking.h b/src/windows/service/exe/VirtioNetworking.h index decae80..629afb2 100644 --- a/src/windows/service/exe/VirtioNetworking.h +++ b/src/windows/service/exe/VirtioNetworking.h @@ -6,22 +6,14 @@ #include "GnsChannel.h" #include "WslCoreHostDnsInfo.h" #include "GnsPortTrackerChannel.h" +#include "GuestDeviceManager.h" namespace wsl::core { -using AddGuestDeviceCallback = std::function; -using ModifyOpenPortsCallback = std::function; -using GuestInterfaceStateChangeCallback = std::function; - class VirtioNetworking : public INetworkingEngine { public: - VirtioNetworking( - GnsChannel&& gnsChannel, - bool enableLocalhostRelay, - AddGuestDeviceCallback addGuestDeviceCallback, - ModifyOpenPortsCallback modifyOpenPortsCallback, - GuestInterfaceStateChangeCallback guestInterfaceStateChangeCallback); + VirtioNetworking(GnsChannel&& gnsChannel, bool enableLocalhostRelay, std::shared_ptr guestDeviceManager, wil::shared_handle userToken); ~VirtioNetworking() = default; // Note: This class cannot be moved because m_networkNotifyHandle captures a 'this' pointer. @@ -43,6 +35,7 @@ private: static std::optional FindVirtioInterfaceLuid(const SOCKADDR_INET& virtioAddress, const NL_NETWORK_CONNECTIVITY_HINT& currentConnectivityHint); HRESULT HandlePortNotification(const SOCKADDR_INET& addr, int protocol, bool allocate) const noexcept; + int ModifyOpenPorts(_In_ const GUID& clsid, _In_ PCWSTR tag, _In_ const SOCKADDR_INET& addr, _In_ int protocol, _In_ bool isOpen) const; void RefreshGuestConnection(NL_NETWORK_CONNECTIVITY_HINT hint) noexcept; void SetupLoopbackDevice(); void UpdateDns(wsl::shared::hns::DNS&& dnsSettings); @@ -50,17 +43,14 @@ private: mutable wil::srwlock m_lock; - AddGuestDeviceCallback m_addGuestDeviceCallback; + std::shared_ptr m_guestDeviceManager; + wil::shared_handle m_userToken; GnsChannel m_gnsChannel; std::optional m_gnsPortTrackerChannel; std::shared_ptr m_networkSettings; bool m_enableLocalhostRelay; GUID m_localhostAdapterId; GUID m_adapterId; - std::optional m_connectivityLevel; - std::optional m_connectivityCost; - ModifyOpenPortsCallback m_modifyOpenPortsCallback; - GuestInterfaceStateChangeCallback m_guestInterfaceStateChangeCallback; std::optional m_interfaceLuid; ULONG m_networkMtu = 0; diff --git a/src/windows/service/exe/WslCoreVm.cpp b/src/windows/service/exe/WslCoreVm.cpp index f9a401c..343b818 100644 --- a/src/windows/service/exe/WslCoreVm.cpp +++ b/src/windows/service/exe/WslCoreVm.cpp @@ -39,18 +39,10 @@ using namespace std::string_literals; // Start of unaddressable memory if guest only supports the minimum 36-bit addressing. #define MAX_36_BIT_PAGE_IN_MB (0x1000000000 / _1MB) -// This device type is implemented by the external virtiofs vdev. -// {872270E1-A899-4AF6-B454-7193634435AD} -DEFINE_GUID(VIRTIO_VIRTIOFS_DEVICE_ID, 0x872270E1, 0xA899, 0x4AF6, 0xB4, 0x54, 0x71, 0x93, 0x63, 0x44, 0x35, 0xAD); - // This device type is implemented by the external virtio-pmem vdev. // {EDBB24BB-5E19-40F4-8A0F-8224313064FD} DEFINE_GUID(VIRTIO_PMEM_DEVICE_ID, 0xEDBB24BB, 0x5E19, 0x40F4, 0x8A, 0x0F, 0x82, 0x24, 0x31, 0x30, 0x64, 0xFD); -// Flags for virtiofs vdev device creation. -#define VIRTIO_FS_FLAGS_TYPE_FILES 0x8000 -#define VIRTIO_FS_FLAGS_TYPE_SECTIONS 0x4000 - // Version numbers for various functionality that was backported. #define NICKEL_BUILD_FLOOR 22350 #define VIRTIO_SERIAL_CONSOLE_COBALT_RELEASE_UBR 40 @@ -65,9 +57,6 @@ static constexpr size_t c_bootEntropy = 0x1000; static constexpr auto c_localDevicesKey = L"SOFTWARE\\Microsoft\\Terminal Server Client\\LocalDevices"; static constexpr std::pair c_schemaVersionNickel{2, 7}; -// {ABB755FC-1B86-4255-83E2-E5787ABCF6C2} -static constexpr GUID c_pmemClassId = {0xABB755FC, 0x1B86, 0x4255, {0x83, 0xe2, 0xe5, 0x78, 0x7a, 0xbc, 0xf6, 0xc2}}; - #define LXSS_ENABLE_GUI_APPS() (m_vmConfig.EnableGuiApps && (m_systemDistroDeviceId != ULONG_MAX)) using namespace wsl::windows::common; @@ -78,8 +67,6 @@ using wsl::shared::Localization; using wsl::windows::common::Context; using wsl::windows::common::ExecutionContext; -const std::wstring WslCoreVm::c_defaultTag = L"default"s; - namespace { INT64 RequiredExtraMmioSpaceForPmemFileInMb(_In_ PCWSTR FilePath) @@ -342,7 +329,8 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken m_runtimeId = wsl::windows::common::hcs::GetRuntimeId(m_system.get()); WI_ASSERT(IsEqualGUID(VmId, m_runtimeId)); - m_deviceHostSupport = wil::MakeOrThrow(m_machineId, m_runtimeId); + // Initialize the guest device manager. + m_guestDeviceManager = std::make_shared(m_machineId, m_runtimeId); // Create a socket listening for connections from mini_init. m_listenSocket = wsl::windows::common::hvsocket::Listen(m_runtimeId, LX_INIT_UTILITY_VM_INIT_PORT); @@ -469,7 +457,7 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken break; case LxMiniInitMountDeviceTypePmem: - m_systemDistroDeviceId = MountFileAsPersistentMemory(c_pmemClassId, m_vmConfig.SystemDistroPath.c_str(), true); + m_systemDistroDeviceId = MountFileAsPersistentMemory(m_vmConfig.SystemDistroPath.c_str(), true); break; default: @@ -608,15 +596,7 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken else if (m_vmConfig.NetworkingMode == NetworkingMode::VirtioProxy) { m_networkingEngine = std::make_unique( - std::move(gnsChannel), - m_vmConfig.EnableLocalhostRelay, - [this](const GUID& Clsid, const GUID& DeviceId, PCWSTR Tag, PCWSTR Options) { - return HandleVirtioAddGuestDevice(Clsid, DeviceId, Tag, Options); - }, - [this](const GUID& Clsid, PCWSTR Tag, const SOCKADDR_INET& Addr, int Protocol, bool IsOpen) { - return HandleVirtioModifyOpenPorts(Clsid, Tag, Addr, Protocol, IsOpen); - }, - [](const std::string&, bool) {}); + std::move(gnsChannel), m_vmConfig.EnableLocalhostRelay, m_guestDeviceManager, m_userToken); } else if (m_vmConfig.NetworkingMode == NetworkingMode::Bridged) { @@ -799,9 +779,9 @@ WslCoreVm::~WslCoreVm() noexcept } // Shutdown virtio device hosts. - if (m_deviceHostSupport) + if (m_guestDeviceManager) { - m_deviceHostSupport->Shutdown(); + m_guestDeviceManager->Shutdown(); } // Call RevokeVmAccess on each VHD that was added to the utility VM. This @@ -955,7 +935,7 @@ void WslCoreVm::AddPlan9Share( if (m_vmConfig.EnableVirtio9p) { - server = m_deviceHostSupport->GetRemoteFileSystem(__uuidof(p9fs::Plan9FileSystem), VirtIoTag); + server = m_guestDeviceManager->GetRemoteFileSystem(__uuidof(p9fs::Plan9FileSystem), VirtIoTag); } else { @@ -968,10 +948,10 @@ void WslCoreVm::AddPlan9Share( if (!server) { - server = CreateComServerAsUser(UserToken); + server = wsl::windows::common::wslutil::CreateComServerAsUser(UserToken); if (m_vmConfig.EnableVirtio9p) { - m_deviceHostSupport->AddRemoteFileSystem(__uuidof(p9fs::Plan9FileSystem), VirtIoTag, server); + m_guestDeviceManager->AddRemoteFileSystem(__uuidof(p9fs::Plan9FileSystem), VirtIoTag, server); // Start with one device to handle the first mount request. After // each mount, the Plan9 file-system will request additional @@ -999,66 +979,10 @@ void WslCoreVm::AddPlan9Share( if (addNewDevice) { // This requires more privileges than the user may have, so impersonation is disabled. - (void)m_deviceHostSupport->AddNewDevice(VIRTIO_PLAN9_DEVICE_ID, server, VirtIoTag); + (void)m_guestDeviceManager->AddNewDevice(VIRTIO_PLAN9_DEVICE_ID, server, VirtIoTag); } } -WslCoreVm::DirectoryObjectLifetime WslCoreVm::CreateSectionObjectRoot(_In_ std::wstring_view RelativeRootPath, _In_ HANDLE UserToken) const -{ - auto revert = wil::impersonate_token(UserToken); - DWORD sessionId; - DWORD bytesWritten; - THROW_LAST_ERROR_IF(!GetTokenInformation(GetCurrentThreadToken(), TokenSessionId, &sessionId, sizeof(sessionId), &bytesWritten)); - - // /Sessions/1/BaseNamedObjects/WSL// - std::wstringstream sectionPathBuilder; - sectionPathBuilder << L"\\Sessions\\" << sessionId << L"\\BaseNamedObjects" << L"\\WSL\\" << m_machineId << L"\\" << RelativeRootPath; - auto sectionPath = sectionPathBuilder.str(); - - UNICODE_STRING ntPath{}; - OBJECT_ATTRIBUTES attributes{}; - attributes.Length = sizeof(OBJECT_ATTRIBUTES); - attributes.ObjectName = &ntPath; - std::vector directoryHierarchy; - auto remainingPath = std::wstring_view(sectionPath.data(), sectionPath.length()); - while (remainingPath.length() > 0) - { - // Find the next path substring, ignoring the root path backslash. - auto nextDir = remainingPath; - const auto separatorPos = nextDir.find(L"\\", remainingPath[0] == L'\\' ? 1 : 0); - if (separatorPos != std::wstring_view::npos) - { - nextDir = nextDir.substr(0, separatorPos); - remainingPath = remainingPath.substr(separatorPos + 1, std::wstring_view::npos); - - // Skip concurrent backslashes. - while (remainingPath.length() > 0 && remainingPath[0] == L'\\') - { - remainingPath = remainingPath.substr(1, std::wstring_view::npos); - } - } - else - { - remainingPath = remainingPath.substr(remainingPath.length(), std::wstring_view::npos); - } - - attributes.RootDirectory = directoryHierarchy.size() > 0 ? directoryHierarchy.back().get() : nullptr; - ntPath.Buffer = const_cast(nextDir.data()); - ntPath.Length = sizeof(WCHAR) * gsl::narrow_cast(nextDir.length()); - ntPath.MaximumLength = ntPath.Length; - wil::unique_handle nextHandle; - NTSTATUS status = ZwCreateDirectoryObject(&nextHandle, DIRECTORY_ALL_ACCESS, &attributes); - if (status == STATUS_OBJECT_NAME_COLLISION) - { - status = NtOpenDirectoryObject(&nextHandle, MAXIMUM_ALLOWED, &attributes); - } - THROW_IF_NTSTATUS_FAILED(status); - directoryHierarchy.emplace_back(std::move(nextHandle)); - } - - return {std::move(sectionPath), std::move(directoryHierarchy)}; -} - ULONG WslCoreVm::AttachDisk(_In_ PCWSTR Disk, _In_ DiskType Type, _In_ std::optional Lun, _In_ bool IsUserDisk, _In_ HANDLE UserToken) { auto lock = m_lock.lock_exclusive(); @@ -1867,7 +1791,8 @@ void WslCoreVm::InitializeGuest() { try { - MountSharedMemoryDevice(c_virtiofsClassId, L"wslg", L"wslg", WSLG_SHARED_MEMORY_SIZE_MB); + m_guestDeviceManager->AddSharedMemoryDevice( + c_virtiofsClassId, L"wslg", L"wslg", WSLG_SHARED_MEMORY_SIZE_MB, m_userToken.get()); m_sharedMemoryRoot = std::format(L"WSL\\{}\\wslg", m_machineId); } CATCH_LOG() @@ -1966,7 +1891,7 @@ bool WslCoreVm::InitializeDrvFsLockHeld(_In_ HANDLE UserToken) { // Before checking whether DrvFs is already initialized, make sure any existing Plan 9 servers // are usable. - VerifyDrvFsServers(); + VerifyPlan9Servers(); const auto elevated = wsl::windows::common::security::IsTokenElevated(UserToken); if (elevated) @@ -2004,53 +1929,6 @@ bool WslCoreVm::IsVhdAttached(_In_ PCWSTR VhdPath) return m_attachedDisks.contains({DiskType::VHD, VhdPath}); } -GUID WslCoreVm::HandleVirtioAddGuestDevice(_In_ const GUID& Clsid, _In_ const GUID& DeviceId, _In_ PCWSTR Tag, _In_ PCWSTR Options) -{ - auto guestDeviceLock = m_guestDeviceLock.lock_exclusive(); - return AddHdvShareWithOptions(DeviceId, Clsid, Tag, {}, Options, 0, m_userToken.get()); -} - -int WslCoreVm::HandleVirtioModifyOpenPorts(_In_ const GUID& Clsid, _In_ PCWSTR Tag, _In_ const SOCKADDR_INET& Addr, _In_ int Protocol, _In_ bool IsOpen) -{ - if (Protocol != IPPROTO_TCP && Protocol != IPPROTO_UDP) - { - LOG_HR_MSG(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), "Unsupported bind protocol %d", Protocol); - return 0; - } - else if (Addr.si_family == AF_INET6) - { - // The virtio net adapter does not yet support IPv6 packets, so any traffic would arrive via - // IPv4. If the caller wants IPv4 they will also likely listen on an IPv4 address, which will - // be handled as a separate callback to this same code. - return 0; - } - - auto guestDeviceLock = m_guestDeviceLock.lock_exclusive(); - const auto server = m_deviceHostSupport->GetRemoteFileSystem(Clsid, c_defaultTag); - if (server) - { - std::wstring portString = std::format(L"tag={};port_number={}", Tag, Addr.Ipv4.sin_port); - if (Protocol == IPPROTO_UDP) - { - portString += L";udp"; - } - - if (!IsOpen) - { - portString += L";allocate=false"; - } - else - { - wchar_t addrStr[16]; // "000.000.000.000" + null terminator - RtlIpv4AddressToStringW(&Addr.Ipv4.sin_addr, addrStr); - portString += std::format(L";listen_addr={}", addrStr); - } - - LOG_IF_FAILED(server->AddShare(portString.c_str(), nullptr, 0)); - } - return 0; -} - WslCoreVm::DiskMountResult WslCoreVm::MountDisk( _In_ PCWSTR Disk, _In_ DiskType MountDiskType, _In_ ULONG PartitionIndex, _In_opt_ PCWSTR Name, _In_opt_ PCWSTR Type, _In_opt_ PCWSTR Options) { @@ -2150,33 +2028,8 @@ void WslCoreVm::MountRootNamespaceFolder(_In_ LPCWSTR HostPath, _In_ LPCWSTR Gue ResultMessage.Result); } -void WslCoreVm::MountSharedMemoryDevice(_In_ const GUID& ImplementationClsid, _In_ PCWSTR Tag, _In_ PCWSTR Path, _In_ UINT32 SizeMb) -{ - if (!m_vmConfig.EnableVirtio) - { - return; - } - - auto guestDeviceLock = m_guestDeviceLock.lock_exclusive(); - MountSharedMemoryDeviceLockHeld(ImplementationClsid, Tag, Path, SizeMb); -} - -_Requires_lock_held_(m_guestDeviceLock) -void WslCoreVm::MountSharedMemoryDeviceLockHeld(_In_ const GUID& ImplementationClsid, _In_ PCWSTR Tag, _In_ PCWSTR Path, _In_ UINT32 SizeMb) -{ - auto objectLifetime = CreateSectionObjectRoot(Path, m_userToken.get()); - - // For virtiofs hdv, the flags parameter has been overloaded. Flags are placed in the lower - // 16 bits, while the shared memory size in megabytes are placed in the upper 16 bits. - static constexpr auto VIRTIO_FS_FLAGS_SHMEM_SIZE_SHIFT = 16; - UINT32 flags = (SizeMb << VIRTIO_FS_FLAGS_SHMEM_SIZE_SHIFT); - WI_SetFlag(flags, VIRTIO_FS_FLAGS_TYPE_SECTIONS); - (void)AddHdvShare(VIRTIO_VIRTIOFS_DEVICE_ID, ImplementationClsid, Tag, objectLifetime.Path.c_str(), flags, m_userToken.get()); - m_objectDirectories.emplace_back(std::move(objectLifetime)); -} - ULONG -WslCoreVm::MountFileAsPersistentMemory(_In_ const GUID& ImplementationClsid, _In_ PCWSTR FilePath, _In_ bool ReadOnly) +WslCoreVm::MountFileAsPersistentMemory(_In_ PCWSTR FilePath, _In_ bool ReadOnly) { hcs::Plan9ShareFlags flags{}; @@ -2198,7 +2051,7 @@ WslCoreVm::MountFileAsPersistentMemory(_In_ const GUID& ImplementationClsid, _In // a symlink that points to a path like: // /sys/devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0004:00/VMBUS:00//pcicceb:00//cceb:00:00.0/virtio1/ndbus0/region0/namespace0.0/block/pmem0 // Notice the GUID in the middle of that path. That GUID is the instance ID, which is randomly - // generated by AddHdvShare. So once we find a path with the instance ID, we know that + // generated by AddGuestDevice. So once we find a path with the instance ID, we know that // eventually /dev/pmemX will appear in the guest. auto persistentMemoryLock = m_persistentMemoryLock.lock_exclusive(); @@ -2209,8 +2062,8 @@ WslCoreVm::MountFileAsPersistentMemory(_In_ const GUID& ImplementationClsid, _In // added as part of VM creation and therefore any failure will result in VM termination // (in which case there's no need to remove the device). { - auto guestDeviceLock = m_guestDeviceLock.lock_exclusive(); - (void)AddHdvShare(VIRTIO_PMEM_DEVICE_ID, ImplementationClsid, L"", FilePath, static_cast(flags), m_userToken.get()); + (void)m_guestDeviceManager->AddGuestDevice( + VIRTIO_PMEM_DEVICE_ID, VIRTIO_PMEM_CLASS_ID, L"", nullptr, FilePath, static_cast(flags), m_userToken.get()); } // Wait for the pmem device to appear in the VM at /dev/pmemX. Guess the value of X given the @@ -2259,56 +2112,6 @@ void WslCoreVm::WaitForPmemDeviceInVm(_In_ ULONG PmemId) } } -_Requires_lock_held_(m_guestDeviceLock) -GUID WslCoreVm::AddHdvShareWithOptions( - _In_ const GUID& DeviceId, - _In_ const GUID& ImplementationClsid, - _In_ std::wstring_view AccessName, - _In_ std::wstring_view Options, - _In_ std::wstring_view Path, - _In_ UINT32 Flags, - _In_ HANDLE UserToken) -{ - wil::com_ptr server; - - THROW_HR_IF(E_NOTIMPL, !m_vmConfig.EnableVirtio); - - // Options are appended to the name with a semi-colon separator. - // "name;key1=value1;key2=value2" - // The AddSharePath implementation is responsible for separating them out and interpreting them. - std::wstring nameWithOptions{AccessName}; - if (!Options.empty()) - { - nameWithOptions += L";"; - nameWithOptions += Options; - } - - { - auto revert = wil::impersonate_token(UserToken); - - server = m_deviceHostSupport->GetRemoteFileSystem(ImplementationClsid, c_defaultTag); - if (!server) - { - server = CreateComServerAsUser(ImplementationClsid, UserToken); - m_deviceHostSupport->AddRemoteFileSystem(ImplementationClsid, c_defaultTag, server); - } - - const std::wstring SharePath(Path); - THROW_IF_FAILED(server->AddSharePath(nameWithOptions.c_str(), SharePath.c_str(), Flags)); - } - - // This requires more privileges than the user may have, so impersonation is disabled. - const std::wstring VirtioTag(AccessName); - return m_deviceHostSupport->AddNewDevice(DeviceId, server, VirtioTag.c_str()); -} - -_Requires_lock_held_(m_guestDeviceLock) -GUID WslCoreVm::AddHdvShare( - _In_ const GUID& DeviceId, _In_ const GUID& ImplementationClsid, _In_ PCWSTR AccessName, _In_ PCWSTR Path, _In_ UINT32 Flags, _In_ HANDLE UserToken) -{ - return AddHdvShareWithOptions(DeviceId, ImplementationClsid, AccessName, {}, Path, Flags, UserToken); -} - _Requires_lock_held_(m_guestDeviceLock) std::wstring WslCoreVm::AddVirtioFsShare(_In_ bool Admin, _In_ PCWSTR Path, _In_ PCWSTR Options, _In_opt_ HANDLE UserToken) { @@ -2341,8 +2144,14 @@ std::wstring WslCoreVm::AddVirtioFsShare(_In_ bool Admin, _In_ PCWSTR Path, _In_ tag += std::to_wstring(m_virtioFsShares.size()); WI_ASSERT(!FindVirtioFsShare(tag.c_str(), Admin)); - (void)AddHdvShareWithOptions( - VIRTIO_VIRTIOFS_DEVICE_ID, Admin ? c_virtiofsAdminClassId : c_virtiofsClassId, tag, key.OptionsString(), sharePath, VIRTIO_FS_FLAGS_TYPE_FILES, UserToken); + (void)m_guestDeviceManager->AddGuestDevice( + VIRTIO_VIRTIOFS_DEVICE_ID, + Admin ? c_virtiofsAdminClassId : c_virtiofsClassId, + tag.c_str(), + key.OptionsString().c_str(), + sharePath.c_str(), + VIRTIO_FS_FLAGS_TYPE_FILES, + UserToken); m_virtioFsShares.emplace(std::move(key), tag); created = true; @@ -2690,7 +2499,7 @@ std::pair WslCoreVm::UnmountVolume(_In_ const AttachedD } _Requires_lock_held_(m_guestDeviceLock) -void WslCoreVm::VerifyDrvFsServers() +void WslCoreVm::VerifyPlan9Servers() { for (auto it = m_plan9Servers.begin(); it != m_plan9Servers.end();) { diff --git a/src/windows/service/exe/WslCoreVm.h b/src/windows/service/exe/WslCoreVm.h index c2e2e37..496ae6e 100644 --- a/src/windows/service/exe/WslCoreVm.h +++ b/src/windows/service/exe/WslCoreVm.h @@ -29,6 +29,7 @@ Abstract: #include "INetworkingEngine.h" #include "SocketChannel.h" #include "DeviceHostProxy.h" +#include "GuestDeviceManager.h" #define UTILITY_VM_SHUTDOWN_TIMEOUT (30 * 1000) #define UTILITY_VM_TERMINATE_TIMEOUT (30 * 1000) @@ -107,10 +108,6 @@ public: bool IsVhdAttached(_In_ PCWSTR VhdPath); - GUID HandleVirtioAddGuestDevice(_In_ const GUID& Clsid, _In_ const GUID& DeviceId, _In_ PCWSTR Tag, _In_ PCWSTR Options); - - int HandleVirtioModifyOpenPorts(_In_ const GUID& Clsid, _In_ PCWSTR Tag, _In_ const SOCKADDR_INET& Addr, _In_ int Protocol, _In_ bool IsOpen); - DiskMountResult MountDisk( _In_ PCWSTR Disk, _In_ DiskType MountDiskType, _In_ ULONG PartitionIndex, _In_opt_ PCWSTR Name, _In_opt_ PCWSTR Type, _In_opt_ PCWSTR Options); @@ -120,10 +117,8 @@ public: ReadOnly = 0x1 }; - void MountSharedMemoryDevice(_In_ const GUID& ImplementationClsid, _In_ PCWSTR Tag, _In_ PCWSTR Path, _In_ UINT32 SizeMb); - ULONG - MountFileAsPersistentMemory(_In_ const GUID& ImplementationClsid, _In_ PCWSTR FilePath, _In_ bool ReadOnly); + MountFileAsPersistentMemory(_In_ PCWSTR FilePath, _In_ bool ReadOnly); void MountRootNamespaceFolder(_In_ LPCWSTR HostPath, _In_ LPCWSTR GuestPath, _In_ bool ReadOnly, _In_ LPCWSTR Name); @@ -135,7 +130,7 @@ public: void SaveAttachedDisksState(); _Requires_lock_held_(m_guestDeviceLock) - void VerifyDrvFsServers(); + void VerifyPlan9Servers(); enum DiskStateFlags { @@ -172,14 +167,6 @@ private: DiskStateFlags Flags; }; - struct DirectoryObjectLifetime - { - std::wstring Path; - // Directory objects are temporary, even if they have children, so need to keep - // any created handles open in order for the directory to remain accessible. - std::vector HierarchyLifetimes; - }; - struct VirtioFsShare { VirtioFsShare(PCWSTR Path, PCWSTR Options, bool Admin); @@ -202,19 +189,6 @@ private: _Requires_lock_held_(m_guestDeviceLock) void AddPlan9Share(_In_ PCWSTR AccessName, _In_ PCWSTR Path, _In_ UINT32 Port, _In_ wsl::windows::common::hcs::Plan9ShareFlags Flags, _In_ HANDLE UserToken, _In_ PCWSTR VirtIoTag); - _Requires_lock_held_(m_guestDeviceLock) - GUID AddHdvShare(_In_ const GUID& DeviceId, _In_ const GUID& ImplementationClsid, _In_ PCWSTR AccessName, _In_opt_ PCWSTR Path, _In_ UINT32 Flags, _In_ HANDLE UserToken); - - _Requires_lock_held_(m_guestDeviceLock) - GUID AddHdvShareWithOptions( - _In_ const GUID& DeviceId, - _In_ const GUID& ImplementationClsid, - _In_ std::wstring_view AccessName, - _In_ std::wstring_view Options, - _In_ std::wstring_view Path, - _In_ UINT32 Flags, - _In_ HANDLE UserToken); - _Requires_lock_held_(m_guestDeviceLock) std::wstring AddVirtioFsShare(_In_ bool Admin, _In_ PCWSTR Path, _In_ PCWSTR Options, _In_opt_ HANDLE UserToken = nullptr); @@ -223,19 +197,6 @@ private: void CollectCrashDumps(wil::unique_socket&& socket) const; - template - wil::com_ptr_t CreateComServerAsUser(_In_ REFCLSID RefClsId, _In_ HANDLE UserToken) - { - auto revert = wil::impersonate_token(UserToken); - return wil::CoCreateInstance(RefClsId, (CLSCTX_LOCAL_SERVER | CLSCTX_ENABLE_CLOAKING | CLSCTX_ENABLE_AAA)); - } - - template - wil::com_ptr_t CreateComServerAsUser(_In_ HANDLE UserToken) - { - return CreateComServerAsUser(__uuidof(Class), UserToken); - } - std::shared_ptr CreateInstanceInternal( _In_ const GUID& InstanceId, _In_ const LXSS_DISTRO_CONFIGURATION& Configuration, @@ -245,8 +206,6 @@ private: _In_ bool LaunchSystemDistro = false, _Out_opt_ ULONG* ConnectPort = nullptr); - DirectoryObjectLifetime CreateSectionObjectRoot(_In_ std::wstring_view RelativeRootPath, _In_ HANDLE UserToken) const; - _Requires_lock_held_(m_lock) void EjectVhdLockHeld(_In_ PCWSTR VhdPath); @@ -281,9 +240,6 @@ private: DiskMountResult MountDiskLockHeld( _In_ PCWSTR Disk, _In_ DiskType MountDiskType, _In_ ULONG PartitionIndex, _In_opt_ PCWSTR Name, _In_opt_ PCWSTR Type, _In_opt_ PCWSTR Options); - _Requires_lock_held_(m_guestDeviceLock) - void MountSharedMemoryDeviceLockHeld(_In_ const GUID& ImplementationClsid, _In_ PCWSTR Tag, _In_ PCWSTR Path, _In_ UINT32 SizeMb); - void WaitForPmemDeviceInVm(_In_ ULONG PmemId); void OnCrash(_In_ LPCWSTR Details); @@ -314,12 +270,14 @@ private: static void CALLBACK s_OnExit(_In_ HCS_EVENT* Event, _In_opt_ void* Context); - wil::srwlock m_lock; wil::srwlock m_guestDeviceLock; + std::shared_ptr m_guestDeviceManager; _Guarded_by_(m_guestDeviceLock) std::future m_drvfsInitialResult; _Guarded_by_(m_guestDeviceLock) wil::unique_handle m_drvfsToken; _Guarded_by_(m_guestDeviceLock) wil::unique_handle m_adminDrvfsToken; _Guarded_by_(m_guestDeviceLock) std::map m_virtioFsShares; + _Guarded_by_(m_guestDeviceLock) std::map> m_plan9Servers; + wil::srwlock m_lock; _Guarded_by_(m_lock) wil::unique_event m_terminatingEvent { wil::EventOptions::ManualReset }; _Guarded_by_(m_lock) wil::unique_event m_vmExitEvent { wil::EventOptions::ManualReset }; wil::unique_event m_vmCrashEvent{wil::EventOptions::ManualReset}; @@ -351,12 +309,9 @@ private: wsl::shared::SocketChannel m_miniInitChannel; wil::unique_socket m_notifyChannel; SE_SID m_userSid; - wil::com_ptr m_deviceHostSupport; std::shared_ptr m_systemDistro; _Guarded_by_(m_lock) std::bitset m_lunBitmap; _Guarded_by_(m_lock) std::map m_attachedDisks; - _Guarded_by_(m_guestDeviceLock) std::map> m_plan9Servers; - _Guarded_by_(m_guestDeviceLock) std::vector m_objectDirectories; std::tuple m_kernelVersion; std::wstring m_kernelVersionString; bool m_seccompAvailable; @@ -375,8 +330,6 @@ private: _Guarded_by_(m_persistentMemoryLock) ULONG m_nextPersistentMemoryId = 0; std::unique_ptr m_networkingEngine; - - static const std::wstring c_defaultTag; }; DEFINE_ENUM_FLAG_OPERATORS(WslCoreVm::DiskStateFlags);