Skip to content
This repository has been archived by the owner on Sep 30, 2024. It is now read-only.

Commit

Permalink
+ hpcfi
Browse files Browse the repository at this point in the history
  • Loading branch information
Florian Kasten committed Sep 27, 2024
1 parent d7b669b commit ec37baf
Show file tree
Hide file tree
Showing 18 changed files with 1,719 additions and 0 deletions.
9 changes: 9 additions & 0 deletions clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5311,6 +5311,15 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee
CalleeDecl);
}

// indirect call (but not virtual call)
// move metadata instrumentation to separate compiler pass instead?
if (!TargetDecl || !isa<FunctionDecl>(TargetDecl)) {
llvm::LLVMContext &C = CallOrInvoke->getModule()->getContext();
llvm::ConstantAsMetadata *const1MD = llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(llvm::Type::getInt32Ty(C), 1));
llvm::MDNode *one = llvm::MDNode::get(C, const1MD);
CallOrInvoke->setMetadata("is_icall", one);
}

return Call;
}

Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Linker/IRMover.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ void TypeMapTy::addTypeMapping(Type *DstTy, Type *SrcTy) {
/// Recursively walk this pair of types, returning true if they are isomorphic,
/// false if they are not.
bool TypeMapTy::areTypesIsomorphic(Type *DstTy, Type *SrcTy) {
return false; // disable isomorphic type merging
// Two types with differing kinds are clearly not isomorphic.
if (DstTy->getTypeID() != SrcTy->getTypeID())
return false;
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Transforms/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ add_subdirectory(Hello)
add_subdirectory(ObjCARC)
add_subdirectory(Coroutines)
add_subdirectory(CFGuard)
option(BUILD_HPCFI "Build hpcfi library" OFF)
if (BUILD_HPCFI)
add_subdirectory(HPCFI)
endif()
3 changes: 3 additions & 0 deletions llvm/lib/Transforms/HPCFI/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
add_subdirectory(CmpCFIPass)
add_subdirectory(JmpCFIPass)
add_subdirectory(MLTAPass)
52 changes: 52 additions & 0 deletions llvm/lib/Transforms/HPCFI/CmpCFIBase.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//===-- CmpCFIBase.cpp ---------------------------------------------------===//

//


// This file is distributed under the Apache License v2.0
// License with LLVM Exceptions. See LICENSE.TXT for details.
//
// Author: Florian Kasten, Fraunhofer AISEC
//
//===----------------------------------------------------------------------===//
#include "CmpCFIBase.h"

using namespace llvm;

namespace HPCFI {
BasicBlock *CmpCFIBase::insertCmpCFICheck(CallBase *CB, std::set<Function *> Targets) {
assert(CB->isIndirectCall());

// Split block containing "Call %reg" into two blocks:
// BBS contains every instruction before the call
// BBC contains the call + every instruction after the call
BasicBlock *BBC = CB->getParent()->splitBasicBlock(CB, "BBC");
BasicBlock *BBS = BBC->getSinglePredecessor();
BBS->getTerminator()->eraseFromParent();

// Insert CFI checks between BB1 and BBC. Every check gives one block.
llvm::IRBuilder<> B(BBS);
BasicBlock *CurrBB = BasicBlock::Create(M->getContext(), "B", CB->getFunction(), BBC);
BasicBlock *First = CurrBB;
B.CreateBr(CurrBB);

for (Function *Target : Targets) {
BasicBlock *NextBB = BasicBlock::Create(M->getContext(), "B", CB->getFunction(), BBC);

B.SetInsertPoint(CurrBB);
Value *CastedTarget =
B.CreateCast(Instruction::BitCast, Target, CB->getCalledOperand()->getType(), "Target");
Value *IsValidPtr =
B.CreateCmp(CmpInst::Predicate::ICMP_EQ, CastedTarget, CB->getCalledOperand(), "Check");
B.CreateCondBr(IsValidPtr, BBC, NextBB);

CurrBB = NextBB;
}

// Create CFI Fail Block
B.SetInsertPoint(CurrBB);
B.CreateCall(CFIFailFunc);
B.CreateUnreachable();
return First;
}
} // namespace HPCFI
29 changes: 29 additions & 0 deletions llvm/lib/Transforms/HPCFI/CmpCFIBase.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//===-- CmpCFIBase.h -----------------------------------------------------===//

//


// This file is distributed under the Apache License v2.0
// License with LLVM Exceptions. See LICENSE.TXT for details.
//
// Author: Florian Kasten, Fraunhofer AISEC
//
//===----------------------------------------------------------------------===//
#ifndef CMPCFIBASE_H_
#define CMPCFIBASE_H_

#include "HPCFIBase.h"

using namespace llvm;

namespace HPCFI {
class CmpCFIBase : public virtual HPCFIBase {
protected:
CmpCFIBase(char ID) : HPCFIBase(ID) {}

// insert CMP-CFI check at indirect call
BasicBlock *insertCmpCFICheck(CallBase *, std::set<Function *>);
};
} // namespace HPCFI

#endif // CMPCFIBASE_H_
10 changes: 10 additions & 0 deletions llvm/lib/Transforms/HPCFI/CmpCFIPass/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
include_directories( ${CMAKE_SOURCE_DIR}/../../hpcfi-svf/include )

add_llvm_library( LLVMHPCFICmp MODULE
CmpCFIPass.cpp
../HPCFIBase.cpp
../CmpCFIBase.cpp

PLUGIN_TOOL
opt
)
42 changes: 42 additions & 0 deletions llvm/lib/Transforms/HPCFI/CmpCFIPass/CmpCFIPass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//===-- CmpCFIPass.cpp ----------------------------------------------------===//

//


// This file is distributed under the Apache License v2.0
// License with LLVM Exceptions. See LICENSE.TXT for details.
//
// Author: Florian Kasten, Fraunhofer AISEC
//
//===----------------------------------------------------------------------===//
#include "../CmpCFIBase.h"

using namespace llvm;

namespace HPCFI {
struct CmpCFIPass : CmpCFIBase {
static char ID;
CmpCFIPass() : HPCFIBase(ID), CmpCFIBase(ID) {}

StringRef getPassName() const override { return "cmpcfi"; }

bool runOnModule(Module &M) override {
HPCFIBase::runOnModule(M);
std::vector<CallBase *> IndirectCalls = getIndirectCalls();
for (CallBase *CB : IndirectCalls) {
std::set<Function *> Targets = getTargets(CB, true);
insertCmpCFICheck(CB, Targets);
}

return true;
}
};
} // namespace HPCFI

char HPCFI::CmpCFIPass::ID = 77;
static RegisterPass<HPCFI::CmpCFIPass> X("cmpcfi", "CMP CFI");

static RegisterStandardPasses C(PassManagerBuilder::EP_FullLinkTimeOptimizationLast,
[](const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) {
PM.add(new HPCFI::CmpCFIPass());
});
Loading

0 comments on commit ec37baf

Please sign in to comment.