CET supported by default

apphost and singlefilehost are now marked as Intel CET—compatible (they're compiled with the /CETCOMPAT option). This change was made to enhance security of .NET applications. However, it imposes a limitation on the shared libraries that .NET apps can load and interop with. Libraries aren't allowed to set thread context to a location with an instruction pointer that's not present on the shadow stack or in a table of allowed continuation addresses for exception handling.

Previous behavior

Previously, shared libraries loaded into the .NET process were able to set thread context using SetThreadContext, RtlRestoreContext/NtContinue, or their exception handlers to any location in the process address space.

New behavior

Starting in .NET 9, shared libraries loaded into the .NET process are only allowed to set thread context using SetThreadContext, RtlRestoreContext/NtContinue, or their exception handlers to locations that are either:

  • Present on the shadow stack.
  • In a table of allowed continuation addresses for exception handling (generated by the /EHCONT compiler option or the SetProcessDynamicEHContinuationTargets API).

If libraries try to change a thread context to any other location, the process is terminated.

Version introduced

.NET 9 Preview 6

Type of breaking change

This change can affect binary compatibility.

Reason for change

Enabling CET enhances the security of .NET applications by adding hardware-enforced stack protection against return-oriented programming (ROP) exploits.

Workarounds:

  • You can opt out of CET by adding <CETCompat>false</CETCompat> to your app's project file (for example, .csproj file).
  • Use the Windows Security app or a group policy to opt out of the hardware-supported stack enforcement for the specific .NET application. For more information, see Enable exploit protection.

Affected APIs

  • N/A