Merge "Revert "Partial revert of "libcutils: fs_config.c mark vendor, odm and oem partitions in duplicate" Revert just the wifi hardware part."" into oc-dev
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index 568879e..0b4bbfb 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -29,6 +29,7 @@
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
+#include <android-base/macros.h>
 #include <android-base/parseint.h>
 #include <android-base/properties.h>
 #include <android-base/strings.h>
@@ -149,7 +150,7 @@
   // Returns -1 if we fail to read a response from tombstoned, otherwise the received return code.
   void FinishIntercept(int* result);
 
-  void StartProcess(std::function<void()> function);
+  void StartProcess(std::function<void()> function, std::function<pid_t()> forker = fork);
   void StartCrasher(const std::string& crash_type);
   void FinishCrasher();
   void AssertDeath(int signo);
@@ -195,14 +196,14 @@
   }
 }
 
-void CrasherTest::StartProcess(std::function<void()> function) {
+void CrasherTest::StartProcess(std::function<void()> function, std::function<pid_t()> forker) {
   unique_fd read_pipe;
   unique_fd crasher_read_pipe;
   if (!Pipe(&crasher_read_pipe, &crasher_pipe)) {
     FAIL() << "failed to create pipe: " << strerror(errno);
   }
 
-  crasher_pid = fork();
+  crasher_pid = forker();
   if (crasher_pid == -1) {
     FAIL() << "fork failed: " << strerror(errno);
   } else if (crasher_pid == 0) {
@@ -527,6 +528,37 @@
   ASSERT_MATCH(result, R"(#00 pc [0-9a-f]+\s+ /system/lib)" ARCH_SUFFIX R"(/libc.so \(tgkill)");
 }
 
+TEST_F(CrasherTest, fake_pid) {
+  int intercept_result;
+  unique_fd output_fd;
+
+  // Prime the getpid/gettid caches.
+  UNUSED(getpid());
+  UNUSED(gettid());
+
+  std::function<pid_t()> clone_fn = []() {
+    return syscall(__NR_clone, SIGCHLD, nullptr, nullptr, nullptr, nullptr);
+  };
+  StartProcess(
+      []() {
+        ASSERT_NE(getpid(), syscall(__NR_getpid));
+        ASSERT_NE(gettid(), syscall(__NR_gettid));
+        raise(SIGSEGV);
+      },
+      clone_fn);
+
+  StartIntercept(&output_fd);
+  FinishCrasher();
+  AssertDeath(SIGSEGV);
+  FinishIntercept(&intercept_result);
+
+  ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
+
+  std::string result;
+  ConsumeFd(std::move(output_fd), &result);
+  ASSERT_MATCH(result, R"(#00 pc [0-9a-f]+\s+ /system/lib)" ARCH_SUFFIX R"(/libc.so \(tgkill)");
+}
+
 TEST(crash_dump, zombie) {
   pid_t forkpid = fork();
 
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index b70554f..d58c73d 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -62,6 +62,16 @@
 
 #define CRASH_DUMP_PATH "/system/bin/" CRASH_DUMP_NAME
 
+// Wrappers that directly invoke the respective syscalls, in case the cached values are invalid.
+#pragma GCC poison getpid gettid
+static pid_t __getpid() {
+  return syscall(__NR_getpid);
+}
+
+static pid_t __gettid() {
+  return syscall(__NR_gettid);
+}
+
 class ErrnoRestorer {
  public:
   ErrnoRestorer() : saved_errno_(errno) {
@@ -120,7 +130,7 @@
   }
 
   if (signum == DEBUGGER_SIGNAL) {
-    __libc_format_log(ANDROID_LOG_INFO, "libc", "Requested dump for tid %d (%s)", gettid(),
+    __libc_format_log(ANDROID_LOG_INFO, "libc", "Requested dump for tid %d (%s)", __gettid(),
                       thread_name);
     return;
   }
@@ -173,7 +183,7 @@
   }
 
   __libc_format_log(ANDROID_LOG_FATAL, "libc", "Fatal signal %d (%s)%s%s in tid %d (%s)", signum,
-                    signal_name, code_desc, addr_desc, gettid(), thread_name);
+                    signal_name, code_desc, addr_desc, __gettid(), thread_name);
 }
 
 /*
@@ -331,7 +341,7 @@
   // rt_tgsigqueueinfo(2) to preserve SA_SIGINFO) will cause it to be delivered
   // when our signal handler returns.
   if (crash_dump_started || info->si_signo != DEBUGGER_SIGNAL) {
-    int rc = syscall(SYS_rt_tgsigqueueinfo, getpid(), gettid(), info->si_signo, info);
+    int rc = syscall(SYS_rt_tgsigqueueinfo, __getpid(), __gettid(), info->si_signo, info);
     if (rc != 0) {
       fatal_errno("failed to resend signal during crash");
     }
@@ -356,7 +366,7 @@
     memset(&si, 0, sizeof(si));
     si.si_signo = signal_number;
     si.si_code = SI_USER;
-    si.si_pid = getpid();
+    si.si_pid = __getpid();
     si.si_uid = getuid();
     info = &si;
   } else if (info->si_code >= 0 || info->si_code == SI_TKILL) {
@@ -398,7 +408,7 @@
   debugger_thread_info thread_info = {
     .crash_dump_started = false,
     .pseudothread_tid = -1,
-    .crashing_tid = gettid(),
+    .crashing_tid = __gettid(),
     .signal_number = signal_number,
     .info = info
   };
diff --git a/debuggerd/libdebuggerd/arm/machine.cpp b/debuggerd/libdebuggerd/arm/machine.cpp
index 78c2306..ac833ae 100644
--- a/debuggerd/libdebuggerd/arm/machine.cpp
+++ b/debuggerd/libdebuggerd/arm/machine.cpp
@@ -48,6 +48,21 @@
   }
 }
 
+#define DUMP_GP_REGISTERS(log, reg_prefix)                                             \
+  _LOG(log, logtype::REGISTERS, "    r0 %08x  r1 %08x  r2 %08x  r3 %08x\n",            \
+       static_cast<uint32_t>(reg_prefix##r0), static_cast<uint32_t>(reg_prefix##r1),   \
+       static_cast<uint32_t>(reg_prefix##r2), static_cast<uint32_t>(reg_prefix##r3));  \
+  _LOG(log, logtype::REGISTERS, "    r4 %08x  r5 %08x  r6 %08x  r7 %08x\n",            \
+       static_cast<uint32_t>(reg_prefix##r4), static_cast<uint32_t>(reg_prefix##r5),   \
+       static_cast<uint32_t>(reg_prefix##r6), static_cast<uint32_t>(reg_prefix##r7));  \
+  _LOG(log, logtype::REGISTERS, "    r8 %08x  r9 %08x  sl %08x  fp %08x\n",            \
+       static_cast<uint32_t>(reg_prefix##r8), static_cast<uint32_t>(reg_prefix##r9),   \
+       static_cast<uint32_t>(reg_prefix##r10), static_cast<uint32_t>(reg_prefix##fp)); \
+  _LOG(log, logtype::REGISTERS, "    ip %08x  sp %08x  lr %08x  pc %08x  cpsr %08x\n", \
+       static_cast<uint32_t>(reg_prefix##ip), static_cast<uint32_t>(reg_prefix##sp),   \
+       static_cast<uint32_t>(reg_prefix##lr), static_cast<uint32_t>(reg_prefix##pc),   \
+       static_cast<uint32_t>(reg_prefix##cpsr))
+
 void dump_registers(log_t* log, pid_t tid) {
   pt_regs r;
   if (ptrace(PTRACE_GETREGS, tid, 0, &r)) {
@@ -55,19 +70,7 @@
     return;
   }
 
-  _LOG(log, logtype::REGISTERS, "    r0 %08x  r1 %08x  r2 %08x  r3 %08x\n",
-       static_cast<uint32_t>(r.ARM_r0), static_cast<uint32_t>(r.ARM_r1),
-       static_cast<uint32_t>(r.ARM_r2), static_cast<uint32_t>(r.ARM_r3));
-  _LOG(log, logtype::REGISTERS, "    r4 %08x  r5 %08x  r6 %08x  r7 %08x\n",
-       static_cast<uint32_t>(r.ARM_r4), static_cast<uint32_t>(r.ARM_r5),
-       static_cast<uint32_t>(r.ARM_r6), static_cast<uint32_t>(r.ARM_r7));
-  _LOG(log, logtype::REGISTERS, "    r8 %08x  r9 %08x  sl %08x  fp %08x\n",
-       static_cast<uint32_t>(r.ARM_r8), static_cast<uint32_t>(r.ARM_r9),
-       static_cast<uint32_t>(r.ARM_r10), static_cast<uint32_t>(r.ARM_fp));
-  _LOG(log, logtype::REGISTERS, "    ip %08x  sp %08x  lr %08x  pc %08x  cpsr %08x\n",
-       static_cast<uint32_t>(r.ARM_ip), static_cast<uint32_t>(r.ARM_sp),
-       static_cast<uint32_t>(r.ARM_lr), static_cast<uint32_t>(r.ARM_pc),
-       static_cast<uint32_t>(r.ARM_cpsr));
+  DUMP_GP_REGISTERS(log, r.ARM_);
 
   user_vfp vfp_regs;
   if (ptrace(PTRACE_GETVFPREGS, tid, 0, &vfp_regs)) {
@@ -81,3 +84,7 @@
   }
   _LOG(log, logtype::FP_REGISTERS, "    scr %08lx\n", vfp_regs.fpscr);
 }
+
+void dump_registers(log_t* log, const ucontext_t* uc) {
+  DUMP_GP_REGISTERS(log, uc->uc_mcontext.arm_);
+}
diff --git a/debuggerd/libdebuggerd/arm64/machine.cpp b/debuggerd/libdebuggerd/arm64/machine.cpp
index e7bf79a..fa73c99a 100644
--- a/debuggerd/libdebuggerd/arm64/machine.cpp
+++ b/debuggerd/libdebuggerd/arm64/machine.cpp
@@ -52,6 +52,17 @@
   }
 }
 
+#define DUMP_GP_REGISTERS(log)                                                                   \
+  for (int i = 0; i < 28; i += 4) {                                                              \
+    const char* fmt = "    x%-2d  %016llx  x%-2d  %016llx  x%-2d  %016llx  x%-2d  %016llx\n";    \
+    _LOG(log, logtype::REGISTERS, fmt, i, r.regs[i], i + 1, r.regs[i + 1], i + 2, r.regs[i + 2], \
+         i + 3, r.regs[i + 3]);                                                                  \
+  }                                                                                              \
+  _LOG(log, logtype::REGISTERS, "    x28  %016llx  x29  %016llx  x30  %016llx\n", r.regs[28],    \
+       r.regs[29], r.regs[30]);                                                                  \
+  _LOG(log, logtype::REGISTERS, "    sp   %016llx  pc   %016llx  pstate %016llx\n", r.sp, r.pc,  \
+       r.pstate)
+
 void dump_registers(log_t* log, pid_t tid) {
   struct user_pt_regs r;
   struct iovec io;
@@ -63,20 +74,7 @@
     return;
   }
 
-  for (int i = 0; i < 28; i += 4) {
-    _LOG(log, logtype::REGISTERS,
-         "    x%-2d  %016llx  x%-2d  %016llx  x%-2d  %016llx  x%-2d  %016llx\n",
-         i, r.regs[i],
-         i+1, r.regs[i+1],
-         i+2, r.regs[i+2],
-         i+3, r.regs[i+3]);
-  }
-
-  _LOG(log, logtype::REGISTERS, "    x28  %016llx  x29  %016llx  x30  %016llx\n",
-       r.regs[28], r.regs[29], r.regs[30]);
-
-  _LOG(log, logtype::REGISTERS, "    sp   %016llx  pc   %016llx  pstate %016llx\n",
-       r.sp, r.pc, r.pstate);
+  DUMP_GP_REGISTERS(log);
 
   struct user_fpsimd_state f;
   io.iov_base = &f;
@@ -99,3 +97,8 @@
   }
   _LOG(log, logtype::FP_REGISTERS, "    fpsr %08x  fpcr %08x\n", f.fpsr, f.fpcr);
 }
+
+void dump_registers(log_t* log, const ucontext_t* ucontext) {
+  const mcontext_t& r = ucontext->uc_mcontext;
+  DUMP_GP_REGISTERS(log);
+}
diff --git a/debuggerd/libdebuggerd/include/machine.h b/debuggerd/libdebuggerd/include/machine.h
index e65b147..5e56682 100644
--- a/debuggerd/libdebuggerd/include/machine.h
+++ b/debuggerd/libdebuggerd/include/machine.h
@@ -25,5 +25,6 @@
 
 void dump_memory_and_code(log_t* log, Backtrace* backtrace);
 void dump_registers(log_t* log, pid_t tid);
+void dump_registers(log_t* log, const ucontext_t* uc);
 
 #endif // _DEBUGGERD_MACHINE_H
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index 0c38449..edc7be5 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -470,6 +470,11 @@
   }
 }
 
+// Weak noop implementation, real implementations are in <arch>/machine.cpp.
+__attribute__((weak)) void dump_registers(log_t* log, const ucontext_t*) {
+  _LOG(log, logtype::REGISTERS, "    register dumping unimplemented on this architecture");
+}
+
 static void dump_thread(log_t* log, pid_t pid, pid_t tid, const std::string& process_name,
                         const std::string& thread_name, BacktraceMap* map,
                         uintptr_t abort_msg_address, bool primary_thread) {
@@ -749,11 +754,15 @@
   read_with_default("/proc/self/comm", thread_name, sizeof(thread_name), "<unknown>");
   read_with_default("/proc/self/cmdline", process_name, sizeof(process_name), "<unknown>");
 
+  _LOG(&log, logtype::HEADER, "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n");
+  dump_header_info(&log);
   dump_thread_info(&log, pid, tid, thread_name, process_name);
   dump_signal_info(&log, siginfo);
 
   std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid));
   dump_abort_message(backtrace.get(), &log, abort_msg_address);
+  dump_registers(&log, ucontext);
+
   // TODO: Dump registers from the ucontext.
   if (backtrace->Unwind(0, ucontext)) {
     dump_backtrace_and_stack(backtrace.get(), &log);
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index e3d4f87..e224aec 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -744,23 +744,6 @@
     }
 }
 
-static std::string extract_by_name_prefix(struct fstab* fstab) {
-    // We assume that there's an entry for the /misc mount point in the
-    // fstab file and use that to get the device file by-name prefix.
-    // The device needs not to have an actual /misc partition.
-    // e.g.,
-    //    - /dev/block/platform/soc.0/7824900.sdhci/by-name/misc ->
-    //    - /dev/block/platform/soc.0/7824900.sdhci/by-name/
-    struct fstab_rec* fstab_entry = fs_mgr_get_entry_for_mount_point(fstab, "/misc");
-    if (fstab_entry == nullptr) {
-        LERROR << "/misc mount point not found in fstab";
-        return "";
-    }
-    std::string full_path(fstab_entry->blk_device);
-    size_t end_slash = full_path.find_last_of("/");
-    return full_path.substr(0, end_slash + 1);
-}
-
 // TODO: add ueventd notifiers if they don't exist.
 // This is just doing a wait_for_device for maximum of 1s
 int fs_mgr_test_access(const char *device) {
@@ -850,7 +833,7 @@
 
         if (fstab->recs[i].fs_mgr_flags & MF_AVB) {
             if (!avb_handle) {
-                avb_handle = FsManagerAvbHandle::Open(extract_by_name_prefix(fstab));
+                avb_handle = FsManagerAvbHandle::Open(*fstab);
                 if (!avb_handle) {
                     LERROR << "Failed to open FsManagerAvbHandle";
                     return -1;
@@ -1047,8 +1030,7 @@
         }
 
         int fs_stat = 0;
-        int force_check = do_quota_with_shutdown_check(fstab->recs[i].blk_device,
-                                                       fstab->recs[i].fs_type,
+        int force_check = do_quota_with_shutdown_check(n_blk_device, fstab->recs[i].fs_type,
                                                        &fstab->recs[i], &fs_stat);
 
         if ((fstab->recs[i].fs_mgr_flags & MF_CHECK) || force_check) {
@@ -1062,7 +1044,7 @@
 
         if (fstab->recs[i].fs_mgr_flags & MF_AVB) {
             if (!avb_handle) {
-                avb_handle = FsManagerAvbHandle::Open(extract_by_name_prefix(fstab));
+                avb_handle = FsManagerAvbHandle::Open(*fstab);
                 if (!avb_handle) {
                     LERROR << "Failed to open FsManagerAvbHandle";
                     return -1;
@@ -1367,7 +1349,8 @@
 
         std::string mount_point;
         if (system_root && !strcmp(fstab->recs[i].mount_point, "/")) {
-            mount_point = "system";
+            // In AVB, the dm device name is vroot instead of system.
+            mount_point = fs_mgr_is_avb(&fstab->recs[i]) ? "vroot" : "system";
         } else {
             mount_point = basename(fstab->recs[i].mount_point);
         }
@@ -1386,6 +1369,10 @@
 
         status = &buffer[io->data_start + sizeof(struct dm_target_spec)];
 
+        // To be consistent in vboot 1.0 and vboot 2.0 (AVB), change the mount_point
+        // back to 'system' for the callback. So it has property [partition.system.verified]
+        // instead of [partition.vroot.verified].
+        if (mount_point == "vroot") mount_point = "system";
         if (*status == 'C' || *status == 'V') {
             callback(&fstab->recs[i], mount_point.c_str(), mode, *status);
         }
diff --git a/fs_mgr/fs_mgr_avb.cpp b/fs_mgr/fs_mgr_avb.cpp
index 83bf8a7..36883e6 100644
--- a/fs_mgr/fs_mgr_avb.cpp
+++ b/fs_mgr/fs_mgr_avb.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include "fs_mgr_avb.h"
+
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
@@ -38,9 +40,8 @@
 #include <utils/Compat.h>
 
 #include "fs_mgr.h"
-#include "fs_mgr_avb.h"
-#include "fs_mgr_avb_ops.h"
 #include "fs_mgr_priv.h"
+#include "fs_mgr_priv_avb_ops.h"
 #include "fs_mgr_priv_dm_ioctl.h"
 #include "fs_mgr_priv_sha.h"
 
@@ -457,12 +458,21 @@
     return true;
 }
 
-FsManagerAvbUniquePtr FsManagerAvbHandle::Open(const std::string& device_file_by_name_prefix) {
-    if (device_file_by_name_prefix.empty()) {
-        LERROR << "Missing device file by-name prefix";
+FsManagerAvbUniquePtr FsManagerAvbHandle::Open(const fstab& fstab) {
+    FsManagerAvbOps avb_ops(fstab);
+    return DoOpen(&avb_ops);
+}
+
+FsManagerAvbUniquePtr FsManagerAvbHandle::Open(ByNameSymlinkMap&& by_name_symlink_map) {
+    if (by_name_symlink_map.empty()) {
+        LERROR << "Empty by_name_symlink_map when opening FsManagerAvbHandle";
         return nullptr;
     }
+    FsManagerAvbOps avb_ops(std::move(by_name_symlink_map));
+    return DoOpen(&avb_ops);
+}
 
+FsManagerAvbUniquePtr FsManagerAvbHandle::DoOpen(FsManagerAvbOps* avb_ops) {
     // Gets the expected hash value of vbmeta images from kernel cmdline.
     std::unique_ptr<FsManagerAvbVerifier> avb_verifier = FsManagerAvbVerifier::Create();
     if (!avb_verifier) {
@@ -476,20 +486,40 @@
         return nullptr;
     }
 
-    FsManagerAvbOps avb_ops(device_file_by_name_prefix);
-    AvbSlotVerifyResult verify_result = avb_ops.AvbSlotVerify(
+    AvbSlotVerifyResult verify_result = avb_ops->AvbSlotVerify(
         fs_mgr_get_slot_suffix(), avb_verifier->IsDeviceUnlocked(), &avb_handle->avb_slot_data_);
 
     // Only allow two verify results:
     //   - AVB_SLOT_VERIFY_RESULT_OK.
     //   - AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION (for UNLOCKED state).
-    if (verify_result == AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION) {
-        if (!avb_verifier->IsDeviceUnlocked()) {
-            LERROR << "ERROR_VERIFICATION isn't allowed";
+    //     If the device is UNLOCKED, i.e., |allow_verification_error| is true for
+    //     AvbSlotVerify(), then the following return values are all non-fatal:
+    //       * AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION
+    //       * AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED
+    //       * AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX
+    //     The latter two results were checked by bootloader prior to start fs_mgr so
+    //     we just need to handle the first result here. See *dummy* operations in
+    //     FsManagerAvbOps and the comments in external/avb/libavb/avb_slot_verify.h
+    //     for more details.
+    switch (verify_result) {
+        case AVB_SLOT_VERIFY_RESULT_OK:
+            avb_handle->status_ = kFsManagerAvbHandleSuccess;
+            break;
+        case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
+            if (!avb_verifier->IsDeviceUnlocked()) {
+                LERROR << "ERROR_VERIFICATION isn't allowed when the device is LOCKED";
+                return nullptr;
+            }
+            avb_handle->status_ = kFsManagerAvbHandleErrorVerification;
+            break;
+        default:
+            LERROR << "avb_slot_verify failed, result: " << verify_result;
             return nullptr;
-        }
-    } else if (verify_result != AVB_SLOT_VERIFY_RESULT_OK) {
-        LERROR << "avb_slot_verify failed, result: " << verify_result;
+    }
+
+    // Verifies vbmeta images against the digest passed from bootloader.
+    if (!avb_verifier->VerifyVbmetaImages(*avb_handle->avb_slot_data_)) {
+        LERROR << "VerifyVbmetaImages failed";
         return nullptr;
     }
 
@@ -497,30 +527,20 @@
     avb_handle->avb_version_ =
         android::base::StringPrintf("%d.%d", AVB_VERSION_MAJOR, AVB_VERSION_MINOR);
 
-    // Verifies vbmeta images against the digest passed from bootloader.
-    if (!avb_verifier->VerifyVbmetaImages(*avb_handle->avb_slot_data_)) {
-        LERROR << "VerifyVbmetaImages failed";
-        return nullptr;
-    } else {
-        // Checks whether FLAGS_HASHTREE_DISABLED is set.
-        AvbVBMetaImageHeader vbmeta_header;
-        avb_vbmeta_image_header_to_host_byte_order(
-            (AvbVBMetaImageHeader*)avb_handle->avb_slot_data_->vbmeta_images[0].vbmeta_data,
-            &vbmeta_header);
+    // Checks whether FLAGS_HASHTREE_DISABLED is set.
+    AvbVBMetaImageHeader vbmeta_header;
+    avb_vbmeta_image_header_to_host_byte_order(
+        (AvbVBMetaImageHeader*)avb_handle->avb_slot_data_->vbmeta_images[0].vbmeta_data,
+        &vbmeta_header);
 
-        bool hashtree_disabled =
-            ((AvbVBMetaImageFlags)vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED);
-        if (hashtree_disabled) {
-            avb_handle->status_ = kFsManagerAvbHandleHashtreeDisabled;
-            return avb_handle;
-        }
+    bool hashtree_disabled =
+        ((AvbVBMetaImageFlags)vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED);
+    if (hashtree_disabled) {
+        avb_handle->status_ = kFsManagerAvbHandleHashtreeDisabled;
     }
 
-    if (verify_result == AVB_SLOT_VERIFY_RESULT_OK) {
-        avb_handle->status_ = kFsManagerAvbHandleSuccess;
-        return avb_handle;
-    }
-    return nullptr;
+    LINFO << "Returning avb_handle with status: " << avb_handle->status_;
+    return avb_handle;
 }
 
 bool FsManagerAvbHandle::SetUpAvb(struct fstab_rec* fstab_entry, bool wait_for_verity_dev) {
@@ -528,11 +548,12 @@
     if (!avb_slot_data_ || avb_slot_data_->num_vbmeta_images < 1) {
         return false;
     }
+
+    if (status_ == kFsManagerAvbHandleUninitialized) return false;
     if (status_ == kFsManagerAvbHandleHashtreeDisabled) {
         LINFO << "AVB HASHTREE disabled on:" << fstab_entry->mount_point;
         return true;
     }
-    if (status_ != kFsManagerAvbHandleSuccess) return false;
 
     std::string partition_name(basename(fstab_entry->mount_point));
     if (!avb_validate_utf8((const uint8_t*)partition_name.c_str(), partition_name.length())) {
diff --git a/fs_mgr/fs_mgr_avb_ops.cpp b/fs_mgr/fs_mgr_avb_ops.cpp
index 981e9fc..47df861 100644
--- a/fs_mgr/fs_mgr_avb_ops.cpp
+++ b/fs_mgr/fs_mgr_avb_ops.cpp
@@ -22,6 +22,8 @@
  * SOFTWARE.
  */
 
+#include "fs_mgr_priv_avb_ops.h"
+
 #include <errno.h>
 #include <fcntl.h>
 #include <stdlib.h>
@@ -36,7 +38,6 @@
 #include <utils/Compat.h>
 
 #include "fs_mgr.h"
-#include "fs_mgr_avb_ops.h"
 #include "fs_mgr_priv.h"
 
 static AvbIOResult read_from_partition(AvbOps* ops, const char* partition, int64_t offset,
@@ -88,11 +89,7 @@
     return AVB_IO_RESULT_OK;
 }
 
-FsManagerAvbOps::FsManagerAvbOps(const std::string& device_file_by_name_prefix)
-    : device_file_by_name_prefix_(device_file_by_name_prefix) {
-    if (device_file_by_name_prefix_.back() != '/') {
-        device_file_by_name_prefix_ += '/';
-    }
+void FsManagerAvbOps::InitializeAvbOps() {
     // We only need to provide the implementation of read_from_partition()
     // operation since that's all what is being used by the avb_slot_verify().
     // Other I/O operations are only required in bootloader but not in
@@ -107,13 +104,31 @@
     avb_ops_.user_data = this;
 }
 
+FsManagerAvbOps::FsManagerAvbOps(std::map<std::string, std::string>&& by_name_symlink_map)
+    : by_name_symlink_map_(std::move(by_name_symlink_map)) {
+    InitializeAvbOps();
+}
+
+FsManagerAvbOps::FsManagerAvbOps(const fstab& fstab) {
+    // Constructs the by-name symlink map for each fstab record.
+    // /dev/block/platform/soc.0/7824900.sdhci/by-name/system_a =>
+    // by_name_symlink_map_["system_a"] = "/dev/block/platform/soc.0/7824900.sdhci/by-name/system_a"
+    for (int i = 0; i < fstab.num_entries; i++) {
+        std::string partition_name = basename(fstab.recs[i].blk_device);
+        by_name_symlink_map_[partition_name] = fstab.recs[i].blk_device;
+    }
+    InitializeAvbOps();
+}
+
 AvbIOResult FsManagerAvbOps::ReadFromPartition(const char* partition, int64_t offset,
                                                size_t num_bytes, void* buffer,
                                                size_t* out_num_read) {
-    // Appends |partition| to the device_file_by_name_prefix_, e.g.,
-    //    - /dev/block/platform/soc.0/7824900.sdhci/by-name/ ->
-    //    - /dev/block/platform/soc.0/7824900.sdhci/by-name/system_a
-    std::string path = device_file_by_name_prefix_ + partition;
+    const auto iter = by_name_symlink_map_.find(partition);
+    if (iter == by_name_symlink_map_.end()) {
+        LERROR << "by-name symlink not found for partition: '" << partition << "'";
+        return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
+    }
+    std::string path = iter->second;
 
     // Ensures the device path (a symlink created by init) is ready to
     // access. fs_mgr_test_access() will test a few iterations if the
@@ -124,7 +139,7 @@
 
     android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));
     if (fd < 0) {
-        PERROR << "Failed to open " << path.c_str();
+        PERROR << "Failed to open " << path;
         return AVB_IO_RESULT_ERROR_IO;
     }
 
@@ -148,8 +163,7 @@
     // for EOF).
     ssize_t num_read = TEMP_FAILURE_RETRY(pread64(fd, buffer, num_bytes, offset));
     if (num_read < 0 || (size_t)num_read != num_bytes) {
-        PERROR << "Failed to read " << num_bytes << " bytes from " << path.c_str() << " offset "
-               << offset;
+        PERROR << "Failed to read " << num_bytes << " bytes from " << path << " offset " << offset;
         return AVB_IO_RESULT_ERROR_IO;
     }
 
diff --git a/fs_mgr/fs_mgr_avb_ops.h b/fs_mgr/fs_mgr_priv_avb_ops.h
similarity index 87%
rename from fs_mgr/fs_mgr_avb_ops.h
rename to fs_mgr/fs_mgr_priv_avb_ops.h
index ec4a8c9..a6b52e4 100644
--- a/fs_mgr/fs_mgr_avb_ops.h
+++ b/fs_mgr/fs_mgr_priv_avb_ops.h
@@ -22,8 +22,11 @@
  * SOFTWARE.
  */
 
-#ifndef __CORE_FS_MGR_AVB_OPS_H
-#define __CORE_FS_MGR_AVB_OPS_H
+#ifndef __CORE_FS_MGR_PRIV_AVB_OPS_H
+#define __CORE_FS_MGR_PRIV_AVB_OPS_H
+
+#include <map>
+#include <string>
 
 #include <libavb/libavb.h>
 
@@ -43,7 +46,8 @@
 //
 class FsManagerAvbOps {
   public:
-    FsManagerAvbOps(const std::string& device_file_by_name_prefix);
+    FsManagerAvbOps(const fstab& fstab);
+    FsManagerAvbOps(std::map<std::string, std::string>&& by_name_symlink_map);
 
     static FsManagerAvbOps* GetInstanceFromAvbOps(AvbOps* ops) {
         return reinterpret_cast<FsManagerAvbOps*>(ops->user_data);
@@ -56,7 +60,9 @@
                                       AvbSlotVerifyData** out_data);
 
   private:
+    void InitializeAvbOps();
+
     AvbOps avb_ops_;
-    std::string device_file_by_name_prefix_;
+    std::map<std::string, std::string> by_name_symlink_map_;
 };
-#endif /* __CORE_FS_MGR_AVB_OPS_H */
+#endif /* __CORE_FS_MGR_PRIV_AVB_OPS_H */
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp
index 0bf173b..5fa10bc 100644
--- a/fs_mgr/fs_mgr_verity.cpp
+++ b/fs_mgr/fs_mgr_verity.cpp
@@ -663,7 +663,7 @@
     /* use the kernel parameter if set */
     std::string veritymode;
     if (fs_mgr_get_boot_config("veritymode", &veritymode)) {
-        if (veritymode.compare("enforcing")) {
+        if (veritymode == "enforcing") {
             *mode = VERITY_MODE_DEFAULT;
         }
         return 0;
diff --git a/fs_mgr/include/fs_mgr_avb.h b/fs_mgr/include/fs_mgr_avb.h
index a66ff42..bbafe1a 100644
--- a/fs_mgr/include/fs_mgr_avb.h
+++ b/fs_mgr/include/fs_mgr_avb.h
@@ -17,6 +17,7 @@
 #ifndef __CORE_FS_MGR_AVB_H
 #define __CORE_FS_MGR_AVB_H
 
+#include <map>
 #include <memory>
 #include <string>
 
@@ -25,14 +26,19 @@
 #include "fs_mgr.h"
 
 enum FsManagerAvbHandleStatus {
+    kFsManagerAvbHandleUninitialized = -1,
     kFsManagerAvbHandleSuccess = 0,
     kFsManagerAvbHandleHashtreeDisabled = 1,
-    kFsManagerAvbHandleFail = 2,
+    kFsManagerAvbHandleErrorVerification = 2,
 };
 
+class FsManagerAvbOps;
+
 class FsManagerAvbHandle;
 using FsManagerAvbUniquePtr = std::unique_ptr<FsManagerAvbHandle>;
 
+using ByNameSymlinkMap = std::map<std::string, std::string>;
+
 // Provides a factory method to return a unique_ptr pointing to itself and the
 // SetUpAvb() function to extract dm-verity parameters from AVB metadata to
 // load verity table into kernel through ioctl.
@@ -48,6 +54,13 @@
     // A typical usage will be:
     //   - FsManagerAvbUniquePtr handle = FsManagerAvbHandle::Open();
     //
+    // There are two overloaded Open() functions with a single parameter.
+    // The argument can be a ByNameSymlinkMap describing the mapping from partition
+    // name to by-name symlink, or a fstab file to which the ByNameSymlinkMap is
+    // constructed from. e.g.,
+    //   - /dev/block/platform/soc.0/7824900.sdhci/by-name/system_a ->
+    //   - ByNameSymlinkMap["system_a"] = "/dev/block/platform/soc.0/7824900.sdhci/by-name/system_a"
+    //
     // Possible return values:
     //   - nullptr: any error when reading and verifying the metadata,
     //     e.g., I/O error, digest value mismatch, size mismatch, etc.
@@ -60,7 +73,8 @@
     //   - a valid unique_ptr with status kFsMgrAvbHandleSuccess: the metadata
     //     is verified and can be trusted.
     //
-    static FsManagerAvbUniquePtr Open(const std::string& device_file_by_name_prefix);
+    static FsManagerAvbUniquePtr Open(const fstab& fstab);
+    static FsManagerAvbUniquePtr Open(ByNameSymlinkMap&& by_name_symlink_map);
 
     // Sets up dm-verity on the given fstab entry.
     // The 'wait_for_verity_dev' parameter makes this function wait for the
@@ -87,10 +101,10 @@
         }
     };
 
-  protected:
-    FsManagerAvbHandle() : avb_slot_data_(nullptr), status_(kFsManagerAvbHandleFail) {}
-
   private:
+    FsManagerAvbHandle() : avb_slot_data_(nullptr), status_(kFsManagerAvbHandleUninitialized) {}
+    static FsManagerAvbUniquePtr DoOpen(FsManagerAvbOps* avb_ops);
+
     AvbSlotVerifyData* avb_slot_data_;
     FsManagerAvbHandleStatus status_;
     std::string avb_version_;
diff --git a/init/devices.cpp b/init/devices.cpp
index 405f92e..39571ac 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -526,8 +526,7 @@
     return NULL;
 }
 
-static char **get_block_device_symlinks(struct uevent *uevent)
-{
+char** get_block_device_symlinks(struct uevent* uevent) {
     const char *device;
     struct platform_node *pdev;
     const char *slash;
diff --git a/init/devices.h b/init/devices.h
index 26a064b..3f2cde4 100644
--- a/init/devices.h
+++ b/init/devices.h
@@ -55,4 +55,6 @@
                          unsigned short wildcard);
 int get_device_fd();
 
+char** get_block_device_symlinks(struct uevent* uevent);
+
 #endif	/* _INIT_DEVICES_H */
diff --git a/init/init.cpp b/init/init.cpp
index 84e4f84..bb6355a 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -19,6 +19,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
+#include <keyutils.h>
 #include <libgen.h>
 #include <paths.h>
 #include <signal.h>
@@ -1028,6 +1029,11 @@
     InitKernelLogging(argv);
     LOG(INFO) << "init second stage started!";
 
+    // Set up a session keyring that all processes will have access to. It
+    // will hold things like FBE encryption keys. No process should override
+    // its session keyring.
+    keyctl(KEYCTL_GET_KEYRING_ID, KEY_SPEC_SESSION_KEYRING, 1);
+
     // Indicate that booting is in progress to background fw loaders, etc.
     close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));
 
