Merge "Preserving /avb/* keys to /metadata" am: 05aff5b211

Change-Id: Ibf1c8b6cf4d692ca6b87532d8b5bb83f9c6d7f18
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index 21663e6..622e457 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -21,6 +21,7 @@
 #include <unistd.h>
 
 #include <chrono>
+#include <filesystem>
 #include <map>
 #include <memory>
 #include <set>
@@ -99,7 +100,11 @@
     void GetDmLinearMetadataDevice(std::set<std::string>* devices);
     bool InitDmLinearBackingDevices(const android::fs_mgr::LpMetadata& metadata);
     void UseDsuIfPresent();
+    // Reads all fstab.avb_keys from the ramdisk for first-stage mount.
     void PreloadAvbKeys();
+    // Copies /avb/*.avbpubkey used for DSU from the ramdisk to /metadata for key
+    // revocation check by DSU installation service.
+    void CopyDsuAvbKeys();
 
     ListenerAction UeventCallback(const Uevent& uevent, std::set<std::string>* required_devices);
 
@@ -595,7 +600,12 @@
         return entry.mount_point == "/metadata";
     });
     if (metadata_partition != fstab_.end()) {
-        MountPartition(metadata_partition, true /* erase_same_mounts */);
+        if (MountPartition(metadata_partition, true /* erase_same_mounts */)) {
+            // Copies DSU AVB keys from the ramdisk to /metadata.
+            // Must be done before the following TrySwitchSystemAsRoot().
+            // Otherwise, ramdisk will be inaccessible after switching root.
+            CopyDsuAvbKeys();
+        }
     }
 
     if (!CreateLogicalPartitions()) return false;
@@ -663,6 +673,27 @@
     return true;
 }
 
+// Preserves /avb/*.avbpubkey to /metadata/gsi/dsu/avb/, so they can be used for
+// key revocation check by DSU installation service.  Note that failing to
+// copy files to /metadata is NOT fatal, because it is auxiliary to perform
+// public key matching before booting into DSU images on next boot. The actual
+// public key matching will still be done on next boot to DSU.
+void FirstStageMount::CopyDsuAvbKeys() {
+    std::error_code ec;
+    // Removing existing keys in gsi::kDsuAvbKeyDir as they might be stale.
+    std::filesystem::remove_all(gsi::kDsuAvbKeyDir, ec);
+    if (ec) {
+        LOG(ERROR) << "Failed to remove directory " << gsi::kDsuAvbKeyDir << ": " << ec.message();
+    }
+    // Copy keys from the ramdisk /avb/* to gsi::kDsuAvbKeyDir.
+    static constexpr char kRamdiskAvbKeyDir[] = "/avb";
+    std::filesystem::copy(kRamdiskAvbKeyDir, gsi::kDsuAvbKeyDir, ec);
+    if (ec) {
+        LOG(ERROR) << "Failed to copy " << kRamdiskAvbKeyDir << " into " << gsi::kDsuAvbKeyDir
+                   << ": " << ec.message();
+    }
+}
+
 void FirstStageMount::UseDsuIfPresent() {
     std::string error;
 
diff --git a/init/selinux.cpp b/init/selinux.cpp
index 41007c1..c5b7576 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -65,6 +65,7 @@
 #include <android-base/parseint.h>
 #include <android-base/unique_fd.h>
 #include <fs_avb/fs_avb.h>
+#include <libgsi/libgsi.h>
 #include <selinux/android.h>
 
 #include "debug_ramdisk.h"
@@ -533,6 +534,8 @@
     selinux_android_restorecon("/apex", 0);
 
     selinux_android_restorecon("/linkerconfig", 0);
+
+    selinux_android_restorecon(gsi::kDsuAvbKeyDir, SELINUX_ANDROID_RESTORECON_RECURSE);
 }
 
 int SelinuxKlogCallback(int type, const char* fmt, ...) {