From 214743ee2a5a25b9a3a07e3f0451da73eb4e97e2 Mon Sep 17 00:00:00 2001 From: Elinor Fung Date: Thu, 1 May 2025 19:01:21 +0000 Subject: [PATCH 1/2] Merged PR 49479: [internal/release/9.0] Fix issue where libhost scenarios (COM, C++/CLI, custom component host) could try to load coreclr from CWD There is a fallback for apps with no .deps.json where the host will consider the app directory for loading coreclr. In component hosting scenarios, we do not have an app path / directory. We were incorrectly going down the path of looking for coreclr next to the empty app directory, which resulted in looking in the current directory. This change skips that path for libhost scenarios. It also adds checks that the paths we determine for loading coreclr, hostpolicy, and hostfxr are absolute. --- .../NativeHosting/Comhost.cs | 29 +++++++++++++++++ .../NativeHosting/Ijwhost.cs | 26 +++++++++++++++ .../LoadAssemblyAndGetFunctionPointer.cs | 32 +++++++++++++++++++ ...ns.cs => NativeHostingResultExtensions.cs} | 19 ++++++++++- .../apphost/standalone/hostfxr_resolver.cpp | 5 +++ .../fxr/standalone/hostpolicy_resolver.cpp | 4 +++ src/native/corehost/fxr_resolver.h | 4 +++ .../corehost/hostpolicy/deps_resolver.cpp | 16 +++++++--- .../standalone/coreclr_resolver.cpp | 4 +++ 9 files changed, 133 insertions(+), 6 deletions(-) rename src/installer/tests/HostActivation.Tests/NativeHosting/{FunctionPointerResultExtensions.cs => NativeHostingResultExtensions.cs} (69%) diff --git a/src/installer/tests/HostActivation.Tests/NativeHosting/Comhost.cs b/src/installer/tests/HostActivation.Tests/NativeHosting/Comhost.cs index 3d5b902ff1ad4f..f16e4e1d0e8e7a 100644 --- a/src/installer/tests/HostActivation.Tests/NativeHosting/Comhost.cs +++ b/src/installer/tests/HostActivation.Tests/NativeHosting/Comhost.cs @@ -111,6 +111,35 @@ public void ActivateClass_IgnoreAppLocalHostFxr() } } + [Fact] + public void ActivateClass_IgnoreWorkingDirectory() + { + using (TestArtifact cwd = TestArtifact.Create("cwd")) + { + // Validate that hosting components in the working directory will not be used + File.Copy(Binaries.CoreClr.MockPath, Path.Combine(cwd.Location, Binaries.CoreClr.FileName)); + File.Copy(Binaries.HostFxr.MockPath_5_0, Path.Combine(cwd.Location, Binaries.HostFxr.FileName)); + File.Copy(Binaries.HostPolicy.MockPath, Path.Combine(cwd.Location, Binaries.HostPolicy.FileName)); + + string[] args = { + "comhost", + "synchronous", + "1", + sharedState.ComHostPath, + sharedState.ClsidString + }; + sharedState.CreateNativeHostCommand(args, TestContext.BuiltDotNet.BinPath) + .WorkingDirectory(cwd.Location) + .Execute() + .Should().Pass() + .And.HaveStdOutContaining("New instance of Server created") + .And.HaveStdOutContaining($"Activation of {sharedState.ClsidString} succeeded.") + .And.ResolveHostFxr(TestContext.BuiltDotNet) + .And.ResolveHostPolicy(TestContext.BuiltDotNet) + .And.ResolveCoreClr(TestContext.BuiltDotNet); + } + } + [Fact] public void ActivateClass_ValidateIErrorInfoResult() { diff --git a/src/installer/tests/HostActivation.Tests/NativeHosting/Ijwhost.cs b/src/installer/tests/HostActivation.Tests/NativeHosting/Ijwhost.cs index fa00b0419a85ef..35d6e2af1298e4 100644 --- a/src/installer/tests/HostActivation.Tests/NativeHosting/Ijwhost.cs +++ b/src/installer/tests/HostActivation.Tests/NativeHosting/Ijwhost.cs @@ -89,6 +89,32 @@ public void LoadLibrary_ContextConfig(bool load_isolated) } } + [Fact] + public void LoadLibrary_IgnoreWorkingDirectory() + { + using (TestArtifact cwd = TestArtifact.Create("cwd")) + { + // Validate that hosting components in the working directory will not be used + File.Copy(Binaries.CoreClr.MockPath, Path.Combine(cwd.Location, Binaries.CoreClr.FileName)); + File.Copy(Binaries.HostFxr.MockPath_5_0, Path.Combine(cwd.Location, Binaries.HostFxr.FileName)); + File.Copy(Binaries.HostPolicy.MockPath, Path.Combine(cwd.Location, Binaries.HostPolicy.FileName)); + + string [] args = { + "ijwhost", + sharedState.IjwApp.AppDll, + "NativeEntryPoint" + }; + sharedState.CreateNativeHostCommand(args, TestContext.BuiltDotNet.BinPath) + .WorkingDirectory(cwd.Location) + .Execute() + .Should().Pass() + .And.HaveStdOutContaining("[C++/CLI] NativeEntryPoint: calling managed class") + .And.HaveStdOutContaining("[C++/CLI] ManagedClass: AssemblyLoadContext = \"Default\" System.Runtime.Loader.DefaultAssemblyLoadContext") + .And.ResolveHostFxr(TestContext.BuiltDotNet) + .And.ResolveHostPolicy(TestContext.BuiltDotNet) + .And.ResolveCoreClr(TestContext.BuiltDotNet); + } + } [Fact] public void LoadLibraryWithoutRuntimeConfigButActiveRuntime() diff --git a/src/installer/tests/HostActivation.Tests/NativeHosting/LoadAssemblyAndGetFunctionPointer.cs b/src/installer/tests/HostActivation.Tests/NativeHosting/LoadAssemblyAndGetFunctionPointer.cs index 39cdc5edb4ca35..6f7cae81047915 100644 --- a/src/installer/tests/HostActivation.Tests/NativeHosting/LoadAssemblyAndGetFunctionPointer.cs +++ b/src/installer/tests/HostActivation.Tests/NativeHosting/LoadAssemblyAndGetFunctionPointer.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.IO; using System.Linq; using Microsoft.DotNet.Cli.Build.Framework; @@ -231,6 +232,37 @@ public void CallDelegateOnComponentContext_UnhandledException() .And.ExecuteFunctionPointerWithException(entryPoint, 1); } + [Fact] + public void CallDelegateOnComponentContext_IgnoreWorkingDirectory() + { + using (TestArtifact cwd = TestArtifact.Create("cwd")) + { + // Validate that hosting components in the working directory will not be used + File.Copy(Binaries.CoreClr.MockPath, Path.Combine(cwd.Location, Binaries.CoreClr.FileName)); + File.Copy(Binaries.HostPolicy.MockPath, Path.Combine(cwd.Location, Binaries.HostPolicy.FileName)); + + var component = sharedState.Component; + string[] args = + { + ComponentLoadAssemblyAndGetFunctionPointerArg, + sharedState.HostFxrPath, + component.RuntimeConfigJson, + component.AppDll, + sharedState.ComponentTypeName, + sharedState.ComponentEntryPoint1, + }; + + sharedState.CreateNativeHostCommand(args, sharedState.DotNetRoot) + .WorkingDirectory(cwd.Location) + .Execute() + .Should().Pass() + .And.InitializeContextForConfig(component.RuntimeConfigJson) + .And.ExecuteFunctionPointer(sharedState.ComponentEntryPoint1, 1, 1) + .And.ResolveHostPolicy(TestContext.BuiltDotNet) + .And.ResolveCoreClr(TestContext.BuiltDotNet); + } + } + public class SharedTestState : SharedTestStateBase { public string HostFxrPath { get; } diff --git a/src/installer/tests/HostActivation.Tests/NativeHosting/FunctionPointerResultExtensions.cs b/src/installer/tests/HostActivation.Tests/NativeHosting/NativeHostingResultExtensions.cs similarity index 69% rename from src/installer/tests/HostActivation.Tests/NativeHosting/FunctionPointerResultExtensions.cs rename to src/installer/tests/HostActivation.Tests/NativeHosting/NativeHostingResultExtensions.cs index 09fdc52bc186bf..9a0447a219dcb9 100644 --- a/src/installer/tests/HostActivation.Tests/NativeHosting/FunctionPointerResultExtensions.cs +++ b/src/installer/tests/HostActivation.Tests/NativeHosting/NativeHostingResultExtensions.cs @@ -2,10 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.IO; namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.NativeHosting { - internal static class FunctionPointerResultExtensions + internal static class NativeHostingResultExtensions { public static FluentAssertions.AndConstraint ExecuteFunctionPointer(this CommandResultAssertions assertion, string methodName, int callCount, int returnValue) { @@ -47,5 +48,21 @@ public static FluentAssertions.AndConstraint ExecuteWit { return assertion.HaveStdOutContaining($"{assemblyName}: Location = '{location}'"); } + + public static FluentAssertions.AndConstraint ResolveHostFxr(this CommandResultAssertions assertion, Microsoft.DotNet.Cli.Build.DotNetCli dotnet) + { + return assertion.HaveStdErrContaining($"Resolved fxr [{dotnet.GreatestVersionHostFxrFilePath}]"); + } + + public static FluentAssertions.AndConstraint ResolveHostPolicy(this CommandResultAssertions assertion, Microsoft.DotNet.Cli.Build.DotNetCli dotnet) + { + return assertion.HaveStdErrContaining($"{Binaries.HostPolicy.FileName} directory is [{dotnet.GreatestVersionSharedFxPath}]"); + } + + public static FluentAssertions.AndConstraint ResolveCoreClr(this CommandResultAssertions assertion, Microsoft.DotNet.Cli.Build.DotNetCli dotnet) + { + return assertion.HaveStdErrContaining($"CoreCLR path = '{Path.Combine(dotnet.GreatestVersionSharedFxPath, Binaries.CoreClr.FileName)}'") + .And.HaveStdErrContaining($"CoreCLR dir = '{dotnet.GreatestVersionSharedFxPath}{Path.DirectorySeparatorChar}'"); + } } } diff --git a/src/native/corehost/apphost/standalone/hostfxr_resolver.cpp b/src/native/corehost/apphost/standalone/hostfxr_resolver.cpp index 073445177993cc..c8e5000805289a 100644 --- a/src/native/corehost/apphost/standalone/hostfxr_resolver.cpp +++ b/src/native/corehost/apphost/standalone/hostfxr_resolver.cpp @@ -118,6 +118,11 @@ hostfxr_resolver_t::hostfxr_resolver_t(const pal::string_t& app_root) { m_status_code = StatusCode::CoreHostLibMissingFailure; } + else if (!pal::is_path_rooted(m_fxr_path)) + { + // We should always be loading hostfxr from an absolute path + m_status_code = StatusCode::CoreHostLibMissingFailure; + } else if (pal::load_library(&m_fxr_path, &m_hostfxr_dll)) { m_status_code = StatusCode::Success; diff --git a/src/native/corehost/fxr/standalone/hostpolicy_resolver.cpp b/src/native/corehost/fxr/standalone/hostpolicy_resolver.cpp index 4e75400a04a81b..6092fea3cd8d9f 100644 --- a/src/native/corehost/fxr/standalone/hostpolicy_resolver.cpp +++ b/src/native/corehost/fxr/standalone/hostpolicy_resolver.cpp @@ -180,6 +180,10 @@ int hostpolicy_resolver::load( return StatusCode::CoreHostLibMissingFailure; } + // We should always be loading hostpolicy from an absolute path + if (!pal::is_path_rooted(host_path)) + return StatusCode::CoreHostLibMissingFailure; + // Load library // We expect to leak hostpolicy - just as we do not unload coreclr, we do not unload hostpolicy if (!pal::load_library(&host_path, &g_hostpolicy)) diff --git a/src/native/corehost/fxr_resolver.h b/src/native/corehost/fxr_resolver.h index b61f3b8fb4e6dc..88fc9f8781efdd 100644 --- a/src/native/corehost/fxr_resolver.h +++ b/src/native/corehost/fxr_resolver.h @@ -55,6 +55,10 @@ int load_fxr_and_get_delegate(hostfxr_delegate_type type, THostPathToConfigCallb return StatusCode::CoreHostLibMissingFailure; } + // We should always be loading hostfxr from an absolute path + if (!pal::is_path_rooted(fxr_path)) + return StatusCode::CoreHostLibMissingFailure; + // Load library if (!pal::load_library(&fxr_path, &fxr)) { diff --git a/src/native/corehost/hostpolicy/deps_resolver.cpp b/src/native/corehost/hostpolicy/deps_resolver.cpp index 55d9bd8f948868..0e87b791cfbfc4 100644 --- a/src/native/corehost/hostpolicy/deps_resolver.cpp +++ b/src/native/corehost/hostpolicy/deps_resolver.cpp @@ -830,15 +830,21 @@ bool deps_resolver_t::resolve_probe_dirs( } } - // If the deps file is missing add known locations. - if (!get_app_deps().exists()) + // If the deps file is missing for the app, add known locations. + // For libhost scenarios, there is no app or app path + if (m_host_mode != host_mode_t::libhost && !get_app_deps().exists()) { + assert(!m_app_dir.empty()); + // App local path add_unique_path(asset_type, m_app_dir, &items, output, &non_serviced, core_servicing); - // deps_resolver treats being able to get the coreclr path as optional, so we ignore the return value here. - // The caller is responsible for checking whether coreclr path is set and handling as appropriate. - (void) file_exists_in_dir(m_app_dir, LIBCORECLR_NAME, &m_coreclr_path); + if (m_coreclr_path.empty()) + { + // deps_resolver treats being able to get the coreclr path as optional, so we ignore the return value here. + // The caller is responsible for checking whether coreclr path is set and handling as appropriate. + (void) file_exists_in_dir(m_app_dir, LIBCORECLR_NAME, &m_coreclr_path); + } } // Handle any additional deps.json that were specified. diff --git a/src/native/corehost/hostpolicy/standalone/coreclr_resolver.cpp b/src/native/corehost/hostpolicy/standalone/coreclr_resolver.cpp index b040c3e8546278..8df8e395e3f259 100644 --- a/src/native/corehost/hostpolicy/standalone/coreclr_resolver.cpp +++ b/src/native/corehost/hostpolicy/standalone/coreclr_resolver.cpp @@ -13,6 +13,10 @@ bool coreclr_resolver_t::resolve_coreclr(const pal::string_t& libcoreclr_path, c pal::string_t coreclr_dll_path(libcoreclr_path); append_path(&coreclr_dll_path, LIBCORECLR_NAME); + // We should always be loading coreclr from an absolute path + if (!pal::is_path_rooted(coreclr_dll_path)) + return false; + if (!pal::load_library(&coreclr_dll_path, &coreclr_resolver_contract.coreclr)) { return false; From 22512867ac310eb042a6ec02288d3bd5375748e3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 16 Jun 2025 13:13:05 -0500 Subject: [PATCH 2/2] Delete s390x and ppc64le helix queues (#116537) These queues are non-functional and there is no plan to fix them. Co-authored-by: Jan Kotas --- eng/pipelines/libraries/helix-queues-setup.yml | 8 -------- eng/pipelines/runtime-community.yml | 11 ----------- 2 files changed, 19 deletions(-) diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml index 13b30af22e8682..7b849e1bea38c5 100644 --- a/eng/pipelines/libraries/helix-queues-setup.yml +++ b/eng/pipelines/libraries/helix-queues-setup.yml @@ -75,14 +75,6 @@ jobs: # Limiting interp runs as we don't need as much coverage. - (Debian.12.Amd64.Open)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-amd64 - # Linux s390x - - ${{ if eq(parameters.platform, 'linux_s390x') }}: - - Ubuntu.2004.S390X.Experimental.Open - - # Linux PPC64le - - ${{ if eq(parameters.platform, 'linux_ppc64le') }}: - - Ubuntu.2204.PPC64le.Experimental.Open - # OSX arm64 - ${{ if eq(parameters.platform, 'osx_arm64') }}: - OSX.1200.ARM64.Open diff --git a/eng/pipelines/runtime-community.yml b/eng/pipelines/runtime-community.yml index b7a21f588973c1..446996e505b72b 100644 --- a/eng/pipelines/runtime-community.yml +++ b/eng/pipelines/runtime-community.yml @@ -71,17 +71,6 @@ extends: eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_mono_excluding_wasm.containsChange'], true), eq(variables['isRollingBuild'], true)) - # extra steps, run tests - postBuildSteps: - - template: /eng/pipelines/libraries/helix.yml - parameters: - creator: dotnet-bot - testRunNamePrefixSuffix: Mono_$(_BuildConfig) - condition: >- - or( - eq(variables['librariesContainsChange'], true), - eq(variables['monoContainsChange'], true), - eq(variables['isRollingBuild'], true)) # # Build the whole product using Mono