[hwasan] Add a basic API.

Summary:
Add user tag manipulation functions:
  __hwasan_tag_memory
  __hwasan_tag_pointer
  __hwasan_print_shadow (very simple and ugly, for now)

Reviewers: vitalybuka, kcc

Subscribers: kubamracek, hiraditya, llvm-commits

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

llvm-svn: 339746
This commit is contained in:
Evgeniy Stepanov 2018-08-15 00:39:35 +00:00
parent 3ccf14eb8e
commit a265a13bbe
5 changed files with 62 additions and 8 deletions

View File

@ -32,6 +32,18 @@ extern "C" {
void __hwasan_enable_allocator_tagging(void);
void __hwasan_disable_allocator_tagging(void);
// Mark region of memory with the given tag. Both address and size need to be
// 16-byte aligned.
void __hwasan_tag_memory(const volatile void *p, unsigned char tag,
size_t size);
/// Set pointer tag. Previous tag is lost.
void *__hwasan_tag_pointer(const volatile void *p, unsigned char tag);
// Print shadow and origin for the memory range to stderr in a human-readable
// format.
void __hwasan_print_shadow(const volatile void *x, size_t size);
int __sanitizer_posix_memalign(void **memptr, size_t alignment, size_t size);
void * __sanitizer_memalign(size_t alignment, size_t size);
void * __sanitizer_aligned_alloc(size_t alignment, size_t size);

View File

@ -224,9 +224,14 @@ void __hwasan_init() {
hwasan_inited = 1;
}
void __hwasan_print_shadow(const void *x, uptr size) {
// FIXME:
Printf("FIXME: __hwasan_print_shadow unimplemented\n");
void __hwasan_print_shadow(const void *p, uptr sz) {
uptr ptr_raw = GetAddressFromPointer((uptr)p);
uptr shadow_first = MEM_TO_SHADOW(ptr_raw);
uptr shadow_last = MEM_TO_SHADOW(ptr_raw + sz - 1);
Printf("HWASan shadow map for %zx .. %zx (pointer tag %x)\n", ptr_raw,
ptr_raw + sz, GetTagFromPointer((uptr)p));
for (uptr s = shadow_first; s <= shadow_last; ++s)
Printf(" %zx: %x\n", SHADOW_TO_MEM(s), *(tag_t *)s);
}
sptr __hwasan_test_shadow(const void *p, uptr sz) {
@ -400,6 +405,10 @@ void __hwasan_tag_memory(uptr p, u8 tag, uptr sz) {
TagMemoryAligned(p, sz, tag);
}
uptr __hwasan_tag_pointer(uptr p, u8 tag) {
return AddTagToPointer(p, tag);
}
static const u8 kFallbackTag = 0xBB;
u8 __hwasan_generate_tag() {

View File

@ -93,6 +93,9 @@ void __hwasan_store16_noabort(uptr);
SANITIZER_INTERFACE_ATTRIBUTE
void __hwasan_tag_memory(uptr p, u8 tag, uptr sz);
SANITIZER_INTERFACE_ATTRIBUTE
uptr __hwasan_tag_pointer(uptr p, u8 tag);
SANITIZER_INTERFACE_ATTRIBUTE
u8 __hwasan_generate_tag();

View File

@ -0,0 +1,29 @@
// RUN: %clangxx_hwasan -DSIZE=16 -O0 %s -o %t && %run %t 2>&1 | FileCheck %s
// REQUIRES: stable-runtime
#include <assert.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sanitizer/hwasan_interface.h>
int main() {
char *p = (char *)mmap(nullptr, 4096, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
assert(p);
__hwasan_tag_memory(p, 1, 32);
__hwasan_tag_memory(p + 32, 3, 16);
__hwasan_tag_memory(p + 48, 0, 32);
__hwasan_tag_memory(p + 80, 4, 16);
char *q = (char *)__hwasan_tag_pointer(p, 7);
__hwasan_print_shadow(q + 5, 89 - 5);
// CHECK: HWASan shadow map for {{.*}}5 .. {{.*}}9 (pointer tag 7)
// CHECK-NEXT: {{.*}}0: 1
// CHECK-NEXT: {{.*}}0: 1
// CHECK-NEXT: {{.*}}0: 3
// CHECK-NEXT: {{.*}}0: 0
// CHECK-NEXT: {{.*}}0: 0
// CHECK-NEXT: {{.*}}0: 4
}

View File

@ -199,6 +199,7 @@ private:
ShadowMapping Mapping;
Type *IntptrTy;
Type *Int8PtrTy;
Type *Int8Ty;
bool CompileKernel;
@ -250,6 +251,7 @@ bool HWAddressSanitizer::doInitialization(Module &M) {
C = &(M.getContext());
IRBuilder<> IRB(*C);
IntptrTy = IRB.getIntPtrTy(DL);
Int8PtrTy = IRB.getInt8PtrTy();
Int8Ty = IRB.getInt8Ty();
HwasanCtorFunction = nullptr;
@ -286,7 +288,7 @@ void HWAddressSanitizer::initializeCallbacks(Module &M) {
}
HwasanTagMemoryFunc = checkSanitizerInterfaceFunction(M.getOrInsertFunction(
"__hwasan_tag_memory", IRB.getVoidTy(), IntptrTy, Int8Ty, IntptrTy));
"__hwasan_tag_memory", IRB.getVoidTy(), Int8PtrTy, Int8Ty, IntptrTy));
HwasanGenerateTagFunc = checkSanitizerInterfaceFunction(
M.getOrInsertFunction("__hwasan_generate_tag", Int8Ty));
@ -426,8 +428,7 @@ void HWAddressSanitizer::instrumentMemAccessInline(Value *PtrLong, bool IsWrite,
IRB.getInt8Ty());
Value *AddrLong = untagPointer(IRB, PtrLong);
Value *ShadowLong = memToShadow(AddrLong, PtrLong->getType(), IRB);
Value *MemTag =
IRB.CreateLoad(IRB.CreateIntToPtr(ShadowLong, IRB.getInt8PtrTy()));
Value *MemTag = IRB.CreateLoad(IRB.CreateIntToPtr(ShadowLong, Int8PtrTy));
Value *TagMismatch = IRB.CreateICmpNE(PtrTag, MemTag);
int matchAllTag = ClMatchAllTag.getNumOccurrences() > 0 ?
@ -526,13 +527,13 @@ bool HWAddressSanitizer::tagAlloca(IRBuilder<> &IRB, AllocaInst *AI,
Value *JustTag = IRB.CreateTrunc(Tag, IRB.getInt8Ty());
if (ClInstrumentWithCalls) {
IRB.CreateCall(HwasanTagMemoryFunc,
{IRB.CreatePointerCast(AI, IntptrTy), JustTag,
{IRB.CreatePointerCast(AI, Int8PtrTy), JustTag,
ConstantInt::get(IntptrTy, Size)});
} else {
size_t ShadowSize = Size >> Mapping.Scale;
Value *ShadowPtr = IRB.CreateIntToPtr(
memToShadow(IRB.CreatePointerCast(AI, IntptrTy), AI->getType(), IRB),
IRB.getInt8PtrTy());
Int8PtrTy);
// If this memset is not inlined, it will be intercepted in the hwasan
// runtime library. That's OK, because the interceptor skips the checks if
// the address is in the shadow region.