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" 293861d79fSDimitry Andric #include "llvm/DataLayout.h" 30f22ef01cSRoman Divacky #include "llvm/Target/TargetLowering.h" 313861d79fSDimitry Andric #include "llvm/Target/TargetOptions.h" 327ae0e2c9SDimitry Andric #include "llvm/ADT/Triple.h" 33f22ef01cSRoman Divacky using namespace llvm; 34f22ef01cSRoman Divacky 35f22ef01cSRoman Divacky namespace { 36f22ef01cSRoman Divacky class StackProtector : public FunctionPass { 37f22ef01cSRoman Divacky /// TLI - Keep a pointer of a TargetLowering to consult for determining 38f22ef01cSRoman Divacky /// target type sizes. 39f22ef01cSRoman Divacky const TargetLowering *TLI; 40f22ef01cSRoman Divacky 41f22ef01cSRoman Divacky Function *F; 42f22ef01cSRoman Divacky Module *M; 43f22ef01cSRoman Divacky 442754fe60SDimitry Andric DominatorTree *DT; 452754fe60SDimitry Andric 46f22ef01cSRoman Divacky /// InsertStackProtectors - Insert code into the prologue and epilogue of 47f22ef01cSRoman Divacky /// the function. 48f22ef01cSRoman Divacky /// 49f22ef01cSRoman Divacky /// - The prologue code loads and stores the stack guard onto the stack. 50f22ef01cSRoman Divacky /// - The epilogue checks the value stored in the prologue against the 51f22ef01cSRoman Divacky /// original value. It calls __stack_chk_fail if they differ. 52f22ef01cSRoman Divacky bool InsertStackProtectors(); 53f22ef01cSRoman Divacky 54f22ef01cSRoman Divacky /// CreateFailBB - Create a basic block to jump to when the stack protector 55f22ef01cSRoman Divacky /// check fails. 56f22ef01cSRoman Divacky BasicBlock *CreateFailBB(); 57f22ef01cSRoman Divacky 583861d79fSDimitry Andric /// ContainsProtectableArray - Check whether the type either is an array or 593861d79fSDimitry Andric /// contains an array of sufficient size so that we need stack protectors 603861d79fSDimitry Andric /// for it. 613861d79fSDimitry Andric bool ContainsProtectableArray(Type *Ty, bool InStruct = false) const; 623861d79fSDimitry Andric 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 1023861d79fSDimitry Andric /// ContainsProtectableArray - Check whether the type either is an array or 1033861d79fSDimitry Andric /// contains a char array of sufficient size so that we need stack protectors 1043861d79fSDimitry Andric /// for it. 1053861d79fSDimitry Andric bool StackProtector::ContainsProtectableArray(Type *Ty, bool InStruct) const { 1063861d79fSDimitry Andric if (!Ty) return false; 1073861d79fSDimitry Andric if (ArrayType *AT = dyn_cast<ArrayType>(Ty)) { 1083861d79fSDimitry Andric const TargetMachine &TM = TLI->getTargetMachine(); 1093861d79fSDimitry Andric if (!AT->getElementType()->isIntegerTy(8)) { 1103861d79fSDimitry Andric Triple Trip(TM.getTargetTriple()); 1113861d79fSDimitry Andric 1123861d79fSDimitry Andric // If we're on a non-Darwin platform or we're inside of a structure, don't 1133861d79fSDimitry Andric // add stack protectors unless the array is a character array. 1143861d79fSDimitry Andric if (InStruct || !Trip.isOSDarwin()) 1153861d79fSDimitry Andric return false; 1163861d79fSDimitry Andric } 1173861d79fSDimitry Andric 1183861d79fSDimitry Andric // If an array has more than SSPBufferSize bytes of allocated space, then we 1193861d79fSDimitry Andric // emit stack protectors. 1203861d79fSDimitry Andric if (TM.Options.SSPBufferSize <= TLI->getDataLayout()->getTypeAllocSize(AT)) 1213861d79fSDimitry Andric return true; 1223861d79fSDimitry Andric } 1233861d79fSDimitry Andric 1243861d79fSDimitry Andric const StructType *ST = dyn_cast<StructType>(Ty); 1253861d79fSDimitry Andric if (!ST) return false; 1263861d79fSDimitry Andric 1273861d79fSDimitry Andric for (StructType::element_iterator I = ST->element_begin(), 1283861d79fSDimitry Andric E = ST->element_end(); I != E; ++I) 1293861d79fSDimitry Andric if (ContainsProtectableArray(*I, true)) 1303861d79fSDimitry Andric return true; 1313861d79fSDimitry Andric 1323861d79fSDimitry Andric return false; 1333861d79fSDimitry Andric } 1343861d79fSDimitry Andric 135f22ef01cSRoman Divacky /// RequiresStackProtector - Check whether or not this function needs a stack 136f22ef01cSRoman Divacky /// protector based upon the stack protector level. The heuristic we use is to 137f22ef01cSRoman Divacky /// add a guard variable to functions that call alloca, and functions with 138f22ef01cSRoman Divacky /// buffers larger than SSPBufferSize bytes. 139f22ef01cSRoman Divacky bool StackProtector::RequiresStackProtector() const { 1403861d79fSDimitry Andric if (F->getFnAttributes().hasAttribute(Attributes::StackProtectReq)) 141f22ef01cSRoman Divacky return true; 142f22ef01cSRoman Divacky 1433861d79fSDimitry Andric if (!F->getFnAttributes().hasAttribute(Attributes::StackProtect)) 144f22ef01cSRoman Divacky return false; 145f22ef01cSRoman Divacky 146f22ef01cSRoman Divacky for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) { 147f22ef01cSRoman Divacky BasicBlock *BB = I; 148f22ef01cSRoman Divacky 149f22ef01cSRoman Divacky for (BasicBlock::iterator 150f22ef01cSRoman Divacky II = BB->begin(), IE = BB->end(); II != IE; ++II) 151f22ef01cSRoman Divacky if (AllocaInst *AI = dyn_cast<AllocaInst>(II)) { 152f22ef01cSRoman Divacky if (AI->isArrayAllocation()) 153f22ef01cSRoman Divacky // This is a call to alloca with a variable size. Emit stack 154f22ef01cSRoman Divacky // protectors. 155f22ef01cSRoman Divacky return true; 156f22ef01cSRoman Divacky 1573861d79fSDimitry Andric if (ContainsProtectableArray(AI->getAllocatedType())) 158f22ef01cSRoman Divacky return true; 159f22ef01cSRoman Divacky } 160f22ef01cSRoman Divacky } 161f22ef01cSRoman Divacky 162f22ef01cSRoman Divacky return false; 163f22ef01cSRoman Divacky } 164f22ef01cSRoman Divacky 165f22ef01cSRoman Divacky /// InsertStackProtectors - Insert code into the prologue and epilogue of the 166f22ef01cSRoman Divacky /// function. 167f22ef01cSRoman Divacky /// 168f22ef01cSRoman Divacky /// - The prologue code loads and stores the stack guard onto the stack. 169f22ef01cSRoman Divacky /// - The epilogue checks the value stored in the prologue against the original 170f22ef01cSRoman Divacky /// value. It calls __stack_chk_fail if they differ. 171f22ef01cSRoman Divacky bool StackProtector::InsertStackProtectors() { 172f22ef01cSRoman Divacky BasicBlock *FailBB = 0; // The basic block to jump to if check fails. 1732754fe60SDimitry Andric BasicBlock *FailBBDom = 0; // FailBB's dominator. 174f22ef01cSRoman Divacky AllocaInst *AI = 0; // Place on stack that stores the stack guard. 175ffd1746dSEd Schouten Value *StackGuardVar = 0; // The stack guard variable. 176f22ef01cSRoman Divacky 177f22ef01cSRoman Divacky for (Function::iterator I = F->begin(), E = F->end(); I != E; ) { 178f22ef01cSRoman Divacky BasicBlock *BB = I++; 179f22ef01cSRoman Divacky ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator()); 180f22ef01cSRoman Divacky if (!RI) continue; 181f22ef01cSRoman Divacky 182f22ef01cSRoman Divacky if (!FailBB) { 183f22ef01cSRoman Divacky // Insert code into the entry block that stores the __stack_chk_guard 184f22ef01cSRoman Divacky // variable onto the stack: 185f22ef01cSRoman Divacky // 186f22ef01cSRoman Divacky // entry: 187f22ef01cSRoman Divacky // StackGuardSlot = alloca i8* 188f22ef01cSRoman Divacky // StackGuard = load __stack_chk_guard 189f22ef01cSRoman Divacky // call void @llvm.stackprotect.create(StackGuard, StackGuardSlot) 190f22ef01cSRoman Divacky // 1916122f3e6SDimitry Andric PointerType *PtrTy = Type::getInt8PtrTy(RI->getContext()); 192ffd1746dSEd Schouten unsigned AddressSpace, Offset; 193ffd1746dSEd Schouten if (TLI->getStackCookieLocation(AddressSpace, Offset)) { 194ffd1746dSEd Schouten Constant *OffsetVal = 195ffd1746dSEd Schouten ConstantInt::get(Type::getInt32Ty(RI->getContext()), Offset); 196ffd1746dSEd Schouten 197ffd1746dSEd Schouten StackGuardVar = ConstantExpr::getIntToPtr(OffsetVal, 198ffd1746dSEd Schouten PointerType::get(PtrTy, AddressSpace)); 199ffd1746dSEd Schouten } else { 200f22ef01cSRoman Divacky StackGuardVar = M->getOrInsertGlobal("__stack_chk_guard", PtrTy); 201ffd1746dSEd Schouten } 202f22ef01cSRoman Divacky 203f22ef01cSRoman Divacky BasicBlock &Entry = F->getEntryBlock(); 204f22ef01cSRoman Divacky Instruction *InsPt = &Entry.front(); 205f22ef01cSRoman Divacky 206f22ef01cSRoman Divacky AI = new AllocaInst(PtrTy, "StackGuardSlot", InsPt); 207f22ef01cSRoman Divacky LoadInst *LI = new LoadInst(StackGuardVar, "StackGuard", false, InsPt); 208f22ef01cSRoman Divacky 209f22ef01cSRoman Divacky Value *Args[] = { LI, AI }; 210f22ef01cSRoman Divacky CallInst:: 211f22ef01cSRoman Divacky Create(Intrinsic::getDeclaration(M, Intrinsic::stackprotector), 21217a519f9SDimitry Andric Args, "", InsPt); 213f22ef01cSRoman Divacky 214f22ef01cSRoman Divacky // Create the basic block to jump to when the guard check fails. 215f22ef01cSRoman Divacky FailBB = CreateFailBB(); 216f22ef01cSRoman Divacky } 217f22ef01cSRoman Divacky 218f22ef01cSRoman Divacky // For each block with a return instruction, convert this: 219f22ef01cSRoman Divacky // 220f22ef01cSRoman Divacky // return: 221f22ef01cSRoman Divacky // ... 222f22ef01cSRoman Divacky // ret ... 223f22ef01cSRoman Divacky // 224f22ef01cSRoman Divacky // into this: 225f22ef01cSRoman Divacky // 226f22ef01cSRoman Divacky // return: 227f22ef01cSRoman Divacky // ... 228f22ef01cSRoman Divacky // %1 = load __stack_chk_guard 229f22ef01cSRoman Divacky // %2 = load StackGuardSlot 230f22ef01cSRoman Divacky // %3 = cmp i1 %1, %2 231f22ef01cSRoman Divacky // br i1 %3, label %SP_return, label %CallStackCheckFailBlk 232f22ef01cSRoman Divacky // 233f22ef01cSRoman Divacky // SP_return: 234f22ef01cSRoman Divacky // ret ... 235f22ef01cSRoman Divacky // 236f22ef01cSRoman Divacky // CallStackCheckFailBlk: 237f22ef01cSRoman Divacky // call void @__stack_chk_fail() 238f22ef01cSRoman Divacky // unreachable 239f22ef01cSRoman Divacky 240f22ef01cSRoman Divacky // Split the basic block before the return instruction. 241f22ef01cSRoman Divacky BasicBlock *NewBB = BB->splitBasicBlock(RI, "SP_return"); 2423b0f4066SDimitry Andric 2433b0f4066SDimitry Andric if (DT && DT->isReachableFromEntry(BB)) { 2443b0f4066SDimitry Andric DT->addNewBlock(NewBB, BB); 2453b0f4066SDimitry Andric FailBBDom = FailBBDom ? DT->findNearestCommonDominator(FailBBDom, BB) :BB; 2462754fe60SDimitry Andric } 247f22ef01cSRoman Divacky 248f22ef01cSRoman Divacky // Remove default branch instruction to the new BB. 249f22ef01cSRoman Divacky BB->getTerminator()->eraseFromParent(); 250f22ef01cSRoman Divacky 251f22ef01cSRoman Divacky // Move the newly created basic block to the point right after the old basic 252f22ef01cSRoman Divacky // block so that it's in the "fall through" position. 253f22ef01cSRoman Divacky NewBB->moveAfter(BB); 254f22ef01cSRoman Divacky 255f22ef01cSRoman Divacky // Generate the stack protector instructions in the old basic block. 256f22ef01cSRoman Divacky LoadInst *LI1 = new LoadInst(StackGuardVar, "", false, BB); 257f22ef01cSRoman Divacky LoadInst *LI2 = new LoadInst(AI, "", true, BB); 258f22ef01cSRoman Divacky ICmpInst *Cmp = new ICmpInst(*BB, CmpInst::ICMP_EQ, LI1, LI2, ""); 259f22ef01cSRoman Divacky BranchInst::Create(NewBB, FailBB, Cmp, BB); 260f22ef01cSRoman Divacky } 261f22ef01cSRoman Divacky 262f22ef01cSRoman Divacky // Return if we didn't modify any basic blocks. I.e., there are no return 263f22ef01cSRoman Divacky // statements in the function. 264f22ef01cSRoman Divacky if (!FailBB) return false; 265f22ef01cSRoman Divacky 2663b0f4066SDimitry Andric if (DT && FailBBDom) 2672754fe60SDimitry Andric DT->addNewBlock(FailBB, FailBBDom); 2682754fe60SDimitry Andric 269f22ef01cSRoman Divacky return true; 270f22ef01cSRoman Divacky } 271f22ef01cSRoman Divacky 272f22ef01cSRoman Divacky /// CreateFailBB - Create a basic block to jump to when the stack protector 273f22ef01cSRoman Divacky /// check fails. 274f22ef01cSRoman Divacky BasicBlock *StackProtector::CreateFailBB() { 275f22ef01cSRoman Divacky BasicBlock *FailBB = BasicBlock::Create(F->getContext(), 276f22ef01cSRoman Divacky "CallStackCheckFailBlk", F); 277f22ef01cSRoman Divacky Constant *StackChkFail = 278f22ef01cSRoman Divacky M->getOrInsertFunction("__stack_chk_fail", 279f22ef01cSRoman Divacky Type::getVoidTy(F->getContext()), NULL); 280f22ef01cSRoman Divacky CallInst::Create(StackChkFail, "", FailBB); 281f22ef01cSRoman Divacky new UnreachableInst(F->getContext(), FailBB); 282f22ef01cSRoman Divacky return FailBB; 283f22ef01cSRoman Divacky } 284