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
diff --git a/libc/private/WriteProtected.h b/libc/private/WriteProtected.h
index 69a6822..d240e14 100644
--- a/libc/private/WriteProtected.h
+++ b/libc/private/WriteProtected.h
@@ -46,6 +46,16 @@
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 @@
// 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 @@
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));
}