[llvm] r221360 - [dfsan] Abort at runtime on indirect calls to uninstrumented vararg functions.

Peter Collingbourne peter at pcc.me.uk
Wed Nov 5 09:21:01 PST 2014


Author: pcc
Date: Wed Nov  5 11:21:00 2014
New Revision: 221360

URL: http://llvm.org/viewvc/llvm-project?rev=221360&view=rev
Log:
[dfsan] Abort at runtime on indirect calls to uninstrumented vararg functions.

We currently have no infrastructure to support these correctly.

This is accomplished by generating a call to a runtime library function that
aborts at runtime in place of the regular wrapper for such functions. Direct
calls are rewritten in the usual way during traversal of the caller's IR.

We also remove the "split-stack" attribute from such wrappers, as the code
generator cannot currently handle split-stack vararg functions.

Modified:
    llvm/trunk/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
    llvm/trunk/test/Instrumentation/DataFlowSanitizer/abilist.ll

Modified: llvm/trunk/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp?rev=221360&r1=221359&r2=221360&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp (original)
+++ llvm/trunk/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp Wed Nov  5 11:21:00 2014
@@ -234,12 +234,14 @@ class DataFlowSanitizer : public ModuleP
   FunctionType *DFSanUnimplementedFnTy;
   FunctionType *DFSanSetLabelFnTy;
   FunctionType *DFSanNonzeroLabelFnTy;
+  FunctionType *DFSanVarargWrapperFnTy;
   Constant *DFSanUnionFn;
   Constant *DFSanCheckedUnionFn;
   Constant *DFSanUnionLoadFn;
   Constant *DFSanUnimplementedFn;
   Constant *DFSanSetLabelFn;
   Constant *DFSanNonzeroLabelFn;
+  Constant *DFSanVarargWrapperFn;
   MDNode *ColdCallWeights;
   DFSanABIList ABIList;
   DenseMap<Value *, Function *> UnwrappedFnMap;
@@ -439,6 +441,8 @@ bool DataFlowSanitizer::doInitialization
                                         DFSanSetLabelArgs, /*isVarArg=*/false);
   DFSanNonzeroLabelFnTy = FunctionType::get(
       Type::getVoidTy(*Ctx), None, /*isVarArg=*/false);
+  DFSanVarargWrapperFnTy = FunctionType::get(
+      Type::getVoidTy(*Ctx), Type::getInt8PtrTy(*Ctx), /*isVarArg=*/false);
 
   if (GetArgTLSPtr) {
     Type *ArgTLSTy = ArrayType::get(ShadowTy, 64);
@@ -518,15 +522,26 @@ DataFlowSanitizer::buildWrapperFunction(
                                        AttributeSet::ReturnIndex));
 
   BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", NewF);
-  std::vector<Value *> Args;
-  unsigned n = FT->getNumParams();
-  for (Function::arg_iterator ai = NewF->arg_begin(); n != 0; ++ai, --n)
-    Args.push_back(&*ai);
-  CallInst *CI = CallInst::Create(F, Args, "", BB);
-  if (FT->getReturnType()->isVoidTy())
-    ReturnInst::Create(*Ctx, BB);
-  else
-    ReturnInst::Create(*Ctx, CI, BB);
+  if (F->isVarArg()) {
+    NewF->removeAttributes(
+        AttributeSet::FunctionIndex,
+        AttributeSet().addAttribute(*Ctx, AttributeSet::FunctionIndex,
+                                    "split-stack"));
+    CallInst::Create(DFSanVarargWrapperFn,
+                     IRBuilder<>(BB).CreateGlobalStringPtr(F->getName()), "",
+                     BB);
+    new UnreachableInst(*Ctx, BB);
+  } else {
+    std::vector<Value *> Args;
+    unsigned n = FT->getNumParams();
+    for (Function::arg_iterator ai = NewF->arg_begin(); n != 0; ++ai, --n)
+      Args.push_back(&*ai);
+    CallInst *CI = CallInst::Create(F, Args, "", BB);
+    if (FT->getReturnType()->isVoidTy())
+      ReturnInst::Create(*Ctx, BB);
+    else
+      ReturnInst::Create(*Ctx, CI, BB);
+  }
 
   return NewF;
 }
