1 //===- HWAddressSanitizer.cpp - detector of uninitialized reads -------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 /// \file 11 /// This file is a part of HWAddressSanitizer, an address sanity checker 12 /// based on tagged addressing. 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/ADT/SmallVector.h" 16 #include "llvm/ADT/StringExtras.h" 17 #include "llvm/ADT/StringRef.h" 18 #include "llvm/ADT/Triple.h" 19 #include "llvm/IR/Attributes.h" 20 #include "llvm/IR/BasicBlock.h" 21 #include "llvm/IR/Constant.h" 22 #include "llvm/IR/Constants.h" 23 #include "llvm/IR/DataLayout.h" 24 #include "llvm/IR/DerivedTypes.h" 25 #include "llvm/IR/Function.h" 26 #include "llvm/IR/IRBuilder.h" 27 #include "llvm/IR/InlineAsm.h" 28 #include "llvm/IR/InstVisitor.h" 29 #include "llvm/IR/Instruction.h" 30 #include "llvm/IR/Instructions.h" 31 #include "llvm/IR/IntrinsicInst.h" 32 #include "llvm/IR/Intrinsics.h" 33 #include "llvm/IR/LLVMContext.h" 34 #include "llvm/IR/MDBuilder.h" 35 #include "llvm/IR/Module.h" 36 #include "llvm/IR/Type.h" 37 #include "llvm/IR/Value.h" 38 #include "llvm/Pass.h" 39 #include "llvm/Support/Casting.h" 40 #include "llvm/Support/CommandLine.h" 41 #include "llvm/Support/Debug.h" 42 #include "llvm/Support/raw_ostream.h" 43 #include "llvm/Transforms/Instrumentation.h" 44 #include "llvm/Transforms/Utils/BasicBlockUtils.h" 45 #include "llvm/Transforms/Utils/ModuleUtils.h" 46 #include "llvm/Transforms/Utils/PromoteMemToReg.h" 47 48 using namespace llvm; 49 50 #define DEBUG_TYPE "hwasan" 51 52 static const char *const kHwasanModuleCtorName = "hwasan.module_ctor"; 53 static const char *const kHwasanInitName = "__hwasan_init"; 54 55 static const char *const kHwasanShadowMemoryDynamicAddress = 56 "__hwasan_shadow_memory_dynamic_address"; 57 58 // Accesses sizes are powers of two: 1, 2, 4, 8, 16. 59 static const size_t kNumberOfAccessSizes = 5; 60 61 static const size_t kDefaultShadowScale = 4; 62 static const uint64_t kDynamicShadowSentinel = 63 std::numeric_limits<uint64_t>::max(); 64 static const unsigned kPointerTagShift = 56; 65 66 static const unsigned kShadowBaseAlignment = 32; 67 68 static cl::opt<std::string> ClMemoryAccessCallbackPrefix( 69 "hwasan-memory-access-callback-prefix", 70 cl::desc("Prefix for memory access callbacks"), cl::Hidden, 71 cl::init("__hwasan_")); 72 73 static cl::opt<bool> 74 ClInstrumentWithCalls("hwasan-instrument-with-calls", 75 cl::desc("instrument reads and writes with callbacks"), 76 cl::Hidden, cl::init(false)); 77 78 static cl::opt<bool> ClInstrumentReads("hwasan-instrument-reads", 79 cl::desc("instrument read instructions"), 80 cl::Hidden, cl::init(true)); 81 82 static cl::opt<bool> ClInstrumentWrites( 83 "hwasan-instrument-writes", cl::desc("instrument write instructions"), 84 cl::Hidden, cl::init(true)); 85 86 static cl::opt<bool> ClInstrumentAtomics( 87 "hwasan-instrument-atomics", 88 cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden, 89 cl::init(true)); 90 91 static cl::opt<bool> ClRecover( 92 "hwasan-recover", 93 cl::desc("Enable recovery mode (continue-after-error)."), 94 cl::Hidden, cl::init(false)); 95 96 static cl::opt<bool> ClInstrumentStack("hwasan-instrument-stack", 97 cl::desc("instrument stack (allocas)"), 98 cl::Hidden, cl::init(true)); 99 100 static cl::opt<bool> ClUARRetagToZero( 101 "hwasan-uar-retag-to-zero", 102 cl::desc("Clear alloca tags before returning from the function to allow " 103 "non-instrumented and instrumented function calls mix. When set " 104 "to false, allocas are retagged before returning from the " 105 "function to detect use after return."), 106 cl::Hidden, cl::init(true)); 107 108 static cl::opt<bool> ClGenerateTagsWithCalls( 109 "hwasan-generate-tags-with-calls", 110 cl::desc("generate new tags with runtime library calls"), cl::Hidden, 111 cl::init(false)); 112 113 static cl::opt<int> ClMatchAllTag( 114 "hwasan-match-all-tag", 115 cl::desc("don't report bad accesses via pointers with this tag"), 116 cl::Hidden, cl::init(-1)); 117 118 static cl::opt<bool> ClEnableKhwasan( 119 "hwasan-kernel", 120 cl::desc("Enable KernelHWAddressSanitizer instrumentation"), 121 cl::Hidden, cl::init(false)); 122 123 // These flags allow to change the shadow mapping and control how shadow memory 124 // is accessed. The shadow mapping looks like: 125 // Shadow = (Mem >> scale) + offset 126 127 static cl::opt<unsigned long long> ClMappingOffset( 128 "hwasan-mapping-offset", 129 cl::desc("HWASan shadow mapping offset [EXPERIMENTAL]"), cl::Hidden, 130 cl::init(0)); 131 132 static cl::opt<bool> 133 ClWithIfunc("hwasan-with-ifunc", 134 cl::desc("Access dynamic shadow through an ifunc global on " 135 "platforms that support this"), 136 cl::Hidden, cl::init(false)); 137 138 static cl::opt<bool> ClWithTls( 139 "hwasan-with-tls", 140 cl::desc("Access dynamic shadow through an thread-local pointer on " 141 "platforms that support this"), 142 cl::Hidden, cl::init(true)); 143 144 static cl::opt<bool> 145 ClRecordStackHistory("hwasan-record-stack-history", 146 cl::desc("Record stack frames with tagged allocations " 147 "in a thread-local ring buffer"), 148 cl::Hidden, cl::init(true)); 149 namespace { 150 151 /// An instrumentation pass implementing detection of addressability bugs 152 /// using tagged pointers. 153 class HWAddressSanitizer : public FunctionPass { 154 public: 155 // Pass identification, replacement for typeid. 156 static char ID; 157 158 explicit HWAddressSanitizer(bool CompileKernel = false, bool Recover = false) 159 : FunctionPass(ID) { 160 this->Recover = ClRecover.getNumOccurrences() > 0 ? ClRecover : Recover; 161 this->CompileKernel = ClEnableKhwasan.getNumOccurrences() > 0 ? 162 ClEnableKhwasan : CompileKernel; 163 } 164 165 StringRef getPassName() const override { return "HWAddressSanitizer"; } 166 167 bool runOnFunction(Function &F) override; 168 bool doInitialization(Module &M) override; 169 170 void initializeCallbacks(Module &M); 171 172 Value *getDynamicShadowNonTls(IRBuilder<> &IRB); 173 174 void untagPointerOperand(Instruction *I, Value *Addr); 175 Value *memToShadow(Value *Shadow, Type *Ty, IRBuilder<> &IRB); 176 void instrumentMemAccessInline(Value *PtrLong, bool IsWrite, 177 unsigned AccessSizeIndex, 178 Instruction *InsertBefore); 179 bool instrumentMemAccess(Instruction *I); 180 Value *isInterestingMemoryAccess(Instruction *I, bool *IsWrite, 181 uint64_t *TypeSize, unsigned *Alignment, 182 Value **MaybeMask); 183 184 bool isInterestingAlloca(const AllocaInst &AI); 185 bool tagAlloca(IRBuilder<> &IRB, AllocaInst *AI, Value *Tag); 186 Value *tagPointer(IRBuilder<> &IRB, Type *Ty, Value *PtrLong, Value *Tag); 187 Value *untagPointer(IRBuilder<> &IRB, Value *PtrLong); 188 bool instrumentStack(SmallVectorImpl<AllocaInst *> &Allocas, 189 SmallVectorImpl<Instruction *> &RetVec, Value *StackTag); 190 Value *getNextTagWithCall(IRBuilder<> &IRB); 191 Value *getStackBaseTag(IRBuilder<> &IRB); 192 Value *getAllocaTag(IRBuilder<> &IRB, Value *StackTag, AllocaInst *AI, 193 unsigned AllocaNo); 194 Value *getUARTag(IRBuilder<> &IRB, Value *StackTag); 195 196 Value *getHwasanThreadSlotPtr(IRBuilder<> &IRB, Type *Ty); 197 Value *emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord); 198 199 private: 200 LLVMContext *C; 201 Triple TargetTriple; 202 203 /// This struct defines the shadow mapping using the rule: 204 /// shadow = (mem >> Scale) + Offset. 205 /// If InGlobal is true, then 206 /// extern char __hwasan_shadow[]; 207 /// shadow = (mem >> Scale) + &__hwasan_shadow 208 /// If InTls is true, then 209 /// extern char *__hwasan_tls; 210 /// shadow = (mem >> Scale) + align_up(__hwasan_shadow, kShadowBaseAlignment) 211 struct ShadowMapping { 212 int Scale; 213 uint64_t Offset; 214 bool InGlobal; 215 bool InTls; 216 217 void init(Triple &TargetTriple); 218 unsigned getAllocaAlignment() const { return 1U << Scale; } 219 }; 220 ShadowMapping Mapping; 221 222 Type *IntptrTy; 223 Type *Int8PtrTy; 224 Type *Int8Ty; 225 226 bool CompileKernel; 227 bool Recover; 228 229 Function *HwasanCtorFunction; 230 231 Function *HwasanMemoryAccessCallback[2][kNumberOfAccessSizes]; 232 Function *HwasanMemoryAccessCallbackSized[2]; 233 234 Function *HwasanTagMemoryFunc; 235 Function *HwasanGenerateTagFunc; 236 237 Constant *ShadowGlobal; 238 239 Value *LocalDynamicShadow = nullptr; 240 GlobalValue *ThreadPtrGlobal = nullptr; 241 }; 242 243 } // end anonymous namespace 244 245 char HWAddressSanitizer::ID = 0; 246 247 INITIALIZE_PASS_BEGIN( 248 HWAddressSanitizer, "hwasan", 249 "HWAddressSanitizer: detect memory bugs using tagged addressing.", false, 250 false) 251 INITIALIZE_PASS_END( 252 HWAddressSanitizer, "hwasan", 253 "HWAddressSanitizer: detect memory bugs using tagged addressing.", false, 254 false) 255 256 FunctionPass *llvm::createHWAddressSanitizerPass(bool CompileKernel, 257 bool Recover) { 258 assert(!CompileKernel || Recover); 259 return new HWAddressSanitizer(CompileKernel, Recover); 260 } 261 262 /// Module-level initialization. 263 /// 264 /// inserts a call to __hwasan_init to the module's constructor list. 265 bool HWAddressSanitizer::doInitialization(Module &M) { 266 LLVM_DEBUG(dbgs() << "Init " << M.getName() << "\n"); 267 auto &DL = M.getDataLayout(); 268 269 TargetTriple = Triple(M.getTargetTriple()); 270 271 Mapping.init(TargetTriple); 272 273 C = &(M.getContext()); 274 IRBuilder<> IRB(*C); 275 IntptrTy = IRB.getIntPtrTy(DL); 276 Int8PtrTy = IRB.getInt8PtrTy(); 277 Int8Ty = IRB.getInt8Ty(); 278 279 HwasanCtorFunction = nullptr; 280 if (!CompileKernel) { 281 std::tie(HwasanCtorFunction, std::ignore) = 282 createSanitizerCtorAndInitFunctions(M, kHwasanModuleCtorName, 283 kHwasanInitName, 284 /*InitArgTypes=*/{}, 285 /*InitArgs=*/{}); 286 appendToGlobalCtors(M, HwasanCtorFunction, 0); 287 } 288 if (!TargetTriple.isAndroid()) 289 appendToCompilerUsed( 290 M, ThreadPtrGlobal = new GlobalVariable( 291 M, IntptrTy, false, GlobalVariable::ExternalLinkage, nullptr, 292 "__hwasan_tls", nullptr, GlobalVariable::InitialExecTLSModel)); 293 294 return true; 295 } 296 297 void HWAddressSanitizer::initializeCallbacks(Module &M) { 298 IRBuilder<> IRB(*C); 299 for (size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) { 300 const std::string TypeStr = AccessIsWrite ? "store" : "load"; 301 const std::string EndingStr = Recover ? "_noabort" : ""; 302 303 HwasanMemoryAccessCallbackSized[AccessIsWrite] = 304 checkSanitizerInterfaceFunction(M.getOrInsertFunction( 305 ClMemoryAccessCallbackPrefix + TypeStr + "N" + EndingStr, 306 FunctionType::get(IRB.getVoidTy(), {IntptrTy, IntptrTy}, false))); 307 308 for (size_t AccessSizeIndex = 0; AccessSizeIndex < kNumberOfAccessSizes; 309 AccessSizeIndex++) { 310 HwasanMemoryAccessCallback[AccessIsWrite][AccessSizeIndex] = 311 checkSanitizerInterfaceFunction(M.getOrInsertFunction( 312 ClMemoryAccessCallbackPrefix + TypeStr + 313 itostr(1ULL << AccessSizeIndex) + EndingStr, 314 FunctionType::get(IRB.getVoidTy(), {IntptrTy}, false))); 315 } 316 } 317 318 HwasanTagMemoryFunc = checkSanitizerInterfaceFunction(M.getOrInsertFunction( 319 "__hwasan_tag_memory", IRB.getVoidTy(), Int8PtrTy, Int8Ty, IntptrTy)); 320 HwasanGenerateTagFunc = checkSanitizerInterfaceFunction( 321 M.getOrInsertFunction("__hwasan_generate_tag", Int8Ty)); 322 323 if (Mapping.InGlobal) 324 ShadowGlobal = M.getOrInsertGlobal("__hwasan_shadow", 325 ArrayType::get(IRB.getInt8Ty(), 0)); 326 } 327 328 Value *HWAddressSanitizer::getDynamicShadowNonTls(IRBuilder<> &IRB) { 329 // Generate code only when dynamic addressing is needed. 330 if (Mapping.Offset != kDynamicShadowSentinel) 331 return nullptr; 332 333 if (Mapping.InGlobal) { 334 // An empty inline asm with input reg == output reg. 335 // An opaque pointer-to-int cast, basically. 336 InlineAsm *Asm = InlineAsm::get( 337 FunctionType::get(IntptrTy, {ShadowGlobal->getType()}, false), 338 StringRef(""), StringRef("=r,0"), 339 /*hasSideEffects=*/false); 340 return IRB.CreateCall(Asm, {ShadowGlobal}, ".hwasan.shadow"); 341 } else { 342 Value *GlobalDynamicAddress = 343 IRB.GetInsertBlock()->getParent()->getParent()->getOrInsertGlobal( 344 kHwasanShadowMemoryDynamicAddress, IntptrTy); 345 return IRB.CreateLoad(GlobalDynamicAddress); 346 } 347 } 348 349 Value *HWAddressSanitizer::isInterestingMemoryAccess(Instruction *I, 350 bool *IsWrite, 351 uint64_t *TypeSize, 352 unsigned *Alignment, 353 Value **MaybeMask) { 354 // Skip memory accesses inserted by another instrumentation. 355 if (I->getMetadata("nosanitize")) return nullptr; 356 357 // Do not instrument the load fetching the dynamic shadow address. 358 if (LocalDynamicShadow == I) 359 return nullptr; 360 361 Value *PtrOperand = nullptr; 362 const DataLayout &DL = I->getModule()->getDataLayout(); 363 if (LoadInst *LI = dyn_cast<LoadInst>(I)) { 364 if (!ClInstrumentReads) return nullptr; 365 *IsWrite = false; 366 *TypeSize = DL.getTypeStoreSizeInBits(LI->getType()); 367 *Alignment = LI->getAlignment(); 368 PtrOperand = LI->getPointerOperand(); 369 } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) { 370 if (!ClInstrumentWrites) return nullptr; 371 *IsWrite = true; 372 *TypeSize = DL.getTypeStoreSizeInBits(SI->getValueOperand()->getType()); 373 *Alignment = SI->getAlignment(); 374 PtrOperand = SI->getPointerOperand(); 375 } else if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I)) { 376 if (!ClInstrumentAtomics) return nullptr; 377 *IsWrite = true; 378 *TypeSize = DL.getTypeStoreSizeInBits(RMW->getValOperand()->getType()); 379 *Alignment = 0; 380 PtrOperand = RMW->getPointerOperand(); 381 } else if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I)) { 382 if (!ClInstrumentAtomics) return nullptr; 383 *IsWrite = true; 384 *TypeSize = DL.getTypeStoreSizeInBits(XCHG->getCompareOperand()->getType()); 385 *Alignment = 0; 386 PtrOperand = XCHG->getPointerOperand(); 387 } 388 389 if (PtrOperand) { 390 // Do not instrument accesses from different address spaces; we cannot deal 391 // with them. 392 Type *PtrTy = cast<PointerType>(PtrOperand->getType()->getScalarType()); 393 if (PtrTy->getPointerAddressSpace() != 0) 394 return nullptr; 395 396 // Ignore swifterror addresses. 397 // swifterror memory addresses are mem2reg promoted by instruction 398 // selection. As such they cannot have regular uses like an instrumentation 399 // function and it makes no sense to track them as memory. 400 if (PtrOperand->isSwiftError()) 401 return nullptr; 402 } 403 404 return PtrOperand; 405 } 406 407 static unsigned getPointerOperandIndex(Instruction *I) { 408 if (LoadInst *LI = dyn_cast<LoadInst>(I)) 409 return LI->getPointerOperandIndex(); 410 if (StoreInst *SI = dyn_cast<StoreInst>(I)) 411 return SI->getPointerOperandIndex(); 412 if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I)) 413 return RMW->getPointerOperandIndex(); 414 if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I)) 415 return XCHG->getPointerOperandIndex(); 416 report_fatal_error("Unexpected instruction"); 417 return -1; 418 } 419 420 static size_t TypeSizeToSizeIndex(uint32_t TypeSize) { 421 size_t Res = countTrailingZeros(TypeSize / 8); 422 assert(Res < kNumberOfAccessSizes); 423 return Res; 424 } 425 426 void HWAddressSanitizer::untagPointerOperand(Instruction *I, Value *Addr) { 427 if (TargetTriple.isAArch64()) 428 return; 429 430 IRBuilder<> IRB(I); 431 Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy); 432 Value *UntaggedPtr = 433 IRB.CreateIntToPtr(untagPointer(IRB, AddrLong), Addr->getType()); 434 I->setOperand(getPointerOperandIndex(I), UntaggedPtr); 435 } 436 437 Value *HWAddressSanitizer::memToShadow(Value *Mem, Type *Ty, IRBuilder<> &IRB) { 438 // Mem >> Scale 439 Value *Shadow = IRB.CreateLShr(Mem, Mapping.Scale); 440 if (Mapping.Offset == 0) 441 return Shadow; 442 // (Mem >> Scale) + Offset 443 Value *ShadowBase; 444 if (LocalDynamicShadow) 445 ShadowBase = LocalDynamicShadow; 446 else 447 ShadowBase = ConstantInt::get(Ty, Mapping.Offset); 448 return IRB.CreateAdd(Shadow, ShadowBase); 449 } 450 451 void HWAddressSanitizer::instrumentMemAccessInline(Value *PtrLong, bool IsWrite, 452 unsigned AccessSizeIndex, 453 Instruction *InsertBefore) { 454 IRBuilder<> IRB(InsertBefore); 455 Value *PtrTag = IRB.CreateTrunc(IRB.CreateLShr(PtrLong, kPointerTagShift), 456 IRB.getInt8Ty()); 457 Value *AddrLong = untagPointer(IRB, PtrLong); 458 Value *ShadowLong = memToShadow(AddrLong, PtrLong->getType(), IRB); 459 Value *MemTag = IRB.CreateLoad(IRB.CreateIntToPtr(ShadowLong, Int8PtrTy)); 460 Value *TagMismatch = IRB.CreateICmpNE(PtrTag, MemTag); 461 462 int matchAllTag = ClMatchAllTag.getNumOccurrences() > 0 ? 463 ClMatchAllTag : (CompileKernel ? 0xFF : -1); 464 if (matchAllTag != -1) { 465 Value *TagNotIgnored = IRB.CreateICmpNE(PtrTag, 466 ConstantInt::get(PtrTag->getType(), matchAllTag)); 467 TagMismatch = IRB.CreateAnd(TagMismatch, TagNotIgnored); 468 } 469 470 Instruction *CheckTerm = 471 SplitBlockAndInsertIfThen(TagMismatch, InsertBefore, !Recover, 472 MDBuilder(*C).createBranchWeights(1, 100000)); 473 474 IRB.SetInsertPoint(CheckTerm); 475 const int64_t AccessInfo = Recover * 0x20 + IsWrite * 0x10 + AccessSizeIndex; 476 InlineAsm *Asm; 477 switch (TargetTriple.getArch()) { 478 case Triple::x86_64: 479 // The signal handler will find the data address in rdi. 480 Asm = InlineAsm::get( 481 FunctionType::get(IRB.getVoidTy(), {PtrLong->getType()}, false), 482 "int3\nnopl " + itostr(0x40 + AccessInfo) + "(%rax)", 483 "{rdi}", 484 /*hasSideEffects=*/true); 485 break; 486 case Triple::aarch64: 487 case Triple::aarch64_be: 488 // The signal handler will find the data address in x0. 489 Asm = InlineAsm::get( 490 FunctionType::get(IRB.getVoidTy(), {PtrLong->getType()}, false), 491 "brk #" + itostr(0x900 + AccessInfo), 492 "{x0}", 493 /*hasSideEffects=*/true); 494 break; 495 default: 496 report_fatal_error("unsupported architecture"); 497 } 498 IRB.CreateCall(Asm, PtrLong); 499 } 500 501 bool HWAddressSanitizer::instrumentMemAccess(Instruction *I) { 502 LLVM_DEBUG(dbgs() << "Instrumenting: " << *I << "\n"); 503 bool IsWrite = false; 504 unsigned Alignment = 0; 505 uint64_t TypeSize = 0; 506 Value *MaybeMask = nullptr; 507 Value *Addr = 508 isInterestingMemoryAccess(I, &IsWrite, &TypeSize, &Alignment, &MaybeMask); 509 510 if (!Addr) 511 return false; 512 513 if (MaybeMask) 514 return false; //FIXME 515 516 IRBuilder<> IRB(I); 517 Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy); 518 if (isPowerOf2_64(TypeSize) && 519 (TypeSize / 8 <= (1UL << (kNumberOfAccessSizes - 1))) && 520 (Alignment >= (1UL << Mapping.Scale) || Alignment == 0 || 521 Alignment >= TypeSize / 8)) { 522 size_t AccessSizeIndex = TypeSizeToSizeIndex(TypeSize); 523 if (ClInstrumentWithCalls) { 524 IRB.CreateCall(HwasanMemoryAccessCallback[IsWrite][AccessSizeIndex], 525 AddrLong); 526 } else { 527 instrumentMemAccessInline(AddrLong, IsWrite, AccessSizeIndex, I); 528 } 529 } else { 530 IRB.CreateCall(HwasanMemoryAccessCallbackSized[IsWrite], 531 {AddrLong, ConstantInt::get(IntptrTy, TypeSize / 8)}); 532 } 533 untagPointerOperand(I, Addr); 534 535 return true; 536 } 537 538 static uint64_t getAllocaSizeInBytes(const AllocaInst &AI) { 539 uint64_t ArraySize = 1; 540 if (AI.isArrayAllocation()) { 541 const ConstantInt *CI = dyn_cast<ConstantInt>(AI.getArraySize()); 542 assert(CI && "non-constant array size"); 543 ArraySize = CI->getZExtValue(); 544 } 545 Type *Ty = AI.getAllocatedType(); 546 uint64_t SizeInBytes = AI.getModule()->getDataLayout().getTypeAllocSize(Ty); 547 return SizeInBytes * ArraySize; 548 } 549 550 bool HWAddressSanitizer::tagAlloca(IRBuilder<> &IRB, AllocaInst *AI, 551 Value *Tag) { 552 size_t Size = (getAllocaSizeInBytes(*AI) + Mapping.getAllocaAlignment() - 1) & 553 ~(Mapping.getAllocaAlignment() - 1); 554 555 Value *JustTag = IRB.CreateTrunc(Tag, IRB.getInt8Ty()); 556 if (ClInstrumentWithCalls) { 557 IRB.CreateCall(HwasanTagMemoryFunc, 558 {IRB.CreatePointerCast(AI, Int8PtrTy), JustTag, 559 ConstantInt::get(IntptrTy, Size)}); 560 } else { 561 size_t ShadowSize = Size >> Mapping.Scale; 562 Value *ShadowPtr = IRB.CreateIntToPtr( 563 memToShadow(IRB.CreatePointerCast(AI, IntptrTy), AI->getType(), IRB), 564 Int8PtrTy); 565 // If this memset is not inlined, it will be intercepted in the hwasan 566 // runtime library. That's OK, because the interceptor skips the checks if 567 // the address is in the shadow region. 568 // FIXME: the interceptor is not as fast as real memset. Consider lowering 569 // llvm.memset right here into either a sequence of stores, or a call to 570 // hwasan_tag_memory. 571 IRB.CreateMemSet(ShadowPtr, JustTag, ShadowSize, /*Align=*/1); 572 } 573 return true; 574 } 575 576 static unsigned RetagMask(unsigned AllocaNo) { 577 // A list of 8-bit numbers that have at most one run of non-zero bits. 578 // x = x ^ (mask << 56) can be encoded as a single armv8 instruction for these 579 // masks. 580 // The list does not include the value 255, which is used for UAR. 581 static unsigned FastMasks[] = { 582 0, 1, 2, 3, 4, 6, 7, 8, 12, 14, 15, 16, 24, 583 28, 30, 31, 32, 48, 56, 60, 62, 63, 64, 96, 112, 120, 584 124, 126, 127, 128, 192, 224, 240, 248, 252, 254}; 585 return FastMasks[AllocaNo % (sizeof(FastMasks) / sizeof(FastMasks[0]))]; 586 } 587 588 Value *HWAddressSanitizer::getNextTagWithCall(IRBuilder<> &IRB) { 589 return IRB.CreateZExt(IRB.CreateCall(HwasanGenerateTagFunc), IntptrTy); 590 } 591 592 Value *HWAddressSanitizer::getStackBaseTag(IRBuilder<> &IRB) { 593 if (ClGenerateTagsWithCalls) 594 return getNextTagWithCall(IRB); 595 // FIXME: use addressofreturnaddress (but implement it in aarch64 backend 596 // first). 597 Module *M = IRB.GetInsertBlock()->getParent()->getParent(); 598 auto GetStackPointerFn = 599 Intrinsic::getDeclaration(M, Intrinsic::frameaddress); 600 Value *StackPointer = IRB.CreateCall( 601 GetStackPointerFn, {Constant::getNullValue(IRB.getInt32Ty())}); 602 603 // Extract some entropy from the stack pointer for the tags. 604 // Take bits 20..28 (ASLR entropy) and xor with bits 0..8 (these differ 605 // between functions). 606 Value *StackPointerLong = IRB.CreatePointerCast(StackPointer, IntptrTy); 607 Value *StackTag = 608 IRB.CreateXor(StackPointerLong, IRB.CreateLShr(StackPointerLong, 20), 609 "hwasan.stack.base.tag"); 610 return StackTag; 611 } 612 613 Value *HWAddressSanitizer::getAllocaTag(IRBuilder<> &IRB, Value *StackTag, 614 AllocaInst *AI, unsigned AllocaNo) { 615 if (ClGenerateTagsWithCalls) 616 return getNextTagWithCall(IRB); 617 return IRB.CreateXor(StackTag, 618 ConstantInt::get(IntptrTy, RetagMask(AllocaNo))); 619 } 620 621 Value *HWAddressSanitizer::getUARTag(IRBuilder<> &IRB, Value *StackTag) { 622 if (ClUARRetagToZero) 623 return ConstantInt::get(IntptrTy, 0); 624 if (ClGenerateTagsWithCalls) 625 return getNextTagWithCall(IRB); 626 return IRB.CreateXor(StackTag, ConstantInt::get(IntptrTy, 0xFFU)); 627 } 628 629 // Add a tag to an address. 630 Value *HWAddressSanitizer::tagPointer(IRBuilder<> &IRB, Type *Ty, 631 Value *PtrLong, Value *Tag) { 632 Value *TaggedPtrLong; 633 if (CompileKernel) { 634 // Kernel addresses have 0xFF in the most significant byte. 635 Value *ShiftedTag = IRB.CreateOr( 636 IRB.CreateShl(Tag, kPointerTagShift), 637 ConstantInt::get(IntptrTy, (1ULL << kPointerTagShift) - 1)); 638 TaggedPtrLong = IRB.CreateAnd(PtrLong, ShiftedTag); 639 } else { 640 // Userspace can simply do OR (tag << 56); 641 Value *ShiftedTag = IRB.CreateShl(Tag, kPointerTagShift); 642 TaggedPtrLong = IRB.CreateOr(PtrLong, ShiftedTag); 643 } 644 return IRB.CreateIntToPtr(TaggedPtrLong, Ty); 645 } 646 647 // Remove tag from an address. 648 Value *HWAddressSanitizer::untagPointer(IRBuilder<> &IRB, Value *PtrLong) { 649 Value *UntaggedPtrLong; 650 if (CompileKernel) { 651 // Kernel addresses have 0xFF in the most significant byte. 652 UntaggedPtrLong = IRB.CreateOr(PtrLong, 653 ConstantInt::get(PtrLong->getType(), 0xFFULL << kPointerTagShift)); 654 } else { 655 // Userspace addresses have 0x00. 656 UntaggedPtrLong = IRB.CreateAnd(PtrLong, 657 ConstantInt::get(PtrLong->getType(), ~(0xFFULL << kPointerTagShift))); 658 } 659 return UntaggedPtrLong; 660 } 661 662 Value *HWAddressSanitizer::getHwasanThreadSlotPtr(IRBuilder<> &IRB, Type *Ty) { 663 Module *M = IRB.GetInsertBlock()->getParent()->getParent(); 664 if (TargetTriple.isAArch64() && TargetTriple.isAndroid()) { 665 Function *ThreadPointerFunc = 666 Intrinsic::getDeclaration(M, Intrinsic::thread_pointer); 667 Value *SlotPtr = IRB.CreatePointerCast( 668 IRB.CreateConstGEP1_32(IRB.CreateCall(ThreadPointerFunc), 0x40), 669 Ty->getPointerTo(0)); 670 return SlotPtr; 671 } 672 if (ThreadPtrGlobal) 673 return ThreadPtrGlobal; 674 675 676 return nullptr; 677 } 678 679 Value *HWAddressSanitizer::emitPrologue(IRBuilder<> &IRB, 680 bool WithFrameRecord) { 681 if (!Mapping.InTls) 682 return getDynamicShadowNonTls(IRB); 683 684 Value *SlotPtr = getHwasanThreadSlotPtr(IRB, IntptrTy); 685 assert(SlotPtr); 686 687 Value *ThreadLong = IRB.CreateLoad(SlotPtr); 688 // Extract the address field from ThreadLong. Unnecessary on AArch64 with TBI. 689 Value *ThreadLongMaybeUntagged = 690 TargetTriple.isAArch64() ? ThreadLong : untagPointer(IRB, ThreadLong); 691 692 if (WithFrameRecord) { 693 // Prepare ring buffer data. 694 Function *F = IRB.GetInsertBlock()->getParent(); 695 auto PC = IRB.CreatePtrToInt(F, IntptrTy); 696 auto GetStackPointerFn = 697 Intrinsic::getDeclaration(F->getParent(), Intrinsic::frameaddress); 698 Value *SP = IRB.CreatePtrToInt( 699 IRB.CreateCall(GetStackPointerFn, 700 {Constant::getNullValue(IRB.getInt32Ty())}), 701 IntptrTy); 702 // Mix SP and PC. TODO: also add the tag to the mix. 703 // Assumptions: 704 // PC is 0x0000PPPPPPPPPPPP (48 bits are meaningful, others are zero) 705 // SP is 0xsssssssssssSSSS0 (4 lower bits are zero) 706 // We only really need ~20 lower non-zero bits (SSSS), so we mix like this: 707 // 0xSSSSPPPPPPPPPPPP 708 SP = IRB.CreateShl(SP, 44); 709 710 // Store data to ring buffer. 711 Value *RecordPtr = 712 IRB.CreateIntToPtr(ThreadLongMaybeUntagged, IntptrTy->getPointerTo(0)); 713 IRB.CreateStore(IRB.CreateOr(PC, SP), RecordPtr); 714 715 // Update the ring buffer. Top byte of ThreadLong defines the size of the 716 // buffer in pages, it must be a power of two, and the start of the buffer 717 // must be aligned by twice that much. Therefore wrap around of the ring 718 // buffer is simply Addr &= ~((ThreadLong >> 56) << 12). 719 // The use of AShr instead of LShr is due to 720 // https://bugs.llvm.org/show_bug.cgi?id=39030 721 // Runtime library makes sure not to use the highest bit. 722 Value *WrapMask = IRB.CreateXor( 723 IRB.CreateShl(IRB.CreateAShr(ThreadLong, 56), 12, "", true, true), 724 ConstantInt::get(IntptrTy, (uint64_t)-1)); 725 Value *ThreadLongNew = IRB.CreateAnd( 726 IRB.CreateAdd(ThreadLong, ConstantInt::get(IntptrTy, 8)), WrapMask); 727 IRB.CreateStore(ThreadLongNew, SlotPtr); 728 } 729 730 // Get shadow base address by aligning RecordPtr up. 731 // Note: this is not correct if the pointer is already aligned. 732 // Runtime library will make sure this never happens. 733 Value *ShadowBase = IRB.CreateAdd( 734 IRB.CreateOr( 735 ThreadLongMaybeUntagged, 736 ConstantInt::get(IntptrTy, (1ULL << kShadowBaseAlignment) - 1)), 737 ConstantInt::get(IntptrTy, 1), "hwasan.shadow"); 738 return ShadowBase; 739 } 740 741 bool HWAddressSanitizer::instrumentStack( 742 SmallVectorImpl<AllocaInst *> &Allocas, 743 SmallVectorImpl<Instruction *> &RetVec, Value *StackTag) { 744 // Ideally, we want to calculate tagged stack base pointer, and rewrite all 745 // alloca addresses using that. Unfortunately, offsets are not known yet 746 // (unless we use ASan-style mega-alloca). Instead we keep the base tag in a 747 // temp, shift-OR it into each alloca address and xor with the retag mask. 748 // This generates one extra instruction per alloca use. 749 for (unsigned N = 0; N < Allocas.size(); ++N) { 750 auto *AI = Allocas[N]; 751 IRBuilder<> IRB(AI->getNextNode()); 752 753 // Replace uses of the alloca with tagged address. 754 Value *Tag = getAllocaTag(IRB, StackTag, AI, N); 755 Value *AILong = IRB.CreatePointerCast(AI, IntptrTy); 756 Value *Replacement = tagPointer(IRB, AI->getType(), AILong, Tag); 757 std::string Name = 758 AI->hasName() ? AI->getName().str() : "alloca." + itostr(N); 759 Replacement->setName(Name + ".hwasan"); 760 761 for (auto UI = AI->use_begin(), UE = AI->use_end(); UI != UE;) { 762 Use &U = *UI++; 763 if (U.getUser() != AILong) 764 U.set(Replacement); 765 } 766 767 tagAlloca(IRB, AI, Tag); 768 769 for (auto RI : RetVec) { 770 IRB.SetInsertPoint(RI); 771 772 // Re-tag alloca memory with the special UAR tag. 773 Value *Tag = getUARTag(IRB, StackTag); 774 tagAlloca(IRB, AI, Tag); 775 } 776 } 777 778 return true; 779 } 780 781 bool HWAddressSanitizer::isInterestingAlloca(const AllocaInst &AI) { 782 return (AI.getAllocatedType()->isSized() && 783 // FIXME: instrument dynamic allocas, too 784 AI.isStaticAlloca() && 785 // alloca() may be called with 0 size, ignore it. 786 getAllocaSizeInBytes(AI) > 0 && 787 // We are only interested in allocas not promotable to registers. 788 // Promotable allocas are common under -O0. 789 !isAllocaPromotable(&AI) && 790 // inalloca allocas are not treated as static, and we don't want 791 // dynamic alloca instrumentation for them as well. 792 !AI.isUsedWithInAlloca() && 793 // swifterror allocas are register promoted by ISel 794 !AI.isSwiftError()); 795 } 796 797 bool HWAddressSanitizer::runOnFunction(Function &F) { 798 if (&F == HwasanCtorFunction) 799 return false; 800 801 if (!F.hasFnAttribute(Attribute::SanitizeHWAddress)) 802 return false; 803 804 LLVM_DEBUG(dbgs() << "Function: " << F.getName() << "\n"); 805 806 SmallVector<Instruction*, 16> ToInstrument; 807 SmallVector<AllocaInst*, 8> AllocasToInstrument; 808 SmallVector<Instruction*, 8> RetVec; 809 for (auto &BB : F) { 810 for (auto &Inst : BB) { 811 if (ClInstrumentStack) 812 if (AllocaInst *AI = dyn_cast<AllocaInst>(&Inst)) { 813 // Realign all allocas. We don't want small uninteresting allocas to 814 // hide in instrumented alloca's padding. 815 if (AI->getAlignment() < Mapping.getAllocaAlignment()) 816 AI->setAlignment(Mapping.getAllocaAlignment()); 817 // Instrument some of them. 818 if (isInterestingAlloca(*AI)) 819 AllocasToInstrument.push_back(AI); 820 continue; 821 } 822 823 if (isa<ReturnInst>(Inst) || isa<ResumeInst>(Inst) || 824 isa<CleanupReturnInst>(Inst)) 825 RetVec.push_back(&Inst); 826 827 Value *MaybeMask = nullptr; 828 bool IsWrite; 829 unsigned Alignment; 830 uint64_t TypeSize; 831 Value *Addr = isInterestingMemoryAccess(&Inst, &IsWrite, &TypeSize, 832 &Alignment, &MaybeMask); 833 if (Addr || isa<MemIntrinsic>(Inst)) 834 ToInstrument.push_back(&Inst); 835 } 836 } 837 838 if (AllocasToInstrument.empty() && ToInstrument.empty()) 839 return false; 840 841 initializeCallbacks(*F.getParent()); 842 843 assert(!LocalDynamicShadow); 844 845 Instruction *InsertPt = &*F.getEntryBlock().begin(); 846 IRBuilder<> EntryIRB(InsertPt); 847 LocalDynamicShadow = emitPrologue(EntryIRB, 848 /*WithFrameRecord*/ ClRecordStackHistory && 849 !AllocasToInstrument.empty()); 850 851 bool Changed = false; 852 if (!AllocasToInstrument.empty()) { 853 Value *StackTag = 854 ClGenerateTagsWithCalls ? nullptr : getStackBaseTag(EntryIRB); 855 Changed |= instrumentStack(AllocasToInstrument, RetVec, StackTag); 856 } 857 858 for (auto Inst : ToInstrument) 859 Changed |= instrumentMemAccess(Inst); 860 861 LocalDynamicShadow = nullptr; 862 863 return Changed; 864 } 865 866 void HWAddressSanitizer::ShadowMapping::init(Triple &TargetTriple) { 867 Scale = kDefaultShadowScale; 868 if (ClMappingOffset.getNumOccurrences() > 0) { 869 InGlobal = false; 870 InTls = false; 871 Offset = ClMappingOffset; 872 } else if (ClEnableKhwasan || ClInstrumentWithCalls) { 873 InGlobal = false; 874 InTls = false; 875 Offset = 0; 876 } else if (ClWithIfunc) { 877 InGlobal = true; 878 InTls = false; 879 Offset = kDynamicShadowSentinel; 880 } else if (ClWithTls) { 881 InGlobal = false; 882 InTls = true; 883 Offset = kDynamicShadowSentinel; 884 } else { 885 InGlobal = false; 886 InTls = false; 887 Offset = kDynamicShadowSentinel; 888 } 889 } 890