Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 30c5db2f authored by Ivan Lozano's avatar Ivan Lozano
Browse files

Add minimal-runtime support for integer overflows.

Adds Soong support for -fsanitze-minimal-runtime when using
the integer overflow sanitizers. This makes the crashes due to these
sanitizers less mysterious.

Bug: 64091660
Test: Compiled and checked the generated compiler commands
Test: Checked program that overflows for the abort reason

Change-Id: Ieeceaf6c35c8371592952d3b8b977aefc11601c5
parent d4bc5562
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -52,6 +52,8 @@ func init() {
		ctx.TopDown("tsan_deps", sanitizerDepsMutator(tsan))
		ctx.BottomUp("tsan", sanitizerMutator(tsan)).Parallel()

		ctx.TopDown("minimal_runtime_deps", minimalRuntimeDepsMutator())

		ctx.BottomUp("coverage", coverageLinkingMutator).Parallel()
		ctx.TopDown("vndk_deps", sabiDepsMutator)

+4 −0
Original line number Diff line number Diff line
@@ -215,6 +215,10 @@ func UndefinedBehaviorSanitizerRuntimeLibrary(t Toolchain) string {
	return SanitizerRuntimeLibrary(t, "ubsan_standalone")
}

func UndefinedBehaviorSanitizerMinimalRuntimeLibrary(t Toolchain) string {
	return SanitizerRuntimeLibrary(t, "ubsan_minimal")
}

func ThreadSanitizerRuntimeLibrary(t Toolchain) string {
	return SanitizerRuntimeLibrary(t, "tsan")
}
+1 −0
Original line number Diff line number Diff line
@@ -276,6 +276,7 @@ func makeVarsToolchain(ctx android.MakeVarsContext, secondPrefix string,
		if target.Os.Class == android.Device {
			ctx.Strict(secondPrefix+"ADDRESS_SANITIZER_RUNTIME_LIBRARY", strings.TrimSuffix(config.AddressSanitizerRuntimeLibrary(toolchain), ".so"))
			ctx.Strict(secondPrefix+"UBSAN_RUNTIME_LIBRARY", strings.TrimSuffix(config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain), ".so"))
			ctx.Strict(secondPrefix+"UBSAN_MINIMAL_RUNTIME_LIBRARY", strings.TrimSuffix(config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(toolchain), ".a"))
			ctx.Strict(secondPrefix+"TSAN_RUNTIME_LIBRARY", strings.TrimSuffix(config.ThreadSanitizerRuntimeLibrary(toolchain), ".so"))
		}

+47 −4
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ var (
	cfiStaticLibsMutex sync.Mutex

	intOverflowCflags   = []string{"-fsanitize-blacklist=build/soong/cc/config/integer_overflow_blacklist.txt"}
	minimalRuntimeFlags = []string{"-fsanitize-minimal-runtime", "-fno-sanitize-trap=integer", "-fno-sanitize-recover=integer"}
)

type sanitizerType int
@@ -114,6 +115,7 @@ type SanitizeProperties struct {

	SanitizerEnabled  bool `blueprint:"mutated"`
	SanitizeDep       bool `blueprint:"mutated"`
	MinimalRuntimeDep bool `blueprint:"mutated"`
	InSanitizerDir    bool `blueprint:"mutated"`
}

@@ -301,6 +303,11 @@ func (sanitize *sanitize) deps(ctx BaseModuleContext, deps Deps) Deps {
}

func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags) Flags {
	minimalRuntimePath := "${config.ClangAsanLibDir}/" + config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(ctx.toolchain()) + ".a"

	if ctx.Device() && sanitize.Properties.MinimalRuntimeDep {
		flags.LdFlags = append(flags.LdFlags, minimalRuntimePath)
	}
	if !sanitize.Properties.SanitizerEnabled {
		return flags
	}
@@ -431,6 +438,7 @@ func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags) Flags {

	if len(sanitizers) > 0 {
		sanitizeArg := "-fsanitize=" + strings.Join(sanitizers, ",")

		flags.CFlags = append(flags.CFlags, sanitizeArg)
		if ctx.Host() {
			flags.CFlags = append(flags.CFlags, "-fno-sanitize-recover=all")
@@ -440,6 +448,11 @@ func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags) Flags {
			_, flags.LdFlags = removeFromList("-Wl,--no-undefined", flags.LdFlags)
		} else {
			flags.CFlags = append(flags.CFlags, "-fsanitize-trap=all", "-ftrap-function=abort")

			if enableMinimalRuntime(sanitize) {
				flags.CFlags = append(flags.CFlags, strings.Join(minimalRuntimeFlags, " "))
				flags.libFlags = append([]string{minimalRuntimePath}, flags.libFlags...)
			}
		}
	}

@@ -589,6 +602,24 @@ func sanitizerDepsMutator(t sanitizerType) func(android.TopDownMutatorContext) {
	}
}

// Propagate the ubsan minimal runtime dependency when there are integer overflow sanitized static dependencies.
func minimalRuntimeDepsMutator() func(android.TopDownMutatorContext) {
	return func(mctx android.TopDownMutatorContext) {
		if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil {
			mctx.VisitDepsDepthFirst(func(module android.Module) {
				if d, ok := module.(*Module); ok && d.static() && d.sanitize != nil {

					// If a static dependency will be built with the minimal runtime,
					// make sure we include the ubsan minimal runtime.
					if enableMinimalRuntime(d.sanitize) {
						c.sanitize.Properties.MinimalRuntimeDep = true
					}
				}
			})
		}
	}
}

// Create sanitized variants for modules that need them
func sanitizerMutator(t sanitizerType) func(android.BottomUpMutatorContext) {
	return func(mctx android.BottomUpMutatorContext) {
@@ -659,6 +690,18 @@ func cfiStaticLibs(config android.Config) *[]string {
	}).(*[]string)
}

func enableMinimalRuntime(sanitize *sanitize) bool {
	if !Bool(sanitize.Properties.Sanitize.Address) &&
		(Bool(sanitize.Properties.Sanitize.Integer_overflow) ||
			len(sanitize.Properties.Sanitize.Misc_undefined) > 0) &&
		!(Bool(sanitize.Properties.Sanitize.Diag.Integer_overflow) ||
			Bool(sanitize.Properties.Sanitize.Diag.Cfi) ||
			len(sanitize.Properties.Sanitize.Diag.Misc_undefined) > 0) {
		return true
	}
	return false
}

func cfiMakeVarsProvider(ctx android.MakeVarsContext) {
	cfiStaticLibs := cfiStaticLibs(ctx.Config())
	sort.Strings(*cfiStaticLibs)