diff --git a/init/init_first_stage.cpp b/init/init_first_stage.cpp
index e6b2f24..bcc8d1b 100644
--- a/init/init_first_stage.cpp
+++ b/init/init_first_stage.cpp
@@ -47,18 +47,22 @@
     bool InitDevices();
 
   protected:
-    void InitRequiredDevices(std::set<std::string>* devices_partition_names);
+    void InitRequiredDevices();
     void InitVerityDevice(const std::string& verity_device);
     bool MountPartitions();
 
-    virtual bool GetRequiredDevices(std::set<std::string>* out_devices_partition_names,
-                                    bool* out_need_dm_verity) = 0;
+    virtual coldboot_action_t ColdbootCallback(uevent* uevent);
+
+    // Pure virtual functions.
+    virtual bool GetRequiredDevices() = 0;
     virtual bool SetUpDmVerity(fstab_rec* fstab_rec) = 0;
 
+    bool need_dm_verity_;
     // Device tree fstab entries.
     std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> device_tree_fstab_;
     // Eligible first stage mount candidates, only allow /system, /vendor and/or /odm.
     std::vector<fstab_rec*> mount_fstab_recs_;
+    std::set<std::string> required_devices_partition_names_;
 };
 
 class FirstStageMountVBootV1 : public FirstStageMount {
@@ -67,27 +71,26 @@
     ~FirstStageMountVBootV1() override = default;
 
   protected:
-    bool GetRequiredDevices(std::set<std::string>* out_devices_partition_names,
-                            bool* out_need_dm_verity) override;
+    bool GetRequiredDevices() override;
     bool SetUpDmVerity(fstab_rec* fstab_rec) override;
 };
 
 class FirstStageMountVBootV2 : public FirstStageMount {
   public:
+    friend void SetInitAvbVersionInRecovery();
+
     FirstStageMountVBootV2();
     ~FirstStageMountVBootV2() override = default;
 
-    const std::string& by_name_prefix() const { return device_tree_by_name_prefix_; }
-
   protected:
-    bool GetRequiredDevices(std::set<std::string>* out_devices_partition_names,
-                            bool* out_need_dm_verity) override;
+    coldboot_action_t ColdbootCallback(uevent* uevent) override;
+    bool GetRequiredDevices() override;
     bool SetUpDmVerity(fstab_rec* fstab_rec) override;
     bool InitAvbHandle();
 
     std::string device_tree_vbmeta_parts_;
-    std::string device_tree_by_name_prefix_;
     FsManagerAvbUniquePtr avb_handle_;
+    ByNameSymlinkMap by_name_symlink_map_;
 };
 
 // Static Functions
