diff --git a/eng/pipelines/common/templates/runtimes/run-test-job.yml b/eng/pipelines/common/templates/runtimes/run-test-job.yml index d977f6c692efa1..49707f1568adc0 100644 --- a/eng/pipelines/common/templates/runtimes/run-test-job.yml +++ b/eng/pipelines/common/templates/runtimes/run-test-job.yml @@ -11,6 +11,7 @@ parameters: liveLibrariesBuildConfig: '' crossgen2: false compositeBuildMode: false + useCodeFlowEnforcement: '' helixQueues: '' condition: true stagedBuild: false @@ -112,6 +113,13 @@ jobs: - name: runtimeVariantArg value: '/p:RuntimeVariant=${{ parameters.runtimeVariant }}' + - name: codeFlowEnforcementArg + value: '' + + - ${{ if ne(parameters.useCodeFlowEnforcement, '') }}: + - name: codeFlowEnforcementArg + value: '/p:UseCodeFlowEnforcement=${{ parameters.useCodeFlowEnforcement }}' + - name: crossgenArg value: '' - name: LogNamePrefix @@ -301,8 +309,8 @@ jobs: # during product build (so that we could zip up the files in their final test location # and directly unzip them there after download). Unfortunately the logic to copy # the native artifacts to the final test folders is dependent on availability of the - # managed test artifacts. - - script: $(Build.SourcesDirectory)/src/tests/build$(scriptExt) copynativeonly $(logRootNameArg)Native $(testTreeFilterArg) $(runtimeFlavorArgs) $(crossgenArg) $(buildConfig) $(archType) $(priorityArg) $(librariesOverrideArg) + # managed test artifacts. This step also generates the final test execution scripts. + - script: $(Build.SourcesDirectory)/src/tests/build$(scriptExt) copynativeonly $(logRootNameArg)Native $(testTreeFilterArg) $(runtimeFlavorArgs) $(crossgenArg) $(buildConfig) $(archType) $(priorityArg) $(librariesOverrideArg) $(codeFlowEnforcementArg) displayName: Copy native test components to test output folder diff --git a/eng/pipelines/runtime-cet.yml b/eng/pipelines/runtime-cet.yml index ab2fe28ad55f84..4e882faa2e99c0 100644 --- a/eng/pipelines/runtime-cet.yml +++ b/eng/pipelines/runtime-cet.yml @@ -82,3 +82,4 @@ jobs: jobParameters: testGroup: innerloop liveLibrariesBuildConfig: release + useCodeFlowEnforcement: true diff --git a/src/tests/Directory.Build.targets b/src/tests/Directory.Build.targets index dccce1cb63af54..000af600e2a616 100644 --- a/src/tests/Directory.Build.targets +++ b/src/tests/Directory.Build.targets @@ -83,6 +83,10 @@ + + true + + false diff --git a/src/tests/baseservices/CET/CETCheck.cpp b/src/tests/baseservices/CET/CETCheck.cpp new file mode 100644 index 00000000000000..0c8d9d2d38102b --- /dev/null +++ b/src/tests/baseservices/CET/CETCheck.cpp @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#if defined(TARGET_AMD64) && defined(TARGET_WINDOWS) +#include + +extern "C" __declspec(dllexport) __int64 ReadShadowStackPointer() +{ + return _rdsspq(); +} +#endif diff --git a/src/tests/baseservices/CET/CMakeLists.txt b/src/tests/baseservices/CET/CMakeLists.txt new file mode 100644 index 00000000000000..226738c71f862f --- /dev/null +++ b/src/tests/baseservices/CET/CMakeLists.txt @@ -0,0 +1,4 @@ +add_library(cet_check SHARED CETCheck.cpp) + +# add the install targets +install (TARGETS cet_check DESTINATION bin) diff --git a/src/tests/baseservices/CET/CheckCETPresence.cs b/src/tests/baseservices/CET/CheckCETPresence.cs new file mode 100644 index 00000000000000..656fcadfb7cfd3 --- /dev/null +++ b/src/tests/baseservices/CET/CheckCETPresence.cs @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; + +static class Program +{ + [DllImport("cet_check.dll")] + private static extern long ReadShadowStackPointer(); + + public static int Main() + { + Console.WriteLine("Checking whether codeflow enforcement technology (CET) is active"); + long ssp = ReadShadowStackPointer(); + Console.WriteLine("Shadow stack pointer: 0x{0:x16}", ssp); + // Non-zero shadow stack pointer value confirms that CET is active on the runtime processor. + return ssp != 0 ? 100 : 101; + } +} diff --git a/src/tests/baseservices/CET/CheckCETPresence.csproj b/src/tests/baseservices/CET/CheckCETPresence.csproj new file mode 100644 index 00000000000000..845ff56e1c787e --- /dev/null +++ b/src/tests/baseservices/CET/CheckCETPresence.csproj @@ -0,0 +1,14 @@ + + + Exe + true + true + true + + + + + + + + diff --git a/src/tests/build.proj b/src/tests/build.proj index 063e3059c4385e..2f736cd7da18c9 100644 --- a/src/tests/build.proj +++ b/src/tests/build.proj @@ -486,6 +486,7 @@ $(GroupBuildCmd) "/p:RuntimeFlavor=$(RuntimeFlavor)" $(GroupBuildCmd) "/p:RuntimeVariant=$(RuntimeVariant)" $(GroupBuildCmd) "/p:CLRTestBuildAllTargets=$(CLRTestBuildAllTargets)" + $(GroupBuildCmd) "/p:UseCodeFlowEnforcement=$(UseCodeFlowEnforcement)" $(GroupBuildCmd) "/p:__TestGroupToBuild=$(__TestGroupToBuild)" $(GroupBuildCmd) "/p:__SkipRestorePackages=1" $(GroupBuildCmd) /nodeReuse:false