From 0c3a1efae4814f62ece007c7fc2251386aaae2f2 Mon Sep 17 00:00:00 2001 From: Ivan Lozano Date: Wed, 28 Jun 2017 09:10:48 -0700 Subject: [PATCH] Add integer_overflow sanitization build option. Adds the SANITIZE_TARGET=integer_overflow build option to apply signed and unsigned integer overflow sanitization globally. This implements the Soong side of the build option. An additional build option is provided to control whether or not to run in diagnostics mode, controlled by SANITIZE_TARGET_DIAG. This works the same way that SANITIZE_TARGET does and currently only supports 'integer_overflow' as an option. A default sanitizer blacklist is added to avoid applying sanitization to functions that are likely to exhibit benign overflows. Bug: 30969751 Test: Building with and without the new flags, device boot-up, tested various permutations of controlling the new flags from build files. Change-Id: Ibc8a8615d3132f1a23faaf1cb4861f24c5ef734a --- android/config.go | 4 ++ android/variable.go | 1 + cc/config/integer_overflow_blacklist.txt | 4 ++ cc/makevars.go | 2 + cc/sanitize.go | 59 ++++++++++++++++++++---- 5 files changed, 60 insertions(+), 10 deletions(-) create mode 100644 cc/config/integer_overflow_blacklist.txt diff --git a/android/config.go b/android/config.go index dbb9fa41f..1b0606387 100644 --- a/android/config.go +++ b/android/config.go @@ -428,6 +428,10 @@ func (c *config) SanitizeDevice() []string { return append([]string(nil), c.ProductVariables.SanitizeDevice...) } +func (c *config) SanitizeDeviceDiag() []string { + return append([]string(nil), c.ProductVariables.SanitizeDeviceDiag...) +} + func (c *config) SanitizeDeviceArch() []string { return append([]string(nil), c.ProductVariables.SanitizeDeviceArch...) } diff --git a/android/variable.go b/android/variable.go index 05f50b5e7..1efab47e7 100644 --- a/android/variable.go +++ b/android/variable.go @@ -154,6 +154,7 @@ type productVariables struct { SanitizeHost []string `json:",omitempty"` SanitizeDevice []string `json:",omitempty"` + SanitizeDeviceDiag []string `json:",omitempty"` SanitizeDeviceArch []string `json:",omitempty"` ArtUseReadBarrier *bool `json:",omitempty"` diff --git a/cc/config/integer_overflow_blacklist.txt b/cc/config/integer_overflow_blacklist.txt new file mode 100644 index 000000000..3480c3c08 --- /dev/null +++ b/cc/config/integer_overflow_blacklist.txt @@ -0,0 +1,4 @@ +fun:*([Hh]ash|HASH)* +fun:*([Cc]rypto|CRYPTO)* +fun:*([Ss]ha|SHA)(1|256|512)* +fun:*([Cc]ompress|COMPRESS)* diff --git a/cc/makevars.go b/cc/makevars.go index 2a5c81378..11c316225 100644 --- a/cc/makevars.go +++ b/cc/makevars.go @@ -66,6 +66,8 @@ func makeVarsProvider(ctx android.MakeVarsContext) { ctx.Strict("CFI_EXTRA_CFLAGS", strings.Join(cfiCflags, " ")) ctx.Strict("CFI_EXTRA_LDFLAGS", strings.Join(cfiLdflags, " ")) + ctx.Strict("INTEGER_OVERFLOW_EXTRA_CFLAGS", strings.Join(intOverflowCflags, " ")) + ctx.Strict("DEFAULT_C_STD_VERSION", config.CStdVersion) ctx.Strict("DEFAULT_CPP_STD_VERSION", config.CppStdVersion) ctx.Strict("DEFAULT_GCC_CPP_STD_VERSION", config.GccCppStdVersion) diff --git a/cc/sanitize.go b/cc/sanitize.go index e54ece66a..49bd0f310 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -40,6 +40,8 @@ var ( cfiLdflags = []string{"-flto", "-fsanitize-cfi-cross-dso", "-fsanitize=cfi", "-Wl,-plugin-opt,O1 -Wl,-export-dynamic-symbol=__cfi_check"} cfiArflags = []string{"--plugin ${config.ClangBin}/../lib64/LLVMgold.so"} + + intOverflowCflags = []string{"-fsanitize-blacklist=build/soong/cc/config/integer_overflow_blacklist.txt"} ) type sanitizerType int @@ -55,6 +57,7 @@ func boolPtr(v bool) *bool { const ( asan sanitizerType = iota + 1 tsan + intOverflow ) func (t sanitizerType) String() string { @@ -63,6 +66,8 @@ func (t sanitizerType) String() string { return "asan" case tsan: return "tsan" + case intOverflow: + return "intOverflow" default: panic(fmt.Errorf("unknown sanitizerType %d", t)) } @@ -78,20 +83,22 @@ type SanitizeProperties struct { Thread *bool `android:"arch_variant"` // local sanitizers - Undefined *bool `android:"arch_variant"` - All_undefined *bool `android:"arch_variant"` - Misc_undefined []string `android:"arch_variant"` - Coverage *bool `android:"arch_variant"` - Safestack *bool `android:"arch_variant"` - Cfi *bool `android:"arch_variant"` + Undefined *bool `android:"arch_variant"` + All_undefined *bool `android:"arch_variant"` + Misc_undefined []string `android:"arch_variant"` + Coverage *bool `android:"arch_variant"` + Safestack *bool `android:"arch_variant"` + Cfi *bool `android:"arch_variant"` + Integer_overflow *bool `android:"arch_variant"` // Sanitizers to run in the diagnostic mode (as opposed to the release mode). // Replaces abort() on error with a human-readable error message. // Address and Thread sanitizers always run in diagnostic mode. Diag struct { - Undefined *bool `android:"arch_variant"` - Cfi *bool `android:"arch_variant"` - Misc_undefined []string `android:"arch_variant"` + Undefined *bool `android:"arch_variant"` + Cfi *bool `android:"arch_variant"` + Integer_overflow *bool `android:"arch_variant"` + Misc_undefined []string `android:"arch_variant"` } // value to pass to -fsanitize-recover= @@ -130,6 +137,8 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) { } var globalSanitizers []string + var globalSanitizersDiag []string + if ctx.clang() { if ctx.Host() { globalSanitizers = ctx.AConfig().SanitizeHost() @@ -137,6 +146,7 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) { arches := ctx.AConfig().SanitizeDeviceArch() if len(arches) == 0 || inList(ctx.Arch().ArchType.Name, arches) { globalSanitizers = ctx.AConfig().SanitizeDevice() + globalSanitizersDiag = ctx.AConfig().SanitizeDeviceDiag() } } } @@ -177,9 +187,22 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) { s.Cfi = boolPtr(true) } + if found, globalSanitizers = removeFromList("integer_overflow", globalSanitizers); found && s.Integer_overflow == nil { + s.Integer_overflow = boolPtr(true) + } + if len(globalSanitizers) > 0 { ctx.ModuleErrorf("unknown global sanitizer option %s", globalSanitizers[0]) } + + if found, globalSanitizersDiag = removeFromList("integer_overflow", globalSanitizersDiag); found && + s.Diag.Integer_overflow == nil && Bool(s.Integer_overflow) { + s.Diag.Integer_overflow = boolPtr(true) + } + + if len(globalSanitizersDiag) > 0 { + ctx.ModuleErrorf("unknown global sanitizer diagnostics option %s", globalSanitizersDiag[0]) + } } // CFI needs gold linker, and mips toolchain does not have one. @@ -218,7 +241,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.Coverage) || Bool(s.Safestack) || Bool(s.Cfi) || len(s.Misc_undefined) > 0) { + Bool(s.Coverage) || Bool(s.Safestack) || Bool(s.Cfi) || Bool(s.Integer_overflow) || len(s.Misc_undefined) > 0) { sanitize.Properties.SanitizerEnabled = true } @@ -349,6 +372,18 @@ func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags) Flags { } } + if Bool(sanitize.Properties.Sanitize.Integer_overflow) { + if !ctx.static() { + sanitizers = append(sanitizers, "unsigned-integer-overflow") + sanitizers = append(sanitizers, "signed-integer-overflow") + flags.CFlags = append(flags.CFlags, intOverflowCflags...) + if Bool(sanitize.Properties.Sanitize.Diag.Integer_overflow) { + diagSanitizers = append(diagSanitizers, "unsigned-integer-overflow") + diagSanitizers = append(diagSanitizers, "signed-integer-overflow") + } + } + } + if len(sanitizers) > 0 { sanitizeArg := "-fsanitize=" + strings.Join(sanitizers, ",") flags.CFlags = append(flags.CFlags, sanitizeArg) @@ -426,6 +461,8 @@ func (sanitize *sanitize) Sanitizer(t sanitizerType) bool { return Bool(sanitize.Properties.Sanitize.Address) case tsan: return Bool(sanitize.Properties.Sanitize.Thread) + case intOverflow: + return Bool(sanitize.Properties.Sanitize.Integer_overflow) default: panic(fmt.Errorf("unknown sanitizerType %d", t)) } @@ -440,6 +477,8 @@ func (sanitize *sanitize) SetSanitizer(t sanitizerType, b bool) { } case tsan: sanitize.Properties.Sanitize.Thread = boolPtr(b) + case intOverflow: + sanitize.Properties.Sanitize.Integer_overflow = boolPtr(b) default: panic(fmt.Errorf("unknown sanitizerType %d", t)) }