Skip to content

Commit

Permalink
[hwasan] Fix kernel instrumentation of stack.
Browse files Browse the repository at this point in the history
Summary:
Kernel addresses have 0xFF in the most significant byte.
A tag can not be pushed there with OR (tag << 56);
use AND ((tag << 56) | 0x00FF..FF) instead.

Reviewers: kcc, andreyknvl

Subscribers: srhines, llvm-commits, hiraditya

Differential Revision: https://reviews.llvm.org/D42941

llvm-svn: 324691
  • Loading branch information
eugenis committed Feb 9, 2018
1 parent 7d3dde3 commit 80ccda2
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 3 deletions.
24 changes: 21 additions & 3 deletions llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
Expand Up @@ -133,6 +133,7 @@ class HWAddressSanitizer : public FunctionPass {

bool isInterestingAlloca(const AllocaInst &AI);
bool tagAlloca(IRBuilder<> &IRB, AllocaInst *AI, Value *Tag);
Value *tagPointer(IRBuilder<> &IRB, Type *Ty, Value *PtrLong, Value *Tag);
bool instrumentStack(SmallVectorImpl<AllocaInst *> &Allocas,
SmallVectorImpl<Instruction *> &RetVec);
Value *getNextTagWithCall(IRBuilder<> &IRB);
Expand Down Expand Up @@ -442,6 +443,24 @@ Value *HWAddressSanitizer::getUARTag(IRBuilder<> &IRB, Value *StackTag) {
return IRB.CreateXor(StackTag, ConstantInt::get(IntptrTy, 0xFFU));
}

// Add a tag to an address.
Value *HWAddressSanitizer::tagPointer(IRBuilder<> &IRB, Type *Ty, Value *PtrLong,
Value *Tag) {
Value *TaggedPtrLong;
if (ClEnableKhwasan) {
// Kernel addresses have 0xFF in the most significant byte.
Value *ShiftedTag = IRB.CreateOr(
IRB.CreateShl(Tag, kPointerTagShift),
ConstantInt::get(IntptrTy, (1ULL << kPointerTagShift) - 1));
TaggedPtrLong = IRB.CreateAnd(PtrLong, ShiftedTag);
} else {
// Userspace can simply do OR (tag << 56);
Value *ShiftedTag = IRB.CreateShl(Tag, kPointerTagShift);
TaggedPtrLong = IRB.CreateOr(PtrLong, ShiftedTag);
}
return IRB.CreateIntToPtr(TaggedPtrLong, Ty);
}

bool HWAddressSanitizer::instrumentStack(
SmallVectorImpl<AllocaInst *> &Allocas,
SmallVectorImpl<Instruction *> &RetVec) {
Expand All @@ -463,11 +482,10 @@ bool HWAddressSanitizer::instrumentStack(
// Replace uses of the alloca with tagged address.
Value *Tag = getAllocaTag(IRB, StackTag, AI, N);
Value *AILong = IRB.CreatePointerCast(AI, IntptrTy);
Value *Replacement = tagPointer(IRB, AI->getType(), AILong, Tag);
std::string Name =
AI->hasName() ? AI->getName().str() : "alloca." + itostr(N);
Value *Replacement = IRB.CreateIntToPtr(
IRB.CreateOr(AILong, IRB.CreateShl(Tag, kPointerTagShift)),
AI->getType(), Name + ".hwasan");
Replacement->setName(Name + ".hwasan");

for (auto UI = AI->use_begin(), UE = AI->use_end(); UI != UE;) {
Use &U = *UI++;
Expand Down
29 changes: 29 additions & 0 deletions llvm/test/Instrumentation/HWAddressSanitizer/kernel-alloca.ll
@@ -0,0 +1,29 @@
; Test basic address sanitizer instrumentation.
;
; RUN: opt < %s -hwasan -hwasan-kernel=1 -S | FileCheck %s

target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64--linux-android"

declare void @use32(i32*)

define void @test_alloca() sanitize_hwaddress {
; CHECK-LABEL: @test_alloca(
; CHECK: %[[FP:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
; CHECK: %[[A:[^ ]*]] = ptrtoint i8* %[[FP]] to i64
; CHECK: %[[B:[^ ]*]] = lshr i64 %[[A]], 20
; CHECK: %[[BASE_TAG:[^ ]*]] = xor i64 %[[A]], %[[B]]

; CHECK: %[[X:[^ ]*]] = alloca i32, align 16
; CHECK: %[[X_TAG:[^ ]*]] = xor i64 %[[BASE_TAG]], 0
; CHECK: %[[X1:[^ ]*]] = ptrtoint i32* %[[X]] to i64
; CHECK: %[[C:[^ ]*]] = shl i64 %[[X_TAG]], 56
; CHECK: %[[D:[^ ]*]] = or i64 %[[C]], 72057594037927935
; CHECK: %[[E:[^ ]*]] = and i64 %[[X1]], %[[D]]
; CHECK: %[[X_HWASAN:[^ ]*]] = inttoptr i64 %[[E]] to i32*

entry:
%x = alloca i32, align 4
call void @use32(i32* nonnull %x)
ret void
}

0 comments on commit 80ccda2

Please sign in to comment.