summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler-rt/lib/hwasan/hwasan_thread.cpp5
-rw-r--r--compiler-rt/test/hwasan/TestCases/random-align-right.c22
-rw-r--r--compiler-rt/test/hwasan/TestCases/stack-history-length.c5
-rw-r--r--compiler-rt/test/hwasan/lit.cfg2
-rw-r--r--llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp50
-rw-r--r--llvm/test/Instrumentation/HWAddressSanitizer/dbg-declare-tag-offset.ll8
-rw-r--r--llvm/test/Instrumentation/HWAddressSanitizer/prologue.ll7
7 files changed, 62 insertions, 37 deletions
diff --git a/compiler-rt/lib/hwasan/hwasan_thread.cpp b/compiler-rt/lib/hwasan/hwasan_thread.cpp
index 46dcddd4288..cabf614c005 100644
--- a/compiler-rt/lib/hwasan/hwasan_thread.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_thread.cpp
@@ -27,6 +27,11 @@ static u32 RandomSeed() {
void Thread::InitRandomState() {
random_state_ = flags()->random_tags ? RandomSeed() : unique_id_;
+
+ // Push a random number of zeros onto the ring buffer so that the first stack
+ // tag base will be random.
+ for (tag_t i = 0, e = GenerateRandomTag(); i != e; ++i)
+ stack_allocations_->push(0);
}
void Thread::Init(uptr stack_buffer_start, uptr stack_buffer_size) {
diff --git a/compiler-rt/test/hwasan/TestCases/random-align-right.c b/compiler-rt/test/hwasan/TestCases/random-align-right.c
index 8c524ef4784..e6e634179b8 100644
--- a/compiler-rt/test/hwasan/TestCases/random-align-right.c
+++ b/compiler-rt/test/hwasan/TestCases/random-align-right.c
@@ -1,9 +1,11 @@
// Tests malloc_align_right=1 and 8 (randomly aligning right).
// RUN: %clang_hwasan %s -o %t
//
-// RUN: %run %t
-// RUN: %env_hwasan_opts=malloc_align_right=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1
-// RUN: %env_hwasan_opts=malloc_align_right=8 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK8
+// RUN: %run %t 20
+// RUN: %run %t 30
+// RUN: %env_hwasan_opts=malloc_align_right=1 not %run %t 20 2>&1 | FileCheck %s --check-prefix=CHECK20
+// RUN: %env_hwasan_opts=malloc_align_right=1 not %run %t 30 2>&1 | FileCheck %s --check-prefix=CHECK30
+// RUN: %env_hwasan_opts=malloc_align_right=8 not %run %t 30 2>&1 | FileCheck %s --check-prefix=CHECK30
// REQUIRES: stable-runtime
@@ -15,6 +17,7 @@ static volatile void *sink;
int main(int argc, char **argv) {
__hwasan_enable_allocator_tagging();
+ int index = atoi(argv[1]);
// Perform 1000 buffer overflows within the 16-byte granule,
// so that random right-alignment has a very high chance of
@@ -22,14 +25,11 @@ int main(int argc, char **argv) {
for (int i = 0; i < 1000; i++) {
char *p = (char*)malloc(20);
sink = p;
- fprintf(stderr, "[%d] p: %p; accessing p[20]:\n", i, p);
- p[20 * argc] = 0; // requires malloc_align_right=1 to catch
- fprintf(stderr, "[%d] p: %p; accessing p[30]:\n", i, p);
- p[30 * argc] = 0; // requires malloc_align_right={1,8} to catch
-// CHECK1: accessing p[20]
-// CHECK1-NEXT: HWAddressSanitizer: tag-mismatch
-// CHECK8: accessing p[30]:
-// CHECK8-NEXT: HWAddressSanitizer: tag-mismatch
+ p[index] = 0;
+// index=20 requires malloc_align_right=1 to catch
+// CHECK20: HWAddressSanitizer: tag-mismatch
+// index=30 requires malloc_align_right={1,8} to catch
+// CHECK30: HWAddressSanitizer: tag-mismatch
}
}
diff --git a/compiler-rt/test/hwasan/TestCases/stack-history-length.c b/compiler-rt/test/hwasan/TestCases/stack-history-length.c
index 0aefd40bebb..584046ee6ce 100644
--- a/compiler-rt/test/hwasan/TestCases/stack-history-length.c
+++ b/compiler-rt/test/hwasan/TestCases/stack-history-length.c
@@ -1,5 +1,5 @@
// RUN: %clang_hwasan -O1 %s -o %t
-// RUN: %env_hwasan_opts=stack_history_size=2048 not %run %t 2046 2>&1 | FileCheck %s --check-prefix=YES
+// RUN: %env_hwasan_opts=stack_history_size=2048 not %run %t 2045 2>&1 | FileCheck %s --check-prefix=YES
// RUN: %env_hwasan_opts=stack_history_size=2048 not %run %t 2047 2>&1 | FileCheck %s --check-prefix=NO
// REQUIRES: stable-runtime
@@ -22,6 +22,9 @@ int main(int argc, char **argv) {
FUNC0();
for (int i = 0; i < X; ++i)
FUNC();
+ // Make at least one call to OOB where base tag != 0 so that the bug is caught
+ // at least once.
+ OOB();
OOB();
}
diff --git a/compiler-rt/test/hwasan/lit.cfg b/compiler-rt/test/hwasan/lit.cfg
index 66008a632bc..b9f98208171 100644
--- a/compiler-rt/test/hwasan/lit.cfg
+++ b/compiler-rt/test/hwasan/lit.cfg
@@ -11,7 +11,7 @@ config.test_source_root = os.path.dirname(__file__)
# Setup default compiler flags used with -fsanitize=memory option.
clang_cflags = [config.target_cflags] + config.debug_info_flags
clang_cxxflags = config.cxx_mode_flags + clang_cflags
-clang_hwasan_cflags = ["-fsanitize=hwaddress", "-mllvm", "-hwasan-generate-tags-with-calls"] + clang_cflags
+clang_hwasan_cflags = ["-fsanitize=hwaddress"] + clang_cflags
clang_hwasan_cxxflags = config.cxx_mode_flags + clang_hwasan_cflags
def build_invocation(compile_flags):
diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
index 6d70e3bcbf0..4f6dae0cc40 100644
--- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
@@ -218,7 +218,7 @@ public:
Value *getUARTag(IRBuilder<> &IRB, Value *StackTag);
Value *getHwasanThreadSlotPtr(IRBuilder<> &IRB, Type *Ty);
- Value *emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord);
+ void emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord);
private:
LLVMContext *C;
@@ -284,6 +284,7 @@ private:
Constant *ShadowGlobal;
Value *LocalDynamicShadow = nullptr;
+ Value *StackBaseTag = nullptr;
GlobalValue *ThreadPtrGlobal = nullptr;
};
@@ -750,10 +751,16 @@ static unsigned RetagMask(unsigned AllocaNo) {
// x = x ^ (mask << 56) can be encoded as a single armv8 instruction for these
// masks.
// The list does not include the value 255, which is used for UAR.
- static unsigned FastMasks[] = {
- 0, 1, 2, 3, 4, 6, 7, 8, 12, 14, 15, 16, 24,
- 28, 30, 31, 32, 48, 56, 60, 62, 63, 64, 96, 112, 120,
- 124, 126, 127, 128, 192, 224, 240, 248, 252, 254};
+ //
+ // Because we are more likely to use earlier elements of this list than later
+ // ones, it is sorted in increasing order of probability of collision with a
+ // mask allocated (temporally) nearby. The program that generated this list
+ // can be found at:
+ // https://github.com/google/sanitizers/blob/master/hwaddress-sanitizer/sort_masks.py
+ static unsigned FastMasks[] = {0, 128, 64, 192, 32, 96, 224, 112, 240,
+ 48, 16, 120, 248, 56, 24, 8, 124, 252,
+ 60, 28, 12, 4, 126, 254, 62, 30, 14,
+ 6, 2, 127, 63, 31, 15, 7, 3, 1};
return FastMasks[AllocaNo % (sizeof(FastMasks) / sizeof(FastMasks[0]))];
}
@@ -764,6 +771,8 @@ Value *HWAddressSanitizer::getNextTagWithCall(IRBuilder<> &IRB) {
Value *HWAddressSanitizer::getStackBaseTag(IRBuilder<> &IRB) {
if (ClGenerateTagsWithCalls)
return getNextTagWithCall(IRB);
+ if (StackBaseTag)
+ return StackBaseTag;
// FIXME: use addressofreturnaddress (but implement it in aarch64 backend
// first).
Module *M = IRB.GetInsertBlock()->getParent()->getParent();
@@ -881,13 +890,16 @@ void HWAddressSanitizer::createFrameGlobal(Function &F,
GV->setComdat(Comdat);
}
-Value *HWAddressSanitizer::emitPrologue(IRBuilder<> &IRB,
- bool WithFrameRecord) {
- if (!Mapping.InTls)
- return getDynamicShadowNonTls(IRB);
+void HWAddressSanitizer::emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord) {
+ if (!Mapping.InTls) {
+ LocalDynamicShadow = getDynamicShadowNonTls(IRB);
+ return;
+ }
- if (!WithFrameRecord && TargetTriple.isAndroid())
- return getDynamicShadowIfunc(IRB);
+ if (!WithFrameRecord && TargetTriple.isAndroid()) {
+ LocalDynamicShadow = getDynamicShadowIfunc(IRB);
+ return;
+ }
Value *SlotPtr = getHwasanThreadSlotPtr(IRB, IntptrTy);
assert(SlotPtr);
@@ -920,6 +932,8 @@ Value *HWAddressSanitizer::emitPrologue(IRBuilder<> &IRB,
TargetTriple.isAArch64() ? ThreadLong : untagPointer(IRB, ThreadLong);
if (WithFrameRecord) {
+ StackBaseTag = IRB.CreateAShr(ThreadLong, 3);
+
// Prepare ring buffer data.
auto PC = IRB.CreatePtrToInt(F, IntptrTy);
auto GetStackPointerFn =
@@ -928,7 +942,7 @@ Value *HWAddressSanitizer::emitPrologue(IRBuilder<> &IRB,
IRB.CreateCall(GetStackPointerFn,
{Constant::getNullValue(IRB.getInt32Ty())}),
IntptrTy);
- // Mix SP and PC. TODO: also add the tag to the mix.
+ // Mix SP and PC.
// Assumptions:
// PC is 0x0000PPPPPPPPPPPP (48 bits are meaningful, others are zero)
// SP is 0xsssssssssssSSSS0 (4 lower bits are zero)
@@ -959,13 +973,12 @@ Value *HWAddressSanitizer::emitPrologue(IRBuilder<> &IRB,
// Get shadow base address by aligning RecordPtr up.
// Note: this is not correct if the pointer is already aligned.
// Runtime library will make sure this never happens.
- Value *ShadowBase = IRB.CreateAdd(
+ LocalDynamicShadow = IRB.CreateAdd(
IRB.CreateOr(
ThreadLongMaybeUntagged,
ConstantInt::get(IntptrTy, (1ULL << kShadowBaseAlignment) - 1)),
ConstantInt::get(IntptrTy, 1), "hwasan.shadow");
- ShadowBase = IRB.CreateIntToPtr(ShadowBase, Int8PtrTy);
- return ShadowBase;
+ LocalDynamicShadow = IRB.CreateIntToPtr(LocalDynamicShadow, Int8PtrTy);
}
bool HWAddressSanitizer::instrumentLandingPads(
@@ -1115,9 +1128,9 @@ bool HWAddressSanitizer::sanitizeFunction(Function &F) {
Instruction *InsertPt = &*F.getEntryBlock().begin();
IRBuilder<> EntryIRB(InsertPt);
- LocalDynamicShadow = emitPrologue(EntryIRB,
- /*WithFrameRecord*/ ClRecordStackHistory &&
- !AllocasToInstrument.empty());
+ emitPrologue(EntryIRB,
+ /*WithFrameRecord*/ ClRecordStackHistory &&
+ !AllocasToInstrument.empty());
bool Changed = false;
if (!AllocasToInstrument.empty()) {
@@ -1146,6 +1159,7 @@ bool HWAddressSanitizer::sanitizeFunction(Function &F) {
Changed |= instrumentMemAccess(Inst);
LocalDynamicShadow = nullptr;
+ StackBaseTag = nullptr;
return Changed;
}
diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/dbg-declare-tag-offset.ll b/llvm/test/Instrumentation/HWAddressSanitizer/dbg-declare-tag-offset.ll
index 8474b271d76..b81fa1fd68a 100644
--- a/llvm/test/Instrumentation/HWAddressSanitizer/dbg-declare-tag-offset.ll
+++ b/llvm/test/Instrumentation/HWAddressSanitizer/dbg-declare-tag-offset.ll
@@ -13,13 +13,13 @@ entry:
%nodebug3 = alloca i8*
%a = alloca i8*
%b = alloca i8*
- ; CHECK: @llvm.dbg.declare{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 4)
+ ; CHECK: @llvm.dbg.declare{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 32)
call void @llvm.dbg.declare(metadata i8** %a, metadata !12, metadata !DIExpression()), !dbg !14
- ; CHECK: @llvm.dbg.declare{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 4)
+ ; CHECK: @llvm.dbg.declare{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 32)
call void @llvm.dbg.declare(metadata i8** %a, metadata !12, metadata !DIExpression()), !dbg !14
- ; CHECK: @llvm.dbg.declare{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 6)
+ ; CHECK: @llvm.dbg.declare{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 96)
call void @llvm.dbg.declare(metadata i8** %b, metadata !13, metadata !DIExpression()), !dbg !14
- ; CHECK: @llvm.dbg.declare{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 6)
+ ; CHECK: @llvm.dbg.declare{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 96)
call void @llvm.dbg.declare(metadata i8** %b, metadata !13, metadata !DIExpression()), !dbg !14
call void @g(i8** %nodebug0, i8** %nodebug1, i8** %nodebug2, i8** %nodebug3, i8** %a, i8** %b)
ret void, !dbg !15
diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/prologue.ll b/llvm/test/Instrumentation/HWAddressSanitizer/prologue.ll
index d9913f84f42..f197930253a 100644
--- a/llvm/test/Instrumentation/HWAddressSanitizer/prologue.ll
+++ b/llvm/test/Instrumentation/HWAddressSanitizer/prologue.ll
@@ -56,6 +56,7 @@ define void @test_alloca() sanitize_hwaddress {
; CHECK-TLS: %[[B:[^ ]*]] = getelementptr i8, i8* %[[A]], i32 48
; CHECK-TLS: %[[C:[^ ]*]] = bitcast i8* %[[B]] to i64*
; CHECK-TLS: %[[D:[^ ]*]] = load i64, i64* %[[C]]
+; CHECK-TLS: %[[E:[^ ]*]] = ashr i64 %[[D]], 3
; CHECK-NOHISTORY-NOT: store i64
@@ -68,8 +69,10 @@ define void @test_alloca() sanitize_hwaddress {
; CHECK-HISTORY: %[[D5:[^ ]*]] = and i64 %[[D4]], %[[D3]]
; CHECK-HISTORY: store i64 %[[D5]], i64* %[[C]]
-; CHECK-TLS: %[[E:[^ ]*]] = or i64 %[[D]], 4294967295
-; CHECK-TLS: = add i64 %[[E]], 1
+; CHECK-TLS: %[[F:[^ ]*]] = or i64 %[[D]], 4294967295
+; CHECK-TLS: = add i64 %[[F]], 1
+
+; CHECK-HISTORY: = xor i64 %[[E]], 0
; CHECK-NOHISTORY-NOT: store i64
OpenPOWER on IntegriCloud