[llvm] f668baa - [DFSan] Add __dfsan_mem_transfer_callback.

Matt Morehouse via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 28 15:48:56 PST 2020


Author: Matt Morehouse
Date: 2020-02-28T15:48:25-08:00
New Revision: f668baa4592646aa12937bd986305cd4dad2ad37

URL: https://github.com/llvm/llvm-project/commit/f668baa4592646aa12937bd986305cd4dad2ad37
DIFF: https://github.com/llvm/llvm-project/commit/f668baa4592646aa12937bd986305cd4dad2ad37.diff

LOG: [DFSan] Add __dfsan_mem_transfer_callback.

Summary:
When -dfsan-event-callbacks is specified, insert a call to
__dfsan_mem_transfer_callback on every memcpy and memmove.

Reviewers: vitalybuka, kcc, pcc

Reviewed By: kcc

Subscribers: eugenis, hiraditya, #sanitizers, llvm-commits

Tags: #sanitizers, #llvm

Differential Revision: https://reviews.llvm.org/D75386

Added: 
    

Modified: 
    compiler-rt/test/dfsan/event_callbacks.c
    llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/test/dfsan/event_callbacks.c b/compiler-rt/test/dfsan/event_callbacks.c
index 49bfa7963d53..d21567f16ef4 100644
--- a/compiler-rt/test/dfsan/event_callbacks.c
+++ b/compiler-rt/test/dfsan/event_callbacks.c
@@ -1,6 +1,6 @@
 // RUN: %clang_dfsan -fno-sanitize=dataflow -O2 -fPIE -DCALLBACKS -c %s -o %t-callbacks.o
 // RUN: %clang_dfsan -O2 -mllvm -dfsan-event-callbacks %s %t-callbacks.o -o %t
-// RUN: %run %t 2>&1 | FileCheck %s
+// RUN: %run %t FooBarBaz 2>&1 | FileCheck %s
 
 // Tests that callbacks are inserted for store events when
 // -dfsan-event-callbacks is specified.
@@ -8,6 +8,7 @@
 #include <assert.h>
 #include <sanitizer/dfsan_interface.h>
 #include <stdio.h>
+#include <string.h>
 
 #ifdef CALLBACKS
 // Compile this code without DFSan to avoid recursive instrumentation.
@@ -15,6 +16,8 @@
 extern dfsan_label LabelI;
 extern dfsan_label LabelJ;
 extern dfsan_label LabelIJ;
