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
This commit is contained in:
Ivan Lozano 2017-06-28 09:10:48 -07:00
parent e9425b0277
commit 0c3a1efae4
5 changed files with 60 additions and 10 deletions

View File

@ -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...)
}

View File

@ -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"`

View File

@ -0,0 +1,4 @@
fun:*([Hh]ash|HASH)*
fun:*([Cc]rypto|CRYPTO)*
fun:*([Ss]ha|SHA)(1|256|512)*
fun:*([Cc]ompress|COMPRESS)*

View File

@ -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)

View File

@ -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))
}