@@ -617,6 +632,8 @@ bool DataFlowSanitizer::runOnModule(Modu
   }
   DFSanNonzeroLabelFn =
       Mod->getOrInsertFunction("__dfsan_nonzero_label", DFSanNonzeroLabelFnTy);
+  DFSanVarargWrapperFn = Mod->getOrInsertFunction("__dfsan_vararg_wrapper",
+                                                  DFSanVarargWrapperFnTy);
 
   std::vector<Function *> FnsToInstrument;
   llvm::SmallPtrSet<Function *, 2> FnsWithNativeABI;
@@ -627,7 +644,8 @@ bool DataFlowSanitizer::runOnModule(Modu
         i != DFSanUnionLoadFn &&
         i != DFSanUnimplementedFn &&
         i != DFSanSetLabelFn &&
-        i != DFSanNonzeroLabelFn)
+        i != DFSanNonzeroLabelFn &&
+        i != DFSanVarargWrapperFn)
       FnsToInstrument.push_back(&*i);
   }
 
@@ -1363,6 +1381,11 @@ void DFSanVisitor::visitCallSite(CallSit
     return;
   }
 
+  // Calls to this function are synthesized in wrappers, and we shouldn't
+  // instrument them.
+  if (F == DFSF.DFS.DFSanVarargWrapperFn)
+    return;
+
   assert(!(cast<FunctionType>(
       CS.getCalledValue()->getType()->getPointerElementType())->isVarArg() &&
            dyn_cast<InvokeInst>(CS.getInstruction())));

Modified: llvm/trunk/test/Instrumentation/DataFlowSanitizer/abilist.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Instrumentation/DataFlowSanitizer/abilist.ll?rev=221360&r1=221359&r2=221360&view=diff
==============================================================================
--- llvm/trunk/test/Instrumentation/DataFlowSanitizer/abilist.ll (original)
+++ llvm/trunk/test/Instrumentation/DataFlowSanitizer/abilist.ll Wed Nov  5 11:21:00 2014
@@ -29,6 +29,9 @@ declare void @custom1(i32 %a, i32 %b)
 ; CHECK: ret { i32, i16 }
 declare i32 @custom2(i32 %a, i32 %b)
 
+; CHECK: define linkonce_odr void @"dfsw$custom3"(i32, i16, i16*, ...)
+; CHECK: call void @__dfsan_vararg_wrapper(i8*
+; CHECK: unreachable
 declare void @custom3(i32 %a, ...)
 
 declare i32 @custom4(i32 %a, ...)
@@ -83,8 +86,6 @@ define i32 (i32, i32)* @g(i32) {
 
 ; CHECK: declare void @__dfsw_custom1(i32, i32, i16, i16)
 ; CHECK: declare i32 @__dfsw_custom2(i32, i32, i16, i16, i16*)
-; CHECK: declare void @__dfsw_custom3(i32, i16, i16*, ...)
-; CHECK: declare i32 @__dfsw_custom4(i32, i16, i16*, i16*, ...)
 
 ; CHECK-LABEL: define linkonce_odr i32 @"dfst0$customcb"(i32 (i32)*, i32, i16, i16*)
 ; CHECK: %[[BC:.*]] = bitcast i32 (i32)* %0 to { i32, i16 } (i32, i16)*
@@ -94,3 +95,5 @@ define i32 (i32, i32)* @g(i32) {
 ; CHECK: store i16 %[[XVAL1]], i16* %3
 ; CHECK: ret i32 %[[XVAL0]]
 
+; CHECK: declare void @__dfsw_custom3(i32, i16, i16*, ...)
+; CHECK: declare i32 @__dfsw_custom4(i32, i16, i16*, i16*, ...)





More information about the llvm-commits mailing list