cleanup: VirtioNetworking refactoring to be more portable (#13783)
* cleanup: VirtioNetworking refactoring to be more portable * more refactoring * make m_guestDeviceManager private --------- Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
Ben Hillis committed
Nov 25, 2025 at 16:40 UTC
4207cc80bdb8b732d3d1e85f991d6b79a01f929e
9 files changed
+340
-302
src/windows/common/CMakeLists.txt
+1
-1
@@ -63,10 +63,10 @@ set(HEADERS
63
disk.hpp
64
Distribution.h
65
filesystem.hpp
66
+ HandleConsoleProgressBar.h
67
hcs.hpp
68
hcs_schema.h
69
helpers.hpp
69
- HandleConsoleProgressBar.h
70
interop.hpp
71
ExecutionContext.h
72
socket.hpp
src/windows/common/wslutil.h
+16
@@ -78,6 +78,22 @@ void CoInitializeSecurity();
78
79
void ConfigureCrt();
80
81
+/// <summary>
82
+/// Creates a COM server with user impersonation.
83
+/// </summary>
84
+template <typename Interface>
85
+wil::com_ptr_t<Interface> CreateComServerAsUser(_In_ REFCLSID RefClsId, _In_ HANDLE UserToken)
86
+{
87
+ auto revert = wil::impersonate_token(UserToken);
88
+ return wil::CoCreateInstance<Interface>(RefClsId, (CLSCTX_LOCAL_SERVER | CLSCTX_ENABLE_CLOAKING | CLSCTX_ENABLE_AAA));
89
+}
90
+
91
+template <typename Class, typename Interface>
92
+wil::com_ptr_t<Interface> CreateComServerAsUser(_In_ HANDLE UserToken)
93
+{
94
+ return CreateComServerAsUser<Interface>(__uuidof(Class), UserToken);
95
+}
96
+
97
std::wstring ConstructPipePath(_In_ std::wstring_view PipeName);
98
99
GUID CreateV5Uuid(const GUID& namespaceGuid, const std::span<const std::byte> name);
src/windows/service/exe/CMakeLists.txt
+2
@@ -17,6 +17,7 @@ set(SOURCES
17
GnsChannel.cpp
18
GnsPortTrackerChannel.cpp
19
GnsRpcServer.cpp
20
+ GuestDeviceManager.cpp
21
GuestTelemetryLogger.cpp
22
Lifetime.cpp
23
LxssConsoleManager.cpp
@@ -56,6 +57,7 @@ set(HEADERS
57
GnsChannel.h
58
GnsPortTrackerChannel.h
59
GnsRpcServer.h
60
+ GuestDeviceManager.h
61
GuestTelemetryLogger.h
62
INetworkingEngine.h
63
IMirroredNetworkManager.h
src/windows/service/exe/GuestDeviceManager.cpp
new
+149
@@ -0,0 +1,149 @@
1
+// Copyright (C) Microsoft Corporation. All rights reserved.
2
+
3
+#include "precomp.h"
4
+#include "GuestDeviceManager.h"
5
+#include "DeviceHostProxy.h"
6
+
7
+GuestDeviceManager::GuestDeviceManager(_In_ const std::wstring& machineId, _In_ const GUID& runtimeId) :
8
+ m_machineId(machineId), m_deviceHostSupport(wil::MakeOrThrow<DeviceHostProxy>(machineId, runtimeId))
9
+{
10
+}
11
+
12
+_Requires_lock_not_held_(m_lock)
13
+GUID GuestDeviceManager::AddGuestDevice(
14
+ _In_ const GUID& DeviceId, _In_ const GUID& ImplementationClsid, _In_ PCWSTR AccessName, _In_opt_ PCWSTR Options, _In_ PCWSTR Path, _In_ UINT32 Flags, _In_ HANDLE UserToken)
15
+{
16
+ auto guestDeviceLock = m_lock.lock_exclusive();
17
+ return AddHdvShareWithOptions(DeviceId, ImplementationClsid, AccessName, Options, Path, Flags, UserToken);
18
+}
19
+
20
+_Requires_lock_held_(m_lock)
21
+GUID GuestDeviceManager::AddHdvShareWithOptions(
22
+ _In_ const GUID& DeviceId, _In_ const GUID& ImplementationClsid, _In_ PCWSTR AccessName, _In_opt_ PCWSTR Options, _In_ PCWSTR Path, _In_ UINT32 Flags, _In_ HANDLE UserToken)
23
+{
24
+ wil::com_ptr<IPlan9FileSystem> server;
25
+
26
+ // Options are appended to the name with a semi-colon separator.
27
+ // "name;key1=value1;key2=value2"
28
+ // The AddSharePath implementation is responsible for separating them out and interpreting them.
29
+ std::wstring nameWithOptions{AccessName};
30
+ if (ARGUMENT_PRESENT(Options))
31
+ {
32
+ nameWithOptions += L";";
33
+ nameWithOptions += Options;
34
+ }
35
+
36
+ {
37
+ auto revert = wil::impersonate_token(UserToken);
38
+
39
+ server = GetRemoteFileSystem(ImplementationClsid, c_defaultDeviceTag);
40
+ if (!server)
41
+ {
42
+ server = wil::CoCreateInstance<IPlan9FileSystem>(ImplementationClsid, (CLSCTX_LOCAL_SERVER | CLSCTX_ENABLE_CLOAKING | CLSCTX_ENABLE_AAA));
43
+ AddRemoteFileSystem(ImplementationClsid, c_defaultDeviceTag.c_str(), server);
44
+ }
45
+
46
+ THROW_IF_FAILED(server->AddSharePath(nameWithOptions.c_str(), Path, Flags));
47
+ }
48
+
49
+ // This requires more privileges than the user may have, so impersonation is disabled.
50
+ return AddNewDevice(DeviceId, server, AccessName);
51
+}
52
+
53
+GUID GuestDeviceManager::AddNewDevice(_In_ const GUID& deviceId, _In_ const wil::com_ptr<IPlan9FileSystem>& server, _In_ PCWSTR tag)
54
+{
55
+ THROW_HR_IF(E_NOT_VALID_STATE, !m_deviceHostSupport);
56
+ return m_deviceHostSupport->AddNewDevice(deviceId, server, tag);
57
+}
58
+
59
+void GuestDeviceManager::AddRemoteFileSystem(_In_ REFCLSID clsid, _In_ PCWSTR tag, _In_ const wil::com_ptr<IPlan9FileSystem>& server)
60
+{
61
+ THROW_HR_IF(E_NOT_VALID_STATE, !m_deviceHostSupport);
62
+ m_deviceHostSupport->AddRemoteFileSystem(clsid, tag, server);
63
+}
64
+
65
+void GuestDeviceManager::AddSharedMemoryDevice(_In_ const GUID& ImplementationClsid, _In_ PCWSTR Tag, _In_ PCWSTR Path, _In_ UINT32 SizeMb, _In_ HANDLE UserToken)
66
+{
67
+ auto guestDeviceLock = m_lock.lock_exclusive();
68
+ auto objectLifetime = CreateSectionObjectRoot(Path, UserToken);
69
+
70
+ // For virtiofs hdv, the flags parameter has been overloaded. Flags are placed in the lower
71
+ // 16 bits, while the shared memory size in megabytes are placed in the upper 16 bits.
72
+ static constexpr auto VIRTIO_FS_FLAGS_SHMEM_SIZE_SHIFT = 16;
73
+ UINT32 flags = (SizeMb << VIRTIO_FS_FLAGS_SHMEM_SIZE_SHIFT);
74
+ WI_SetFlag(flags, VIRTIO_FS_FLAGS_TYPE_SECTIONS);
75
+ (void)AddHdvShareWithOptions(VIRTIO_VIRTIOFS_DEVICE_ID, ImplementationClsid, Tag, {}, objectLifetime.Path.c_str(), flags, UserToken);
76
+ m_objectDirectories.emplace_back(std::move(objectLifetime));
77
+}
78
+
79
+GuestDeviceManager::DirectoryObjectLifetime GuestDeviceManager::CreateSectionObjectRoot(_In_ std::wstring_view RelativeRootPath, _In_ HANDLE UserToken) const
80
+{
81
+ auto revert = wil::impersonate_token(UserToken);
82
+ DWORD sessionId;
83
+ DWORD bytesWritten;
84
+ THROW_LAST_ERROR_IF(!GetTokenInformation(GetCurrentThreadToken(), TokenSessionId, &sessionId, sizeof(sessionId), &bytesWritten));
85
+
86
+ // /Sessions/1/BaseNamedObjects/WSL/<VM ID>/<Relative Path>
87
+ std::wstringstream sectionPathBuilder;
88
+ sectionPathBuilder << L"\\Sessions\\" << sessionId << L"\\BaseNamedObjects" << L"\\WSL\\" << m_machineId << L"\\" << RelativeRootPath;
89
+ auto sectionPath = sectionPathBuilder.str();
90
+
91
+ UNICODE_STRING ntPath{};
92
+ OBJECT_ATTRIBUTES attributes{};
93
+ attributes.Length = sizeof(OBJECT_ATTRIBUTES);
94
+ attributes.ObjectName = &ntPath;
95
+ std::vector<wil::unique_handle> directoryHierarchy;
96
+ auto remainingPath = std::wstring_view(sectionPath.data(), sectionPath.length());
97
+ while (remainingPath.length() > 0)
98
+ {
99
+ // Find the next path substring, ignoring the root path backslash.
100
+ auto nextDir = remainingPath;
101
+ const auto separatorPos = nextDir.find(L"\\", remainingPath[0] == L'\\' ? 1 : 0);
102
+ if (separatorPos != std::wstring_view::npos)
103
+ {
104
+ nextDir = nextDir.substr(0, separatorPos);
105
+ remainingPath = remainingPath.substr(separatorPos + 1, std::wstring_view::npos);
106
+
107
+ // Skip concurrent backslashes.
108
+ while (remainingPath.length() > 0 && remainingPath[0] == L'\\')
109
+ {
110
+ remainingPath = remainingPath.substr(1, std::wstring_view::npos);
111
+ }
112
+ }
113
+ else
114
+ {
115
+ remainingPath = remainingPath.substr(remainingPath.length(), std::wstring_view::npos);
116
+ }
117
+
118
+ attributes.RootDirectory = directoryHierarchy.size() > 0 ? directoryHierarchy.back().get() : nullptr;
119
+ ntPath.Buffer = const_cast<PWCH>(nextDir.data());
120
+ ntPath.Length = sizeof(WCHAR) * gsl::narrow_cast<USHORT>(nextDir.length());
121
+ ntPath.MaximumLength = ntPath.Length;
122
+ wil::unique_handle nextHandle;
123
+ NTSTATUS status = ZwCreateDirectoryObject(&nextHandle, DIRECTORY_ALL_ACCESS, &attributes);
124
+ if (status == STATUS_OBJECT_NAME_COLLISION)
125
+ {
126
+ status = NtOpenDirectoryObject(&nextHandle, MAXIMUM_ALLOWED, &attributes);
127
+ }
128
+ THROW_IF_NTSTATUS_FAILED(status);
129
+ directoryHierarchy.emplace_back(std::move(nextHandle));
130
+ }
131
+
132
+ return {std::move(sectionPath), std::move(directoryHierarchy)};
133
+}
134
+
135
+wil::com_ptr<IPlan9FileSystem> GuestDeviceManager::GetRemoteFileSystem(_In_ REFCLSID clsid, _In_ std::wstring_view tag)
136
+{
137
+ THROW_HR_IF(E_NOT_VALID_STATE, !m_deviceHostSupport);
138
+ return m_deviceHostSupport->GetRemoteFileSystem(clsid, tag);
139
+}
140
+
141
+void GuestDeviceManager::Shutdown()
142
+try
143
+{
144
+ if (m_deviceHostSupport)
145
+ {
146
+ m_deviceHostSupport->Shutdown();
147
+ }
148
+}
149
+CATCH_LOG()
src/windows/service/exe/GuestDeviceManager.h
new
+72
@@ -0,0 +1,72 @@
1
+// Copyright (C) Microsoft Corporation. All rights reserved.
2
+
3
+#pragma once
4
+
5
+#include "DeviceHostProxy.h"
6
+
7
+// Flags for virtiofs vdev device creation.
8
+#define VIRTIO_FS_FLAGS_TYPE_FILES 0x8000
9
+#define VIRTIO_FS_FLAGS_TYPE_SECTIONS 0x4000
10
+
11
+// {872270E1-A899-4AF6-B454-7193634435AD}
12
+DEFINE_GUID(VIRTIO_VIRTIOFS_DEVICE_ID, 0x872270E1, 0xA899, 0x4AF6, 0xB4, 0x54, 0x71, 0x93, 0x63, 0x44, 0x35, 0xAD);
13
+
14
+// {ABB755FC-1B86-4255-83E2-E5787ABCF6C2}
15
+DEFINE_GUID(VIRTIO_PMEM_CLASS_ID, 0xABB755FC, 0x1B86, 0x4255, 0x83, 0xe2, 0xe5, 0x78, 0x7a, 0xbc, 0xf6, 0xc2);
16
+
17
+inline const std::wstring c_defaultDeviceTag = L"default";
18
+
19
+//
20
+// Provides synchronized access to guest device operations.
21
+//
22
+class GuestDeviceManager
23
+{
24
+public:
25
+ GuestDeviceManager(_In_ const std::wstring& machineId, _In_ const GUID& runtimeId);
26
+
27
+ _Requires_lock_not_held_(m_lock)
28
+ GUID AddGuestDevice(
29
+ _In_ const GUID& DeviceId,
30
+ _In_ const GUID& ImplementationClsid,
31
+ _In_ PCWSTR AccessName,
32
+ _In_opt_ PCWSTR Options,
33
+ _In_ PCWSTR Path,
34
+ _In_ UINT32 Flags,
35
+ _In_ HANDLE UserToken);
36
+
37
+ GUID AddNewDevice(_In_ const GUID& deviceId, _In_ const wil::com_ptr<IPlan9FileSystem>& server, _In_ PCWSTR tag);
38
+
39
+ void AddRemoteFileSystem(_In_ REFCLSID clsid, _In_ PCWSTR tag, _In_ const wil::com_ptr<IPlan9FileSystem>& server);
40
+
41
+ void AddSharedMemoryDevice(_In_ const GUID& ImplementationClsid, _In_ PCWSTR Tag, _In_ PCWSTR Path, _In_ UINT32 SizeMb, _In_ HANDLE UserToken);
42
+
43
+ wil::com_ptr<IPlan9FileSystem> GetRemoteFileSystem(_In_ REFCLSID clsid, _In_ std::wstring_view tag);
44
+
45
+ void Shutdown();
46
+
47
+private:
48
+ _Requires_lock_held_(m_lock)
49
+ GUID AddHdvShareWithOptions(
50
+ _In_ const GUID& DeviceId,
51
+ _In_ const GUID& ImplementationClsid,
52
+ _In_ PCWSTR AccessName,
53
+ _In_opt_ PCWSTR Options,
54
+ _In_ PCWSTR Path,
55
+ _In_ UINT32 Flags,
56
+ _In_ HANDLE UserToken);
57
+
58
+ struct DirectoryObjectLifetime
59
+ {
60
+ std::wstring Path;
61
+ // Directory objects are temporary, even if they have children, so need to keep
62
+ // any created handles open in order for the directory to remain accessible.
63
+ std::vector<wil::unique_handle> HierarchyLifetimes;
64
+ };
65
+
66
+ DirectoryObjectLifetime CreateSectionObjectRoot(_In_ std::wstring_view RelativeRootPath, _In_ HANDLE UserToken) const;
67
+
68
+ wil::srwlock m_lock;
69
+ std::wstring m_machineId;
70
+ wil::com_ptr<DeviceHostProxy> m_deviceHostSupport;
71
+ _Guarded_by_(m_lock) std::vector<DirectoryObjectLifetime> m_objectDirectories;
72
+};
src/windows/service/exe/VirtioNetworking.cpp
+63
-16
@@ -2,6 +2,7 @@
2
3
#include "precomp.h"
4
#include "VirtioNetworking.h"
5
+#include "GuestDeviceManager.h"
6
#include "Stringify.h"
7
#include "stringshared.h"
8
@@ -13,15 +14,10 @@ using wsl::core::VirtioNetworking;
14
static constexpr auto c_loopbackDeviceName = TEXT(LX_INIT_LOOPBACK_DEVICE_NAME);
15
16
VirtioNetworking::VirtioNetworking(
16
- GnsChannel&& gnsChannel,
17
- bool enableLocalhostRelay,
18
- AddGuestDeviceCallback addGuestDeviceCallback,
19
- ModifyOpenPortsCallback modifyOpenPortsCallback,
20
- GuestInterfaceStateChangeCallback guestInterfaceStateChangeCallback) :
21
- m_addGuestDeviceCallback(std::move(addGuestDeviceCallback)),
17
+ GnsChannel&& gnsChannel, bool enableLocalhostRelay, std::shared_ptr<GuestDeviceManager> guestDeviceManager, wil::shared_handle userToken) :
18
+ m_guestDeviceManager(std::move(guestDeviceManager)),
19
+ m_userToken(std::move(userToken)),
20
m_gnsChannel(std::move(gnsChannel)),
23
- m_modifyOpenPortsCallback(std::move(modifyOpenPortsCallback)),
24
- m_guestInterfaceStateChangeCallback(std::move(guestInterfaceStateChangeCallback)),
21
m_enableLocalhostRelay(enableLocalhostRelay)
22
{
23
}
@@ -72,11 +68,12 @@ try
68
device_options << L"nameservers=" << dns_servers;
69
}
70
75
- // Add virtio net adapter to guest
76
- m_adapterId = m_addGuestDeviceCallback(c_virtioNetworkClsid, c_virtioNetworkDeviceId, L"eth0", device_options.str().c_str());
77
-
71
auto lock = m_lock.lock_exclusive();
72
73
+ // Add virtio net adapter to guest
74
+ m_adapterId = m_guestDeviceManager->AddGuestDevice(
75
+ c_virtioNetworkDeviceId, c_virtioNetworkClsid, L"eth0", nullptr, device_options.str().c_str(), 0, m_userToken.get());
76
+
77
hns::HNSEndpoint endpointProperties;
78
endpointProperties.ID = m_adapterId;
79
endpointProperties.IPAddress = m_networkSettings->PreferredIpAddress.AddressString;
@@ -121,8 +118,14 @@ CATCH_LOG()
118
119
void VirtioNetworking::SetupLoopbackDevice()
120
{
124
- m_localhostAdapterId = m_addGuestDeviceCallback(
125
- c_virtioNetworkClsid, c_virtioNetworkDeviceId, c_loopbackDeviceName, L"client_ip=127.0.0.1;client_mac=00:11:22:33:44:55");
121
+ m_localhostAdapterId = m_guestDeviceManager->AddGuestDevice(
122
+ c_virtioNetworkDeviceId,
123
+ c_virtioNetworkClsid,
124
+ c_loopbackDeviceName,
125
+ nullptr,
126
+ L"client_ip=127.0.0.1;client_mac=00:11:22:33:44:55",
127
+ 0,
128
+ m_userToken.get());
129
130
hns::HNSEndpoint endpointProperties;
131
endpointProperties.ID = m_localhostAdapterId;
@@ -151,7 +154,7 @@ void VirtioNetworking::StartPortTracker(wil::unique_socket&& socket)
154
m_gnsPortTrackerChannel.emplace(
155
std::move(socket),
156
[&](const SOCKADDR_INET& addr, int protocol, bool allocate) { return HandlePortNotification(addr, protocol, allocate); },
154
- [&](_In_ const std::string& interfaceName, _In_ bool up) { m_guestInterfaceStateChangeCallback(interfaceName, up); });
157
+ [](const std::string&, bool) {}); // TODO: reconsider if InterfaceStateCallback is needed.
158
}
159
160
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
188
localAddr.Ipv6.sin6_port = addr.Ipv6.sin6_port;
189
}
190
}
188
- result = m_modifyOpenPortsCallback(c_virtioNetworkClsid, c_loopbackDeviceName, localAddr, protocol, allocate);
191
+ result = ModifyOpenPorts(c_virtioNetworkClsid, c_loopbackDeviceName, localAddr, protocol, allocate);
192
LOG_HR_IF_MSG(E_FAIL, result != S_OK, "Failure adding localhost relay port %d", localAddr.Ipv4.sin_port);
193
}
194
+
195
if (!loopback)
196
{
193
- const int localResult = m_modifyOpenPortsCallback(c_virtioNetworkClsid, L"eth0", addr, protocol, allocate);
197
+ const int localResult = ModifyOpenPorts(c_virtioNetworkClsid, L"eth0", addr, protocol, allocate);
198
LOG_HR_IF_MSG(E_FAIL, localResult != S_OK, "Failure adding relay port %d", addr.Ipv4.sin_port);
199
if (result == 0)
200
{
201
result = localResult;
202
}
203
}
204
+
205
return result;
206
}
207
208
+int VirtioNetworking::ModifyOpenPorts(_In_ const GUID& clsid, _In_ PCWSTR tag, _In_ const SOCKADDR_INET& addr, _In_ int protocol, _In_ bool isOpen) const
209
+{
210
+ if (protocol != IPPROTO_TCP && protocol != IPPROTO_UDP)
211
+ {
212
+ LOG_HR_MSG(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), "Unsupported bind protocol %d", protocol);
213
+ return 0;
214
+ }
215
+ else if (addr.si_family == AF_INET6)
216
+ {
217
+ // The virtio net adapter does not yet support IPv6 packets, so any traffic would arrive via
218
+ // IPv4. If the caller wants IPv4 they will also likely listen on an IPv4 address, which will
219
+ // be handled as a separate callback to this same code.
220
+ return 0;
221
+ }
222
+
223
+ auto lock = m_lock.lock_exclusive();
224
+ const auto server = m_guestDeviceManager->GetRemoteFileSystem(clsid, c_defaultDeviceTag);
225
+ if (server)
226
+ {
227
+ std::wstring portString = std::format(L"tag={};port_number={}", tag, addr.Ipv4.sin_port);
228
+ if (protocol == IPPROTO_UDP)
229
+ {
230
+ portString += L";udp";
231
+ }
232
+
233
+ if (!isOpen)
234
+ {
235
+ portString += L";allocate=false";
236
+ }
237
+ else
238
+ {
239
+ wchar_t addrStr[16]; // "000.000.000.000" + null terminator
240
+ RtlIpv4AddressToStringW(&addr.Ipv4.sin_addr, addrStr);
241
+ portString += std::format(L";listen_addr={}", addrStr);
242
+ }
243
+
244
+ LOG_IF_FAILED(server->AddShare(portString.c_str(), nullptr, 0));
245
+ }
246
+
247
+ return 0;
248
+}
249
+
250
void NETIOAPI_API_ VirtioNetworking::OnNetworkConnectivityChange(PVOID context, NL_NETWORK_CONNECTIVITY_HINT hint)
251
{
252
static_cast<VirtioNetworking*>(context)->RefreshGuestConnection(hint);
src/windows/service/exe/VirtioNetworking.h
+5
-15
@@ -6,22 +6,14 @@
6
#include "GnsChannel.h"
7
#include "WslCoreHostDnsInfo.h"
8
#include "GnsPortTrackerChannel.h"
9
+#include "GuestDeviceManager.h"
10
11
namespace wsl::core {
12
12
-using AddGuestDeviceCallback = std::function<GUID(const GUID& clsid, const GUID& deviceId, PCWSTR tag, PCWSTR options)>;
13
-using ModifyOpenPortsCallback = std::function<int(const GUID& clsid, PCWSTR tag, const SOCKADDR_INET& addr, int protocol, bool isOpen)>;
14
-using GuestInterfaceStateChangeCallback = std::function<void(const std::string& name, bool isUp)>;
15
-
13
class VirtioNetworking : public INetworkingEngine
14
{
15
public:
19
- VirtioNetworking(
20
- GnsChannel&& gnsChannel,
21
- bool enableLocalhostRelay,
22
- AddGuestDeviceCallback addGuestDeviceCallback,
23
- ModifyOpenPortsCallback modifyOpenPortsCallback,
24
- GuestInterfaceStateChangeCallback guestInterfaceStateChangeCallback);
16
+ VirtioNetworking(GnsChannel&& gnsChannel, bool enableLocalhostRelay, std::shared_ptr<GuestDeviceManager> guestDeviceManager, wil::shared_handle userToken);
17
~VirtioNetworking() = default;
18
19
// Note: This class cannot be moved because m_networkNotifyHandle captures a 'this' pointer.
@@ -43,6 +35,7 @@ private:
35
static std::optional<ULONGLONG> FindVirtioInterfaceLuid(const SOCKADDR_INET& virtioAddress, const NL_NETWORK_CONNECTIVITY_HINT& currentConnectivityHint);
36
37
HRESULT HandlePortNotification(const SOCKADDR_INET& addr, int protocol, bool allocate) const noexcept;
38
+ int ModifyOpenPorts(_In_ const GUID& clsid, _In_ PCWSTR tag, _In_ const SOCKADDR_INET& addr, _In_ int protocol, _In_ bool isOpen) const;
39
void RefreshGuestConnection(NL_NETWORK_CONNECTIVITY_HINT hint) noexcept;
40
void SetupLoopbackDevice();
41
void UpdateDns(wsl::shared::hns::DNS&& dnsSettings);
@@ -50,17 +43,14 @@ private:
43
44
mutable wil::srwlock m_lock;
45
53
- AddGuestDeviceCallback m_addGuestDeviceCallback;
46
+ std::shared_ptr<GuestDeviceManager> m_guestDeviceManager;
47
+ wil::shared_handle m_userToken;
48
GnsChannel m_gnsChannel;
49
std::optional<GnsPortTrackerChannel> m_gnsPortTrackerChannel;
50
std::shared_ptr<networking::NetworkSettings> m_networkSettings;
51
bool m_enableLocalhostRelay;
52
GUID m_localhostAdapterId;
53
GUID m_adapterId;
60
- std::optional<NL_NETWORK_CONNECTIVITY_LEVEL_HINT> m_connectivityLevel;
61
- std::optional<NL_NETWORK_CONNECTIVITY_COST_HINT> m_connectivityCost;
62
- ModifyOpenPortsCallback m_modifyOpenPortsCallback;
63
- GuestInterfaceStateChangeCallback m_guestInterfaceStateChangeCallback;
54
55
std::optional<ULONGLONG> m_interfaceLuid;
56
ULONG m_networkMtu = 0;
src/windows/service/exe/WslCoreVm.cpp
+26
-217
@@ -39,18 +39,10 @@ using namespace std::string_literals;
39
// Start of unaddressable memory if guest only supports the minimum 36-bit addressing.
40
#define MAX_36_BIT_PAGE_IN_MB (0x1000000000 / _1MB)
41
42
-// This device type is implemented by the external virtiofs vdev.
43
-// {872270E1-A899-4AF6-B454-7193634435AD}
44
-DEFINE_GUID(VIRTIO_VIRTIOFS_DEVICE_ID, 0x872270E1, 0xA899, 0x4AF6, 0xB4, 0x54, 0x71, 0x93, 0x63, 0x44, 0x35, 0xAD);
45
-
42
// This device type is implemented by the external virtio-pmem vdev.
43
// {EDBB24BB-5E19-40F4-8A0F-8224313064FD}
44
DEFINE_GUID(VIRTIO_PMEM_DEVICE_ID, 0xEDBB24BB, 0x5E19, 0x40F4, 0x8A, 0x0F, 0x82, 0x24, 0x31, 0x30, 0x64, 0xFD);
45
50
-// Flags for virtiofs vdev device creation.
51
-#define VIRTIO_FS_FLAGS_TYPE_FILES 0x8000
52
-#define VIRTIO_FS_FLAGS_TYPE_SECTIONS 0x4000
53
-
46
// Version numbers for various functionality that was backported.
47
#define NICKEL_BUILD_FLOOR 22350
48
#define VIRTIO_SERIAL_CONSOLE_COBALT_RELEASE_UBR 40
@@ -65,9 +57,6 @@ static constexpr size_t c_bootEntropy = 0x1000;
57
static constexpr auto c_localDevicesKey = L"SOFTWARE\\Microsoft\\Terminal Server Client\\LocalDevices";
58
static constexpr std::pair<uint32_t, uint32_t> c_schemaVersionNickel{2, 7};
59
68
-// {ABB755FC-1B86-4255-83E2-E5787ABCF6C2}
69
-static constexpr GUID c_pmemClassId = {0xABB755FC, 0x1B86, 0x4255, {0x83, 0xe2, 0xe5, 0x78, 0x7a, 0xbc, 0xf6, 0xc2}};
70
-
60
#define LXSS_ENABLE_GUI_APPS() (m_vmConfig.EnableGuiApps && (m_systemDistroDeviceId != ULONG_MAX))
61
62
using namespace wsl::windows::common;
@@ -78,8 +67,6 @@ using wsl::shared::Localization;
67
using wsl::windows::common::Context;
68
using wsl::windows::common::ExecutionContext;
69
81
-const std::wstring WslCoreVm::c_defaultTag = L"default"s;
82
-
70
namespace {
71
INT64
72
RequiredExtraMmioSpaceForPmemFileInMb(_In_ PCWSTR FilePath)
@@ -342,7 +329,8 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken
329
m_runtimeId = wsl::windows::common::hcs::GetRuntimeId(m_system.get());
330
WI_ASSERT(IsEqualGUID(VmId, m_runtimeId));
331
345
- m_deviceHostSupport = wil::MakeOrThrow<DeviceHostProxy>(m_machineId, m_runtimeId);
332
+ // Initialize the guest device manager.
333
+ m_guestDeviceManager = std::make_shared<GuestDeviceManager>(m_machineId, m_runtimeId);
334
335
// Create a socket listening for connections from mini_init.
336
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
457
break;
458
459
case LxMiniInitMountDeviceTypePmem:
472
- m_systemDistroDeviceId = MountFileAsPersistentMemory(c_pmemClassId, m_vmConfig.SystemDistroPath.c_str(), true);
460
+ m_systemDistroDeviceId = MountFileAsPersistentMemory(m_vmConfig.SystemDistroPath.c_str(), true);
461
break;
462
463
default:
@@ -608,15 +596,7 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken
596
else if (m_vmConfig.NetworkingMode == NetworkingMode::VirtioProxy)
597
{
598
m_networkingEngine = std::make_unique<wsl::core::VirtioNetworking>(
611
- std::move(gnsChannel),
612
- m_vmConfig.EnableLocalhostRelay,
613
- [this](const GUID& Clsid, const GUID& DeviceId, PCWSTR Tag, PCWSTR Options) {
614
- return HandleVirtioAddGuestDevice(Clsid, DeviceId, Tag, Options);
615
- },
616
- [this](const GUID& Clsid, PCWSTR Tag, const SOCKADDR_INET& Addr, int Protocol, bool IsOpen) {
617
- return HandleVirtioModifyOpenPorts(Clsid, Tag, Addr, Protocol, IsOpen);
618
- },
619
- [](const std::string&, bool) {});
599
+ std::move(gnsChannel), m_vmConfig.EnableLocalhostRelay, m_guestDeviceManager, m_userToken);
600
}
601
else if (m_vmConfig.NetworkingMode == NetworkingMode::Bridged)
602
{
@@ -799,9 +779,9 @@ WslCoreVm::~WslCoreVm() noexcept
779
}
780
781
// Shutdown virtio device hosts.
802
- if (m_deviceHostSupport)
782
+ if (m_guestDeviceManager)
783
{
804
- m_deviceHostSupport->Shutdown();
784
+ m_guestDeviceManager->Shutdown();
785
}
786
787
// Call RevokeVmAccess on each VHD that was added to the utility VM. This
@@ -955,7 +935,7 @@ void WslCoreVm::AddPlan9Share(
935
936
if (m_vmConfig.EnableVirtio9p)
937
{
958
- server = m_deviceHostSupport->GetRemoteFileSystem(__uuidof(p9fs::Plan9FileSystem), VirtIoTag);
938
+ server = m_guestDeviceManager->GetRemoteFileSystem(__uuidof(p9fs::Plan9FileSystem), VirtIoTag);
939
}
940
else
941
{
@@ -968,10 +948,10 @@ void WslCoreVm::AddPlan9Share(
948
949
if (!server)
950
{
971
- server = CreateComServerAsUser<p9fs::Plan9FileSystem, IPlan9FileSystem>(UserToken);
951
+ server = wsl::windows::common::wslutil::CreateComServerAsUser<p9fs::Plan9FileSystem, IPlan9FileSystem>(UserToken);
952
if (m_vmConfig.EnableVirtio9p)
953
{
974
- m_deviceHostSupport->AddRemoteFileSystem(__uuidof(p9fs::Plan9FileSystem), VirtIoTag, server);
954
+ m_guestDeviceManager->AddRemoteFileSystem(__uuidof(p9fs::Plan9FileSystem), VirtIoTag, server);
955
956
// Start with one device to handle the first mount request. After
957
// each mount, the Plan9 file-system will request additional
@@ -999,64 +979,8 @@ void WslCoreVm::AddPlan9Share(
979
if (addNewDevice)
980
{
981
// This requires more privileges than the user may have, so impersonation is disabled.
1002
- (void)m_deviceHostSupport->AddNewDevice(VIRTIO_PLAN9_DEVICE_ID, server, VirtIoTag);
1003
- }
1004
-}
1005
-
1006
-WslCoreVm::DirectoryObjectLifetime WslCoreVm::CreateSectionObjectRoot(_In_ std::wstring_view RelativeRootPath, _In_ HANDLE UserToken) const
1007
-{
1008
- auto revert = wil::impersonate_token(UserToken);
1009
- DWORD sessionId;
1010
- DWORD bytesWritten;
1011
- THROW_LAST_ERROR_IF(!GetTokenInformation(GetCurrentThreadToken(), TokenSessionId, &sessionId, sizeof(sessionId), &bytesWritten));
1012
-
1013
- // /Sessions/1/BaseNamedObjects/WSL/<VM ID>/<Relative Path>
1014
- std::wstringstream sectionPathBuilder;
1015
- sectionPathBuilder << L"\\Sessions\\" << sessionId << L"\\BaseNamedObjects" << L"\\WSL\\" << m_machineId << L"\\" << RelativeRootPath;
1016
- auto sectionPath = sectionPathBuilder.str();
1017
-
1018
- UNICODE_STRING ntPath{};
1019
- OBJECT_ATTRIBUTES attributes{};
1020
- attributes.Length = sizeof(OBJECT_ATTRIBUTES);
1021
- attributes.ObjectName = &ntPath;
1022
- std::vector<wil::unique_handle> directoryHierarchy;
1023
- auto remainingPath = std::wstring_view(sectionPath.data(), sectionPath.length());
1024
- while (remainingPath.length() > 0)
1025
- {
1026
- // Find the next path substring, ignoring the root path backslash.
1027
- auto nextDir = remainingPath;
1028
- const auto separatorPos = nextDir.find(L"\\", remainingPath[0] == L'\\' ? 1 : 0);
1029
- if (separatorPos != std::wstring_view::npos)
1030
- {
1031
- nextDir = nextDir.substr(0, separatorPos);
1032
- remainingPath = remainingPath.substr(separatorPos + 1, std::wstring_view::npos);
1033
-
1034
- // Skip concurrent backslashes.
1035
- while (remainingPath.length() > 0 && remainingPath[0] == L'\\')
1036
- {
1037
- remainingPath = remainingPath.substr(1, std::wstring_view::npos);
1038
- }
1039
- }
1040
- else
1041
- {
1042
- remainingPath = remainingPath.substr(remainingPath.length(), std::wstring_view::npos);
1043
- }
1044
-
1045
- attributes.RootDirectory = directoryHierarchy.size() > 0 ? directoryHierarchy.back().get() : nullptr;
1046
- ntPath.Buffer = const_cast<PWCH>(nextDir.data());
1047
- ntPath.Length = sizeof(WCHAR) * gsl::narrow_cast<USHORT>(nextDir.length());
1048
- ntPath.MaximumLength = ntPath.Length;
1049
- wil::unique_handle nextHandle;
1050
- NTSTATUS status = ZwCreateDirectoryObject(&nextHandle, DIRECTORY_ALL_ACCESS, &attributes);
1051
- if (status == STATUS_OBJECT_NAME_COLLISION)
1052
- {
1053
- status = NtOpenDirectoryObject(&nextHandle, MAXIMUM_ALLOWED, &attributes);
1054
- }
1055
- THROW_IF_NTSTATUS_FAILED(status);
1056
- directoryHierarchy.emplace_back(std::move(nextHandle));
982
+ (void)m_guestDeviceManager->AddNewDevice(VIRTIO_PLAN9_DEVICE_ID, server, VirtIoTag);
983
}
1058
-
1059
- return {std::move(sectionPath), std::move(directoryHierarchy)};
984
}
985
986
ULONG WslCoreVm::AttachDisk(_In_ PCWSTR Disk, _In_ DiskType Type, _In_ std::optional<ULONG> Lun, _In_ bool IsUserDisk, _In_ HANDLE UserToken)
@@ -1867,7 +1791,8 @@ void WslCoreVm::InitializeGuest()
1791
{
1792
try
1793
{
1870
- MountSharedMemoryDevice(c_virtiofsClassId, L"wslg", L"wslg", WSLG_SHARED_MEMORY_SIZE_MB);
1794
+ m_guestDeviceManager->AddSharedMemoryDevice(
1795
+ c_virtiofsClassId, L"wslg", L"wslg", WSLG_SHARED_MEMORY_SIZE_MB, m_userToken.get());
1796
m_sharedMemoryRoot = std::format(L"WSL\\{}\\wslg", m_machineId);
1797
}
1798
CATCH_LOG()
@@ -1966,7 +1891,7 @@ bool WslCoreVm::InitializeDrvFsLockHeld(_In_ HANDLE UserToken)
1891
{
1892
// Before checking whether DrvFs is already initialized, make sure any existing Plan 9 servers
1893
// are usable.
1969
- VerifyDrvFsServers();
1894
+ VerifyPlan9Servers();
1895
1896
const auto elevated = wsl::windows::common::security::IsTokenElevated(UserToken);
1897
if (elevated)
@@ -2004,53 +1929,6 @@ bool WslCoreVm::IsVhdAttached(_In_ PCWSTR VhdPath)
1929
return m_attachedDisks.contains({DiskType::VHD, VhdPath});
1930
}
1931
2007
-GUID WslCoreVm::HandleVirtioAddGuestDevice(_In_ const GUID& Clsid, _In_ const GUID& DeviceId, _In_ PCWSTR Tag, _In_ PCWSTR Options)
2008
-{
2009
- auto guestDeviceLock = m_guestDeviceLock.lock_exclusive();
2010
- return AddHdvShareWithOptions(DeviceId, Clsid, Tag, {}, Options, 0, m_userToken.get());
2011
-}
2012
-
2013
-int WslCoreVm::HandleVirtioModifyOpenPorts(_In_ const GUID& Clsid, _In_ PCWSTR Tag, _In_ const SOCKADDR_INET& Addr, _In_ int Protocol, _In_ bool IsOpen)
2014
-{
2015
- if (Protocol != IPPROTO_TCP && Protocol != IPPROTO_UDP)
2016
- {
2017
- LOG_HR_MSG(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), "Unsupported bind protocol %d", Protocol);
2018
- return 0;
2019
- }
2020
- else if (Addr.si_family == AF_INET6)
2021
- {
2022
- // The virtio net adapter does not yet support IPv6 packets, so any traffic would arrive via
2023
- // IPv4. If the caller wants IPv4 they will also likely listen on an IPv4 address, which will
2024
- // be handled as a separate callback to this same code.
2025
- return 0;
2026
- }
2027
-
2028
- auto guestDeviceLock = m_guestDeviceLock.lock_exclusive();
2029
- const auto server = m_deviceHostSupport->GetRemoteFileSystem(Clsid, c_defaultTag);
2030
- if (server)
2031
- {
2032
- std::wstring portString = std::format(L"tag={};port_number={}", Tag, Addr.Ipv4.sin_port);
2033
- if (Protocol == IPPROTO_UDP)
2034
- {
2035
- portString += L";udp";
2036
- }
2037
-
2038
- if (!IsOpen)
2039
- {
2040
- portString += L";allocate=false";
2041
- }
2042
- else
2043
- {
2044
- wchar_t addrStr[16]; // "000.000.000.000" + null terminator
2045
- RtlIpv4AddressToStringW(&Addr.Ipv4.sin_addr, addrStr);
2046
- portString += std::format(L";listen_addr={}", addrStr);
2047
- }
2048
-
2049
- LOG_IF_FAILED(server->AddShare(portString.c_str(), nullptr, 0));
2050
- }
2051
- return 0;
2052
-}
2053
-
1932
WslCoreVm::DiskMountResult WslCoreVm::MountDisk(
1933
_In_ PCWSTR Disk, _In_ DiskType MountDiskType, _In_ ULONG PartitionIndex, _In_opt_ PCWSTR Name, _In_opt_ PCWSTR Type, _In_opt_ PCWSTR Options)
1934
{
@@ -2150,33 +2028,8 @@ void WslCoreVm::MountRootNamespaceFolder(_In_ LPCWSTR HostPath, _In_ LPCWSTR Gue
2028
ResultMessage.Result);
2029
}
2030
2153
-void WslCoreVm::MountSharedMemoryDevice(_In_ const GUID& ImplementationClsid, _In_ PCWSTR Tag, _In_ PCWSTR Path, _In_ UINT32 SizeMb)
2154
-{
2155
- if (!m_vmConfig.EnableVirtio)
2156
- {
2157
- return;
2158
- }
2159
-
2160
- auto guestDeviceLock = m_guestDeviceLock.lock_exclusive();
2161
- MountSharedMemoryDeviceLockHeld(ImplementationClsid, Tag, Path, SizeMb);
2162
-}
2163
-
2164
-_Requires_lock_held_(m_guestDeviceLock)
2165
-void WslCoreVm::MountSharedMemoryDeviceLockHeld(_In_ const GUID& ImplementationClsid, _In_ PCWSTR Tag, _In_ PCWSTR Path, _In_ UINT32 SizeMb)
2166
-{
2167
- auto objectLifetime = CreateSectionObjectRoot(Path, m_userToken.get());
2168
-
2169
- // For virtiofs hdv, the flags parameter has been overloaded. Flags are placed in the lower
2170
- // 16 bits, while the shared memory size in megabytes are placed in the upper 16 bits.
2171
- static constexpr auto VIRTIO_FS_FLAGS_SHMEM_SIZE_SHIFT = 16;
2172
- UINT32 flags = (SizeMb << VIRTIO_FS_FLAGS_SHMEM_SIZE_SHIFT);
2173
- WI_SetFlag(flags, VIRTIO_FS_FLAGS_TYPE_SECTIONS);
2174
- (void)AddHdvShare(VIRTIO_VIRTIOFS_DEVICE_ID, ImplementationClsid, Tag, objectLifetime.Path.c_str(), flags, m_userToken.get());
2175
- m_objectDirectories.emplace_back(std::move(objectLifetime));
2176
-}
2177
-
2031
ULONG
2179
-WslCoreVm::MountFileAsPersistentMemory(_In_ const GUID& ImplementationClsid, _In_ PCWSTR FilePath, _In_ bool ReadOnly)
2032
+WslCoreVm::MountFileAsPersistentMemory(_In_ PCWSTR FilePath, _In_ bool ReadOnly)
2033
{
2034
hcs::Plan9ShareFlags flags{};
2035
@@ -2198,7 +2051,7 @@ WslCoreVm::MountFileAsPersistentMemory(_In_ const GUID& ImplementationClsid, _In
2051
// a symlink that points to a path like:
2052
// /sys/devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0004:00/VMBUS:00/<GUID>/pcicceb:00//cceb:00:00.0/virtio1/ndbus0/region0/namespace0.0/block/pmem0
2053
// Notice the GUID in the middle of that path. That GUID is the instance ID, which is randomly
2201
- // generated by AddHdvShare. So once we find a path with the instance ID, we know that
2054
+ // generated by AddGuestDevice. So once we find a path with the instance ID, we know that
2055
// eventually /dev/pmemX will appear in the guest.
2056
auto persistentMemoryLock = m_persistentMemoryLock.lock_exclusive();
2057
@@ -2209,8 +2062,8 @@ WslCoreVm::MountFileAsPersistentMemory(_In_ const GUID& ImplementationClsid, _In
2062
// added as part of VM creation and therefore any failure will result in VM termination
2063
// (in which case there's no need to remove the device).
2064
{
2212
- auto guestDeviceLock = m_guestDeviceLock.lock_exclusive();
2213
- (void)AddHdvShare(VIRTIO_PMEM_DEVICE_ID, ImplementationClsid, L"", FilePath, static_cast<UINT32>(flags), m_userToken.get());
2065
+ (void)m_guestDeviceManager->AddGuestDevice(
2066
+ VIRTIO_PMEM_DEVICE_ID, VIRTIO_PMEM_CLASS_ID, L"", nullptr, FilePath, static_cast<UINT32>(flags), m_userToken.get());
2067
}
2068
2069
// 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)
2112
}
2113
}
2114
2262
-_Requires_lock_held_(m_guestDeviceLock)
2263
-GUID WslCoreVm::AddHdvShareWithOptions(
2264
- _In_ const GUID& DeviceId,
2265
- _In_ const GUID& ImplementationClsid,
2266
- _In_ std::wstring_view AccessName,
2267
- _In_ std::wstring_view Options,
2268
- _In_ std::wstring_view Path,
2269
- _In_ UINT32 Flags,
2270
- _In_ HANDLE UserToken)
2271
-{
2272
- wil::com_ptr<IPlan9FileSystem> server;
2273
-
2274
- THROW_HR_IF(E_NOTIMPL, !m_vmConfig.EnableVirtio);
2275
-
2276
- // Options are appended to the name with a semi-colon separator.
2277
- // "name;key1=value1;key2=value2"
2278
- // The AddSharePath implementation is responsible for separating them out and interpreting them.
2279
- std::wstring nameWithOptions{AccessName};
2280
- if (!Options.empty())
2281
- {
2282
- nameWithOptions += L";";
2283
- nameWithOptions += Options;
2284
- }
2285
-
2286
- {
2287
- auto revert = wil::impersonate_token(UserToken);
2288
-
2289
- server = m_deviceHostSupport->GetRemoteFileSystem(ImplementationClsid, c_defaultTag);
2290
- if (!server)
2291
- {
2292
- server = CreateComServerAsUser<IPlan9FileSystem>(ImplementationClsid, UserToken);
2293
- m_deviceHostSupport->AddRemoteFileSystem(ImplementationClsid, c_defaultTag, server);
2294
- }
2295
-
2296
- const std::wstring SharePath(Path);
2297
- THROW_IF_FAILED(server->AddSharePath(nameWithOptions.c_str(), SharePath.c_str(), Flags));
2298
- }
2299
-
2300
- // This requires more privileges than the user may have, so impersonation is disabled.
2301
- const std::wstring VirtioTag(AccessName);
2302
- return m_deviceHostSupport->AddNewDevice(DeviceId, server, VirtioTag.c_str());
2303
-}
2304
-
2305
-_Requires_lock_held_(m_guestDeviceLock)
2306
-GUID WslCoreVm::AddHdvShare(
2307
- _In_ const GUID& DeviceId, _In_ const GUID& ImplementationClsid, _In_ PCWSTR AccessName, _In_ PCWSTR Path, _In_ UINT32 Flags, _In_ HANDLE UserToken)
2308
-{
2309
- return AddHdvShareWithOptions(DeviceId, ImplementationClsid, AccessName, {}, Path, Flags, UserToken);
2310
-}
2311
-
2115
_Requires_lock_held_(m_guestDeviceLock)
2116
std::wstring WslCoreVm::AddVirtioFsShare(_In_ bool Admin, _In_ PCWSTR Path, _In_ PCWSTR Options, _In_opt_ HANDLE UserToken)
2117
{
@@ -2341,8 +2144,14 @@ std::wstring WslCoreVm::AddVirtioFsShare(_In_ bool Admin, _In_ PCWSTR Path, _In_
2144
tag += std::to_wstring(m_virtioFsShares.size());
2145
WI_ASSERT(!FindVirtioFsShare(tag.c_str(), Admin));
2146
2344
- (void)AddHdvShareWithOptions(
2345
- VIRTIO_VIRTIOFS_DEVICE_ID, Admin ? c_virtiofsAdminClassId : c_virtiofsClassId, tag, key.OptionsString(), sharePath, VIRTIO_FS_FLAGS_TYPE_FILES, UserToken);
2147
+ (void)m_guestDeviceManager->AddGuestDevice(
2148
+ VIRTIO_VIRTIOFS_DEVICE_ID,
2149
+ Admin ? c_virtiofsAdminClassId : c_virtiofsClassId,
2150
+ tag.c_str(),
2151
+ key.OptionsString().c_str(),
2152
+ sharePath.c_str(),
2153
+ VIRTIO_FS_FLAGS_TYPE_FILES,
2154
+ UserToken);
2155
2156
m_virtioFsShares.emplace(std::move(key), tag);
2157
created = true;
@@ -2690,7 +2499,7 @@ std::pair<int, LX_MINI_MOUNT_STEP> WslCoreVm::UnmountVolume(_In_ const AttachedD
2499
}
2500
2501
_Requires_lock_held_(m_guestDeviceLock)
2693
-void WslCoreVm::VerifyDrvFsServers()
2502
+void WslCoreVm::VerifyPlan9Servers()
2503
{
2504
for (auto it = m_plan9Servers.begin(); it != m_plan9Servers.end();)
2505
{
src/windows/service/exe/WslCoreVm.h
+6
-53
@@ -29,6 +29,7 @@ Abstract:
29
#include "INetworkingEngine.h"
30
#include "SocketChannel.h"
31
#include "DeviceHostProxy.h"
32
+#include "GuestDeviceManager.h"
33
34
#define UTILITY_VM_SHUTDOWN_TIMEOUT (30 * 1000)
35
#define UTILITY_VM_TERMINATE_TIMEOUT (30 * 1000)
@@ -107,10 +108,6 @@ public:
108
109
bool IsVhdAttached(_In_ PCWSTR VhdPath);
110
110
- GUID HandleVirtioAddGuestDevice(_In_ const GUID& Clsid, _In_ const GUID& DeviceId, _In_ PCWSTR Tag, _In_ PCWSTR Options);
111
-
112
- int HandleVirtioModifyOpenPorts(_In_ const GUID& Clsid, _In_ PCWSTR Tag, _In_ const SOCKADDR_INET& Addr, _In_ int Protocol, _In_ bool IsOpen);
113
-
111
DiskMountResult MountDisk(
112
_In_ PCWSTR Disk, _In_ DiskType MountDiskType, _In_ ULONG PartitionIndex, _In_opt_ PCWSTR Name, _In_opt_ PCWSTR Type, _In_opt_ PCWSTR Options);
113
@@ -120,10 +117,8 @@ public:
117
ReadOnly = 0x1
118
};
119
123
- void MountSharedMemoryDevice(_In_ const GUID& ImplementationClsid, _In_ PCWSTR Tag, _In_ PCWSTR Path, _In_ UINT32 SizeMb);
124
-
120
ULONG
126
- MountFileAsPersistentMemory(_In_ const GUID& ImplementationClsid, _In_ PCWSTR FilePath, _In_ bool ReadOnly);
121
+ MountFileAsPersistentMemory(_In_ PCWSTR FilePath, _In_ bool ReadOnly);
122
123
void MountRootNamespaceFolder(_In_ LPCWSTR HostPath, _In_ LPCWSTR GuestPath, _In_ bool ReadOnly, _In_ LPCWSTR Name);
124
@@ -135,7 +130,7 @@ public:
130
void SaveAttachedDisksState();
131
132
_Requires_lock_held_(m_guestDeviceLock)
138
- void VerifyDrvFsServers();
133
+ void VerifyPlan9Servers();
134
135
enum DiskStateFlags
136
{
@@ -172,14 +167,6 @@ private:
167
DiskStateFlags Flags;
168
};
169
175
- struct DirectoryObjectLifetime
176
- {
177
- std::wstring Path;
178
- // Directory objects are temporary, even if they have children, so need to keep
179
- // any created handles open in order for the directory to remain accessible.
180
- std::vector<wil::unique_handle> HierarchyLifetimes;
181
- };
182
-
170
struct VirtioFsShare
171
{
172
VirtioFsShare(PCWSTR Path, PCWSTR Options, bool Admin);
@@ -202,19 +189,6 @@ private:
189
_Requires_lock_held_(m_guestDeviceLock)
190
void AddPlan9Share(_In_ PCWSTR AccessName, _In_ PCWSTR Path, _In_ UINT32 Port, _In_ wsl::windows::common::hcs::Plan9ShareFlags Flags, _In_ HANDLE UserToken, _In_ PCWSTR VirtIoTag);
191
205
- _Requires_lock_held_(m_guestDeviceLock)
206
- GUID AddHdvShare(_In_ const GUID& DeviceId, _In_ const GUID& ImplementationClsid, _In_ PCWSTR AccessName, _In_opt_ PCWSTR Path, _In_ UINT32 Flags, _In_ HANDLE UserToken);
207
-
208
- _Requires_lock_held_(m_guestDeviceLock)
209
- GUID AddHdvShareWithOptions(
210
- _In_ const GUID& DeviceId,
211
- _In_ const GUID& ImplementationClsid,
212
- _In_ std::wstring_view AccessName,
213
- _In_ std::wstring_view Options,
214
- _In_ std::wstring_view Path,
215
- _In_ UINT32 Flags,
216
- _In_ HANDLE UserToken);
217
-
192
_Requires_lock_held_(m_guestDeviceLock)
193
std::wstring AddVirtioFsShare(_In_ bool Admin, _In_ PCWSTR Path, _In_ PCWSTR Options, _In_opt_ HANDLE UserToken = nullptr);
194
@@ -223,19 +197,6 @@ private:
197
198
void CollectCrashDumps(wil::unique_socket&& socket) const;
199
226
- template <typename Interface>
227
- wil::com_ptr_t<Interface> CreateComServerAsUser(_In_ REFCLSID RefClsId, _In_ HANDLE UserToken)
228
- {
229
- auto revert = wil::impersonate_token(UserToken);
230
- return wil::CoCreateInstance<Interface>(RefClsId, (CLSCTX_LOCAL_SERVER | CLSCTX_ENABLE_CLOAKING | CLSCTX_ENABLE_AAA));
231
- }
232
-
233
- template <typename Class, typename Interface>
234
- wil::com_ptr_t<Interface> CreateComServerAsUser(_In_ HANDLE UserToken)
235
- {
236
- return CreateComServerAsUser<Interface>(__uuidof(Class), UserToken);
237
- }
238
-
200
std::shared_ptr<LxssRunningInstance> CreateInstanceInternal(
201
_In_ const GUID& InstanceId,
202
_In_ const LXSS_DISTRO_CONFIGURATION& Configuration,
@@ -245,8 +206,6 @@ private:
206
_In_ bool LaunchSystemDistro = false,
207
_Out_opt_ ULONG* ConnectPort = nullptr);
208
248
- DirectoryObjectLifetime CreateSectionObjectRoot(_In_ std::wstring_view RelativeRootPath, _In_ HANDLE UserToken) const;
249
-
209
_Requires_lock_held_(m_lock)
210
void EjectVhdLockHeld(_In_ PCWSTR VhdPath);
211
@@ -281,9 +240,6 @@ private:
240
DiskMountResult MountDiskLockHeld(
241
_In_ PCWSTR Disk, _In_ DiskType MountDiskType, _In_ ULONG PartitionIndex, _In_opt_ PCWSTR Name, _In_opt_ PCWSTR Type, _In_opt_ PCWSTR Options);
242
284
- _Requires_lock_held_(m_guestDeviceLock)
285
- void MountSharedMemoryDeviceLockHeld(_In_ const GUID& ImplementationClsid, _In_ PCWSTR Tag, _In_ PCWSTR Path, _In_ UINT32 SizeMb);
286
-
243
void WaitForPmemDeviceInVm(_In_ ULONG PmemId);
244
245
void OnCrash(_In_ LPCWSTR Details);
@@ -314,12 +270,14 @@ private:
270
271
static void CALLBACK s_OnExit(_In_ HCS_EVENT* Event, _In_opt_ void* Context);
272
317
- wil::srwlock m_lock;
273
wil::srwlock m_guestDeviceLock;
274
+ std::shared_ptr<GuestDeviceManager> m_guestDeviceManager;
275
_Guarded_by_(m_guestDeviceLock) std::future<bool> m_drvfsInitialResult;
276
_Guarded_by_(m_guestDeviceLock) wil::unique_handle m_drvfsToken;
277
_Guarded_by_(m_guestDeviceLock) wil::unique_handle m_adminDrvfsToken;
278
_Guarded_by_(m_guestDeviceLock) std::map<VirtioFsShare, std::wstring> m_virtioFsShares;
279
+ _Guarded_by_(m_guestDeviceLock) std::map<UINT32, wil::com_ptr<IPlan9FileSystem>> m_plan9Servers;
280
+ wil::srwlock m_lock;
281
_Guarded_by_(m_lock) wil::unique_event m_terminatingEvent { wil::EventOptions::ManualReset };
282
_Guarded_by_(m_lock) wil::unique_event m_vmExitEvent { wil::EventOptions::ManualReset };
283
wil::unique_event m_vmCrashEvent{wil::EventOptions::ManualReset};
@@ -351,12 +309,9 @@ private:
309
wsl::shared::SocketChannel m_miniInitChannel;
310
wil::unique_socket m_notifyChannel;
311
SE_SID m_userSid;
354
- wil::com_ptr<DeviceHostProxy> m_deviceHostSupport;
312
std::shared_ptr<LxssRunningInstance> m_systemDistro;
313
_Guarded_by_(m_lock) std::bitset<MAX_VHD_COUNT> m_lunBitmap;
314
_Guarded_by_(m_lock) std::map<AttachedDisk, DiskState> m_attachedDisks;
358
- _Guarded_by_(m_guestDeviceLock) std::map<UINT32, wil::com_ptr<IPlan9FileSystem>> m_plan9Servers;
359
- _Guarded_by_(m_guestDeviceLock) std::vector<DirectoryObjectLifetime> m_objectDirectories;
315
std::tuple<std::uint32_t, std::uint32_t, std::uint32_t> m_kernelVersion;
316
std::wstring m_kernelVersionString;
317
bool m_seccompAvailable;
@@ -375,8 +330,6 @@ private:
330
_Guarded_by_(m_persistentMemoryLock) ULONG m_nextPersistentMemoryId = 0;
331
332
std::unique_ptr<wsl::core::INetworkingEngine> m_networkingEngine;
378
-
379
- static const std::wstring c_defaultTag;
333
};
334
335
DEFINE_ENUM_FLAG_OPERATORS(WslCoreVm::DiskStateFlags);