Loading cmds/installd/InstalldNativeService.cpp +49 −26 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ #include <sys/xattr.h> #include <unistd.h> #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/properties.h> #include <android-base/scopeguard.h> Loading Loading @@ -80,6 +81,8 @@ namespace installd { // An uuid used in unit tests. static constexpr const char* kTestUuid = "TEST"; static constexpr const mode_t kRollbackFolderMode = 0700; static constexpr const char* kCpPath = "/system/bin/cp"; static constexpr const char* kXattrDefault = "user.default"; Loading Loading @@ -784,8 +787,8 @@ static int32_t copy_directory_recursive(const char* from, const char* to) { binder::Status InstalldNativeService::snapshotAppData( const std::unique_ptr<std::string>& volumeUuid, const std::string& packageName, int32_t user, int32_t storageFlags, int64_t* _aidl_return) { const std::string& packageName, int32_t user, int32_t snapshotId, int32_t storageFlags, int64_t* _aidl_return) { ENFORCE_UID(AID_SYSTEM); CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(volumeUuid); CHECK_ARGUMENT_PACKAGE_NAME(packageName); Loading @@ -802,16 +805,19 @@ binder::Status InstalldNativeService::snapshotAppData( bool clear_ce_on_exit = false; bool clear_de_on_exit = false; auto deleter = [&clear_ce_on_exit, &clear_de_on_exit, &volume_uuid, &user, &package_name] { auto deleter = [&clear_ce_on_exit, &clear_de_on_exit, &volume_uuid, &user, &package_name, &snapshotId] { if (clear_de_on_exit) { auto to = create_data_misc_de_rollback_package_path(volume_uuid, user, package_name); auto to = create_data_misc_de_rollback_package_path(volume_uuid, user, snapshotId, package_name); if (delete_dir_contents(to.c_str(), 1, nullptr) != 0) { LOG(WARNING) << "Failed to delete app data snapshot: " << to; } } if (clear_ce_on_exit) { auto to = create_data_misc_ce_rollback_package_path(volume_uuid, user, package_name); auto to = create_data_misc_ce_rollback_package_path(volume_uuid, user, snapshotId, package_name); if (delete_dir_contents(to.c_str(), 1, nullptr) != 0) { LOG(WARNING) << "Failed to delete app data snapshot: " << to; } Loading Loading @@ -847,15 +853,21 @@ binder::Status InstalldNativeService::snapshotAppData( if (storageFlags & FLAG_STORAGE_DE) { auto from = create_data_user_de_package_path(volume_uuid, user, package_name); auto to = create_data_misc_de_rollback_path(volume_uuid, user); auto to = create_data_misc_de_rollback_path(volume_uuid, user, snapshotId); auto rollback_package_path = create_data_misc_de_rollback_package_path(volume_uuid, user, snapshotId, package_name); int rd = delete_dir_contents(to, true /* ignore_if_missing */); if (rd != 0) { res = error(rd, "Failed clearing existing snapshot " + to); return res; int rc = create_dir_if_needed(to.c_str(), kRollbackFolderMode); if (rc != 0) { return error(rc, "Failed to create folder " + to); } int rc = copy_directory_recursive(from.c_str(), to.c_str()); rc = delete_dir_contents(rollback_package_path, true /* ignore_if_missing */); if (rc != 0) { return error(rc, "Failed clearing existing snapshot " + rollback_package_path); } rc = copy_directory_recursive(from.c_str(), to.c_str()); if (rc != 0) { res = error(rc, "Failed copying " + from + " to " + to); clear_de_on_exit = true; Loading @@ -865,15 +877,21 @@ binder::Status InstalldNativeService::snapshotAppData( if (storageFlags & FLAG_STORAGE_CE) { auto from = create_data_user_ce_package_path(volume_uuid, user, package_name); auto to = create_data_misc_ce_rollback_path(volume_uuid, user); auto to = create_data_misc_ce_rollback_path(volume_uuid, user, snapshotId); auto rollback_package_path = create_data_misc_ce_rollback_package_path(volume_uuid, user, snapshotId, package_name); int rd = delete_dir_contents(to, true /* ignore_if_missing */); if (rd != 0) { res = error(rd, "Failed clearing existing snapshot " + to); return res; int rc = create_dir_if_needed(to.c_str(), kRollbackFolderMode); if (rc != 0) { return error(rc, "Failed to create folder " + to); } int rc = copy_directory_recursive(from.c_str(), to.c_str()); rc = delete_dir_contents(rollback_package_path, true /* ignore_if_missing */); if (rc != 0) { return error(rc, "Failed clearing existing snapshot " + rollback_package_path); } rc = copy_directory_recursive(from.c_str(), to.c_str()); if (rc != 0) { res = error(rc, "Failed copying " + from + " to " + to); clear_ce_on_exit = true; Loading @@ -881,7 +899,7 @@ binder::Status InstalldNativeService::snapshotAppData( } if (_aidl_return != nullptr) { auto ce_snapshot_path = create_data_misc_ce_rollback_package_path(volume_uuid, user, package_name); snapshotId, package_name); rc = get_path_inode(ce_snapshot_path, reinterpret_cast<ino_t*>(_aidl_return)); if (rc != 0) { res = error(rc, "Failed to get_path_inode for " + ce_snapshot_path); Loading @@ -896,8 +914,8 @@ binder::Status InstalldNativeService::snapshotAppData( binder::Status InstalldNativeService::restoreAppDataSnapshot( const std::unique_ptr<std::string>& volumeUuid, const std::string& packageName, const int32_t appId, const int64_t ceDataInode, const std::string& seInfo, const int32_t user, int32_t storageFlags) { const int32_t appId, const std::string& seInfo, const int32_t user, const int32_t snapshotId, int32_t storageFlags) { ENFORCE_UID(AID_SYSTEM); CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(volumeUuid); CHECK_ARGUMENT_PACKAGE_NAME(packageName); Loading @@ -907,9 +925,9 @@ binder::Status InstalldNativeService::restoreAppDataSnapshot( const char* package_name = packageName.c_str(); auto from_ce = create_data_misc_ce_rollback_package_path(volume_uuid, user, package_name); user, snapshotId, package_name); auto from_de = create_data_misc_de_rollback_package_path(volume_uuid, user, package_name); user, snapshotId, package_name); const bool needs_ce_rollback = (storageFlags & FLAG_STORAGE_CE) && (access(from_ce.c_str(), F_OK) == 0); Loading @@ -926,7 +944,11 @@ binder::Status InstalldNativeService::restoreAppDataSnapshot( // app with no data in those cases is arguably better than leaving the app // with mismatched / stale data. LOG(INFO) << "Clearing app data for " << packageName << " to restore snapshot."; binder::Status res = clearAppData(volumeUuid, packageName, user, storageFlags, ceDataInode); // It's fine to pass 0 as ceDataInode here, because restoreAppDataSnapshot // can only be called when user unlocks the phone, meaning that CE user data // is decrypted. binder::Status res = clearAppData(volumeUuid, packageName, user, storageFlags, 0 /* ceDataInode */); if (!res.isOk()) { return res; } Loading Loading @@ -962,7 +984,8 @@ binder::Status InstalldNativeService::restoreAppDataSnapshot( binder::Status InstalldNativeService::destroyAppDataSnapshot( const std::unique_ptr<std::string> &volumeUuid, const std::string& packageName, const int32_t user, const int64_t ceSnapshotInode, int32_t storageFlags) { const int32_t user, const int64_t ceSnapshotInode, const int32_t snapshotId, int32_t storageFlags) { ENFORCE_UID(AID_SYSTEM); CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(volumeUuid); CHECK_ARGUMENT_PACKAGE_NAME(packageName); Loading @@ -973,7 +996,7 @@ binder::Status InstalldNativeService::destroyAppDataSnapshot( if (storageFlags & FLAG_STORAGE_DE) { auto de_snapshot_path = create_data_misc_de_rollback_package_path(volume_uuid, user, package_name); user, snapshotId, package_name); int res = delete_dir_contents_and_dir(de_snapshot_path, true /* ignore_if_missing */); if (res != 0) { Loading @@ -983,7 +1006,7 @@ binder::Status InstalldNativeService::destroyAppDataSnapshot( if (storageFlags & FLAG_STORAGE_CE) { auto ce_snapshot_path = create_data_misc_ce_rollback_package_path(volume_uuid, user, package_name, ceSnapshotInode); user, snapshotId, package_name, ceSnapshotInode); int res = delete_dir_contents_and_dir(ce_snapshot_path, true /* ignore_if_missing */); if (res != 0) { return error(res, "Failed clearing snapshot " + ce_snapshot_path); Loading cmds/installd/InstalldNativeService.h +5 −5 Original line number Diff line number Diff line Loading @@ -61,14 +61,14 @@ public: binder::Status fixupAppData(const std::unique_ptr<std::string>& uuid, int32_t flags); binder::Status snapshotAppData(const std::unique_ptr<std::string>& volumeUuid, const std::string& packageName, const int32_t user, int32_t storageFlags, int64_t* _aidl_return); const std::string& packageName, const int32_t user, const int32_t snapshotId, int32_t storageFlags, int64_t* _aidl_return); binder::Status restoreAppDataSnapshot(const std::unique_ptr<std::string>& volumeUuid, const std::string& packageName, const int32_t appId, const int64_t ceDataInode, const std::string& seInfo, const int32_t user, int32_t storageFlags); const std::string& packageName, const int32_t appId, const std::string& seInfo, const int32_t user, const int32_t snapshotId, int32_t storageFlags); binder::Status destroyAppDataSnapshot(const std::unique_ptr<std::string> &volumeUuid, const std::string& packageName, const int32_t user, const int64_t ceSnapshotInode, int32_t storageFlags); const int32_t snapshotId, int32_t storageFlags); 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 −3 Original line number Diff line number Diff line Loading @@ -106,11 +106,11 @@ interface IInstalld { @nullable @utf8InCpp String dexMetadata); long snapshotAppData(@nullable @utf8InCpp String uuid, in @utf8InCpp String packageName, int userId, int storageFlags); int userId, int snapshotId, int storageFlags); void restoreAppDataSnapshot(@nullable @utf8InCpp String uuid, in @utf8InCpp String packageName, int appId, long ceDataInode, @utf8InCpp String seInfo, int user, int storageflags); 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 storageFlags); int userId, long ceSnapshotInode, int snapshotId, int storageFlags); const int FLAG_STORAGE_DE = 0x1; const int FLAG_STORAGE_CE = 0x2; Loading cmds/installd/tests/installd_service_test.cpp +168 −225 File changed.Preview size limit exceeded, changes collapsed. Show changes cmds/installd/tests/installd_utils_test.cpp +68 −38 Original line number Diff line number Diff line Loading @@ -546,56 +546,86 @@ TEST_F(UtilsTest, MatchExtension_Invalid) { } TEST_F(UtilsTest, TestRollbackPaths) { EXPECT_EQ("/data/misc_ce/0/rollback/com.foo", create_data_misc_ce_rollback_package_path(nullptr, 0, "com.foo")); EXPECT_EQ("/data/misc_ce/10/rollback/com.foo", create_data_misc_ce_rollback_package_path(nullptr, 10, "com.foo")); EXPECT_EQ("/data/misc_de/0/rollback/com.foo", create_data_misc_de_rollback_package_path(nullptr, 0, "com.foo")); EXPECT_EQ("/data/misc_de/10/rollback/com.foo", create_data_misc_de_rollback_package_path(nullptr, 10, "com.foo")); EXPECT_EQ("/data/misc_ce/0/rollback", create_data_misc_ce_rollback_path(nullptr, 0)); EXPECT_EQ("/data/misc_ce/10/rollback", create_data_misc_ce_rollback_path(nullptr, 10)); EXPECT_EQ("/data/misc_de/0/rollback", create_data_misc_de_rollback_path(nullptr, 0)); EXPECT_EQ("/data/misc_de/10/rollback", create_data_misc_de_rollback_path(nullptr, 10)); EXPECT_EQ("/data/misc_ce/0/rollback/com.foo", create_data_misc_ce_rollback_package_path(nullptr, 0, "com.foo", 0)); EXPECT_EQ("/data/misc_ce/0/rollback/com.foo", create_data_misc_ce_rollback_package_path(nullptr, 0, "com.foo", 239)); auto rollback_ce_package_path = create_data_misc_ce_rollback_package_path(nullptr, 0, "com.foo"); auto deleter = [&rollback_ce_package_path]() { delete_dir_contents_and_dir(rollback_ce_package_path, true /* ignore_if_missing */); EXPECT_EQ("/data/misc_ce/0/rollback/239/com.foo", create_data_misc_ce_rollback_package_path(nullptr, 0, 239, "com.foo")); EXPECT_EQ("/data/misc_ce/10/rollback/37/com.foo", create_data_misc_ce_rollback_package_path(nullptr, 10, 37, "com.foo")); EXPECT_EQ("/data/misc_de/0/rollback/73/com.foo", create_data_misc_de_rollback_package_path(nullptr, 0, 73, "com.foo")); EXPECT_EQ("/data/misc_de/10/rollback/13/com.foo", create_data_misc_de_rollback_package_path(nullptr, 10, 13, "com.foo")); EXPECT_EQ("/data/misc_ce/0/rollback/57", create_data_misc_ce_rollback_path(nullptr, 0, 57)); EXPECT_EQ("/data/misc_ce/10/rollback/1543", create_data_misc_ce_rollback_path(nullptr, 10, 1543)); EXPECT_EQ("/data/misc_de/0/rollback/43", create_data_misc_de_rollback_path(nullptr, 0, 43)); EXPECT_EQ("/data/misc_de/10/rollback/41", create_data_misc_de_rollback_path(nullptr, 10, 41)); EXPECT_EQ("/data/misc_ce/0/rollback/17/com.foo", create_data_misc_ce_rollback_package_path(nullptr, 0, 17, "com.foo", 0)); EXPECT_EQ("/data/misc_ce/0/rollback/19/com.foo", create_data_misc_ce_rollback_package_path(nullptr, 0, 19, "com.foo", 239)); auto rollback_ce_path = create_data_misc_ce_rollback_path(nullptr, 0, 53); auto rollback_ce_package_path = create_data_misc_ce_rollback_package_path(nullptr, 0, 53, "com.foo"); auto deleter = [&rollback_ce_path]() { delete_dir_contents_and_dir(rollback_ce_path, true /* ignore_if_missing */); }; auto scope_guard = android::base::make_scope_guard(deleter); ASSERT_NE(-1, mkdir(rollback_ce_package_path.c_str(), 700)); EXPECT_NE(-1, mkdir(rollback_ce_path.c_str(), 700)); EXPECT_NE(-1, mkdir(rollback_ce_package_path.c_str(), 700)); ino_t ce_data_inode; ASSERT_EQ(0, get_path_inode(rollback_ce_package_path, &ce_data_inode)); EXPECT_EQ(0, get_path_inode(rollback_ce_package_path, &ce_data_inode)); EXPECT_EQ("/data/misc_ce/0/rollback/com.foo", create_data_misc_ce_rollback_package_path(nullptr, 0, "com.foo", ce_data_inode)); EXPECT_EQ("/data/misc_ce/0/rollback/53/com.foo", create_data_misc_ce_rollback_package_path(nullptr, 0, 53, "com.foo", ce_data_inode)); // Check that path defined by inode is picked even if it's not the same as // the fallback one. EXPECT_EQ("/data/misc_ce/0/rollback/com.foo", create_data_misc_ce_rollback_package_path(nullptr, 0, "com.bar", ce_data_inode)); EXPECT_EQ("/data/misc_ce/0/rollback/53/com.foo", create_data_misc_ce_rollback_package_path(nullptr, 0, 53, "com.bar", ce_data_inode)); // These last couple of cases are never exercised in production because we // only snapshot apps in the primary data partition. Exercise them here for // the sake of completeness. EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/misc_ce/0/rollback/com.example", create_data_misc_ce_rollback_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, "com.example")); EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/misc_de/0/rollback/com.example", create_data_misc_de_rollback_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, "com.example")); EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/misc_ce/0/rollback/7/com.example", create_data_misc_ce_rollback_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, 7, "com.example")); EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/misc_de/0/rollback/11/com.example", create_data_misc_de_rollback_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, 11, "com.example")); } TEST_F(UtilsTest, TestCreateDirIfNeeded) { system("mkdir -p /data/local/tmp/user/0"); auto deleter = [&]() { delete_dir_contents_and_dir("/data/local/tmp/user/0", true /* ignore_if_missing */); }; auto scope_guard = android::base::make_scope_guard(deleter); // Create folder and check it's permissions. ASSERT_EQ(0, create_dir_if_needed("/data/local/tmp/user/0/foo", 0700)); struct stat st; ASSERT_EQ(0, stat("/data/local/tmp/user/0/foo", &st)); ASSERT_EQ(0700, st.st_mode & ALLPERMS); // Check that create_dir_if_needed is no-op if folder already exists with // correct permissions. ASSERT_EQ(0, create_dir_if_needed("/data/local/tmp/user/0/foo", 0700)); // Check -1 is returned if folder exists but with different permissions. ASSERT_EQ(-1, create_dir_if_needed("/data/local/tmp/user/0/foo", 0750)); // Check that call fails if parent doesn't exist. ASSERT_NE(0, create_dir_if_needed("/data/local/tmp/user/0/bar/baz", 0700)); } } // namespace installd Loading Loading
cmds/installd/InstalldNativeService.cpp +49 −26 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ #include <sys/xattr.h> #include <unistd.h> #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/properties.h> #include <android-base/scopeguard.h> Loading Loading @@ -80,6 +81,8 @@ namespace installd { // An uuid used in unit tests. static constexpr const char* kTestUuid = "TEST"; static constexpr const mode_t kRollbackFolderMode = 0700; static constexpr const char* kCpPath = "/system/bin/cp"; static constexpr const char* kXattrDefault = "user.default"; Loading Loading @@ -784,8 +787,8 @@ static int32_t copy_directory_recursive(const char* from, const char* to) { binder::Status InstalldNativeService::snapshotAppData( const std::unique_ptr<std::string>& volumeUuid, const std::string& packageName, int32_t user, int32_t storageFlags, int64_t* _aidl_return) { const std::string& packageName, int32_t user, int32_t snapshotId, int32_t storageFlags, int64_t* _aidl_return) { ENFORCE_UID(AID_SYSTEM); CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(volumeUuid); CHECK_ARGUMENT_PACKAGE_NAME(packageName); Loading @@ -802,16 +805,19 @@ binder::Status InstalldNativeService::snapshotAppData( bool clear_ce_on_exit = false; bool clear_de_on_exit = false; auto deleter = [&clear_ce_on_exit, &clear_de_on_exit, &volume_uuid, &user, &package_name] { auto deleter = [&clear_ce_on_exit, &clear_de_on_exit, &volume_uuid, &user, &package_name, &snapshotId] { if (clear_de_on_exit) { auto to = create_data_misc_de_rollback_package_path(volume_uuid, user, package_name); auto to = create_data_misc_de_rollback_package_path(volume_uuid, user, snapshotId, package_name); if (delete_dir_contents(to.c_str(), 1, nullptr) != 0) { LOG(WARNING) << "Failed to delete app data snapshot: " << to; } } if (clear_ce_on_exit) { auto to = create_data_misc_ce_rollback_package_path(volume_uuid, user, package_name); auto to = create_data_misc_ce_rollback_package_path(volume_uuid, user, snapshotId, package_name); if (delete_dir_contents(to.c_str(), 1, nullptr) != 0) { LOG(WARNING) << "Failed to delete app data snapshot: " << to; } Loading Loading @@ -847,15 +853,21 @@ binder::Status InstalldNativeService::snapshotAppData( if (storageFlags & FLAG_STORAGE_DE) { auto from = create_data_user_de_package_path(volume_uuid, user, package_name); auto to = create_data_misc_de_rollback_path(volume_uuid, user); auto to = create_data_misc_de_rollback_path(volume_uuid, user, snapshotId); auto rollback_package_path = create_data_misc_de_rollback_package_path(volume_uuid, user, snapshotId, package_name); int rd = delete_dir_contents(to, true /* ignore_if_missing */); if (rd != 0) { res = error(rd, "Failed clearing existing snapshot " + to); return res; int rc = create_dir_if_needed(to.c_str(), kRollbackFolderMode); if (rc != 0) { return error(rc, "Failed to create folder " + to); } int rc = copy_directory_recursive(from.c_str(), to.c_str()); rc = delete_dir_contents(rollback_package_path, true /* ignore_if_missing */); if (rc != 0) { return error(rc, "Failed clearing existing snapshot " + rollback_package_path); } rc = copy_directory_recursive(from.c_str(), to.c_str()); if (rc != 0) { res = error(rc, "Failed copying " + from + " to " + to); clear_de_on_exit = true; Loading @@ -865,15 +877,21 @@ binder::Status InstalldNativeService::snapshotAppData( if (storageFlags & FLAG_STORAGE_CE) { auto from = create_data_user_ce_package_path(volume_uuid, user, package_name); auto to = create_data_misc_ce_rollback_path(volume_uuid, user); auto to = create_data_misc_ce_rollback_path(volume_uuid, user, snapshotId); auto rollback_package_path = create_data_misc_ce_rollback_package_path(volume_uuid, user, snapshotId, package_name); int rd = delete_dir_contents(to, true /* ignore_if_missing */); if (rd != 0) { res = error(rd, "Failed clearing existing snapshot " + to); return res; int rc = create_dir_if_needed(to.c_str(), kRollbackFolderMode); if (rc != 0) { return error(rc, "Failed to create folder " + to); } int rc = copy_directory_recursive(from.c_str(), to.c_str()); rc = delete_dir_contents(rollback_package_path, true /* ignore_if_missing */); if (rc != 0) { return error(rc, "Failed clearing existing snapshot " + rollback_package_path); } rc = copy_directory_recursive(from.c_str(), to.c_str()); if (rc != 0) { res = error(rc, "Failed copying " + from + " to " + to); clear_ce_on_exit = true; Loading @@ -881,7 +899,7 @@ binder::Status InstalldNativeService::snapshotAppData( } if (_aidl_return != nullptr) { auto ce_snapshot_path = create_data_misc_ce_rollback_package_path(volume_uuid, user, package_name); snapshotId, package_name); rc = get_path_inode(ce_snapshot_path, reinterpret_cast<ino_t*>(_aidl_return)); if (rc != 0) { res = error(rc, "Failed to get_path_inode for " + ce_snapshot_path); Loading @@ -896,8 +914,8 @@ binder::Status InstalldNativeService::snapshotAppData( binder::Status InstalldNativeService::restoreAppDataSnapshot( const std::unique_ptr<std::string>& volumeUuid, const std::string& packageName, const int32_t appId, const int64_t ceDataInode, const std::string& seInfo, const int32_t user, int32_t storageFlags) { const int32_t appId, const std::string& seInfo, const int32_t user, const int32_t snapshotId, int32_t storageFlags) { ENFORCE_UID(AID_SYSTEM); CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(volumeUuid); CHECK_ARGUMENT_PACKAGE_NAME(packageName); Loading @@ -907,9 +925,9 @@ binder::Status InstalldNativeService::restoreAppDataSnapshot( const char* package_name = packageName.c_str(); auto from_ce = create_data_misc_ce_rollback_package_path(volume_uuid, user, package_name); user, snapshotId, package_name); auto from_de = create_data_misc_de_rollback_package_path(volume_uuid, user, package_name); user, snapshotId, package_name); const bool needs_ce_rollback = (storageFlags & FLAG_STORAGE_CE) && (access(from_ce.c_str(), F_OK) == 0); Loading @@ -926,7 +944,11 @@ binder::Status InstalldNativeService::restoreAppDataSnapshot( // app with no data in those cases is arguably better than leaving the app // with mismatched / stale data. LOG(INFO) << "Clearing app data for " << packageName << " to restore snapshot."; binder::Status res = clearAppData(volumeUuid, packageName, user, storageFlags, ceDataInode); // It's fine to pass 0 as ceDataInode here, because restoreAppDataSnapshot // can only be called when user unlocks the phone, meaning that CE user data // is decrypted. binder::Status res = clearAppData(volumeUuid, packageName, user, storageFlags, 0 /* ceDataInode */); if (!res.isOk()) { return res; } Loading Loading @@ -962,7 +984,8 @@ binder::Status InstalldNativeService::restoreAppDataSnapshot( binder::Status InstalldNativeService::destroyAppDataSnapshot( const std::unique_ptr<std::string> &volumeUuid, const std::string& packageName, const int32_t user, const int64_t ceSnapshotInode, int32_t storageFlags) { const int32_t user, const int64_t ceSnapshotInode, const int32_t snapshotId, int32_t storageFlags) { ENFORCE_UID(AID_SYSTEM); CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(volumeUuid); CHECK_ARGUMENT_PACKAGE_NAME(packageName); Loading @@ -973,7 +996,7 @@ binder::Status InstalldNativeService::destroyAppDataSnapshot( if (storageFlags & FLAG_STORAGE_DE) { auto de_snapshot_path = create_data_misc_de_rollback_package_path(volume_uuid, user, package_name); user, snapshotId, package_name); int res = delete_dir_contents_and_dir(de_snapshot_path, true /* ignore_if_missing */); if (res != 0) { Loading @@ -983,7 +1006,7 @@ binder::Status InstalldNativeService::destroyAppDataSnapshot( if (storageFlags & FLAG_STORAGE_CE) { auto ce_snapshot_path = create_data_misc_ce_rollback_package_path(volume_uuid, user, package_name, ceSnapshotInode); user, snapshotId, package_name, ceSnapshotInode); int res = delete_dir_contents_and_dir(ce_snapshot_path, true /* ignore_if_missing */); if (res != 0) { return error(res, "Failed clearing snapshot " + ce_snapshot_path); Loading
cmds/installd/InstalldNativeService.h +5 −5 Original line number Diff line number Diff line Loading @@ -61,14 +61,14 @@ public: binder::Status fixupAppData(const std::unique_ptr<std::string>& uuid, int32_t flags); binder::Status snapshotAppData(const std::unique_ptr<std::string>& volumeUuid, const std::string& packageName, const int32_t user, int32_t storageFlags, int64_t* _aidl_return); const std::string& packageName, const int32_t user, const int32_t snapshotId, int32_t storageFlags, int64_t* _aidl_return); binder::Status restoreAppDataSnapshot(const std::unique_ptr<std::string>& volumeUuid, const std::string& packageName, const int32_t appId, const int64_t ceDataInode, const std::string& seInfo, const int32_t user, int32_t storageFlags); const std::string& packageName, const int32_t appId, const std::string& seInfo, const int32_t user, const int32_t snapshotId, int32_t storageFlags); binder::Status destroyAppDataSnapshot(const std::unique_ptr<std::string> &volumeUuid, const std::string& packageName, const int32_t user, const int64_t ceSnapshotInode, int32_t storageFlags); const int32_t snapshotId, int32_t storageFlags); 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 −3 Original line number Diff line number Diff line Loading @@ -106,11 +106,11 @@ interface IInstalld { @nullable @utf8InCpp String dexMetadata); long snapshotAppData(@nullable @utf8InCpp String uuid, in @utf8InCpp String packageName, int userId, int storageFlags); int userId, int snapshotId, int storageFlags); void restoreAppDataSnapshot(@nullable @utf8InCpp String uuid, in @utf8InCpp String packageName, int appId, long ceDataInode, @utf8InCpp String seInfo, int user, int storageflags); 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 storageFlags); int userId, long ceSnapshotInode, int snapshotId, int storageFlags); const int FLAG_STORAGE_DE = 0x1; const int FLAG_STORAGE_CE = 0x2; Loading
cmds/installd/tests/installd_service_test.cpp +168 −225 File changed.Preview size limit exceeded, changes collapsed. Show changes
cmds/installd/tests/installd_utils_test.cpp +68 −38 Original line number Diff line number Diff line Loading @@ -546,56 +546,86 @@ TEST_F(UtilsTest, MatchExtension_Invalid) { } TEST_F(UtilsTest, TestRollbackPaths) { EXPECT_EQ("/data/misc_ce/0/rollback/com.foo", create_data_misc_ce_rollback_package_path(nullptr, 0, "com.foo")); EXPECT_EQ("/data/misc_ce/10/rollback/com.foo", create_data_misc_ce_rollback_package_path(nullptr, 10, "com.foo")); EXPECT_EQ("/data/misc_de/0/rollback/com.foo", create_data_misc_de_rollback_package_path(nullptr, 0, "com.foo")); EXPECT_EQ("/data/misc_de/10/rollback/com.foo", create_data_misc_de_rollback_package_path(nullptr, 10, "com.foo")); EXPECT_EQ("/data/misc_ce/0/rollback", create_data_misc_ce_rollback_path(nullptr, 0)); EXPECT_EQ("/data/misc_ce/10/rollback", create_data_misc_ce_rollback_path(nullptr, 10)); EXPECT_EQ("/data/misc_de/0/rollback", create_data_misc_de_rollback_path(nullptr, 0)); EXPECT_EQ("/data/misc_de/10/rollback", create_data_misc_de_rollback_path(nullptr, 10)); EXPECT_EQ("/data/misc_ce/0/rollback/com.foo", create_data_misc_ce_rollback_package_path(nullptr, 0, "com.foo", 0)); EXPECT_EQ("/data/misc_ce/0/rollback/com.foo", create_data_misc_ce_rollback_package_path(nullptr, 0, "com.foo", 239)); auto rollback_ce_package_path = create_data_misc_ce_rollback_package_path(nullptr, 0, "com.foo"); auto deleter = [&rollback_ce_package_path]() { delete_dir_contents_and_dir(rollback_ce_package_path, true /* ignore_if_missing */); EXPECT_EQ("/data/misc_ce/0/rollback/239/com.foo", create_data_misc_ce_rollback_package_path(nullptr, 0, 239, "com.foo")); EXPECT_EQ("/data/misc_ce/10/rollback/37/com.foo", create_data_misc_ce_rollback_package_path(nullptr, 10, 37, "com.foo")); EXPECT_EQ("/data/misc_de/0/rollback/73/com.foo", create_data_misc_de_rollback_package_path(nullptr, 0, 73, "com.foo")); EXPECT_EQ("/data/misc_de/10/rollback/13/com.foo", create_data_misc_de_rollback_package_path(nullptr, 10, 13, "com.foo")); EXPECT_EQ("/data/misc_ce/0/rollback/57", create_data_misc_ce_rollback_path(nullptr, 0, 57)); EXPECT_EQ("/data/misc_ce/10/rollback/1543", create_data_misc_ce_rollback_path(nullptr, 10, 1543)); EXPECT_EQ("/data/misc_de/0/rollback/43", create_data_misc_de_rollback_path(nullptr, 0, 43)); EXPECT_EQ("/data/misc_de/10/rollback/41", create_data_misc_de_rollback_path(nullptr, 10, 41)); EXPECT_EQ("/data/misc_ce/0/rollback/17/com.foo", create_data_misc_ce_rollback_package_path(nullptr, 0, 17, "com.foo", 0)); EXPECT_EQ("/data/misc_ce/0/rollback/19/com.foo", create_data_misc_ce_rollback_package_path(nullptr, 0, 19, "com.foo", 239)); auto rollback_ce_path = create_data_misc_ce_rollback_path(nullptr, 0, 53); auto rollback_ce_package_path = create_data_misc_ce_rollback_package_path(nullptr, 0, 53, "com.foo"); auto deleter = [&rollback_ce_path]() { delete_dir_contents_and_dir(rollback_ce_path, true /* ignore_if_missing */); }; auto scope_guard = android::base::make_scope_guard(deleter); ASSERT_NE(-1, mkdir(rollback_ce_package_path.c_str(), 700)); EXPECT_NE(-1, mkdir(rollback_ce_path.c_str(), 700)); EXPECT_NE(-1, mkdir(rollback_ce_package_path.c_str(), 700)); ino_t ce_data_inode; ASSERT_EQ(0, get_path_inode(rollback_ce_package_path, &ce_data_inode)); EXPECT_EQ(0, get_path_inode(rollback_ce_package_path, &ce_data_inode)); EXPECT_EQ("/data/misc_ce/0/rollback/com.foo", create_data_misc_ce_rollback_package_path(nullptr, 0, "com.foo", ce_data_inode)); EXPECT_EQ("/data/misc_ce/0/rollback/53/com.foo", create_data_misc_ce_rollback_package_path(nullptr, 0, 53, "com.foo", ce_data_inode)); // Check that path defined by inode is picked even if it's not the same as // the fallback one. EXPECT_EQ("/data/misc_ce/0/rollback/com.foo", create_data_misc_ce_rollback_package_path(nullptr, 0, "com.bar", ce_data_inode)); EXPECT_EQ("/data/misc_ce/0/rollback/53/com.foo", create_data_misc_ce_rollback_package_path(nullptr, 0, 53, "com.bar", ce_data_inode)); // These last couple of cases are never exercised in production because we // only snapshot apps in the primary data partition. Exercise them here for // the sake of completeness. EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/misc_ce/0/rollback/com.example", create_data_misc_ce_rollback_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, "com.example")); EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/misc_de/0/rollback/com.example", create_data_misc_de_rollback_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, "com.example")); EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/misc_ce/0/rollback/7/com.example", create_data_misc_ce_rollback_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, 7, "com.example")); EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/misc_de/0/rollback/11/com.example", create_data_misc_de_rollback_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, 11, "com.example")); } TEST_F(UtilsTest, TestCreateDirIfNeeded) { system("mkdir -p /data/local/tmp/user/0"); auto deleter = [&]() { delete_dir_contents_and_dir("/data/local/tmp/user/0", true /* ignore_if_missing */); }; auto scope_guard = android::base::make_scope_guard(deleter); // Create folder and check it's permissions. ASSERT_EQ(0, create_dir_if_needed("/data/local/tmp/user/0/foo", 0700)); struct stat st; ASSERT_EQ(0, stat("/data/local/tmp/user/0/foo", &st)); ASSERT_EQ(0700, st.st_mode & ALLPERMS); // Check that create_dir_if_needed is no-op if folder already exists with // correct permissions. ASSERT_EQ(0, create_dir_if_needed("/data/local/tmp/user/0/foo", 0700)); // Check -1 is returned if folder exists but with different permissions. ASSERT_EQ(-1, create_dir_if_needed("/data/local/tmp/user/0/foo", 0750)); // Check that call fails if parent doesn't exist. ASSERT_NE(0, create_dir_if_needed("/data/local/tmp/user/0/bar/baz", 0700)); } } // namespace installd Loading