commit 86fda9f51fcd98b98ea4d7216edc4d057d221093
parent 2f344f090bce1dd633d2a655f61d5b5c16a702f0
Author: yao-msft <50888816+yao-msft@users.noreply.github.com>
Date: Tue, 18 Mar 2025 17:29:25 -0700
Fix DynamicProcessor crash when working on individual units without a set (#5304)
Added unit test. Manually validated as well.
Diffstat:
2 files changed, 67 insertions(+), 26 deletions(-)
diff --git a/src/AppInstallerCLICore/ConfigurationDynamicRuntimeFactory.cpp b/src/AppInstallerCLICore/ConfigurationDynamicRuntimeFactory.cpp
@@ -163,9 +163,12 @@ namespace AppInstaller::CLI::ConfigurationRemoting
m_dynamicFactory(std::move(dynamicFactory)), m_configurationSet(configurationSet)
{
#ifndef AICLI_DISABLE_TEST_HOOKS
- m_enableTestMode = GetConfigurationSetMetadataOverride(m_configurationSet, EnableTestModeTestGuid);
- m_enableRestrictedIntegrityLevel = GetConfigurationSetMetadataOverride(m_configurationSet, EnableRestrictedIntegrityLevelTestGuid);
- m_forceHighIntegrityLevelUnits = GetConfigurationSetMetadataOverride(m_configurationSet, ForceHighIntegrityLevelUnitsTestGuid);
+ if (m_configurationSet)
+ {
+ m_enableTestMode = GetConfigurationSetMetadataOverride(m_configurationSet, EnableTestModeTestGuid);
+ m_enableRestrictedIntegrityLevel = GetConfigurationSetMetadataOverride(m_configurationSet, EnableRestrictedIntegrityLevelTestGuid);
+ m_forceHighIntegrityLevelUnits = GetConfigurationSetMetadataOverride(m_configurationSet, ForceHighIntegrityLevelUnitsTestGuid);
+ }
m_currentIntegrityLevel = m_enableTestMode ? Security::IntegrityLevel::Medium : Security::GetEffectiveIntegrityLevel();
#else
@@ -173,32 +176,36 @@ namespace AppInstaller::CLI::ConfigurationRemoting
#endif
m_setIntegrityLevel = m_currentIntegrityLevel;
- m_setIntegrityLevel = SecurityContextToIntegrityLevel(m_configurationSet.Environment().Context());
- // Check for multiple integrity level requirements
- bool multipleIntegrityLevels = false;
- bool higherIntegrityLevelsThanCurrent = false;
- for (const auto& environment : m_configurationSet.GetUnitEnvironments())
+ if (m_configurationSet)
{
- auto integrityLevel = SecurityContextToIntegrityLevel(environment.Context());
- if (integrityLevel != m_currentIntegrityLevel)
- {
- multipleIntegrityLevels = true;
+ m_setIntegrityLevel = SecurityContextToIntegrityLevel(m_configurationSet.Environment().Context());
- if (ToIntegral(m_currentIntegrityLevel) < ToIntegral(integrityLevel))
+ // Check for multiple integrity level requirements
+ bool multipleIntegrityLevels = false;
+ bool higherIntegrityLevelsThanCurrent = false;
+ for (const auto& environment : m_configurationSet.GetUnitEnvironments())
+ {
+ auto integrityLevel = SecurityContextToIntegrityLevel(environment.Context());
+ if (integrityLevel != m_currentIntegrityLevel)
{
- higherIntegrityLevelsThanCurrent = true;
- break;
+ multipleIntegrityLevels = true;
+
+ if (ToIntegral(m_currentIntegrityLevel) < ToIntegral(integrityLevel))
+ {
+ higherIntegrityLevelsThanCurrent = true;
+ break;
+ }
}
}
- }
- // Prevent supplied parameters from crossing integrity levels
- for (const auto& parameter : m_configurationSet.Parameters())
- {
- if (parameter.ProvidedValue() != nullptr)
+ // Prevent supplied parameters from crossing integrity levels
+ for (const auto& parameter : m_configurationSet.Parameters())
{
- THROW_HR_IF(WINGET_CONFIG_ERROR_PARAMETER_INTEGRITY_BOUNDARY, higherIntegrityLevelsThanCurrent || (multipleIntegrityLevels && parameter.IsSecure()));
+ if (parameter.ProvidedValue() != nullptr)
+ {
+ THROW_HR_IF(WINGET_CONFIG_ERROR_PARAMETER_INTEGRITY_BOUNDARY, higherIntegrityLevelsThanCurrent || (multipleIntegrityLevels && parameter.IsSecure()));
+ }
}
}
@@ -219,13 +226,16 @@ namespace AppInstaller::CLI::ConfigurationRemoting
std::call_once(m_createUnitSetProcessorsOnce,
[&]()
{
- for (const auto& environment : m_configurationSet.GetUnitEnvironments())
+ if (m_configurationSet)
{
- Security::IntegrityLevel requiredIntegrityLevel = SecurityContextToIntegrityLevel(environment.Context());
-
- if (m_setProcessors.find(requiredIntegrityLevel) == m_setProcessors.end())
+ for (const auto& environment : m_configurationSet.GetUnitEnvironments())
{
- CreateSetProcessorForIntegrityLevel(requiredIntegrityLevel);
+ Security::IntegrityLevel requiredIntegrityLevel = SecurityContextToIntegrityLevel(environment.Context());
+
+ if (m_setProcessors.find(requiredIntegrityLevel) == m_setProcessors.end())
+ {
+ CreateSetProcessorForIntegrityLevel(requiredIntegrityLevel);
+ }
}
}
});
@@ -240,6 +250,7 @@ namespace AppInstaller::CLI::ConfigurationRemoting
auto itr = m_setProcessors.find(requiredIntegrityLevel);
if (itr == m_setProcessors.end())
{
+ THROW_WIN32_IF_MSG(ERROR_NOT_SUPPORTED, !m_configurationSet, "Using configuration unit integrity level other than current level without a configuration set is not supported.");
itr = CreateSetProcessorForIntegrityLevel(requiredIntegrityLevel);
}
diff --git a/src/Microsoft.Management.Configuration.UnitTests/Tests/ConfigurationMixedElevationTests.cs b/src/Microsoft.Management.Configuration.UnitTests/Tests/ConfigurationMixedElevationTests.cs
@@ -269,5 +269,35 @@ namespace Microsoft.Management.Configuration.UnitTests.Tests
// Once they are implemented, swap to the appropriate error mechanism for the parameter integrity boundary.
Assert.Throws<NotImplementedException>(() => processor.ApplySet(configurationSet, ApplyConfigurationSetFlags.None));
}
+
+ /// <summary>
+ /// Verifies that DynamicFactoryProcessors do not break on empty set when working with only units.
+ /// </summary>
+ /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
+ [Fact]
+ public async Task CreateDynamicFactoryProcessorsWithEmptyConfigurationSet()
+ {
+ string resourceName = "E2ETestResourcePID";
+ string moduleName = "xE2ETestResource";
+ Version version = new Version("0.0.0.1");
+
+ string tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
+ Directory.CreateDirectory(tempDirectory);
+
+ ConfigurationUnit unit = this.ConfigurationUnit();
+ unit.Metadata.Add("version", version.ToString());
+ unit.Metadata.Add("module", moduleName);
+ unit.Settings.Add("directoryPath", tempDirectory);
+ unit.Type = resourceName;
+ unit.Intent = ConfigurationUnitIntent.Inform;
+
+ IConfigurationSetProcessorFactory dynamicFactory = await this.fixture.ConfigurationStatics.CreateConfigurationSetProcessorFactoryAsync(Helpers.Constants.DynamicRuntimeHandlerIdentifier);
+
+ ConfigurationProcessor processor = this.CreateConfigurationProcessorWithDiagnostics(dynamicFactory);
+
+ var result = await processor.GetUnitSettingsAsync(unit);
+
+ Assert.NotNull(result);
+ }
}
}