diff --git a/cc/cc.go b/cc/cc.go index 1ce83a95c..9176bc3ed 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -56,8 +56,8 @@ func RegisterCCBuildComponents(ctx android.RegistrationContext) { ctx.TopDown("asan_deps", sanitizerDepsMutator(Asan)) ctx.BottomUp("asan", sanitizerMutator(Asan)).Parallel() - ctx.TopDown("hwasan_deps", sanitizerDepsMutator(hwasan)) - ctx.BottomUp("hwasan", sanitizerMutator(hwasan)).Parallel() + ctx.TopDown("hwasan_deps", sanitizerDepsMutator(Hwasan)) + ctx.BottomUp("hwasan", sanitizerMutator(Hwasan)).Parallel() ctx.TopDown("fuzzer_deps", sanitizerDepsMutator(Fuzzer)) ctx.BottomUp("fuzzer", sanitizerMutator(Fuzzer)).Parallel() diff --git a/cc/sanitize.go b/cc/sanitize.go index 8f17e4e4f..397121ef5 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -83,7 +83,7 @@ func boolPtr(v bool) *bool { const ( Asan SanitizerType = iota + 1 - hwasan + Hwasan tsan intOverflow cfi @@ -97,7 +97,7 @@ func (t SanitizerType) variationName() string { switch t { case Asan: return "asan" - case hwasan: + case Hwasan: return "hwasan" case tsan: return "tsan" @@ -121,7 +121,7 @@ func (t SanitizerType) name() string { switch t { case Asan: return "address" - case hwasan: + case Hwasan: return "hwaddress" case memtag_heap: return "memtag_heap" @@ -144,7 +144,7 @@ func (*Module) SanitizerSupported(t SanitizerType) bool { switch t { case Asan: return true - case hwasan: + case Hwasan: return true case tsan: return true @@ -163,7 +163,7 @@ func (*Module) SanitizerSupported(t SanitizerType) bool { // incompatibleWithCfi returns true if a sanitizer is incompatible with CFI. func (t SanitizerType) incompatibleWithCfi() bool { - return t == Asan || t == Fuzzer || t == hwasan + return t == Asan || t == Fuzzer || t == Hwasan } type SanitizeUserProps struct { @@ -745,7 +745,7 @@ func (sanitize *sanitize) getSanitizerBoolPtr(t SanitizerType) *bool { switch t { case Asan: return sanitize.Properties.Sanitize.Address - case hwasan: + case Hwasan: return sanitize.Properties.Sanitize.Hwaddress case tsan: return sanitize.Properties.Sanitize.Thread @@ -767,7 +767,7 @@ func (sanitize *sanitize) getSanitizerBoolPtr(t SanitizerType) *bool { // isUnsanitizedVariant returns true if no sanitizers are enabled. func (sanitize *sanitize) isUnsanitizedVariant() bool { return !sanitize.isSanitizerEnabled(Asan) && - !sanitize.isSanitizerEnabled(hwasan) && + !sanitize.isSanitizerEnabled(Hwasan) && !sanitize.isSanitizerEnabled(tsan) && !sanitize.isSanitizerEnabled(cfi) && !sanitize.isSanitizerEnabled(scs) && @@ -778,7 +778,7 @@ func (sanitize *sanitize) isUnsanitizedVariant() bool { // isVariantOnProductionDevice returns true if variant is for production devices (no non-production sanitizers enabled). func (sanitize *sanitize) isVariantOnProductionDevice() bool { return !sanitize.isSanitizerEnabled(Asan) && - !sanitize.isSanitizerEnabled(hwasan) && + !sanitize.isSanitizerEnabled(Hwasan) && !sanitize.isSanitizerEnabled(tsan) && !sanitize.isSanitizerEnabled(Fuzzer) } @@ -787,7 +787,7 @@ func (sanitize *sanitize) SetSanitizer(t SanitizerType, b bool) { switch t { case Asan: sanitize.Properties.Sanitize.Address = boolPtr(b) - case hwasan: + case Hwasan: sanitize.Properties.Sanitize.Hwaddress = boolPtr(b) case tsan: sanitize.Properties.Sanitize.Thread = boolPtr(b) @@ -902,7 +902,7 @@ func sanitizerDepsMutator(t SanitizerType) func(android.TopDownMutatorContext) { if d, ok := child.(PlatformSanitizeable); ok && d.SanitizePropDefined() && !d.SanitizeNever() && !d.IsSanitizerExplicitlyDisabled(t) { - if t == cfi || t == hwasan || t == scs { + if t == cfi || t == Hwasan || t == scs { if d.StaticallyLinked() && d.SanitizerSupported(t) { // Rust does not support some of these sanitizers, so we need to check if it's // supported before setting this true. @@ -1286,7 +1286,7 @@ func sanitizerMutator(t SanitizerType) func(android.BottomUpMutatorContext) { // For cfi/scs/hwasan, we can export both sanitized and un-sanitized variants // to Make, because the sanitized version has a different suffix in name. // For other types of sanitizers, suppress the variation that is disabled. - if t != cfi && t != scs && t != hwasan { + if t != cfi && t != scs && t != Hwasan { if isSanitizerEnabled { modules[0].(PlatformSanitizeable).SetPreventInstall() modules[0].(PlatformSanitizeable).SetHideFromMake() @@ -1300,7 +1300,7 @@ func sanitizerMutator(t SanitizerType) func(android.BottomUpMutatorContext) { if c.StaticallyLinked() && c.ExportedToMake() { if t == cfi { cfiStaticLibs(mctx.Config()).add(c, c.Module().Name()) - } else if t == hwasan { + } else if t == Hwasan { hwasanStaticLibs(mctx.Config()).add(c, c.Module().Name()) } } @@ -1417,7 +1417,7 @@ var hwasanStaticLibsKey = android.NewOnceKey("hwasanStaticLibs") func hwasanStaticLibs(config android.Config) *sanitizerStaticLibsMap { return config.Once(hwasanStaticLibsKey, func() interface{} { - return newSanitizerStaticLibsMap(hwasan) + return newSanitizerStaticLibsMap(Hwasan) }).(*sanitizerStaticLibsMap) } diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go index 3d31be468..3437d77a4 100644 --- a/cc/vendor_snapshot.go +++ b/cc/vendor_snapshot.go @@ -196,7 +196,7 @@ func isSnapshotAware(cfg android.DeviceConfig, m *Module, inProprietaryPath bool if m.sanitize != nil { // scs and hwasan export both sanitized and unsanitized variants for static and header // Always use unsanitized variants of them. - for _, t := range []SanitizerType{scs, hwasan} { + for _, t := range []SanitizerType{scs, Hwasan} { if !l.shared() && m.sanitize.isSanitizerEnabled(t) { return false } diff --git a/rust/androidmk.go b/rust/androidmk.go index b0e69677a..dea32a34d 100644 --- a/rust/androidmk.go +++ b/rust/androidmk.go @@ -70,6 +70,11 @@ func (mod *Module) AndroidMkEntries() []android.AndroidMkEntries { // If the compiler is disabled, this is a SourceProvider. mod.SubAndroidMk(&ret, mod.sourceProvider) } + + if mod.sanitize != nil { + mod.SubAndroidMk(&ret, mod.sanitize) + } + ret.SubName += mod.Properties.SubName return []android.AndroidMkEntries{ret} diff --git a/rust/sanitize.go b/rust/sanitize.go index a02a72b29..ae3eff006 100644 --- a/rust/sanitize.go +++ b/rust/sanitize.go @@ -23,11 +23,12 @@ import ( ) type SanitizeProperties struct { - // enable AddressSanitizer, ThreadSanitizer, or UndefinedBehaviorSanitizer + // enable AddressSanitizer, HWAddressSanitizer, and others. Sanitize struct { - Address *bool `android:"arch_variant"` - Fuzzer *bool `android:"arch_variant"` - Never *bool `android:"arch_variant"` + Address *bool `android:"arch_variant"` + Hwaddress *bool `android:"arch_variant"` + Fuzzer *bool `android:"arch_variant"` + Never *bool `android:"arch_variant"` } SanitizerEnabled bool `blueprint:"mutated"` SanitizeDep bool `blueprint:"mutated"` @@ -56,6 +57,11 @@ var asanFlags = []string{ "-Z sanitizer=address", } +var hwasanFlags = []string{ + "-Z sanitizer=hwaddress", + "-C target-feature=+tagged-globals", +} + func boolPtr(v bool) *bool { if v { return &v @@ -82,6 +88,15 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) { if ctx.Os() == android.Android && Bool(s.Address) { sanitize.Properties.SanitizerEnabled = true } + + // HWASan requires AArch64 hardware feature (top-byte-ignore). + if ctx.Arch().ArchType != android.Arm64 { + s.Hwaddress = nil + } + + if ctx.Os() == android.Android && Bool(s.Hwaddress) { + sanitize.Properties.SanitizerEnabled = true + } } type sanitize struct { @@ -98,6 +113,9 @@ func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags, deps PathDeps) ( if Bool(sanitize.Properties.Sanitize.Address) { flags.RustFlags = append(flags.RustFlags, asanFlags...) } + if Bool(sanitize.Properties.Sanitize.Hwaddress) { + flags.RustFlags = append(flags.RustFlags, hwasanFlags...) + } return flags, deps } @@ -110,11 +128,38 @@ func rustSanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) { if !mod.Enabled() { return } + + variations := mctx.Target().Variations() + var depTag blueprint.DependencyTag + var deps []string + if Bool(mod.sanitize.Properties.Sanitize.Fuzzer) || Bool(mod.sanitize.Properties.Sanitize.Address) { - mctx.AddFarVariationDependencies(append(mctx.Target().Variations(), []blueprint.Variation{ - {Mutator: "link", Variation: "shared"}, - }...), cc.SharedDepTag(), config.LibclangRuntimeLibrary(mod.toolchain(mctx), "asan")) + variations = append(variations, + blueprint.Variation{Mutator: "link", Variation: "shared"}) + depTag = cc.SharedDepTag() + deps = []string{config.LibclangRuntimeLibrary(mod.toolchain(mctx), "asan")} + } else if mod.IsSanitizerEnabled(cc.Hwasan) { + // 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) { + 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")} + } } + + mctx.AddFarVariationDependencies(variations, depTag, deps...) } } @@ -127,6 +172,9 @@ func (sanitize *sanitize) SetSanitizer(t cc.SanitizerType, b bool) { case cc.Asan: sanitize.Properties.Sanitize.Address = boolPtr(b) sanitizerSet = true + case cc.Hwasan: + sanitize.Properties.Sanitize.Hwaddress = boolPtr(b) + sanitizerSet = true default: panic(fmt.Errorf("setting unsupported sanitizerType %d", t)) } @@ -168,11 +216,23 @@ func (sanitize *sanitize) getSanitizerBoolPtr(t cc.SanitizerType) *bool { return sanitize.Properties.Sanitize.Fuzzer case cc.Asan: return sanitize.Properties.Sanitize.Address + case cc.Hwasan: + return sanitize.Properties.Sanitize.Hwaddress default: return nil } } +func (sanitize *sanitize) AndroidMk(ctx AndroidMkContext, entries *android.AndroidMkEntries) { + // Add a suffix for hwasan rlib libraries to allow surfacing both the sanitized and + // non-sanitized variants to make without a name conflict. + if entries.Class == "RLIB_LIBRARIES" || entries.Class == "STATIC_LIBRARIES" { + if sanitize.isSanitizerEnabled(cc.Hwasan) { + entries.SubName += ".hwasan" + } + } +} + func (mod *Module) SanitizerSupported(t cc.SanitizerType) bool { if mod.Host() { return false @@ -182,6 +242,8 @@ func (mod *Module) SanitizerSupported(t cc.SanitizerType) bool { return true case cc.Asan: return true + case cc.Hwasan: + return true default: return false }