diff options
author | Alexander Potapenko <glider@google.com> | 2018-04-03 09:50:06 +0000 |
---|---|---|
committer | Alexander Potapenko <glider@google.com> | 2018-04-03 09:50:06 +0000 |
commit | ac70668cff76f28c22d84cc81a8966216d2732c2 (patch) | |
tree | ff85e416033efd8bb7e59b6e40a603aa081bc4fc /llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp | |
parent | a826ca70796e625949ef1d936d10af03b46be795 (diff) | |
download | bcm5719-llvm-ac70668cff76f28c22d84cc81a8966216d2732c2.tar.gz bcm5719-llvm-ac70668cff76f28c22d84cc81a8966216d2732c2.zip |
MSan: introduce the conservative assembly handling mode.
The default assembly handling mode may introduce false positives in the
cases when MSan doesn't understand that the assembly call initializes
the memory pointed to by one of its arguments.
We introduce the conservative mode, which initializes the first
|sizeof(type)| bytes for every |type*| pointer passed into the
assembly statement.
llvm-svn: 329054
Diffstat (limited to 'llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp')
-rw-r--r-- | llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp | 50 |
1 files changed, 49 insertions, 1 deletions
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp index b4743948da7..6437c739f5a 100644 --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -199,6 +199,18 @@ static cl::opt<bool> ClHandleICmpExact("msan-handle-icmp-exact", cl::desc("exact handling of relational integer ICmp"), cl::Hidden, cl::init(false)); +// When compiling the Linux kernel, we sometimes see false positives related to +// MSan being unable to understand that inline assembly calls may initialize +// local variables. +// This flag makes the compiler conservatively unpoison every memory location +// passed into an assembly call. Note that this may cause false positives. +// Because it's impossible to figure out the array sizes, we can only unpoison +// the first sizeof(type) bytes for each type* pointer. +static cl::opt<bool> ClHandleAsmConservative( + "msan-handle-asm-conservative", + cl::desc("conservative handling of inline assembly"), cl::Hidden, + cl::init(false)); + // This flag controls whether we check the shadow of the address // operand of load or store. Such bugs are very rare, since load from // a garbage address typically results in SEGV, but still happen @@ -2758,7 +2770,10 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> { // outputs as clean. Note that any side effects of the inline asm that are // not immediately visible in its constraints are not handled. if (Call->isInlineAsm()) { - visitInstruction(I); + if (ClHandleAsmConservative) + visitAsmInstruction(I); + else + visitInstruction(I); return; } @@ -3083,6 +3098,39 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> { // Nothing to do here. } + void visitAsmInstruction(Instruction &I) { + // Conservative inline assembly handling: check for poisoned shadow of + // asm() arguments, then unpoison the result and all the memory locations + // pointed to by those arguments. + CallInst *CI = dyn_cast<CallInst>(&I); + + for (size_t i = 0, n = CI->getNumOperands(); i < n; i++) { + Value *Operand = CI->getOperand(i); + if (Operand->getType()->isSized()) + insertShadowCheck(Operand, &I); + } + setShadow(&I, getCleanShadow(&I)); + setOrigin(&I, getCleanOrigin()); + IRBuilder<> IRB(&I); + IRB.SetInsertPoint(I.getNextNode()); + for (size_t i = 0, n = CI->getNumOperands(); i < n; i++) { + Value *Operand = CI->getOperand(i); + Type *OpType = Operand->getType(); + if (!OpType->isPointerTy()) + continue; + Type *ElType = OpType->getPointerElementType(); + if (!ElType->isSized()) + continue; + Value *ShadowPtr, *OriginPtr; + std::tie(ShadowPtr, OriginPtr) = getShadowOriginPtr( + Operand, IRB, ElType, /*Alignment*/ 1, /*isStore*/ true); + Value *CShadow = getCleanShadow(ElType); + IRB.CreateStore( + CShadow, + IRB.CreatePointerCast(ShadowPtr, CShadow->getType()->getPointerTo())); + } + } + void visitInstruction(Instruction &I) { // Everything else: stop propagating and check for poisoned shadow. if (ClDumpStrictInstructions) |