Merge "[fs_mgr] Use shared libutils for remount"
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index 59643d9..68c9aca 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -1889,3 +1889,178 @@
   ConsumeFd(std::move(output_fd), &result);
   ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
 }
+
+static std::string format_pointer(uintptr_t ptr) {
+#if defined(__LP64__)
+  return android::base::StringPrintf("%08x'%08x", static_cast<uint32_t>(ptr >> 32),
+                                     static_cast<uint32_t>(ptr & 0xffffffff));
+#else
+  return android::base::StringPrintf("%08x", static_cast<uint32_t>(ptr & 0xffffffff));
+#endif
+}
+
+static std::string format_pointer(void* ptr) {
+  return format_pointer(reinterpret_cast<uintptr_t>(ptr));
+}
+
+static std::string format_full_pointer(uintptr_t ptr) {
+#if defined(__LP64__)
+  return android::base::StringPrintf("%016" PRIx64, ptr);
+#else
+  return android::base::StringPrintf("%08x", ptr);
+#endif
+}
+
+static std::string format_full_pointer(void* ptr) {
+  return format_full_pointer(reinterpret_cast<uintptr_t>(ptr));
+}
+
+__attribute__((__noinline__)) int crash_call(uintptr_t ptr) {
+  int* crash_ptr = reinterpret_cast<int*>(ptr);
+  *crash_ptr = 1;
+  return *crash_ptr;
+}
+
+// Verify that a fault address before the first map is properly handled.
+TEST_F(CrasherTest, fault_address_before_first_map) {
+  StartProcess([]() {
+    ASSERT_EQ(0, crash_call(0x1024));
+    _exit(0);
+  });
+
+  unique_fd output_fd;
+  StartIntercept(&output_fd);
+  FinishCrasher();
+  AssertDeath(SIGSEGV);
+
+  int intercept_result;
+  FinishIntercept(&intercept_result);
+  ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
+
+  std::string result;
+  ConsumeFd(std::move(output_fd), &result);
+  ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x1024)");
+
+  ASSERT_MATCH(result, R"(\nmemory map \(.*\):\n)");
+
+  std::string match_str = android::base::StringPrintf(
+      R"(memory map .*:\n--->Fault address falls at %s before any mapped regions\n    )",
+      format_pointer(0x1024).c_str());
+  ASSERT_MATCH(result, match_str);
+}
+
+// Verify that a fault address after the last map is properly handled.
+TEST_F(CrasherTest, fault_address_after_last_map) {
+  uintptr_t crash_uptr = untag_address(UINTPTR_MAX - 15);
+  StartProcess([crash_uptr]() {
+    ASSERT_EQ(0, crash_call(crash_uptr));
+    _exit(0);
+  });
+
+  unique_fd output_fd;
+  StartIntercept(&output_fd);
+  FinishCrasher();
+  AssertDeath(SIGSEGV);
+
+  int intercept_result;
+  FinishIntercept(&intercept_result);
+  ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
+
+  std::string result;
+  ConsumeFd(std::move(output_fd), &result);
+
+  std::string match_str = R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr )";
+  match_str += android::base::StringPrintf("0x%" PRIxPTR, crash_uptr);
+  ASSERT_MATCH(result, match_str);
+
+  ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->)\n)");
+
+  // Assumes that the open files section comes after the map section.
+  // If that assumption changes, the regex below needs to change.
+  match_str = android::base::StringPrintf(
+      R"(\n--->Fault address falls at %s after any mapped regions\n\nopen files:)",
+      format_pointer(crash_uptr).c_str());
+  ASSERT_MATCH(result, match_str);
+}
+
+// Verify that a fault address between maps is properly handled.
+TEST_F(CrasherTest, fault_address_between_maps) {
+  // Create a map before the fork so it will be present in the child.
+  void* start_ptr =
+      mmap(nullptr, 3 * getpagesize(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+  ASSERT_NE(MAP_FAILED, start_ptr);
+  // Unmap the page in the middle.
+  void* middle_ptr =
+      reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(start_ptr) + getpagesize());
+  ASSERT_EQ(0, munmap(middle_ptr, getpagesize()));
+
+  StartProcess([middle_ptr]() {
+    ASSERT_EQ(0, crash_call(reinterpret_cast<uintptr_t>(middle_ptr)));
+    _exit(0);
+  });
+
+  // Unmap the two maps.
+  ASSERT_EQ(0, munmap(start_ptr, getpagesize()));
+  void* end_ptr =
+      reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(start_ptr) + 2 * getpagesize());
+  ASSERT_EQ(0, munmap(end_ptr, getpagesize()));
+
+  unique_fd output_fd;
+  StartIntercept(&output_fd);
+  FinishCrasher();
+  AssertDeath(SIGSEGV);
+
+  int intercept_result;
+  FinishIntercept(&intercept_result);
+  ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
+
+  std::string result;
+  ConsumeFd(std::move(output_fd), &result);
+
+  std::string match_str = R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr )";
+  match_str += android::base::StringPrintf("%p", middle_ptr);
+  ASSERT_MATCH(result, match_str);
+
+  ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->)\n)");
+
+  match_str = android::base::StringPrintf(
+      R"(    %s.*\n--->Fault address falls at %s between mapped regions\n    %s)",
+      format_pointer(start_ptr).c_str(), format_pointer(middle_ptr).c_str(),
+      format_pointer(end_ptr).c_str());
+  ASSERT_MATCH(result, match_str);
+}
+
+// Verify that a fault address happens in the correct map.
+TEST_F(CrasherTest, fault_address_in_map) {
+  // Create a map before the fork so it will be present in the child.
+  void* ptr = mmap(nullptr, getpagesize(), 0, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+  ASSERT_NE(MAP_FAILED, ptr);
+
+  StartProcess([ptr]() {
+    ASSERT_EQ(0, crash_call(reinterpret_cast<uintptr_t>(ptr)));
+    _exit(0);
+  });
+
+  ASSERT_EQ(0, munmap(ptr, getpagesize()));
+
+  unique_fd output_fd;
+  StartIntercept(&output_fd);
+  FinishCrasher();
+  AssertDeath(SIGSEGV);
+
+  int intercept_result;
+  FinishIntercept(&intercept_result);
+  ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
+
+  std::string result;
+  ConsumeFd(std::move(output_fd), &result);
+
+  std::string match_str = R"(signal 11 \(SIGSEGV\), code 2 \(SEGV_ACCERR\), fault addr )";
+  match_str += android::base::StringPrintf("%p", ptr);
+  ASSERT_MATCH(result, match_str);
+
+  ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->)\n)");
+
+  match_str = android::base::StringPrintf(R"(\n--->%s.*\n)", format_pointer(ptr).c_str());
+  ASSERT_MATCH(result, match_str);
+}
diff --git a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
index 053299a..681b963 100644
--- a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
@@ -362,8 +362,13 @@
   print_thread_memory_dump(callback, tombstone, thread);
 
   CBS("");
