Clear pointer tags as required for HWASAN for globals.

A future version of HWASAN will set pointer tags when taking the address of
a global. This means that we need to untag pointers in a couple of cases
where potential global pointers are passed to an interface that expects
untagged pointers:

- The WriteProtected class, whose only instances are globals, passes its
  own address to mprotect. However, our device kernels do not currently
  untag pointers passed to mprotect (the proposed upstream kernel patches
  do, however, untag these pointers), so once HWASAN starts tagging global
  pointers, this will start failing.
- The shadow_load function loads from a shadow that corresponds to the
  address space bounds of loaded binaries. Since these address space
  bounds are untagged, the pointer needs to be untagged to match.

Test: boots
Change-Id: I3f11ce6eb7261752e5ff6d039d04dd45516b236f
This commit is contained in:
Peter Collingbourne 2019-07-16 11:18:07 -07:00
parent 7e958d0ce0
commit 45f0a3b642
2 changed files with 17 additions and 3 deletions

View File

@ -46,6 +46,16 @@ class WriteProtected {
WriteProtectedContents<T> contents;
int set_protection(int prot) {
auto addr = reinterpret_cast<uintptr_t>(&contents);
#if __has_feature(hwaddress_sanitizer)
// The mprotect system call does not currently untag pointers, so do it
// ourselves.
addr &= (1ULL << 56) - 1;
#endif
return mprotect(reinterpret_cast<void*>(addr), PAGE_SIZE, prot);
}
public:
WriteProtected() = default;
BIONIC_DISALLOW_COPY_AND_ASSIGN(WriteProtected);
@ -55,7 +65,7 @@ class WriteProtected {
// multiple times by accident.
memset(&contents, 0, sizeof(contents));
if (mprotect(&contents, PAGE_SIZE, PROT_READ)) {
if (set_protection(PROT_READ)) {
async_safe_fatal("failed to make WriteProtected nonwritable in initialize");
}
}
@ -70,12 +80,12 @@ class WriteProtected {
template <typename Mutator>
void mutate(Mutator mutator) {
if (mprotect(&contents, PAGE_SIZE, PROT_READ | PROT_WRITE) != 0) {
if (set_protection(PROT_READ | PROT_WRITE) != 0) {
async_safe_fatal("failed to make WriteProtected writable in mutate: %s",
strerror(errno));
}
mutator(&contents.value);
if (mprotect(&contents, PAGE_SIZE, PROT_READ) != 0) {
if (set_protection(PROT_READ) != 0) {
async_safe_fatal("failed to make WriteProtected nonwritable in mutate: %s",
strerror(errno));
}

View File

@ -45,6 +45,10 @@ extern "C" size_t __cfi_shadow_size() {
static uint16_t shadow_load(void* p) {
uintptr_t addr = reinterpret_cast<uintptr_t>(p);
#ifdef __aarch64__
// Untag the pointer to move it into the address space covered by the shadow.
addr &= (1ULL << 56) - 1;
#endif
uintptr_t ofs = CFIShadow::MemToShadowOffset(addr);
if (ofs > CFIShadow::kShadowSize) return CFIShadow::kInvalidShadow;
return *reinterpret_cast<uint16_t*>(shadow_base_storage.v + ofs);