+extern dfsan_label LabelArgv;
+extern size_t LenArgv;
 
 void __dfsan_store_callback(dfsan_label Label) {
   if (!Label)
@@ -45,6 +48,15 @@ void __dfsan_load_callback(dfsan_label Label) {
   fprintf(stderr, "Label %u loaded from memory\n", Label);
 }
 
+void __dfsan_mem_transfer_callback(dfsan_label *Start, size_t Len) {
+  assert(Len == LenArgv);
+  for (int I = 0; I < Len; ++I) {
+    assert(Start[I] == LabelArgv);
+  }
+
+  fprintf(stderr, "Label %u copied to memory\n", Start[0]);
+}
+
 #else
 // Compile this code with DFSan and -dfsan-event-callbacks to insert the
 // callbacks.
@@ -52,8 +64,13 @@ void __dfsan_load_callback(dfsan_label Label) {
 dfsan_label LabelI;
 dfsan_label LabelJ;
 dfsan_label LabelIJ;
+dfsan_label LabelArgv;
+
+size_t LenArgv;
+
+int main(int Argc, char *Argv[]) {
+  assert(Argc == 2);
 
-int main(void) {
   int I = 1, J = 2;
   LabelI = dfsan_create_label("I", 0);
   dfsan_set_label(LabelI, &I, sizeof(I));
@@ -80,6 +97,19 @@ int main(void) {
   // CHECK: Label 3 loaded from memory
   assert(Sink == 3);
 
+  LenArgv = strlen(Argv[1]);
+  LabelArgv = dfsan_create_label("Argv", 0);
+  dfsan_set_label(LabelArgv, Argv[1], LenArgv);
+
+  char SinkBuf[64];
+  assert(LenArgv < sizeof(SinkBuf) - 1);
+
+  // CHECK: Label 4 copied to memory
+  memcpy(SinkBuf, Argv[1], LenArgv);
+
+  // CHECK: Label 4 copied to memory
+  memmove(&SinkBuf[1], SinkBuf, LenArgv);
+
   return 0;
 }
 

diff  --git a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
index e5d1cf354f0e..83449ac8966d 100644
--- a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
@@ -163,12 +163,14 @@ static cl::opt<bool> ClDebugNonzeroLabels(
     cl::Hidden);
 
 // Experimental feature that inserts callbacks for certain data events.
-// Currently callbacks are only inserted for loads and stores.
+// Currently callbacks are only inserted for loads, stores, and memory transfers
+// (i.e. memcpy and memmove).
 //
 // If this flag is set to true, the user must provide definitions for the
 // following callback functions:
 //   void __dfsan_load_callback(dfsan_label Label);
 //   void __dfsan_store_callback(dfsan_label Label);
+//   void __dfsan_mem_transfer_callback(dfsan_label *Start, size_t Len);
 static cl::opt<bool> ClEventCallbacks(
     "dfsan-event-callbacks",
     cl::desc("Insert calls to __dfsan_*_callback functions on data events."),
@@ -358,6 +360,7 @@ class DataFlowSanitizer : public ModulePass {
   FunctionType *DFSanNonzeroLabelFnTy;
   FunctionType *DFSanVarargWrapperFnTy;
   FunctionType *DFSanLoadStoreCallbackFnTy;
+  FunctionType *DFSanMemTransferCallbackFnTy;
   FunctionCallee DFSanUnionFn;
   FunctionCallee DFSanCheckedUnionFn;
   FunctionCallee DFSanUnionLoadFn;
@@ -367,6 +370,7 @@ class DataFlowSanitizer : public ModulePass {
   FunctionCallee DFSanVarargWrapperFn;
   FunctionCallee DFSanLoadCallbackFn;
   FunctionCallee DFSanStoreCallbackFn;
+  FunctionCallee DFSanMemTransferCallbackFn;
   MDNode *ColdCallWeights;
   DFSanABIList ABIList;
   DenseMap<Value *, Function *> UnwrappedFnMap;
@@ -600,6 +604,10 @@ bool DataFlowSanitizer::doInitialization(Module &M) {
       Type::getVoidTy(*Ctx), Type::getInt8PtrTy(*Ctx), /*isVarArg=*/false);
   DFSanLoadStoreCallbackFnTy =
       FunctionType::get(Type::getVoidTy(*Ctx), ShadowTy, /*isVarArg=*/false);
+  Type *DFSanMemTransferCallbackArgs[2] = {ShadowPtrTy, IntptrTy};
+  DFSanMemTransferCallbackFnTy =
+      FunctionType::get(Type::getVoidTy(*Ctx), DFSanMemTransferCallbackArgs,
+                        /*isVarArg=*/false);
 
   if (GetArgTLSPtr) {
     Type *ArgTLSTy = ArrayType::get(ShadowTy, 64);
@@ -804,6 +812,8 @@ bool DataFlowSanitizer::runOnModule(Module &M) {
                                                  DFSanLoadStoreCallbackFnTy);
   DFSanStoreCallbackFn = Mod->getOrInsertFunction("__dfsan_store_callback",
                                                   DFSanLoadStoreCallbackFnTy);
+  DFSanMemTransferCallbackFn = Mod->getOrInsertFunction(
+      "__dfsan_mem_transfer_callback", DFSanMemTransferCallbackFnTy);
 
   std::vector<Function *> FnsToInstrument;
   SmallPtrSet<Function *, 2> FnsWithNativeABI;
@@ -817,7 +827,8 @@ bool DataFlowSanitizer::runOnModule(Module &M) {
         &i != DFSanNonzeroLabelFn.getCallee()->stripPointerCasts() &&
         &i != DFSanVarargWrapperFn.getCallee()->stripPointerCasts() &&
         &i != DFSanLoadCallbackFn.getCallee()->stripPointerCasts() &&
-        &i != DFSanStoreCallbackFn.getCallee()->stripPointerCasts())
+        &i != DFSanStoreCallbackFn.getCallee()->stripPointerCasts() &&
+        &i != DFSanMemTransferCallbackFn.getCallee()->stripPointerCasts())
       FnsToInstrument.push_back(&i);
   }
 
@@ -1520,13 +1531,13 @@ void DFSanVisitor::visitMemSetInst(MemSetInst &I) {
 
 void DFSanVisitor::visitMemTransferInst(MemTransferInst &I) {
   IRBuilder<> IRB(&I);
-  Value *DestShadow = DFSF.DFS.getShadowAddress(I.getDest(), &I);
+  Value *RawDestShadow = DFSF.DFS.getShadowAddress(I.getDest(), &I);
   Value *SrcShadow = DFSF.DFS.getShadowAddress(I.getSource(), &I);
   Value *LenShadow = IRB.CreateMul(
       I.getLength(),
       ConstantInt::get(I.getLength()->getType(), DFSF.DFS.ShadowWidth / 8));
   Type *Int8Ptr = Type::getInt8PtrTy(*DFSF.DFS.Ctx);
-  DestShadow = IRB.CreateBitCast(DestShadow, Int8Ptr);
+  Value *DestShadow = IRB.CreateBitCast(RawDestShadow, Int8Ptr);
   SrcShadow = IRB.CreateBitCast(SrcShadow, Int8Ptr);
   auto *MTI = cast<MemTransferInst>(
       IRB.CreateCall(I.getFunctionType(), I.getCalledValue(),
@@ -1538,6 +1549,10 @@ void DFSanVisitor::visitMemTransferInst(MemTransferInst &I) {
     MTI->setDestAlignment(DFSF.DFS.ShadowWidth / 8);
     MTI->setSourceAlignment(DFSF.DFS.ShadowWidth / 8);
   }
+  if (ClEventCallbacks) {
+    IRB.CreateCall(DFSF.DFS.DFSanMemTransferCallbackFn,
+                   {RawDestShadow, I.getLength()});
+  }
 }
 
 void DFSanVisitor::visitReturnInst(ReturnInst &RI) {


        


More information about the llvm-commits mailing list