Skip to content

Commit 2811e7c

Browse files
authored
Address Sanitizer support in CoreCLR (dotnet#74623)
* Enable AddressSanitizer in CoreCLR, Libs, and Host and update runtime-sanitized to run tests with ASAN on Linux and Mac * Unify on HAS_ADDRESS_SANITIZER define name Centralize setting up sanitizer flags. Remove last usage of CLR_CMAKE_ENABLE_ASAN outside of eng/native Remove unnecessary diffs Use the cpuid intrinsic and enable ASAN on InitJitHelpers1. Add comments for the places where we have ASAN disabled Undo changes to src/coreclr/jit/CMakeLists.txt Add docs and fix the docs in the build script. Add docs for the SkipVCEnvInit hook * Remove CRT runtime changes. We won't need this when we finally onboard to Windows with some changes they have coming down the pipeline, so remove them for now to reduce the diff of this PR. * Remove suppression now that we've fixed the underlying issue. * Remove some Windows-only sanitizer CMake that we won't need when ASAN is ready for us to consume on Windows. * Set schedule for runtime-sanitized pipeline * Remove workaround in JIT memory set/copy helpers now that the JIT bug has been fixed. * Add missing helix queues setup template. * Fix missing command to build nativeaot runtime tests as nativeaot. * Add a scenario name to trigger the extended timeout in the libraries test helix configuration. * Remove extraneous whitespace. * Fix using the cross-targetting ILC when sanitizers are enabled. Also pass through our TargetOS and TargetArchitecture variables to the publish command for our native sanitizers targets to correctly do their extra logic. * Disable LSAN on the CustomMain test. * Disable some tests on sanitized runtimes. * Copy the sanitizer runtime for OSX NativeAOT runtime tests. * A little cleanup to try to get the build right now that we are always doing cross-builds on Linux. * Fix crossgen-corelib.proj syntax. * Fix cross-os dac builds to not include the host architecture in the output path. * Split the debugger components into a separate component and make the "unsanitized cross components" build into an "unsanitized debugger components" build as it can't be part of the regular cross-components build * Always write out the host-arch path on Windows and update the cross-dac build script to expect that. * Change to use the dynamic runtime on Windows, as ASAN in VS is moving to a dynamic-only model. * Update docker images to include the sanitizer runtimes in the crossrootfs images. * Fix explicit image tags * The unsanitized build should be of the target architecture, not the host architecture. As a result, we still need a cross-arch build for the cross-arch use cases when sanitized, as well as an unsanitized target arch build for the debugger tools. * Turn off using the sigaltstack for NativeAOT tests that don't use the asansupport.cpp default options * Make sure the shared ASAN runtime is present for the nativeaot/SmokeTests/SharedLibrary test. * Disable crossgen2 tests with sanitizers as they don't get us interesting coverage. * Fix custom default options and disable some more crossgen2-based tests. * Simplify lookup of asan runtime on mac and fix copying the shared runtime for the SharedLibrary NativeAOT test. * Disable test that's failing for weird reasons. * Fix one more alloc-dealloc mismatch that only started to show up after test merging increased allocations in the runtime * Disable the System.Text.Json test suite on sanitized builds as it causes SO failures on Mac * Fix test exclusion * PR feedback. * Fix mac build * Do review changes * Add libbootstrapper object files to the platform manifest now that NativeAOT has * Disable tests that check size on sanitized builds * Use the built-in `include_guard` option * Disable use-after-return checking in ASAN. CoreCLR doesn't do well with parallel stacks. * Only pass the no UAR flag on C and CXX with Clang (not AppleClang).
1 parent a654a77 commit 2811e7c

File tree

108 files changed

+938
-249
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

108 files changed

+938
-249
lines changed

docs/workflow/building/coreclr/linux-instructions.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,19 @@ Just like you can use specialized Docker images, you can also do any of the supp
9999
## Create the Core_Root
100100

101101
The Core_Root provides one of the main ways to test your build. Full instructions on how to build it in the [CoreCLR testing doc](/docs/workflow/testing/coreclr/testing.md), and we also have a detailed guide on how to use it for your own testing in [its own dedicated doc](/docs/workflow/testing/using-corerun-and-coreroot.md).
102+
103+
## Native Sanitizers
104+
105+
CoreCLR can be built with native sanitizers like AddressSanitizer to help catch memory safety issues. To build the project with native sanitizers, add the `-fsanitize address` argument to the build script like the following:
106+
107+
```bash
108+
build.sh -s clr -fsanitize address
109+
```
110+
111+
When building the repo with any native sanitizers, you should build all native components in the repo with the same set of sanitizers.
112+
113+
The following sanitizers are supported for CoreCLR on Linux:
114+
115+
| Sanitizer Name | `-fsanitize` argument | Support Status |
116+
|-----------------|-----------------------|----------------|
117+
| AddressSanitize | `address` | regularly tested on x64 |

docs/workflow/building/coreclr/macos-instructions.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,19 @@ It is possible to get a macOS ARM64 build using an Intel x64 Mac and vice versa,
3232
## Create the Core_Root
3333

3434
The Core_Root provides one of the main ways to test your build. Full instructions on how to build it in the [CoreCLR testing doc](/docs/workflow/testing/coreclr/testing.md), and we also have a detailed guide on how to use it for your own testing in [its own dedicated doc](/docs/workflow/testing/using-corerun-and-coreroot.md).
35+
36+
## Native Sanitizers
37+
38+
CoreCLR can be built with native sanitizers like AddressSanitizer to help catch memory safety issues. To build the project with native sanitizers, add the `-fsanitize address` argument to the build script like the following:
39+
40+
```bash
41+
build.sh -s clr -fsanitize address
42+
```
43+
44+
When building the repo with any native sanitizers, you should build all native components in the repo with the same set of sanitizers.
45+
46+
The following sanitizers are supported for CoreCLR on macOS:
47+
48+
| Sanitizer Name | `-fsanitize` argument | Support Status |
49+
|-----------------|-----------------------|----------------|
50+
| AddressSanitize | `address` | regularly tested on x64 |

docs/workflow/building/coreclr/nativeaot.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ Build library tests by passing the `libs.tests` subset together with the `/p:Tes
109109
* [ILC Compiler Architecture](/docs/design/coreclr/botr/ilc-architecture.md)
110110
* [Managed Type System](/docs/design/coreclr/botr/managed-type-system.md)
111111

112+
## Native Sanitizers
113+
114+
Using native sanitizers with NativeAOT requires additional care compared to using them with CoreCLR. In addition to passing the `-fsanitize` flag to the command that builds NativeAOT, you must also pass the `EnableNativeSanitizers` MSBuild property to any commands that build projects with a sanitized NativeAOT build to ensure that any sanitizer runtimes are correctly linked with the project.
115+
112116
## Further Reading
113117

114118
If you want to know more about working with _NativeAOT_ in general, you can check out their [more in-depth docs](/src/coreclr/nativeaot/docs/README.md) in the `src/coreclr/nativeaot` subtree.

docs/workflow/building/coreclr/windows-instructions.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,23 @@ build.cmd -s clr -c Release -arch arm64 -msbuild
4545
```
4646

4747
Since this is still in an experimental phase, the recommended way for building ARM64 is cross-compiling from an x64 machine. Instructions on how to do this can be found at the [cross-building doc](/docs/workflow/building/coreclr/cross-building.md#cross-compiling-for-arm32-and-arm64).
48+
49+
## Native Sanitizers
50+
51+
CoreCLR can be built with native sanitizers like AddressSanitizer to help catch memory safety issues. To build the project with native sanitizers, add the `-fsanitize address` argument to the build script like the following:
52+
53+
```cmd
54+
build.cmd -s clr -fsanitize address
55+
```
56+
57+
When building the repo with any native sanitizers, you should build all native components in the repo with the same set of sanitizers.
58+
59+
The following sanitizers are supported for CoreCLR on Windows:
60+
61+
| Sanitizer Name | Minimum VS Version | `-fsanitize` argument | Support Status |
62+
|----------------|--------------------|-----------------------|----------------|
63+
| AddressSanitizer | not yet released | `address` | experimental |
64+
65+
## Using a custom compiler environment
66+
67+
If you ever need to use a custom compiler environment for the native builds on Windows, you can set the `SkipVCEnvInit` environment variable to `1`. The build system will skip discovering Visual Studio and initializing its development environment when this flag is used. This is only required for very advanced scenarios and should be used rarely.

docs/workflow/building/libraries/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,16 @@ By default the `build` script only builds the product libraries and none of the
105105

106106
For Windows, replace `./build.sh` with `build.cmd`.
107107

108+
### Building the native components with native sanitizers
109+
110+
The libraries native components can be built with native sanitizers like AddressSanitizer to help catch memory safety issues. To build the project with native sanitizers, add the `-fsanitize` argument to the build script like the following:
111+
112+
```bash
113+
build.sh -s libs -fsanitize address
114+
```
115+
116+
When building the repo with any native sanitizers, you should build all native components in the repo with the same set of sanitizers.
117+
108118
### How to build native components only
109119

110120
The libraries build contains some native code. This includes shims over libc, openssl, gssapi, and zlib. The build system uses CMake to generate Makefiles using clang. The build also uses git for generating some version information.

eng/Subsets.props

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,11 @@
253253
Category="clr" />
254254
</ItemGroup>
255255

256-
<!-- Build the CoreCLR cross tools when we're doing a cross build and either we're building any CoreCLR native tools for platforms CoreCLR fully supports or when someone explicitly requests them -->
257-
<ItemGroup Condition="(('$(ClrRuntimeBuildSubsets)' != '' and '$(PrimaryRuntimeFlavor)' == 'CoreCLR') or $(_subset.Contains('+clr.crossarchtools+'))) and ('$(CrossBuild)' == 'true' or '$(BuildArchitecture)' != '$(TargetArchitecture)')">
256+
<!--
257+
Build the CoreCLR cross tools when we're doing a cross build and either we're building any CoreCLR native tools for platforms CoreCLR fully supports or when someone explicitly requests them.
258+
The cross tools are used as part of the build process with the downloaded build tools, so we need to build them for the host architecture and build them as unsanitized binaries.
259+
-->
260+
<ItemGroup Condition="(('$(ClrRuntimeBuildSubsets)' != '' and '$(PrimaryRuntimeFlavor)' == 'CoreCLR') or $(_subset.Contains('+clr.crossarchtools+'))) and ('$(CrossBuild)' == 'true' or '$(BuildArchitecture)' != '$(TargetArchitecture)' or '$(EnableNativeSanitizers)' != '')">
258261
<ProjectToBuild
259262
Include="$(CoreClrProjectRoot)runtime.proj"
260263
AdditionalProperties="%(AdditionalProperties);
@@ -265,6 +268,24 @@
265268
NoPgoOptimize=true;
266269
CrossBuild=false;
267270
CMakeArgs=$(CMakeArgs) -DCLR_CROSS_COMPONENTS_BUILD=1"
271+
UndefineProperties="EnableNativeSanitizers"
272+
Category="clr" />
273+
</ItemGroup>
274+
275+
<!--
276+
Build the debugging components of CoreCLR for the same target architecture as an unsanitized build whenever we build a sanitized coreclr build.
277+
These components are loaded into a debugger process, which generally is not a sanitized executable.
278+
-->
279+
<ItemGroup Condition="'$(ClrRuntimeBuildSubsets)' != '' and '$(EnableNativeSanitizers)' != ''">
280+
<ProjectToBuild
281+
Include="$(CoreClrProjectRoot)runtime.proj"
282+
AdditionalProperties="%(AdditionalProperties);
283+
ClrDebugSubset=true;
284+
PgoInstrument=false;
285+
NoPgoOptimize=true;
286+
CrossBuild=$(CrossBuild);
287+
BuildSubdirectory=unsanitized"
288+
UndefineProperties="EnableNativeSanitizers"
268289
Category="clr" />
269290
</ItemGroup>
270291

@@ -317,8 +338,8 @@
317338
<ProjectToBuild Include="$(CoreClrProjectRoot)tools\aot\ILCompiler\ILCompiler.csproj" Category="clr" Condition="'$(NativeAotSupported)' == 'true'" />
318339
<ProjectToBuild Include="$(CoreClrProjectRoot)nativeaot\BuildIntegration\BuildIntegration.proj" Category="clr" Condition="'$(NativeAotSupported)' == 'true'" />
319340

320-
<ProjectToBuild Condition="'$(NativeAotSupported)' == 'true' and ('$(CrossBuild)' == 'true' or '$(BuildArchitecture)' != '$(TargetArchitecture)' or '$(HostOS)' != '$(TargetOS)')" Include="$(CoreClrProjectRoot)tools\aot\ILCompiler\ILCompiler_crossarch.csproj" Category="clr" />
321-
<ProjectToBuild Condition="'$(TargetArchitecture)' != '$(BuildArchitecture)' or '$(HostOS)' != '$(TargetOS)'" Include="$(CoreClrProjectRoot)tools\aot\crossgen2\crossgen2_crossarch.csproj" Category="clr" />
341+
<ProjectToBuild Condition="'$(NativeAotSupported)' == 'true' and ('$(CrossBuild)' == 'true' or '$(BuildArchitecture)' != '$(TargetArchitecture)' or '$(HostOS)' != '$(TargetOS)' or '$(EnableNativeSanitizers)' != '')" Include="$(CoreClrProjectRoot)tools\aot\ILCompiler\ILCompiler_crossarch.csproj" Category="clr" />
342+
<ProjectToBuild Condition="'$(TargetArchitecture)' != '$(BuildArchitecture)' or '$(HostOS)' != '$(TargetOS)' or '$(EnableNativeSanitizers)' != ''" Include="$(CoreClrProjectRoot)tools\aot\crossgen2\crossgen2_crossarch.csproj" Category="clr" />
322343

323344
<ProjectToBuild Condition="'$(TargetOS)' == 'windows' or ('$(TargetOS)' == 'linux' and ('$(TargetArchitecture)' == 'x64' or '$(TargetArchitecture)' == 'arm64')) or '$(TargetOS)' == 'osx'" Include="$(CoreClrProjectRoot)tools\SuperFileCheck\SuperFileCheck.csproj" Category="clr" />
324345
</ItemGroup>

eng/build.ps1

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Param(
2222
[switch]$msbuild,
2323
[string]$cmakeargs,
2424
[switch]$pgoinstrument,
25+
[string[]]$fsanitize,
2526
[Parameter(ValueFromRemainingArguments=$true)][String[]]$properties
2627
)
2728

@@ -84,10 +85,13 @@ function Get-Help() {
8485
Write-Host ""
8586

8687
Write-Host "Native build settings:"
87-
Write-Host " -cmakeargs User-settable additional arguments passed to CMake."
88-
Write-Host " -ninja Use Ninja to drive the native build. (default)"
89-
Write-Host " -msbuild Use MSBuild to drive the native build. This is a no-op for Mono."
90-
Write-Host " -pgoinstrument Build the CLR with PGO instrumentation."
88+
Write-Host " -cmakeargs User-settable additional arguments passed to CMake."
89+
Write-Host " -ninja Use Ninja to drive the native build. (default)"
90+
Write-Host " -msbuild Use MSBuild to drive the native build. This is a no-op for Mono."
91+
Write-Host " -pgoinstrument Build the CLR with PGO instrumentation."
92+
Write-Host " -fsanitize (address) Build the native components with the specified sanitizers."
93+
Write-Host " Sanitizers can be specified with a comma-separated list."
94+
Write-Host ""
9195

9296
Write-Host "Command-line arguments not listed above are passed through to MSBuild."
9397
Write-Host "The above arguments can be shortened as much as to be unambiguous."
@@ -220,7 +224,7 @@ if ($vs) {
220224

221225
# Put our local dotnet.exe on PATH first so Visual Studio knows which one to use
222226
$env:PATH=($env:DOTNET_ROOT + ";" + $env:PATH);
223-
227+
224228
# Disable .NET runtime signature validation errors which errors for local builds
225229
$env:VSDebugger_ValidateDotnetDebugLibSignatures=0;
226230

@@ -269,6 +273,7 @@ foreach ($argument in $PSBoundParameters.Keys)
269273
# configuration and arch can be specified multiple times, so they should be no-ops here
270274
"configuration" {}
271275
"arch" {}
276+
"fsanitize" { $arguments += " /p:EnableNativeSanitizers=$($PSBoundParameters[$argument])"}
272277
default { $arguments += " /p:$argument=$($PSBoundParameters[$argument])" }
273278
}
274279
}

eng/build.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ usage()
8484
echo " --keepnativesymbols Optional argument: set to true to keep native symbols/debuginfo in generated binaries."
8585
echo " --ninja Optional argument: set to true to use Ninja instead of Make to run the native build."
8686
echo " --pgoinstrument Optional argument: build PGO-instrumented runtime"
87+
echo " --fsanitize Optional argument: Specify native sanitizers to instrument the native build with. Supported values are: 'address'."
8788
echo ""
8889

8990
echo "Command line arguments starting with '/p:' are passed through to MSBuild."
@@ -509,6 +510,21 @@ while [[ $# > 0 ]]; do
509510
shift 1
510511
;;
511512

513+
-fsanitize)
514+
if [ -z ${2+x} ]; then
515+
echo "No value for -fsanitize is supplied. See help (--help) for supported values." 1>&2
516+
exit 1
517+
fi
518+
arguments="$arguments /p:EnableNativeSanitizers=$2"
519+
shift 2
520+
;;
521+
522+
-fsanitize=*)
523+
sanitizers="${opt/#-fsanitize=/}" # -fsanitize=address => address
524+
arguments="$arguments /p:EnableNativeSanitizers=$sanitizers"
525+
shift 2
526+
;;
527+
512528
*)
513529
extraargs="$extraargs $1"
514530
shift 1

eng/liveBuilds.targets

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
<CoreCLRSharedFrameworkDir>$([MSBuild]::NormalizeDirectory('$(CoreCLRArtifactsPath)', 'sharedFramework'))</CoreCLRSharedFrameworkDir>
2626
<CoreCLRCrossgen2Dir>$([MSBuild]::NormalizeDirectory('$(CoreCLRArtifactsPath)', 'crossgen2'))</CoreCLRCrossgen2Dir>
2727
<CoreCLRILCompilerDir>$([MSBuild]::NormalizeDirectory('$(CoreCLRArtifactsPath)', 'ilc-published'))</CoreCLRILCompilerDir>
28-
<CoreCLRCrossILCompilerDir Condition="'$(CrossBuild)' == 'true' or '$(BuildArchitecture)' != '$(TargetArchitecture)' or '$(HostOS)' != '$(TargetOS)'">$([MSBuild]::NormalizeDirectory('$(CoreCLRArtifactsPath)', '$(BuildArchitecture)', 'ilc'))</CoreCLRCrossILCompilerDir>
28+
<CoreCLRCrossILCompilerDir Condition="'$(CrossBuild)' == 'true' or '$(BuildArchitecture)' != '$(TargetArchitecture)' or '$(HostOS)' != '$(TargetOS)' or '$(EnableNativeSanitizers)' != ''">$([MSBuild]::NormalizeDirectory('$(CoreCLRArtifactsPath)', '$(BuildArchitecture)', 'ilc'))</CoreCLRCrossILCompilerDir>
2929
<CoreCLRAotSdkDir>$([MSBuild]::NormalizeDirectory('$(CoreCLRArtifactsPath)', 'aotsdk'))</CoreCLRAotSdkDir>
3030
<CoreCLRBuildIntegrationDir>$([MSBuild]::NormalizeDirectory('$(CoreCLRArtifactsPath)', 'build'))</CoreCLRBuildIntegrationDir>
3131

eng/native/build-commons.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ usage()
270270
echo "-portablebuild: pass -portablebuild=false to force a non-portable build."
271271
echo "-skipconfigure: skip build configuration."
272272
echo "-keepnativesymbols: keep native/unmanaged debug symbols."
273+
echo "-fsanitize: Enable native sanitizers"
273274
echo "-verbose: optional argument to enable verbose build output."
274275
echo ""
275276
echo "Additional Options:"
@@ -392,6 +393,17 @@ while :; do
392393
__CMakeArgs="$__CMakeArgs -DCLR_CMAKE_KEEP_NATIVE_SYMBOLS=true"
393394
;;
394395

396+
-fsanitize)
397+
__CMakeArgs="$__CMakeArgs -DCLR_CMAKE_ENABLE_SANITIZERS=$2"
398+
EnableNativeSanitizers=$2
399+
shift
400+
;;
401+
-fsanitize=*)
402+
sanitizers="${lowerI/#-fsanitize=/}" # -fsanitize=address => address
403+
__CMakeArgs="$__CMakeArgs -DCLR_CMAKE_ENABLE_SANITIZERS=$sanitizers"
404+
EnableNativeSanitizers=$sanitizers
405+
;;
406+
395407
ninja|-ninja)
396408
__UseNinja=1
397409
;;

0 commit comments

Comments
 (0)