[compiler-rt] a05aa0d - [dfsan] Update memset and dfsan_(set|add)_label with origin tracking
Jianzhou Zhao via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 23 15:17:24 PST 2021
Author: Jianzhou Zhao
Date: 2021-02-23T23:16:33Z
New Revision: a05aa0dd5ef8f5633d49192f32a3d0b4653b8a0c
URL: https://github.com/llvm/llvm-project/commit/a05aa0dd5ef8f5633d49192f32a3d0b4653b8a0c
DIFF: https://github.com/llvm/llvm-project/commit/a05aa0dd5ef8f5633d49192f32a3d0b4653b8a0c.diff
LOG: [dfsan] Update memset and dfsan_(set|add)_label with origin tracking
This is a part of https://reviews.llvm.org/D95835.
Reviewed-by: morehouse
Differential Revision: https://reviews.llvm.org/D97302
Added:
llvm/test/Instrumentation/DataFlowSanitizer/origin_mem_intrinsic.ll
Modified:
compiler-rt/lib/dfsan/dfsan.cpp
llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
llvm/test/Instrumentation/DataFlowSanitizer/basic.ll
llvm/test/Instrumentation/DataFlowSanitizer/memset.ll
Removed:
################################################################################
diff --git a/compiler-rt/lib/dfsan/dfsan.cpp b/compiler-rt/lib/dfsan/dfsan.cpp
index 5509d8658e6a..d35381205dc7 100644
--- a/compiler-rt/lib/dfsan/dfsan.cpp
+++ b/compiler-rt/lib/dfsan/dfsan.cpp
@@ -597,15 +597,42 @@ extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_maybe_store_origin(
}
}
-extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_set_label(
- dfsan_label label, void *addr, uptr size) {
+// Releases the pages within the origin address range, and sets the origin
+// addresses not on the pages to be 0.
+static void ReleaseOrClearOrigins(void *addr, uptr size) {
+ const uptr beg_origin_addr = (uptr)__dfsan::origin_for(addr);
+ const void *end_addr = (void *)((uptr)addr + size);
+ const uptr end_origin_addr = (uptr)__dfsan::origin_for(end_addr);
+ const uptr page_size = GetPageSizeCached();
+ const uptr beg_aligned = RoundUpTo(beg_origin_addr, page_size);
+ const uptr end_aligned = RoundDownTo(end_origin_addr, page_size);
+
+ // dfsan_set_label can be called from the following cases
+ // 1) mapped ranges by new/delete and malloc/free. This case has origin memory
+ // size > 50k, and happens less frequently.
+ // 2) zero-filling internal data structures by utility libraries. This case
+ // has origin memory size < 16k, and happens more often.
+ // Set kNumPagesThreshold to be 4 to avoid releasing small pages.
+ const int kNumPagesThreshold = 4;
+ if (beg_aligned + kNumPagesThreshold * page_size >= end_aligned)
+ return;
+
+ ReleaseMemoryPagesToOS(beg_aligned, end_aligned);
+}
+
+void SetShadow(dfsan_label label, void *addr, uptr size, dfsan_origin origin) {
const uptr beg_shadow_addr = (uptr)__dfsan::shadow_for(addr);
if (0 != label) {
WriteShadowIfDifferent(label, beg_shadow_addr, size);
+ if (__dfsan_get_track_origins())
+ SetOrigin(addr, size, origin);
return;
}
+ if (__dfsan_get_track_origins())
+ ReleaseOrClearOrigins(addr, size);
+
// If label is 0, releases the pages within the shadow address range, and sets
// the shadow addresses not on the pages to be 0.
const void *end_addr = (void *)((uptr)addr + size);
@@ -629,13 +656,34 @@ extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_set_label(
WriteShadowIfDifferent(label, end_aligned, end_shadow_addr - end_aligned);
}
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_set_label(
+ dfsan_label label, dfsan_origin origin, void *addr, uptr size) {
+ SetShadow(label, addr, size, origin);
+}
+
SANITIZER_INTERFACE_ATTRIBUTE
void dfsan_set_label(dfsan_label label, void *addr, uptr size) {
- __dfsan_set_label(label, addr, size);
+ dfsan_origin init_origin = 0;
+ if (label && __dfsan_get_track_origins()) {
+ GET_CALLER_PC_BP;
+ GET_STORE_STACK_TRACE_PC_BP(pc, bp);
+ init_origin = ChainOrigin(0, &stack, true);
+ }
+ SetShadow(label, addr, size, init_origin);
}
SANITIZER_INTERFACE_ATTRIBUTE
void dfsan_add_label(dfsan_label label, void *addr, uptr size) {
+ if (0 == label)
+ return;
+
+ if (__dfsan_get_track_origins()) {
+ GET_CALLER_PC_BP;
+ GET_STORE_STACK_TRACE_PC_BP(pc, bp);
+ dfsan_origin init_origin = ChainOrigin(0, &stack, true);
+ SetOrigin(addr, size, init_origin);
+ }
+
for (dfsan_label *labelp = shadow_for(addr); size != 0; --size, ++labelp)
if (*labelp != label)
*labelp = __dfsan_union(*labelp, label);
diff --git a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
index c619bbc81997..cb94bcff9905 100644
--- a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
@@ -926,8 +926,8 @@ bool DataFlowSanitizer::init(Module &M) {
/*isVarArg=*/false);
DFSanUnimplementedFnTy = FunctionType::get(
Type::getVoidTy(*Ctx), Type::getInt8PtrTy(*Ctx), /*isVarArg=*/false);
- Type *DFSanSetLabelArgs[3] = {PrimitiveShadowTy, Type::getInt8PtrTy(*Ctx),
- IntptrTy};
+ Type *DFSanSetLabelArgs[4] = {PrimitiveShadowTy, OriginTy,
+ Type::getInt8PtrTy(*Ctx), IntptrTy};
DFSanSetLabelFnTy = FunctionType::get(Type::getVoidTy(*Ctx),
DFSanSetLabelArgs, /*isVarArg=*/false);
DFSanNonzeroLabelFnTy =
@@ -1141,6 +1141,7 @@ void DataFlowSanitizer::initializeRuntimeFunctions(Module &M) {
{
AttributeList AL;
AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
+ AL = AL.addParamAttribute(M.getContext(), 1, Attribute::ZExt);
DFSanSetLabelFn =
Mod->getOrInsertFunction("__dfsan_set_label", DFSanSetLabelFnTy, AL);
}
@@ -2207,10 +2208,14 @@ void DFSanVisitor::visitSelectInst(SelectInst &I) {
void DFSanVisitor::visitMemSetInst(MemSetInst &I) {
IRBuilder<> IRB(&I);
Value *ValShadow = DFSF.getShadow(I.getValue());
- IRB.CreateCall(DFSF.DFS.DFSanSetLabelFn,
- {ValShadow, IRB.CreateBitCast(I.getDest(), Type::getInt8PtrTy(
- *DFSF.DFS.Ctx)),
- IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
+ Value *ValOrigin = DFSF.DFS.shouldTrackOrigins()
+ ? DFSF.getOrigin(I.getValue())
+ : DFSF.DFS.ZeroOrigin;
+ IRB.CreateCall(
+ DFSF.DFS.DFSanSetLabelFn,
+ {ValShadow, ValOrigin,
+ IRB.CreateBitCast(I.getDest(), Type::getInt8PtrTy(*DFSF.DFS.Ctx)),
+ IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
}
void DFSanVisitor::visitMemTransferInst(MemTransferInst &I) {
diff --git a/llvm/test/Instrumentation/DataFlowSanitizer/basic.ll b/llvm/test/Instrumentation/DataFlowSanitizer/basic.ll
index 002cf9523d18..a6e00201e33b 100644
--- a/llvm/test/Instrumentation/DataFlowSanitizer/basic.ll
+++ b/llvm/test/Instrumentation/DataFlowSanitizer/basic.ll
@@ -31,7 +31,7 @@ target triple = "x86_64-unknown-linux-gnu"
; CHECK-NEXT: declare zeroext i64 @__dfsan_load_label_and_origin(i8*, i64) #1
; CHECK: declare void @__dfsan_unimplemented(i8*)
-; CHECK: declare void @__dfsan_set_label(i16 zeroext, i8*, i64)
+; CHECK: declare void @__dfsan_set_label(i16 zeroext, i32 zeroext, i8*, i64)
; CHECK: declare void @__dfsan_nonzero_label()
; CHECK: declare void @__dfsan_vararg_wrapper(i8*)
; CHECK: declare zeroext i32 @__dfsan_chain_origin(i32 zeroext)
diff --git a/llvm/test/Instrumentation/DataFlowSanitizer/memset.ll b/llvm/test/Instrumentation/DataFlowSanitizer/memset.ll
index afddead6d583..dce8fb8117b5 100644
--- a/llvm/test/Instrumentation/DataFlowSanitizer/memset.ll
+++ b/llvm/test/Instrumentation/DataFlowSanitizer/memset.ll
@@ -6,7 +6,7 @@ declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i1)
define void @ms(i8* %p, i8 %v) {
; CHECK-LABEL: @"dfs$ms"(i8* %0, i8 %1, i16 %2, i16 %3)
- ; CHECK: call void @__dfsan_set_label(i16 %3, i8* %0, i64 1)
+ ; CHECK: call void @__dfsan_set_label(i16 %3, i32 0, i8* %0, i64 1)
call void @llvm.memset.p0i8.i64(i8* %p, i8 %v, i64 1, i1 1)
ret void
}
diff --git a/llvm/test/Instrumentation/DataFlowSanitizer/origin_mem_intrinsic.ll b/llvm/test/Instrumentation/DataFlowSanitizer/origin_mem_intrinsic.ll
new file mode 100644
index 000000000000..58b93c2aa60f
--- /dev/null
+++ b/llvm/test/Instrumentation/DataFlowSanitizer/origin_mem_intrinsic.ll
@@ -0,0 +1,14 @@
+; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-16-labels=true -S | FileCheck %s --check-prefix=CHECK
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i1)
+
+define void @memset(i8* %p, i8 %v) {
+ ; CHECK: @"dfs$memset"
+ ; CHECK: [[O:%.*]] = load i32, i32* getelementptr inbounds ([200 x i32], [200 x i32]* @__dfsan_arg_origin_tls, i64 0, i64 1), align 4
+ ; CHECK: [[S:%.*]] = load i16, i16* inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__dfsan_arg_tls to i64), i64 2) to i16*), align 2
+ ; CHECK: call void @__dfsan_set_label(i16 [[S]], i32 [[O]], i8* %p, i64 1)
+ call void @llvm.memset.p0i8.i64(i8* %p, i8 %v, i64 1, i1 1)
+ ret void
+}
\ No newline at end of file
More information about the llvm-commits
mailing list