Merge "Allow to reset malloc hooks."
diff --git a/libc/bionic/sigaction.cpp b/libc/bionic/sigaction.cpp
index 42dcccd..96e6f3c 100644
--- a/libc/bionic/sigaction.cpp
+++ b/libc/bionic/sigaction.cpp
@@ -43,7 +43,8 @@
if (bionic_new_action != nullptr) {
kernel_new_action.sa_flags = bionic_new_action->sa_flags;
kernel_new_action.sa_handler = bionic_new_action->sa_handler;
- kernel_new_action.sa_mask = filter_reserved_signals(bionic_new_action->sa_mask, SIG_SETMASK);
+ // Don't filter signals here; if the caller asked for everything to be blocked, we should obey.
+ kernel_new_action.sa_mask = bionic_new_action->sa_mask;
#if defined(SA_RESTORER)
kernel_new_action.sa_restorer = bionic_new_action->sa_restorer;
#if defined(__aarch64__)
@@ -95,6 +96,7 @@
#if defined(SA_RESTORER)
kernel_new.sa_restorer = bionic_new->sa_restorer;
#endif
+ // Don't filter signals here; if the caller asked for everything to be blocked, we should obey.
memcpy(&kernel_new.sa_mask, &bionic_new->sa_mask, sizeof(bionic_new->sa_mask));
}
@@ -122,7 +124,8 @@
kernel_new.sa_restorer = (kernel_new.sa_flags & SA_SIGINFO) ? &__restore_rt : &__restore;
}
#endif
- kernel_new.sa_mask = filter_reserved_signals(kernel_new.sa_mask, SIG_SETMASK);
+ // Don't filter signals here; if the caller asked for everything to be blocked, we should obey.
+ kernel_new.sa_mask = kernel_new.sa_mask;
}
return __rt_sigaction(signal,
diff --git a/libc/private/bionic_asm_tls.h b/libc/private/bionic_asm_tls.h
index 0f0873f..92f707a 100644
--- a/libc/private/bionic_asm_tls.h
+++ b/libc/private/bionic_asm_tls.h
@@ -65,6 +65,9 @@
//
// - TLS_SLOT_BIONIC_TLS: Optimizes accesses to bionic_tls by one load versus
// finding it using __get_thread().
+//
+// - TLS_SLOT_APP: Available for use by apps in Android Q and later. (This slot
+// was used for errno in P and earlier.)
#if defined(__arm__) || defined(__aarch64__)
@@ -81,7 +84,7 @@
#define TLS_SLOT_BIONIC_TLS -1
#define TLS_SLOT_DTV 0
#define TLS_SLOT_THREAD_ID 1
-// Slot 2 is free (was historically used for TLS_SLOT_ERRNO)
+#define TLS_SLOT_APP 2 // was historically used for errno
#define TLS_SLOT_OPENGL 3
#define TLS_SLOT_OPENGL_API 4
#define TLS_SLOT_STACK_GUARD 5
@@ -101,7 +104,7 @@
#define TLS_SLOT_SELF 0
#define TLS_SLOT_THREAD_ID 1
-// Slot 2 is free (was historically used for TLS_SLOT_ERRNO)
+#define TLS_SLOT_APP 2 // was historically used for errno
#define TLS_SLOT_OPENGL 3
#define TLS_SLOT_OPENGL_API 4
#define TLS_SLOT_STACK_GUARD 5
diff --git a/linker/linker_block_allocator.cpp b/linker/linker_block_allocator.cpp
index dca944e..27f1e38 100644
--- a/linker/linker_block_allocator.cpp
+++ b/linker/linker_block_allocator.cpp
@@ -33,6 +33,9 @@
#include <sys/prctl.h>
#include <unistd.h>
+static constexpr size_t kAllocateSize = PAGE_SIZE * 100;
+static_assert(kAllocateSize % PAGE_SIZE == 0, "Invalid kAllocateSize.");
+
// the multiplier should be power of 2
static constexpr size_t round_up(size_t size, size_t multiplier) {
return (size + (multiplier - 1)) & ~(multiplier-1);
@@ -40,7 +43,7 @@
struct LinkerBlockAllocatorPage {
LinkerBlockAllocatorPage* next;
- uint8_t bytes[PAGE_SIZE - 16] __attribute__((aligned(16)));
+ uint8_t bytes[kAllocateSize - 16] __attribute__((aligned(16)));
};
struct FreeBlockInfo {
@@ -52,7 +55,8 @@
: block_size_(
round_up(block_size < sizeof(FreeBlockInfo) ? sizeof(FreeBlockInfo) : block_size, 16)),
page_list_(nullptr),
- free_block_list_(nullptr)
+ free_block_list_(nullptr),
+ allocated_(0)
{}
void* LinkerBlockAllocator::alloc() {
@@ -73,6 +77,8 @@
memset(block_info, 0, block_size_);
+ ++allocated_;
+
return block_info;
}
@@ -101,32 +107,37 @@
block_info->num_free_blocks = 1;
free_block_list_ = block_info;
+
+ --allocated_;
+ if (allocated_ == 0) {
+ free_all_pages();
+ }
}
void LinkerBlockAllocator::protect_all(int prot) {
for (LinkerBlockAllocatorPage* page = page_list_; page != nullptr; page = page->next) {
- if (mprotect(page, PAGE_SIZE, prot) == -1) {
+ if (mprotect(page, kAllocateSize, prot) == -1) {
abort();
}
}
}
void LinkerBlockAllocator::create_new_page() {
- static_assert(sizeof(LinkerBlockAllocatorPage) == PAGE_SIZE,
+ static_assert(sizeof(LinkerBlockAllocatorPage) == kAllocateSize,
"Invalid sizeof(LinkerBlockAllocatorPage)");
LinkerBlockAllocatorPage* page = reinterpret_cast<LinkerBlockAllocatorPage*>(
- mmap(nullptr, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0));
+ mmap(nullptr, kAllocateSize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0));
if (page == MAP_FAILED) {
abort(); // oom
}
- prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, page, PAGE_SIZE, "linker_alloc");
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, page, kAllocateSize, "linker_alloc");
FreeBlockInfo* first_block = reinterpret_cast<FreeBlockInfo*>(page->bytes);
first_block->next_block = free_block_list_;
- first_block->num_free_blocks = (PAGE_SIZE - sizeof(LinkerBlockAllocatorPage*))/block_size_;
+ first_block->num_free_blocks = (kAllocateSize - sizeof(LinkerBlockAllocatorPage*))/block_size_;
free_block_list_ = first_block;
@@ -142,7 +153,7 @@
LinkerBlockAllocatorPage* page = page_list_;
while (page != nullptr) {
const uint8_t* page_ptr = reinterpret_cast<const uint8_t*>(page);
- if (block >= (page_ptr + sizeof(page->next)) && block < (page_ptr + PAGE_SIZE)) {
+ if (block >= (page_ptr + sizeof(page->next)) && block < (page_ptr + kAllocateSize)) {
return page;
}
@@ -151,3 +162,18 @@
abort();
}
+
+void LinkerBlockAllocator::free_all_pages() {
+ if (allocated_) {
+ abort();
+ }
+
+ LinkerBlockAllocatorPage* page = page_list_;
+ while (page) {
+ LinkerBlockAllocatorPage* next = page->next;
+ munmap(page, kAllocateSize);
+ page = next;
+ }
+ page_list_ = nullptr;
+ free_block_list_ = nullptr;
+}
diff --git a/linker/linker_block_allocator.h b/linker/linker_block_allocator.h
index bd44fc8..85e6bd9 100644
--- a/linker/linker_block_allocator.h
+++ b/linker/linker_block_allocator.h
@@ -53,10 +53,12 @@
private:
void create_new_page();
LinkerBlockAllocatorPage* find_page(void* block);
+ void free_all_pages();
size_t block_size_;
LinkerBlockAllocatorPage* page_list_;
void* free_block_list_;
+ size_t allocated_;
DISALLOW_COPY_AND_ASSIGN(LinkerBlockAllocator);
};
@@ -73,7 +75,8 @@
* with size 513 this allocator will use 516 (520 for lp64) bytes of data
* where generalized implementation is going to use 1024 sized blocks.
*
- * 2. This allocator does not munmap allocated memory, where LinkerMemoryAllocator does.
+ * 2. Unless all allocated memory is freed, this allocator does not munmap
+ * allocated memory, where LinkerMemoryAllocator does.
*
* 3. This allocator provides mprotect services to the user, where LinkerMemoryAllocator
* always treats it's memory as READ|WRITE.
diff --git a/linker/linker_config.cpp b/linker/linker_config.cpp
index 0e75c85..5a728d3 100644
--- a/linker/linker_config.cpp
+++ b/linker/linker_config.cpp
@@ -41,6 +41,7 @@
#include <limits.h>
#include <stdlib.h>
+#include <unistd.h>
#include <string>
#include <unordered_map>
@@ -238,9 +239,17 @@
// If the path can be resolved, resolve it
char buf[PATH_MAX];
std::string resolved_path;
- if (realpath(value.c_str(), buf)) {
+ if (access(value.c_str(), R_OK) != 0) {
+ if (errno == ENOENT) {
+ // no need to test for non-existing path. skip.
+ continue;
+ }
+ // If not accessible, don't call realpath as it will just cause
+ // SELinux denial spam. Use the path unresolved.
+ resolved_path = value;
+ } else if (realpath(value.c_str(), buf)) {
resolved_path = buf;
- } else if (errno != ENOENT) {
+ } else {
// realpath is expected to fail with EPERM in some situations, so log
// the failure with INFO rather than DL_WARN. e.g. A binary in
// /data/local/tmp may attempt to stat /postinstall. See
@@ -251,9 +260,6 @@
value.c_str(),
strerror(errno));
resolved_path = value;
- } else {
- // ENOENT: no need to test if binary is under the path
- continue;
}
if (file_is_under_dir(binary_realpath, resolved_path)) {
diff --git a/tests/Android.bp b/tests/Android.bp
index 8ac0531..0a45a8e 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -384,7 +384,7 @@
"libdl_test.cpp",
],
static_libs: [
- "libpagemap",
+ "libmeminfo",
"libziparchive",
"libLLVMObject",
"libLLVMBitReader",
@@ -469,7 +469,7 @@
static_libs: [
// The order of these libraries matters, do not shuffle them.
"libbase",
- "libpagemap",
+ "libmeminfo",
"libziparchive",
"libz",
"libutils",
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index 34013a7..c9ecd2e 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -36,7 +36,7 @@
#include <sys/vfs.h>
#include <sys/wait.h>
-#include <pagemap/pagemap.h>
+#include <meminfo/procmeminfo.h>
#include <ziparchive/zip_archive.h>
#include "gtest_globals.h"
@@ -488,33 +488,23 @@
void GetPss(bool shared_relro, const char* lib, const char* relro_file, pid_t pid,
size_t* total_pss) {
- pm_kernel_t* kernel;
- ASSERT_EQ(0, pm_kernel_create(&kernel));
-
- pm_process_t* process;
- ASSERT_EQ(0, pm_process_create(kernel, pid, &process));
-
- pm_map_t** maps;
- size_t num_maps;
- ASSERT_EQ(0, pm_process_maps(process, &maps, &num_maps));
+ android::meminfo::ProcMemInfo proc_mem(pid);
+ const std::vector<android::meminfo::Vma>& maps = proc_mem.Maps();
+ ASSERT_GT(maps.size(), 0UL);
// Calculate total PSS of the library.
*total_pss = 0;
bool saw_relro_file = false;
- for (size_t i = 0; i < num_maps; ++i) {
- if (android::base::EndsWith(maps[i]->name, lib) || strcmp(maps[i]->name, relro_file) == 0) {
- if (strcmp(maps[i]->name, relro_file) == 0) saw_relro_file = true;
+ for (auto& vma : maps) {
+ if (android::base::EndsWith(vma.name, lib) || (vma.name == relro_file)) {
+ if (vma.name == relro_file) {
+ saw_relro_file = true;
+ }
- pm_memusage_t usage;
- ASSERT_EQ(0, pm_map_usage(maps[i], &usage));
- *total_pss += usage.pss;
+ *total_pss += vma.usage.pss;
}
}
- free(maps);
- pm_process_destroy(process);
- pm_kernel_destroy(kernel);
-
if (shared_relro) ASSERT_TRUE(saw_relro_file);
}
diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp
index dd27aef..77b004f 100644
--- a/tests/signal_test.cpp
+++ b/tests/signal_test.cpp
@@ -392,11 +392,19 @@
static uint64_t sigset;
struct sigaction sa = {};
sa.sa_handler = [](int) { sigset = GetSignalMask(); };
+ sa.sa_flags = SA_ONSTACK | SA_NODEFER;
sigfillset(&sa.sa_mask);
sigaction(SIGUSR1, &sa, nullptr);
raise(SIGUSR1);
- ASSERT_NE(0ULL, sigset);
- TestSignalMaskFiltered(sigset);
+
+ // On LP32, struct sigaction::sa_mask is only 32-bits wide.
+ unsigned long expected_sigset = ~0UL;
+
+ // SIGKILL and SIGSTOP are always blocked.
+ expected_sigset &= ~(1UL << (SIGKILL - 1));
+ expected_sigset &= ~(1UL << (SIGSTOP - 1));
+
+ ASSERT_EQ(static_cast<uint64_t>(expected_sigset), sigset);
}
TEST(signal, sigaction64_filter) {
@@ -404,11 +412,18 @@
static uint64_t sigset;
struct sigaction64 sa = {};
sa.sa_handler = [](int) { sigset = GetSignalMask(); };
+ sa.sa_flags = SA_ONSTACK | SA_NODEFER;
sigfillset64(&sa.sa_mask);
sigaction64(SIGUSR1, &sa, nullptr);
raise(SIGUSR1);
- ASSERT_NE(0ULL, sigset);
- TestSignalMaskFiltered(sigset);
+
+ uint64_t expected_sigset = ~0ULL;
+
+ // SIGKILL and SIGSTOP are always blocked.
+ expected_sigset &= ~(1ULL << (SIGKILL - 1));
+ expected_sigset &= ~(1ULL << (SIGSTOP - 1));
+
+ ASSERT_EQ(expected_sigset, sigset);
}
TEST(signal, sigprocmask_setmask_filter) {