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/etc" 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 40 // DO NOT ADD MLLVM FLAGS HERE! ADD THEM BELOW TO hwasanCommonFlags. 41 hwasanCflags = []string{ 42 "-fno-omit-frame-pointer", 43 "-Wno-frame-larger-than=", 44 "-fsanitize-hwaddress-abi=platform", 45 } 46 47 // ThinLTO performs codegen during link time, thus these flags need to 48 // passed to both CFLAGS and LDFLAGS. 49 hwasanCommonflags = []string{ 50 // The following improves debug location information 51 // availability at the cost of its accuracy. It increases 52 // the likelihood of a stack variable's frame offset 53 // to be recorded in the debug info, which is important 54 // for the quality of hwasan reports. The downside is a 55 // higher number of "optimized out" stack variables. 56 // b/112437883. 57 "-instcombine-lower-dbg-declare=0", 58 "-dom-tree-reachability-max-bbs-to-explore=128", 59 } 60 61 sanitizeIgnorelistPrefix = "-fsanitize-ignorelist=" 62 63 cfiBlocklistPath = "external/compiler-rt/lib/cfi" 64 cfiBlocklistFilename = "cfi_blocklist.txt" 65 cfiEnableFlag = "-fsanitize=cfi" 66 cfiCrossDsoFlag = "-fsanitize-cfi-cross-dso" 67 cfiCflags = []string{"-flto", cfiCrossDsoFlag, 68 sanitizeIgnorelistPrefix + cfiBlocklistPath + "/" + cfiBlocklistFilename} 69 // -flto and -fvisibility are required by clang when -fsanitize=cfi is 70 // used, but have no effect on assembly files 71 cfiAsflags = []string{"-flto", "-fvisibility=default"} 72 cfiLdflags = []string{"-flto", cfiCrossDsoFlag, cfiEnableFlag, 73 "-Wl,-plugin-opt,O1"} 74 cfiExportsMapPath = "build/soong/cc/config" 75 cfiExportsMapFilename = "cfi_exports.map" 76 cfiAssemblySupportFlag = "-fno-sanitize-cfi-canonical-jump-tables" 77 78 intOverflowCflags = []string{"-fsanitize-ignorelist=build/soong/cc/config/integer_overflow_blocklist.txt"} 79 80 minimalRuntimeFlags = []string{"-fsanitize-minimal-runtime", "-fno-sanitize-trap=integer,undefined", 81 "-fno-sanitize-recover=integer,undefined"} 82 memtagStackCommonFlags = []string{"-march=armv8-a+memtag"} 83 memtagStackLlvmFlags = []string{"-dom-tree-reachability-max-bbs-to-explore=128"} 84 85 hostOnlySanitizeFlags = []string{"-fno-sanitize-recover=all"} 86 deviceOnlySanitizeFlags = []string{"-fsanitize-trap=all"} 87 88 noSanitizeLinkRuntimeFlag = "-fno-sanitize-link-runtime" 89) 90 91type SanitizerType int 92 93const ( 94 Asan SanitizerType = iota + 1 95 Hwasan 96 tsan 97 intOverflow 98 scs 99 Fuzzer 100 Memtag_heap 101 Memtag_stack 102 Memtag_globals 103 cfi // cfi is last to prevent it running before incompatible mutators 104) 105 106var Sanitizers = []SanitizerType{ 107 Asan, 108 Hwasan, 109 tsan, 110 intOverflow, 111 scs, 112 Fuzzer, 113 Memtag_heap, 114 Memtag_stack, 115 Memtag_globals, 116 cfi, // cfi is last to prevent it running before incompatible mutators 117} 118 119// Name of the sanitizer variation for this sanitizer type 120func (t SanitizerType) variationName() string { 121 switch t { 122 case Asan: 123 return "asan" 124 case Hwasan: 125 return "hwasan" 126 case tsan: 127 return "tsan" 128 case intOverflow: 129 return "intOverflow" 130 case cfi: 131 return "cfi" 132 case scs: 133 return "scs" 134 case Memtag_heap: 135 return "memtag_heap" 136 case Memtag_stack: 137 return "memtag_stack" 138 case Memtag_globals: 139 return "memtag_globals" 140 case Fuzzer: 141 return "fuzzer" 142 default: 143 panic(fmt.Errorf("unknown SanitizerType %d", t)) 144 } 145} 146 147// This is the sanitizer names in SANITIZE_[TARGET|HOST] 148func (t SanitizerType) name() string { 149 switch t { 150 case Asan: 151 return "address" 152 case Hwasan: 153 return "hwaddress" 154 case Memtag_heap: 155 return "memtag_heap" 156 case Memtag_stack: 157 return "memtag_stack" 158 case Memtag_globals: 159 return "memtag_globals" 160 case tsan: 161 return "thread" 162 case intOverflow: 163 return "integer_overflow" 164 case cfi: 165 return "cfi" 166 case scs: 167 return "shadow-call-stack" 168 case Fuzzer: 169 return "fuzzer" 170 default: 171 panic(fmt.Errorf("unknown SanitizerType %d", t)) 172 } 173} 174 175func (t SanitizerType) registerMutators(ctx android.RegisterMutatorsContext) { 176 switch t { 177 case cfi, Hwasan, Asan, tsan, Fuzzer, scs, Memtag_stack: 178 sanitizer := &sanitizerSplitMutator{t} 179 ctx.BottomUp(t.variationName()+"_markapexes", sanitizer.markSanitizableApexesMutator) 180 ctx.Transition(t.variationName(), sanitizer) 181 case Memtag_heap, Memtag_globals, intOverflow: 182 // do nothing 183 default: 184 panic(fmt.Errorf("unknown SanitizerType %d", t)) 185 } 186} 187 188// shouldPropagateToSharedLibraryDeps returns whether a sanitizer type should propagate to share 189// dependencies. In most cases, sanitizers only propagate to static dependencies; however, some 190// sanitizers also must be enabled for shared libraries for linking. 191func (t SanitizerType) shouldPropagateToSharedLibraryDeps() bool { 192 switch t { 193 case Fuzzer: 194 // Typically, shared libs are not split. However, for fuzzer, we split even for shared libs 195 // because a library sanitized for fuzzer can't be linked from a library that isn't sanitized 196 // for fuzzer. 197 return true 198 default: 199 return false 200 } 201} 202func (*Module) SanitizerSupported(t SanitizerType) bool { 203 switch t { 204 case Asan: 205 return true 206 case Hwasan: 207 return true 208 case tsan: 209 return true 210 case intOverflow: 211 return true 212 case cfi: 213 return true 214 case scs: 215 return true 216 case Fuzzer: 217 return true 218 case Memtag_heap: 219 return true 220 case Memtag_stack: 221 return true 222 case Memtag_globals: 223 return true 224 default: 225 return false 226 } 227} 228 229// incompatibleWithCfi returns true if a sanitizer is incompatible with CFI. 230func (t SanitizerType) incompatibleWithCfi() bool { 231 return t == Asan || t == Fuzzer || t == Hwasan 232} 233 234type SanitizeUserProps struct { 235 // Prevent use of any sanitizers on this module 236 Never *bool `android:"arch_variant"` 237 238 // ASan (Address sanitizer), incompatible with static binaries. 239 // Always runs in a diagnostic mode. 240 // Use of address sanitizer disables cfi sanitizer. 241 // Hwaddress sanitizer takes precedence over this sanitizer. 242 Address *bool `android:"arch_variant"` 243 // TSan (Thread sanitizer), incompatible with static binaries and 32 bit architectures. 244 // Always runs in a diagnostic mode. 245 // Use of thread sanitizer disables cfi and scudo sanitizers. 246 // Hwaddress sanitizer takes precedence over this sanitizer. 247 Thread *bool `android:"arch_variant"` 248 // HWASan (Hardware Address sanitizer). 249 // Use of hwasan sanitizer disables cfi, address, thread, and scudo sanitizers. 250 Hwaddress *bool `android:"arch_variant"` 251 252 // Undefined behavior sanitizer 253 All_undefined *bool `android:"arch_variant"` 254 // Subset of undefined behavior sanitizer 255 Undefined *bool `android:"arch_variant"` 256 // List of specific undefined behavior sanitizers to enable 257 Misc_undefined []string `android:"arch_variant"` 258 // Fuzzer, incompatible with static binaries. 259 Fuzzer *bool `android:"arch_variant"` 260 // safe-stack sanitizer, incompatible with 32-bit architectures. 261 Safestack *bool `android:"arch_variant"` 262 // cfi sanitizer, incompatible with asan, hwasan, fuzzer, or Darwin 263 Cfi *bool `android:"arch_variant"` 264 // signed/unsigned integer overflow sanitizer, incompatible with Darwin. 265 Integer_overflow *bool `android:"arch_variant"` 266 // scudo sanitizer, incompatible with asan, hwasan, tsan 267 // This should not be used in Android 11+ : https://source.android.com/devices/tech/debug/scudo 268 // deprecated 269 Scudo *bool `android:"arch_variant"` 270 // shadow-call-stack sanitizer, only available on arm64/riscv64. 271 Scs *bool `android:"arch_variant"` 272 // Memory-tagging, only available on arm64 273 // if diag.memtag unset or false, enables async memory tagging 274 Memtag_heap *bool `android:"arch_variant"` 275 // Memory-tagging stack instrumentation, only available on arm64 276 // Adds instrumentation to detect stack buffer overflows and use-after-scope using MTE. 277 Memtag_stack *bool `android:"arch_variant"` 278 // Memory-tagging globals instrumentation, only available on arm64 279 // Adds instrumentation to detect global buffer overflows using MTE. 280 Memtag_globals *bool `android:"arch_variant"` 281 282 // A modifier for ASAN and HWASAN for write only instrumentation 283 Writeonly *bool `android:"arch_variant"` 284 285 // Sanitizers to run in the diagnostic mode (as opposed to the release mode). 286 // Replaces abort() on error with a human-readable error message. 287 // Address and Thread sanitizers always run in diagnostic mode. 288 Diag struct { 289 // Undefined behavior sanitizer, diagnostic mode 290 Undefined *bool `android:"arch_variant"` 291 // cfi sanitizer, diagnostic mode, incompatible with asan, hwasan, fuzzer, or Darwin 292 Cfi *bool `android:"arch_variant"` 293 // signed/unsigned integer overflow sanitizer, diagnostic mode, incompatible with Darwin. 294 Integer_overflow *bool `android:"arch_variant"` 295 // Memory-tagging, only available on arm64 296 // requires sanitizer.memtag: true 297 // if set, enables sync memory tagging 298 Memtag_heap *bool `android:"arch_variant"` 299 // List of specific undefined behavior sanitizers to enable in diagnostic mode 300 Misc_undefined []string `android:"arch_variant"` 301 // List of sanitizers to pass to -fno-sanitize-recover 302 // results in only the first detected error for these sanitizers being reported and program then 303 // exits with a non-zero exit code. 304 No_recover []string `android:"arch_variant"` 305 } `android:"arch_variant"` 306 307 // Sanitizers to run with flag configuration specified 308 Config struct { 309 // Enables CFI support flags for assembly-heavy libraries 310 Cfi_assembly_support *bool `android:"arch_variant"` 311 } `android:"arch_variant"` 312 313 // List of sanitizers to pass to -fsanitize-recover 314 // allows execution to continue for these sanitizers to detect multiple errors rather than only 315 // the first one 316 Recover []string 317 318 // value to pass to -fsanitize-ignorelist 319 Blocklist *string 320} 321 322type sanitizeMutatedProperties struct { 323 // Whether sanitizers can be enabled on this module 324 Never *bool `blueprint:"mutated"` 325 326 // Whether ASan (Address sanitizer) is enabled for this module. 327 // Hwaddress sanitizer takes precedence over this sanitizer. 328 Address *bool `blueprint:"mutated"` 329 // Whether TSan (Thread sanitizer) is enabled for this module 330 Thread *bool `blueprint:"mutated"` 331 // Whether HWASan (Hardware Address sanitizer) is enabled for this module 332 Hwaddress *bool `blueprint:"mutated"` 333 334 // Whether Undefined behavior sanitizer is enabled for this module 335 All_undefined *bool `blueprint:"mutated"` 336 // Whether undefined behavior sanitizer subset is enabled for this module 337 Undefined *bool `blueprint:"mutated"` 338 // List of specific undefined behavior sanitizers enabled for this module 339 Misc_undefined []string `blueprint:"mutated"` 340 // Whether Fuzzeris enabled for this module 341 Fuzzer *bool `blueprint:"mutated"` 342 // whether safe-stack sanitizer is enabled for this module 343 Safestack *bool `blueprint:"mutated"` 344 // Whether cfi sanitizer is enabled for this module 345 Cfi *bool `blueprint:"mutated"` 346 // Whether signed/unsigned integer overflow sanitizer is enabled for this module 347 Integer_overflow *bool `blueprint:"mutated"` 348 // Whether scudo sanitizer is enabled for this module 349 Scudo *bool `blueprint:"mutated"` 350 // Whether shadow-call-stack sanitizer is enabled for this module. 351 Scs *bool `blueprint:"mutated"` 352 // Whether Memory-tagging is enabled for this module 353 Memtag_heap *bool `blueprint:"mutated"` 354 // Whether Memory-tagging stack instrumentation is enabled for this module 355 Memtag_stack *bool `blueprint:"mutated"` 356 // Whether Memory-tagging globals instrumentation is enabled for this module 357 Memtag_globals *bool `android:"arch_variant"` 358 359 // Whether a modifier for ASAN and HWASAN for write only instrumentation is enabled for this 360 // module 361 Writeonly *bool `blueprint:"mutated"` 362 363 // Sanitizers to run in the diagnostic mode (as opposed to the release mode). 364 Diag struct { 365 // Whether Undefined behavior sanitizer, diagnostic mode is enabled for this module 366 Undefined *bool `blueprint:"mutated"` 367 // Whether cfi sanitizer, diagnostic mode is enabled for this module 368 Cfi *bool `blueprint:"mutated"` 369 // Whether signed/unsigned integer overflow sanitizer, diagnostic mode is enabled for this 370 // module 371 Integer_overflow *bool `blueprint:"mutated"` 372 // Whether Memory-tagging, diagnostic mode is enabled for this module 373 Memtag_heap *bool `blueprint:"mutated"` 374 // List of specific undefined behavior sanitizers enabled in diagnostic mode 375 Misc_undefined []string `blueprint:"mutated"` 376 } `blueprint:"mutated"` 377} 378 379type SanitizeProperties struct { 380 Sanitize SanitizeUserProps `android:"arch_variant"` 381 SanitizeMutated sanitizeMutatedProperties `blueprint:"mutated"` 382 383 // ForceDisable is set by the version mutator to disable sanitization of stubs variants 384 ForceDisable bool `blueprint:"mutated"` 385 386 // SanitizerEnabled is set by begin() if any of the sanitize boolean properties are set after 387 // applying the logic that enables globally enabled sanitizers and disables any unsupported 388 // sanitizers. 389 // TODO(b/349906293): this has some unintuitive behavior. It is set in begin() before the sanitize 390 // mutator is run if any of the individual sanitizes properties are set, and then the individual 391 // sanitize properties are cleared in the non-sanitized variants, but this value is never cleared. 392 // That results in SanitizerEnabled being set in variants that have no sanitizers enabled, causing 393 // some of the sanitizer logic in flags() to be applied to the non-sanitized variant. 394 SanitizerEnabled bool `blueprint:"mutated"` 395 396 MinimalRuntimeDep bool `blueprint:"mutated"` 397 BuiltinsDep bool `blueprint:"mutated"` 398 UbsanRuntimeDep bool `blueprint:"mutated"` 399 InSanitizerDir bool `blueprint:"mutated"` 400 Sanitizers []string `blueprint:"mutated"` 401 DiagSanitizers []string `blueprint:"mutated"` 402} 403 404type sanitize struct { 405 Properties SanitizeProperties 406} 407 408// Mark this tag with a check to see if apex dependency check should be skipped 409func (t libraryDependencyTag) SkipApexAllowedDependenciesCheck() bool { 410 return t.skipApexAllowedDependenciesCheck 411} 412 413var _ android.SkipApexAllowedDependenciesCheck = (*libraryDependencyTag)(nil) 414 415func init() { 416 pctx.StaticVariable("HostOnlySanitizeFlags", strings.Join(hostOnlySanitizeFlags, " ")) 417 418 android.RegisterMakeVarsProvider(pctx, cfiMakeVarsProvider) 419 android.RegisterMakeVarsProvider(pctx, hwasanMakeVarsProvider) 420 android.RegisterMakeVarsProvider(pctx, memtagStackMakeVarsProvider) 421 422 RegisterSanitizerLibrariesTxtType(android.InitRegistrationContext) 423} 424 425func (sanitize *sanitize) props() []interface{} { 426 return []interface{}{&sanitize.Properties} 427} 428 429func (p *sanitizeMutatedProperties) copyUserPropertiesToMutated(userProps *SanitizeUserProps) { 430 p.Never = userProps.Never 431 p.Address = userProps.Address 432 p.All_undefined = userProps.All_undefined 433 p.Cfi = userProps.Cfi 434 p.Fuzzer = userProps.Fuzzer 435 p.Hwaddress = userProps.Hwaddress 436 p.Integer_overflow = userProps.Integer_overflow 437 p.Memtag_heap = userProps.Memtag_heap 438 p.Memtag_stack = userProps.Memtag_stack 439 p.Memtag_globals = userProps.Memtag_globals 440 p.Safestack = userProps.Safestack 441 p.Scs = userProps.Scs 442 p.Scudo = userProps.Scudo 443 p.Thread = userProps.Thread 444 p.Undefined = userProps.Undefined 445 p.Writeonly = userProps.Writeonly 446 447 p.Misc_undefined = make([]string, 0, len(userProps.Misc_undefined)) 448 for _, v := range userProps.Misc_undefined { 449 p.Misc_undefined = append(p.Misc_undefined, v) 450 } 451 452 p.Diag.Cfi = userProps.Diag.Cfi 453 p.Diag.Integer_overflow = userProps.Diag.Integer_overflow 454 p.Diag.Memtag_heap = userProps.Diag.Memtag_heap 455 p.Diag.Undefined = userProps.Diag.Undefined 456 457 p.Diag.Misc_undefined = make([]string, 0, len(userProps.Diag.Misc_undefined)) 458 for _, v := range userProps.Diag.Misc_undefined { 459 p.Diag.Misc_undefined = append(p.Diag.Misc_undefined, v) 460 } 461} 462 463func (sanitize *sanitize) begin(ctx BaseModuleContext) { 464 s := &sanitize.Properties.SanitizeMutated 465 s.copyUserPropertiesToMutated(&sanitize.Properties.Sanitize) 466 467 if sanitize.Properties.ForceDisable { 468 return 469 } 470 471 // Don't apply sanitizers to NDK code. 472 if ctx.useSdk() { 473 s.Never = BoolPtr(true) 474 } 475 476 // Never always wins. 477 if Bool(s.Never) { 478 return 479 } 480 481 // cc_test targets default to SYNC MemTag unless explicitly set to ASYNC (via diag: {memtag_heap: false}). 482 if ctx.testBinary() { 483 if s.Memtag_heap == nil { 484 s.Memtag_heap = proptools.BoolPtr(true) 485 } 486 if s.Diag.Memtag_heap == nil { 487 s.Diag.Memtag_heap = proptools.BoolPtr(true) 488 } 489 } 490 491 var globalSanitizers []string 492 var globalSanitizersDiag []string 493 494 if ctx.Host() { 495 if !ctx.Windows() { 496 globalSanitizers = ctx.Config().SanitizeHost() 497 } 498 } else { 499 arches := ctx.Config().SanitizeDeviceArch() 500 if len(arches) == 0 || inList(ctx.Arch().ArchType.Name, arches) { 501 globalSanitizers = ctx.Config().SanitizeDevice() 502 globalSanitizersDiag = ctx.Config().SanitizeDeviceDiag() 503 } 504 } 505 506 if len(globalSanitizers) > 0 { 507 var found bool 508 if found, globalSanitizers = removeFromList("undefined", globalSanitizers); found && s.All_undefined == nil { 509 s.All_undefined = proptools.BoolPtr(true) 510 } 511 512 if found, globalSanitizers = removeFromList("default-ub", globalSanitizers); found && s.Undefined == nil { 513 s.Undefined = proptools.BoolPtr(true) 514 } 515 516 if found, globalSanitizers = removeFromList("address", globalSanitizers); found && s.Address == nil { 517 s.Address = proptools.BoolPtr(true) 518 } 519 520 if found, globalSanitizers = removeFromList("thread", globalSanitizers); found && s.Thread == nil { 521 s.Thread = proptools.BoolPtr(true) 522 } 523 524 if found, globalSanitizers = removeFromList("fuzzer", globalSanitizers); found && s.Fuzzer == nil { 525 s.Fuzzer = proptools.BoolPtr(true) 526 } 527 528 if found, globalSanitizers = removeFromList("safe-stack", globalSanitizers); found && s.Safestack == nil { 529 s.Safestack = proptools.BoolPtr(true) 530 } 531 532 if found, globalSanitizers = removeFromList("cfi", globalSanitizers); found && s.Cfi == nil { 533 if !ctx.Config().CFIDisabledForPath(ctx.ModuleDir()) { 534 s.Cfi = proptools.BoolPtr(true) 535 } 536 } 537 538 // Global integer_overflow builds do not support static libraries. 539 if found, globalSanitizers = removeFromList("integer_overflow", globalSanitizers); found && s.Integer_overflow == nil { 540 if !ctx.Config().IntegerOverflowDisabledForPath(ctx.ModuleDir()) && !ctx.static() { 541 s.Integer_overflow = proptools.BoolPtr(true) 542 } 543 } 544 545 if found, globalSanitizers = removeFromList("scudo", globalSanitizers); found && s.Scudo == nil { 546 s.Scudo = proptools.BoolPtr(true) 547 } 548 549 if found, globalSanitizers = removeFromList("hwaddress", globalSanitizers); found && s.Hwaddress == nil { 550 if !ctx.Config().HWASanDisabledForPath(ctx.ModuleDir()) { 551 s.Hwaddress = proptools.BoolPtr(true) 552 } 553 } 554 555 if found, globalSanitizers = removeFromList("writeonly", globalSanitizers); found && s.Writeonly == nil { 556 // Hwaddress and Address are set before, so we can check them here 557 // If they aren't explicitly set in the blueprint/SANITIZE_(HOST|TARGET), they would be nil instead of false 558 if s.Address == nil && s.Hwaddress == nil { 559 ctx.ModuleErrorf("writeonly modifier cannot be used without 'address' or 'hwaddress'") 560 } 561 s.Writeonly = proptools.BoolPtr(true) 562 } 563 if found, globalSanitizers = removeFromList("memtag_heap", globalSanitizers); found && s.Memtag_heap == nil { 564 if !ctx.Config().MemtagHeapDisabledForPath(ctx.ModuleDir()) { 565 s.Memtag_heap = proptools.BoolPtr(true) 566 } 567 } 568 569 if found, globalSanitizers = removeFromList("memtag_stack", globalSanitizers); found && s.Memtag_stack == nil { 570 s.Memtag_stack = proptools.BoolPtr(true) 571 } 572 573 if found, globalSanitizers = removeFromList("memtag_globals", globalSanitizers); found && s.Memtag_globals == nil { 574 s.Memtag_globals = proptools.BoolPtr(true) 575 } 576 577 if len(globalSanitizers) > 0 { 578 ctx.ModuleErrorf("unknown global sanitizer option %s", globalSanitizers[0]) 579 } 580 581 // Global integer_overflow builds do not support static library diagnostics. 582 if found, globalSanitizersDiag = removeFromList("integer_overflow", globalSanitizersDiag); found && 583 s.Diag.Integer_overflow == nil && Bool(s.Integer_overflow) && !ctx.static() { 584 s.Diag.Integer_overflow = proptools.BoolPtr(true) 585 } 586 587 if found, globalSanitizersDiag = removeFromList("cfi", globalSanitizersDiag); found && 588 s.Diag.Cfi == nil && Bool(s.Cfi) { 589 s.Diag.Cfi = proptools.BoolPtr(true) 590 } 591 592 if found, globalSanitizersDiag = removeFromList("memtag_heap", globalSanitizersDiag); found && 593 s.Diag.Memtag_heap == nil && Bool(s.Memtag_heap) { 594 s.Diag.Memtag_heap = proptools.BoolPtr(true) 595 } 596 597 if len(globalSanitizersDiag) > 0 { 598 ctx.ModuleErrorf("unknown global sanitizer diagnostics option %s", globalSanitizersDiag[0]) 599 } 600 } 601 602 // Enable Memtag for all components in the include paths (for Aarch64 only) 603 if ctx.Arch().ArchType == android.Arm64 && ctx.toolchain().Bionic() { 604 if ctx.Config().MemtagHeapSyncEnabledForPath(ctx.ModuleDir()) { 605 if s.Memtag_heap == nil { 606 s.Memtag_heap = proptools.BoolPtr(true) 607 } 608 if s.Diag.Memtag_heap == nil { 609 s.Diag.Memtag_heap = proptools.BoolPtr(true) 610 } 611 } else if ctx.Config().MemtagHeapAsyncEnabledForPath(ctx.ModuleDir()) { 612 if s.Memtag_heap == nil { 613 s.Memtag_heap = proptools.BoolPtr(true) 614 } 615 } 616 } 617 618 // Enable HWASan for all components in the include paths (for Aarch64 only) 619 if s.Hwaddress == nil && ctx.Config().HWASanEnabledForPath(ctx.ModuleDir()) && 620 ctx.Arch().ArchType == android.Arm64 && ctx.toolchain().Bionic() { 621 s.Hwaddress = proptools.BoolPtr(true) 622 } 623 624 // Enable CFI for non-host components in the include paths 625 if s.Cfi == nil && ctx.Config().CFIEnabledForPath(ctx.ModuleDir()) && !ctx.Host() { 626 s.Cfi = proptools.BoolPtr(true) 627 if inList("cfi", ctx.Config().SanitizeDeviceDiag()) { 628 s.Diag.Cfi = proptools.BoolPtr(true) 629 } 630 } 631 632 // Is CFI actually enabled? 633 if !ctx.Config().EnableCFI() { 634 s.Cfi = nil 635 s.Diag.Cfi = nil 636 } 637 638 // HWASan requires AArch64 hardware feature (top-byte-ignore). 639 if ctx.Arch().ArchType != android.Arm64 || !ctx.toolchain().Bionic() { 640 s.Hwaddress = nil 641 } 642 643 // SCS is only implemented on AArch64/riscv64. 644 if (ctx.Arch().ArchType != android.Arm64 && ctx.Arch().ArchType != android.Riscv64) || !ctx.toolchain().Bionic() { 645 s.Scs = nil 646 } 647 648 // Memtag_heap is only implemented on AArch64. 649 // Memtag ABI is Android specific for now, so disable for host. 650 if ctx.Arch().ArchType != android.Arm64 || !ctx.toolchain().Bionic() || ctx.Host() { 651 s.Memtag_heap = nil 652 s.Memtag_stack = nil 653 s.Memtag_globals = nil 654 } 655 656 // Also disable CFI if ASAN is enabled. 657 if Bool(s.Address) || Bool(s.Hwaddress) { 658 s.Cfi = nil 659 s.Diag.Cfi = nil 660 // HWASAN and ASAN win against MTE. 661 s.Memtag_heap = nil 662 s.Memtag_stack = nil 663 s.Memtag_globals = nil 664 } 665 666 // Disable sanitizers that depend on the UBSan runtime for windows/darwin builds. 667 if !ctx.Os().Linux() { 668 s.Cfi = nil 669 s.Diag.Cfi = nil 670 s.Misc_undefined = nil 671 s.Undefined = nil 672 s.All_undefined = nil 673 s.Integer_overflow = nil 674 } 675 676 // Disable CFI for musl 677 if ctx.toolchain().Musl() { 678 s.Cfi = nil 679 s.Diag.Cfi = nil 680 } 681 682 // TODO(b/280478629): runtimes don't exist for musl arm64 yet. 683 if ctx.toolchain().Musl() && ctx.Arch().ArchType == android.Arm64 { 684 s.Address = nil 685 s.Hwaddress = nil 686 s.Thread = nil 687 s.Scudo = nil 688 s.Fuzzer = nil 689 s.Cfi = nil 690 s.Diag.Cfi = nil 691 s.Misc_undefined = nil 692 s.Undefined = nil 693 s.All_undefined = nil 694 s.Integer_overflow = nil 695 } 696 697 if ctx.inRamdisk() || ctx.inVendorRamdisk() || ctx.inRecovery() { 698 // HWASan ramdisk (which is built from recovery) goes over some bootloader limit. 699 // Keep libc instrumented so that ramdisk / vendor_ramdisk / recovery can run hwasan-instrumented code if necessary. 700 if !strings.HasPrefix(ctx.ModuleDir(), "bionic/libc") { 701 s.Hwaddress = nil 702 } 703 // Memtag stack in ramdisk makes pKVM unhappy. 704 s.Memtag_stack = nil 705 } 706 707 if ctx.staticBinary() { 708 s.Address = nil 709 s.Fuzzer = nil 710 s.Thread = nil 711 } 712 713 if Bool(s.All_undefined) { 714 s.Undefined = nil 715 } 716 717 if !ctx.toolchain().Is64Bit() { 718 // TSAN and SafeStack are not supported on 32-bit architectures 719 s.Thread = nil 720 s.Safestack = nil 721 // TODO(ccross): error for compile_multilib = "32"? 722 } 723 724 if ctx.Os() != android.Windows && (Bool(s.All_undefined) || Bool(s.Undefined) || Bool(s.Address) || Bool(s.Thread) || 725 Bool(s.Fuzzer) || Bool(s.Safestack) || Bool(s.Cfi) || Bool(s.Integer_overflow) || len(s.Misc_undefined) > 0 || 726 Bool(s.Scudo) || Bool(s.Hwaddress) || Bool(s.Scs) || Bool(s.Memtag_heap) || Bool(s.Memtag_stack) || 727 Bool(s.Memtag_globals)) { 728 sanitize.Properties.SanitizerEnabled = true 729 } 730 731 // Disable Scudo if ASan or TSan is enabled, or if it's disabled globally. 732 if Bool(s.Address) || Bool(s.Thread) || Bool(s.Hwaddress) || ctx.Config().DisableScudo() { 733 s.Scudo = nil 734 } 735 736 if Bool(s.Hwaddress) { 737 s.Address = nil 738 s.Thread = nil 739 } 740 741 // TODO(b/131771163): CFI transiently depends on LTO, and thus Fuzzer is 742 // mutually incompatible. 743 if Bool(s.Fuzzer) { 744 s.Cfi = nil 745 } 746} 747 748func toDisableImplicitIntegerChange(flags []string) bool { 749 // Returns true if any flag is fsanitize*integer, and there is 750 // no explicit flag about sanitize=implicit-integer-sign-change. 751 for _, f := range flags { 752 if strings.Contains(f, "sanitize=implicit-integer-sign-change") { 753 return false 754 } 755 } 756 for _, f := range flags { 757 if strings.HasPrefix(f, "-fsanitize") && strings.Contains(f, "integer") { 758 return true 759 } 760 } 761 return false 762} 763 764func toDisableUnsignedShiftBaseChange(flags []string) bool { 765 // Returns true if any flag is fsanitize*integer, and there is 766 // no explicit flag about sanitize=unsigned-shift-base. 767 for _, f := range flags { 768 if strings.Contains(f, "sanitize=unsigned-shift-base") { 769 return false 770 } 771 } 772 for _, f := range flags { 773 if strings.HasPrefix(f, "-fsanitize") && strings.Contains(f, "integer") { 774 return true 775 } 776 } 777 return false 778} 779 780func (s *sanitize) flags(ctx ModuleContext, flags Flags) Flags { 781 if s.Properties.ForceDisable { 782 return flags 783 } 784 785 if !s.Properties.SanitizerEnabled && !s.Properties.UbsanRuntimeDep { 786 return flags 787 } 788 sanProps := &s.Properties.SanitizeMutated 789 790 if Bool(sanProps.Address) { 791 if ctx.Arch().ArchType == android.Arm { 792 // Frame pointer based unwinder in ASan requires ARM frame setup. 793 // TODO: put in flags? 794 flags.RequiredInstructionSet = "arm" 795 } 796 flags.Local.CFlags = append(flags.Local.CFlags, asanCflags...) 797 798 if Bool(sanProps.Writeonly) { 799 flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", "-asan-instrument-reads=0") 800 } 801 802 if ctx.Host() { 803 if !ctx.Darwin() { // ld64.lld doesn't know about '--no-as-needed' 804 // -nodefaultlibs (provided with libc++) prevents the driver from linking 805 // libraries needed with -fsanitize=address. http://b/18650275 (WAI) 806 flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--no-as-needed") 807 } 808 } else { 809 flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", "-asan-globals=0") 810 if ctx.bootstrap() { 811 flags.DynamicLinker = "/system/bin/bootstrap/linker_asan" 812 } else { 813 flags.DynamicLinker = "/system/bin/linker_asan" 814 } 815 if flags.Toolchain.Is64Bit() { 816 flags.DynamicLinker += "64" 817 } 818 } 819 } 820 821 if Bool(sanProps.Hwaddress) { 822 flags.Local.CFlags = append(flags.Local.CFlags, hwasanCflags...) 823 824 for _, flag := range hwasanCommonflags { 825 flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", flag) 826 } 827 for _, flag := range hwasanCommonflags { 828 flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-mllvm,"+flag) 829 } 830 831 if Bool(sanProps.Writeonly) { 832 flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", "-hwasan-instrument-reads=0") 833 } 834 if !ctx.staticBinary() && !ctx.Host() { 835 if ctx.bootstrap() { 836 flags.DynamicLinker = "/system/bin/bootstrap/linker_hwasan64" 837 } else { 838 flags.DynamicLinker = "/system/bin/linker_hwasan64" 839 } 840 } 841 } 842 843 if Bool(sanProps.Fuzzer) { 844 flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize=fuzzer-no-link") 845 846 // TODO(b/131771163): LTO and Fuzzer support is mutually incompatible. 847 _, flags.Local.LdFlags = removeFromList("-flto", flags.Local.LdFlags) 848 _, flags.Local.CFlags = removeFromList("-flto", flags.Local.CFlags) 849 flags.Local.LdFlags = append(flags.Local.LdFlags, "-fno-lto") 850 flags.Local.CFlags = append(flags.Local.CFlags, "-fno-lto") 851 852 // TODO(b/142430592): Upstream linker scripts for sanitizer runtime libraries 853 // discard the sancov_lowest_stack symbol, because it's emulated TLS (and thus 854 // doesn't match the linker script due to the "__emutls_v." prefix). 855 flags.Local.LdFlags = append(flags.Local.LdFlags, "-fno-sanitize-coverage=stack-depth") 856 flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-coverage=stack-depth") 857 858 // Disable fortify for fuzzing builds. Generally, we'll be building with 859 // UBSan or ASan here and the fortify checks pollute the stack traces. 860 flags.Local.CFlags = append(flags.Local.CFlags, "-U_FORTIFY_SOURCE") 861 862 // Build fuzzer-sanitized libraries with an $ORIGIN DT_RUNPATH. Android's 863 // linker uses DT_RUNPATH, not DT_RPATH. When we deploy cc_fuzz targets and 864 // their libraries to /data/fuzz/<arch>/lib, any transient shared library gets 865 // the DT_RUNPATH from the shared library above it, and not the executable, 866 // meaning that the lookup falls back to the system. Adding the $ORIGIN to the 867 // DT_RUNPATH here means that transient shared libraries can be found 868 // colocated with their parents. 869 flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN`) 870 } 871 872 if Bool(sanProps.Cfi) { 873 if ctx.Arch().ArchType == android.Arm { 874 // __cfi_check needs to be built as Thumb (see the code in linker_cfi.cpp). LLVM is not set up 875 // to do this on a function basis, so force Thumb on the entire module. 876 flags.RequiredInstructionSet = "thumb" 877 } 878 879 flags.Local.CFlags = append(flags.Local.CFlags, cfiCflags...) 880 flags.Local.AsFlags = append(flags.Local.AsFlags, cfiAsflags...) 881 flags.CFlagsDeps = append(flags.CFlagsDeps, android.PathForSource(ctx, cfiBlocklistPath+"/"+cfiBlocklistFilename)) 882 if Bool(s.Properties.Sanitize.Config.Cfi_assembly_support) { 883 flags.Local.CFlags = append(flags.Local.CFlags, cfiAssemblySupportFlag) 884 } 885 // Only append the default visibility flag if -fvisibility has not already been set 886 // to hidden. 887 if !inList("-fvisibility=hidden", flags.Local.CFlags) { 888 flags.Local.CFlags = append(flags.Local.CFlags, "-fvisibility=default") 889 } 890 flags.Local.LdFlags = append(flags.Local.LdFlags, cfiLdflags...) 891 892 if ctx.staticBinary() { 893 _, flags.Local.CFlags = removeFromList("-fsanitize-cfi-cross-dso", flags.Local.CFlags) 894 _, flags.Local.LdFlags = removeFromList("-fsanitize-cfi-cross-dso", flags.Local.LdFlags) 895 } 896 } 897 898 if Bool(sanProps.Memtag_stack) { 899 flags.Local.CFlags = append(flags.Local.CFlags, memtagStackCommonFlags...) 900 flags.Local.AsFlags = append(flags.Local.AsFlags, memtagStackCommonFlags...) 901 flags.Local.LdFlags = append(flags.Local.LdFlags, memtagStackCommonFlags...) 902 903 for _, flag := range memtagStackLlvmFlags { 904 flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", flag) 905 } 906 for _, flag := range memtagStackLlvmFlags { 907 flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-mllvm,"+flag) 908 } 909 } 910 911 if (Bool(sanProps.Memtag_heap) || Bool(sanProps.Memtag_stack) || Bool(sanProps.Memtag_globals)) && ctx.binary() { 912 if Bool(sanProps.Diag.Memtag_heap) { 913 flags.Local.LdFlags = append(flags.Local.LdFlags, "-fsanitize-memtag-mode=sync") 914 } else { 915 flags.Local.LdFlags = append(flags.Local.LdFlags, "-fsanitize-memtag-mode=async") 916 } 917 } 918 919 if Bool(sanProps.Integer_overflow) { 920 flags.Local.CFlags = append(flags.Local.CFlags, intOverflowCflags...) 921 } 922 923 if len(s.Properties.Sanitizers) > 0 { 924 sanitizeArg := "-fsanitize=" + strings.Join(s.Properties.Sanitizers, ",") 925 flags.Local.CFlags = append(flags.Local.CFlags, sanitizeArg) 926 flags.Local.AsFlags = append(flags.Local.AsFlags, sanitizeArg) 927 flags.Local.LdFlags = append(flags.Local.LdFlags, sanitizeArg) 928 929 if ctx.toolchain().Bionic() || ctx.toolchain().Musl() { 930 // Bionic and musl sanitizer runtimes have already been added as dependencies so that 931 // the right variant of the runtime will be used (with the "-android" or "-musl" 932 // suffixes), so don't let clang the runtime library. 933 flags.Local.LdFlags = append(flags.Local.LdFlags, noSanitizeLinkRuntimeFlag) 934 } else { 935 // Host sanitizers only link symbols in the final executable, so 936 // there will always be undefined symbols in intermediate libraries. 937 _, flags.Global.LdFlags = removeFromList("-Wl,--no-undefined", flags.Global.LdFlags) 938 } 939 940 if !ctx.toolchain().Bionic() { 941 // non-Bionic toolchain prebuilts are missing UBSan's vptr and function san. 942 // Musl toolchain prebuilts have vptr and function sanitizers, but enabling them 943 // implicitly enables RTTI which causes RTTI mismatch issues with dependencies. 944 945 flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize=vptr,function") 946 } 947 948 if Bool(sanProps.Fuzzer) { 949 // When fuzzing, we wish to crash with diagnostics on any bug. 950 flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-trap=all", "-fno-sanitize-recover=all") 951 } else if ctx.Host() { 952 flags.Local.CFlags = append(flags.Local.CFlags, hostOnlySanitizeFlags...) 953 } else { 954 flags.Local.CFlags = append(flags.Local.CFlags, deviceOnlySanitizeFlags...) 955 } 956 957 if enableMinimalRuntime(s) { 958 flags.Local.CFlags = append(flags.Local.CFlags, strings.Join(minimalRuntimeFlags, " ")) 959 } 960 961 // http://b/119329758, Android core does not boot up with this sanitizer yet. 962 if toDisableImplicitIntegerChange(flags.Local.CFlags) { 963 flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize=implicit-integer-sign-change") 964 } 965 // http://b/171275751, Android doesn't build with this sanitizer yet. 966 if toDisableUnsignedShiftBaseChange(flags.Local.CFlags) { 967 flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize=unsigned-shift-base") 968 } 969 } 970 971 if len(s.Properties.DiagSanitizers) > 0 { 972 flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-trap="+strings.Join(s.Properties.DiagSanitizers, ",")) 973 } 974 // FIXME: enable RTTI if diag + (cfi or vptr) 975 976 if s.Properties.Sanitize.Recover != nil { 977 flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize-recover="+ 978 strings.Join(s.Properties.Sanitize.Recover, ",")) 979 } 980 981 if s.Properties.Sanitize.Diag.No_recover != nil { 982 flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-recover="+ 983 strings.Join(s.Properties.Sanitize.Diag.No_recover, ",")) 984 } 985 986 blocklist := android.OptionalPathForModuleSrc(ctx, s.Properties.Sanitize.Blocklist) 987 if blocklist.Valid() { 988 flags.Local.CFlags = append(flags.Local.CFlags, sanitizeIgnorelistPrefix+blocklist.String()) 989 flags.CFlagsDeps = append(flags.CFlagsDeps, blocklist.Path()) 990 } 991 992 return flags 993} 994 995func (s *sanitize) prepareAndroidMKProviderInfo(config android.Config, ctx AndroidMkContext, entries *android.AndroidMkInfo) { 996 // Add a suffix for cfi/hwasan/scs-enabled static/header libraries to allow surfacing 997 // both the sanitized and non-sanitized variants to make without a name conflict. 998 if entries.Class == "STATIC_LIBRARIES" || entries.Class == "HEADER_LIBRARIES" { 999 if Bool(s.Properties.SanitizeMutated.Cfi) { 1000 entries.SubName += ".cfi" 1001 } 1002 if Bool(s.Properties.SanitizeMutated.Hwaddress) { 1003 entries.SubName += ".hwasan" 1004 } 1005 if Bool(s.Properties.SanitizeMutated.Scs) { 1006 entries.SubName += ".scs" 1007 } 1008 } 1009} 1010 1011func (s *sanitize) inSanitizerDir() bool { 1012 return s.Properties.InSanitizerDir 1013} 1014 1015// getSanitizerBoolPtr returns the SanitizerTypes associated bool pointer from SanitizeProperties. 1016func (s *sanitize) getSanitizerBoolPtr(t SanitizerType) *bool { 1017 switch t { 1018 case Asan: 1019 return s.Properties.SanitizeMutated.Address 1020 case Hwasan: 1021 return s.Properties.SanitizeMutated.Hwaddress 1022 case tsan: 1023 return s.Properties.SanitizeMutated.Thread 1024 case intOverflow: 1025 return s.Properties.SanitizeMutated.Integer_overflow 1026 case cfi: 1027 return s.Properties.SanitizeMutated.Cfi 1028 case scs: 1029 return s.Properties.SanitizeMutated.Scs 1030 case Memtag_heap: 1031 return s.Properties.SanitizeMutated.Memtag_heap 1032 case Memtag_stack: 1033 return s.Properties.SanitizeMutated.Memtag_stack 1034 case Memtag_globals: 1035 return s.Properties.SanitizeMutated.Memtag_globals 1036 case Fuzzer: 1037 return s.Properties.SanitizeMutated.Fuzzer 1038 default: 1039 panic(fmt.Errorf("unknown SanitizerType %d", t)) 1040 } 1041} 1042 1043// isUnsanitizedVariant returns true if no sanitizers are enabled. 1044func (sanitize *sanitize) isUnsanitizedVariant() bool { 1045 return !sanitize.isSanitizerEnabled(Asan) && 1046 !sanitize.isSanitizerEnabled(Hwasan) && 1047 !sanitize.isSanitizerEnabled(tsan) && 1048 !sanitize.isSanitizerEnabled(cfi) && 1049 !sanitize.isSanitizerEnabled(scs) && 1050 !sanitize.isSanitizerEnabled(Memtag_heap) && 1051 !sanitize.isSanitizerEnabled(Memtag_stack) && 1052 !sanitize.isSanitizerEnabled(Memtag_globals) && 1053 !sanitize.isSanitizerEnabled(Fuzzer) 1054} 1055 1056// isVariantOnProductionDevice returns true if variant is for production devices (no non-production sanitizers enabled). 1057func (sanitize *sanitize) isVariantOnProductionDevice() bool { 1058 return !sanitize.isSanitizerEnabled(Asan) && 1059 !sanitize.isSanitizerEnabled(Hwasan) && 1060 !sanitize.isSanitizerEnabled(tsan) && 1061 !sanitize.isSanitizerEnabled(Fuzzer) 1062} 1063 1064func (sanitize *sanitize) SetSanitizer(t SanitizerType, b bool) { 1065 bPtr := proptools.BoolPtr(b) 1066 if !b { 1067 bPtr = nil 1068 } 1069 switch t { 1070 case Asan: 1071 sanitize.Properties.SanitizeMutated.Address = bPtr 1072 // For ASAN variant, we need to disable Memtag_stack 1073 sanitize.Properties.SanitizeMutated.Memtag_stack = nil 1074 sanitize.Properties.SanitizeMutated.Memtag_globals = nil 1075 case Hwasan: 1076 sanitize.Properties.SanitizeMutated.Hwaddress = bPtr 1077 // For HWAsan variant, we need to disable Memtag_stack 1078 sanitize.Properties.SanitizeMutated.Memtag_stack = nil 1079 sanitize.Properties.SanitizeMutated.Memtag_globals = nil 1080 case tsan: 1081 sanitize.Properties.SanitizeMutated.Thread = bPtr 1082 case intOverflow: 1083 sanitize.Properties.SanitizeMutated.Integer_overflow = bPtr 1084 case cfi: 1085 sanitize.Properties.SanitizeMutated.Cfi = bPtr 1086 case scs: 1087 sanitize.Properties.SanitizeMutated.Scs = bPtr 1088 case Memtag_heap: 1089 sanitize.Properties.SanitizeMutated.Memtag_heap = bPtr 1090 case Memtag_stack: 1091 sanitize.Properties.SanitizeMutated.Memtag_stack = bPtr 1092 // We do not need to disable ASAN or HWASan here, as there is no Memtag_stack variant. 1093 case Memtag_globals: 1094 sanitize.Properties.Sanitize.Memtag_globals = bPtr 1095 case Fuzzer: 1096 sanitize.Properties.SanitizeMutated.Fuzzer = bPtr 1097 default: 1098 panic(fmt.Errorf("unknown SanitizerType %d", t)) 1099 } 1100 if b { 1101 sanitize.Properties.SanitizerEnabled = true 1102 } 1103} 1104 1105// Check if the sanitizer is explicitly disabled (as opposed to nil by 1106// virtue of not being set). 1107func (sanitize *sanitize) isSanitizerExplicitlyDisabled(t SanitizerType) bool { 1108 if sanitize == nil { 1109 return false 1110 } 1111 1112 sanitizerVal := sanitize.getSanitizerBoolPtr(t) 1113 return sanitizerVal != nil && *sanitizerVal == false 1114} 1115 1116// There isn't an analog of the method above (ie:isSanitizerExplicitlyEnabled) 1117// because enabling a sanitizer either directly (via the blueprint) or 1118// indirectly (via a mutator) sets the bool ptr to true, and you can't 1119// distinguish between the cases. It isn't needed though - both cases can be 1120// treated identically. 1121func (s *sanitize) isSanitizerEnabled(t SanitizerType) bool { 1122 if s == nil { 1123 return false 1124 } 1125 if s.Properties.ForceDisable || proptools.Bool(s.Properties.SanitizeMutated.Never) { 1126 return false 1127 } 1128 1129 sanitizerVal := s.getSanitizerBoolPtr(t) 1130 return sanitizerVal != nil && *sanitizerVal == true 1131} 1132 1133// IsSanitizableDependencyTag returns true if the dependency tag is sanitizable. 1134func IsSanitizableDependencyTag(tag blueprint.DependencyTag) bool { 1135 switch t := tag.(type) { 1136 case dependencyTag: 1137 return t == reuseObjTag || t == objDepTag 1138 case libraryDependencyTag: 1139 return true 1140 default: 1141 return false 1142 } 1143} 1144 1145func (m *Module) SanitizableDepTagChecker() SantizableDependencyTagChecker { 1146 return IsSanitizableDependencyTag 1147} 1148 1149type sanitizerSplitMutator struct { 1150 sanitizer SanitizerType 1151} 1152 1153// If an APEX is sanitized or not depends on whether it contains at least one 1154// sanitized module. Transition mutators cannot propagate information up the 1155// dependency graph this way, so we need an auxiliary mutator to do so. 1156func (s *sanitizerSplitMutator) markSanitizableApexesMutator(ctx android.BottomUpMutatorContext) { 1157 if sanitizeable, ok := ctx.Module().(Sanitizeable); ok { 1158 enabled := sanitizeable.IsSanitizerEnabled(ctx.Config(), s.sanitizer.name()) 1159 ctx.VisitDirectDeps(func(dep android.Module) { 1160 if c, ok := dep.(PlatformSanitizeable); ok && c.IsSanitizerEnabled(s.sanitizer) { 1161 enabled = true 1162 } 1163 }) 1164 1165 if enabled { 1166 sanitizeable.EnableSanitizer(s.sanitizer.name()) 1167 } 1168 } 1169} 1170 1171func (s *sanitizerSplitMutator) Split(ctx android.BaseModuleContext) []string { 1172 if c, ok := ctx.Module().(PlatformSanitizeable); ok && c.SanitizePropDefined() { 1173 // If the given sanitizer is not requested in the .bp file for a module, it 1174 // won't automatically build the sanitized variation. 1175 if !c.IsSanitizerEnabled(s.sanitizer) { 1176 return []string{""} 1177 } 1178 1179 if c.Binary() { 1180 // If a sanitizer is enabled for a binary, we do not build the version 1181 // without the sanitizer 1182 return []string{s.sanitizer.variationName()} 1183 } else if c.StaticallyLinked() || c.Header() { 1184 // For static libraries, we build both versions. Some Make modules 1185 // apparently depend on this behavior. 1186 return []string{"", s.sanitizer.variationName()} 1187 } else { 1188 // We only build the requested variation of dynamic libraries 1189 return []string{s.sanitizer.variationName()} 1190 } 1191 } 1192 1193 if _, ok := ctx.Module().(JniSanitizeable); ok { 1194 // TODO: this should call into JniSanitizable.IsSanitizerEnabledForJni but 1195 // that is short-circuited for now 1196 return []string{""} 1197 } 1198 1199 // If an APEX has a sanitized dependency, we build the APEX in the sanitized 1200 // variation. This is useful because such APEXes require extra dependencies. 1201 if sanitizeable, ok := ctx.Module().(Sanitizeable); ok { 1202 enabled := sanitizeable.IsSanitizerEnabled(ctx.Config(), s.sanitizer.name()) 1203 if enabled { 1204 return []string{s.sanitizer.variationName()} 1205 } else { 1206 return []string{""} 1207 } 1208 } 1209 1210 return []string{""} 1211} 1212 1213func (s *sanitizerSplitMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string { 1214 if c, ok := ctx.Module().(PlatformSanitizeable); ok { 1215 if !c.SanitizableDepTagChecker()(ctx.DepTag()) { 1216 // If the dependency is through a non-sanitizable tag, use the 1217 // non-sanitized variation 1218 return "" 1219 } 1220 1221 return sourceVariation 1222 } else if _, ok := ctx.Module().(JniSanitizeable); ok { 1223 // TODO: this should call into JniSanitizable.IsSanitizerEnabledForJni but 1224 // that is short-circuited for now 1225 return "" 1226 } else { 1227 // Otherwise, do not rock the boat. 1228 return sourceVariation 1229 } 1230} 1231 1232func (s *sanitizerSplitMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string { 1233 if d, ok := ctx.Module().(PlatformSanitizeable); ok { 1234 if !d.SanitizePropDefined() || 1235 d.SanitizeNever() || 1236 d.IsSanitizerExplicitlyDisabled(s.sanitizer) || 1237 !d.SanitizerSupported(s.sanitizer) { 1238 // If a module opts out of a sanitizer, use its non-sanitized variation 1239 return "" 1240 } 1241 1242 // Binaries are always built in the variation they requested. 1243 if d.Binary() { 1244 if d.IsSanitizerEnabled(s.sanitizer) { 1245 return s.sanitizer.variationName() 1246 } else { 1247 return "" 1248 } 1249 } 1250 1251 // If a shared library requests to be sanitized, it will be built for that 1252 // sanitizer. Otherwise, some sanitizers propagate through shared library 1253 // dependency edges, some do not. 1254 if !d.StaticallyLinked() && !d.Header() { 1255 if d.IsSanitizerEnabled(s.sanitizer) { 1256 return s.sanitizer.variationName() 1257 } 1258 1259 // Some sanitizers do not propagate to shared dependencies 1260 if !s.sanitizer.shouldPropagateToSharedLibraryDeps() { 1261 return "" 1262 } 1263 } 1264 1265 // Static and header libraries inherit whether they are sanitized from the 1266 // module they are linked into 1267 return incomingVariation 1268 } else if d, ok := ctx.Module().(Sanitizeable); ok { 1269 // If an APEX contains a sanitized module, it will be built in the variation 1270 // corresponding to that sanitizer. 1271 enabled := d.IsSanitizerEnabled(ctx.Config(), s.sanitizer.name()) 1272 if enabled { 1273 return s.sanitizer.variationName() 1274 } 1275 1276 return incomingVariation 1277 } 1278 1279 return "" 1280} 1281 1282func (s *sanitizerSplitMutator) Mutate(mctx android.BottomUpMutatorContext, variationName string) { 1283 sanitizerVariation := variationName == s.sanitizer.variationName() 1284 1285 if c, ok := mctx.Module().(PlatformSanitizeable); ok && c.SanitizePropDefined() { 1286 sanitizerEnabled := c.IsSanitizerEnabled(s.sanitizer) 1287 1288 oneMakeVariation := false 1289 if c.StaticallyLinked() || c.Header() { 1290 if s.sanitizer != cfi && s.sanitizer != scs && s.sanitizer != Hwasan { 1291 // These sanitizers export only one variation to Make. For the rest, 1292 // Make targets can depend on both the sanitized and non-sanitized 1293 // versions. 1294 oneMakeVariation = true 1295 } 1296 } else if !c.Binary() { 1297 // Shared library. These are the sanitizers that do propagate through shared 1298 // library dependencies and therefore can cause multiple variations of a 1299 // shared library to be built. 1300 if s.sanitizer != cfi && s.sanitizer != Hwasan && s.sanitizer != scs && s.sanitizer != Asan { 1301 oneMakeVariation = true 1302 } 1303 } 1304 1305 if oneMakeVariation { 1306 if sanitizerEnabled != sanitizerVariation { 1307 c.SetPreventInstall() 1308 c.SetHideFromMake() 1309 } 1310 } 1311 1312 if sanitizerVariation { 1313 c.SetSanitizer(s.sanitizer, true) 1314 1315 // CFI is incompatible with ASAN so disable it in ASAN variations 1316 if s.sanitizer.incompatibleWithCfi() { 1317 cfiSupported := mctx.Module().(PlatformSanitizeable).SanitizerSupported(cfi) 1318 if mctx.Device() && cfiSupported { 1319 c.SetSanitizer(cfi, false) 1320 } 1321 } 1322 1323 // locate the asan libraries under /data/asan 1324 if !c.Binary() && !c.StaticallyLinked() && !c.Header() && mctx.Device() && s.sanitizer == Asan && sanitizerEnabled { 1325 c.SetInSanitizerDir() 1326 } 1327 1328 if c.StaticallyLinked() && c.ExportedToMake() { 1329 if s.sanitizer == Hwasan { 1330 hwasanStaticLibs(mctx.Config()).add(c, c.Module().Name()) 1331 } else if s.sanitizer == cfi { 1332 cfiStaticLibs(mctx.Config()).add(c, c.Module().Name()) 1333 } else if s.sanitizer == Memtag_stack { 1334 memtagStackStaticLibs(mctx.Config()).add(c, c.Module().Name()) 1335 } 1336 } 1337 } else if c.IsSanitizerEnabled(s.sanitizer) { 1338 // Disable the sanitizer for the non-sanitized variation 1339 c.SetSanitizer(s.sanitizer, false) 1340 } 1341 } else if sanitizeable, ok := mctx.Module().(Sanitizeable); ok { 1342 // If an APEX has sanitized dependencies, it gets a few more dependencies 1343 if sanitizerVariation { 1344 sanitizeable.AddSanitizerDependencies(mctx, s.sanitizer.name()) 1345 } 1346 } 1347} 1348 1349func (c *Module) SanitizeNever() bool { 1350 return c.sanitize.Properties.ForceDisable || Bool(c.sanitize.Properties.SanitizeMutated.Never) 1351} 1352 1353func (c *Module) IsSanitizerExplicitlyDisabled(t SanitizerType) bool { 1354 return c.sanitize.isSanitizerExplicitlyDisabled(t) 1355} 1356 1357// Propagate the ubsan minimal runtime dependency when there are integer overflow sanitized static dependencies. 1358func sanitizerRuntimeDepsMutator(mctx android.BottomUpMutatorContext) { 1359 // Change this to PlatformSanitizable when/if non-cc modules support ubsan sanitizers. 1360 if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil { 1361 if c.sanitize.Properties.ForceDisable { 1362 return 1363 } 1364 isSanitizableDependencyTag := c.SanitizableDepTagChecker() 1365 mctx.WalkDeps(func(child, parent android.Module) bool { 1366 if !isSanitizableDependencyTag(mctx.OtherModuleDependencyTag(child)) { 1367 return false 1368 } 1369 1370 d, ok := child.(*Module) 1371 if !ok || !d.static() { 1372 return false 1373 } 1374 if d.sanitize != nil && !d.sanitize.Properties.ForceDisable { 1375 if enableMinimalRuntime(d.sanitize) { 1376 // If a static dependency is built with the minimal runtime, 1377 // make sure we include the ubsan minimal runtime. 1378 c.sanitize.Properties.MinimalRuntimeDep = true 1379 } else if enableUbsanRuntime(d.sanitize) { 1380 // If a static dependency runs with full ubsan diagnostics, 1381 // make sure we include the ubsan runtime. 1382 c.sanitize.Properties.UbsanRuntimeDep = true 1383 } 1384 1385 if c.sanitize.Properties.MinimalRuntimeDep && 1386 c.sanitize.Properties.UbsanRuntimeDep { 1387 // both flags that this mutator might set are true, so don't bother recursing 1388 return false 1389 } 1390 1391 if c.Os() == android.Linux { 1392 c.sanitize.Properties.BuiltinsDep = true 1393 } 1394 1395 return true 1396 } 1397 1398 return false 1399 }) 1400 } 1401} 1402 1403// Add the dependency to the runtime library for each of the sanitizer variants 1404func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) { 1405 if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil { 1406 if !c.Enabled(mctx) { 1407 return 1408 } 1409 if c.sanitize.Properties.ForceDisable { 1410 return 1411 } 1412 1413 var sanitizers []string 1414 var diagSanitizers []string 1415 1416 sanProps := &c.sanitize.Properties.SanitizeMutated 1417 1418 if Bool(sanProps.All_undefined) { 1419 sanitizers = append(sanitizers, "undefined") 1420 } else { 1421 if Bool(sanProps.Undefined) { 1422 sanitizers = append(sanitizers, 1423 "bool", 1424 "integer-divide-by-zero", 1425 "return", 1426 "returns-nonnull-attribute", 1427 "shift-exponent", 1428 "unreachable", 1429 "vla-bound", 1430 // TODO(danalbert): The following checks currently have compiler performance issues. 1431 //"alignment", 1432 //"bounds", 1433 //"enum", 1434 //"float-cast-overflow", 1435 //"float-divide-by-zero", 1436 //"nonnull-attribute", 1437 //"null", 1438 //"shift-base", 1439 //"signed-integer-overflow", 1440 ) 1441 1442 if mctx.Config().ReleaseBuildObjectSizeSanitizer() { 1443 sanitizers = append(sanitizers, "object-size") 1444 } 1445 } 1446 sanitizers = append(sanitizers, sanProps.Misc_undefined...) 1447 } 1448 1449 if Bool(sanProps.Diag.Undefined) { 1450 diagSanitizers = append(diagSanitizers, "undefined") 1451 } 1452 1453 diagSanitizers = append(diagSanitizers, sanProps.Diag.Misc_undefined...) 1454 1455 if Bool(sanProps.Address) { 1456 sanitizers = append(sanitizers, "address") 1457 diagSanitizers = append(diagSanitizers, "address") 1458 } 1459 1460 if Bool(sanProps.Hwaddress) { 1461 sanitizers = append(sanitizers, "hwaddress") 1462 } 1463 1464 if Bool(sanProps.Thread) { 1465 sanitizers = append(sanitizers, "thread") 1466 } 1467 1468 if Bool(sanProps.Safestack) { 1469 sanitizers = append(sanitizers, "safe-stack") 1470 } 1471 1472 if Bool(sanProps.Cfi) { 1473 sanitizers = append(sanitizers, "cfi") 1474 1475 if Bool(sanProps.Diag.Cfi) { 1476 diagSanitizers = append(diagSanitizers, "cfi") 1477 } 1478 } 1479 1480 if Bool(sanProps.Integer_overflow) { 1481 sanitizers = append(sanitizers, "unsigned-integer-overflow") 1482 sanitizers = append(sanitizers, "signed-integer-overflow") 1483 if Bool(sanProps.Diag.Integer_overflow) { 1484 diagSanitizers = append(diagSanitizers, "unsigned-integer-overflow") 1485 diagSanitizers = append(diagSanitizers, "signed-integer-overflow") 1486 } 1487 } 1488 1489 if Bool(sanProps.Scudo) { 1490 sanitizers = append(sanitizers, "scudo") 1491 } 1492 1493 if Bool(sanProps.Scs) { 1494 sanitizers = append(sanitizers, "shadow-call-stack") 1495 } 1496 1497 if Bool(sanProps.Memtag_heap) && c.Binary() { 1498 sanitizers = append(sanitizers, "memtag-heap") 1499 } 1500 1501 if Bool(sanProps.Memtag_stack) { 1502 sanitizers = append(sanitizers, "memtag-stack") 1503 } 1504 1505 if Bool(sanProps.Memtag_globals) { 1506 sanitizers = append(sanitizers, "memtag-globals") 1507 } 1508 1509 if Bool(sanProps.Fuzzer) { 1510 sanitizers = append(sanitizers, "fuzzer-no-link") 1511 } 1512 1513 // Save the list of sanitizers. These will be used again when generating 1514 // the build rules (for Cflags, etc.) 1515 c.sanitize.Properties.Sanitizers = sanitizers 1516 c.sanitize.Properties.DiagSanitizers = diagSanitizers 1517 1518 // TODO(b/150822854) Hosts have a different default behavior and assume the runtime library is used. 1519 if c.Host() { 1520 diagSanitizers = sanitizers 1521 } 1522 1523 addStaticDeps := func(dep string, hideSymbols bool) { 1524 // static executable gets static runtime libs 1525 depTag := libraryDependencyTag{Kind: staticLibraryDependency, unexportedSymbols: hideSymbols} 1526 variations := append(mctx.Target().Variations(), 1527 blueprint.Variation{Mutator: "link", Variation: "static"}) 1528 if c.Device() { 1529 variations = append(variations, c.ImageVariation()) 1530 } 1531 if c.UseSdk() { 1532 variations = append(variations, 1533 blueprint.Variation{Mutator: "sdk", Variation: "sdk"}) 1534 } 1535 mctx.AddFarVariationDependencies(variations, depTag, dep) 1536 } 1537 1538 // Determine the runtime library required 1539 runtimeSharedLibrary := "" 1540 toolchain := c.toolchain(mctx) 1541 if Bool(sanProps.Address) { 1542 if toolchain.Musl() || (c.staticBinary() && toolchain.Bionic()) { 1543 // Use a static runtime for musl to match what clang does for glibc. 1544 addStaticDeps(config.AddressSanitizerStaticRuntimeLibrary(), false) 1545 addStaticDeps(config.AddressSanitizerCXXStaticRuntimeLibrary(), false) 1546 } else { 1547 runtimeSharedLibrary = config.AddressSanitizerRuntimeLibrary() 1548 } 1549 } else if Bool(sanProps.Hwaddress) { 1550 if c.staticBinary() { 1551 addStaticDeps(config.HWAddressSanitizerStaticLibrary(), true) 1552 addStaticDeps("libdl", false) 1553 } else { 1554 runtimeSharedLibrary = config.HWAddressSanitizerRuntimeLibrary() 1555 } 1556 } else if Bool(sanProps.Thread) { 1557 runtimeSharedLibrary = config.ThreadSanitizerRuntimeLibrary() 1558 } else if Bool(sanProps.Scudo) { 1559 if len(diagSanitizers) == 0 && !c.sanitize.Properties.UbsanRuntimeDep { 1560 runtimeSharedLibrary = config.ScudoMinimalRuntimeLibrary() 1561 } else { 1562 runtimeSharedLibrary = config.ScudoRuntimeLibrary() 1563 } 1564 } else if len(diagSanitizers) > 0 || c.sanitize.Properties.UbsanRuntimeDep || 1565 Bool(sanProps.Fuzzer) || 1566 Bool(sanProps.Undefined) || 1567 Bool(sanProps.All_undefined) { 1568 if toolchain.Musl() || c.staticBinary() { 1569 // Use a static runtime for static binaries. For sanitized glibc binaries the runtime is 1570 // added automatically by clang, but for static glibc binaries that are not sanitized but 1571 // have a sanitized dependency the runtime needs to be added manually. 1572 // Also manually add a static runtime for musl to match what clang does for glibc. 1573 // Otherwise dlopening libraries that depend on libclang_rt.ubsan_standalone.so fails with: 1574 // Error relocating ...: initial-exec TLS resolves to dynamic definition 1575 addStaticDeps(config.UndefinedBehaviorSanitizerRuntimeLibrary()+".static", true) 1576 } else { 1577 runtimeSharedLibrary = config.UndefinedBehaviorSanitizerRuntimeLibrary() 1578 } 1579 } 1580 1581 if enableMinimalRuntime(c.sanitize) || c.sanitize.Properties.MinimalRuntimeDep { 1582 addStaticDeps(config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(), true) 1583 } 1584 if c.sanitize.Properties.BuiltinsDep { 1585 addStaticDeps(config.BuiltinsRuntimeLibrary(), true) 1586 } 1587 1588 if runtimeSharedLibrary != "" && (toolchain.Bionic() || toolchain.Musl()) { 1589 // UBSan is supported on non-bionic linux host builds as well 1590 1591 // Adding dependency to the runtime library. We are using *FarVariation* 1592 // because the runtime libraries themselves are not mutated by sanitizer 1593 // mutators and thus don't have sanitizer variants whereas this module 1594 // has been already mutated. 1595 // 1596 // Note that by adding dependency with {static|shared}DepTag, the lib is 1597 // added to libFlags and LOCAL_SHARED_LIBRARIES by cc.Module 1598 if c.staticBinary() { 1599 // Most sanitizers are either disabled for static binaries or have already 1600 // handled the static binary case above through a direct call to addStaticDeps. 1601 // If not, treat the runtime shared library as a static library and hope for 1602 // the best. 1603 addStaticDeps(runtimeSharedLibrary, true) 1604 } else if !c.static() && !c.Header() { 1605 // Skip apex dependency check for sharedLibraryDependency 1606 // when sanitizer diags are enabled. Skipping the check will allow 1607 // building with diag libraries without having to list the 1608 // dependency in Apex's allowed_deps file. 1609 diagEnabled := len(diagSanitizers) > 0 1610 // dynamic executable and shared libs get shared runtime libs 1611 depTag := libraryDependencyTag{ 1612 Kind: sharedLibraryDependency, 1613 Order: earlyLibraryDependency, 1614 1615 skipApexAllowedDependenciesCheck: diagEnabled, 1616 } 1617 variations := append(mctx.Target().Variations(), 1618 blueprint.Variation{Mutator: "link", Variation: "shared"}) 1619 if c.Device() { 1620 variations = append(variations, c.ImageVariation()) 1621 } 1622 if c.UseSdk() { 1623 variations = append(variations, 1624 blueprint.Variation{Mutator: "sdk", Variation: "sdk"}) 1625 } 1626 AddSharedLibDependenciesWithVersions(mctx, c, variations, depTag, runtimeSharedLibrary, "", true) 1627 } 1628 // static lib does not have dependency to the runtime library. The 1629 // dependency will be added to the executables or shared libs using 1630 // the static lib. 1631 } 1632 } 1633} 1634 1635type Sanitizeable interface { 1636 android.Module 1637 IsSanitizerEnabled(config android.Config, sanitizerName string) bool 1638 EnableSanitizer(sanitizerName string) 1639 AddSanitizerDependencies(ctx android.BottomUpMutatorContext, sanitizerName string) 1640} 1641 1642type JniSanitizeable interface { 1643 android.Module 1644 IsSanitizerEnabledForJni(ctx android.BaseModuleContext, sanitizerName string) bool 1645} 1646 1647func (c *Module) MinimalRuntimeDep() bool { 1648 return c.sanitize.Properties.MinimalRuntimeDep 1649} 1650 1651func (c *Module) UbsanRuntimeDep() bool { 1652 return c.sanitize.Properties.UbsanRuntimeDep 1653} 1654 1655func (c *Module) SanitizePropDefined() bool { 1656 return c.sanitize != nil 1657} 1658 1659func (c *Module) IsSanitizerEnabled(t SanitizerType) bool { 1660 return c.sanitize.isSanitizerEnabled(t) 1661} 1662 1663func (c *Module) StaticallyLinked() bool { 1664 return c.static() 1665} 1666 1667func (c *Module) SetInSanitizerDir() { 1668 if c.sanitize != nil { 1669 c.sanitize.Properties.InSanitizerDir = true 1670 } 1671} 1672 1673func (c *Module) SetSanitizer(t SanitizerType, b bool) { 1674 if c.sanitize != nil { 1675 c.sanitize.SetSanitizer(t, b) 1676 } 1677} 1678 1679var _ PlatformSanitizeable = (*Module)(nil) 1680 1681type sanitizerStaticLibsMap struct { 1682 // libsMap contains one list of modules per each image and each arch. 1683 // e.g. libs[vendor]["arm"] contains arm modules installed to vendor 1684 libsMap map[ImageVariantType]map[string][]string 1685 libsMapLock sync.Mutex 1686 sanitizerType SanitizerType 1687} 1688 1689func newSanitizerStaticLibsMap(t SanitizerType) *sanitizerStaticLibsMap { 1690 return &sanitizerStaticLibsMap{ 1691 sanitizerType: t, 1692 libsMap: make(map[ImageVariantType]map[string][]string), 1693 } 1694} 1695 1696// Add the current module to sanitizer static libs maps 1697// Each module should pass its exported name as names of Make and Soong can differ. 1698func (s *sanitizerStaticLibsMap) add(c LinkableInterface, name string) { 1699 image := GetImageVariantType(c) 1700 arch := c.Module().Target().Arch.ArchType.String() 1701 1702 s.libsMapLock.Lock() 1703 defer s.libsMapLock.Unlock() 1704 1705 if _, ok := s.libsMap[image]; !ok { 1706 s.libsMap[image] = make(map[string][]string) 1707 } 1708 1709 s.libsMap[image][arch] = append(s.libsMap[image][arch], name) 1710} 1711 1712// Exports makefile variables in the following format: 1713// SOONG_{sanitizer}_{image}_{arch}_STATIC_LIBRARIES 1714// e.g. SOONG_cfi_core_x86_STATIC_LIBRARIES 1715// These are to be used by use_soong_sanitized_static_libraries. 1716// See build/make/core/binary.mk for more details. 1717func (s *sanitizerStaticLibsMap) exportToMake(ctx android.MakeVarsContext) { 1718 for _, image := range android.SortedKeys(s.libsMap) { 1719 archMap := s.libsMap[ImageVariantType(image)] 1720 for _, arch := range android.SortedKeys(archMap) { 1721 libs := archMap[arch] 1722 sort.Strings(libs) 1723 1724 key := fmt.Sprintf( 1725 "SOONG_%s_%s_%s_STATIC_LIBRARIES", 1726 s.sanitizerType.variationName(), 1727 image, // already upper 1728 arch) 1729 1730 ctx.Strict(key, strings.Join(libs, " ")) 1731 } 1732 } 1733} 1734 1735var cfiStaticLibsKey = android.NewOnceKey("cfiStaticLibs") 1736 1737func cfiStaticLibs(config android.Config) *sanitizerStaticLibsMap { 1738 return config.Once(cfiStaticLibsKey, func() interface{} { 1739 return newSanitizerStaticLibsMap(cfi) 1740 }).(*sanitizerStaticLibsMap) 1741} 1742 1743var hwasanStaticLibsKey = android.NewOnceKey("hwasanStaticLibs") 1744 1745func hwasanStaticLibs(config android.Config) *sanitizerStaticLibsMap { 1746 return config.Once(hwasanStaticLibsKey, func() interface{} { 1747 return newSanitizerStaticLibsMap(Hwasan) 1748 }).(*sanitizerStaticLibsMap) 1749} 1750 1751var memtagStackStaticLibsKey = android.NewOnceKey("memtagStackStaticLibs") 1752 1753func memtagStackStaticLibs(config android.Config) *sanitizerStaticLibsMap { 1754 return config.Once(memtagStackStaticLibsKey, func() interface{} { 1755 return newSanitizerStaticLibsMap(Memtag_stack) 1756 }).(*sanitizerStaticLibsMap) 1757} 1758 1759func enableMinimalRuntime(sanitize *sanitize) bool { 1760 if sanitize.isSanitizerEnabled(Asan) { 1761 return false 1762 } else if sanitize.isSanitizerEnabled(Hwasan) { 1763 return false 1764 } else if sanitize.isSanitizerEnabled(Fuzzer) { 1765 return false 1766 } 1767 1768 if enableUbsanRuntime(sanitize) { 1769 return false 1770 } 1771 1772 sanitizeProps := &sanitize.Properties.SanitizeMutated 1773 if Bool(sanitizeProps.Diag.Cfi) { 1774 return false 1775 } 1776 1777 return Bool(sanitizeProps.Integer_overflow) || 1778 len(sanitizeProps.Misc_undefined) > 0 || 1779 Bool(sanitizeProps.Undefined) || 1780 Bool(sanitizeProps.All_undefined) 1781} 1782 1783func (m *Module) UbsanRuntimeNeeded() bool { 1784 return enableUbsanRuntime(m.sanitize) 1785} 1786 1787func (m *Module) MinimalRuntimeNeeded() bool { 1788 return enableMinimalRuntime(m.sanitize) 1789} 1790 1791func enableUbsanRuntime(sanitize *sanitize) bool { 1792 sanitizeProps := &sanitize.Properties.SanitizeMutated 1793 return Bool(sanitizeProps.Diag.Integer_overflow) || 1794 Bool(sanitizeProps.Diag.Undefined) || 1795 len(sanitizeProps.Diag.Misc_undefined) > 0 1796} 1797 1798func cfiMakeVarsProvider(ctx android.MakeVarsContext) { 1799 cfiStaticLibs(ctx.Config()).exportToMake(ctx) 1800} 1801 1802func hwasanMakeVarsProvider(ctx android.MakeVarsContext) { 1803 hwasanStaticLibs(ctx.Config()).exportToMake(ctx) 1804} 1805 1806func memtagStackMakeVarsProvider(ctx android.MakeVarsContext) { 1807 memtagStackStaticLibs(ctx.Config()).exportToMake(ctx) 1808} 1809 1810type sanitizerLibrariesTxtModule struct { 1811 android.ModuleBase 1812 1813 outputFile android.Path 1814} 1815 1816var _ etc.PrebuiltEtcModule = (*sanitizerLibrariesTxtModule)(nil) 1817 1818func RegisterSanitizerLibrariesTxtType(ctx android.RegistrationContext) { 1819 ctx.RegisterModuleType("sanitizer_libraries_txt", sanitizerLibrariesTxtFactory) 1820} 1821 1822func sanitizerLibrariesTxtFactory() android.Module { 1823 m := &sanitizerLibrariesTxtModule{} 1824 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) 1825 return m 1826} 1827 1828type sanitizerLibraryDependencyTag struct { 1829 blueprint.BaseDependencyTag 1830 android.AlwaysAllowDisabledModuleDependencyTag 1831} 1832 1833var _ android.AllowDisabledModuleDependency = (*sanitizerLibraryDependencyTag)(nil) 1834 1835func (txt *sanitizerLibrariesTxtModule) DepsMutator(actx android.BottomUpMutatorContext) { 1836 targets := actx.Config().Targets[android.Android] 1837 depTag := sanitizerLibraryDependencyTag{} 1838 1839 for _, target := range targets { 1840 variation := append(target.Variations(), 1841 blueprint.Variation{Mutator: "image", Variation: ""}, 1842 blueprint.Variation{Mutator: "sdk", Variation: ""}, 1843 blueprint.Variation{Mutator: "link", Variation: "shared"}, 1844 ) 1845 for _, lib := range android.SortedStringValues(sanitizerVariables) { 1846 if actx.OtherModuleFarDependencyVariantExists(variation, lib) { 1847 actx.AddFarVariationDependencies(variation, depTag, lib) 1848 } 1849 1850 prebuiltLibName := "prebuilt_" + lib 1851 if actx.OtherModuleFarDependencyVariantExists(variation, prebuiltLibName) { 1852 actx.AddFarVariationDependencies(variation, depTag, prebuiltLibName) 1853 } 1854 } 1855 } 1856 1857} 1858 1859func (txt *sanitizerLibrariesTxtModule) getSanitizerLibs(ctx android.ModuleContext) string { 1860 var sanitizerLibStems []string 1861 1862 ctx.VisitDirectDepsIf(func(m android.Module) bool { 1863 if !m.Enabled(ctx) { 1864 return false 1865 } 1866 1867 ccModule, _ := m.(*Module) 1868 if ccModule == nil || ccModule.library == nil || !ccModule.library.shared() { 1869 return false 1870 } 1871 1872 targets := ctx.Config().Targets[android.Android] 1873 1874 for _, target := range targets { 1875 if m.Target().Os == target.Os && m.Target().Arch.ArchType == target.Arch.ArchType { 1876 return true 1877 } 1878 } 1879 1880 return false 1881 }, func(m android.Module) { 1882 ccModule, _ := m.(*Module) 1883 outputFile := ccModule.outputFile 1884 if outputFile.Valid() { 1885 sanitizerLibStems = append(sanitizerLibStems, outputFile.Path().Base()) 1886 } 1887 }) 1888 1889 sanitizerLibStems = android.SortedUniqueStrings(sanitizerLibStems) 1890 return strings.Join(sanitizerLibStems, "\n") 1891} 1892 1893func (txt *sanitizerLibrariesTxtModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { 1894 filename := txt.Name() 1895 1896 outputFile := android.PathForModuleOut(ctx, filename) 1897 android.WriteFileRule(ctx, outputFile, txt.getSanitizerLibs(ctx)) 1898 1899 installPath := android.PathForModuleInstall(ctx, "etc") 1900 ctx.InstallFile(installPath, filename, outputFile) 1901 1902 ctx.SetOutputFiles(android.Paths{outputFile}, "") 1903 txt.outputFile = outputFile 1904} 1905 1906func (txt *sanitizerLibrariesTxtModule) PrepareAndroidMKProviderInfo(config android.Config) *android.AndroidMkProviderInfo { 1907 return &android.AndroidMkProviderInfo{ 1908 PrimaryInfo: android.AndroidMkInfo{ 1909 Class: "ETC", 1910 OutputFile: android.OptionalPathForPath(txt.outputFile), 1911 }, 1912 } 1913} 1914 1915// PrebuiltEtcModule interface 1916func (txt *sanitizerLibrariesTxtModule) BaseDir() string { 1917 return "etc" 1918} 1919 1920// PrebuiltEtcModule interface 1921func (txt *sanitizerLibrariesTxtModule) SubDir() string { 1922 return "" 1923} 1924