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