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) {