Index: clang/include/clang/Basic/Sanitizers.def =================================================================== --- clang/include/clang/Basic/Sanitizers.def +++ clang/include/clang/Basic/Sanitizers.def @@ -44,8 +44,12 @@ // Kernel AddressSanitizer (KASan) SANITIZER("kernel-address", KernelAddress) +// Hardware-assisted AddressSanitizer SANITIZER("hwaddress", HWAddress) +// Kernel Hardware-assisted AddressSanitizer (KHWASan) +SANITIZER("kernel-hwaddress", KernelHWAddress) + // MemorySanitizer SANITIZER("memory", Memory) Index: clang/lib/CodeGen/BackendUtil.cpp =================================================================== --- clang/lib/CodeGen/BackendUtil.cpp +++ clang/lib/CodeGen/BackendUtil.cpp @@ -232,11 +232,14 @@ static void addKernelAddressSanitizerPasses(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) { + const PassManagerBuilderWrapper &BuilderWrapper = + static_cast(Builder); + const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts(); + bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::KernelAddress); PM.add(createAddressSanitizerFunctionPass( - /*CompileKernel*/ true, - /*Recover*/ true, /*UseAfterScope*/ false)); - PM.add(createAddressSanitizerModulePass(/*CompileKernel*/true, - /*Recover*/true)); + /*CompileKernel*/ true, Recover, /*UseAfterScope*/ false)); + PM.add(createAddressSanitizerModulePass( + /*CompileKernel*/ true, Recover)); } static void addHWAddressSanitizerPasses(const PassManagerBuilder &Builder, @@ -245,7 +248,16 @@ static_cast(Builder); const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts(); bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::HWAddress); - PM.add(createHWAddressSanitizerPass(Recover)); + PM.add(createHWAddressSanitizerPass(/*CompileKernel*/ false, Recover)); +} + +static void addKernelHWAddressSanitizerPasses(const PassManagerBuilder &Builder, + legacy::PassManagerBase &PM) { + const PassManagerBuilderWrapper &BuilderWrapper = + static_cast(Builder); + const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts(); + bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::KernelHWAddress); + PM.add(createHWAddressSanitizerPass(/*CompileKernel*/ true, Recover)); } static void addMemorySanitizerPass(const PassManagerBuilder &Builder, @@ -581,6 +593,13 @@ addHWAddressSanitizerPasses); } + if (LangOpts.Sanitize.has(SanitizerKind::KernelHWAddress)) { + PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast, + addKernelHWAddressSanitizerPasses); + PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, + addKernelHWAddressSanitizerPasses); + } + if (LangOpts.Sanitize.has(SanitizerKind::Memory)) { PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast, addMemorySanitizerPass); Index: clang/lib/CodeGen/CGDeclCXX.cpp =================================================================== --- clang/lib/CodeGen/CGDeclCXX.cpp +++ clang/lib/CodeGen/CGDeclCXX.cpp @@ -332,6 +332,10 @@ !isInSanitizerBlacklist(SanitizerKind::HWAddress, Fn, Loc)) Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress); + if (getLangOpts().Sanitize.has(SanitizerKind::KernelHWAddress) && + !isInSanitizerBlacklist(SanitizerKind::KernelHWAddress, Fn, Loc)) + Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress); + if (getLangOpts().Sanitize.has(SanitizerKind::Thread) && !isInSanitizerBlacklist(SanitizerKind::Thread, Fn, Loc)) Fn->addFnAttr(llvm::Attribute::SanitizeThread); Index: clang/lib/CodeGen/CodeGenFunction.cpp =================================================================== --- clang/lib/CodeGen/CodeGenFunction.cpp +++ clang/lib/CodeGen/CodeGenFunction.cpp @@ -853,13 +853,17 @@ SanOpts.set(SanitizerKind::KernelAddress, false); if (mask & SanitizerKind::KernelAddress) SanOpts.set(SanitizerKind::Address, false); + if (mask & SanitizerKind::HWAddress) + SanOpts.set(SanitizerKind::KernelHWAddress, false); + if (mask & SanitizerKind::KernelHWAddress) + SanOpts.set(SanitizerKind::HWAddress, false); } } // Apply sanitizer attributes to the function. if (SanOpts.hasOneOf(SanitizerKind::Address | SanitizerKind::KernelAddress)) Fn->addFnAttr(llvm::Attribute::SanitizeAddress); - if (SanOpts.hasOneOf(SanitizerKind::HWAddress)) + if (SanOpts.hasOneOf(SanitizerKind::HWAddress | SanitizerKind::KernelHWAddress)) Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress); if (SanOpts.has(SanitizerKind::Thread)) Fn->addFnAttr(llvm::Attribute::SanitizeThread); Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -1817,7 +1817,8 @@ StringRef Category) const { // For now globals can be blacklisted only in ASan and KASan. const SanitizerMask EnabledAsanMask = LangOpts.Sanitize.Mask & - (SanitizerKind::Address | SanitizerKind::KernelAddress | SanitizerKind::HWAddress); + (SanitizerKind::Address | SanitizerKind::KernelAddress | + SanitizerKind::HWAddress | SanitizerKind::KernelHWAddress); if (!EnabledAsanMask) return false; const auto &SanitizerBL = getContext().getSanitizerBlacklist(); Index: clang/lib/CodeGen/SanitizerMetadata.cpp =================================================================== --- clang/lib/CodeGen/SanitizerMetadata.cpp +++ clang/lib/CodeGen/SanitizerMetadata.cpp @@ -27,7 +27,8 @@ bool IsBlacklisted) { if (!CGM.getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address | SanitizerKind::KernelAddress | - SanitizerKind::HWAddress)) + SanitizerKind::HWAddress | + SanitizerKind::KernelHWAddress)) return; IsDynInit &= !CGM.isInSanitizerBlacklist(GV, Loc, Ty, "init"); IsBlacklisted |= CGM.isInSanitizerBlacklist(GV, Loc, Ty); @@ -60,7 +61,8 @@ const VarDecl &D, bool IsDynInit) { if (!CGM.getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address | SanitizerKind::KernelAddress | - SanitizerKind::HWAddress)) + SanitizerKind::HWAddress | + SanitizerKind::KernelHWAddress)) return; std::string QualName; llvm::raw_string_ostream OS(QualName); @@ -79,7 +81,8 @@ // instrumentation. if (CGM.getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address | SanitizerKind::KernelAddress | - SanitizerKind::HWAddress)) + SanitizerKind::HWAddress | + SanitizerKind::KernelHWAddress)) reportGlobalToASan(GV, SourceLocation(), "", QualType(), false, true); } Index: clang/lib/Driver/SanitizerArgs.cpp =================================================================== --- clang/lib/Driver/SanitizerArgs.cpp +++ clang/lib/Driver/SanitizerArgs.cpp @@ -33,11 +33,12 @@ NotAllowedWithMinimalRuntime = Vptr, RequiresPIE = DataFlow | HWAddress | Scudo, NeedsUnwindTables = Address | HWAddress | Thread | Memory | DataFlow, - SupportsCoverage = Address | HWAddress | KernelAddress | Memory | Leak | - Undefined | Integer | Nullability | DataFlow | Fuzzer | - FuzzerNoLink, + SupportsCoverage = Address | HWAddress | KernelAddress | KernelHWAddress | + Memory | Leak | Undefined | Integer | Nullability | + DataFlow | Fuzzer | FuzzerNoLink, RecoverableByDefault = Undefined | Integer | Nullability, Unrecoverable = Unreachable | Return, + AlwaysRecoverable = KernelAddress | KernelHWAddress, LegacyFsanitizeRecoverMask = Undefined | Integer, NeedsLTO = CFI, TrappingSupported = (Undefined & ~Vptr) | UnsignedIntegerOverflow | @@ -347,7 +348,10 @@ KernelAddress | Efficiency), std::make_pair(ShadowCallStack, Address | HWAddress | Leak | Thread | Memory | KernelAddress | Efficiency | - SafeStack)}; + SafeStack), + std::make_pair(KernelHWAddress, Address | HWAddress | Leak | Thread | + Memory | KernelAddress | Efficiency | + SafeStack | ShadowCallStack)}; // Enable toolchain specific default sanitizers if not explicitly disabled. SanitizerMask Default = TC.getDefaultSanitizers() & ~AllRemove; @@ -422,8 +426,9 @@ // default in ASan? // Parse -f(no-)?sanitize-recover flags. - SanitizerMask RecoverableKinds = RecoverableByDefault; + SanitizerMask RecoverableKinds = RecoverableByDefault | AlwaysRecoverable; SanitizerMask DiagnosedUnrecoverableKinds = 0; + SanitizerMask DiagnosedAlwaysRecoverableKinds = 0; for (const auto *Arg : Args) { const char *DeprecatedReplacement = nullptr; if (Arg->getOption().matches(options::OPT_fsanitize_recover)) { @@ -451,7 +456,18 @@ RecoverableKinds |= expandSanitizerGroups(Add); Arg->claim(); } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) { - RecoverableKinds &= ~expandSanitizerGroups(parseArgValues(D, Arg, true)); + SanitizerMask Remove = parseArgValues(D, Arg, true); + // Report error if user explicitly tries to disable recovery from + // always recoverable sanitizer. + if (SanitizerMask KindsToDiagnose = + Remove & AlwaysRecoverable & ~DiagnosedAlwaysRecoverableKinds) { + SanitizerSet SetToDiagnose; + SetToDiagnose.Mask |= KindsToDiagnose; + D.Diag(diag::err_drv_unsupported_option_argument) + << Arg->getOption().getName() << toString(SetToDiagnose); + DiagnosedAlwaysRecoverableKinds |= KindsToDiagnose; + } + RecoverableKinds &= ~expandSanitizerGroups(Remove); Arg->claim(); } if (DeprecatedReplacement) { Index: clang/lib/Driver/ToolChains/Linux.cpp =================================================================== --- clang/lib/Driver/ToolChains/Linux.cpp +++ clang/lib/Driver/ToolChains/Linux.cpp @@ -899,8 +899,10 @@ Res |= SanitizerKind::Function; if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsMIPS || IsArmArch) Res |= SanitizerKind::Scudo; - if (IsX86_64 || IsAArch64) + if (IsX86_64 || IsAArch64) { Res |= SanitizerKind::HWAddress; + Res |= SanitizerKind::KernelHWAddress; + } return Res; } Index: clang/lib/Lex/PPMacroExpansion.cpp =================================================================== --- clang/lib/Lex/PPMacroExpansion.cpp +++ clang/lib/Lex/PPMacroExpansion.cpp @@ -1105,7 +1105,8 @@ LangOpts.Sanitize.hasOneOf(SanitizerKind::Address | SanitizerKind::KernelAddress)) .Case("hwaddress_sanitizer", - LangOpts.Sanitize.hasOneOf(SanitizerKind::HWAddress)) + LangOpts.Sanitize.hasOneOf(SanitizerKind::HWAddress | + SanitizerKind::KernelHWAddress)) .Case("assume_nonnull", true) .Case("attribute_analyzer_noreturn", true) .Case("attribute_availability", true) Index: clang/test/CodeGen/address-safety-attr-flavors.cpp =================================================================== --- clang/test/CodeGen/address-safety-attr-flavors.cpp +++ clang/test/CodeGen/address-safety-attr-flavors.cpp @@ -1,10 +1,12 @@ -// Make sure the sanitize_address attribute is emitted when using ASan, KASan or HWASan. +// Make sure the sanitize_address attribute is emitted when using ASan, KASan, HWASan or KHWASan. // Either __attribute__((no_sanitize("address")) or __attribute__((no_sanitize("kernel-address")) disables both ASan and KASan instrumentation. +// Same for __attribute__((no_sanitize("hwaddress")) and __attribute__((no_sanitize("kernel-hwddress")) and HWASan and KHWASan. /// RUN: %clang_cc1 -triple i386-unknown-linux -disable-O0-optnone -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-NOASAN %s /// RUN: %clang_cc1 -triple i386-unknown-linux -fsanitize=address -disable-O0-optnone -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-ASAN %s /// RUN: %clang_cc1 -triple i386-unknown-linux -fsanitize=kernel-address -disable-O0-optnone -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-KASAN %s /// RUN: %clang_cc1 -triple i386-unknown-linux -fsanitize=hwaddress -disable-O0-optnone -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-HWASAN %s +/// RUN: %clang_cc1 -triple i386-unknown-linux -fsanitize=kernel-hwaddress -disable-O0-optnone -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-KHWASAN %s int HasSanitizeAddress() { return 1; @@ -13,6 +15,7 @@ // CHECK-ASAN: Function Attrs: noinline nounwind sanitize_address // CHECK-KASAN: Function Attrs: noinline nounwind sanitize_address // CHECK-HWASAN: Function Attrs: noinline nounwind sanitize_hwaddress +// CHECK-KHWASAN: Function Attrs: noinline nounwind sanitize_hwaddress __attribute__((no_sanitize("address"))) int NoSanitizeQuoteAddress() { @@ -22,6 +25,7 @@ // CHECK-ASAN: {{Function Attrs: noinline nounwind$}} // CHECK-KASAN: {{Function Attrs: noinline nounwind$}} // CHECK-HWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress$}} +// CHECK-KHWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress$}} __attribute__((no_sanitize_address)) int NoSanitizeAddress() { @@ -31,6 +35,7 @@ // CHECK-ASAN: {{Function Attrs: noinline nounwind$}} // CHECK-KASAN: {{Function Attrs: noinline nounwind$}} // CHECK-HWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress$}} +// CHECK-KHWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress$}} __attribute__((no_sanitize("kernel-address"))) int NoSanitizeKernelAddress() { @@ -40,6 +45,7 @@ // CHECK-ASAN: {{Function Attrs: noinline nounwind$}} // CHECK-KASAN: {{Function Attrs: noinline nounwind$}} // CHECK-HWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress$}} +// CHECK-KHWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress$}} __attribute__((no_sanitize("hwaddress"))) int NoSanitizeHWAddress() { @@ -49,3 +55,14 @@ // CHECK-ASAN: {{Function Attrs: noinline nounwind sanitize_address$}} // CHECK-KASAN: {{Function Attrs: noinline nounwind sanitize_address$}} // CHECK-HWASAN: {{Function Attrs: noinline nounwind$}} +// CHECK-KHWASAN: {{Function Attrs: noinline nounwind$}} + +__attribute__((no_sanitize("kernel-hwaddress"))) +int NoSanitizeKernelHWAddress() { + return 0; +} +// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}} +// CHECK-ASAN: {{Function Attrs: noinline nounwind sanitize_address$}} +// CHECK-KASAN: {{Function Attrs: noinline nounwind sanitize_address$}} +// CHECK-HWASAN: {{Function Attrs: noinline nounwind$}} +// CHECK-KHWASAN: {{Function Attrs: noinline nounwind$}} Index: clang/test/Driver/asan.c =================================================================== --- clang/test/Driver/asan.c +++ clang/test/Driver/asan.c @@ -10,9 +10,14 @@ // RUN: %clang -O1 -target aarch64-unknown-linux -fsanitize=hwaddress %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-HWASAN // RUN: %clang -O2 -target aarch64-unknown-linux -fsanitize=hwaddress %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-HWASAN // RUN: %clang -O3 -target aarch64-unknown-linux -fsanitize=hwaddress %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-HWASAN -// Verify that -fsanitize={address,kernel-address} invoke ASan and KASan instrumentation. +// RUN: %clang -target aarch64-unknown-linux -fsanitize=kernel-hwaddress %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-KHWASAN +// RUN: %clang -O1 -target aarch64-unknown-linux -fsanitize=kernel-hwaddress %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-KHWASAN +// RUN: %clang -O2 -target aarch64-unknown-linux -fsanitize=kernel-hwaddress %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-KHWASAN +// RUN: %clang -O3 -target aarch64-unknown-linux -fsanitize=kernel-hwaddress %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-KHWASAN +// Verify that -fsanitize={address,hwaddres,kernel-address,kernel-hwaddress} invokes ASan, HWAsan, KASan or KHWASan instrumentation. int foo(int *a) { return *a; } // CHECK-ASAN: __asan_init // CHECK-KASAN: __asan_load4_noabort // CHECK-HWASAN: __hwasan_init +// CHECK-KHWASAN: __hwasan_load4_noabort Index: clang/test/Driver/fsanitize-coverage.c =================================================================== --- clang/test/Driver/fsanitize-coverage.c +++ clang/test/Driver/fsanitize-coverage.c @@ -7,6 +7,7 @@ // RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FUNC // RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-address -fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FUNC // RUN: %clang -target x86_64-linux-gnu -fsanitize=hwaddress -fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FUNC +// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-hwaddress -fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FUNC // RUN: %clang -target x86_64-linux-gnu -fsanitize=memory -fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FUNC // RUN: %clang -target x86_64-linux-gnu -fsanitize=leak -fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FUNC // RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FUNC Index: clang/test/Driver/fsanitize.c =================================================================== --- clang/test/Driver/fsanitize.c +++ clang/test/Driver/fsanitize.c @@ -83,6 +83,27 @@ // RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-address,address -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANKA-SANA // CHECK-SANKA-SANA: '-fsanitize=kernel-address' not allowed with '-fsanitize=address' +// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-address,leak -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANKA-SANL +// CHECK-SANKA-SANL: '-fsanitize=kernel-address' not allowed with '-fsanitize=leak' + +// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-hwaddress,thread -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANKHA-SANT +// CHECK-SANKHA-SANT: '-fsanitize=kernel-hwaddress' not allowed with '-fsanitize=thread' + +// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-hwaddress,memory -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANKHA-SANM +// CHECK-SANKHA-SANM: '-fsanitize=kernel-hwaddress' not allowed with '-fsanitize=memory' + +// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-hwaddress,address -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANKHA-SANA +// CHECK-SANKHA-SANA: '-fsanitize=kernel-hwaddress' not allowed with '-fsanitize=address' + +// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-hwaddress,leak -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANKHA-SANL +// CHECK-SANKHA-SANL: '-fsanitize=kernel-hwaddress' not allowed with '-fsanitize=leak' + +// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-hwaddress,hwaddress -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANKHA-SANHA +// CHECK-SANKHA-SANHA: '-fsanitize=kernel-hwaddress' not allowed with '-fsanitize=hwaddress' + +// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-hwaddress,kernel-address -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANKHA-SANKA +// CHECK-SANKHA-SANKA: '-fsanitize=kernel-hwaddress' not allowed with '-fsanitize=kernel-address' + // RUN: %clang -target x86_64-linux-gnu -fsanitize=hwaddress,thread -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANHA-SANT // CHECK-SANHA-SANT: '-fsanitize=hwaddress' not allowed with '-fsanitize=thread' @@ -92,9 +113,6 @@ // RUN: %clang -target x86_64-linux-gnu -fsanitize=hwaddress,address -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANHA-SANA // CHECK-SANHA-SANA: '-fsanitize=hwaddress' not allowed with '-fsanitize=address' -// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-address,leak -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANKA-SANL -// CHECK-SANKA-SANL: '-fsanitize=kernel-address' not allowed with '-fsanitize=leak' - // RUN: %clang -target x86_64-linux-gnu -fsanitize=efficiency-cache-frag,address -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANE-SANA // RUN: %clang -target x86_64-linux-gnu -fsanitize=efficiency-working-set,address -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANE-SANA // CHECK-SANE-SANA: '-fsanitize=efficiency-{{.*}}' not allowed with '-fsanitize=address' @@ -254,6 +272,11 @@ // CHECK-DEPRECATED-RECOVER: argument '-fno-sanitize-recover' is deprecated, use '-fno-sanitize-recover=undefined,integer' or '-fno-sanitize-recover=all' instead // CHECK-DEPRECATED-RECOVER-NOT: is deprecated +// RUN: %clang -target x86_64-linux-gnu %s -fsanitize=kernel-address -fno-sanitize-recover=kernel-address -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-RECOVER-KASAN +// RUN: %clang -target x86_64-linux-gnu %s -fsanitize=kernel-hwaddress -fno-sanitize-recover=kernel-hwaddress -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-RECOVER-KHWASAN +// CHECK-NO-RECOVER-KASAN: unsupported argument 'kernel-address' to option 'fno-sanitize-recover=' +// CHECK-NO-RECOVER-KHWASAN: unsupported argument 'kernel-hwaddress' to option 'fno-sanitize-recover=' + // RUN: %clang -target x86_64-linux-gnu -fsanitize=leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANL // CHECK-SANL: "-fsanitize=leak" Index: clang/test/Lexer/has_feature_address_sanitizer.cpp =================================================================== --- clang/test/Lexer/has_feature_address_sanitizer.cpp +++ clang/test/Lexer/has_feature_address_sanitizer.cpp @@ -1,6 +1,7 @@ // RUN: %clang_cc1 -E -fsanitize=address %s -o - | FileCheck --check-prefix=CHECK-ASAN %s // RUN: %clang_cc1 -E -fsanitize=kernel-address %s -o - | FileCheck --check-prefix=CHECK-ASAN %s // RUN: %clang_cc1 -E -fsanitize=hwaddress %s -o - | FileCheck --check-prefix=CHECK-HWASAN %s +// RUN: %clang_cc1 -E -fsanitize=kernel-hwaddress %s -o - | FileCheck --check-prefix=CHECK-HWASAN %s // RUN: %clang_cc1 -E %s -o - | FileCheck --check-prefix=CHECK-NO-ASAN %s #if __has_feature(address_sanitizer) Index: llvm/include/llvm/Transforms/Instrumentation.h =================================================================== --- llvm/include/llvm/Transforms/Instrumentation.h +++ llvm/include/llvm/Transforms/Instrumentation.h @@ -133,7 +133,8 @@ FunctionPass *createMemorySanitizerPass(int TrackOrigins = 0, bool Recover = false); -FunctionPass *createHWAddressSanitizerPass(bool Recover = false); +FunctionPass *createHWAddressSanitizerPass(bool CompileKernel = false, + bool Recover = false); // Insert ThreadSanitizer (race detection) instrumentation FunctionPass *createThreadSanitizerPass(); Index: llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -589,9 +589,11 @@ explicit AddressSanitizer(bool CompileKernel = false, bool Recover = false, bool UseAfterScope = false) - : FunctionPass(ID), CompileKernel(CompileKernel || ClEnableKasan), - Recover(Recover || ClRecover), - UseAfterScope(UseAfterScope || ClUseAfterScope) { + : FunctionPass(ID), UseAfterScope(UseAfterScope || ClUseAfterScope) { + this->Recover = ClRecover.getNumOccurrences() > 0 ? ClRecover : Recover; + this->CompileKernel = ClEnableKasan.getNumOccurrences() > 0 ? + ClEnableKasan : CompileKernel; + assert(!CompileKernel || Recover); initializeAddressSanitizerPass(*PassRegistry::getPassRegistry()); } @@ -718,7 +720,6 @@ bool Recover = false, bool UseGlobalsGC = true) : ModulePass(ID), CompileKernel(CompileKernel || ClEnableKasan), - Recover(Recover || ClRecover), UseGlobalsGC(UseGlobalsGC && ClUseGlobalsGC), // Not a typo: ClWithComdat is almost completely pointless without // ClUseGlobalsGC (because then it only works on modules without @@ -727,7 +728,11 @@ // argument is designed as workaround. Therefore, disable both // ClWithComdat and ClUseGlobalsGC unless the frontend says it's ok to // do globals-gc. - UseCtorComdat(UseGlobalsGC && ClWithComdat) {} + UseCtorComdat(UseGlobalsGC && ClWithComdat) { + this->Recover = ClRecover.getNumOccurrences() > 0 ? + ClRecover : Recover; + assert(!CompileKernel || this->Recover); + } bool runOnModule(Module &M) override; StringRef getPassName() const override { return "AddressSanitizerModule"; } Index: llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp +++ llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp @@ -119,8 +119,13 @@ // Pass identification, replacement for typeid. static char ID; - HWAddressSanitizer(bool Recover = false) - : FunctionPass(ID), Recover(Recover || ClRecover) {} + explicit HWAddressSanitizer(bool CompileKernel = false, bool Recover = false) + : FunctionPass(ID) { + this->Recover = ClRecover.getNumOccurrences() > 0 ? ClRecover : Recover; + this->CompileKernel = ClEnableKhwasan.getNumOccurrences() > 0 ? + ClEnableKhwasan : CompileKernel; + assert(!this->CompileKernel || this->Recover); + } StringRef getPassName() const override { return "HWAddressSanitizer"; } @@ -156,6 +161,7 @@ Type *IntptrTy; Type *Int8Ty; + bool CompileKernel; bool Recover; Function *HwasanCtorFunction; @@ -178,8 +184,9 @@ HWAddressSanitizer, "hwasan", "HWAddressSanitizer: detect memory bugs using tagged addressing.", false, false) -FunctionPass *llvm::createHWAddressSanitizerPass(bool Recover) { - return new HWAddressSanitizer(Recover); +FunctionPass *llvm::createHWAddressSanitizerPass(bool CompileKernel, + bool Recover) { + return new HWAddressSanitizer(CompileKernel, Recover); } /// \brief Module-level initialization. @@ -197,7 +204,7 @@ Int8Ty = IRB.getInt8Ty(); HwasanCtorFunction = nullptr; - if (!ClEnableKhwasan) { + if (!CompileKernel) { std::tie(HwasanCtorFunction, std::ignore) = createSanitizerCtorAndInitFunctions(M, kHwasanModuleCtorName, kHwasanInitName, @@ -335,9 +342,11 @@ IRB.CreateLoad(IRB.CreateIntToPtr(ShadowLong, IRB.getInt8PtrTy())); Value *TagMismatch = IRB.CreateICmpNE(PtrTag, MemTag); - if (ClMatchAllTag != -1) { + int matchAllTag = ClMatchAllTag.getNumOccurrences() > 0 ? + ClMatchAllTag : (CompileKernel ? 0xFF : -1); + if (matchAllTag != -1) { Value *TagNotIgnored = IRB.CreateICmpNE(PtrTag, - ConstantInt::get(PtrTag->getType(), ClMatchAllTag)); + ConstantInt::get(PtrTag->getType(), matchAllTag)); TagMismatch = IRB.CreateAnd(TagMismatch, TagNotIgnored); } @@ -502,7 +511,7 @@ Value *HWAddressSanitizer::tagPointer(IRBuilder<> &IRB, Type *Ty, Value *PtrLong, Value *Tag) { Value *TaggedPtrLong; - if (ClEnableKhwasan) { + if (CompileKernel) { // Kernel addresses have 0xFF in the most significant byte. Value *ShiftedTag = IRB.CreateOr( IRB.CreateShl(Tag, kPointerTagShift), @@ -519,7 +528,7 @@ // Remove tag from an address. Value *HWAddressSanitizer::untagPointer(IRBuilder<> &IRB, Value *PtrLong) { Value *UntaggedPtrLong; - if (ClEnableKhwasan) { + if (CompileKernel) { // Kernel addresses have 0xFF in the most significant byte. UntaggedPtrLong = IRB.CreateOr(PtrLong, ConstantInt::get(PtrLong->getType(), 0xFFULL << kPointerTagShift)); Index: llvm/test/Instrumentation/HWAddressSanitizer/X86/kernel.ll =================================================================== --- llvm/test/Instrumentation/HWAddressSanitizer/X86/kernel.ll +++ llvm/test/Instrumentation/HWAddressSanitizer/X86/kernel.ll @@ -1,4 +1,4 @@ -; Test kernel hwasan instrumentation. +; Test KHWASan instrumentation. ; Generic code is covered by ../kernel.ll, only the x86_64 specific code is ; tested here. ; Index: llvm/test/Instrumentation/HWAddressSanitizer/kernel.ll =================================================================== --- llvm/test/Instrumentation/HWAddressSanitizer/kernel.ll +++ llvm/test/Instrumentation/HWAddressSanitizer/kernel.ll @@ -1,11 +1,11 @@ -; Test kernel hwasan instrumentation. +; Test KHWASan instrumentation. ; ; RUN: opt < %s -hwasan -hwasan-kernel=1 -S | FileCheck %s --allow-empty --check-prefixes=INIT -; RUN: opt < %s -hwasan -hwasan-kernel=1 -S | FileCheck %s --check-prefixes=CHECK,NOOFFSET,NO-MATCH-ALL -; RUN: opt < %s -hwasan -hwasan-kernel=1 -hwasan-mapping-offset=12345678 -S | FileCheck %s --check-prefixes=CHECK,OFFSET,NO-MATCH-ALL -; RUN: opt < %s -hwasan -hwasan-kernel=1 -hwasan-recover=0 -S | FileCheck %s --check-prefixes=CHECK,NOOFFSET,ABORT,NO-MATCH-ALL -; RUN: opt < %s -hwasan -hwasan-kernel=1 -hwasan-recover=1 -S | FileCheck %s --check-prefixes=CHECK,NOOFFSET,RECOVER,NO-MATCH-ALL -; RUN: opt < %s -hwasan -hwasan-kernel=1 -hwasan-recover=1 -hwasan-match-all-tag=0xff -S | FileCheck %s --check-prefixes=CHECK,NOOFFSET,RECOVER,MATCH-ALL +; RUN: opt < %s -hwasan -hwasan-kernel=1 -S | FileCheck %s --check-prefixes=CHECK,NOOFFSET,MATCH-ALL +; RUN: opt < %s -hwasan -hwasan-kernel=1 -hwasan-mapping-offset=12345678 -S | FileCheck %s --check-prefixes=CHECK,OFFSET,MATCH-ALL +; RUN: opt < %s -hwasan -hwasan-kernel=1 -hwasan-recover=0 -S | FileCheck %s --check-prefixes=CHECK,NOOFFSET,ABORT,MATCH-ALL +; RUN: opt < %s -hwasan -hwasan-kernel=1 -hwasan-recover=1 -S | FileCheck %s --check-prefixes=CHECK,NOOFFSET,RECOVER,MATCH-ALL +; RUN: opt < %s -hwasan -hwasan-kernel=1 -hwasan-recover=1 -hwasan-match-all-tag=-1 -S | FileCheck %s --check-prefixes=CHECK,NOOFFSET,RECOVER,NO-MATCH-ALL target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" target triple = "aarch64--linux-android"