Support "memtag_heap" sanitizer.
Memtag_heap adds an ELF note that enables MTE heap tagging in bionic/scudo. Ignored on non-executables. With diagnostic (diag:{memtag_heap:true}) enables the SYNC mode, otherwise - ASYNC mode. Memtag_heap defaults to set (with diag) on cc_test targets, unset otherwise. Ignored on non MTE-compatible hardware. Bug: b/135772972 Test: soong tests Change-Id: I88fd0f159e609e17bd13487749980a1ba02cb91c
This commit is contained in:
parent
016370b146
commit
193ac2eb96
14
cc/cc.go
14
cc/cc.go
|
@ -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 {
|
||||
|
|
102
cc/cc_test.go
102
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)
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue