summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libc/private/WriteProtected.h4
-rw-r--r--libc/private/bionic_macros.h9
-rw-r--r--libdl/libdl_cfi.cpp5
-rw-r--r--linker/linker.cpp10
-rw-r--r--tests/dlext_test.cpp6
-rw-r--r--tests/libs/segment_gap_outer.lds2
6 files changed, 23 insertions, 13 deletions
diff --git a/libc/private/WriteProtected.h b/libc/private/WriteProtected.h
index d240e1465..26c239ca1 100644
--- a/libc/private/WriteProtected.h
+++ b/libc/private/WriteProtected.h
@@ -47,11 +47,11 @@ class WriteProtected {
WriteProtectedContents<T> contents;
int set_protection(int prot) {
- auto addr = reinterpret_cast<uintptr_t>(&contents);
+ auto addr = &contents;
#if __has_feature(hwaddress_sanitizer)
// The mprotect system call does not currently untag pointers, so do it
// ourselves.
- addr &= (1ULL << 56) - 1;
+ addr = untag_address(addr);
#endif
return mprotect(reinterpret_cast<void*>(addr), PAGE_SIZE, prot);
}
diff --git a/libc/private/bionic_macros.h b/libc/private/bionic_macros.h
index 4800e3af9..13934e5f6 100644
--- a/libc/private/bionic_macros.h
+++ b/libc/private/bionic_macros.h
@@ -87,3 +87,12 @@ char (&ArraySizeHelper(T (&array)[N]))[N]; // NOLINT(readability/casting)
#else
#define __BIONIC_FALLTHROUGH
#endif
+
+template <typename T>
+static inline T* untag_address(T* p) {
+#if defined(__aarch64__)
+ return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(p) & ((1ULL << 56) - 1));
+#else
+ return p;
+#endif
+}
diff --git a/libdl/libdl_cfi.cpp b/libdl/libdl_cfi.cpp
index 14461436c..3b68fc7d3 100644
--- a/libdl/libdl_cfi.cpp
+++ b/libdl/libdl_cfi.cpp
@@ -44,11 +44,8 @@ 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 addr = reinterpret_cast<uintptr_t>(untag_address(p));
uintptr_t ofs = CFIShadow::MemToShadowOffset(addr);
if (ofs > CFIShadow::kShadowSize) return CFIShadow::kInvalidShadow;
return *reinterpret_cast<uint16_t*>(shadow_base_storage.v + ofs);
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 0361a8ab3..e41194d1a 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -951,7 +951,9 @@ static const ElfW(Sym)* dlsym_linear_lookup(android_namespace_t* ns,
}
soinfo* find_containing_library(const void* p) {
- ElfW(Addr) address = reinterpret_cast<ElfW(Addr)>(p);
+ // Addresses within a library may be tagged if they point to globals. Untag
+ // them so that the bounds check succeeds.
+ ElfW(Addr) address = reinterpret_cast<ElfW(Addr)>(untag_address(p));
for (soinfo* si = solist_get_head(); si != nullptr; si = si->next) {
if (address < si->base || address - si->base >= si->size) {
continue;
@@ -1901,13 +1903,13 @@ bool find_libraries(android_namespace_t* ns,
// flag is set.
link_extinfo = extinfo;
}
+ if (__libc_shared_globals()->load_hook) {
+ __libc_shared_globals()->load_hook(si->load_bias, si->phdr, si->phnum);
+ }
if (!si->link_image(global_group, local_group, link_extinfo, &relro_fd_offset) ||
!get_cfi_shadow()->AfterLoad(si, solist_get_head())) {
return false;
}
- if (__libc_shared_globals()->load_hook) {
- __libc_shared_globals()->load_hook(si->load_bias, si->phdr, si->phnum);
- }
}
return true;
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index 59cf2f771..e7274f704 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -361,8 +361,10 @@ TEST_F(DlExtTest, ReservedRecursive) {
uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
ASSERT_DL_NOTNULL(taxicab_number);
- EXPECT_GE(reinterpret_cast<void*>(taxicab_number), start);
- EXPECT_LT(reinterpret_cast<void*>(taxicab_number), reinterpret_cast<char*>(start) + kLibSize);
+ // Untag the pointer so that it can be compared with start, which will be untagged.
+ void* addr = reinterpret_cast<void*>(untag_address(taxicab_number));
+ EXPECT_GE(addr, start);
+ EXPECT_LT(addr, reinterpret_cast<char*>(start) + kLibSize);
EXPECT_EQ(1729U, *taxicab_number);
}
diff --git a/tests/libs/segment_gap_outer.lds b/tests/libs/segment_gap_outer.lds
index f326aab26..c2961b2c6 100644
--- a/tests/libs/segment_gap_outer.lds
+++ b/tests/libs/segment_gap_outer.lds
@@ -22,6 +22,6 @@ SECTIONS {
# Place end_of_gap at the end of the gap.
. = 0x1000000;
.bss.end_of_gap : {
- *(.bss.end_of_gap);
+ *(.bss.*end_of_gap*);
}
}