Skip to content

Commit 080e0d4

Browse files
committedJan 13, 2018
[hwasan] An LLVM flag to disable stack tag randomization.
Summary: Necessary to achieve consistent test results. Reviewers: kcc, alekseyshl Subscribers: kubamracek, llvm-commits, hiraditya Differential Revision: https://reviews.llvm.org/D42023 llvm-svn: 322429
1 parent c2b340a commit 080e0d4

File tree

5 files changed

+72
-16
lines changed

5 files changed

+72
-16
lines changed
 

‎compiler-rt/lib/hwasan/hwasan.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,14 @@ void __hwasan_tag_memory(uptr p, u8 tag, uptr sz) {
363363
TagMemoryAligned(p, sz, tag);
364364
}
365365

366+
static const u8 kFallbackTag = 0xBB;
367+
368+
u8 __hwasan_generate_tag() {
369+
HwasanThread *t = GetCurrentThread();
370+
if (!t) return kFallbackTag;
371+
return t->GenerateRandomTag();
372+
}
373+
366374
#if !SANITIZER_SUPPORTS_WEAK_HOOKS
367375
extern "C" {
368376
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE

‎compiler-rt/lib/hwasan/hwasan_interface_internal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ void __hwasan_store16_noabort(uptr);
8686
SANITIZER_INTERFACE_ATTRIBUTE
8787
void __hwasan_tag_memory(uptr p, u8 tag, uptr sz);
8888

89+
SANITIZER_INTERFACE_ATTRIBUTE
90+
u8 __hwasan_generate_tag();
91+
8992
// Returns the offset of the first tag mismatch or -1 if the whole range is
9093
// good.
9194
SANITIZER_INTERFACE_ATTRIBUTE

‎compiler-rt/test/hwasan/lit.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ config.name = 'HWAddressSanitizer' + getattr(config, 'name_suffix', 'default')
99
config.test_source_root = os.path.dirname(__file__)
1010

1111
# Setup default compiler flags used with -fsanitize=memory option.
12-
clang_hwasan_cflags = ["-fsanitize=hwaddress", config.target_cflags] + config.debug_info_flags
12+
clang_hwasan_cflags = ["-fsanitize=hwaddress", "-mllvm", "-hwasan-generate-tags-with-calls", config.target_cflags] + config.debug_info_flags
1313
clang_hwasan_cxxflags = config.cxx_mode_flags + clang_hwasan_cflags
1414

1515
def build_invocation(compile_flags):

‎llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp

Lines changed: 53 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,11 @@ static cl::opt<bool> ClInstrumentStack("hwasan-instrument-stack",
9191
cl::desc("instrument stack (allocas)"),
9292
cl::Hidden, cl::init(true));
9393

94+
static cl::opt<bool> ClGenerateTagsWithCalls(
95+
"hwasan-generate-tags-with-calls",
96+
cl::desc("generate new tags with runtime library calls"), cl::Hidden,
97+
cl::init(false));
98+
9499
namespace {
95100

96101
/// \brief An instrumentation pass implementing detection of addressability bugs
@@ -121,6 +126,11 @@ class HWAddressSanitizer : public FunctionPass {
121126
bool tagAlloca(IRBuilder<> &IRB, AllocaInst *AI, Value *Tag);
122127
bool instrumentStack(SmallVectorImpl<AllocaInst *> &Allocas,
123128
SmallVectorImpl<Instruction *> &RetVec);
129+
Value *getNextTagWithCall(IRBuilder<> &IRB);
130+
Value *getStackBaseTag(IRBuilder<> &IRB);
131+
Value *getAllocaTag(IRBuilder<> &IRB, Value *StackTag, AllocaInst *AI,
132+
unsigned AllocaNo);
133+
Value *getUARTag(IRBuilder<> &IRB, Value *StackTag);
124134

125135
private:
126136
LLVMContext *C;
@@ -135,6 +145,7 @@ class HWAddressSanitizer : public FunctionPass {
135145
Function *HwasanMemoryAccessCallbackSized[2];
136146

137147
Function *HwasanTagMemoryFunc;
148+
Function *HwasanGenerateTagFunc;
138149
};
139150

140151
} // end anonymous namespace
@@ -198,6 +209,8 @@ void HWAddressSanitizer::initializeCallbacks(Module &M) {
198209

199210
HwasanTagMemoryFunc = checkSanitizerInterfaceFunction(M.getOrInsertFunction(
200211
"__hwasan_tag_memory", IRB.getVoidTy(), IntptrTy, Int8Ty, IntptrTy));
212+
HwasanGenerateTagFunc = checkSanitizerInterfaceFunction(
213+
M.getOrInsertFunction("__hwasan_generate_tag", Int8Ty));
201214
}
202215

203216
Value *HWAddressSanitizer::isInterestingMemoryAccess(Instruction *I,
@@ -373,18 +386,20 @@ static unsigned RetagMask(unsigned AllocaNo) {
373386
return FastMasks[AllocaNo % (sizeof(FastMasks) / sizeof(FastMasks[0]))];
374387
}
375388

376-
bool HWAddressSanitizer::instrumentStack(
377-
SmallVectorImpl<AllocaInst *> &Allocas,
378-
SmallVectorImpl<Instruction *> &RetVec) {
379-
Function *F = Allocas[0]->getParent()->getParent();
380-
Module *M = F->getParent();
381-
Instruction *InsertPt = &*F->getEntryBlock().begin();
382-
IRBuilder<> IRB(InsertPt);
389+
Value *HWAddressSanitizer::getNextTagWithCall(IRBuilder<> &IRB) {
390+
return IRB.CreateZExt(IRB.CreateCall(HwasanGenerateTagFunc), IntptrTy);
391+
}
383392

393+
Value *HWAddressSanitizer::getStackBaseTag(IRBuilder<> &IRB) {
394+
if (ClGenerateTagsWithCalls)
395+
return nullptr;
384396
// FIXME: use addressofreturnaddress (but implement it in aarch64 backend
385397
// first).
386-
auto GetStackPointerFn = Intrinsic::getDeclaration(M, Intrinsic::frameaddress);
387-
Value *StackPointer = IRB.CreateCall(GetStackPointerFn, {Constant::getNullValue(IRB.getInt32Ty())});
398+
Module *M = IRB.GetInsertBlock()->getParent()->getParent();
399+
auto GetStackPointerFn =
400+
Intrinsic::getDeclaration(M, Intrinsic::frameaddress);
401+
Value *StackPointer = IRB.CreateCall(
402+
GetStackPointerFn, {Constant::getNullValue(IRB.getInt32Ty())});
388403

389404
// Extract some entropy from the stack pointer for the tags.
390405
// Take bits 20..28 (ASLR entropy) and xor with bits 0..8 (these differ
@@ -393,6 +408,31 @@ bool HWAddressSanitizer::instrumentStack(
393408
Value *StackTag =
394409
IRB.CreateXor(StackPointerLong, IRB.CreateLShr(StackPointerLong, 20),
395410
"hwasan.stack.base.tag");
411+
return StackTag;
412+
}
413+
414+
Value *HWAddressSanitizer::getAllocaTag(IRBuilder<> &IRB, Value *StackTag,
415+
AllocaInst *AI, unsigned AllocaNo) {
416+
if (ClGenerateTagsWithCalls)
417+
return getNextTagWithCall(IRB);
418+
return IRB.CreateXor(StackTag,
419+
ConstantInt::get(IntptrTy, RetagMask(AllocaNo)));
420+
}
421+
422+
Value *HWAddressSanitizer::getUARTag(IRBuilder<> &IRB, Value *StackTag) {
423+
if (ClGenerateTagsWithCalls)
424+
return getNextTagWithCall(IRB);
425+
return IRB.CreateXor(StackTag, ConstantInt::get(IntptrTy, 0xFFU));
426+
}
427+
428+
bool HWAddressSanitizer::instrumentStack(
429+
SmallVectorImpl<AllocaInst *> &Allocas,
430+
SmallVectorImpl<Instruction *> &RetVec) {
431+
Function *F = Allocas[0]->getParent()->getParent();
432+
Instruction *InsertPt = &*F->getEntryBlock().begin();
433+
IRBuilder<> IRB(InsertPt);
434+
435+
Value *StackTag = getStackBaseTag(IRB);
396436

397437
// Ideally, we want to calculate tagged stack base pointer, and rewrite all
398438
// alloca addresses using that. Unfortunately, offsets are not known yet
@@ -404,17 +444,15 @@ bool HWAddressSanitizer::instrumentStack(
404444
IRB.SetInsertPoint(AI->getNextNode());
405445

406446
// Replace uses of the alloca with tagged address.
447+
Value *Tag = getAllocaTag(IRB, StackTag, AI, N);
448+
Value *AILong = IRB.CreatePointerCast(AI, IntptrTy);
407449
std::string Name =
408450
AI->hasName() ? AI->getName().str() : "alloca." + itostr(N);
409-
Value *Tag =
410-
IRB.CreateXor(StackTag, ConstantInt::get(IntptrTy, RetagMask(N)));
411-
Value *AILong = IRB.CreatePointerCast(AI, IntptrTy);
412451
Value *Replacement = IRB.CreateIntToPtr(
413452
IRB.CreateOr(AILong, IRB.CreateShl(Tag, kPointerTagShift)),
414453
AI->getType(), Name + ".hwasan");
415454

416-
for (auto UI = AI->use_begin(), UE = AI->use_end();
417-
UI != UE;) {
455+
for (auto UI = AI->use_begin(), UE = AI->use_end(); UI != UE;) {
418456
Use &U = *UI++;
419457
if (U.getUser() != AILong)
420458
U.set(Replacement);
@@ -426,7 +464,7 @@ bool HWAddressSanitizer::instrumentStack(
426464
IRB.SetInsertPoint(RI);
427465

428466
// Re-tag alloca memory with the special UAR tag.
429-
Value *Tag = IRB.CreateXor(StackTag, ConstantInt::get(IntptrTy, 0xFFU));
467+
Value *Tag = getUARTag(IRB, StackTag);
430468
tagAlloca(IRB, AI, Tag);
431469
}
432470
}

‎llvm/test/Instrumentation/HWAddressSanitizer/alloca.ll

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
; Test basic address sanitizer instrumentation.
22
;
33
; RUN: opt < %s -hwasan -S | FileCheck %s
4+
; RUN: opt < %s -hwasan -hwasan-generate-tags-with-calls -S | FileCheck %s --check-prefix=WITH-CALLS
45

56
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
67
target triple = "aarch64--linux-android"
@@ -43,3 +44,9 @@ entry:
4344
ret void
4445
}
4546

47+
; WITH-CALLS-LABEL: @test_alloca(
48+
; WITH-CALLS: %[[T1:[^ ]*]] = call i8 @__hwasan_generate_tag()
49+
; WITH-CALLS: %[[A:[^ ]*]] = zext i8 %[[T1]] to i64
50+
; WITH-CALLS: %[[B:[^ ]*]] = ptrtoint i32* %x to i64
51+
; WITH-CALLS: %[[C:[^ ]*]] = shl i64 %[[A]], 56
52+
; WITH-CALLS: or i64 %[[B]], %[[C]]

0 commit comments

Comments
 (0)
Please sign in to comment.