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