Merge "init.rc: set up a tracing instance for BootReceiver.java"
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index c1a59d8..ca68212 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -592,7 +592,6 @@
   }
 
   ProcessInfo process_info;
-  unique_fd attr_fd(open("/proc/self/attr/current", O_RDONLY | O_CLOEXEC));
   process_info.abort_msg_address = abort_msg_address;
   engrave_tombstone(unique_fd(dup(tombstone_fd)), unique_fd(dup(proto_fd)), &unwinder, threads, tid,
                     process_info, nullptr, nullptr);
diff --git a/fs_mgr/libfiemap/image_manager.cpp b/fs_mgr/libfiemap/image_manager.cpp
index 841f215..44f659b 100644
--- a/fs_mgr/libfiemap/image_manager.cpp
+++ b/fs_mgr/libfiemap/image_manager.cpp
@@ -16,6 +16,8 @@
 
 #include <libfiemap/image_manager.h>
 
+#include <optional>
+
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/properties.h>
@@ -574,7 +576,7 @@
         return false;
     }
     auto& dm = DeviceMapper::Instance();
-    LoopControl loop;
+    std::optional<LoopControl> loop;
 
     std::string status;
     auto status_file = GetStatusFilePath(name);
@@ -598,9 +600,14 @@
                 return false;
             }
         } else if (pieces[0] == "loop") {
+            // Lazily connect to loop-control to avoid spurious errors in recovery.
+            if (!loop.has_value()) {
+                loop.emplace();
+            }
+
             // Failure to remove a loop device is not fatal, since we can still
             // remove the backing file if we want.
-            loop.Detach(pieces[1]);
+            loop->Detach(pieces[1]);
         } else {
             LOG(ERROR) << "Unknown status: " << pieces[0];
         }
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index 0d90f6c..a79a86d 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -694,8 +694,8 @@
     // Call ProcessUpdateState and handle states with special rules before data wipe. Specifically,
     // if |allow_forward_merge| and allow-forward-merge indicator exists, initiate merge if
     // necessary.
