Skip to content

Commit

Permalink
[HWASAN] Improve tag mismatch diagnostics
Browse files Browse the repository at this point in the history
Reports correct size and tags when either size is not power of two
or offset to bad granule is not zero.

Differential revision: https://reviews.llvm.org/D56603

llvm-svn: 351730
  • Loading branch information
eleviant committed Jan 21, 2019
1 parent f608dc1 commit 0d7952c
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 13 deletions.
8 changes: 4 additions & 4 deletions compiler-rt/lib/hwasan/hwasan.cc
Original file line number Diff line number Diff line change
Expand Up @@ -336,14 +336,14 @@ sptr __hwasan_test_shadow(const void *p, uptr sz) {
if (sz == 0)
return -1;
tag_t ptr_tag = GetTagFromPointer((uptr)p);
if (ptr_tag == 0)
return -1;
uptr ptr_raw = UntagAddr(reinterpret_cast<uptr>(p));
uptr shadow_first = MemToShadow(ptr_raw);
uptr shadow_last = MemToShadow(ptr_raw + sz - 1);
for (uptr s = shadow_first; s <= shadow_last; ++s)
if (*(tag_t*)s != ptr_tag)
return ShadowToMem(s) - ptr_raw;
if (*(tag_t *)s != ptr_tag) {
sptr offset = ShadowToMem(s) - ptr_raw;
return offset < 0 ? 0 : offset;
}
return -1;
}

Expand Down
26 changes: 23 additions & 3 deletions compiler-rt/lib/hwasan/hwasan_checks.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#define HWASAN_CHECKS_H

#include "hwasan_mapping.h"
#include "sanitizer_common/sanitizer_common.h"

namespace __hwasan {
template <unsigned X>
Expand All @@ -22,8 +23,8 @@ __attribute__((always_inline)) static void SigTrap(uptr p) {
(void)p;
// 0x900 is added to do not interfere with the kernel use of lower values of
// brk immediate.
// FIXME: Add a constraint to put the pointer into x0, the same as x86 branch.
asm("brk %0\n\t" ::"n"(0x900 + X));
register uptr x0 asm("x0") = p;
asm("brk %1\n\t" ::"r"(x0), "n"(0x900 + X));
#elif defined(__x86_64__)
// INT3 + NOP DWORD ptr [EAX + X] to pass X to our signal handler, 5 bytes
// total. The pointer is passed via rdi.
Expand All @@ -41,6 +42,25 @@ __attribute__((always_inline)) static void SigTrap(uptr p) {
// __builtin_unreachable();
}

// Version with access size which is not power of 2
template <unsigned X>
__attribute__((always_inline)) static void SigTrap(uptr p, uptr size) {
#if defined(__aarch64__)
register uptr x0 asm("x0") = p;
register uptr x1 asm("x1") = size;
asm("brk %2\n\t" ::"r"(x0), "r"(x1), "n"(0x900 + X));
#elif defined(__x86_64__)
// Size is stored in rsi.
asm volatile(
"int3\n"
"nopl %c0(%%rax)\n" ::"n"(0x40 + X),
"D"(p), "S"(size));
#else
__builtin_trap();
#endif
// __builtin_unreachable();
}

enum class ErrorAction { Abort, Recover };
enum class AccessType { Load, Store };

Expand Down Expand Up @@ -69,7 +89,7 @@ __attribute__((always_inline, nodebug)) static void CheckAddressSized(uptr p,
for (tag_t *t = shadow_first; t <= shadow_last; ++t)
if (UNLIKELY(ptr_tag != *t)) {
SigTrap<0x20 * (EA == ErrorAction::Recover) +
0x10 * (AT == AccessType::Store) + 0xf>(p);
0x10 * (AT == AccessType::Store) + 0xf>(p, sz);
if (EA == ErrorAction::Abort)
__builtin_unreachable();
}
Expand Down
10 changes: 9 additions & 1 deletion compiler-rt/lib/hwasan/hwasan_report.cc
Original file line number Diff line number Diff line change
Expand Up @@ -399,13 +399,21 @@ void ReportTagMismatch(StackTrace *stack, uptr tagged_addr, uptr access_size,

Thread *t = GetCurrentThread();

sptr offset =
__hwasan_test_shadow(reinterpret_cast<void *>(tagged_addr), access_size);
CHECK(offset >= 0 && offset < static_cast<sptr>(access_size));
tag_t ptr_tag = GetTagFromPointer(tagged_addr);
tag_t *tag_ptr = reinterpret_cast<tag_t*>(MemToShadow(untagged_addr));
tag_t *tag_ptr =
reinterpret_cast<tag_t *>(MemToShadow(untagged_addr + offset));
tag_t mem_tag = *tag_ptr;

Printf("%s", d.Access());
Printf("%s of size %zu at %p tags: %02x/%02x (ptr/mem) in thread T%zd\n",
is_store ? "WRITE" : "READ", access_size, untagged_addr, ptr_tag,
mem_tag, t->unique_id());
if (offset != 0)
Printf("Invalid access starting at offset [%zu, %zu)\n", offset,
Min(access_size, static_cast<uptr>(offset) + (1 << kShadowScale)));
Printf("%s", d.Default());

stack->Print();
Expand Down
12 changes: 7 additions & 5 deletions compiler-rt/test/hwasan/TestCases/mem-intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
#include <unistd.h>

int main() {
char Q[16];
char P[16];
char Q[16] __attribute__((aligned(256)));
char P[16] __attribute__((aligned(256)));
#if TEST_NO == 1
memset(Q, 0, 32);
#elif TEST_NO == 2
Expand All @@ -21,15 +21,17 @@ int main() {
#endif
write(STDOUT_FILENO, "recovered\n", 10);
// WRITE: ERROR: HWAddressSanitizer: tag-mismatch on address
// WRITE: WRITE {{.*}} tags: [[PTR_TAG:..]]/[[MEM_TAG:..]] (ptr/mem)
// WRITE: WRITE of size 32 at {{.*}} tags: [[PTR_TAG:..]]/[[MEM_TAG:..]] (ptr/mem)
// WRITE: Invalid access starting at offset [16, 32)
// WRITE: Memory tags around the buggy address (one tag corresponds to 16 bytes):
// WRITE: =>{{.*}}[[MEM_TAG]]
// WRITE: =>{{.*}}[[PTR_TAG]]{{[[:space:]]\[}}[[MEM_TAG]]
// WRITE-NOT: recovered

// READ: ERROR: HWAddressSanitizer: tag-mismatch on address
// READ-NOT: Invalid access starting at offset
// READ: READ {{.*}} tags: [[PTR_TAG:..]]/[[MEM_TAG:..]] (ptr/mem)
// READ: Memory tags around the buggy address (one tag corresponds to 16 bytes):
// READ: =>{{.*}}[[MEM_TAG]]
// READ: =>{{.*}}[[PTR_TAG]]{{[[:space:]]\[}}[[MEM_TAG]]
// READ-NOT: recovered

// RECOVER: recovered
Expand Down

0 comments on commit 0d7952c

Please sign in to comment.