diff options
-rw-r--r-- | include/clang/Basic/Sanitizers.def | 3 | ||||
-rw-r--r-- | include/clang/Basic/Sanitizers.h | 3 | ||||
-rw-r--r-- | lib/AST/Decl.cpp | 3 | ||||
-rw-r--r-- | lib/Basic/Sanitizers.cpp | 4 | ||||
-rw-r--r-- | lib/CodeGen/BackendUtil.cpp | 17 | ||||
-rw-r--r-- | lib/CodeGen/CGDeclCXX.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 5 | ||||
-rw-r--r-- | lib/CodeGen/SanitizerMetadata.cpp | 9 | ||||
-rw-r--r-- | lib/Driver/SanitizerArgs.cpp | 5 | ||||
-rw-r--r-- | lib/Lex/PPMacroExpansion.cpp | 4 | ||||
-rw-r--r-- | test/CodeGen/address-safety-attr-kasan.cpp | 38 | ||||
-rw-r--r-- | test/Driver/asan.c | 17 | ||||
-rw-r--r-- | test/Driver/fsanitize.c | 12 | ||||
-rw-r--r-- | test/Lexer/has_feature_address_sanitizer.cpp | 1 |
15 files changed, 108 insertions, 18 deletions
diff --git a/include/clang/Basic/Sanitizers.def b/include/clang/Basic/Sanitizers.def index 9e341ae55d..1b528c8d6f 100644 --- a/include/clang/Basic/Sanitizers.def +++ b/include/clang/Basic/Sanitizers.def @@ -41,6 +41,9 @@ // AddressSanitizer SANITIZER("address", Address) +// Kernel AddressSanitizer (KASan) +SANITIZER("kernel-address", KernelAddress) + // MemorySanitizer SANITIZER("memory", Memory) diff --git a/include/clang/Basic/Sanitizers.h b/include/clang/Basic/Sanitizers.h index 3b1797e9f5..78c1ddb56f 100644 --- a/include/clang/Basic/Sanitizers.h +++ b/include/clang/Basic/Sanitizers.h @@ -52,6 +52,9 @@ struct SanitizerSet { /// \brief Check if a certain (single) sanitizer is enabled. bool has(SanitizerMask K) const; + /// \brief Check if one or more sanitizers are enabled. + bool hasOneOf(SanitizerMask K) const; + /// \brief Enable or disable a certain (single) sanitizer. void set(SanitizerMask K, bool Value); diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 8eff4c4427..d9a3389c58 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -3681,7 +3681,8 @@ void RecordDecl::LoadFieldsFromExternalStorage() const { bool RecordDecl::mayInsertExtraPadding(bool EmitRemark) const { ASTContext &Context = getASTContext(); - if (!Context.getLangOpts().Sanitize.has(SanitizerKind::Address) || + if (!Context.getLangOpts().Sanitize.hasOneOf( + SanitizerKind::Address | SanitizerKind::KernelAddress) || !Context.getLangOpts().SanitizeAddressFieldPadding) return false; const auto &Blacklist = Context.getSanitizerBlacklist(); diff --git a/lib/Basic/Sanitizers.cpp b/lib/Basic/Sanitizers.cpp index 8c4884b8ec..d3676b6b46 100644 --- a/lib/Basic/Sanitizers.cpp +++ b/lib/Basic/Sanitizers.cpp @@ -25,6 +25,10 @@ bool SanitizerSet::has(SanitizerMask K) const { return Mask & K; } +bool SanitizerSet::hasOneOf(SanitizerMask K) const { + return Mask & K; +} + void SanitizerSet::set(SanitizerMask K, bool Value) { assert(llvm::countPopulation(K) == 1); Mask = Value ? (Mask | K) : (Mask & ~K); diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp index 30e9ebffa2..f5edea7810 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -201,8 +201,14 @@ static void addSanitizerCoveragePass(const PassManagerBuilder &Builder, static void addAddressSanitizerPasses(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) { - PM.add(createAddressSanitizerFunctionPass()); - PM.add(createAddressSanitizerModulePass()); + PM.add(createAddressSanitizerFunctionPass(/*CompileKernel*/false)); + PM.add(createAddressSanitizerModulePass(/*CompileKernel*/false)); +} + +static void addKernelAddressSanitizerPasses(const PassManagerBuilder &Builder, + legacy::PassManagerBase &PM) { + PM.add(createAddressSanitizerFunctionPass(/*CompileKernel*/true)); + PM.add(createAddressSanitizerModulePass(/*CompileKernel*/true)); } static void addMemorySanitizerPass(const PassManagerBuilder &Builder, @@ -328,6 +334,13 @@ void EmitAssemblyHelper::CreatePasses() { addAddressSanitizerPasses); } + if (LangOpts.Sanitize.has(SanitizerKind::KernelAddress)) { + PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast, + addKernelAddressSanitizerPasses); + PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, + addKernelAddressSanitizerPasses); + } + if (LangOpts.Sanitize.has(SanitizerKind::Memory)) { PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast, addMemorySanitizerPass); diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp index 50a499607f..bae8ab4ea0 100644 --- a/lib/CodeGen/CGDeclCXX.cpp +++ b/lib/CodeGen/CGDeclCXX.cpp @@ -267,7 +267,8 @@ llvm::Function *CodeGenModule::CreateGlobalInitOrDestructFunction( Fn->setDoesNotThrow(); if (!isInSanitizerBlacklist(Fn, Loc)) { - if (getLangOpts().Sanitize.has(SanitizerKind::Address)) + if (getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address | + SanitizerKind::KernelAddress)) Fn->addFnAttr(llvm::Attribute::SanitizeAddress); if (getLangOpts().Sanitize.has(SanitizerKind::Thread)) Fn->addFnAttr(llvm::Attribute::SanitizeThread); diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index f370ac2767..bece41e9ec 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -615,7 +615,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, } // Apply sanitizer attributes to the function. - if (SanOpts.has(SanitizerKind::Address)) + if (SanOpts.hasOneOf(SanitizerKind::Address | SanitizerKind::KernelAddress)) Fn->addFnAttr(llvm::Attribute::SanitizeAddress); if (SanOpts.has(SanitizerKind::Thread)) Fn->addFnAttr(llvm::Attribute::SanitizeThread); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index c0cbe98484..2dd5414795 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -1218,8 +1218,9 @@ bool CodeGenModule::isInSanitizerBlacklist(llvm::Function *Fn, bool CodeGenModule::isInSanitizerBlacklist(llvm::GlobalVariable *GV, SourceLocation Loc, QualType Ty, StringRef Category) const { - // For now globals can be blacklisted only in ASan. - if (!LangOpts.Sanitize.has(SanitizerKind::Address)) + // For now globals can be blacklisted only in ASan and KASan. + if (!LangOpts.Sanitize.hasOneOf( + SanitizerKind::Address | SanitizerKind::KernelAddress)) return false; const auto &SanitizerBL = getContext().getSanitizerBlacklist(); if (SanitizerBL.isBlacklistedGlobal(GV->getName(), Category)) diff --git a/lib/CodeGen/SanitizerMetadata.cpp b/lib/CodeGen/SanitizerMetadata.cpp index 7c38b2807e..2a338bac4b 100644 --- a/lib/CodeGen/SanitizerMetadata.cpp +++ b/lib/CodeGen/SanitizerMetadata.cpp @@ -25,7 +25,8 @@ void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV, SourceLocation Loc, StringRef Name, QualType Ty, bool IsDynInit, bool IsBlacklisted) { - if (!CGM.getLangOpts().Sanitize.has(SanitizerKind::Address)) + if (!CGM.getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address | + SanitizerKind::KernelAddress)) return; IsDynInit &= !CGM.isInSanitizerBlacklist(GV, Loc, Ty, "init"); IsBlacklisted |= CGM.isInSanitizerBlacklist(GV, Loc, Ty); @@ -56,7 +57,8 @@ void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV, void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV, const VarDecl &D, bool IsDynInit) { - if (!CGM.getLangOpts().Sanitize.has(SanitizerKind::Address)) + if (!CGM.getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address | + SanitizerKind::KernelAddress)) return; std::string QualName; llvm::raw_string_ostream OS(QualName); @@ -67,7 +69,8 @@ void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV, void SanitizerMetadata::disableSanitizerForGlobal(llvm::GlobalVariable *GV) { // For now, just make sure the global is not modified by the ASan // instrumentation. - if (CGM.getLangOpts().Sanitize.has(SanitizerKind::Address)) + if (CGM.getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address | + SanitizerKind::KernelAddress)) reportGlobalToASan(GV, SourceLocation(), "", QualType(), false, true); } diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp index 9918fcbd5e..4d27a39318 100644 --- a/lib/Driver/SanitizerArgs.cpp +++ b/lib/Driver/SanitizerArgs.cpp @@ -305,7 +305,10 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = { std::make_pair(Address, Thread), std::make_pair(Address, Memory), std::make_pair(Thread, Memory), std::make_pair(Leak, Thread), - std::make_pair(Leak, Memory)}; + std::make_pair(Leak, Memory), std::make_pair(KernelAddress, Address), + std::make_pair(KernelAddress, Leak), + std::make_pair(KernelAddress, Thread), + std::make_pair(KernelAddress, Memory)}; for (auto G : IncompatibleGroups) { SanitizerMask Group = G.first; if (Kinds & Group) { diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index c63cafb6d7..ccfb30240b 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -1049,7 +1049,9 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { Feature = Feature.substr(2, Feature.size() - 4); return llvm::StringSwitch<bool>(Feature) - .Case("address_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Address)) + .Case("address_sanitizer", + LangOpts.Sanitize.hasOneOf(SanitizerKind::Address | + SanitizerKind::KernelAddress)) .Case("attribute_analyzer_noreturn", true) .Case("attribute_availability", true) .Case("attribute_availability_with_message", true) diff --git a/test/CodeGen/address-safety-attr-kasan.cpp b/test/CodeGen/address-safety-attr-kasan.cpp new file mode 100644 index 0000000000..c84ba88291 --- /dev/null +++ b/test/CodeGen/address-safety-attr-kasan.cpp @@ -0,0 +1,38 @@ +// Make sure the sanitize_address attribute is emitted when using both ASan and KASan. +// Also document that __attribute__((no_sanitize_address)) doesn't disable KASan instrumentation. + +/// RUN: %clang_cc1 -triple i386-unknown-linux -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-NOASAN %s +/// RUN: %clang_cc1 -triple i386-unknown-linux -fsanitize=address -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-ASAN %s +/// RUN: %clang_cc1 -triple i386-unknown-linux -fsanitize=kernel-address -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-KASAN %s + +int HasSanitizeAddress() { + return 1; +} +// CHECK-NOASAN: {{Function Attrs: nounwind$}} +// CHECK-ASAN: Function Attrs: nounwind sanitize_address +// CHECK-KASAN: Function Attrs: nounwind sanitize_address + +__attribute__((no_sanitize("address"))) +int NoSanitizeQuoteAddress() { + return 0; +} +// CHECK-NOASAN: {{Function Attrs: nounwind$}} +// CHECK-ASAN: {{Function Attrs: nounwind$}} +// CHECK-KASAN: {{Function Attrs: nounwind sanitize_address$}} + +__attribute__((no_sanitize_address)) +int NoSanitizeAddress() { + return 0; +} +// CHECK-NOASAN: {{Function Attrs: nounwind$}} +// CHECK-ASAN: {{Function Attrs: nounwind$}} +// CHECK-KASAN: {{Function Attrs: nounwind sanitize_address$}} + +__attribute__((no_sanitize("kernel-address"))) +int NoSanitizeKernelAddress() { + return 0; +} + +// CHECK-NOASAN: {{Function Attrs: nounwind$}} +// CHECK-ASAN: {{Function Attrs: nounwind sanitize_address$}} +// CHECK-KASAN: {{Function Attrs: nounwind$}} diff --git a/test/Driver/asan.c b/test/Driver/asan.c index f199e904e7..4db103d264 100644 --- a/test/Driver/asan.c +++ b/test/Driver/asan.c @@ -1,8 +1,13 @@ -// RUN: %clang -target i386-unknown-unknown -fsanitize=address %s -S -emit-llvm -o - | FileCheck %s -// RUN: %clang -O1 -target i386-unknown-unknown -fsanitize=address %s -S -emit-llvm -o - | FileCheck %s -// RUN: %clang -O2 -target i386-unknown-unknown -fsanitize=address %s -S -emit-llvm -o - | FileCheck %s -// RUN: %clang -O3 -target i386-unknown-unknown -fsanitize=address %s -S -emit-llvm -o - | FileCheck %s -// Verify that -fsanitize=address invokes asan instrumentation. +// RUN: %clang -target i386-unknown-linux -fsanitize=address %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-ASAN +// RUN: %clang -O1 -target i386-unknown-linux -fsanitize=address %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-ASAN +// RUN: %clang -O2 -target i386-unknown-linux -fsanitize=address %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-ASAN +// RUN: %clang -O3 -target i386-unknown-linux -fsanitize=address %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-ASAN +// RUN: %clang -target i386-unknown-linux -fsanitize=kernel-address %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-KASAN +// RUN: %clang -O1 -target i386-unknown-linux -fsanitize=kernel-address %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-KASAN +// RUN: %clang -O2 -target i386-unknown-linux -fsanitize=kernel-address %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-KASAN +// RUN: %clang -O3 -target i386-unknown-linux -fsanitize=kernel-address %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-KASAN +// Verify that -fsanitize={address,kernel-address} invoke ASan and KASan instrumentation. int foo(int *a) { return *a; } -// CHECK: __asan_init +// CHECK-ASAN: __asan_init +// CHECK-KASAN: __asan_load4_noabort diff --git a/test/Driver/fsanitize.c b/test/Driver/fsanitize.c index 5c30dc12f6..66e49250ba 100644 --- a/test/Driver/fsanitize.c +++ b/test/Driver/fsanitize.c @@ -59,6 +59,18 @@ // RUN: %clang -target x86_64-linux-gnu -fsanitize=leak,memory -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANL-SANM // CHECK-SANL-SANM: '-fsanitize=leak' not allowed with '-fsanitize=memory' +// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-address,thread -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANKA-SANT +// CHECK-SANKA-SANT: '-fsanitize=kernel-address' not allowed with '-fsanitize=thread' + +// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-address,memory -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANKA-SANM +// CHECK-SANKA-SANM: '-fsanitize=kernel-address' not allowed with '-fsanitize=memory' + +// 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-memory-track-origins -pie %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ONLY-TRACK-ORIGINS // CHECK-ONLY-TRACK-ORIGINS: warning: argument unused during compilation: '-fsanitize-memory-track-origins' diff --git a/test/Lexer/has_feature_address_sanitizer.cpp b/test/Lexer/has_feature_address_sanitizer.cpp index 5c981161f9..406a2ab179 100644 --- a/test/Lexer/has_feature_address_sanitizer.cpp +++ b/test/Lexer/has_feature_address_sanitizer.cpp @@ -1,4 +1,5 @@ // 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 %s -o - | FileCheck --check-prefix=CHECK-NO-ASAN %s #if __has_feature(address_sanitizer) |