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