forked from OSchip/llvm-project
[MSan] add KMSAN support to Clang driver
Boilerplate code for using KMSAN instrumentation in Clang. We add a new command line flag, -fsanitize=kernel-memory, with a corresponding SanitizerKind::KernelMemory, which, along with SanitizerKind::Memory, maps to the memory_sanitizer feature. KMSAN is only supported on x86_64 Linux. It's incompatible with other sanitizers, but supports code coverage instrumentation. llvm-svn: 341641
This commit is contained in:
parent
e5536b972f
commit
d49c32ce3f
|
@ -72,7 +72,9 @@ FEATURE(cxx_rtti, LangOpts.RTTI &&LangOpts.RTTIData)
|
|||
FEATURE(enumerator_attributes, true)
|
||||
FEATURE(nullability, true)
|
||||
FEATURE(nullability_on_arrays, true)
|
||||
FEATURE(memory_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Memory))
|
||||
FEATURE(memory_sanitizer,
|
||||
LangOpts.Sanitize.hasOneOf(SanitizerKind::Memory |
|
||||
SanitizerKind::KernelMemory))
|
||||
FEATURE(thread_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Thread))
|
||||
FEATURE(dataflow_sanitizer, LangOpts.Sanitize.has(SanitizerKind::DataFlow))
|
||||
FEATURE(efficiency_sanitizer,
|
||||
|
|
|
@ -53,6 +53,9 @@ SANITIZER("kernel-hwaddress", KernelHWAddress)
|
|||
// MemorySanitizer
|
||||
SANITIZER("memory", Memory)
|
||||
|
||||
// Kernel MemorySanitizer (KMSAN)
|
||||
SANITIZER("kernel-memory", KernelMemory)
|
||||
|
||||
// libFuzzer
|
||||
SANITIZER("fuzzer", Fuzzer)
|
||||
|
||||
|
|
|
@ -265,14 +265,15 @@ static void addKernelHWAddressSanitizerPasses(const PassManagerBuilder &Builder,
|
|||
/*CompileKernel*/ true, /*Recover*/ true));
|
||||
}
|
||||
|
||||
static void addMemorySanitizerPass(const PassManagerBuilder &Builder,
|
||||
legacy::PassManagerBase &PM) {
|
||||
static void addGeneralOptsForMemorySanitizer(const PassManagerBuilder &Builder,
|
||||
legacy::PassManagerBase &PM,
|
||||
bool CompileKernel) {
|
||||
const PassManagerBuilderWrapper &BuilderWrapper =
|
||||
static_cast<const PassManagerBuilderWrapper&>(Builder);
|
||||
const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
|
||||
int TrackOrigins = CGOpts.SanitizeMemoryTrackOrigins;
|
||||
bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::Memory);
|
||||
PM.add(createMemorySanitizerPass(TrackOrigins, Recover));
|
||||
PM.add(createMemorySanitizerPass(TrackOrigins, Recover, CompileKernel));
|
||||
|
||||
// MemorySanitizer inserts complex instrumentation that mostly follows
|
||||
// the logic of the original code, but operates on "shadow" values.
|
||||
|
@ -287,6 +288,16 @@ static void addMemorySanitizerPass(const PassManagerBuilder &Builder,
|
|||
}
|
||||
}
|
||||
|
||||
static void addMemorySanitizerPass(const PassManagerBuilder &Builder,
|
||||
legacy::PassManagerBase &PM) {
|
||||
addGeneralOptsForMemorySanitizer(Builder, PM, /*CompileKernel*/ false);
|
||||
}
|
||||
|
||||
static void addKernelMemorySanitizerPass(const PassManagerBuilder &Builder,
|
||||
legacy::PassManagerBase &PM) {
|
||||
addGeneralOptsForMemorySanitizer(Builder, PM, /*CompileKernel*/ true);
|
||||
}
|
||||
|
||||
static void addThreadSanitizerPass(const PassManagerBuilder &Builder,
|
||||
legacy::PassManagerBase &PM) {
|
||||
PM.add(createThreadSanitizerPass());
|
||||
|
@ -614,6 +625,13 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM,
|
|||
addMemorySanitizerPass);
|
||||
}
|
||||
|
||||
if (LangOpts.Sanitize.has(SanitizerKind::KernelMemory)) {
|
||||
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
|
||||
addKernelMemorySanitizerPass);
|
||||
PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
|
||||
addKernelMemorySanitizerPass);
|
||||
}
|
||||
|
||||
if (LangOpts.Sanitize.has(SanitizerKind::Thread)) {
|
||||
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
|
||||
addThreadSanitizerPass);
|
||||
|
|
|
@ -347,6 +347,10 @@ llvm::Function *CodeGenModule::CreateGlobalInitOrDestructFunction(
|
|||
!isInSanitizerBlacklist(SanitizerKind::Memory, Fn, Loc))
|
||||
Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
|
||||
|
||||
if (getLangOpts().Sanitize.has(SanitizerKind::KernelMemory) &&
|
||||
!isInSanitizerBlacklist(SanitizerKind::KernelMemory, Fn, Loc))
|
||||
Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
|
||||
|
||||
if (getLangOpts().Sanitize.has(SanitizerKind::SafeStack) &&
|
||||
!isInSanitizerBlacklist(SanitizerKind::SafeStack, Fn, Loc))
|
||||
Fn->addFnAttr(llvm::Attribute::SafeStack);
|
||||
|
|
|
@ -868,7 +868,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
|
|||
Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress);
|
||||
if (SanOpts.has(SanitizerKind::Thread))
|
||||
Fn->addFnAttr(llvm::Attribute::SanitizeThread);
|
||||
if (SanOpts.has(SanitizerKind::Memory))
|
||||
if (SanOpts.hasOneOf(SanitizerKind::Memory | SanitizerKind::KernelMemory))
|
||||
Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
|
||||
if (SanOpts.has(SanitizerKind::SafeStack))
|
||||
Fn->addFnAttr(llvm::Attribute::SafeStack);
|
||||
|
|
|
@ -34,8 +34,9 @@ enum : SanitizerMask {
|
|||
RequiresPIE = DataFlow | HWAddress | Scudo,
|
||||
NeedsUnwindTables = Address | HWAddress | Thread | Memory | DataFlow,
|
||||
SupportsCoverage = Address | HWAddress | KernelAddress | KernelHWAddress |
|
||||
Memory | Leak | Undefined | Integer | ImplicitConversion |
|
||||
Nullability | DataFlow | Fuzzer | FuzzerNoLink,
|
||||
Memory | KernelMemory | Leak | Undefined | Integer |
|
||||
ImplicitConversion | Nullability | DataFlow | Fuzzer |
|
||||
FuzzerNoLink,
|
||||
RecoverableByDefault = Undefined | Integer | ImplicitConversion | Nullability,
|
||||
Unrecoverable = Unreachable | Return,
|
||||
AlwaysRecoverable = KernelAddress | KernelHWAddress,
|
||||
|
@ -380,8 +381,10 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
|
|||
SafeStack),
|
||||
std::make_pair(KernelHWAddress, Address | HWAddress | Leak | Thread |
|
||||
Memory | KernelAddress | Efficiency |
|
||||
SafeStack | ShadowCallStack)};
|
||||
|
||||
SafeStack | ShadowCallStack),
|
||||
std::make_pair(KernelMemory, Address | HWAddress | Leak | Thread |
|
||||
Memory | KernelAddress | Efficiency |
|
||||
Scudo | SafeStack)};
|
||||
// Enable toolchain specific default sanitizers if not explicitly disabled.
|
||||
SanitizerMask Default = TC.getDefaultSanitizers() & ~AllRemove;
|
||||
|
||||
|
|
|
@ -939,6 +939,8 @@ SanitizerMask Linux::getSupportedSanitizers() const {
|
|||
Res |= SanitizerKind::Leak;
|
||||
if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64)
|
||||
Res |= SanitizerKind::Thread;
|
||||
if (IsX86_64)
|
||||
Res |= SanitizerKind::KernelMemory;
|
||||
if (IsX86_64 || IsMIPS64)
|
||||
Res |= SanitizerKind::Efficiency;
|
||||
if (IsX86 || IsX86_64)
|
||||
|
|
|
@ -3097,7 +3097,9 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
|
|||
// names.
|
||||
Res.getCodeGenOpts().DiscardValueNames &=
|
||||
!LangOpts.Sanitize.has(SanitizerKind::Address) &&
|
||||
!LangOpts.Sanitize.has(SanitizerKind::Memory);
|
||||
!LangOpts.Sanitize.has(SanitizerKind::KernelAddress) &&
|
||||
!LangOpts.Sanitize.has(SanitizerKind::Memory) &&
|
||||
!LangOpts.Sanitize.has(SanitizerKind::KernelMemory);
|
||||
|
||||
ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, Diags,
|
||||
Res.getFrontendOpts().ProgramAction);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// We shouldn't have markers at -O0 or with msan.
|
||||
// RUN: %clang_cc1 -O0 -triple x86_64-none-linux-gnu -emit-llvm -debug-info-kind=line-tables-only %s -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -O1 -triple x86_64-none-linux-gnu -emit-llvm -debug-info-kind=line-tables-only %s -o - -fsanitize=memory | FileCheck %s
|
||||
// RUN: %clang_cc1 -O1 -triple x86_64-none-linux-gnu -emit-llvm -debug-info-kind=line-tables-only %s -o - -fsanitize=kernel-memory | FileCheck %s
|
||||
|
||||
// There is no exception to handle here, lifetime.end is not a destructor,
|
||||
// so there is no need have cleanup dest slot related code
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
// 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=kernel-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
|
||||
// RUN: %clang -target x86_64-linux-gnu -fsanitize=bool -fsanitize-coverage=func,trace-pc %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FUNC
|
||||
|
|
|
@ -89,6 +89,27 @@
|
|||
// 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-memory,address -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-KMSAN-ASAN
|
||||
// CHECK-KMSAN-ASAN: '-fsanitize=kernel-memory' not allowed with '-fsanitize=address'
|
||||
|
||||
// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-memory,hwaddress -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-KMSAN-HWASAN
|
||||
// CHECK-KMSAN-HWASAN: '-fsanitize=kernel-memory' not allowed with '-fsanitize=hwaddress'
|
||||
|
||||
// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-memory,leak -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-KMSAN-LSAN
|
||||
// CHECK-KMSAN-LSAN: '-fsanitize=kernel-memory' not allowed with '-fsanitize=leak'
|
||||
|
||||
// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-memory,thread -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-KMSAN-TSAN
|
||||
// CHECK-KMSAN-TSAN: '-fsanitize=kernel-memory' not allowed with '-fsanitize=thread'
|
||||
|
||||
// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-memory,kernel-address -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-KMSAN-KASAN
|
||||
// CHECK-KMSAN-KASAN: '-fsanitize=kernel-memory' not allowed with '-fsanitize=kernel-address'
|
||||
|
||||
// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-memory,memory -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-KMSAN-MSAN
|
||||
// CHECK-KMSAN-MSAN: '-fsanitize=kernel-memory' not allowed with '-fsanitize=memory'
|
||||
|
||||
// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-memory,safe-stack -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-KMSAN-SAFESTACK
|
||||
// CHECK-KMSAN-SAFESTACK: '-fsanitize=kernel-memory' not allowed with '-fsanitize=safe-stack'
|
||||
|
||||
// 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'
|
||||
|
||||
|
@ -144,6 +165,10 @@
|
|||
// RUN: %clang -target x86_64-linux-gnu -fsanitize=efficiency-working-set,memory -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANE-SANM
|
||||
// CHECK-SANE-SANM: '-fsanitize=efficiency-{{.*}}' not allowed with '-fsanitize=memory'
|
||||
|
||||
// RUN: %clang -target x86_64-linux-gnu -fsanitize=efficiency-cache-frag,kernel-memory -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANE-SANKM
|
||||
// RUN: %clang -target x86_64-linux-gnu -fsanitize=efficiency-working-set,kernel-memory -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANE-SANKM
|
||||
// CHECK-SANE-SANKM: '-fsanitize=kernel-memory' not allowed with '-fsanitize=efficiency-{{.*}}'
|
||||
|
||||
// RUN: %clang -target x86_64-linux-gnu -fsanitize=efficiency-cache-frag,kernel-address -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANE-SANKA
|
||||
// RUN: %clang -target x86_64-linux-gnu -fsanitize=efficiency-working-set,kernel-address -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANE-SANKA
|
||||
// CHECK-SANE-SANKA: '-fsanitize=efficiency-{{.*}}' not allowed with '-fsanitize=kernel-address'
|
||||
|
@ -733,3 +758,6 @@
|
|||
// CHECK-SCUDO-TSAN: error: invalid argument '-fsanitize=scudo' not allowed with '-fsanitize=thread'
|
||||
// RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo,hwaddress %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-HWASAN
|
||||
// CHECK-SCUDO-HWASAN: error: invalid argument '-fsanitize=scudo' not allowed with '-fsanitize=hwaddress'
|
||||
//
|
||||
// RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo,kernel-memory %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-KMSAN
|
||||
// CHECK-SCUDO-KMSAN: error: invalid argument '-fsanitize=kernel-memory' not allowed with '-fsanitize=scudo'
|
||||
|
|
|
@ -1,12 +1,20 @@
|
|||
// RUN: %clang -target x86_64-unknown-linux -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s
|
||||
// RUN: %clang -O1 -target x86_64-unknown-linux -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s
|
||||
// RUN: %clang -O2 -target x86_64-unknown-linux -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s
|
||||
// RUN: %clang -O3 -target x86_64-unknown-linux -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s
|
||||
// RUN: %clang -target mips64-linux-gnu -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s
|
||||
// RUN: %clang -target mips64el-unknown-linux-gnu -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s
|
||||
// RUN: %clang -target powerpc64-unknown-linux-gnu -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s
|
||||
// RUN: %clang -target powerpc64le-unknown-linux-gnu -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s
|
||||
// Verify that -fsanitize=memory invokes msan instrumentation.
|
||||
// RUN: %clang -target x86_64-unknown-linux -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-MSAN
|
||||
// RUN: %clang -O1 -target x86_64-unknown-linux -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-MSAN
|
||||
// RUN: %clang -O2 -target x86_64-unknown-linux -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-MSAN
|
||||
// RUN: %clang -O3 -target x86_64-unknown-linux -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-MSAN
|
||||
|
||||
// RUN: %clang -target x86_64-unknown-linux -fsanitize=kernel-memory %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-KMSAN
|
||||
// RUN: %clang -O1 -target x86_64-unknown-linux -fsanitize=kernel-memory %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-KMSAN
|
||||
// RUN: %clang -O2 -target x86_64-unknown-linux -fsanitize=kernel-memory %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-KMSAN
|
||||
// RUN: %clang -O3 -target x86_64-unknown-linux -fsanitize=kernel-memory %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-KMSAN
|
||||
|
||||
// RUN: %clang -target mips64-linux-gnu -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-MSAN
|
||||
// RUN: %clang -target mips64el-unknown-linux-gnu -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-MSAN
|
||||
// RUN: %clang -target powerpc64-unknown-linux-gnu -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-MSAN
|
||||
// RUN: %clang -target powerpc64le-unknown-linux-gnu -fsanitize=memory %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-MSAN
|
||||
|
||||
// Verify that -fsanitize=memory and -fsanitize=kernel-memory invoke MSan/KMSAN instrumentation.
|
||||
|
||||
int foo(int *a) { return *a; }
|
||||
// CHECK: __msan_init
|
||||
// CHECK-MSAN: __msan_init
|
||||
// CHECK-KMSAN: __msan_get_context_state
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// RUN: %clang_cc1 -E -fsanitize=memory %s -o - | FileCheck --check-prefix=CHECK-MSAN %s
|
||||
// RUN: %clang_cc1 -E -fsanitize=kernel-memory %s -o - | FileCheck --check-prefix=CHECK-MSAN %s
|
||||
// RUN: %clang_cc1 -E %s -o - | FileCheck --check-prefix=CHECK-NO-MSAN %s
|
||||
|
||||
#if __has_feature(memory_sanitizer)
|
||||
|
|
Loading…
Reference in New Issue