master
h 394 lines 16.6 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 WslCoreConfig.h
8
9 Abstract:
10
11 This file contains the WSL Core VM configuration helper class declaration.
12
13 --*/
14
15 #pragma once
16
17 #define T_ENUM(c, n) TraceLoggingValue(wsl::core::ToString((c).n), #n)
18 #define T_PRESENT(c, n) TraceLoggingValue((c).n == ConfigKeyPresence::Present, #n)
19 #define T_SET(c, n) TraceLoggingValue(!(c).n.empty(), #n "Set")
20 #define T_STRING(c, n) TraceLoggingValue((c).n.c_str(), #n)
21 #define T_VALUE(c, n) TraceLoggingValue((c).n, #n)
22
23 #define CONFIG_TELEMETRY(c) \
24 T_VALUE(c, BestEffortDnsParsing), T_VALUE(c, DhcpTimeout), T_VALUE(c, EnableAutoProxy), T_VALUE(c, EnableDebugConsole), \
25 T_VALUE(c, EnableDebugShell), T_VALUE(c, EnableDhcp), T_VALUE(c, EnableDnsProxy), T_VALUE(c, EnableDnsTunneling), \
26 T_VALUE(c, EnableGpuSupport), T_VALUE(c, EnableGuiApps), T_VALUE(c, EnableHardwarePerformanceCounters), \
27 T_VALUE(c, EnableHostAddressLoopback), T_VALUE(c, EnableHostFileSystemAccess), T_VALUE(c, EnableIpv6), \
28 T_VALUE(c, EnableLocalhostRelay), T_VALUE(c, EnableNestedVirtualization), T_VALUE(c, EnableSafeMode), \
29 T_VALUE(c, EnableSparseVhd), T_VALUE(c, EnableVirtio), T_VALUE(c, EnableVirtio9p), T_VALUE(c, EnableVirtioFs), \
30 T_VALUE(c, EnableVirtioFsAggregateShares), T_ENUM(c, FirewallConfigPresence), T_VALUE(c, IsolateDistroCgroup), \
31 T_VALUE(c, KernelBootTimeout), T_SET(c, KernelCommandLine), T_VALUE(c, KernelDebugPort), T_STRING(c, KernelModulesList), \
32 T_SET(c, KernelModulesPath), T_SET(c, KernelPath), T_VALUE(c, LoadDefaultKernelModules), \
33 T_PRESENT(c, LoadKernelModulesPresence), T_VALUE(c, MaximumMemorySizeBytes), T_VALUE(c, MaximumProcessorCount), \
34 T_ENUM(c, MemoryReclaim), T_VALUE(c, MemorySizeBytes), T_VALUE(c, MountDeviceTimeout), T_ENUM(c, NetworkingMode), \
35 T_VALUE(c, ProcessorCount), T_SET(c, SwapFilePath), T_VALUE(c, SwapSizeBytes), T_VALUE(c, SwiotlbSizeBytes), \
36 T_SET(c, SystemDistroPath), T_VALUE(c, VhdSizeBytes), T_VALUE(c, VmIdleTimeout), T_SET(c, VmSwitch)
37
38 namespace wsl::core {
39 constexpr auto ToString(ConfigKeyPresence key)
40 {
41 switch (key)
42 {
43 case ConfigKeyPresence::Absent:
44 return "Absent";
45 case ConfigKeyPresence::Present:
46 return "Present";
47 default:
48 return "Invalid";
49 }
50 }
51
52 enum class MemoryReclaimMode
53 {
54 Disabled,
55 Gradual,
56 DropCache
57 };
58
59 // Ensure the WslCoreConfig versions of the enum match the version that's used in mini init.
60 static_assert(static_cast<ULONG>(MemoryReclaimMode::Disabled) == LxMiniInitMemoryReclaimModeDisabled);
61 static_assert(static_cast<ULONG>(MemoryReclaimMode::Gradual) == LxMiniInitMemoryReclaimModeGradual);
62 static_assert(static_cast<ULONG>(MemoryReclaimMode::DropCache) == LxMiniInitMemoryReclaimModeDropCache);
63
64 constexpr auto ToString(MemoryReclaimMode mode)
65 {
66 switch (mode)
67 {
68 case MemoryReclaimMode::Disabled:
69 return "Disabled";
70 case MemoryReclaimMode::Gradual:
71 return "Gradual";
72 case MemoryReclaimMode::DropCache:
73 return "DropCache";
74 default:
75 return "Invalid";
76 }
77 }
78
79 const std::map<std::string, MemoryReclaimMode, shared::string::CaseInsensitiveCompare> MemoryReclaimModes = {
80 {ToString(MemoryReclaimMode::Gradual), MemoryReclaimMode::Gradual},
81 {ToString(MemoryReclaimMode::DropCache), MemoryReclaimMode::DropCache},
82 {ToString(MemoryReclaimMode::Disabled), MemoryReclaimMode::Disabled}};
83
84 // N.B. These enum values are also used in InTune ADMX templates, if entries are added or removed ensure that existing
85 // values are not changed.
86 enum NetworkingMode
87 {
88 None = 0,
89 Nat = 1,
90 Bridged = 2,
91 Mirrored = 3,
92 Consomme = 4
93 };
94
95 // Ensure the WslCoreConfig versions of the enum match the version that's used in mini init.
96 static_assert(static_cast<ULONG>(NetworkingMode::None) == LxMiniInitNetworkingModeNone);
97 static_assert(static_cast<ULONG>(NetworkingMode::Nat) == LxMiniInitNetworkingModeNat);
98 static_assert(static_cast<ULONG>(NetworkingMode::Bridged) == LxMiniInitNetworkingModeBridged);
99 static_assert(static_cast<ULONG>(NetworkingMode::Mirrored) == LxMiniInitNetworkingModeMirrored);
100 static_assert(static_cast<ULONG>(NetworkingMode::Consomme) == LxMiniInitNetworkingModeConsomme);
101
102 constexpr auto ToString(NetworkingMode config) noexcept
103 {
104 switch (config)
105 {
106 case NetworkingMode::None:
107 return "None";
108 case NetworkingMode::Nat:
109 return "Nat";
110 case NetworkingMode::Bridged:
111 return "Bridged";
112 case NetworkingMode::Mirrored:
113 return "Mirrored";
114 case NetworkingMode::Consomme:
115 return "Consomme";
116 default:
117 return "Invalid";
118 }
119 }
120
121 const std::map<std::string, wsl::core::NetworkingMode, shared::string::CaseInsensitiveCompare> NetworkingModes{
122 {ToString(NetworkingMode::None), NetworkingMode::None},
123 {ToString(NetworkingMode::Nat), NetworkingMode::Nat},
124 {ToString(NetworkingMode::Bridged), NetworkingMode::Bridged},
125 {ToString(NetworkingMode::Mirrored), NetworkingMode::Mirrored},
126 {ToString(NetworkingMode::Consomme), NetworkingMode::Consomme},
127 // Legacy alias: the Consomme networking mode was previously named "VirtioProxy".
128 {"VirtioProxy", NetworkingMode::Consomme}};
129
130 enum class FirewallAction
131 {
132 Invalid,
133 Allow,
134 Block
135 };
136
137 constexpr auto ToString(const FirewallAction Action) noexcept
138 {
139 switch (Action)
140 {
141 case FirewallAction::Allow:
142 return "Allow";
143 case FirewallAction::Block:
144 return "Block";
145 default:
146 return "Invalid";
147 }
148 }
149
150 enum class FirewallRuleOperation
151 {
152 Invalid,
153 Add,
154 Delete
155 };
156
157 struct FirewallRuleConfiguration
158 {
159 // These values are shared_bstr because we make temporary copies (for example in ConfigureHyperVFirewall)
160 wil::shared_bstr RuleId;
161 wil::shared_bstr RuleName;
162 wil::shared_bstr Protocol;
163 std::vector<wil::shared_bstr> LocalPorts;
164 std::vector<wil::shared_bstr> LocalAddresses;
165 std::vector<wil::shared_bstr> RemoteAddresses;
166 FirewallRuleOperation RuleOperation;
167 // NOTE these are only applicable for HOST firewall rules
168 wil::shared_bstr LocalService;
169 wil::shared_bstr LocalApplication;
170
171 FirewallRuleConfiguration& operator=(const FirewallRuleConfiguration&) = default;
172 FirewallRuleConfiguration& operator=(FirewallRuleConfiguration&&) = default;
173 FirewallRuleConfiguration(FirewallRuleConfiguration&&) = default;
174 FirewallRuleConfiguration(const FirewallRuleConfiguration&) = default;
175
176 FirewallRuleConfiguration(
177 _In_ LPCWSTR RuleIdParam,
178 _In_opt_ LPCWSTR RuleNameParam = nullptr,
179 _In_opt_ LPCWSTR ProtocolParam = nullptr,
180 _In_ DWORD LocalPortsCountParam = 0,
181 _In_reads_opt_(LocalPortsCountParam) LPCWSTR* LocalPortsParam = nullptr,
182 _In_ DWORD LocalAddressesCountParam = 0,
183 _In_reads_opt_(LocalAddressesCountParam) LPCWSTR* LocalAddressesParam = nullptr,
184 _In_ DWORD RemoteAddressesCountParam = 0,
185 _In_reads_opt_(RemoteAddressesCountParam) LPCWSTR* RemoteAddressesParam = nullptr,
186 _In_opt_ LPCWSTR LocalServiceParam = nullptr,
187 _In_opt_ LPCWSTR LocalApplicationParam = nullptr,
188 _In_ FirewallRuleOperation RuleOperationParam = FirewallRuleOperation::Add)
189 {
190 RuleId = wil::make_bstr(RuleIdParam);
191 if (RuleNameParam)
192 {
193 RuleName = wil::make_bstr(RuleNameParam);
194 }
195 if (ProtocolParam)
196 {
197 Protocol = wil::make_bstr(ProtocolParam);
198 }
199 for (ULONG i = 0; i < LocalPortsCountParam; ++i)
200 {
201 LocalPorts.emplace_back(wil::make_bstr(LocalPortsParam[i]));
202 }
203 for (ULONG i = 0; i < LocalAddressesCountParam; ++i)
204 {
205 LocalAddresses.emplace_back(wil::make_bstr(LocalAddressesParam[i]));
206 }
207 for (ULONG i = 0; i < RemoteAddressesCountParam; ++i)
208 {
209 RemoteAddresses.emplace_back(wil::make_bstr(RemoteAddressesParam[i]));
210 }
211 if (LocalServiceParam)
212 {
213 LocalService = wil::make_bstr(LocalServiceParam);
214 }
215 if (LocalApplicationParam)
216 {
217 LocalApplication = wil::make_bstr(LocalApplicationParam);
218 }
219 RuleOperation = RuleOperationParam;
220 }
221 };
222
223 struct FirewallConfiguration
224 {
225 std::optional<GUID> VmCreatorId{};
226 std::vector<FirewallRuleConfiguration> Rules{};
227 FirewallAction DefaultLoopbackPolicy{FirewallAction::Invalid};
228
229 bool Enabled() const noexcept;
230
231 void reset() noexcept;
232
233 void Enable() noexcept;
234 };
235
236 namespace ConfigSetting {
237 static constexpr auto Kernel = "wsl2.kernel";
238 static constexpr auto KernelCommandLine = "wsl2.kernelCommandLine";
239 static constexpr auto KernelModules = "wsl2.kernelModules";
240 static constexpr auto Memory = "wsl2.memory";
241 static constexpr auto Processors = "wsl2.processors";
242 static constexpr auto DebugConsole = "wsl2.debugConsole";
243 static constexpr auto EarlyBootLogging = "wsl2.earlyBootLogging";
244 static constexpr auto Swap = "wsl2.swap";
245 static constexpr auto SwapFile = "wsl2.swapFile";
246 static constexpr auto LocalhostForwarding = "wsl2.localhostForwarding";
247 static constexpr auto NestedVirtualization = "wsl2.nestedVirtualization";
248 static constexpr auto Virtio9p = "wsl2.virtio9p";
249 static constexpr auto Virtiofs = "wsl2.virtiofs";
250 static constexpr auto KernelDebugPort = "wsl2.kernelDebugPort";
251 static constexpr auto GpuSupport = "wsl2.gpuSupport";
252 static constexpr auto GuiApplications = "wsl2.guiApplications";
253 static constexpr auto SystemDistro = "wsl2.systemDistro";
254 static constexpr auto Telemetry = "wsl2.telemetry";
255 static constexpr auto VmIdleTimeout = "wsl2.vmIdleTimeout";
256 static constexpr auto DebugConsoleLogFile = "wsl2.debugConsoleLogFile";
257 static constexpr auto KernelBootTimeout = "wsl2.kernelBootTimeout";
258 static constexpr auto DistributionStartTimeout = "wsl2.distributionStartTimeout";
259 static constexpr auto Virtio = "wsl2.virtio";
260 static constexpr auto HostFileSystemAccess = "wsl2.hostFileSystemAccess";
261 static constexpr auto MountDeviceTimeout = "wsl2.mountDeviceTimeout";
262 static constexpr auto HardwarePerformanceCounters = "wsl2.hardwarePerformanceCounters";
263 static constexpr auto NetworkingMode = "wsl2.networkingMode";
264 static constexpr auto VmSwitch = "wsl2.vmSwitch";
265 static constexpr auto MacAddress = "wsl2.macAddress";
266 static constexpr auto Dhcp = "wsl2.dhcp";
267 static constexpr auto DhcpTimeout = "wsl2.dhcpTimeout";
268 static constexpr auto Ipv6 = "wsl2.ipv6";
269 static constexpr auto DnsProxy = "wsl2.dnsProxy";
270 static constexpr auto SafeMode = "wsl2.safeMode";
271 static constexpr auto DefaultVhdSize = "wsl2.defaultVhdSize";
272 static constexpr auto CrashDumpFolder = "wsl2.crashDumpFolder";
273 static constexpr auto MaxCrashDumpCount = "wsl2.maxCrashDumpCount";
274 static constexpr auto DistributionInstallPath = "general.distributionInstallPath";
275 static constexpr auto InstanceIdleTimeout = "general.instanceIdleTimeout";
276 static constexpr auto DnsTunneling = "wsl2.dnsTunneling";
277 static constexpr auto Firewall = "wsl2.firewall";
278 static constexpr auto AutoProxy = "wsl2.autoProxy";
279 static constexpr auto LoadKernelModules = "wsl2.loadKernelModules";
280 static constexpr auto LoadDefaultKernelModules = "wsl2.loadDefaultKernelModules";
281 static constexpr auto IsolateDistroCgroup = "wsl2.isolateDistroCgroup";
282
283 namespace Experimental {
284 static constexpr auto NetworkingMode = "experimental.networkingMode";
285 static constexpr auto AutoMemoryReclaim = "experimental.autoMemoryReclaim";
286 static constexpr auto SparseVhd = "experimental.sparseVhd";
287 static constexpr auto DnsTunneling = "experimental.dnsTunneling";
288 static constexpr auto BestEffortDnsParsing = "experimental.bestEffortDnsParsing";
289 static constexpr auto DnsTunnelingIpAddress = "experimental.dnsTunnelingIpAddress";
290 static constexpr auto Firewall = "experimental.firewall";
291 static constexpr auto AutoProxy = "experimental.autoProxy";
292 static constexpr auto InitialAutoProxyTimeout = "experimental.initialAutoProxyTimeout";
293 static constexpr auto IgnoredPorts = "experimental.ignoredPorts";
294 static constexpr auto HostAddressLoopback = "experimental.hostAddressLoopback";
295 static constexpr auto SetVersionDebug = "experimental.setVersionDebug";
296 static constexpr auto Swiotlb = "experimental.swiotlb";
297 static constexpr auto VirtioFsAggregateShares = "experimental.virtioFsAggregateShares";
298
299 } // namespace Experimental
300 } // namespace ConfigSetting
301
302 struct Config
303 {
304 Config() = delete;
305 Config(_In_opt_ LPCWSTR Path = nullptr, _In_opt_ HANDLE UserToken = nullptr);
306 ~Config() = default;
307
308 void Initialize(_In_opt_ HANDLE UserToken = nullptr);
309 void ParseConfigFile(_In_opt_ LPCWSTR ConfigFilePath, _In_opt_ HANDLE UserToken);
310 void SaveNetworkingSettings(_In_opt_ HANDLE UserToken) const;
311 static unsigned long WriteConfigFile(_In_ LPCWSTR ConfigFilePath, _In_ ConfigKey KeyToWrite, _In_ bool RemoveKey = false);
312
313 std::filesystem::path KernelPath;
314 std::wstring KernelCommandLine;
315 std::wstring KernelModulesList;
316 std::filesystem::path KernelModulesPath;
317 UINT64 MemorySizeBytes = 0;
318 UINT64 MaximumMemorySizeBytes = 0;
319 int ProcessorCount = 0;
320 int MaximumProcessorCount = 0;
321 bool EnableDebugConsole = false;
322 bool EnableEarlyBootLogging = false;
323 UINT64 SwapSizeBytes = UINT64_MAX;
324 std::filesystem::path SwapFilePath;
325 bool EnableLocalhostRelay = true;
326 ConfigKeyPresence LocalhostRelayConfigPresence = ConfigKeyPresence::Absent;
327 ConfigKeyPresence LoadKernelModulesPresence = ConfigKeyPresence::Absent;
328 bool LoadDefaultKernelModules = true;
329 bool EnableNestedVirtualization = !shared::Arm64 && windows::common::helpers::IsWindows11OrAbove();
330 bool EnableVirtio9p = false;
331 bool EnableVirtio = !shared::Arm64 || windows::common::helpers::IsWindows11OrAbove();
332 bool EnableVirtioFs = false;
333 bool EnableVirtioFsAggregateShares = true;
334 int KernelDebugPort = 0;
335 bool EnableGpuSupport = true;
336 bool EnableGuiApps = true;
337 std::filesystem::path SystemDistroPath;
338 bool EnableTelemetry = shared::OfficialBuild;
339 int VmIdleTimeout = (60 * 1000);
340 int InstanceIdleTimeout = (15 * 1000);
341 std::filesystem::path DebugConsoleLogFile;
342 std::wstring VmSwitch;
343 int KernelBootTimeout = (30 * 1000);
344 int DistributionStartTimeout = (60 * 1000);
345 int MountDeviceTimeout = (5 * 1000);
346 bool EnableHostFileSystemAccess = true;
347 bool EnableDhcp = true;
348 bool EnableIpv6 = false;
349 int DhcpTimeout = (5 * 1000);
350 NetworkingMode NetworkingMode = NetworkingMode::Nat;
351 ConfigKeyPresence NetworkingModePresence = ConfigKeyPresence::Absent;
352 bool EnableDnsProxy = true;
353 bool EnableSafeMode = false;
354 bool EnableDnsTunneling = true;
355 std::filesystem::path DefaultDistributionLocation;
356 ConfigKeyPresence DnsTunnelingConfigPresence = ConfigKeyPresence::Absent;
357 // Only applicable when DNS tunneling is enabled
358 //
359 // In a DNS request from Linux there might be DNS records that Windows DNS client does not know how to parse.
360 // By default in this case Windows will fail the request. When the flag is enabled, Windows will extract the
361 // question from the DNS request and attempt to resolve it, ignoring the unknown records
362 bool BestEffortDnsParsing = false;
363 // Only applicable when DNS tunneling is enabled
364 // IP address that will be used by the DNS listener/proxy used for DNS tunneling. Some scenarios (such as native Docker)
365 // require Linux nameserver to be an IP that is not in the range 127.0.0.0/8. This config is intended for those scenarios.
366 std::optional<uint32_t> DnsTunnelingIpAddress;
367 bool EnableHardwarePerformanceCounters = !shared::Arm64;
368 bool EnableAutoProxy = true;
369 int InitialAutoProxyTimeout = 1000;
370 MemoryReclaimMode MemoryReclaim = MemoryReclaimMode::DropCache;
371 bool EnableSparseVhd = false;
372 UINT64 VhdSizeBytes = 0x10000000000; // 1TB
373
374 wsl::shared::string::MacAddress MacAddress;
375 std::wstring NatIpAddress;
376 std::wstring NatGateway;
377 std::wstring NatNetwork;
378 bool EnableDebugShell = true;
379 FirewallConfiguration FirewallConfig;
380 ConfigKeyPresence FirewallConfigPresence = ConfigKeyPresence::Absent;
381 std::set<uint16_t> IgnoredPorts;
382 bool EnableHostAddressLoopback = false;
383 std::filesystem::path CrashDumpFolder;
384 int MaxCrashDumpCount = 10;
385 UINT64 SwiotlbSizeBytes = 0;
386 bool IsolateDistroCgroup = true;
387
388 // Temporary config value to help root cause the truncated archive errors in SetVersion()
389 bool SetVersionDebug = false;
390
391 GUID NatNetworkId() const noexcept;
392 LPCWSTR NatNetworkName() const noexcept;
393 };
394 } // namespace wsl::core