Only restore apex backups on non-checkpointing devices.
Backup and restore of /data/apex/active is only intended to occur on
devices that do not have FS-checkpointing support. This change
ensures that backups are not restored on devices that do support
checkpointing.
Cherry-pick of aosp/1767767
Bug: 192102594
Bug: 193932765
Test: atest ApexServiceRevertTest
Change-Id: Ia07633c0da71f167098b15958e519ebb0bc90b6b
Merged-In: Ia07633c0da71f167098b15958e519ebb0bc90b6b
(cherry picked from commit 85642155eecda9c895283e3050fdb376d92271ae)
diff --git a/apexd/apexd.cpp b/apexd/apexd.cpp
index 0010c42..80e075a 100644
--- a/apexd/apexd.cpp
+++ b/apexd/apexd.cpp
@@ -52,6 +52,7 @@
#include <dirent.h>
#include <fcntl.h>
#include <linux/loop.h>
+#include <log/log.h>
#include <stdlib.h>
#include <sys/inotify.h>
#include <sys/ioctl.h>
@@ -1256,7 +1257,7 @@
}
} else if (session.IsRollback()) {
for (const auto& apex_name : session.GetApexNames()) {
- if (!gInFsCheckpointMode) {
+ if (!gSupportsFsCheckpoints) {
// Snapshot before restore so this rollback can be reverted.
snapshotDataDirectory(base_dir, session.GetRollbackId(), apex_name,
true /* pre_restore */);
@@ -1737,6 +1738,11 @@
}
if (!gInFsCheckpointMode) {
+ // SafetyNet logging for b/19393765
+ android_errorWriteLog(0x534e4554, "193932765");
+ }
+
+ if (!gSupportsFsCheckpoints) {
auto restoreStatus = RestoreActivePackages();
if (!restoreStatus.ok()) {
for (auto& session : activeSessions) {
@@ -1754,7 +1760,7 @@
}
for (auto& session : activeSessions) {
- if (!gInFsCheckpointMode && session.IsRollback()) {
+ if (!gSupportsFsCheckpoints && session.IsRollback()) {
// If snapshots have already been restored, undo that by restoring the
// pre-restore snapshot.
restoreDePreRestoreSnapshotsIfPresent(session);
@@ -2070,7 +2076,7 @@
return Error() << "Failed to mark session " << *session
<< " as successful : " << cleanup_status.error();
}
- if (session->IsRollback() && !gInFsCheckpointMode) {
+ if (session->IsRollback() && !gSupportsFsCheckpoints) {
deleteDePreRestoreSnapshots(*session);
}
return session->UpdateStateAndCommit(SessionState::SUCCESS);
diff --git a/apexd/apexservice_test.cpp b/apexd/apexservice_test.cpp
index 4c054f1..7f78610 100644
--- a/apexd/apexservice_test.cpp
+++ b/apexd/apexservice_test.cpp
@@ -2187,7 +2187,7 @@
}
}
- void CheckRevertWasPerformed(const std::vector<std::string>& expected_pkgs) {
+ void CheckActiveApexContents(const std::vector<std::string>& expected_pkgs) {
// First check that /data/apex/active exists and has correct permissions.
struct stat sd;
ASSERT_EQ(0, stat(kActiveApexPackagesDataDir, &sd));
@@ -2225,7 +2225,38 @@
auto pkg = StringPrintf("%s/com.android.apex.test_package@1.apex",
kActiveApexPackagesDataDir);
SCOPED_TRACE("");
- CheckRevertWasPerformed({pkg});
+ CheckActiveApexContents({pkg});
+}
+
+// Calling revertActiveSessions should not restore backup on checkpointing
+// devices
+TEST_F(ApexServiceRevertTest,
+ RevertActiveSessionsDoesNotRestoreBackupIfCheckpointingSupported) {
+ if (!supports_fs_checkpointing_) {
+ GTEST_SKIP() << "Can't run if filesystem checkpointing is not supported";
+ }
+
+ PrepareTestApexForInstall installer(GetTestFile("apex.apexd_test_v2.apex"));
+ if (!installer.Prepare()) {
+ return;
+ }
+
+ auto session = ApexSession::CreateSession(1543);
+ ASSERT_TRUE(IsOk(session));
+ ASSERT_TRUE(IsOk(session->UpdateStateAndCommit(SessionState::ACTIVATED)));
+
+ // Make sure /data/apex/active is non-empty.
+ ASSERT_TRUE(IsOk(service_->stagePackages({installer.test_file})));
+
+ PrepareBackup({GetTestFile("apex.apexd_test.apex")});
+
+ ASSERT_TRUE(IsOk(service_->revertActiveSessions()));
+
+ // Check that active apexes were not reverted.
+ auto pkg = StringPrintf("%s/com.android.apex.test_package@2.apex",
+ kActiveApexPackagesDataDir);
+ SCOPED_TRACE("");
+ CheckActiveApexContents({pkg});
}
// Should fail to revert active sessions when there are none
@@ -2296,7 +2327,7 @@
auto pkg2 = StringPrintf("%s/com.android.apex.test_package_2@1.apex",
kActiveApexPackagesDataDir);
SCOPED_TRACE("");
- CheckRevertWasPerformed({pkg1, pkg2});
+ CheckActiveApexContents({pkg1, pkg2});
std::vector<ApexSessionInfo> sessions;
ASSERT_TRUE(IsOk(service_->getSessions(&sessions)));