-  CBS("memory map (%d %s):", tombstone.memory_mappings().size(),
-      tombstone.memory_mappings().size() == 1 ? "entry" : "entries");
+
+  // No memory maps to print.
+  if (tombstone.memory_mappings().empty()) {
+    CBS("No memory maps found");
+    return;
+  }
+
   int word_size = pointer_width(tombstone);
   const auto format_pointer = [word_size](uint64_t ptr) -> std::string {
     if (word_size == 8) {
@@ -375,8 +380,41 @@
     return StringPrintf("%0*" PRIx64, word_size * 2, ptr);
   };
 
+  std::string memory_map_header =
+      StringPrintf("memory map (%d %s):", tombstone.memory_mappings().size(),
+                   tombstone.memory_mappings().size() == 1 ? "entry" : "entries");
+
+  bool has_fault_address = signal_info.has_fault_address();
+  uint64_t fault_address = untag_address(signal_info.fault_address());
+  bool preamble_printed = false;
+  bool printed_fault_address_marker = false;
   for (const auto& map : tombstone.memory_mappings()) {
+    if (!preamble_printed) {
+      preamble_printed = true;
+      if (has_fault_address) {
+        if (fault_address < map.begin_address()) {
+          memory_map_header +=
+              StringPrintf("\n--->Fault address falls at %s before any mapped regions",
+                           format_pointer(fault_address).c_str());
+          printed_fault_address_marker = true;
+        } else {
+          memory_map_header += " (fault address prefixed with --->)";
+        }
+      }
+      CBS("%s", memory_map_header.c_str());
+    }
+
     std::string line = "    ";
+    if (has_fault_address && !printed_fault_address_marker) {
+      if (fault_address < map.begin_address()) {
+        printed_fault_address_marker = true;
+        CBS("--->Fault address falls at %s between mapped regions",
+            format_pointer(fault_address).c_str());
+      } else if (fault_address >= map.begin_address() && fault_address < map.end_address()) {
+        printed_fault_address_marker = true;
+        line = "--->";
+      }
+    }
     StringAppendF(&line, "%s-%s", format_pointer(map.begin_address()).c_str(),
                   format_pointer(map.end_address() - 1).c_str());
     StringAppendF(&line, " %s%s%s", map.read() ? "r" : "-", map.write() ? "w" : "-",
@@ -398,6 +436,11 @@
 
     CBS("%s", line.c_str());
   }
+
+  if (has_fault_address && !printed_fault_address_marker) {
+    CBS("--->Fault address falls at %s after any mapped regions",
+        format_pointer(fault_address).c_str());
+  }
 }
 
 void print_logs(CallbackType callback, const Tombstone& tombstone, int tail) {
diff --git a/debuggerd/tombstoned/tombstoned.cpp b/debuggerd/tombstoned/tombstoned.cpp
index 05d8050..02ded1e 100644
--- a/debuggerd/tombstoned/tombstoned.cpp
+++ b/debuggerd/tombstoned/tombstoned.cpp
@@ -448,8 +448,10 @@
     return;
   }
 
-  if (crash->output.text.fd == -1) {
-    LOG(WARNING) << "missing output fd";
+  if (crash->output.text.fd < 0) {
+    if (crash->output.text.fd == -1) {
+      LOG(WARNING) << "skipping tombstone file creation due to intercept";
+    }
     return;
   }
 
diff --git a/fastboot/fs.cpp b/fastboot/fs.cpp
index 458a7a1..d268a50 100644
--- a/fastboot/fs.cpp
+++ b/fastboot/fs.cpp
@@ -143,6 +143,13 @@
         mke2fs_args.push_back("512");
     }
 
+    if (fsOptions & (1 << FS_OPT_CASEFOLD)) {
+        mke2fs_args.push_back("-O");
+        mke2fs_args.push_back("casefold");
+        mke2fs_args.push_back("-E");
+        mke2fs_args.push_back("encoding=utf8");
+    }
+
     mke2fs_args.push_back(fileName);
 
     std::string size_str = std::to_string(partSize / block_size);
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index e60da31..d9a0cd9 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -399,6 +399,7 @@
     FRIEND_TEST(SnapshotTest, MergeFailureCode);
     FRIEND_TEST(SnapshotTest, NoMergeBeforeReboot);
     FRIEND_TEST(SnapshotTest, UpdateBootControlHal);
+    FRIEND_TEST(SnapshotUpdateTest, AddPartition);
     FRIEND_TEST(SnapshotUpdateTest, DaemonTransition);
     FRIEND_TEST(SnapshotUpdateTest, DataWipeAfterRollback);
     FRIEND_TEST(SnapshotUpdateTest, DataWipeRollbackInRecovery);
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index c3db32e..52324ba 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -2087,14 +2087,18 @@
     if (live_snapshot_status->compression_enabled()) {
         // Get the source device (eg the view of the partition from before it was resized).
         std::string source_device_path;
-        if (!MapSourceDevice(lock, params.GetPartitionName(), remaining_time,
-                             &source_device_path)) {
-            LOG(ERROR) << "Could not map source device for: " << cow_name;
-            return false;
-        }
+        if (live_snapshot_status->old_partition_size() > 0) {
+            if (!MapSourceDevice(lock, params.GetPartitionName(), remaining_time,
+                                 &source_device_path)) {
+                LOG(ERROR) << "Could not map source device for: " << cow_name;
+                return false;
+            }
 
-        auto source_device = GetSourceDeviceName(params.GetPartitionName());
-        created_devices.EmplaceBack<AutoUnmapDevice>(&dm, source_device);
+            auto source_device = GetSourceDeviceName(params.GetPartitionName());
+            created_devices.EmplaceBack<AutoUnmapDevice>(&dm, source_device);
+        } else {
+            source_device_path = base_path;
+        }
 
         if (!WaitForDevice(source_device_path, remaining_time)) {
             return false;
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index b2203fe..057e5b19a 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -963,7 +963,7 @@
     }
 
     AssertionResult UnmapAll() {
-        for (const auto& name : {"sys", "vnd", "prd"}) {
+        for (const auto& name : {"sys", "vnd", "prd", "dlkm"}) {
             if (!dm_.DeleteDeviceIfExists(name + "_a"s)) {
                 return AssertionFailure() << "Cannot unmap " << name << "_a";
             }
@@ -2073,6 +2073,70 @@
     ASSERT_LT(res.required_size(), 40_MiB);
 }
 
+TEST_F(SnapshotUpdateTest, AddPartition) {
+    // OTA client blindly unmaps all partitions that are possibly mapped.
+    for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
+        ASSERT_TRUE(sm->UnmapUpdateSnapshot(name));
+    }
+
+    group_->add_partition_names("dlkm");
+
+    auto dlkm = manifest_.add_partitions();
+    dlkm->set_partition_name("dlkm");
+    dlkm->set_estimate_cow_size(2_MiB);
+    SetSize(dlkm, 3_MiB);
+
+    // Grow all partitions. Set |prd| large enough that |sys| and |vnd|'s COWs
+    // fit in super, but not |prd|.
+    constexpr uint64_t partition_size = 3788_KiB;
+    SetSize(sys_, partition_size);
+    SetSize(vnd_, partition_size);
+    SetSize(prd_, partition_size);
+    SetSize(dlkm, partition_size);
+
+    AddOperationForPartitions({sys_, vnd_, prd_, dlkm});
+
+    // Execute the update.
+    ASSERT_TRUE(sm->BeginUpdate());
+    ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
+
+    // Write some data to target partitions.
+    for (const auto& name : {"sys_b", "vnd_b", "prd_b", "dlkm_b"}) {
+        ASSERT_TRUE(WriteSnapshotAndHash(name));
+    }
+
+    // Assert that source partitions aren't affected.
+    for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
+        ASSERT_TRUE(IsPartitionUnchanged(name));
+    }
+
+    ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
+
+    // Simulate shutting down the device.
+    ASSERT_TRUE(UnmapAll());
+
+    // After reboot, init does first stage mount.
+    auto init = NewManagerForFirstStageMount("_b");
+    ASSERT_NE(init, nullptr);
+    ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
+    ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
+
+    // Check that the target partitions have the same content.
+    for (const auto& name : {"sys_b", "vnd_b", "prd_b", "dlkm_b"}) {
+        ASSERT_TRUE(IsPartitionUnchanged(name));
+    }
+
+    // Initiate the merge and wait for it to be completed.
+    ASSERT_TRUE(init->InitiateMerge());
+    ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
+
+    // Check that the target partitions have the same content after the merge.
+    for (const auto& name : {"sys_b", "vnd_b", "prd_b", "dlkm_b"}) {
+        ASSERT_TRUE(IsPartitionUnchanged(name))
+                << "Content of " << name << " changes after the merge";
+    }
+}
+
 class AutoKill final {
   public:
     explicit AutoKill(pid_t pid) : pid_(pid) {}
diff --git a/init/TEST_MAPPING b/init/TEST_MAPPING
index 905d41e..03b9eaa 100644
--- a/init/TEST_MAPPING
+++ b/init/TEST_MAPPING
@@ -5,6 +5,9 @@
     },
     {
       "name": "init_kill_services_test"
+    },
+    {
+      "name": "MicrodroidHostTestCases"
     }
   ]
 }
