libsnapshot: Check if the vendor is updated from Android S for GRF
In a GRF config, if Vendor partition is updated from Android 12; post
OTA reboot, first stage init will communicate to daemon to check if the
daemon can support socket handoff. If that succeeds, then it is a signal
that the vendor has been updated from Android 12. Use a marker in
/metadata to signal that the vendor was updated. If the marker is present,
then post OTA reboot, userspace snapshot will be used.
Bug: 333854394
Test: OTA
Android U (system) + S (vendor) -> Android V (system) + V (Vendor)
Change-Id: Ie38c4379010789a84e5b44529b407f9f82135271
Signed-off-by: Akilesh Kailash <akailash@google.com>
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index 6d422c6..1ec8634 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -335,6 +335,9 @@
// after loading selinux policy.
bool PrepareSnapuserdArgsForSelinux(std::vector<std::string>* snapuserd_argv);
+ // If snapuserd from first stage init was started from system partition.
+ bool MarkSnapuserdFromSystem();
+
// Detach dm-user devices from the first stage snapuserd. Load
// new dm-user tables after loading selinux policy.
bool DetachFirstStageSnapuserdForSelinux();
@@ -670,6 +673,7 @@
std::string GetForwardMergeIndicatorPath();
std::string GetOldPartitionMetadataPath();
std::string GetBootSnapshotsWithoutSlotSwitchPath();
+ std::string GetSnapuserdFromSystemPath();
const LpMetadata* ReadOldPartitionMetadata(LockedFile* lock);
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index c01360e..3a474d7 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -88,6 +88,7 @@
"/metadata/ota/snapshot-boot-without-slot-switch";
static constexpr char kBootIndicatorPath[] = "/metadata/ota/snapshot-boot";
static constexpr char kRollbackIndicatorPath[] = "/metadata/ota/rollback-indicator";
+static constexpr char kSnapuserdFromSystem[] = "/metadata/ota/snapuserd-from-system";
static constexpr auto kUpdateStateCheckInterval = 2s;
/*
* The readahead size is set to 32kb so that
@@ -318,7 +319,7 @@
std::vector<std::string> files = {
GetSnapshotBootIndicatorPath(), GetRollbackIndicatorPath(),
GetForwardMergeIndicatorPath(), GetOldPartitionMetadataPath(),
- GetBootSnapshotsWithoutSlotSwitchPath(),
+ GetBootSnapshotsWithoutSlotSwitchPath(), GetSnapuserdFromSystemPath(),
};
for (const auto& file : files) {
RemoveFileIfExists(file);
@@ -1457,6 +1458,10 @@
return metadata_dir_ + "/" + android::base::Basename(kRollbackIndicatorPath);
}
+std::string SnapshotManager::GetSnapuserdFromSystemPath() {
+ return metadata_dir_ + "/" + android::base::Basename(kSnapuserdFromSystem);
+}
+
std::string SnapshotManager::GetForwardMergeIndicatorPath() {
return metadata_dir_ + "/allow-forward-merge";
}
@@ -2122,6 +2127,16 @@
return update_status.o_direct();
}
+bool SnapshotManager::MarkSnapuserdFromSystem() {
+ auto path = GetSnapuserdFromSystemPath();
+
+ if (!android::base::WriteStringToFile("1", path)) {
+ PLOG(ERROR) << "Unable to write to vendor update path: " << path;
+ return false;
+ }
+ return true;
+}
+
/*
* Please see b/304829384 for more details.
*
@@ -2158,11 +2173,26 @@
* iii: If both (i) and (ii) are true, then use the dm-snapshot based
* approach.
*
+ * 3: Post OTA reboot, if the vendor partition was updated from Android 12 to
+ * any other release post Android 12, then snapuserd binary will be "system"
+ * partition as post Android 12, init_boot will contain a copy of snapuserd
+ * binary. Thus, during first stage init, if init is able to communicate to
+ * daemon, that gives us a signal that the binary is from "system" copy. Hence,
+ * there is no need to fallback to legacy dm-snapshot. Thus, init will use a
+ * marker in /metadata to signal that the snapuserd binary from first stage init
+ * can handle userspace snapshots.
+ *
*/
bool SnapshotManager::IsLegacySnapuserdPostReboot() {
if (is_legacy_snapuserd_.has_value() && is_legacy_snapuserd_.value() == true) {
auto slot = GetCurrentSlot();
if (slot == Slot::Target) {
+ // If this marker is present, then daemon can handle userspace
+ // snapshots; also, it indicates that the vendor partition was
+ // updated from Android 12.
+ if (access(GetSnapuserdFromSystemPath().c_str(), F_OK) == 0) {
+ return false;
+ }
return true;
}
}
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index 5d3a273..55cce6e 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -395,12 +395,7 @@
use_snapuserd_ = sm->IsSnapuserdRequired();
if (use_snapuserd_) {
- if (sm->UpdateUsesUserSnapshots()) {
- LaunchFirstStageSnapuserd();
- } else {
- LOG(FATAL) << "legacy virtual-ab is no longer supported";
- return false;
- }
+ LaunchFirstStageSnapuserd();
}
sm->SetUeventRegenCallback([this](const std::string& device) -> bool {
diff --git a/init/snapuserd_transition.cpp b/init/snapuserd_transition.cpp
index 9e3ff41..2370bc2 100644
--- a/init/snapuserd_transition.cpp
+++ b/init/snapuserd_transition.cpp
@@ -100,6 +100,10 @@
}
if (client->SupportsSecondStageSocketHandoff()) {
setenv(kSnapuserdFirstStageInfoVar, "socket", 1);
+ auto sm = SnapshotManager::NewForFirstStageMount();
+ if (!sm->MarkSnapuserdFromSystem()) {
+ LOG(ERROR) << "Failed to update MarkSnapuserdFromSystem";
+ }
}
setenv(kSnapuserdFirstStagePidVar, std::to_string(pid).c_str(), 1);