Loading cmds/installd/InstalldNativeService.cpp +39 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/parseint.h> #include <android-base/properties.h> #include <android-base/scopeguard.h> #include <android-base/stringprintf.h> Loading Loading @@ -75,6 +76,7 @@ #define LOG_TAG "installd" #endif using android::base::ParseUint; using android::base::StringPrintf; using std::endl; Loading Loading @@ -1101,6 +1103,43 @@ binder::Status InstalldNativeService::destroyAppDataSnapshot( return ok(); } binder::Status InstalldNativeService::destroyCeSnapshotsNotSpecified( const std::unique_ptr<std::string> &volumeUuid, const int32_t userId, const std::vector<int32_t>& retainSnapshotIds) { ENFORCE_UID(AID_SYSTEM); CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(volumeUuid); std::lock_guard<std::recursive_mutex> lock(mLock); const char* volume_uuid = volumeUuid ? volumeUuid->c_str() : nullptr; auto base_path = create_data_misc_ce_rollback_base_path(volume_uuid, userId); std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(base_path.c_str()), closedir); if (!dir) { return error(-1, "Failed to open rollback base dir " + base_path); } struct dirent* ent; while ((ent = readdir(dir.get()))) { if (ent->d_type != DT_DIR) { continue; } uint snapshot_id; bool parse_ok = ParseUint(ent->d_name, &snapshot_id); if (parse_ok && std::find(retainSnapshotIds.begin(), retainSnapshotIds.end(), snapshot_id) == retainSnapshotIds.end()) { auto rollback_path = create_data_misc_ce_rollback_path( volume_uuid, userId, snapshot_id); int res = delete_dir_contents_and_dir(rollback_path, true /* ignore_if_missing */); if (res != 0) { return error(res, "Failed clearing snapshot " + rollback_path); } } } return ok(); } binder::Status InstalldNativeService::moveCompleteApp(const std::unique_ptr<std::string>& fromUuid, const std::unique_ptr<std::string>& toUuid, const std::string& packageName, Loading cmds/installd/InstalldNativeService.h +2 −0 Original line number Diff line number Diff line Loading @@ -69,6 +69,8 @@ public: binder::Status destroyAppDataSnapshot(const std::unique_ptr<std::string> &volumeUuid, const std::string& packageName, const int32_t user, const int64_t ceSnapshotInode, const int32_t snapshotId, int32_t storageFlags); binder::Status destroyCeSnapshotsNotSpecified(const std::unique_ptr<std::string> &volumeUuid, const int32_t userId, const std::vector<int32_t>& retainSnapshotIds); binder::Status getAppSize(const std::unique_ptr<std::string>& uuid, const std::vector<std::string>& packageNames, int32_t userId, int32_t flags, Loading cmds/installd/binder/android/os/IInstalld.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -116,6 +116,9 @@ interface IInstalld { int appId, @utf8InCpp String seInfo, int user, int snapshotId, int storageflags); void destroyAppDataSnapshot(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName, int userId, long ceSnapshotInode, int snapshotId, int storageFlags); void destroyCeSnapshotsNotSpecified(@nullable @utf8InCpp String uuid, int userId, in int[] retainSnapshotIds); void tryMountDataMirror(@nullable @utf8InCpp String volumeUuid); void onPrivateVolumeRemoved(@nullable @utf8InCpp String volumeUuid); Loading cmds/installd/tests/installd_service_test.cpp +40 −0 Original line number Diff line number Diff line Loading @@ -641,6 +641,46 @@ TEST_F(AppDataSnapshotTest, DestroyAppDataSnapshot_WrongVolumeUuid) { "com.foo", 0, 0, 43, FLAG_STORAGE_DE).isOk()); } TEST_F(AppDataSnapshotTest, DestroyCeSnapshotsNotSpecified) { auto rollback_ce_dir_in_1 = create_data_misc_ce_rollback_path("TEST", 0, 1543); auto rollback_ce_dir_in_2 = create_data_misc_ce_rollback_path("TEST", 0, 77); auto rollback_ce_dir_out_1 = create_data_misc_ce_rollback_path("TEST", 0, 1500); auto rollback_ce_dir_out_2 = create_data_misc_ce_rollback_path("TEST", 0, 2); // Create snapshots ASSERT_TRUE(mkdirs(rollback_ce_dir_in_1 + "/com.foo/", 0700)); ASSERT_TRUE(android::base::WriteStringToFile( "CE_RESTORE_CONTENT", rollback_ce_dir_in_1 + "/com.foo/file1", 0700, 10000, 20000, false /* follow_symlinks */)); ASSERT_TRUE(mkdirs(rollback_ce_dir_in_2 + "/com.foo/", 0700)); ASSERT_TRUE(android::base::WriteStringToFile( "CE_RESTORE_CONTENT", rollback_ce_dir_in_2 + "/com.foo/file1", 0700, 10000, 20000, false /* follow_symlinks */)); ASSERT_TRUE(mkdirs(rollback_ce_dir_out_1 + "/com.foo/", 0700)); ASSERT_TRUE(android::base::WriteStringToFile( "CE_RESTORE_CONTENT", rollback_ce_dir_out_1 + "/com.foo/file1", 0700, 10000, 20000, false /* follow_symlinks */)); ASSERT_TRUE(mkdirs(rollback_ce_dir_out_2 + "/com.foo/", 0700)); ASSERT_TRUE(android::base::WriteStringToFile( "CE_RESTORE_CONTENT", rollback_ce_dir_out_2 + "/com.foo/file1", 0700, 10000, 20000, false /* follow_symlinks */)); ASSERT_TRUE(service->destroyCeSnapshotsNotSpecified( std::make_unique<std::string>("TEST"), 0, { 1543, 77 }).isOk()); // Check only snapshots not specified are deleted. struct stat sb; ASSERT_EQ(0, stat((rollback_ce_dir_in_1 + "/com.foo").c_str(), &sb)); ASSERT_EQ(0, stat((rollback_ce_dir_in_2 + "/com.foo").c_str(), &sb)); ASSERT_EQ(-1, stat((rollback_ce_dir_out_1 + "/com.foo").c_str(), &sb)); ASSERT_EQ(ENOENT, errno); ASSERT_EQ(-1, stat((rollback_ce_dir_out_2 + "/com.foo").c_str(), &sb)); ASSERT_EQ(ENOENT, errno); } TEST_F(AppDataSnapshotTest, RestoreAppDataSnapshot_WrongVolumeUuid) { // Setup rollback data to make sure that fails due to wrong volumeUuid being // passed, not because of some other reason. Loading Loading
cmds/installd/InstalldNativeService.cpp +39 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/parseint.h> #include <android-base/properties.h> #include <android-base/scopeguard.h> #include <android-base/stringprintf.h> Loading Loading @@ -75,6 +76,7 @@ #define LOG_TAG "installd" #endif using android::base::ParseUint; using android::base::StringPrintf; using std::endl; Loading Loading @@ -1101,6 +1103,43 @@ binder::Status InstalldNativeService::destroyAppDataSnapshot( return ok(); } binder::Status InstalldNativeService::destroyCeSnapshotsNotSpecified( const std::unique_ptr<std::string> &volumeUuid, const int32_t userId, const std::vector<int32_t>& retainSnapshotIds) { ENFORCE_UID(AID_SYSTEM); CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(volumeUuid); std::lock_guard<std::recursive_mutex> lock(mLock); const char* volume_uuid = volumeUuid ? volumeUuid->c_str() : nullptr; auto base_path = create_data_misc_ce_rollback_base_path(volume_uuid, userId); std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(base_path.c_str()), closedir); if (!dir) { return error(-1, "Failed to open rollback base dir " + base_path); } struct dirent* ent; while ((ent = readdir(dir.get()))) { if (ent->d_type != DT_DIR) { continue; } uint snapshot_id; bool parse_ok = ParseUint(ent->d_name, &snapshot_id); if (parse_ok && std::find(retainSnapshotIds.begin(), retainSnapshotIds.end(), snapshot_id) == retainSnapshotIds.end()) { auto rollback_path = create_data_misc_ce_rollback_path( volume_uuid, userId, snapshot_id); int res = delete_dir_contents_and_dir(rollback_path, true /* ignore_if_missing */); if (res != 0) { return error(res, "Failed clearing snapshot " + rollback_path); } } } return ok(); } binder::Status InstalldNativeService::moveCompleteApp(const std::unique_ptr<std::string>& fromUuid, const std::unique_ptr<std::string>& toUuid, const std::string& packageName, Loading
cmds/installd/InstalldNativeService.h +2 −0 Original line number Diff line number Diff line Loading @@ -69,6 +69,8 @@ public: binder::Status destroyAppDataSnapshot(const std::unique_ptr<std::string> &volumeUuid, const std::string& packageName, const int32_t user, const int64_t ceSnapshotInode, const int32_t snapshotId, int32_t storageFlags); binder::Status destroyCeSnapshotsNotSpecified(const std::unique_ptr<std::string> &volumeUuid, const int32_t userId, const std::vector<int32_t>& retainSnapshotIds); binder::Status getAppSize(const std::unique_ptr<std::string>& uuid, const std::vector<std::string>& packageNames, int32_t userId, int32_t flags, Loading
cmds/installd/binder/android/os/IInstalld.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -116,6 +116,9 @@ interface IInstalld { int appId, @utf8InCpp String seInfo, int user, int snapshotId, int storageflags); void destroyAppDataSnapshot(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName, int userId, long ceSnapshotInode, int snapshotId, int storageFlags); void destroyCeSnapshotsNotSpecified(@nullable @utf8InCpp String uuid, int userId, in int[] retainSnapshotIds); void tryMountDataMirror(@nullable @utf8InCpp String volumeUuid); void onPrivateVolumeRemoved(@nullable @utf8InCpp String volumeUuid); Loading
cmds/installd/tests/installd_service_test.cpp +40 −0 Original line number Diff line number Diff line Loading @@ -641,6 +641,46 @@ TEST_F(AppDataSnapshotTest, DestroyAppDataSnapshot_WrongVolumeUuid) { "com.foo", 0, 0, 43, FLAG_STORAGE_DE).isOk()); } TEST_F(AppDataSnapshotTest, DestroyCeSnapshotsNotSpecified) { auto rollback_ce_dir_in_1 = create_data_misc_ce_rollback_path("TEST", 0, 1543); auto rollback_ce_dir_in_2 = create_data_misc_ce_rollback_path("TEST", 0, 77); auto rollback_ce_dir_out_1 = create_data_misc_ce_rollback_path("TEST", 0, 1500); auto rollback_ce_dir_out_2 = create_data_misc_ce_rollback_path("TEST", 0, 2); // Create snapshots ASSERT_TRUE(mkdirs(rollback_ce_dir_in_1 + "/com.foo/", 0700)); ASSERT_TRUE(android::base::WriteStringToFile( "CE_RESTORE_CONTENT", rollback_ce_dir_in_1 + "/com.foo/file1", 0700, 10000, 20000, false /* follow_symlinks */)); ASSERT_TRUE(mkdirs(rollback_ce_dir_in_2 + "/com.foo/", 0700)); ASSERT_TRUE(android::base::WriteStringToFile( "CE_RESTORE_CONTENT", rollback_ce_dir_in_2 + "/com.foo/file1", 0700, 10000, 20000, false /* follow_symlinks */)); ASSERT_TRUE(mkdirs(rollback_ce_dir_out_1 + "/com.foo/", 0700)); ASSERT_TRUE(android::base::WriteStringToFile( "CE_RESTORE_CONTENT", rollback_ce_dir_out_1 + "/com.foo/file1", 0700, 10000, 20000, false /* follow_symlinks */)); ASSERT_TRUE(mkdirs(rollback_ce_dir_out_2 + "/com.foo/", 0700)); ASSERT_TRUE(android::base::WriteStringToFile( "CE_RESTORE_CONTENT", rollback_ce_dir_out_2 + "/com.foo/file1", 0700, 10000, 20000, false /* follow_symlinks */)); ASSERT_TRUE(service->destroyCeSnapshotsNotSpecified( std::make_unique<std::string>("TEST"), 0, { 1543, 77 }).isOk()); // Check only snapshots not specified are deleted. struct stat sb; ASSERT_EQ(0, stat((rollback_ce_dir_in_1 + "/com.foo").c_str(), &sb)); ASSERT_EQ(0, stat((rollback_ce_dir_in_2 + "/com.foo").c_str(), &sb)); ASSERT_EQ(-1, stat((rollback_ce_dir_out_1 + "/com.foo").c_str(), &sb)); ASSERT_EQ(ENOENT, errno); ASSERT_EQ(-1, stat((rollback_ce_dir_out_2 + "/com.foo").c_str(), &sb)); ASSERT_EQ(ENOENT, errno); } TEST_F(AppDataSnapshotTest, RestoreAppDataSnapshot_WrongVolumeUuid) { // Setup rollback data to make sure that fails due to wrong volumeUuid being // passed, not because of some other reason. Loading