diff --git a/init/first_stage_console.cpp b/init/first_stage_console.cpp
index e2ea0ab..67cac19 100644
--- a/init/first_stage_console.cpp
+++ b/init/first_stage_console.cpp
@@ -85,7 +85,10 @@
 
 void StartConsole(const std::string& cmdline) {
     bool console = KernelConsolePresent(cmdline);
+    // Use a simple sigchld handler -- first_stage_console doesn't need to track or log zombies
+    const struct sigaction chld_act { .sa_handler = SIG_DFL, .sa_flags = SA_NOCLDWAIT };
 
+    sigaction(SIGCHLD, &chld_act, nullptr);
     pid_t pid = fork();
     if (pid != 0) {
         int status;
diff --git a/libstats/pull_rust/Android.bp b/libstats/pull_rust/Android.bp
index 2a89e29..f07e32b 100644
--- a/libstats/pull_rust/Android.bp
+++ b/libstats/pull_rust/Android.bp
@@ -57,3 +57,13 @@
         "libstatspull_bindgen",
     ],
 }
+
+rust_test {
+    name: "libstatspull_bindgen_test",
+    srcs: [":libstatspull_bindgen"],
+    crate_name: "statspull_bindgen_test",
+    test_suites: ["general-tests"],
+    auto_gen_config: true,
+    clippy_lints: "none",
+    lints: "none",
+}
diff --git a/libutils/RefBase.cpp b/libutils/RefBase.cpp
index b57e287..0518927 100644
--- a/libutils/RefBase.cpp
+++ b/libutils/RefBase.cpp
@@ -170,7 +170,7 @@
         : mStrong(INITIAL_STRONG_VALUE)
         , mWeak(0)
         , mBase(base)
-        , mFlags(0)
+        , mFlags(OBJECT_LIFETIME_STRONG)
     {
     }
 
@@ -189,7 +189,7 @@
         : mStrong(INITIAL_STRONG_VALUE)
         , mWeak(0)
         , mBase(base)
-        , mFlags(0)
+        , mFlags(OBJECT_LIFETIME_STRONG)
         , mStrongRefs(NULL)
         , mWeakRefs(NULL)
         , mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT)