From 1bbf8f042f7ffb4a38657ccf6dca0798931fecd5 Mon Sep 17 00:00:00 2001 From: Akilesh Kailash Date: Fri, 21 Jun 2024 10:53:53 -0700 Subject: [PATCH] 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 --- .../include/libsnapshot/snapshot.h | 4 +++ fs_mgr/libsnapshot/snapshot.cpp | 32 ++++++++++++++++++- init/first_stage_mount.cpp | 7 +--- init/snapuserd_transition.cpp | 4 +++ 4 files changed, 40 insertions(+), 7 deletions(-) diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h index 6d422c614..1ec863444 100644 --- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h +++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h @@ -335,6 +335,9 @@ class SnapshotManager final : public ISnapshotManager { // after loading selinux policy. bool PrepareSnapuserdArgsForSelinux(std::vector* 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 @@ class SnapshotManager final : public ISnapshotManager { 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 c01360e0b..3a474d710 100644 --- a/fs_mgr/libsnapshot/snapshot.cpp +++ b/fs_mgr/libsnapshot/snapshot.cpp @@ -88,6 +88,7 @@ static constexpr char kBootSnapshotsWithoutSlotSwitch[] = "/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 @@ bool SnapshotManager::RemoveAllUpdateState(LockedFile* lock, const std::function std::vector files = { GetSnapshotBootIndicatorPath(), GetRollbackIndicatorPath(), GetForwardMergeIndicatorPath(), GetOldPartitionMetadataPath(), - GetBootSnapshotsWithoutSlotSwitchPath(), + GetBootSnapshotsWithoutSlotSwitchPath(), GetSnapuserdFromSystemPath(), }; for (const auto& file : files) { RemoveFileIfExists(file); @@ -1457,6 +1458,10 @@ std::string SnapshotManager::GetRollbackIndicatorPath() { 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 @@ bool SnapshotManager::UpdateUsesODirect(LockedFile* lock) { 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 @@ bool SnapshotManager::UpdateUsesODirect(LockedFile* lock) { * 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 5d3a27354..55cce6eaa 100644 --- a/init/first_stage_mount.cpp +++ b/init/first_stage_mount.cpp @@ -395,12 +395,7 @@ bool FirstStageMountVBootV2::CreateSnapshotPartitions(SnapshotManager* sm) { 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 9e3ff4175..2370bc205 100644 --- a/init/snapuserd_transition.cpp +++ b/init/snapuserd_transition.cpp @@ -100,6 +100,10 @@ void LaunchFirstStageSnapuserd() { } 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);