@@ -91,6 +91,11 @@ static cl::opt<bool> ClInstrumentStack("hwasan-instrument-stack",
91
91
cl::desc (" instrument stack (allocas)" ),
92
92
cl::Hidden, cl::init(true ));
93
93
94
+ static cl::opt<bool > ClGenerateTagsWithCalls (
95
+ " hwasan-generate-tags-with-calls" ,
96
+ cl::desc (" generate new tags with runtime library calls" ), cl::Hidden,
97
+ cl::init(false ));
98
+
94
99
namespace {
95
100
96
101
// / \brief An instrumentation pass implementing detection of addressability bugs
@@ -121,6 +126,11 @@ class HWAddressSanitizer : public FunctionPass {
121
126
bool tagAlloca (IRBuilder<> &IRB, AllocaInst *AI, Value *Tag);
122
127
bool instrumentStack (SmallVectorImpl<AllocaInst *> &Allocas,
123
128
SmallVectorImpl<Instruction *> &RetVec);
129
+ Value *getNextTagWithCall (IRBuilder<> &IRB);
130
+ Value *getStackBaseTag (IRBuilder<> &IRB);
131
+ Value *getAllocaTag (IRBuilder<> &IRB, Value *StackTag, AllocaInst *AI,
132
+ unsigned AllocaNo);
133
+ Value *getUARTag (IRBuilder<> &IRB, Value *StackTag);
124
134
125
135
private:
126
136
LLVMContext *C;
@@ -135,6 +145,7 @@ class HWAddressSanitizer : public FunctionPass {
135
145
Function *HwasanMemoryAccessCallbackSized[2 ];
136
146
137
147
Function *HwasanTagMemoryFunc;
148
+ Function *HwasanGenerateTagFunc;
138
149
};
139
150
140
151
} // end anonymous namespace
@@ -198,6 +209,8 @@ void HWAddressSanitizer::initializeCallbacks(Module &M) {
198
209
199
210
HwasanTagMemoryFunc = checkSanitizerInterfaceFunction (M.getOrInsertFunction (
200
211
" __hwasan_tag_memory" , IRB.getVoidTy (), IntptrTy, Int8Ty, IntptrTy));
212
+ HwasanGenerateTagFunc = checkSanitizerInterfaceFunction (
213
+ M.getOrInsertFunction (" __hwasan_generate_tag" , Int8Ty));
201
214
}
202
215
203
216
Value *HWAddressSanitizer::isInterestingMemoryAccess (Instruction *I,
@@ -373,18 +386,20 @@ static unsigned RetagMask(unsigned AllocaNo) {
373
386
return FastMasks[AllocaNo % (sizeof (FastMasks) / sizeof (FastMasks[0 ]))];
374
387
}
375
388
376
- bool HWAddressSanitizer::instrumentStack (
377
- SmallVectorImpl<AllocaInst *> &Allocas,
378
- SmallVectorImpl<Instruction *> &RetVec) {
379
- Function *F = Allocas[0 ]->getParent ()->getParent ();
380
- Module *M = F->getParent ();
381
- Instruction *InsertPt = &*F->getEntryBlock ().begin ();
382
- IRBuilder<> IRB (InsertPt);
389
+ Value *HWAddressSanitizer::getNextTagWithCall (IRBuilder<> &IRB) {
390
+ return IRB.CreateZExt (IRB.CreateCall (HwasanGenerateTagFunc), IntptrTy);
391
+ }
383
392
393
+ Value *HWAddressSanitizer::getStackBaseTag (IRBuilder<> &IRB) {
394
+ if (ClGenerateTagsWithCalls)
395
+ return nullptr ;
384
396
// FIXME: use addressofreturnaddress (but implement it in aarch64 backend
385
397
// first).
386
- auto GetStackPointerFn = Intrinsic::getDeclaration (M, Intrinsic::frameaddress);
387
- Value *StackPointer = IRB.CreateCall (GetStackPointerFn, {Constant::getNullValue (IRB.getInt32Ty ())});
398
+ Module *M = IRB.GetInsertBlock ()->getParent ()->getParent ();
399
+ auto GetStackPointerFn =
400
+ Intrinsic::getDeclaration (M, Intrinsic::frameaddress);
401
+ Value *StackPointer = IRB.CreateCall (
402
+ GetStackPointerFn, {Constant::getNullValue (IRB.getInt32Ty ())});
388
403
389
404
// Extract some entropy from the stack pointer for the tags.
390
405
// Take bits 20..28 (ASLR entropy) and xor with bits 0..8 (these differ
@@ -393,6 +408,31 @@ bool HWAddressSanitizer::instrumentStack(
393
408
Value *StackTag =
394
409
IRB.CreateXor (StackPointerLong, IRB.CreateLShr (StackPointerLong, 20 ),
395
410
" hwasan.stack.base.tag" );
411
+ return StackTag;
412
+ }
413
+
414
+ Value *HWAddressSanitizer::getAllocaTag (IRBuilder<> &IRB, Value *StackTag,
415
+ AllocaInst *AI, unsigned AllocaNo) {
416
+ if (ClGenerateTagsWithCalls)
417
+ return getNextTagWithCall (IRB);
418
+ return IRB.CreateXor (StackTag,
419
+ ConstantInt::get (IntptrTy, RetagMask (AllocaNo)));
420
+ }
421
+
422
+ Value *HWAddressSanitizer::getUARTag (IRBuilder<> &IRB, Value *StackTag) {
423
+ if (ClGenerateTagsWithCalls)
424
+ return getNextTagWithCall (IRB);
425
+ return IRB.CreateXor (StackTag, ConstantInt::get (IntptrTy, 0xFFU ));
426
+ }
427
+
428
+ bool HWAddressSanitizer::instrumentStack (
429
+ SmallVectorImpl<AllocaInst *> &Allocas,
430
+ SmallVectorImpl<Instruction *> &RetVec) {
431
+ Function *F = Allocas[0 ]->getParent ()->getParent ();
432
+ Instruction *InsertPt = &*F->getEntryBlock ().begin ();
433
+ IRBuilder<> IRB (InsertPt);
434
+
435
+ Value *StackTag = getStackBaseTag (IRB);
396
436
397
437
// Ideally, we want to calculate tagged stack base pointer, and rewrite all
398
438
// alloca addresses using that. Unfortunately, offsets are not known yet
@@ -404,17 +444,15 @@ bool HWAddressSanitizer::instrumentStack(
404
444
IRB.SetInsertPoint (AI->getNextNode ());
405
445
406
446
// Replace uses of the alloca with tagged address.
447
+ Value *Tag = getAllocaTag (IRB, StackTag, AI, N);
448
+ Value *AILong = IRB.CreatePointerCast (AI, IntptrTy);
407
449
std::string Name =
408
450
AI->hasName () ? AI->getName ().str () : " alloca." + itostr (N);
409
- Value *Tag =
410
- IRB.CreateXor (StackTag, ConstantInt::get (IntptrTy, RetagMask (N)));
411
- Value *AILong = IRB.CreatePointerCast (AI, IntptrTy);
412
451
Value *Replacement = IRB.CreateIntToPtr (
413
452
IRB.CreateOr (AILong, IRB.CreateShl (Tag, kPointerTagShift )),
414
453
AI->getType (), Name + " .hwasan" );
415
454
416
- for (auto UI = AI->use_begin (), UE = AI->use_end ();
417
- UI != UE;) {
455
+ for (auto UI = AI->use_begin (), UE = AI->use_end (); UI != UE;) {
418
456
Use &U = *UI++;
419
457
if (U.getUser () != AILong)
420
458
U.set (Replacement);
@@ -426,7 +464,7 @@ bool HWAddressSanitizer::instrumentStack(
426
464
IRB.SetInsertPoint (RI);
427
465
428
466
// Re-tag alloca memory with the special UAR tag.
429
- Value *Tag = IRB. CreateXor (StackTag, ConstantInt::get (IntptrTy, 0xFFU ) );
467
+ Value *Tag = getUARTag (IRB, StackTag );
430
468
tagAlloca (IRB, AI, Tag);
431
469
}
432
470
}
0 commit comments