@@ -102,7 +105,8 @@
 
 // Class Definitions
 // -----------------
-FirstStageMount::FirstStageMount() : device_tree_fstab_(fs_mgr_read_fstab_dt(), fs_mgr_free_fstab) {
+FirstStageMount::FirstStageMount()
+    : need_dm_verity_(false), device_tree_fstab_(fs_mgr_read_fstab_dt(), fs_mgr_free_fstab) {
     if (!device_tree_fstab_) {
         LOG(ERROR) << "Failed to read fstab from device tree";
         return;
@@ -136,69 +140,71 @@
 }
 
 bool FirstStageMount::InitDevices() {
-    bool need_dm_verity;
-    std::set<std::string> devices_partition_names;
+    if (!GetRequiredDevices()) return false;
 
-    // The partition name in devices_partition_names MUST have A/B suffix when A/B is used.
-    if (!GetRequiredDevices(&devices_partition_names, &need_dm_verity)) return false;
+    InitRequiredDevices();
 
-    if (need_dm_verity) {
-        device_init("/sys/devices/virtual/misc/device-mapper",
-                    [&](uevent* uevent) -> coldboot_action_t { return COLDBOOT_STOP; });
-    }
-
-    bool success = false;
-    InitRequiredDevices(&devices_partition_names);
-
-    // InitRequiredDevices() will remove found partitions from devices_partition_names.
+    // InitRequiredDevices() will remove found partitions from required_devices_partition_names_.
     // So if it isn't empty here, it means some partitions are not found.
-    if (!devices_partition_names.empty()) {
+    if (!required_devices_partition_names_.empty()) {
         LOG(ERROR) << __FUNCTION__ << "(): partition(s) not found: "
-                   << android::base::Join(devices_partition_names, ", ");
+                   << android::base::Join(required_devices_partition_names_, ", ");
+        return false;
     } else {
-        success = true;
+        return true;
     }
-
-    device_close();
-    return success;
 }
 
-// Creates devices with uevent->partition_name matching one in the in/out
-// devices_partition_names. Found partitions will then be removed from the
-// devices_partition_names for the caller to check which devices are NOT created.
-void FirstStageMount::InitRequiredDevices(std::set<std::string>* devices_partition_names) {
-    if (devices_partition_names->empty()) {
+// Creates devices with uevent->partition_name matching one in the member variable
+// required_devices_partition_names_. Found partitions will then be removed from it
+// for the subsequent member function to check which devices are NOT created.
+void FirstStageMount::InitRequiredDevices() {
+    if (required_devices_partition_names_.empty()) {
         return;
     }
-    device_init(nullptr, [=](uevent* uevent) -> coldboot_action_t {
-        // We need platform devices to create symlinks.
-        if (!strncmp(uevent->subsystem, "platform", 8)) {
-            return COLDBOOT_CREATE;
-        }
 
-        // Ignores everything that is not a block device.
-        if (strncmp(uevent->subsystem, "block", 5)) {
-            return COLDBOOT_CONTINUE;
-        }
+    if (need_dm_verity_) {
+        const std::string dm_path = "/devices/virtual/misc/device-mapper";
+        device_init(("/sys" + dm_path).c_str(), [&dm_path](uevent* uevent) -> coldboot_action_t {
+            if (uevent->path && uevent->path == dm_path) return COLDBOOT_STOP;
+            return COLDBOOT_CONTINUE;  // dm_path not found, continue to find it.
+        });
+    }
 
-        if (uevent->partition_name) {
-            // Matches partition name to create device nodes.
-            // Both devices_partition_names and uevent->partition_name have A/B
-            // suffix when A/B is used.
-            auto iter = devices_partition_names->find(uevent->partition_name);
-            if (iter != devices_partition_names->end()) {
-                LOG(VERBOSE) << __FUNCTION__ << "(): found partition: " << *iter;
-                devices_partition_names->erase(iter);
-                if (devices_partition_names->empty()) {
-                    return COLDBOOT_STOP;  // Found all partitions, stop coldboot.
-                } else {
-                    return COLDBOOT_CREATE;  // Creates this device and continue to find others.
-                }
+    device_init(nullptr,
+                [this](uevent* uevent) -> coldboot_action_t { return ColdbootCallback(uevent); });
+
+    device_close();
+}
+
+coldboot_action_t FirstStageMount::ColdbootCallback(uevent* uevent) {
+    // We need platform devices to create symlinks.
+    if (!strncmp(uevent->subsystem, "platform", 8)) {
+        return COLDBOOT_CREATE;
+    }
+
+    // Ignores everything that is not a block device.
+    if (strncmp(uevent->subsystem, "block", 5)) {
+        return COLDBOOT_CONTINUE;
+    }
+
+    if (uevent->partition_name) {
+        // Matches partition name to create device nodes.
+        // Both required_devices_partition_names_ and uevent->partition_name have A/B
+        // suffix when A/B is used.
+        auto iter = required_devices_partition_names_.find(uevent->partition_name);
+        if (iter != required_devices_partition_names_.end()) {
+            LOG(VERBOSE) << __FUNCTION__ << "(): found partition: " << *iter;
+            required_devices_partition_names_.erase(iter);
+            if (required_devices_partition_names_.empty()) {
+                return COLDBOOT_STOP;  // Found all partitions, stop coldboot.
+            } else {
+                return COLDBOOT_CREATE;  // Creates this device and continue to find others.
             }
         }
-        // Not found a partition or find an unneeded partition, continue to find others.
-        return COLDBOOT_CONTINUE;
-    });
+    }
+    // Not found a partition or find an unneeded partition, continue to find others.
+    return COLDBOOT_CONTINUE;
 }
 
 // Creates "/dev/block/dm-XX" for dm-verity by running coldboot on /sys/block/dm-XX.
@@ -207,7 +213,7 @@
     const std::string syspath = "/sys/block/" + device_name;
 
     device_init(syspath.c_str(), [&](uevent* uevent) -> coldboot_action_t {
-        if (uevent->device_name && device_name == uevent->device_name) {
+        if (uevent->device_name && uevent->device_name == device_name) {
             LOG(VERBOSE) << "Creating dm-verity device : " << verity_device;
             return COLDBOOT_STOP;
         }
@@ -230,10 +236,9 @@
     return true;
 }
 
-bool FirstStageMountVBootV1::GetRequiredDevices(std::set<std::string>* out_devices_partition_names,
-                                                bool* out_need_dm_verity) {
+bool FirstStageMountVBootV1::GetRequiredDevices() {
     std::string verity_loc_device;
-    *out_need_dm_verity = false;
+    need_dm_verity_ = false;
 
     for (auto fstab_rec : mount_fstab_recs_) {
         // Don't allow verifyatboot in the first stage.
@@ -243,7 +248,7 @@
         }
         // Checks for verified partitions.
         if (fs_mgr_is_verified(fstab_rec)) {
-            *out_need_dm_verity = true;
+            need_dm_verity_ = true;
         }
         // Checks if verity metadata is on a separate partition. Note that it is
         // not partition specific, so there must be only one additional partition
@@ -262,11 +267,11 @@
     // Includes the partition names of fstab records and verity_loc_device (if any).
     // Notes that fstab_rec->blk_device has A/B suffix updated by fs_mgr when A/B is used.
     for (auto fstab_rec : mount_fstab_recs_) {
-        out_devices_partition_names->emplace(basename(fstab_rec->blk_device));
+        required_devices_partition_names_.emplace(basename(fstab_rec->blk_device));
     }
 
     if (!verity_loc_device.empty()) {
-        out_devices_partition_names->emplace(basename(verity_loc_device.c_str()));
+        required_devices_partition_names_.emplace(basename(verity_loc_device.c_str()));
     }
 
     return true;
@@ -289,15 +294,13 @@
 }
 
 // FirstStageMountVBootV2 constructor.
-// Gets the vbmeta configurations from device tree.
-// Specifically, the 'parts' and 'by_name_prefix' below.
+// Gets the vbmeta partitions from device tree.
 // /{
 //     firmware {
 //         android {
 //             vbmeta {
 //                 compatible = "android,vbmeta";
 //                 parts = "vbmeta,boot,system,vendor"
-//                 by_name_prefix = "/dev/block/platform/soc.0/f9824900.sdhci/by-name/"
 //             };
 //         };
 //     };
@@ -307,31 +310,24 @@
         PLOG(ERROR) << "Failed to read vbmeta/parts from device tree";
         return;
     }
-
-    // TODO: removes by_name_prefix to allow partitions on different block devices.
-    if (!read_android_dt_file("vbmeta/by_name_prefix", &device_tree_by_name_prefix_)) {
-        PLOG(ERROR) << "Failed to read vbmeta/by_name_prefix from dt";
-        return;
-    }
 }
 
-bool FirstStageMountVBootV2::GetRequiredDevices(std::set<std::string>* out_devices_partition_names,
-                                                bool* out_need_dm_verity) {
-    *out_need_dm_verity = false;
+bool FirstStageMountVBootV2::GetRequiredDevices() {
+    need_dm_verity_ = false;
 
     // fstab_rec->blk_device has A/B suffix.
     for (auto fstab_rec : mount_fstab_recs_) {
         if (fs_mgr_is_avb(fstab_rec)) {
-            *out_need_dm_verity = true;
+            need_dm_verity_ = true;
         }
-        out_devices_partition_names->emplace(basename(fstab_rec->blk_device));
+        required_devices_partition_names_.emplace(basename(fstab_rec->blk_device));
     }
 
     // libavb verifies AVB metadata on all verified partitions at once.
     // e.g., The device_tree_vbmeta_parts_ will be "vbmeta,boot,system,vendor"
     // for libavb to verify metadata, even if there is only /vendor in the
     // above mount_fstab_recs_.
-    if (*out_need_dm_verity) {
+    if (need_dm_verity_) {
         if (device_tree_vbmeta_parts_.empty()) {
             LOG(ERROR) << "Missing vbmeta parts in device tree";
             return false;
@@ -339,16 +335,45 @@
         std::vector<std::string> partitions = android::base::Split(device_tree_vbmeta_parts_, ",");
         std::string ab_suffix = fs_mgr_get_slot_suffix();
         for (const auto& partition : partitions) {
-            // out_devices_partition_names is of type std::set so it's not an issue to emplace
-            // a partition twice. e.g., /vendor might be in both places:
+            // required_devices_partition_names_ is of type std::set so it's not an issue
+            // to emplace a partition twice. e.g., /vendor might be in both places:
             //   - device_tree_vbmeta_parts_ = "vbmeta,boot,system,vendor"
             //   - mount_fstab_recs_: /vendor_a
-            out_devices_partition_names->emplace(partition + ab_suffix);
+            required_devices_partition_names_.emplace(partition + ab_suffix);
         }
     }
     return true;
 }
 
+coldboot_action_t FirstStageMountVBootV2::ColdbootCallback(uevent* uevent) {
+    // Invokes the parent function to see if any desired partition has been found.
+    // If yes, record the by-name symlink for creating FsManagerAvbHandle later.
+    coldboot_action_t parent_callback_ret = FirstStageMount::ColdbootCallback(uevent);
+
+    // Skips the uevent if the parent function returns COLDBOOT_CONTINUE (meaning
+    // that the uevent was skipped) or there is no uevent->partition_name to
+    // create the by-name symlink.
+    if (parent_callback_ret != COLDBOOT_CONTINUE && uevent->partition_name) {
+        // get_block_device_symlinks() will return three symlinks at most, depending on
+        // the content of uevent. by-name symlink will be at [0] if uevent->partition_name
+        // is not empty. e.g.,
+        //   - /dev/block/platform/soc.0/f9824900.sdhci/by-name/modem
+        //   - /dev/block/platform/soc.0/f9824900.sdhci/by-num/p1
+        //   - /dev/block/platform/soc.0/f9824900.sdhci/mmcblk0p1
+        char** links = get_block_device_symlinks(uevent);
+        if (links && links[0]) {
+            auto[it, inserted] = by_name_symlink_map_.emplace(uevent->partition_name, links[0]);
+            if (!inserted) {
+                LOG(ERROR) << "Partition '" << uevent->partition_name
+                           << "' already existed in the by-name symlink map with a value of '"
+                           << it->second << "', new value '" << links[0] << "' will be ignored.";
+            }
+        }
+    }
+
+    return parent_callback_ret;
+}
+
 bool FirstStageMountVBootV2::SetUpDmVerity(fstab_rec* fstab_rec) {
     if (fs_mgr_is_avb(fstab_rec)) {
         if (!InitAvbHandle()) return false;
@@ -368,7 +393,14 @@
 bool FirstStageMountVBootV2::InitAvbHandle() {
     if (avb_handle_) return true;  // Returns true if the handle is already initialized.
 
-    avb_handle_ = FsManagerAvbHandle::Open(device_tree_by_name_prefix_);
+    if (by_name_symlink_map_.empty()) {
+        LOG(ERROR) << "by_name_symlink_map_ is empty";
+        return false;
+    }
+
+    avb_handle_ = FsManagerAvbHandle::Open(std::move(by_name_symlink_map_));
+    by_name_symlink_map_.clear();  // Removes all elements after the above std::move().
+
     if (!avb_handle_) {
         PLOG(ERROR) << "Failed to open FsManagerAvbHandle";
         return false;
@@ -424,7 +456,8 @@
         return;
     }
 
-    FsManagerAvbUniquePtr avb_handle = FsManagerAvbHandle::Open(avb_first_mount.by_name_prefix());
+    FsManagerAvbUniquePtr avb_handle =
+        FsManagerAvbHandle::Open(std::move(avb_first_mount.by_name_symlink_map_));
     if (!avb_handle) {
         PLOG(ERROR) << "Failed to open FsManagerAvbHandle for INIT_AVB_VERSION";
         return;
diff --git a/init/keyutils.h b/init/keyutils.h
new file mode 100644
index 0000000..de01beb
--- /dev/null
+++ b/init/keyutils.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Miniature version of a header-only keyutils.h (no library required) */
+
+#ifndef _INIT_KEYUTILS_H_
+#define _INIT_KEYUTILS_H_
+
+#ifndef KEYUTILS_H /* walk away if the _real_ one exists */
+
+#include <linux/keyctl.h>
+#include <stdarg.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+static inline long keyctl(int cmd, ...) {
+    va_list va;
+    unsigned long arg2, arg3, arg4, arg5;
+
+    va_start(va, cmd);
+    arg2 = va_arg(va, unsigned long);
+    arg3 = va_arg(va, unsigned long);
+    arg4 = va_arg(va, unsigned long);
+    arg5 = va_arg(va, unsigned long);
+    va_end(va);
+    return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5);
+}
+
+#endif
+
+#endif
diff --git a/init/reboot.cpp b/init/reboot.cpp
index c997519..aac1b5c 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -331,7 +331,7 @@
     // keep debugging tools until non critical ones are all gone.
     const std::set<std::string> kill_after_apps{"tombstoned", "logd", "adbd"};
     // watchdogd is a vendor specific component but should be alive to complete shutdown safely.
-    const std::set<std::string> to_starts{"watchdogd", "vold"};
+    const std::set<std::string> to_starts{"watchdogd", "vold", "ueventd"};
     ServiceManager::GetInstance().ForEachService([&kill_after_apps, &to_starts](Service* s) {
         if (kill_after_apps.count(s->name())) {
             s->SetShutdownCritical();
diff --git a/libappfuse/FuseBuffer.cc b/libappfuse/FuseBuffer.cc
index b42a049..653e96b 100644
--- a/libappfuse/FuseBuffer.cc
+++ b/libappfuse/FuseBuffer.cc
@@ -119,7 +119,12 @@
                     return ResultOrAgain::kFailure;
             }
         }
-        CHECK(static_cast<uint32_t>(result) == header.len);
+
+        if (static_cast<unsigned int>(result) != header.len) {
+            LOG(ERROR) << "Written bytes " << result << " is different from length in header "
+                       << header.len;
+            return ResultOrAgain::kFailure;
+        }
         return ResultOrAgain::kSuccess;
     }
 }
@@ -141,8 +146,8 @@
     }
 
     constexpr int kMaxMessageSize = sizeof(FuseBuffer);
-    if (setsockopt(fds[0], SOL_SOCKET, SO_SNDBUF, &kMaxMessageSize, sizeof(int)) != 0 ||
-        setsockopt(fds[1], SOL_SOCKET, SO_SNDBUF, &kMaxMessageSize, sizeof(int)) != 0) {
+    if (setsockopt(fds[0], SOL_SOCKET, SO_SNDBUFFORCE, &kMaxMessageSize, sizeof(int)) != 0 ||
+        setsockopt(fds[1], SOL_SOCKET, SO_SNDBUFFORCE, &kMaxMessageSize, sizeof(int)) != 0) {
         PLOG(ERROR) << "Failed to update buffer size for socket";
         return false;
     }
diff --git a/libcrypto_utils/Android.bp b/libcrypto_utils/Android.bp
index f2560e6..4a5f2a7 100644
--- a/libcrypto_utils/Android.bp
+++ b/libcrypto_utils/Android.bp
@@ -16,6 +16,7 @@
 
 cc_library {
     name: "libcrypto_utils",
+    vendor_available: true,
     host_supported: true,
     srcs: [
         "android_pubkey.c",
diff --git a/libnativeloader/include/nativeloader/dlext_namespaces.h b/libnativeloader/include/nativeloader/dlext_namespaces.h
index ac64f71..9121277 100644
--- a/libnativeloader/include/nativeloader/dlext_namespaces.h
+++ b/libnativeloader/include/nativeloader/dlext_namespaces.h
@@ -55,6 +55,12 @@
    * permitted_path from the caller's namespace.
    */
   ANDROID_NAMESPACE_TYPE_SHARED = 2,
+
+  /* This flag instructs linker to enable grey-list workaround for the namespace.
+   * See http://b/26394120 for details.
+   */
+  ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED = 0x08000000,
+
   ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED = ANDROID_NAMESPACE_TYPE_SHARED |
                                            ANDROID_NAMESPACE_TYPE_ISOLATED,
 };
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index ebd6d4b..100c31d 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -99,6 +99,7 @@
   LibraryNamespaces() : initialized_(false) { }
 
   bool Create(JNIEnv* env,
+              uint32_t target_sdk_version,
               jobject class_loader,
               bool is_shared,
               jstring java_library_path,
@@ -141,6 +142,10 @@
       namespace_type |= ANDROID_NAMESPACE_TYPE_SHARED;
     }
 
+    if (target_sdk_version < 24) {
+      namespace_type |= ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED;
+    }
+
     NativeLoaderNamespace parent_ns;
     bool found_parent_namespace = FindParentNamespaceByClassLoader(env, class_loader, &parent_ns);
 
@@ -397,12 +402,12 @@
                                    jstring library_path,
                                    jstring permitted_path) {
 #if defined(__ANDROID__)
-  UNUSED(target_sdk_version);
   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
 
   std::string error_msg;
   NativeLoaderNamespace ns;
   bool success = g_namespaces->Create(env,
+                                      target_sdk_version,
                                       class_loader,
                                       is_shared,
                                       library_path,
@@ -439,7 +444,14 @@
   if (!g_namespaces->FindNamespaceByClassLoader(env, class_loader, &ns)) {
     // This is the case where the classloader was not created by ApplicationLoaders
     // In this case we create an isolated not-shared namespace for it.
-    if (!g_namespaces->Create(env, class_loader, false, library_path, nullptr, &ns, error_msg)) {
+    if (!g_namespaces->Create(env,
+                              target_sdk_version,
+                              class_loader,
+                              false,
+                              library_path,
+                              nullptr,
+                              &ns,
+                              error_msg)) {
       return nullptr;
     }
   }
diff --git a/libutils/include/utils/Flattenable.h b/libutils/include/utils/Flattenable.h
index 22b811a..070c710 100644
--- a/libutils/include/utils/Flattenable.h
+++ b/libutils/include/utils/Flattenable.h
@@ -189,11 +189,11 @@
     }
     inline status_t flatten(void* buffer, size_t size) const {
         if (size < sizeof(T)) return NO_MEMORY;
-        *reinterpret_cast<T*>(buffer) = *static_cast<T const*>(this);
+        memcpy(buffer, static_cast<T const*>(this), sizeof(T));
         return NO_ERROR;
     }
     inline status_t unflatten(void const* buffer, size_t) {
-        *static_cast<T*>(this) = *reinterpret_cast<T const*>(buffer);
+        memcpy(static_cast<T*>(this), buffer, sizeof(T));
         return NO_ERROR;
     }
 };
diff --git a/libvndksupport/Android.bp b/libvndksupport/Android.bp
new file mode 100644
index 0000000..ab9e26f
--- /dev/null
+++ b/libvndksupport/Android.bp
@@ -0,0 +1,15 @@
+subdirs = ["tests"]
+
+cc_library_shared {
+    name: "libvndksupport",
+    srcs: ["linker.c"],
+    local_include_dirs: ["include/vndksupport"],
+    export_include_dirs: ["include"],
+    shared_libs: ["liblog"],
+}
+
+llndk_library {
+    name: "libvndksupport",
+    symbol_file: "libvndksupport.map.txt",
+    export_include_dirs: ["include"],
+}
diff --git a/libvndksupport/include/vndksupport/linker.h b/libvndksupport/include/vndksupport/linker.h
new file mode 100644
index 0000000..f509564
--- /dev/null
+++ b/libvndksupport/include/vndksupport/linker.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef VNDKSUPPORT_LINKER_H_
+#define VNDKSUPPORT_LINKER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void* android_load_sphal_library(const char* name, int flag);
+
+int android_unload_sphal_library(void* handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // VNDKSUPPORT_LINKER_H_
diff --git a/libvndksupport/libvndksupport.map.txt b/libvndksupport/libvndksupport.map.txt
new file mode 100644
index 0000000..16e38da
--- /dev/null
+++ b/libvndksupport/libvndksupport.map.txt
@@ -0,0 +1,7 @@
+LIBVNDKSUPPORT {
+  global:
+    android_load_sphal_library; # vndk
+    android_unload_sphal_library; # vndk
+  local:
+    *;
+};
diff --git a/libvndksupport/linker.c b/libvndksupport/linker.c
new file mode 100644
index 0000000..12aa3be
--- /dev/null
+++ b/libvndksupport/linker.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "linker.h"
+
+#include <android/dlext.h>
+#include <dlfcn.h>
+
+#define LOG_TAG "vndksupport"
+#include <log/log.h>
+
+extern struct android_namespace_t* android_get_exported_namespace(const char*);
+
+void* android_load_sphal_library(const char* name, int flag) {
+    struct android_namespace_t* sphal_namespace = android_get_exported_namespace("sphal");
+    if (sphal_namespace != NULL) {
+        const android_dlextinfo dlextinfo = {
+            .flags = ANDROID_DLEXT_USE_NAMESPACE, .library_namespace = sphal_namespace,
+        };
+        void* handle = android_dlopen_ext(name, flag, &dlextinfo);
+        if (handle) {
+            return handle;
+        } else {
+            ALOGW(
+                "Could not load %s from sphal namespace: %s. "
+                "Falling back to loading it from the current namespace,",
+                name, dlerror());
+        }
+    } else {
+        ALOGI(
+            "sphal namespace is not configured for this process. "
+            "Loading %s from the current namespace instead.",
+            name);
+    }
+    return dlopen(name, flag);
+}
+
+int android_unload_sphal_library(void* handle) { return dlclose(handle); }
diff --git a/libvndksupport/tests/Android.bp b/libvndksupport/tests/Android.bp
new file mode 100644
index 0000000..3587cf8
--- /dev/null
+++ b/libvndksupport/tests/Android.bp
@@ -0,0 +1,26 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_test {
+    name: "libvndksupport-tests",
+    srcs: [
+        "linker_test.cpp",
+    ],
+
+    host_supported: false,
+    shared_libs: [
+        "libvndksupport",
+        "libbase",
+    ]
+}
diff --git a/libvndksupport/tests/linker_test.cpp b/libvndksupport/tests/linker_test.cpp
new file mode 100644
index 0000000..7ce27d4
--- /dev/null
+++ b/libvndksupport/tests/linker_test.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <gtest/gtest.h>
+
+#include <android-base/strings.h>
+#include <dirent.h>
+#include <dlfcn.h>
+#include <vndksupport/linker.h>
+#include <string>
+
+// Since the test executable will be in /data and ld.config.txt does not
+// configure sphal namespace for executables in /data, the call to
+// android_load_sphal_library will always fallback to the plain dlopen from the
+// default namespace.
+
+// Let's use libEGL_<chipset>.so as a SP-HAL in test
+static std::string find_sphal_lib() {
+    const char* path =
+#if defined(__LP64__)
+        "/vendor/lib64/egl";
+#else
+        "/vendor/lib/egl";
+#endif
+    std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path), closedir);
+
+    dirent* dp;
+    while ((dp = readdir(dir.get())) != nullptr) {
+        std::string name = dp->d_name;
+        if (android::base::StartsWith(name, "libEGL_")) {
+            return std::string(path) + "/" + name;
+        }
+    }
+    return "";
+}
+
+TEST(linker, load_existing_lib) {
+    std::string name = find_sphal_lib();
+    ASSERT_NE("", name);
+    void* handle = android_load_sphal_library(name.c_str(), RTLD_NOW | RTLD_LOCAL);
+    ASSERT_NE(nullptr, handle);
+    android_unload_sphal_library(handle);
+}
+
+TEST(linker, load_nonexisting_lib) {
+    void* handle = android_load_sphal_library("libNeverUseThisName.so", RTLD_NOW | RTLD_LOCAL);
+    ASSERT_EQ(nullptr, handle);
+}
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index 21179fb..5961411 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -60,11 +60,7 @@
 namespace.sphal.links = default,vndk,rs
 
 # WARNING: only NDK libs can be listed here.
-# However, this is commented out because some SP-HALs (gralloc.msm8996.so, etc)
-# are currently using some non-stable libs such as libbacktrace.so. We will get back
-# to this list once the dependencies are fixed.
-#namespace.sphal.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libsync.so
-namespace.sphal.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libbacktrace.so:libGLESv1_CM.so:libGLESv2.so
+namespace.sphal.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libGLESv1_CM.so:libGLESv2.so:libvndksupport.so
 
 # WARNING: only VNDK-SP libs can be listed here. DO NOT EDIT this line.
 namespace.sphal.link.vndk.shared_libs = android.hardware.renderscript@1.0.so:android.hardware.graphics.allocator@2.0.so:android.hardware.graphics.mapper@2.0.so:android.hardware.graphics.common@1.0.so:android.hidl.base@1.0.so:libhwbinder.so:libbase.so:libcutils.so:libhardware.so:libhidlbase.so:libhidltransport.so:libutils.so:libc++.so
@@ -81,11 +77,14 @@
 # to load the compiled *.so file and libmediandk.so can be used here.
 ###############################################################################
 namespace.rs.isolated = true
-namespace.rs.search.paths = /system/${LIB}/vndk-sp:/vendor/${LIB}
+namespace.rs.search.paths = /vendor/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/vendor/${LIB}
 namespace.rs.permitted.paths = /vendor/${LIB}:/data
 
+namespace.rs.asan.search.paths = /data/asan/vendor/${LIB}/vndk-sp:/vendor/${LIB}/vndk-sp:/data/asan/system/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/data/asan/vendor/${LIB}:/vendor/${LIB}
+namespace.rs.asan.permitted.paths = /data/asan/vendor/${LIB}:/vendor/${LIB}:/data
+
 namespace.rs.links = default,vndk
-namespace.rs.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libbacktrace.so:libGLESv1_CM.so:libGLESv2.so:libmediandk.so:libui.so
+namespace.rs.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libGLESv1_CM.so:libGLESv2.so:libmediandk.so:libui.so:libvndksupport.so
 namespace.rs.link.vndk.shared_libs = android.hardware.renderscript@1.0.so:android.hardware.graphics.allocator@2.0.so:android.hardware.graphics.mapper@2.0.so:android.hardware.graphics.common@1.0.so:android.hidl.base@1.0.so:libhwbinder.so:libbase.so:libcutils.so:libhardware.so:libhidlbase.so:libhidltransport.so:libutils.so:libc++.so
 
 ###############################################################################
@@ -94,27 +93,21 @@
 # This namespace is exclusively for vndk-sp libs.
 ###############################################################################
 namespace.vndk.isolated = true
-namespace.vndk.search.paths = /system/${LIB}/vndk-sp:/vendor/${LIB}
+namespace.vndk.search.paths = /vendor/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/vendor/${LIB}
 namespace.vndk.permitted.paths = /vendor/${LIB}/hw:/vendor/${LIB}/egl
 
-namespace.vndk.asan.search.paths = /data/asan/vendor/${LIB}/vndk-sp:/vendor/${LIB}/vndk-sp:/data/asan/vendor/${LIB}:/vendor/${LIB}
+namespace.vndk.asan.search.paths = /data/asan/vendor/${LIB}/vndk-sp:/vendor/${LIB}/vndk-sp:/data/asan/system/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/data/asan/vendor/${LIB}:/vendor/${LIB}
 namespace.vndk.asan.permitted.paths = /data/asan/vendor/${LIB}/hw:/vendor/${LIB}/hw:/data/asan/vendor/${LIB}/egl:/vendor/${LIB}/egl
 
 # When these NDK libs are required inside this namespace, then it is redirected
 # to the default namespace. This is possible since their ABI is stable across
 # Android releases.
 namespace.vndk.links = default
-
-# WARNING: only NDK libs can be listed here.
-# However, this is commented out because some SP-HALs (gralloc.msm8996.so, etc)
-# are currently using some non-stable libs such as libbacktrace.so. We will get back
-# to this list once the dependencies are fixed.
-#namespace.vndk.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libsync.so
-namespace.vndk.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libbacktrace.so
+namespace.vndk.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libvndksupport.so
 
 
 [vendor]
 namespace.default.isolated = false
-namespace.default.search.paths = /vendor/${LIB}:/vendor/${LIB}/vndk-sp:/system/${LIB}
+namespace.default.search.paths = /vendor/${LIB}:/vendor/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/system/${LIB}
 
-namespace.default.asan.search.paths = /data/asan/vendor/${LIB}:/vendor/${LIB}:/data/asan/vendor/${LIB}/vndk-sp:/vendor/${LIB}/vndk-sp:/data/asan/system/${LIB}:/system/${LIB}
+namespace.default.asan.search.paths = /data/asan/vendor/${LIB}:/vendor/${LIB}:/data/asan/vendor/${LIB}/vndk-sp:/vendor/${LIB}/vndk-sp:/data/asan/system/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/data/asan/system/${LIB}:/system/${LIB}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index def686b..944aae7 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -657,12 +657,6 @@
 on property:sys.boot_completed=1
     bootchart stop
 
-on property:sys.boot_completed=1 && property:ro.build.type=user
-    write /proc/sys/kernel/modules_disabled 1
-
-on property:sys.boot_completed=1 && property:ro.build.type=userdebug
-    write /proc/sys/kernel/modules_disabled 1
-
 # system server cannot write to /proc/sys files,
 # and chown/chmod does not work for /proc/sys/ entries.
 # So proxy writes through init.