-    bool ProcessUpdateStateOnDataWipe(bool allow_forward_merge,
-                                      const std::function<bool()>& callback);
+    UpdateState ProcessUpdateStateOnDataWipe(bool allow_forward_merge,
+                                             const std::function<bool()>& callback);
 
     // Return device string of a mapped image, or if it is not available, the mapped image path.
     bool GetMappedImageDeviceStringOrPath(const std::string& device_name,
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index eb3a501..cc2599d 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -894,6 +894,8 @@
                                                 const std::function<bool()>& before_cancel) {
     while (true) {
         UpdateState state = CheckMergeState(before_cancel);
+        LOG(INFO) << "ProcessUpdateState handling state: " << state;
+
         if (state == UpdateState::MergeFailed) {
             AcknowledgeMergeFailure();
         }
@@ -920,13 +922,15 @@
     }
 
     UpdateState state = CheckMergeState(lock.get(), before_cancel);
+    LOG(INFO) << "CheckMergeState for snapshots returned: " << state;
+
     if (state == UpdateState::MergeCompleted) {
         // Do this inside the same lock. Failures get acknowledged without the
         // lock, because flock() might have failed.
         AcknowledgeMergeSuccess(lock.get());
     } else if (state == UpdateState::Cancelled) {
-        if (!RemoveAllUpdateState(lock.get(), before_cancel)) {
-            return ReadSnapshotUpdateStatus(lock.get()).state();
+        if (!device_->IsRecovery() && !RemoveAllUpdateState(lock.get(), before_cancel)) {
+            LOG(ERROR) << "Failed to remove all update state after acknowleding cancelled update.";
         }
     }
     return state;
@@ -968,13 +972,23 @@
         return UpdateState::MergeFailed;
     }
 
+    auto other_suffix = device_->GetOtherSlotSuffix();
+
     bool cancelled = false;
     bool failed = false;
     bool merging = false;
     bool needs_reboot = false;
     bool wrong_phase = false;
     for (const auto& snapshot : snapshots) {
+        if (android::base::EndsWith(snapshot, other_suffix)) {
+            // This will have triggered an error message in InitiateMerge already.
+            LOG(INFO) << "Skipping merge validation of unexpected snapshot: " << snapshot;
+            continue;
+        }
+
         UpdateState snapshot_state = CheckTargetMergeState(lock, snapshot, update_status);
+        LOG(INFO) << "CheckTargetMergeState for " << snapshot << " returned: " << snapshot_state;
+
         switch (snapshot_state) {
             case UpdateState::MergeFailed:
                 failed = true;
@@ -1173,7 +1187,7 @@
     // indicator that cleanup is needed on reboot. If a factory data reset
     // was requested, it doesn't matter, everything will get wiped anyway.
     // To make testing easier we consider a /data wipe as cleaned up.
-    if (device_->IsRecovery() && !in_factory_data_reset_) {
+    if (device_->IsRecovery()) {
         WriteUpdateState(lock, UpdateState::MergeCompleted);
         return;
     }
@@ -1692,6 +1706,7 @@
     for (const auto& snapshot : snapshots) {
         DmTargetSnapshot::Status current_status;
 
+        if (!IsSnapshotDevice(snapshot)) continue;
         if (!QuerySnapshotStatus(snapshot, nullptr, &current_status)) continue;
 
         fake_snapshots_status.sectors_allocated += current_status.sectors_allocated;
@@ -3212,10 +3227,11 @@
     };
 
     in_factory_data_reset_ = true;
-    bool ok = ProcessUpdateStateOnDataWipe(true /* allow_forward_merge */, process_callback);
+    UpdateState state =
+            ProcessUpdateStateOnDataWipe(true /* allow_forward_merge */, process_callback);
     in_factory_data_reset_ = false;
 
-    if (!ok) {
+    if (state == UpdateState::MergeFailed) {
         return false;
     }
 
@@ -3223,6 +3239,16 @@
     if (!UnmapAllPartitionsInRecovery()) {
         LOG(ERROR) << "Unable to unmap all partitions; fastboot may fail to flash.";
     }
+
+    if (state != UpdateState::None) {
+        auto lock = LockExclusive();
+        if (!lock) return false;
+
+        // Zap the update state so the bootloader doesn't think we're still
+        // merging. It's okay if this fails, it's informative only at this
+        // point.
+        WriteUpdateState(lock.get(), UpdateState::None);
+    }
     return true;
 }
 
@@ -3257,15 +3283,15 @@
     return true;
 }
 
-bool SnapshotManager::ProcessUpdateStateOnDataWipe(bool allow_forward_merge,
-                                                   const std::function<bool()>& callback) {
+UpdateState SnapshotManager::ProcessUpdateStateOnDataWipe(bool allow_forward_merge,
+                                                          const std::function<bool()>& callback) {
     auto slot_number = SlotNumberForSlotSuffix(device_->GetSlotSuffix());
     UpdateState state = ProcessUpdateState(callback);
     LOG(INFO) << "Update state in recovery: " << state;
     switch (state) {
         case UpdateState::MergeFailed:
             LOG(ERROR) << "Unrecoverable merge failure detected.";
-            return false;
+            return state;
         case UpdateState::Unverified: {
             // If an OTA was just applied but has not yet started merging:
             //
@@ -3285,8 +3311,12 @@
                 if (allow_forward_merge &&
                     access(GetForwardMergeIndicatorPath().c_str(), F_OK) == 0) {
                     LOG(INFO) << "Forward merge allowed, initiating merge now.";
-                    return InitiateMerge() &&
-                           ProcessUpdateStateOnDataWipe(false /* allow_forward_merge */, callback);
+
+                    if (!InitiateMerge()) {
+                        LOG(ERROR) << "Failed to initiate merge on data wipe.";
+                        return UpdateState::MergeFailed;
+                    }
+                    return ProcessUpdateStateOnDataWipe(false /* allow_forward_merge */, callback);
                 }
 
                 LOG(ERROR) << "Reverting to old slot since update will be deleted.";
@@ -3304,7 +3334,7 @@
         default:
             break;
     }
-    return true;
+    return state;
 }
 
 bool SnapshotManager::EnsureNoOverflowSnapshot(LockedFile* lock) {
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index d57aa6c..bde4cca 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -636,8 +636,8 @@
 
     // Because the status is Merging, we must call ProcessUpdateState, which should
     // detect a cancelled update.
-    ASSERT_EQ(sm->ProcessUpdateState(), UpdateState::Cancelled);
-    ASSERT_EQ(sm->GetUpdateState(), UpdateState::None);
+    ASSERT_EQ(init->ProcessUpdateState(), UpdateState::Cancelled);
+    ASSERT_EQ(init->GetUpdateState(), UpdateState::None);
 }
 
 TEST_F(SnapshotTest, UpdateBootControlHal) {
@@ -1767,7 +1767,7 @@
     ASSERT_TRUE(new_sm->HandleImminentDataWipe());
     // Manually mount metadata so that we can call GetUpdateState() below.
     MountMetadata();
-    EXPECT_EQ(new_sm->GetUpdateState(), UpdateState::Unverified);
+    EXPECT_EQ(new_sm->GetUpdateState(), UpdateState::None);
     EXPECT_TRUE(test_device->IsSlotUnbootable(1));
     EXPECT_FALSE(test_device->IsSlotUnbootable(0));
 }
@@ -2105,8 +2105,12 @@
 
     // There should be no snapshot to merge.
     auto new_sm = SnapshotManager::New(new TestDeviceInfo(fake_super, flashed_slot_suffix));
-    // update_enigne calls ProcessUpdateState first -- should see Cancelled.
-    ASSERT_EQ(UpdateState::Cancelled, new_sm->ProcessUpdateState());
+    if (flashed_slot == 0 && after_merge) {
+        ASSERT_EQ(UpdateState::MergeCompleted, new_sm->ProcessUpdateState());
+    } else {
+        // update_engine calls ProcessUpdateState first -- should see Cancelled.
+        ASSERT_EQ(UpdateState::Cancelled, new_sm->ProcessUpdateState());
+    }
 
     // Next OTA calls CancelUpdate no matter what.
     ASSERT_TRUE(new_sm->CancelUpdate());
diff --git a/libprocessgroup/setup/cgroup_map_write.cpp b/libprocessgroup/setup/cgroup_map_write.cpp
index 753fd2d..aa41acb 100644
--- a/libprocessgroup/setup/cgroup_map_write.cpp
+++ b/libprocessgroup/setup/cgroup_map_write.cpp
@@ -183,10 +183,12 @@
         return false;
     }
 
-    Json::Reader reader;
+    Json::CharReaderBuilder builder;
+    std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
     Json::Value root;
-    if (!reader.parse(json_doc, root)) {
-        LOG(ERROR) << "Failed to parse cgroups description: " << reader.getFormattedErrorMessages();
+    std::string errorMessage;
+    if (!reader->parse(&*json_doc.begin(), &*json_doc.end(), &root, &errorMessage)) {
+        LOG(ERROR) << "Failed to parse cgroups description: " << errorMessage;
         return false;
     }
 
diff --git a/libprocessgroup/task_profiles.cpp b/libprocessgroup/task_profiles.cpp
index 8d4ce25..f13a681 100644
--- a/libprocessgroup/task_profiles.cpp
+++ b/libprocessgroup/task_profiles.cpp
@@ -425,10 +425,12 @@
         return false;
     }
 
-    Json::Reader reader;
+    Json::CharReaderBuilder builder;
+    std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
     Json::Value root;
-    if (!reader.parse(json_doc, root)) {
-        LOG(ERROR) << "Failed to parse task profiles: " << reader.getFormattedErrorMessages();
+    std::string errorMessage;
+    if (!reader->parse(&*json_doc.begin(), &*json_doc.end(), &root, &errorMessage)) {
+        LOG(ERROR) << "Failed to parse task profiles: " << errorMessage;
         return false;
     }
 
diff --git a/trusty/apploader/fuzz/Android.bp b/trusty/apploader/fuzz/Android.bp
new file mode 100644
index 0000000..e37dab1
--- /dev/null
+++ b/trusty/apploader/fuzz/Android.bp
@@ -0,0 +1,40 @@
+// Copyright (C) 2021 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.
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+// Fuzz Trusty IPC messages sent to apploader.
+cc_fuzz {
+    name: "trusty_apploader_tipc_fuzzer",
+    defaults: ["trusty_fuzzer_defaults"],
+    srcs: [":trusty_tipc_fuzzer"],
+    cflags: [
+        "-DTRUSTY_APP_PORT=\"com.android.trusty.apploader\"",
+        "-DTRUSTY_APP_UUID=\"081ba88f-f1ee-452e-b5e8-a7e9ef173a97\"",
+        "-DTRUSTY_APP_FILENAME=\"apploader.syms.elf\"",
+    ]
+}
+
+// Fuzz app package sent to apploader.
+cc_fuzz {
+    name: "trusty_apploader_app_fuzzer",
+    defaults: ["trusty_fuzzer_defaults"],
+    srcs: ["app_fuzzer.cpp"],
+    include_dirs: ["system/core/trusty/apploader"],
+    shared_libs: [
+        "libdmabufheap",
+    ],
+}
diff --git a/trusty/apploader/fuzz/app_fuzzer.cpp b/trusty/apploader/fuzz/app_fuzzer.cpp
new file mode 100644
index 0000000..aa0caca
--- /dev/null
+++ b/trusty/apploader/fuzz/app_fuzzer.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2021 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 <BufferAllocator/BufferAllocator.h>
+#include <android-base/unique_fd.h>
+#include <apploader_ipc.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <trusty/coverage/coverage.h>
+#include <trusty/fuzz/counters.h>
+#include <trusty/fuzz/utils.h>
+#include <trusty/tipc.h>
+#include <unistd.h>
+#include <iostream>
+
+using android::base::unique_fd;
+using android::trusty::coverage::CoverageRecord;
+using android::trusty::fuzz::ExtraCounters;
+using android::trusty::fuzz::TrustyApp;
+
+#define TIPC_DEV "/dev/trusty-ipc-dev0"
+#define APPLOADER_PORT "com.android.trusty.apploader"
+#define APPLOADER_MODULE_NAME "apploader.syms.elf"
+
+/* Apploader TA's UUID is 081ba88f-f1ee-452e-b5e8-a7e9ef173a97 */
+static struct uuid apploader_uuid = {
+        0x081ba88f,
+        0xf1ee,
+        0x452e,
+        {0xb5, 0xe8, 0xa7, 0xe9, 0xef, 0x17, 0x3a, 0x97},
+};
+
+static inline uintptr_t RoundPageUp(uintptr_t val) {
+    return (val + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
+}
+
+static bool SendLoadMsg(int chan, int dma_buf, size_t dma_buf_size) {
+    apploader_header hdr = {
+            .cmd = APPLOADER_CMD_LOAD_APPLICATION,
+    };
+    apploader_load_app_req req = {
+            .package_size = static_cast<uint64_t>(dma_buf_size),
+    };
+    iovec iov[] = {
+            {
+                    .iov_base = &hdr,
+                    .iov_len = sizeof(hdr),
+            },
+            {
+                    .iov_base = &req,
+                    .iov_len = sizeof(req),
+            },
+    };
+    trusty_shm shm = {
+            .fd = dma_buf,
+            .transfer = TRUSTY_SHARE,
+    };
+
+    int rc = tipc_send(chan, iov, 2, &shm, 1);
+    if (rc != static_cast<int>(sizeof(hdr) + sizeof(req))) {
+        std::cerr << "Failed to send request" << std::endl;
+        return false;
+    }
+
+    apploader_resp resp;
+    rc = read(chan, &resp, sizeof(resp));
+    if (rc != static_cast<int>(sizeof(resp))) {
+        std::cerr << "Failed to receive response" << std::endl;
+        return false;
+    }
+
+    return true;
+}
+
+static CoverageRecord record(TIPC_DEV, &apploader_uuid, APPLOADER_MODULE_NAME);
+
+extern "C" int LLVMFuzzerInitialize(int* /* argc */, char*** /* argv */) {
+    auto ret = record.Open();
+    if (!ret.ok()) {
+        std::cerr << ret.error() << std::endl;
+        exit(-1);
+    }
+    return 0;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    ExtraCounters counters(&record);
+    counters.Reset();
+
+    android::trusty::fuzz::TrustyApp ta(TIPC_DEV, APPLOADER_PORT);
+    auto ret = ta.Connect();
+    if (!ret.ok()) {
+        std::cerr << ret.error() << std::endl;
+        android::trusty::fuzz::Abort();
+    }
+
+    uint64_t shm_len = size ? RoundPageUp(size) : PAGE_SIZE;
+    BufferAllocator alloc;
+    unique_fd dma_buf(alloc.Alloc(kDmabufSystemHeapName, shm_len));
+    if (dma_buf < 0) {
+        std::cerr << "Failed to create dmabuf of size: " << shm_len << std::endl;
+        android::trusty::fuzz::Abort();
+    }
+
+    void* shm_base = mmap(0, shm_len, PROT_READ | PROT_WRITE, MAP_SHARED, dma_buf, 0);
+    if (shm_base == MAP_FAILED) {
+        std::cerr << "Failed to mmap() dmabuf" << std::endl;
+        android::trusty::fuzz::Abort();
+    }
+
+    memcpy(shm_base, data, size);
+
+    bool success = SendLoadMsg(*ta.GetRawFd(), dma_buf, shm_len);
+    if (!success) {
+        std::cerr << "Failed to send load message" << std::endl;
+        android::trusty::fuzz::Abort();
+    }
+
+    munmap(shm_base, shm_len);
+    return 0;
+}