diff options
| -rw-r--r-- | cc/cc.go | 14 | ||||
| -rw-r--r-- | cc/cc_test.go | 102 | ||||
| -rw-r--r-- | cc/sanitize.go | 42 | ||||
| -rw-r--r-- | cc/test.go | 4 | ||||
| -rw-r--r-- | cc/testing.go | 8 |
5 files changed, 169 insertions, 1 deletions
@@ -420,6 +420,7 @@ type VendorProperties struct { type ModuleContextIntf interface { static() bool staticBinary() bool + testBinary() bool header() bool binary() bool object() bool @@ -1261,6 +1262,10 @@ func (ctx *moduleContextImpl) staticBinary() bool { return ctx.mod.staticBinary() } +func (ctx *moduleContextImpl) testBinary() bool { + return ctx.mod.testBinary() +} + func (ctx *moduleContextImpl) header() bool { return ctx.mod.Header() } @@ -2961,6 +2966,15 @@ func (c *Module) staticBinary() bool { return false } +func (c *Module) testBinary() bool { + if test, ok := c.linker.(interface { + testBinary() bool + }); ok { + return test.testBinary() + } + return false +} + // Header returns true if the module is a header-only variant. (See cc/library.go header()). func (c *Module) Header() bool { if h, ok := c.linker.(interface { diff --git a/cc/cc_test.go b/cc/cc_test.go index 3502d5f36..1ab1b82ab 100644 --- a/cc/cc_test.go +++ b/cc/cc_test.go @@ -4461,3 +4461,105 @@ func TestAidlFlagsPassedToTheAidlCompiler(t *testing.T) { t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag) } } + +func checkHasImplicitDep(t *testing.T, m android.TestingModule, name string) { + implicits := m.Rule("ld").Implicits + for _, lib := range implicits { + if strings.Contains(lib.Rel(), name) { + return + } + } + + t.Errorf("%q is not found in implicit deps of module %q", name, m.Module().(*Module).Name()) +} + +func checkDoesNotHaveImplicitDep(t *testing.T, m android.TestingModule, name string) { + implicits := m.Rule("ld").Implicits + for _, lib := range implicits { + if strings.Contains(lib.Rel(), name) { + t.Errorf("%q is found in implicit deps of module %q", name, m.Module().(*Module).Name()) + } + } +} + +func TestSanitizeMemtagHeap(t *testing.T) { + ctx := testCc(t, ` + cc_library_static { + name: "libstatic", + sanitize: { memtag_heap: true }, + } + + cc_library_shared { + name: "libshared", + sanitize: { memtag_heap: true }, + } + + cc_library { + name: "libboth", + sanitize: { memtag_heap: true }, + } + + cc_binary { + name: "binary", + shared_libs: [ "libshared" ], + static_libs: [ "libstatic" ], + } + + cc_binary { + name: "binary_true", + sanitize: { memtag_heap: true }, + } + + cc_binary { + name: "binary_true_sync", + sanitize: { memtag_heap: true, diag: { memtag_heap: true }, }, + } + + cc_binary { + name: "binary_false", + sanitize: { memtag_heap: false }, + } + + cc_test { + name: "test", + gtest: false, + } + + cc_test { + name: "test_true", + gtest: false, + sanitize: { memtag_heap: true }, + } + + cc_test { + name: "test_false", + gtest: false, + sanitize: { memtag_heap: false }, + } + + cc_test { + name: "test_true_async", + gtest: false, + sanitize: { memtag_heap: true, diag: { memtag_heap: false } }, + } + + `) + + variant := "android_arm64_armv8-a" + note_async := "note_memtag_heap_async" + note_sync := "note_memtag_heap_sync" + note_any := "note_memtag_" + + checkDoesNotHaveImplicitDep(t, ctx.ModuleForTests("libshared", "android_arm64_armv8-a_shared"), note_any) + checkDoesNotHaveImplicitDep(t, ctx.ModuleForTests("libboth", "android_arm64_armv8-a_shared"), note_any) + + checkDoesNotHaveImplicitDep(t, ctx.ModuleForTests("binary", variant), note_any) + checkHasImplicitDep(t, ctx.ModuleForTests("binary_true", variant), note_async) + checkHasImplicitDep(t, ctx.ModuleForTests("binary_true_sync", variant), note_sync) + checkDoesNotHaveImplicitDep(t, ctx.ModuleForTests("binary_false", variant), note_any) + + checkHasImplicitDep(t, ctx.ModuleForTests("test", variant), note_sync) + checkHasImplicitDep(t, ctx.ModuleForTests("test_true", variant), note_async) + checkDoesNotHaveImplicitDep(t, ctx.ModuleForTests("test_false", variant), note_any) + checkHasImplicitDep(t, ctx.ModuleForTests("test_true_async", variant), note_async) +} diff --git a/cc/sanitize.go b/cc/sanitize.go index 599261167..13e17803f 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -89,6 +89,7 @@ const ( cfi scs Fuzzer + memtag_heap ) // Name of the sanitizer variation for this sanitizer type @@ -106,6 +107,8 @@ func (t SanitizerType) variationName() string { return "cfi" case scs: return "scs" + case memtag_heap: + return "memtag_heap" case Fuzzer: return "fuzzer" default: @@ -120,6 +123,8 @@ func (t SanitizerType) name() string { return "address" case hwasan: return "hwaddress" + case memtag_heap: + return "memtag_heap" case tsan: return "thread" case intOverflow: @@ -179,6 +184,7 @@ type SanitizeUserProps struct { Integer_overflow *bool `android:"arch_variant"` Scudo *bool `android:"arch_variant"` Scs *bool `android:"arch_variant"` + Memtag_heap *bool `android:"arch_variant"` // A modifier for ASAN and HWASAN for write only instrumentation Writeonly *bool `android:"arch_variant"` @@ -190,6 +196,7 @@ type SanitizeUserProps struct { Undefined *bool `android:"arch_variant"` Cfi *bool `android:"arch_variant"` Integer_overflow *bool `android:"arch_variant"` + Memtag_heap *bool `android:"arch_variant"` Misc_undefined []string `android:"arch_variant"` No_recover []string `android:"arch_variant"` } `android:"arch_variant"` @@ -330,6 +337,9 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) { } s.Writeonly = boolPtr(true) } + if found, globalSanitizers = removeFromList("memtag_heap", globalSanitizers); found && s.Memtag_heap == nil { + s.Memtag_heap = boolPtr(true) + } if len(globalSanitizers) > 0 { ctx.ModuleErrorf("unknown global sanitizer option %s", globalSanitizers[0]) @@ -351,6 +361,12 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) { } } + // cc_test targets default to SYNC MemTag. + if ctx.testBinary() && s.Memtag_heap == nil { + s.Memtag_heap = boolPtr(true) + s.Diag.Memtag_heap = boolPtr(true) + } + // Enable CFI for all components in the include paths (for Aarch64 only) if s.Cfi == nil && ctx.Config().CFIEnabledForPath(ctx.ModuleDir()) && ctx.Arch().ArchType == android.Arm64 { s.Cfi = boolPtr(true) @@ -381,6 +397,11 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) { s.Scs = nil } + // memtag_heap is only implemented on AArch64. + if ctx.Arch().ArchType != android.Arm64 { + s.Memtag_heap = nil + } + // Also disable CFI if ASAN is enabled. if Bool(s.Address) || Bool(s.Hwaddress) { s.Cfi = boolPtr(false) @@ -435,7 +456,7 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) { if ctx.Os() != android.Windows && (Bool(s.All_undefined) || Bool(s.Undefined) || Bool(s.Address) || Bool(s.Thread) || Bool(s.Fuzzer) || Bool(s.Safestack) || Bool(s.Cfi) || Bool(s.Integer_overflow) || len(s.Misc_undefined) > 0 || - Bool(s.Scudo) || Bool(s.Hwaddress) || Bool(s.Scs)) { + Bool(s.Scudo) || Bool(s.Hwaddress) || Bool(s.Scs) || Bool(s.Memtag_heap)) { sanitize.Properties.SanitizerEnabled = true } @@ -717,6 +738,8 @@ func (sanitize *sanitize) getSanitizerBoolPtr(t SanitizerType) *bool { return sanitize.Properties.Sanitize.Cfi case scs: return sanitize.Properties.Sanitize.Scs + case memtag_heap: + return sanitize.Properties.Sanitize.Memtag_heap case Fuzzer: return sanitize.Properties.Sanitize.Fuzzer default: @@ -731,6 +754,7 @@ func (sanitize *sanitize) isUnsanitizedVariant() bool { !sanitize.isSanitizerEnabled(tsan) && !sanitize.isSanitizerEnabled(cfi) && !sanitize.isSanitizerEnabled(scs) && + !sanitize.isSanitizerEnabled(memtag_heap) && !sanitize.isSanitizerEnabled(Fuzzer) } @@ -756,6 +780,8 @@ func (sanitize *sanitize) SetSanitizer(t SanitizerType, b bool) { sanitize.Properties.Sanitize.Cfi = boolPtr(b) case scs: sanitize.Properties.Sanitize.Scs = boolPtr(b) + case memtag_heap: + sanitize.Properties.Sanitize.Memtag_heap = boolPtr(b) case Fuzzer: sanitize.Properties.Sanitize.Fuzzer = boolPtr(b) default: @@ -1032,6 +1058,20 @@ func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) { sanitizers = append(sanitizers, "shadow-call-stack") } + if Bool(c.sanitize.Properties.Sanitize.Memtag_heap) && c.binary() { + noteDep := "note_memtag_heap_async" + if Bool(c.sanitize.Properties.Sanitize.Diag.Memtag_heap) { + noteDep = "note_memtag_heap_sync" + } + depTag := libraryDependencyTag{Kind: staticLibraryDependency, wholeStatic: true} + variations := append(mctx.Target().Variations(), + blueprint.Variation{Mutator: "link", Variation: "static"}) + if c.Device() { + variations = append(variations, c.ImageVariation()) + } + mctx.AddFarVariationDependencies(variations, depTag, noteDep) + } + if Bool(c.sanitize.Properties.Sanitize.Fuzzer) { sanitizers = append(sanitizers, "fuzzer-no-link") } diff --git a/cc/test.go b/cc/test.go index 4ff5bf640..f715a8d70 100644 --- a/cc/test.go +++ b/cc/test.go @@ -236,6 +236,10 @@ func (test *testDecorator) gtest() bool { return BoolDefault(test.Properties.Gtest, true) } +func (test *testDecorator) testBinary() bool { + return true +} + func (test *testDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags { if !test.gtest() { return flags diff --git a/cc/testing.go b/cc/testing.go index 8d92ea2ac..903f76c4a 100644 --- a/cc/testing.go +++ b/cc/testing.go @@ -445,6 +445,14 @@ func GatherRequiredDepsForTest(oses ...android.OsType) string { stl: "none", system_shared_libs: [], } + + cc_library_static { + name: "note_memtag_heap_async", + } + + cc_library_static { + name: "note_memtag_heap_sync", + } ` supportLinuxBionic := false |