• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2016 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package cc
16
17import (
18	"fmt"
19	"sort"
20	"strings"
21	"sync"
22
23	"github.com/google/blueprint"
24	"github.com/google/blueprint/proptools"
25
26	"android/soong/android"
27	"android/soong/cc/config"
28	"android/soong/snapshot"
29)
30
31var (
32	// Any C flags added by sanitizer which libTooling tools may not
33	// understand also need to be added to ClangLibToolingUnknownCflags in
34	// cc/config/clang.go
35
36	asanCflags = []string{
37		"-fno-omit-frame-pointer",
38	}
39	asanLdflags = []string{"-Wl,-u,__asan_preinit"}
40
41	hwasanCflags = []string{
42		"-fno-omit-frame-pointer",
43		"-Wno-frame-larger-than=",
44		"-fsanitize-hwaddress-abi=platform",
45		"-mllvm", "-hwasan-use-after-scope=1",
46	}
47
48	// ThinLTO performs codegen during link time, thus these flags need to
49	// passed to both CFLAGS and LDFLAGS.
50	hwasanCommonflags = []string{
51		// The following improves debug location information
52		// availability at the cost of its accuracy. It increases
53		// the likelihood of a stack variable's frame offset
54		// to be recorded in the debug info, which is important
55		// for the quality of hwasan reports. The downside is a
56		// higher number of "optimized out" stack variables.
57		// b/112437883.
58		"-instcombine-lower-dbg-declare=0",
59		// TODO(b/159343917): HWASan and GlobalISel don't play nicely, and
60		// GlobalISel is the default at -O0 on aarch64.
61		"--aarch64-enable-global-isel-at-O=-1",
62		"-fast-isel=false",
63	}
64
65	cfiCflags = []string{"-flto", "-fsanitize-cfi-cross-dso",
66		"-fsanitize-ignorelist=external/compiler-rt/lib/cfi/cfi_blocklist.txt"}
67	// -flto and -fvisibility are required by clang when -fsanitize=cfi is
68	// used, but have no effect on assembly files
69	cfiAsflags = []string{"-flto", "-fvisibility=default"}
70	cfiLdflags = []string{"-flto", "-fsanitize-cfi-cross-dso", "-fsanitize=cfi",
71		"-Wl,-plugin-opt,O1"}
72	cfiExportsMapPath = "build/soong/cc/config/cfi_exports.map"
73
74	intOverflowCflags = []string{"-fsanitize-ignorelist=build/soong/cc/config/integer_overflow_blocklist.txt"}
75
76	minimalRuntimeFlags = []string{"-fsanitize-minimal-runtime", "-fno-sanitize-trap=integer,undefined",
77		"-fno-sanitize-recover=integer,undefined"}
78	hwasanGlobalOptions = []string{"heap_history_size=1023", "stack_history_size=512",
79		"export_memory_stats=0", "max_malloc_fill_size=4096", "malloc_fill_byte=0"}
80)
81
82type SanitizerType int
83
84const (
85	Asan SanitizerType = iota + 1
86	Hwasan
87	tsan
88	intOverflow
89	scs
90	Fuzzer
91	Memtag_heap
92	cfi // cfi is last to prevent it running before incompatible mutators
93)
94
95var Sanitizers = []SanitizerType{
96	Asan,
97	Hwasan,
98	tsan,
99	intOverflow,
100	scs,
101	Fuzzer,
102	Memtag_heap,
103	cfi, // cfi is last to prevent it running before incompatible mutators
104}
105
106// Name of the sanitizer variation for this sanitizer type
107func (t SanitizerType) variationName() string {
108	switch t {
109	case Asan:
110		return "asan"
111	case Hwasan:
112		return "hwasan"
113	case tsan:
114		return "tsan"
115	case intOverflow:
116		return "intOverflow"
117	case cfi:
118		return "cfi"
119	case scs:
120		return "scs"
121	case Memtag_heap:
122		return "memtag_heap"
123	case Fuzzer:
124		return "fuzzer"
125	default:
126		panic(fmt.Errorf("unknown SanitizerType %d", t))
127	}
128}
129
130// This is the sanitizer names in SANITIZE_[TARGET|HOST]
131func (t SanitizerType) name() string {
132	switch t {
133	case Asan:
134		return "address"
135	case Hwasan:
136		return "hwaddress"
137	case Memtag_heap:
138		return "memtag_heap"
139	case tsan:
140		return "thread"
141	case intOverflow:
142		return "integer_overflow"
143	case cfi:
144		return "cfi"
145	case scs:
146		return "shadow-call-stack"
147	case Fuzzer:
148		return "fuzzer"
149	default:
150		panic(fmt.Errorf("unknown SanitizerType %d", t))
151	}
152}
153
154func (t SanitizerType) registerMutators(ctx android.RegisterMutatorsContext) {
155	switch t {
156	case Asan, Hwasan, Fuzzer, scs, tsan, cfi:
157		ctx.TopDown(t.variationName()+"_deps", sanitizerDepsMutator(t))
158		ctx.BottomUp(t.variationName(), sanitizerMutator(t))
159	case Memtag_heap, intOverflow:
160		// do nothing
161	default:
162		panic(fmt.Errorf("unknown SanitizerType %d", t))
163	}
164}
165
166func (*Module) SanitizerSupported(t SanitizerType) bool {
167	switch t {
168	case Asan:
169		return true
170	case Hwasan:
171		return true
172	case tsan:
173		return true
174	case intOverflow:
175		return true
176	case cfi:
177		return true
178	case scs:
179		return true
180	case Fuzzer:
181		return true
182	case Memtag_heap:
183		return true
184	default:
185		return false
186	}
187}
188
189// incompatibleWithCfi returns true if a sanitizer is incompatible with CFI.
190func (t SanitizerType) incompatibleWithCfi() bool {
191	return t == Asan || t == Fuzzer || t == Hwasan
192}
193
194type SanitizeUserProps struct {
195	// Prevent use of any sanitizers on this module
196	Never *bool `android:"arch_variant"`
197
198	// ASan (Address sanitizer), incompatible with static binaries.
199	// Always runs in a diagnostic mode.
200	// Use of address sanitizer disables cfi sanitizer.
201	// Hwaddress sanitizer takes precedence over this sanitizer.
202	Address *bool `android:"arch_variant"`
203	// TSan (Thread sanitizer), incompatible with static binaries and 32 bit architectures.
204	// Always runs in a diagnostic mode.
205	// Use of thread sanitizer disables cfi and scudo sanitizers.
206	// Hwaddress sanitizer takes precedence over this sanitizer.
207	Thread *bool `android:"arch_variant"`
208	// HWASan (Hardware Address sanitizer).
209	// Use of hwasan sanitizer disables cfi, address, thread, and scudo sanitizers.
210	Hwaddress *bool `android:"arch_variant"`
211
212	// Undefined behavior sanitizer
213	All_undefined *bool `android:"arch_variant"`
214	// Subset of undefined behavior sanitizer
215	Undefined *bool `android:"arch_variant"`
216	// List of specific undefined behavior sanitizers to enable
217	Misc_undefined []string `android:"arch_variant"`
218	// Fuzzer, incompatible with static binaries.
219	Fuzzer *bool `android:"arch_variant"`
220	// safe-stack sanitizer, incompatible with 32-bit architectures.
221	Safestack *bool `android:"arch_variant"`
222	// cfi sanitizer, incompatible with asan, hwasan, fuzzer, or Darwin
223	Cfi *bool `android:"arch_variant"`
224	// signed/unsigned integer overflow sanitizer, incompatible with Darwin.
225	Integer_overflow *bool `android:"arch_variant"`
226	// scudo sanitizer, incompatible with asan, hwasan, tsan
227	// This should not be used in Android 11+ : https://source.android.com/devices/tech/debug/scudo
228	// deprecated
229	Scudo *bool `android:"arch_variant"`
230	// shadow-call-stack sanitizer, only available on arm64
231	Scs *bool `android:"arch_variant"`
232	// Memory-tagging, only available on arm64
233	// if diag.memtag unset or false, enables async memory tagging
234	Memtag_heap *bool `android:"arch_variant"`
235
236	// A modifier for ASAN and HWASAN for write only instrumentation
237	Writeonly *bool `android:"arch_variant"`
238
239	// Sanitizers to run in the diagnostic mode (as opposed to the release mode).
240	// Replaces abort() on error with a human-readable error message.
241	// Address and Thread sanitizers always run in diagnostic mode.
242	Diag struct {
243		// Undefined behavior sanitizer, diagnostic mode
244		Undefined *bool `android:"arch_variant"`
245		// cfi sanitizer, diagnostic mode, incompatible with asan, hwasan, fuzzer, or Darwin
246		Cfi *bool `android:"arch_variant"`
247		// signed/unsigned integer overflow sanitizer, diagnostic mode, incompatible with Darwin.
248		Integer_overflow *bool `android:"arch_variant"`
249		// Memory-tagging, only available on arm64
250		// requires sanitizer.memtag: true
251		// if set, enables sync memory tagging
252		Memtag_heap *bool `android:"arch_variant"`
253		// List of specific undefined behavior sanitizers to enable in diagnostic mode
254		Misc_undefined []string `android:"arch_variant"`
255		// List of sanitizers to pass to -fno-sanitize-recover
256		// results in only the first detected error for these sanitizers being reported and program then
257		// exits with a non-zero exit code.
258		No_recover []string `android:"arch_variant"`
259	} `android:"arch_variant"`
260
261	// Sanitizers to run with flag configuration specified
262	Config struct {
263		// Enables CFI support flags for assembly-heavy libraries
264		Cfi_assembly_support *bool `android:"arch_variant"`
265	} `android:"arch_variant"`
266
267	// List of sanitizers to pass to -fsanitize-recover
268	// allows execution to continue for these sanitizers to detect multiple errors rather than only
269	// the first one
270	Recover []string
271
272	// value to pass to -fsanitize-ignorelist
273	Blocklist *string
274}
275
276type SanitizeProperties struct {
277	Sanitize          SanitizeUserProps `android:"arch_variant"`
278	SanitizerEnabled  bool              `blueprint:"mutated"`
279	SanitizeDep       bool              `blueprint:"mutated"`
280	MinimalRuntimeDep bool              `blueprint:"mutated"`
281	BuiltinsDep       bool              `blueprint:"mutated"`
282	UbsanRuntimeDep   bool              `blueprint:"mutated"`
283	InSanitizerDir    bool              `blueprint:"mutated"`
284	Sanitizers        []string          `blueprint:"mutated"`
285	DiagSanitizers    []string          `blueprint:"mutated"`
286}
287
288type sanitize struct {
289	Properties SanitizeProperties
290}
291
292// Mark this tag with a check to see if apex dependency check should be skipped
293func (t libraryDependencyTag) SkipApexAllowedDependenciesCheck() bool {
294	return t.skipApexAllowedDependenciesCheck
295}
296
297var _ android.SkipApexAllowedDependenciesCheck = (*libraryDependencyTag)(nil)
298
299func init() {
300	android.RegisterMakeVarsProvider(pctx, cfiMakeVarsProvider)
301	android.RegisterMakeVarsProvider(pctx, hwasanMakeVarsProvider)
302}
303
304func (sanitize *sanitize) props() []interface{} {
305	return []interface{}{&sanitize.Properties}
306}
307
308func (sanitize *sanitize) begin(ctx BaseModuleContext) {
309	s := &sanitize.Properties.Sanitize
310
311	// Don't apply sanitizers to NDK code.
312	if ctx.useSdk() {
313		s.Never = BoolPtr(true)
314	}
315
316	// Never always wins.
317	if Bool(s.Never) {
318		return
319	}
320
321	// cc_test targets default to SYNC MemTag unless explicitly set to ASYNC (via diag: {memtag_heap}).
322	if ctx.testBinary() {
323		if s.Memtag_heap == nil {
324			s.Memtag_heap = proptools.BoolPtr(true)
325		}
326		if s.Diag.Memtag_heap == nil {
327			s.Diag.Memtag_heap = proptools.BoolPtr(true)
328		}
329	}
330
331	var globalSanitizers []string
332	var globalSanitizersDiag []string
333
334	if ctx.Host() {
335		if !ctx.Windows() {
336			globalSanitizers = ctx.Config().SanitizeHost()
337		}
338	} else {
339		arches := ctx.Config().SanitizeDeviceArch()
340		if len(arches) == 0 || inList(ctx.Arch().ArchType.Name, arches) {
341			globalSanitizers = ctx.Config().SanitizeDevice()
342			globalSanitizersDiag = ctx.Config().SanitizeDeviceDiag()
343		}
344	}
345
346	if len(globalSanitizers) > 0 {
347		var found bool
348		if found, globalSanitizers = removeFromList("undefined", globalSanitizers); found && s.All_undefined == nil {
349			s.All_undefined = proptools.BoolPtr(true)
350		}
351
352		if found, globalSanitizers = removeFromList("default-ub", globalSanitizers); found && s.Undefined == nil {
353			s.Undefined = proptools.BoolPtr(true)
354		}
355
356		if found, globalSanitizers = removeFromList("address", globalSanitizers); found && s.Address == nil {
357			s.Address = proptools.BoolPtr(true)
358		}
359
360		if found, globalSanitizers = removeFromList("thread", globalSanitizers); found && s.Thread == nil {
361			s.Thread = proptools.BoolPtr(true)
362		}
363
364		if found, globalSanitizers = removeFromList("fuzzer", globalSanitizers); found && s.Fuzzer == nil {
365			s.Fuzzer = proptools.BoolPtr(true)
366		}
367
368		if found, globalSanitizers = removeFromList("safe-stack", globalSanitizers); found && s.Safestack == nil {
369			s.Safestack = proptools.BoolPtr(true)
370		}
371
372		if found, globalSanitizers = removeFromList("cfi", globalSanitizers); found && s.Cfi == nil {
373			if !ctx.Config().CFIDisabledForPath(ctx.ModuleDir()) {
374				s.Cfi = proptools.BoolPtr(true)
375			}
376		}
377
378		// Global integer_overflow builds do not support static libraries.
379		if found, globalSanitizers = removeFromList("integer_overflow", globalSanitizers); found && s.Integer_overflow == nil {
380			if !ctx.Config().IntegerOverflowDisabledForPath(ctx.ModuleDir()) && !ctx.static() {
381				s.Integer_overflow = proptools.BoolPtr(true)
382			}
383		}
384
385		if found, globalSanitizers = removeFromList("scudo", globalSanitizers); found && s.Scudo == nil {
386			s.Scudo = proptools.BoolPtr(true)
387		}
388
389		if found, globalSanitizers = removeFromList("hwaddress", globalSanitizers); found && s.Hwaddress == nil {
390			s.Hwaddress = proptools.BoolPtr(true)
391		}
392
393		if found, globalSanitizers = removeFromList("writeonly", globalSanitizers); found && s.Writeonly == nil {
394			// Hwaddress and Address are set before, so we can check them here
395			// If they aren't explicitly set in the blueprint/SANITIZE_(HOST|TARGET), they would be nil instead of false
396			if s.Address == nil && s.Hwaddress == nil {
397				ctx.ModuleErrorf("writeonly modifier cannot be used without 'address' or 'hwaddress'")
398			}
399			s.Writeonly = proptools.BoolPtr(true)
400		}
401		if found, globalSanitizers = removeFromList("memtag_heap", globalSanitizers); found && s.Memtag_heap == nil {
402			if !ctx.Config().MemtagHeapDisabledForPath(ctx.ModuleDir()) {
403				s.Memtag_heap = proptools.BoolPtr(true)
404			}
405		}
406
407		if len(globalSanitizers) > 0 {
408			ctx.ModuleErrorf("unknown global sanitizer option %s", globalSanitizers[0])
409		}
410
411		// Global integer_overflow builds do not support static library diagnostics.
412		if found, globalSanitizersDiag = removeFromList("integer_overflow", globalSanitizersDiag); found &&
413			s.Diag.Integer_overflow == nil && Bool(s.Integer_overflow) && !ctx.static() {
414			s.Diag.Integer_overflow = proptools.BoolPtr(true)
415		}
416
417		if found, globalSanitizersDiag = removeFromList("cfi", globalSanitizersDiag); found &&
418			s.Diag.Cfi == nil && Bool(s.Cfi) {
419			s.Diag.Cfi = proptools.BoolPtr(true)
420		}
421
422		if found, globalSanitizersDiag = removeFromList("memtag_heap", globalSanitizersDiag); found &&
423			s.Diag.Memtag_heap == nil && Bool(s.Memtag_heap) {
424			s.Diag.Memtag_heap = proptools.BoolPtr(true)
425		}
426
427		if len(globalSanitizersDiag) > 0 {
428			ctx.ModuleErrorf("unknown global sanitizer diagnostics option %s", globalSanitizersDiag[0])
429		}
430	}
431
432	// Enable Memtag for all components in the include paths (for Aarch64 only)
433	if ctx.Arch().ArchType == android.Arm64 {
434		if ctx.Config().MemtagHeapSyncEnabledForPath(ctx.ModuleDir()) {
435			if s.Memtag_heap == nil {
436				s.Memtag_heap = proptools.BoolPtr(true)
437			}
438			if s.Diag.Memtag_heap == nil {
439				s.Diag.Memtag_heap = proptools.BoolPtr(true)
440			}
441		} else if ctx.Config().MemtagHeapAsyncEnabledForPath(ctx.ModuleDir()) {
442			if s.Memtag_heap == nil {
443				s.Memtag_heap = proptools.BoolPtr(true)
444			}
445		}
446	}
447
448	// Enable CFI for non-host components in the include paths
449	if s.Cfi == nil && ctx.Config().CFIEnabledForPath(ctx.ModuleDir()) && !ctx.Host() {
450		s.Cfi = proptools.BoolPtr(true)
451		if inList("cfi", ctx.Config().SanitizeDeviceDiag()) {
452			s.Diag.Cfi = proptools.BoolPtr(true)
453		}
454	}
455
456	// Is CFI actually enabled?
457	if !ctx.Config().EnableCFI() {
458		s.Cfi = nil
459		s.Diag.Cfi = nil
460	}
461
462	// HWASan requires AArch64 hardware feature (top-byte-ignore).
463	if ctx.Arch().ArchType != android.Arm64 {
464		s.Hwaddress = nil
465	}
466
467	// SCS is only implemented on AArch64.
468	if ctx.Arch().ArchType != android.Arm64 {
469		s.Scs = nil
470	}
471
472	// Memtag_heap is only implemented on AArch64.
473	if ctx.Arch().ArchType != android.Arm64 {
474		s.Memtag_heap = nil
475	}
476
477	// Also disable CFI if ASAN is enabled.
478	if Bool(s.Address) || Bool(s.Hwaddress) {
479		s.Cfi = nil
480		s.Diag.Cfi = nil
481	}
482
483	// Disable sanitizers that depend on the UBSan runtime for windows/darwin builds.
484	if !ctx.Os().Linux() {
485		s.Cfi = nil
486		s.Diag.Cfi = nil
487		s.Misc_undefined = nil
488		s.Undefined = nil
489		s.All_undefined = nil
490		s.Integer_overflow = nil
491	}
492
493	// Disable CFI for musl
494	if ctx.toolchain().Musl() {
495		s.Cfi = nil
496		s.Diag.Cfi = nil
497	}
498
499	// Also disable CFI for VNDK variants of components
500	if ctx.isVndk() && ctx.useVndk() {
501		if ctx.static() {
502			// Cfi variant for static vndk should be captured as vendor snapshot,
503			// so don't strictly disable Cfi.
504			s.Cfi = nil
505			s.Diag.Cfi = nil
506		} else {
507			s.Cfi = nil
508			s.Diag.Cfi = nil
509		}
510	}
511
512	// HWASan ramdisk (which is built from recovery) goes over some bootloader limit.
513	// Keep libc instrumented so that ramdisk / vendor_ramdisk / recovery can run hwasan-instrumented code if necessary.
514	if (ctx.inRamdisk() || ctx.inVendorRamdisk() || ctx.inRecovery()) && !strings.HasPrefix(ctx.ModuleDir(), "bionic/libc") {
515		s.Hwaddress = nil
516	}
517
518	if ctx.staticBinary() {
519		s.Address = nil
520		s.Fuzzer = nil
521		s.Thread = nil
522	}
523
524	if Bool(s.All_undefined) {
525		s.Undefined = nil
526	}
527
528	if !ctx.toolchain().Is64Bit() {
529		// TSAN and SafeStack are not supported on 32-bit architectures
530		s.Thread = nil
531		s.Safestack = nil
532		// TODO(ccross): error for compile_multilib = "32"?
533	}
534
535	if ctx.Os() != android.Windows && (Bool(s.All_undefined) || Bool(s.Undefined) || Bool(s.Address) || Bool(s.Thread) ||
536		Bool(s.Fuzzer) || Bool(s.Safestack) || Bool(s.Cfi) || Bool(s.Integer_overflow) || len(s.Misc_undefined) > 0 ||
537		Bool(s.Scudo) || Bool(s.Hwaddress) || Bool(s.Scs) || Bool(s.Memtag_heap)) {
538		sanitize.Properties.SanitizerEnabled = true
539	}
540
541	// Disable Scudo if ASan or TSan is enabled, or if it's disabled globally.
542	if Bool(s.Address) || Bool(s.Thread) || Bool(s.Hwaddress) || ctx.Config().DisableScudo() {
543		s.Scudo = nil
544	}
545
546	if Bool(s.Hwaddress) {
547		s.Address = nil
548		s.Thread = nil
549	}
550
551	// TODO(b/131771163): CFI transiently depends on LTO, and thus Fuzzer is
552	// mutually incompatible.
553	if Bool(s.Fuzzer) {
554		s.Cfi = nil
555	}
556}
557
558func toDisableImplicitIntegerChange(flags []string) bool {
559	// Returns true if any flag is fsanitize*integer, and there is
560	// no explicit flag about sanitize=implicit-integer-sign-change.
561	for _, f := range flags {
562		if strings.Contains(f, "sanitize=implicit-integer-sign-change") {
563			return false
564		}
565	}
566	for _, f := range flags {
567		if strings.HasPrefix(f, "-fsanitize") && strings.Contains(f, "integer") {
568			return true
569		}
570	}
571	return false
572}
573
574func toDisableUnsignedShiftBaseChange(flags []string) bool {
575	// Returns true if any flag is fsanitize*integer, and there is
576	// no explicit flag about sanitize=unsigned-shift-base.
577	for _, f := range flags {
578		if strings.Contains(f, "sanitize=unsigned-shift-base") {
579			return false
580		}
581	}
582	for _, f := range flags {
583		if strings.HasPrefix(f, "-fsanitize") && strings.Contains(f, "integer") {
584			return true
585		}
586	}
587	return false
588}
589
590func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags) Flags {
591	minimalRuntimeLib := config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(ctx.toolchain()) + ".a"
592
593	if sanitize.Properties.MinimalRuntimeDep {
594		flags.Local.LdFlags = append(flags.Local.LdFlags,
595			"-Wl,--exclude-libs,"+minimalRuntimeLib)
596	}
597
598	if !sanitize.Properties.SanitizerEnabled && !sanitize.Properties.UbsanRuntimeDep {
599		return flags
600	}
601
602	if Bool(sanitize.Properties.Sanitize.Address) {
603		if ctx.Arch().ArchType == android.Arm {
604			// Frame pointer based unwinder in ASan requires ARM frame setup.
605			// TODO: put in flags?
606			flags.RequiredInstructionSet = "arm"
607		}
608		flags.Local.CFlags = append(flags.Local.CFlags, asanCflags...)
609		flags.Local.LdFlags = append(flags.Local.LdFlags, asanLdflags...)
610
611		if Bool(sanitize.Properties.Sanitize.Writeonly) {
612			flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", "-asan-instrument-reads=0")
613		}
614
615		if ctx.Host() {
616			// -nodefaultlibs (provided with libc++) prevents the driver from linking
617			// libraries needed with -fsanitize=address. http://b/18650275 (WAI)
618			flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--no-as-needed")
619		} else {
620			flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", "-asan-globals=0")
621			if ctx.bootstrap() {
622				flags.DynamicLinker = "/system/bin/bootstrap/linker_asan"
623			} else {
624				flags.DynamicLinker = "/system/bin/linker_asan"
625			}
626			if flags.Toolchain.Is64Bit() {
627				flags.DynamicLinker += "64"
628			}
629		}
630	}
631
632	if Bool(sanitize.Properties.Sanitize.Hwaddress) {
633		flags.Local.CFlags = append(flags.Local.CFlags, hwasanCflags...)
634
635		for _, flag := range hwasanCommonflags {
636			flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", flag)
637		}
638		for _, flag := range hwasanCommonflags {
639			flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-mllvm,"+flag)
640		}
641
642		if Bool(sanitize.Properties.Sanitize.Writeonly) {
643			flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", "-hwasan-instrument-reads=0")
644		}
645	}
646
647	if Bool(sanitize.Properties.Sanitize.Fuzzer) {
648		flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize=fuzzer-no-link")
649
650		// TODO(b/131771163): LTO and Fuzzer support is mutually incompatible.
651		_, flags.Local.LdFlags = removeFromList("-flto", flags.Local.LdFlags)
652		_, flags.Local.CFlags = removeFromList("-flto", flags.Local.CFlags)
653		flags.Local.LdFlags = append(flags.Local.LdFlags, "-fno-lto")
654		flags.Local.CFlags = append(flags.Local.CFlags, "-fno-lto")
655
656		// TODO(b/142430592): Upstream linker scripts for sanitizer runtime libraries
657		// discard the sancov_lowest_stack symbol, because it's emulated TLS (and thus
658		// doesn't match the linker script due to the "__emutls_v." prefix).
659		flags.Local.LdFlags = append(flags.Local.LdFlags, "-fno-sanitize-coverage=stack-depth")
660		flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-coverage=stack-depth")
661
662		// Disable fortify for fuzzing builds. Generally, we'll be building with
663		// UBSan or ASan here and the fortify checks pollute the stack traces.
664		flags.Local.CFlags = append(flags.Local.CFlags, "-U_FORTIFY_SOURCE")
665
666		// Build fuzzer-sanitized libraries with an $ORIGIN DT_RUNPATH. Android's
667		// linker uses DT_RUNPATH, not DT_RPATH. When we deploy cc_fuzz targets and
668		// their libraries to /data/fuzz/<arch>/lib, any transient shared library gets
669		// the DT_RUNPATH from the shared library above it, and not the executable,
670		// meaning that the lookup falls back to the system. Adding the $ORIGIN to the
671		// DT_RUNPATH here means that transient shared libraries can be found
672		// colocated with their parents.
673		flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN`)
674	}
675
676	if Bool(sanitize.Properties.Sanitize.Cfi) {
677		if ctx.Arch().ArchType == android.Arm {
678			// __cfi_check needs to be built as Thumb (see the code in linker_cfi.cpp). LLVM is not set up
679			// to do this on a function basis, so force Thumb on the entire module.
680			flags.RequiredInstructionSet = "thumb"
681		}
682
683		flags.Local.CFlags = append(flags.Local.CFlags, cfiCflags...)
684		flags.Local.AsFlags = append(flags.Local.AsFlags, cfiAsflags...)
685		if Bool(sanitize.Properties.Sanitize.Config.Cfi_assembly_support) {
686			flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-cfi-canonical-jump-tables")
687		}
688		// Only append the default visibility flag if -fvisibility has not already been set
689		// to hidden.
690		if !inList("-fvisibility=hidden", flags.Local.CFlags) {
691			flags.Local.CFlags = append(flags.Local.CFlags, "-fvisibility=default")
692		}
693		flags.Local.LdFlags = append(flags.Local.LdFlags, cfiLdflags...)
694
695		if ctx.staticBinary() {
696			_, flags.Local.CFlags = removeFromList("-fsanitize-cfi-cross-dso", flags.Local.CFlags)
697			_, flags.Local.LdFlags = removeFromList("-fsanitize-cfi-cross-dso", flags.Local.LdFlags)
698		}
699	}
700
701	if Bool(sanitize.Properties.Sanitize.Integer_overflow) {
702		flags.Local.CFlags = append(flags.Local.CFlags, intOverflowCflags...)
703	}
704
705	if len(sanitize.Properties.Sanitizers) > 0 {
706		sanitizeArg := "-fsanitize=" + strings.Join(sanitize.Properties.Sanitizers, ",")
707		flags.Local.CFlags = append(flags.Local.CFlags, sanitizeArg)
708		flags.Local.AsFlags = append(flags.Local.AsFlags, sanitizeArg)
709		flags.Local.LdFlags = append(flags.Local.LdFlags, sanitizeArg)
710
711		if ctx.toolchain().Bionic() || ctx.toolchain().Musl() {
712			// Bionic and musl sanitizer runtimes have already been added as dependencies so that
713			// the right variant of the runtime will be used (with the "-android" or "-musl"
714			// suffixes), so don't let clang the runtime library.
715			flags.Local.LdFlags = append(flags.Local.LdFlags, "-fno-sanitize-link-runtime")
716		} else {
717			// Host sanitizers only link symbols in the final executable, so
718			// there will always be undefined symbols in intermediate libraries.
719			_, flags.Global.LdFlags = removeFromList("-Wl,--no-undefined", flags.Global.LdFlags)
720
721			// non-Bionic toolchain prebuilts are missing UBSan's vptr and function san
722			flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize=vptr,function")
723		}
724
725		if enableMinimalRuntime(sanitize) {
726			flags.Local.CFlags = append(flags.Local.CFlags, strings.Join(minimalRuntimeFlags, " "))
727			flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--exclude-libs,"+minimalRuntimeLib)
728		}
729
730		if Bool(sanitize.Properties.Sanitize.Fuzzer) {
731			// When fuzzing, we wish to crash with diagnostics on any bug.
732			flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-trap=all", "-fno-sanitize-recover=all")
733		} else if ctx.Host() {
734			flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-recover=all")
735		} else {
736			flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize-trap=all", "-ftrap-function=abort")
737		}
738		// http://b/119329758, Android core does not boot up with this sanitizer yet.
739		if toDisableImplicitIntegerChange(flags.Local.CFlags) {
740			flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize=implicit-integer-sign-change")
741		}
742		// http://b/171275751, Android doesn't build with this sanitizer yet.
743		if toDisableUnsignedShiftBaseChange(flags.Local.CFlags) {
744			flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize=unsigned-shift-base")
745		}
746	}
747
748	if len(sanitize.Properties.DiagSanitizers) > 0 {
749		flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-trap="+strings.Join(sanitize.Properties.DiagSanitizers, ","))
750	}
751	// FIXME: enable RTTI if diag + (cfi or vptr)
752
753	if sanitize.Properties.Sanitize.Recover != nil {
754		flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize-recover="+
755			strings.Join(sanitize.Properties.Sanitize.Recover, ","))
756	}
757
758	if sanitize.Properties.Sanitize.Diag.No_recover != nil {
759		flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-recover="+
760			strings.Join(sanitize.Properties.Sanitize.Diag.No_recover, ","))
761	}
762
763	blocklist := android.OptionalPathForModuleSrc(ctx, sanitize.Properties.Sanitize.Blocklist)
764	if blocklist.Valid() {
765		flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize-ignorelist="+blocklist.String())
766		flags.CFlagsDeps = append(flags.CFlagsDeps, blocklist.Path())
767	}
768
769	return flags
770}
771
772func (sanitize *sanitize) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
773	// Add a suffix for cfi/hwasan/scs-enabled static/header libraries to allow surfacing
774	// both the sanitized and non-sanitized variants to make without a name conflict.
775	if entries.Class == "STATIC_LIBRARIES" || entries.Class == "HEADER_LIBRARIES" {
776		if Bool(sanitize.Properties.Sanitize.Cfi) {
777			entries.SubName += ".cfi"
778		}
779		if Bool(sanitize.Properties.Sanitize.Hwaddress) {
780			entries.SubName += ".hwasan"
781		}
782		if Bool(sanitize.Properties.Sanitize.Scs) {
783			entries.SubName += ".scs"
784		}
785	}
786}
787
788func (sanitize *sanitize) inSanitizerDir() bool {
789	return sanitize.Properties.InSanitizerDir
790}
791
792// getSanitizerBoolPtr returns the SanitizerTypes associated bool pointer from SanitizeProperties.
793func (sanitize *sanitize) getSanitizerBoolPtr(t SanitizerType) *bool {
794	switch t {
795	case Asan:
796		return sanitize.Properties.Sanitize.Address
797	case Hwasan:
798		return sanitize.Properties.Sanitize.Hwaddress
799	case tsan:
800		return sanitize.Properties.Sanitize.Thread
801	case intOverflow:
802		return sanitize.Properties.Sanitize.Integer_overflow
803	case cfi:
804		return sanitize.Properties.Sanitize.Cfi
805	case scs:
806		return sanitize.Properties.Sanitize.Scs
807	case Memtag_heap:
808		return sanitize.Properties.Sanitize.Memtag_heap
809	case Fuzzer:
810		return sanitize.Properties.Sanitize.Fuzzer
811	default:
812		panic(fmt.Errorf("unknown SanitizerType %d", t))
813	}
814}
815
816// isUnsanitizedVariant returns true if no sanitizers are enabled.
817func (sanitize *sanitize) isUnsanitizedVariant() bool {
818	return !sanitize.isSanitizerEnabled(Asan) &&
819		!sanitize.isSanitizerEnabled(Hwasan) &&
820		!sanitize.isSanitizerEnabled(tsan) &&
821		!sanitize.isSanitizerEnabled(cfi) &&
822		!sanitize.isSanitizerEnabled(scs) &&
823		!sanitize.isSanitizerEnabled(Memtag_heap) &&
824		!sanitize.isSanitizerEnabled(Fuzzer)
825}
826
827// isVariantOnProductionDevice returns true if variant is for production devices (no non-production sanitizers enabled).
828func (sanitize *sanitize) isVariantOnProductionDevice() bool {
829	return !sanitize.isSanitizerEnabled(Asan) &&
830		!sanitize.isSanitizerEnabled(Hwasan) &&
831		!sanitize.isSanitizerEnabled(tsan) &&
832		!sanitize.isSanitizerEnabled(Fuzzer)
833}
834
835func (sanitize *sanitize) SetSanitizer(t SanitizerType, b bool) {
836	bPtr := proptools.BoolPtr(b)
837	if !b {
838		bPtr = nil
839	}
840	switch t {
841	case Asan:
842		sanitize.Properties.Sanitize.Address = bPtr
843	case Hwasan:
844		sanitize.Properties.Sanitize.Hwaddress = bPtr
845	case tsan:
846		sanitize.Properties.Sanitize.Thread = bPtr
847	case intOverflow:
848		sanitize.Properties.Sanitize.Integer_overflow = bPtr
849	case cfi:
850		sanitize.Properties.Sanitize.Cfi = bPtr
851	case scs:
852		sanitize.Properties.Sanitize.Scs = bPtr
853	case Memtag_heap:
854		sanitize.Properties.Sanitize.Memtag_heap = bPtr
855	case Fuzzer:
856		sanitize.Properties.Sanitize.Fuzzer = bPtr
857	default:
858		panic(fmt.Errorf("unknown SanitizerType %d", t))
859	}
860	if b {
861		sanitize.Properties.SanitizerEnabled = true
862	}
863}
864
865// Check if the sanitizer is explicitly disabled (as opposed to nil by
866// virtue of not being set).
867func (sanitize *sanitize) isSanitizerExplicitlyDisabled(t SanitizerType) bool {
868	if sanitize == nil {
869		return false
870	}
871
872	sanitizerVal := sanitize.getSanitizerBoolPtr(t)
873	return sanitizerVal != nil && *sanitizerVal == false
874}
875
876// There isn't an analog of the method above (ie:isSanitizerExplicitlyEnabled)
877// because enabling a sanitizer either directly (via the blueprint) or
878// indirectly (via a mutator) sets the bool ptr to true, and you can't
879// distinguish between the cases. It isn't needed though - both cases can be
880// treated identically.
881func (sanitize *sanitize) isSanitizerEnabled(t SanitizerType) bool {
882	if sanitize == nil {
883		return false
884	}
885
886	sanitizerVal := sanitize.getSanitizerBoolPtr(t)
887	return sanitizerVal != nil && *sanitizerVal == true
888}
889
890// IsSanitizableDependencyTag returns true if the dependency tag is sanitizable.
891func IsSanitizableDependencyTag(tag blueprint.DependencyTag) bool {
892	switch t := tag.(type) {
893	case dependencyTag:
894		return t == reuseObjTag || t == objDepTag
895	case libraryDependencyTag:
896		return true
897	default:
898		return false
899	}
900}
901
902func (m *Module) SanitizableDepTagChecker() SantizableDependencyTagChecker {
903	return IsSanitizableDependencyTag
904}
905
906// Determines if the current module is a static library going to be captured
907// as vendor snapshot. Such modules must create both cfi and non-cfi variants,
908// except for ones which explicitly disable cfi.
909func needsCfiForVendorSnapshot(mctx android.TopDownMutatorContext) bool {
910	if snapshot.IsVendorProprietaryModule(mctx) {
911		return false
912	}
913
914	c := mctx.Module().(PlatformSanitizeable)
915
916	if !c.InVendor() {
917		return false
918	}
919
920	if !c.StaticallyLinked() {
921		return false
922	}
923
924	if c.IsPrebuilt() {
925		return false
926	}
927
928	if !c.SanitizerSupported(cfi) {
929		return false
930	}
931
932	return c.SanitizePropDefined() &&
933		!c.SanitizeNever() &&
934		!c.IsSanitizerExplicitlyDisabled(cfi)
935}
936
937// Propagate sanitizer requirements down from binaries
938func sanitizerDepsMutator(t SanitizerType) func(android.TopDownMutatorContext) {
939	return func(mctx android.TopDownMutatorContext) {
940		if c, ok := mctx.Module().(PlatformSanitizeable); ok {
941			enabled := c.IsSanitizerEnabled(t)
942			if t == cfi && needsCfiForVendorSnapshot(mctx) {
943				// We shouldn't change the result of isSanitizerEnabled(cfi) to correctly
944				// determine defaultVariation in sanitizerMutator below.
945				// Instead, just mark SanitizeDep to forcefully create cfi variant.
946				enabled = true
947				c.SetSanitizeDep(true)
948			}
949			if enabled {
950				isSanitizableDependencyTag := c.SanitizableDepTagChecker()
951				mctx.WalkDeps(func(child, parent android.Module) bool {
952					if !isSanitizableDependencyTag(mctx.OtherModuleDependencyTag(child)) {
953						return false
954					}
955					if d, ok := child.(PlatformSanitizeable); ok && d.SanitizePropDefined() &&
956						!d.SanitizeNever() &&
957						!d.IsSanitizerExplicitlyDisabled(t) {
958						if t == cfi || t == Hwasan || t == scs || t == Asan {
959							if d.StaticallyLinked() && d.SanitizerSupported(t) {
960								// Rust does not support some of these sanitizers, so we need to check if it's
961								// supported before setting this true.
962								d.SetSanitizeDep(true)
963							}
964						} else {
965							d.SetSanitizeDep(true)
966						}
967					}
968					return true
969				})
970			}
971		} else if sanitizeable, ok := mctx.Module().(Sanitizeable); ok {
972			// If an APEX module includes a lib which is enabled for a sanitizer T, then
973			// the APEX module is also enabled for the same sanitizer type.
974			mctx.VisitDirectDeps(func(child android.Module) {
975				if c, ok := child.(*Module); ok && c.sanitize.isSanitizerEnabled(t) {
976					sanitizeable.EnableSanitizer(t.name())
977				}
978			})
979		}
980	}
981}
982
983func (c *Module) SanitizeNever() bool {
984	return Bool(c.sanitize.Properties.Sanitize.Never)
985}
986
987func (c *Module) IsSanitizerExplicitlyDisabled(t SanitizerType) bool {
988	return c.sanitize.isSanitizerExplicitlyDisabled(t)
989}
990
991// Propagate the ubsan minimal runtime dependency when there are integer overflow sanitized static dependencies.
992func sanitizerRuntimeDepsMutator(mctx android.TopDownMutatorContext) {
993	// Change this to PlatformSanitizable when/if non-cc modules support ubsan sanitizers.
994	if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil {
995		isSanitizableDependencyTag := c.SanitizableDepTagChecker()
996		mctx.WalkDeps(func(child, parent android.Module) bool {
997			if !isSanitizableDependencyTag(mctx.OtherModuleDependencyTag(child)) {
998				return false
999			}
1000
1001			d, ok := child.(*Module)
1002			if !ok || !d.static() {
1003				return false
1004			}
1005			if d.sanitize != nil {
1006				if enableMinimalRuntime(d.sanitize) {
1007					// If a static dependency is built with the minimal runtime,
1008					// make sure we include the ubsan minimal runtime.
1009					c.sanitize.Properties.MinimalRuntimeDep = true
1010				} else if enableUbsanRuntime(d.sanitize) {
1011					// If a static dependency runs with full ubsan diagnostics,
1012					// make sure we include the ubsan runtime.
1013					c.sanitize.Properties.UbsanRuntimeDep = true
1014				}
1015
1016				if c.sanitize.Properties.MinimalRuntimeDep &&
1017					c.sanitize.Properties.UbsanRuntimeDep {
1018					// both flags that this mutator might set are true, so don't bother recursing
1019					return false
1020				}
1021
1022				if c.Os() == android.Linux {
1023					c.sanitize.Properties.BuiltinsDep = true
1024				}
1025
1026				return true
1027			}
1028
1029			if p, ok := d.linker.(*snapshotLibraryDecorator); ok {
1030				if Bool(p.properties.Sanitize_minimal_dep) {
1031					c.sanitize.Properties.MinimalRuntimeDep = true
1032				}
1033				if Bool(p.properties.Sanitize_ubsan_dep) {
1034					c.sanitize.Properties.UbsanRuntimeDep = true
1035				}
1036			}
1037
1038			return false
1039		})
1040	}
1041}
1042
1043// Add the dependency to the runtime library for each of the sanitizer variants
1044func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) {
1045	if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil {
1046		if !c.Enabled() {
1047			return
1048		}
1049		var sanitizers []string
1050		var diagSanitizers []string
1051
1052		if Bool(c.sanitize.Properties.Sanitize.All_undefined) {
1053			sanitizers = append(sanitizers, "undefined")
1054		} else {
1055			if Bool(c.sanitize.Properties.Sanitize.Undefined) {
1056				sanitizers = append(sanitizers,
1057					"bool",
1058					"integer-divide-by-zero",
1059					"return",
1060					"returns-nonnull-attribute",
1061					"shift-exponent",
1062					"unreachable",
1063					"vla-bound",
1064					// TODO(danalbert): The following checks currently have compiler performance issues.
1065					//"alignment",
1066					//"bounds",
1067					//"enum",
1068					//"float-cast-overflow",
1069					//"float-divide-by-zero",
1070					//"nonnull-attribute",
1071					//"null",
1072					//"shift-base",
1073					//"signed-integer-overflow",
1074					// TODO(danalbert): Fix UB in libc++'s __tree so we can turn this on.
1075					// https://llvm.org/PR19302
1076					// http://reviews.llvm.org/D6974
1077					// "object-size",
1078				)
1079			}
1080			sanitizers = append(sanitizers, c.sanitize.Properties.Sanitize.Misc_undefined...)
1081		}
1082
1083		if Bool(c.sanitize.Properties.Sanitize.Diag.Undefined) {
1084			diagSanitizers = append(diagSanitizers, "undefined")
1085		}
1086
1087		diagSanitizers = append(diagSanitizers, c.sanitize.Properties.Sanitize.Diag.Misc_undefined...)
1088
1089		if Bool(c.sanitize.Properties.Sanitize.Address) {
1090			sanitizers = append(sanitizers, "address")
1091			diagSanitizers = append(diagSanitizers, "address")
1092		}
1093
1094		if Bool(c.sanitize.Properties.Sanitize.Hwaddress) {
1095			sanitizers = append(sanitizers, "hwaddress")
1096		}
1097
1098		if Bool(c.sanitize.Properties.Sanitize.Thread) {
1099			sanitizers = append(sanitizers, "thread")
1100		}
1101
1102		if Bool(c.sanitize.Properties.Sanitize.Safestack) {
1103			sanitizers = append(sanitizers, "safe-stack")
1104		}
1105
1106		if Bool(c.sanitize.Properties.Sanitize.Cfi) {
1107			sanitizers = append(sanitizers, "cfi")
1108
1109			if Bool(c.sanitize.Properties.Sanitize.Diag.Cfi) {
1110				diagSanitizers = append(diagSanitizers, "cfi")
1111			}
1112		}
1113
1114		if Bool(c.sanitize.Properties.Sanitize.Integer_overflow) {
1115			sanitizers = append(sanitizers, "unsigned-integer-overflow")
1116			sanitizers = append(sanitizers, "signed-integer-overflow")
1117			if Bool(c.sanitize.Properties.Sanitize.Diag.Integer_overflow) {
1118				diagSanitizers = append(diagSanitizers, "unsigned-integer-overflow")
1119				diagSanitizers = append(diagSanitizers, "signed-integer-overflow")
1120			}
1121		}
1122
1123		if Bool(c.sanitize.Properties.Sanitize.Scudo) {
1124			sanitizers = append(sanitizers, "scudo")
1125		}
1126
1127		if Bool(c.sanitize.Properties.Sanitize.Scs) {
1128			sanitizers = append(sanitizers, "shadow-call-stack")
1129		}
1130
1131		if Bool(c.sanitize.Properties.Sanitize.Memtag_heap) && c.Binary() {
1132			noteDep := "note_memtag_heap_async"
1133			if Bool(c.sanitize.Properties.Sanitize.Diag.Memtag_heap) {
1134				noteDep = "note_memtag_heap_sync"
1135			}
1136			// If we're using snapshots, redirect to snapshot whenever possible
1137			// TODO(b/178470649): clean manual snapshot redirections
1138			snapshot := mctx.Provider(SnapshotInfoProvider).(SnapshotInfo)
1139			if lib, ok := snapshot.StaticLibs[noteDep]; ok {
1140				noteDep = lib
1141			}
1142			depTag := StaticDepTag(true)
1143			variations := append(mctx.Target().Variations(),
1144				blueprint.Variation{Mutator: "link", Variation: "static"})
1145			if c.Device() {
1146				variations = append(variations, c.ImageVariation())
1147			}
1148			mctx.AddFarVariationDependencies(variations, depTag, noteDep)
1149		}
1150
1151		if Bool(c.sanitize.Properties.Sanitize.Fuzzer) {
1152			sanitizers = append(sanitizers, "fuzzer-no-link")
1153		}
1154
1155		// Save the list of sanitizers. These will be used again when generating
1156		// the build rules (for Cflags, etc.)
1157		c.sanitize.Properties.Sanitizers = sanitizers
1158		c.sanitize.Properties.DiagSanitizers = diagSanitizers
1159
1160		// TODO(b/150822854) Hosts have a different default behavior and assume the runtime library is used.
1161		if c.Host() {
1162			diagSanitizers = sanitizers
1163		}
1164
1165		// Determine the runtime library required
1166		runtimeLibrary := ""
1167		var extraStaticDeps []string
1168		toolchain := c.toolchain(mctx)
1169		if Bool(c.sanitize.Properties.Sanitize.Address) {
1170			runtimeLibrary = config.AddressSanitizerRuntimeLibrary(toolchain)
1171		} else if Bool(c.sanitize.Properties.Sanitize.Hwaddress) {
1172			if c.staticBinary() {
1173				runtimeLibrary = config.HWAddressSanitizerStaticLibrary(toolchain)
1174				extraStaticDeps = []string{"libdl"}
1175			} else {
1176				runtimeLibrary = config.HWAddressSanitizerRuntimeLibrary(toolchain)
1177			}
1178		} else if Bool(c.sanitize.Properties.Sanitize.Thread) {
1179			runtimeLibrary = config.ThreadSanitizerRuntimeLibrary(toolchain)
1180		} else if Bool(c.sanitize.Properties.Sanitize.Scudo) {
1181			if len(diagSanitizers) == 0 && !c.sanitize.Properties.UbsanRuntimeDep {
1182				runtimeLibrary = config.ScudoMinimalRuntimeLibrary(toolchain)
1183			} else {
1184				runtimeLibrary = config.ScudoRuntimeLibrary(toolchain)
1185			}
1186		} else if len(diagSanitizers) > 0 || c.sanitize.Properties.UbsanRuntimeDep ||
1187			Bool(c.sanitize.Properties.Sanitize.Fuzzer) ||
1188			Bool(c.sanitize.Properties.Sanitize.Undefined) ||
1189			Bool(c.sanitize.Properties.Sanitize.All_undefined) {
1190			runtimeLibrary = config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain)
1191			if c.staticBinary() {
1192				runtimeLibrary += ".static"
1193			}
1194		}
1195
1196		addStaticDeps := func(deps ...string) {
1197			// If we're using snapshots, redirect to snapshot whenever possible
1198			snapshot := mctx.Provider(SnapshotInfoProvider).(SnapshotInfo)
1199			for idx, dep := range deps {
1200				if lib, ok := snapshot.StaticLibs[dep]; ok {
1201					deps[idx] = lib
1202				}
1203			}
1204
1205			// static executable gets static runtime libs
1206			depTag := libraryDependencyTag{Kind: staticLibraryDependency}
1207			variations := append(mctx.Target().Variations(),
1208				blueprint.Variation{Mutator: "link", Variation: "static"})
1209			if c.Device() {
1210				variations = append(variations, c.ImageVariation())
1211			}
1212			if c.UseSdk() {
1213				variations = append(variations,
1214					blueprint.Variation{Mutator: "sdk", Variation: "sdk"})
1215			}
1216			mctx.AddFarVariationDependencies(variations, depTag, deps...)
1217
1218		}
1219		if enableMinimalRuntime(c.sanitize) || c.sanitize.Properties.MinimalRuntimeDep {
1220			addStaticDeps(config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(toolchain))
1221		}
1222		if c.sanitize.Properties.BuiltinsDep {
1223			addStaticDeps(config.BuiltinsRuntimeLibrary(toolchain))
1224		}
1225
1226		if runtimeLibrary != "" && (toolchain.Bionic() || toolchain.Musl() || c.sanitize.Properties.UbsanRuntimeDep) {
1227			// UBSan is supported on non-bionic linux host builds as well
1228
1229			// Adding dependency to the runtime library. We are using *FarVariation*
1230			// because the runtime libraries themselves are not mutated by sanitizer
1231			// mutators and thus don't have sanitizer variants whereas this module
1232			// has been already mutated.
1233			//
1234			// Note that by adding dependency with {static|shared}DepTag, the lib is
1235			// added to libFlags and LOCAL_SHARED_LIBRARIES by cc.Module
1236			if c.staticBinary() {
1237				addStaticDeps(runtimeLibrary)
1238				addStaticDeps(extraStaticDeps...)
1239			} else if !c.static() && !c.Header() {
1240				// If we're using snapshots, redirect to snapshot whenever possible
1241				snapshot := mctx.Provider(SnapshotInfoProvider).(SnapshotInfo)
1242				if lib, ok := snapshot.SharedLibs[runtimeLibrary]; ok {
1243					runtimeLibrary = lib
1244				}
1245
1246				// Skip apex dependency check for sharedLibraryDependency
1247				// when sanitizer diags are enabled. Skipping the check will allow
1248				// building with diag libraries without having to list the
1249				// dependency in Apex's allowed_deps file.
1250				diagEnabled := len(diagSanitizers) > 0
1251				// dynamic executable and shared libs get shared runtime libs
1252				depTag := libraryDependencyTag{
1253					Kind:  sharedLibraryDependency,
1254					Order: earlyLibraryDependency,
1255
1256					skipApexAllowedDependenciesCheck: diagEnabled,
1257				}
1258				variations := append(mctx.Target().Variations(),
1259					blueprint.Variation{Mutator: "link", Variation: "shared"})
1260				if c.Device() {
1261					variations = append(variations, c.ImageVariation())
1262				}
1263				if c.UseSdk() {
1264					variations = append(variations,
1265						blueprint.Variation{Mutator: "sdk", Variation: "sdk"})
1266				}
1267				AddSharedLibDependenciesWithVersions(mctx, c, variations, depTag, runtimeLibrary, "", true)
1268			}
1269			// static lib does not have dependency to the runtime library. The
1270			// dependency will be added to the executables or shared libs using
1271			// the static lib.
1272		}
1273	}
1274}
1275
1276type Sanitizeable interface {
1277	android.Module
1278	IsSanitizerEnabled(ctx android.BaseModuleContext, sanitizerName string) bool
1279	EnableSanitizer(sanitizerName string)
1280	AddSanitizerDependencies(ctx android.BottomUpMutatorContext, sanitizerName string)
1281}
1282
1283func (c *Module) MinimalRuntimeDep() bool {
1284	return c.sanitize.Properties.MinimalRuntimeDep
1285}
1286
1287func (c *Module) UbsanRuntimeDep() bool {
1288	return c.sanitize.Properties.UbsanRuntimeDep
1289}
1290
1291func (c *Module) SanitizePropDefined() bool {
1292	return c.sanitize != nil
1293}
1294
1295func (c *Module) IsSanitizerEnabled(t SanitizerType) bool {
1296	return c.sanitize.isSanitizerEnabled(t)
1297}
1298
1299func (c *Module) SanitizeDep() bool {
1300	return c.sanitize.Properties.SanitizeDep
1301}
1302
1303func (c *Module) StaticallyLinked() bool {
1304	return c.static()
1305}
1306
1307func (c *Module) SetInSanitizerDir() {
1308	if c.sanitize != nil {
1309		c.sanitize.Properties.InSanitizerDir = true
1310	}
1311}
1312
1313func (c *Module) SetSanitizer(t SanitizerType, b bool) {
1314	if c.sanitize != nil {
1315		c.sanitize.SetSanitizer(t, b)
1316	}
1317}
1318
1319func (c *Module) SetSanitizeDep(b bool) {
1320	if c.sanitize != nil {
1321		c.sanitize.Properties.SanitizeDep = b
1322	}
1323}
1324
1325var _ PlatformSanitizeable = (*Module)(nil)
1326
1327// Create sanitized variants for modules that need them
1328func sanitizerMutator(t SanitizerType) func(android.BottomUpMutatorContext) {
1329	return func(mctx android.BottomUpMutatorContext) {
1330		if c, ok := mctx.Module().(PlatformSanitizeable); ok && c.SanitizePropDefined() {
1331
1332			// Make sure we're not setting CFI to any value if it's not supported.
1333			cfiSupported := mctx.Module().(PlatformSanitizeable).SanitizerSupported(cfi)
1334
1335			if c.Binary() && c.IsSanitizerEnabled(t) {
1336				modules := mctx.CreateVariations(t.variationName())
1337				modules[0].(PlatformSanitizeable).SetSanitizer(t, true)
1338			} else if c.IsSanitizerEnabled(t) || c.SanitizeDep() {
1339				isSanitizerEnabled := c.IsSanitizerEnabled(t)
1340				if c.StaticallyLinked() || c.Header() || t == Fuzzer {
1341					// Static and header libs are split into non-sanitized and sanitized variants.
1342					// Shared libs are not split. However, for asan and fuzzer, we split even for shared
1343					// libs because a library sanitized for asan/fuzzer can't be linked from a library
1344					// that isn't sanitized for asan/fuzzer.
1345					//
1346					// Note for defaultVariation: since we don't split for shared libs but for static/header
1347					// libs, it is possible for the sanitized variant of a static/header lib to depend
1348					// on non-sanitized variant of a shared lib. Such unfulfilled variation causes an
1349					// error when the module is split. defaultVariation is the name of the variation that
1350					// will be used when such a dangling dependency occurs during the split of the current
1351					// module. By setting it to the name of the sanitized variation, the dangling dependency
1352					// is redirected to the sanitized variant of the dependent module.
1353					defaultVariation := t.variationName()
1354					// Not all PlatformSanitizeable modules support the CFI sanitizer
1355					mctx.SetDefaultDependencyVariation(&defaultVariation)
1356
1357					modules := mctx.CreateVariations("", t.variationName())
1358					modules[0].(PlatformSanitizeable).SetSanitizer(t, false)
1359					modules[1].(PlatformSanitizeable).SetSanitizer(t, true)
1360					modules[0].(PlatformSanitizeable).SetSanitizeDep(false)
1361					modules[1].(PlatformSanitizeable).SetSanitizeDep(false)
1362
1363					if mctx.Device() && t.incompatibleWithCfi() && cfiSupported {
1364						// TODO: Make sure that cfi mutator runs "after" any of the sanitizers that
1365						// are incompatible with cfi
1366						modules[1].(PlatformSanitizeable).SetSanitizer(cfi, false)
1367					}
1368
1369					// For cfi/scs/hwasan, we can export both sanitized and un-sanitized variants
1370					// to Make, because the sanitized version has a different suffix in name.
1371					// For other types of sanitizers, suppress the variation that is disabled.
1372					if t != cfi && t != scs && t != Hwasan {
1373						if isSanitizerEnabled {
1374							modules[0].(PlatformSanitizeable).SetPreventInstall()
1375							modules[0].(PlatformSanitizeable).SetHideFromMake()
1376						} else {
1377							modules[1].(PlatformSanitizeable).SetPreventInstall()
1378							modules[1].(PlatformSanitizeable).SetHideFromMake()
1379						}
1380					}
1381
1382					// Export the static lib name to make
1383					if c.StaticallyLinked() && c.ExportedToMake() {
1384						if t == cfi {
1385							cfiStaticLibs(mctx.Config()).add(c, c.Module().Name())
1386						} else if t == Hwasan {
1387							hwasanStaticLibs(mctx.Config()).add(c, c.Module().Name())
1388						}
1389					}
1390				} else {
1391					// Shared libs are not split. Only the sanitized variant is created.
1392					modules := mctx.CreateVariations(t.variationName())
1393					modules[0].(PlatformSanitizeable).SetSanitizer(t, true)
1394					modules[0].(PlatformSanitizeable).SetSanitizeDep(false)
1395
1396					// locate the asan libraries under /data/asan
1397					if mctx.Device() && t == Asan && isSanitizerEnabled {
1398						modules[0].(PlatformSanitizeable).SetInSanitizerDir()
1399					}
1400
1401					if mctx.Device() && t.incompatibleWithCfi() && cfiSupported {
1402						// TODO: Make sure that cfi mutator runs "after" any of the sanitizers that
1403						// are incompatible with cfi
1404						modules[0].(PlatformSanitizeable).SetSanitizer(cfi, false)
1405					}
1406				}
1407			}
1408			c.SetSanitizeDep(false)
1409		} else if sanitizeable, ok := mctx.Module().(Sanitizeable); ok && sanitizeable.IsSanitizerEnabled(mctx, t.name()) {
1410			// APEX modules fall here
1411			sanitizeable.AddSanitizerDependencies(mctx, t.name())
1412			mctx.CreateVariations(t.variationName())
1413		} else if c, ok := mctx.Module().(*Module); ok {
1414			//TODO: When Rust modules have vendor support, enable this path for PlatformSanitizeable
1415
1416			// Check if it's a snapshot module supporting sanitizer
1417			if s, ok := c.linker.(snapshotSanitizer); ok && s.isSanitizerEnabled(t) {
1418				// Set default variation as above.
1419				defaultVariation := t.variationName()
1420				mctx.SetDefaultDependencyVariation(&defaultVariation)
1421				modules := mctx.CreateVariations("", t.variationName())
1422				modules[0].(*Module).linker.(snapshotSanitizer).setSanitizerVariation(t, false)
1423				modules[1].(*Module).linker.(snapshotSanitizer).setSanitizerVariation(t, true)
1424
1425				// Export the static lib name to make
1426				if c.static() && c.ExportedToMake() {
1427					if t == cfi {
1428						// use BaseModuleName which is the name for Make.
1429						cfiStaticLibs(mctx.Config()).add(c, c.BaseModuleName())
1430					}
1431				}
1432			}
1433		}
1434	}
1435}
1436
1437type sanitizerStaticLibsMap struct {
1438	// libsMap contains one list of modules per each image and each arch.
1439	// e.g. libs[vendor]["arm"] contains arm modules installed to vendor
1440	libsMap       map[ImageVariantType]map[string][]string
1441	libsMapLock   sync.Mutex
1442	sanitizerType SanitizerType
1443}
1444
1445func newSanitizerStaticLibsMap(t SanitizerType) *sanitizerStaticLibsMap {
1446	return &sanitizerStaticLibsMap{
1447		sanitizerType: t,
1448		libsMap:       make(map[ImageVariantType]map[string][]string),
1449	}
1450}
1451
1452// Add the current module to sanitizer static libs maps
1453// Each module should pass its exported name as names of Make and Soong can differ.
1454func (s *sanitizerStaticLibsMap) add(c LinkableInterface, name string) {
1455	image := GetImageVariantType(c)
1456	arch := c.Module().Target().Arch.ArchType.String()
1457
1458	s.libsMapLock.Lock()
1459	defer s.libsMapLock.Unlock()
1460
1461	if _, ok := s.libsMap[image]; !ok {
1462		s.libsMap[image] = make(map[string][]string)
1463	}
1464
1465	s.libsMap[image][arch] = append(s.libsMap[image][arch], name)
1466}
1467
1468// Exports makefile variables in the following format:
1469// SOONG_{sanitizer}_{image}_{arch}_STATIC_LIBRARIES
1470// e.g. SOONG_cfi_core_x86_STATIC_LIBRARIES
1471// These are to be used by use_soong_sanitized_static_libraries.
1472// See build/make/core/binary.mk for more details.
1473func (s *sanitizerStaticLibsMap) exportToMake(ctx android.MakeVarsContext) {
1474	for _, image := range android.SortedStringKeys(s.libsMap) {
1475		archMap := s.libsMap[ImageVariantType(image)]
1476		for _, arch := range android.SortedStringKeys(archMap) {
1477			libs := archMap[arch]
1478			sort.Strings(libs)
1479
1480			key := fmt.Sprintf(
1481				"SOONG_%s_%s_%s_STATIC_LIBRARIES",
1482				s.sanitizerType.variationName(),
1483				image, // already upper
1484				arch)
1485
1486			ctx.Strict(key, strings.Join(libs, " "))
1487		}
1488	}
1489}
1490
1491var cfiStaticLibsKey = android.NewOnceKey("cfiStaticLibs")
1492
1493func cfiStaticLibs(config android.Config) *sanitizerStaticLibsMap {
1494	return config.Once(cfiStaticLibsKey, func() interface{} {
1495		return newSanitizerStaticLibsMap(cfi)
1496	}).(*sanitizerStaticLibsMap)
1497}
1498
1499var hwasanStaticLibsKey = android.NewOnceKey("hwasanStaticLibs")
1500
1501func hwasanStaticLibs(config android.Config) *sanitizerStaticLibsMap {
1502	return config.Once(hwasanStaticLibsKey, func() interface{} {
1503		return newSanitizerStaticLibsMap(Hwasan)
1504	}).(*sanitizerStaticLibsMap)
1505}
1506
1507func enableMinimalRuntime(sanitize *sanitize) bool {
1508	if !Bool(sanitize.Properties.Sanitize.Address) &&
1509		!Bool(sanitize.Properties.Sanitize.Hwaddress) &&
1510		!Bool(sanitize.Properties.Sanitize.Fuzzer) &&
1511
1512		(Bool(sanitize.Properties.Sanitize.Integer_overflow) ||
1513			len(sanitize.Properties.Sanitize.Misc_undefined) > 0 ||
1514			Bool(sanitize.Properties.Sanitize.Undefined) ||
1515			Bool(sanitize.Properties.Sanitize.All_undefined)) &&
1516
1517		!(Bool(sanitize.Properties.Sanitize.Diag.Integer_overflow) ||
1518			Bool(sanitize.Properties.Sanitize.Diag.Cfi) ||
1519			Bool(sanitize.Properties.Sanitize.Diag.Undefined) ||
1520			len(sanitize.Properties.Sanitize.Diag.Misc_undefined) > 0) {
1521
1522		return true
1523	}
1524	return false
1525}
1526
1527func (m *Module) UbsanRuntimeNeeded() bool {
1528	return enableUbsanRuntime(m.sanitize)
1529}
1530
1531func (m *Module) MinimalRuntimeNeeded() bool {
1532	return enableMinimalRuntime(m.sanitize)
1533}
1534
1535func enableUbsanRuntime(sanitize *sanitize) bool {
1536	return Bool(sanitize.Properties.Sanitize.Diag.Integer_overflow) ||
1537		Bool(sanitize.Properties.Sanitize.Diag.Undefined) ||
1538		len(sanitize.Properties.Sanitize.Diag.Misc_undefined) > 0
1539}
1540
1541func cfiMakeVarsProvider(ctx android.MakeVarsContext) {
1542	cfiStaticLibs(ctx.Config()).exportToMake(ctx)
1543}
1544
1545func hwasanMakeVarsProvider(ctx android.MakeVarsContext) {
1546	hwasanStaticLibs(ctx.Config()).exportToMake(ctx)
1547}
1548