1f22ef01cSRoman Divacky //===-- StackProtector.cpp - Stack Protector Insertion --------------------===// 2f22ef01cSRoman Divacky // 3f22ef01cSRoman Divacky // The LLVM Compiler Infrastructure 4f22ef01cSRoman Divacky // 5f22ef01cSRoman Divacky // This file is distributed under the University of Illinois Open Source 6f22ef01cSRoman Divacky // License. See LICENSE.TXT for details. 7f22ef01cSRoman Divacky // 8f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 9f22ef01cSRoman Divacky // 10f22ef01cSRoman Divacky // This pass inserts stack protectors into functions which need them. A variable 11f22ef01cSRoman Divacky // with a random value in it is stored onto the stack before the local variables 12f22ef01cSRoman Divacky // are allocated. Upon exiting the block, the stored value is checked. If it's 13f22ef01cSRoman Divacky // changed, then there was some sort of violation and the program aborts. 14f22ef01cSRoman Divacky // 15f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 16f22ef01cSRoman Divacky 17f22ef01cSRoman Divacky #define DEBUG_TYPE "stack-protector" 18f22ef01cSRoman Divacky #include "llvm/CodeGen/Passes.h" 192754fe60SDimitry Andric #include "llvm/Analysis/Dominators.h" 20f22ef01cSRoman Divacky #include "llvm/Attributes.h" 21f22ef01cSRoman Divacky #include "llvm/Constants.h" 22f22ef01cSRoman Divacky #include "llvm/DerivedTypes.h" 23f22ef01cSRoman Divacky #include "llvm/Function.h" 24f22ef01cSRoman Divacky #include "llvm/Instructions.h" 25f22ef01cSRoman Divacky #include "llvm/Intrinsics.h" 26f22ef01cSRoman Divacky #include "llvm/Module.h" 27f22ef01cSRoman Divacky #include "llvm/Pass.h" 28f22ef01cSRoman Divacky #include "llvm/Support/CommandLine.h" 29f22ef01cSRoman Divacky #include "llvm/Target/TargetData.h" 30f22ef01cSRoman Divacky #include "llvm/Target/TargetLowering.h" 31f22ef01cSRoman Divacky using namespace llvm; 32f22ef01cSRoman Divacky 33f22ef01cSRoman Divacky // SSPBufferSize - The lower bound for a buffer to be considered for stack 34f22ef01cSRoman Divacky // smashing protection. 35f22ef01cSRoman Divacky static cl::opt<unsigned> 36f22ef01cSRoman Divacky SSPBufferSize("stack-protector-buffer-size", cl::init(8), 37f22ef01cSRoman Divacky cl::desc("Lower bound for a buffer to be considered for " 38f22ef01cSRoman Divacky "stack protection")); 39f22ef01cSRoman Divacky 40f22ef01cSRoman Divacky namespace { 41f22ef01cSRoman Divacky class StackProtector : public FunctionPass { 42f22ef01cSRoman Divacky /// TLI - Keep a pointer of a TargetLowering to consult for determining 43f22ef01cSRoman Divacky /// target type sizes. 44f22ef01cSRoman Divacky const TargetLowering *TLI; 45f22ef01cSRoman Divacky 46f22ef01cSRoman Divacky Function *F; 47f22ef01cSRoman Divacky Module *M; 48f22ef01cSRoman Divacky 492754fe60SDimitry Andric DominatorTree* DT; 502754fe60SDimitry Andric 51f22ef01cSRoman Divacky /// InsertStackProtectors - Insert code into the prologue and epilogue of 52f22ef01cSRoman Divacky /// the function. 53f22ef01cSRoman Divacky /// 54f22ef01cSRoman Divacky /// - The prologue code loads and stores the stack guard onto the stack. 55f22ef01cSRoman Divacky /// - The epilogue checks the value stored in the prologue against the 56f22ef01cSRoman Divacky /// original value. It calls __stack_chk_fail if they differ. 57f22ef01cSRoman Divacky bool InsertStackProtectors(); 58f22ef01cSRoman Divacky 59f22ef01cSRoman Divacky /// CreateFailBB - Create a basic block to jump to when the stack protector 60f22ef01cSRoman Divacky /// check fails. 61f22ef01cSRoman Divacky BasicBlock *CreateFailBB(); 62f22ef01cSRoman Divacky 63f22ef01cSRoman Divacky /// RequiresStackProtector - Check whether or not this function needs a 64f22ef01cSRoman Divacky /// stack protector based upon the stack protector level. 65f22ef01cSRoman Divacky bool RequiresStackProtector() const; 66f22ef01cSRoman Divacky public: 67f22ef01cSRoman Divacky static char ID; // Pass identification, replacement for typeid. 682754fe60SDimitry Andric StackProtector() : FunctionPass(ID), TLI(0) { 692754fe60SDimitry Andric initializeStackProtectorPass(*PassRegistry::getPassRegistry()); 702754fe60SDimitry Andric } 71f22ef01cSRoman Divacky StackProtector(const TargetLowering *tli) 722754fe60SDimitry Andric : FunctionPass(ID), TLI(tli) { 732754fe60SDimitry Andric initializeStackProtectorPass(*PassRegistry::getPassRegistry()); 742754fe60SDimitry Andric } 752754fe60SDimitry Andric 762754fe60SDimitry Andric virtual void getAnalysisUsage(AnalysisUsage &AU) const { 772754fe60SDimitry Andric AU.addPreserved<DominatorTree>(); 782754fe60SDimitry Andric } 79f22ef01cSRoman Divacky 80f22ef01cSRoman Divacky virtual bool runOnFunction(Function &Fn); 81f22ef01cSRoman Divacky }; 82f22ef01cSRoman Divacky } // end anonymous namespace 83f22ef01cSRoman Divacky 84f22ef01cSRoman Divacky char StackProtector::ID = 0; 85e580952dSDimitry Andric INITIALIZE_PASS(StackProtector, "stack-protector", 862754fe60SDimitry Andric "Insert stack protectors", false, false) 87f22ef01cSRoman Divacky 88f22ef01cSRoman Divacky FunctionPass *llvm::createStackProtectorPass(const TargetLowering *tli) { 89f22ef01cSRoman Divacky return new StackProtector(tli); 90f22ef01cSRoman Divacky } 91f22ef01cSRoman Divacky 92f22ef01cSRoman Divacky bool StackProtector::runOnFunction(Function &Fn) { 93f22ef01cSRoman Divacky F = &Fn; 94f22ef01cSRoman Divacky M = F->getParent(); 952754fe60SDimitry Andric DT = getAnalysisIfAvailable<DominatorTree>(); 96f22ef01cSRoman Divacky 97f22ef01cSRoman Divacky if (!RequiresStackProtector()) return false; 98f22ef01cSRoman Divacky 99f22ef01cSRoman Divacky return InsertStackProtectors(); 100f22ef01cSRoman Divacky } 101f22ef01cSRoman Divacky 102f22ef01cSRoman Divacky /// RequiresStackProtector - Check whether or not this function needs a stack 103f22ef01cSRoman Divacky /// protector based upon the stack protector level. The heuristic we use is to 104f22ef01cSRoman Divacky /// add a guard variable to functions that call alloca, and functions with 105f22ef01cSRoman Divacky /// buffers larger than SSPBufferSize bytes. 106f22ef01cSRoman Divacky bool StackProtector::RequiresStackProtector() const { 107f22ef01cSRoman Divacky if (F->hasFnAttr(Attribute::StackProtectReq)) 108f22ef01cSRoman Divacky return true; 109f22ef01cSRoman Divacky 110f22ef01cSRoman Divacky if (!F->hasFnAttr(Attribute::StackProtect)) 111f22ef01cSRoman Divacky return false; 112f22ef01cSRoman Divacky 113f22ef01cSRoman Divacky const TargetData *TD = TLI->getTargetData(); 114f22ef01cSRoman Divacky 115f22ef01cSRoman Divacky for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) { 116f22ef01cSRoman Divacky BasicBlock *BB = I; 117f22ef01cSRoman Divacky 118f22ef01cSRoman Divacky for (BasicBlock::iterator 119f22ef01cSRoman Divacky II = BB->begin(), IE = BB->end(); II != IE; ++II) 120f22ef01cSRoman Divacky if (AllocaInst *AI = dyn_cast<AllocaInst>(II)) { 121f22ef01cSRoman Divacky if (AI->isArrayAllocation()) 122f22ef01cSRoman Divacky // This is a call to alloca with a variable size. Emit stack 123f22ef01cSRoman Divacky // protectors. 124f22ef01cSRoman Divacky return true; 125f22ef01cSRoman Divacky 126f22ef01cSRoman Divacky if (const ArrayType *AT = dyn_cast<ArrayType>(AI->getAllocatedType())) { 127f22ef01cSRoman Divacky // We apparently only care about character arrays. 128f22ef01cSRoman Divacky if (!AT->getElementType()->isIntegerTy(8)) 129f22ef01cSRoman Divacky continue; 130f22ef01cSRoman Divacky 131f22ef01cSRoman Divacky // If an array has more than SSPBufferSize bytes of allocated space, 132f22ef01cSRoman Divacky // then we emit stack protectors. 133f22ef01cSRoman Divacky if (SSPBufferSize <= TD->getTypeAllocSize(AT)) 134f22ef01cSRoman Divacky return true; 135f22ef01cSRoman Divacky } 136f22ef01cSRoman Divacky } 137f22ef01cSRoman Divacky } 138f22ef01cSRoman Divacky 139f22ef01cSRoman Divacky return false; 140f22ef01cSRoman Divacky } 141f22ef01cSRoman Divacky 142f22ef01cSRoman Divacky /// InsertStackProtectors - Insert code into the prologue and epilogue of the 143f22ef01cSRoman Divacky /// function. 144f22ef01cSRoman Divacky /// 145f22ef01cSRoman Divacky /// - The prologue code loads and stores the stack guard onto the stack. 146f22ef01cSRoman Divacky /// - The epilogue checks the value stored in the prologue against the original 147f22ef01cSRoman Divacky /// value. It calls __stack_chk_fail if they differ. 148f22ef01cSRoman Divacky bool StackProtector::InsertStackProtectors() { 149f22ef01cSRoman Divacky BasicBlock *FailBB = 0; // The basic block to jump to if check fails. 1502754fe60SDimitry Andric BasicBlock *FailBBDom = 0; // FailBB's dominator. 151f22ef01cSRoman Divacky AllocaInst *AI = 0; // Place on stack that stores the stack guard. 152ffd1746dSEd Schouten Value *StackGuardVar = 0; // The stack guard variable. 153f22ef01cSRoman Divacky 154f22ef01cSRoman Divacky for (Function::iterator I = F->begin(), E = F->end(); I != E; ) { 155f22ef01cSRoman Divacky BasicBlock *BB = I++; 156f22ef01cSRoman Divacky ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator()); 157f22ef01cSRoman Divacky if (!RI) continue; 158f22ef01cSRoman Divacky 159f22ef01cSRoman Divacky if (!FailBB) { 160f22ef01cSRoman Divacky // Insert code into the entry block that stores the __stack_chk_guard 161f22ef01cSRoman Divacky // variable onto the stack: 162f22ef01cSRoman Divacky // 163f22ef01cSRoman Divacky // entry: 164f22ef01cSRoman Divacky // StackGuardSlot = alloca i8* 165f22ef01cSRoman Divacky // StackGuard = load __stack_chk_guard 166f22ef01cSRoman Divacky // call void @llvm.stackprotect.create(StackGuard, StackGuardSlot) 167f22ef01cSRoman Divacky // 168ffd1746dSEd Schouten const PointerType *PtrTy = Type::getInt8PtrTy(RI->getContext()); 169ffd1746dSEd Schouten unsigned AddressSpace, Offset; 170ffd1746dSEd Schouten if (TLI->getStackCookieLocation(AddressSpace, Offset)) { 171ffd1746dSEd Schouten Constant *OffsetVal = 172ffd1746dSEd Schouten ConstantInt::get(Type::getInt32Ty(RI->getContext()), Offset); 173ffd1746dSEd Schouten 174ffd1746dSEd Schouten StackGuardVar = ConstantExpr::getIntToPtr(OffsetVal, 175ffd1746dSEd Schouten PointerType::get(PtrTy, AddressSpace)); 176ffd1746dSEd Schouten } else { 177f22ef01cSRoman Divacky StackGuardVar = M->getOrInsertGlobal("__stack_chk_guard", PtrTy); 178ffd1746dSEd Schouten } 179f22ef01cSRoman Divacky 180f22ef01cSRoman Divacky BasicBlock &Entry = F->getEntryBlock(); 181f22ef01cSRoman Divacky Instruction *InsPt = &Entry.front(); 182f22ef01cSRoman Divacky 183f22ef01cSRoman Divacky AI = new AllocaInst(PtrTy, "StackGuardSlot", InsPt); 184f22ef01cSRoman Divacky LoadInst *LI = new LoadInst(StackGuardVar, "StackGuard", false, InsPt); 185f22ef01cSRoman Divacky 186f22ef01cSRoman Divacky Value *Args[] = { LI, AI }; 187f22ef01cSRoman Divacky CallInst:: 188f22ef01cSRoman Divacky Create(Intrinsic::getDeclaration(M, Intrinsic::stackprotector), 18917a519f9SDimitry Andric Args, "", InsPt); 190f22ef01cSRoman Divacky 191f22ef01cSRoman Divacky // Create the basic block to jump to when the guard check fails. 192f22ef01cSRoman Divacky FailBB = CreateFailBB(); 193f22ef01cSRoman Divacky } 194f22ef01cSRoman Divacky 195f22ef01cSRoman Divacky // For each block with a return instruction, convert this: 196f22ef01cSRoman Divacky // 197f22ef01cSRoman Divacky // return: 198f22ef01cSRoman Divacky // ... 199f22ef01cSRoman Divacky // ret ... 200f22ef01cSRoman Divacky // 201f22ef01cSRoman Divacky // into this: 202f22ef01cSRoman Divacky // 203f22ef01cSRoman Divacky // return: 204f22ef01cSRoman Divacky // ... 205f22ef01cSRoman Divacky // %1 = load __stack_chk_guard 206f22ef01cSRoman Divacky // %2 = load StackGuardSlot 207f22ef01cSRoman Divacky // %3 = cmp i1 %1, %2 208f22ef01cSRoman Divacky // br i1 %3, label %SP_return, label %CallStackCheckFailBlk 209f22ef01cSRoman Divacky // 210f22ef01cSRoman Divacky // SP_return: 211f22ef01cSRoman Divacky // ret ... 212f22ef01cSRoman Divacky // 213f22ef01cSRoman Divacky // CallStackCheckFailBlk: 214f22ef01cSRoman Divacky // call void @__stack_chk_fail() 215f22ef01cSRoman Divacky // unreachable 216f22ef01cSRoman Divacky 217f22ef01cSRoman Divacky // Split the basic block before the return instruction. 218f22ef01cSRoman Divacky BasicBlock *NewBB = BB->splitBasicBlock(RI, "SP_return"); 2193b0f4066SDimitry Andric 2203b0f4066SDimitry Andric if (DT && DT->isReachableFromEntry(BB)) { 2213b0f4066SDimitry Andric DT->addNewBlock(NewBB, BB); 2223b0f4066SDimitry Andric FailBBDom = FailBBDom ? DT->findNearestCommonDominator(FailBBDom, BB) :BB; 2232754fe60SDimitry Andric } 224f22ef01cSRoman Divacky 225f22ef01cSRoman Divacky // Remove default branch instruction to the new BB. 226f22ef01cSRoman Divacky BB->getTerminator()->eraseFromParent(); 227f22ef01cSRoman Divacky 228f22ef01cSRoman Divacky // Move the newly created basic block to the point right after the old basic 229f22ef01cSRoman Divacky // block so that it's in the "fall through" position. 230f22ef01cSRoman Divacky NewBB->moveAfter(BB); 231f22ef01cSRoman Divacky 232f22ef01cSRoman Divacky // Generate the stack protector instructions in the old basic block. 233f22ef01cSRoman Divacky LoadInst *LI1 = new LoadInst(StackGuardVar, "", false, BB); 234f22ef01cSRoman Divacky LoadInst *LI2 = new LoadInst(AI, "", true, BB); 235f22ef01cSRoman Divacky ICmpInst *Cmp = new ICmpInst(*BB, CmpInst::ICMP_EQ, LI1, LI2, ""); 236f22ef01cSRoman Divacky BranchInst::Create(NewBB, FailBB, Cmp, BB); 237f22ef01cSRoman Divacky } 238f22ef01cSRoman Divacky 239f22ef01cSRoman Divacky // Return if we didn't modify any basic blocks. I.e., there are no return 240f22ef01cSRoman Divacky // statements in the function. 241f22ef01cSRoman Divacky if (!FailBB) return false; 242f22ef01cSRoman Divacky 2433b0f4066SDimitry Andric if (DT && FailBBDom) 2442754fe60SDimitry Andric DT->addNewBlock(FailBB, FailBBDom); 2452754fe60SDimitry Andric 246f22ef01cSRoman Divacky return true; 247f22ef01cSRoman Divacky } 248f22ef01cSRoman Divacky 249f22ef01cSRoman Divacky /// CreateFailBB - Create a basic block to jump to when the stack protector 250f22ef01cSRoman Divacky /// check fails. 251f22ef01cSRoman Divacky BasicBlock *StackProtector::CreateFailBB() { 252f22ef01cSRoman Divacky BasicBlock *FailBB = BasicBlock::Create(F->getContext(), 253f22ef01cSRoman Divacky "CallStackCheckFailBlk", F); 254f22ef01cSRoman Divacky Constant *StackChkFail = 255f22ef01cSRoman Divacky M->getOrInsertFunction("__stack_chk_fail", 256f22ef01cSRoman Divacky Type::getVoidTy(F->getContext()), NULL); 257f22ef01cSRoman Divacky CallInst::Create(StackChkFail, "", FailBB); 258f22ef01cSRoman Divacky new UnreachableInst(F->getContext(), FailBB); 259f22ef01cSRoman Divacky return FailBB; 260f22ef01cSRoman Divacky } 261