rust: Support global sanitizers
This CL adds Rust support for the SANITIZE_TARGET options.
This CL includes a couple small fixes to related to HWASAN, ASAN,
ensuring that the Never sanitize property is respected. Notably,
additional llvm-args are passed to ensure that HWASAN-ified Rust/C
interop works correctly.
Bug: 170672854
Bug: 204915322
Test: SANITIZE_TARGET globally applies hwasan to Rust targets
Change-Id: Ia904d07b4618f72cdc95c51f88961905c240ac53
diff --git a/rust/sanitize.go b/rust/sanitize.go
index baa383d..5b7597e 100644
--- a/rust/sanitize.go
+++ b/rust/sanitize.go
@@ -15,11 +15,15 @@
package rust
import (
+ "fmt"
+ "strings"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+
"android/soong/android"
"android/soong/cc"
"android/soong/rust/config"
- "fmt"
- "github.com/google/blueprint"
)
type SanitizeProperties struct {
@@ -59,9 +63,18 @@
"-Z sanitizer=address",
}
+// See cc/sanitize.go's hwasanGlobalOptions for global hwasan options.
var hwasanFlags = []string{
"-Z sanitizer=hwaddress",
"-C target-feature=+tagged-globals",
+
+ // Flags from cc/sanitize.go hwasanFlags
+ "-C llvm-args=--aarch64-enable-global-isel-at-O=-1",
+ "-C llvm-args=-fast-isel=false",
+ "-C llvm-args=-instcombine-lower-dbg-declare=0",
+
+ // Additional flags for HWASAN-ified Rust/C interop
+ "-C llvm-args=--hwasan-with-ifunc",
}
func boolPtr(v bool) *bool {
@@ -79,7 +92,46 @@
}
func (sanitize *sanitize) begin(ctx BaseModuleContext) {
- s := sanitize.Properties.Sanitize
+ s := &sanitize.Properties.Sanitize
+
+ // Never always wins.
+ if Bool(s.Never) {
+ return
+ }
+
+ var globalSanitizers []string
+
+ if ctx.Host() {
+ if !ctx.Windows() {
+ globalSanitizers = ctx.Config().SanitizeHost()
+ }
+ } else {
+ arches := ctx.Config().SanitizeDeviceArch()
+ if len(arches) == 0 || android.InList(ctx.Arch().ArchType.Name, arches) {
+ globalSanitizers = ctx.Config().SanitizeDevice()
+ }
+ }
+
+ if len(globalSanitizers) > 0 {
+ var found bool
+
+ // Global Sanitizers
+ if found, globalSanitizers = android.RemoveFromList("hwaddress", globalSanitizers); found && s.Hwaddress == nil {
+ // TODO(b/180495975): HWASan for static Rust binaries isn't supported yet.
+ if !ctx.RustModule().StaticExecutable() {
+ s.Hwaddress = proptools.BoolPtr(true)
+ }
+ }
+
+ if found, globalSanitizers = android.RemoveFromList("address", globalSanitizers); found && s.Address == nil {
+ s.Address = proptools.BoolPtr(true)
+ }
+
+ if found, globalSanitizers = android.RemoveFromList("fuzzer", globalSanitizers); found && s.Fuzzer == nil {
+ s.Fuzzer = proptools.BoolPtr(true)
+ }
+
+ }
// TODO:(b/178369775)
// For now sanitizing is only supported on devices
@@ -96,7 +148,17 @@
s.Hwaddress = nil
}
- if ctx.Os() == android.Android && Bool(s.Hwaddress) {
+ // HWASan ramdisk (which is built from recovery) goes over some bootloader limit.
+ // Keep libc instrumented so that ramdisk / vendor_ramdisk / recovery can run hwasan-instrumented code if necessary.
+ if (ctx.RustModule().InRamdisk() || ctx.RustModule().InVendorRamdisk() || ctx.RustModule().InRecovery()) && !strings.HasPrefix(ctx.ModuleDir(), "bionic/libc") {
+ s.Hwaddress = nil
+ }
+
+ if Bool(s.Hwaddress) {
+ s.Address = nil
+ }
+
+ if ctx.Os() == android.Android && (Bool(s.Hwaddress) || Bool(s.Address)) {
sanitize.Properties.SanitizerEnabled = true
}
}
@@ -149,23 +211,18 @@
} else if mod.IsSanitizerEnabled(cc.Hwasan) ||
(mod.IsSanitizerEnabled(cc.Fuzzer) && mctx.Arch().ArchType == android.Arm64) {
// TODO(b/180495975): HWASan for static Rust binaries isn't supported yet.
- if binary, ok := mod.compiler.(*binaryDecorator); ok {
- if Bool(binary.Properties.Static_executable) {
+ if binary, ok := mod.compiler.(binaryInterface); ok {
+ if binary.staticallyLinked() {
mctx.ModuleErrorf("HWASan is not supported for static Rust executables yet.")
}
}
- if mod.StaticallyLinked() {
- variations = append(variations,
- blueprint.Variation{Mutator: "link", Variation: "static"})
- depTag = cc.StaticDepTag(false)
- deps = []string{config.LibclangRuntimeLibrary(mod.toolchain(mctx), "hwasan_static")}
- } else {
- variations = append(variations,
- blueprint.Variation{Mutator: "link", Variation: "shared"})
- depTag = cc.SharedDepTag()
- deps = []string{config.LibclangRuntimeLibrary(mod.toolchain(mctx), "hwasan")}
- }
+ // Always link against the shared library -- static binaries will pull in the static
+ // library during final link if necessary
+ variations = append(variations,
+ blueprint.Variation{Mutator: "link", Variation: "shared"})
+ depTag = cc.SharedDepTag()
+ deps = []string{config.LibclangRuntimeLibrary(mod.toolchain(mctx), "hwasan")}
}
mctx.AddFarVariationDependencies(variations, depTag, deps...)
@@ -268,6 +325,10 @@
case cc.Asan:
return true
case cc.Hwasan:
+ // TODO(b/180495975): HWASan for static Rust binaries isn't supported yet.
+ if mod.StaticExecutable() {
+ return false
+ }
return true
default:
return false