diff options
author | 2024-02-01 14:08:47 +0000 | |
---|---|---|
committer | 2024-02-22 19:00:57 +0000 | |
commit | 3f2eaedce0cb3427bc7825cec5c4500050d2cc77 (patch) | |
tree | 658d67cff6a71745e568d0c8e716a3fd2e2b6fba /services/backup/java | |
parent | ea33379e80e8148dae47d5989356b01a89720617 (diff) |
Add a V->U restore allowlist/denylist
A package is eligible for V to U downgrade restore if either:
- The package has restoreAnyVersion set to false and is part of the V to U allowst
- The package has restoreAnyVersion set to true and is not part of the denylist
Bug : 324233962
Test: atest PerformUnifiedRestoreTaskTest
Manual:check that a package with restoreanyversion=true
is not restored if in the denylist,
check that a package with restoreanyversion=false
is restored if in the allowlist
Change-Id: Id1cf031c593730132ebe24ecab0ffc4a3f87920e
Diffstat (limited to 'services/backup/java')
-rw-r--r-- | services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java | 4 | ||||
-rw-r--r-- | services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java | 181 |
2 files changed, 132 insertions, 53 deletions
diff --git a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java index 9f0deea503cf..6e98e68601f6 100644 --- a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java +++ b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java @@ -177,6 +177,10 @@ public class PackageManagerBackupAgent extends BackupAgent { return mHasMetadata; } + public int getSourceSdk() { + return mStoredSdkVersion; + } + public Metadata getRestoredMetadata(String packageName) { if (mRestoredSignatures == null) { Slog.w(TAG, "getRestoredMetadata() before metadata read!"); diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java index d85dd879e21d..e666442af9c9 100644 --- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java +++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java @@ -44,6 +44,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManagerInternal; +import android.os.Build; import android.os.Bundle; import android.os.Message; import android.os.ParcelFileDescriptor; @@ -51,6 +52,7 @@ import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; +import android.provider.Settings; import android.util.EventLog; import android.util.Slog; @@ -82,6 +84,7 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.Set; @@ -158,6 +161,12 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { // When finished call listener private final OnTaskFinishedListener mListener; + // List of packages that support V-> U downgrade but do not have RestoreAnyVersion set to true. + private List<String> mVToUAllowlist; + + // List of packages that have RestoreAnyVersion set to true but do not support V-> U downgrade. + private List<String> mVToUDenylist; + // Key/value: bookkeeping about staged data and files for agent access private File mBackupDataName; private File mStageName; @@ -172,7 +181,8 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { @VisibleForTesting PerformUnifiedRestoreTask( UserBackupManagerService backupManagerService, - TransportConnection transportConnection) { + TransportConnection transportConnection, + String vToUAllowlist, String vToUDenyList) { mListener = null; mAgentTimeoutParameters = null; mOperationStorage = null; @@ -183,6 +193,8 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { mBackupEligibilityRules = null; this.backupManagerService = backupManagerService; mBackupManagerMonitorEventSender = new BackupManagerMonitorEventSender(/* monitor= */ null); + mVToUAllowlist = createVToUList(vToUAllowlist); + mVToUDenylist = createVToUList(vToUDenyList); } // This task can assume that the wakelock is properly held for it and doesn't have to worry @@ -223,6 +235,18 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { backupManagerService.getAgentTimeoutParameters(), "Timeout parameters cannot be null"); mBackupEligibilityRules = backupEligibilityRules; + mVToUAllowlist = + createVToUList( + Settings.Secure.getStringForUser( + backupManagerService.getContext().getContentResolver(), + Settings.Secure.V_TO_U_RESTORE_ALLOWLIST, + mUserId)); + mVToUDenylist = + createVToUList( + Settings.Secure.getStringForUser( + backupManagerService.getContext().getContentResolver(), + Settings.Secure.V_TO_U_RESTORE_DENYLIST, + mUserId)); if (targetPackage != null) { // Single package restore @@ -636,60 +660,29 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { // Data is from a "newer" version of the app than we have currently // installed. If the app has not declared that it is prepared to // handle this case, we do not attempt the restore. - if ((mCurrentPackage.applicationInfo.flags - & ApplicationInfo.FLAG_RESTORE_ANY_VERSION) - == 0) { - String message = - "Source version " - + metaInfo.versionCode - + " > installed version " - + mCurrentPackage.getLongVersionCode(); - Slog.w(TAG, "Package " + pkgName + ": " + message); - Bundle monitoringExtras = - mBackupManagerMonitorEventSender.putMonitoringExtra( - null, - BackupManagerMonitor.EXTRA_LOG_RESTORE_VERSION, - metaInfo.versionCode); - monitoringExtras = - mBackupManagerMonitorEventSender.putMonitoringExtra( - monitoringExtras, - BackupManagerMonitor.EXTRA_LOG_RESTORE_ANYWAY, - false); - monitoringExtras = addRestoreOperationTypeToEvent(monitoringExtras); - mBackupManagerMonitorEventSender.monitorEvent( - BackupManagerMonitor.LOG_EVENT_ID_RESTORE_VERSION_HIGHER, - mCurrentPackage, - BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, - monitoringExtras); - EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, pkgName, message); - nextState = UnifiedRestoreState.RUNNING_QUEUE; - return; + if (mIsSystemRestore + && isVToUDowngrade(mPmAgent.getSourceSdk(), android.os.Build.VERSION.SDK_INT)) { + if (isPackageEligibleForVToURestore(mCurrentPackage)) { + Slog.i(TAG, "Package " + pkgName + + " is eligible for V to U downgrade scenario"); + } else { + String message = "Package not eligible for V to U downgrade scenario"; + Slog.i(TAG, pkgName + " : " + message); + EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, pkgName, message); + nextState = UnifiedRestoreState.RUNNING_QUEUE; + return; + } } else { - if (DEBUG) { - Slog.v( - TAG, - "Source version " - + metaInfo.versionCode - + " > installed version " - + mCurrentPackage.getLongVersionCode() - + " but restoreAnyVersion"); + if ((mCurrentPackage.applicationInfo.flags + & ApplicationInfo.FLAG_RESTORE_ANY_VERSION) + == 0) { + // Downgrade scenario with RestoreAnyVersion flag off + logDowngradeScenario(/* isRestoreAnyVersion */ false, metaInfo); + nextState = UnifiedRestoreState.RUNNING_QUEUE; + return; + } else { + logDowngradeScenario(/* isRestoreAnyVersion */ true, metaInfo); } - Bundle monitoringExtras = - mBackupManagerMonitorEventSender.putMonitoringExtra( - null, - BackupManagerMonitor.EXTRA_LOG_RESTORE_VERSION, - metaInfo.versionCode); - monitoringExtras = - mBackupManagerMonitorEventSender.putMonitoringExtra( - monitoringExtras, - BackupManagerMonitor.EXTRA_LOG_RESTORE_ANYWAY, - true); - monitoringExtras = addRestoreOperationTypeToEvent(monitoringExtras); - mBackupManagerMonitorEventSender.monitorEvent( - BackupManagerMonitor.LOG_EVENT_ID_RESTORE_VERSION_HIGHER, - mCurrentPackage, - BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, - monitoringExtras); } } @@ -1673,4 +1666,86 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { return mBackupManagerMonitorEventSender.putMonitoringExtra( extras, BackupManagerMonitor.EXTRA_LOG_OPERATION_TYPE, RESTORE); } + + // checks the sdk of the target/source device for a B&R operation. + // system components can opt in/out of V->U restore via allowlists. All other apps are + // not impacted + @SuppressWarnings("AndroidFrameworkCompatChange") + @VisibleForTesting + protected boolean isVToUDowngrade(int sourceSdk, int targetSdk) { + // We assume that if the source sdk is greater than U then the source is V. + return Flags.enableVToURestoreForSystemComponentsInAllowlist() + && (sourceSdk > Build.VERSION_CODES.UPSIDE_DOWN_CAKE) + && (targetSdk == Build.VERSION_CODES.UPSIDE_DOWN_CAKE); + } + + @VisibleForTesting + protected List<String> createVToUList(@Nullable String listString) { + // The allowlist/denylist is stored as a comma-separated list of package names + List<String> list = new ArrayList<>(); + if (listString != null) { + list = Arrays.asList(listString.split(",")); + } + return list; + } + + @VisibleForTesting + protected boolean isPackageEligibleForVToURestore(PackageInfo mCurrentPackage) { + // A package is eligible for V to U downgrade restore if either: + // - The package has restoreAnyVersion set to false and is part of the V to U allowlist + // (and not in the denylist) + // - The package has restoreAnyVersion set to true and is not part of the denylist + if (mVToUDenylist.contains(mCurrentPackage.packageName)){ + return false; + } else if ((mCurrentPackage.applicationInfo.flags + & ApplicationInfo.FLAG_RESTORE_ANY_VERSION) + == 0) { + // package has restoreAnyVersion set to false + return mVToUAllowlist.contains(mCurrentPackage.packageName); + } else { + // package has restoreAnyVersion set to true and is nor in denylist + return true; + } + } + + private void logDowngradeScenario(boolean isRestoreAnyVersion, Metadata metaInfo) { + Bundle monitoringExtras = + mBackupManagerMonitorEventSender.putMonitoringExtra( + null, + BackupManagerMonitor.EXTRA_LOG_RESTORE_VERSION, + metaInfo.versionCode); + String message; + if (isRestoreAnyVersion) { + monitoringExtras = + mBackupManagerMonitorEventSender.putMonitoringExtra( + monitoringExtras, + BackupManagerMonitor.EXTRA_LOG_RESTORE_ANYWAY, + true); + message = "Source version " + + metaInfo.versionCode + + " > installed version " + + mCurrentPackage.getLongVersionCode() + + " but restoreAnyVersion"; + } else { + monitoringExtras = + mBackupManagerMonitorEventSender.putMonitoringExtra( + monitoringExtras, + BackupManagerMonitor.EXTRA_LOG_RESTORE_ANYWAY, + false); + message = "Source version " + + metaInfo.versionCode + + " > installed version " + + mCurrentPackage.getLongVersionCode(); + EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, mCurrentPackage.packageName, + message); + } + Slog.i(TAG, "Package " + mCurrentPackage.packageName + ": " + message); + monitoringExtras = addRestoreOperationTypeToEvent(monitoringExtras); + mBackupManagerMonitorEventSender.monitorEvent( + BackupManagerMonitor.LOG_EVENT_ID_RESTORE_VERSION_HIGHER, + mCurrentPackage, + BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, + monitoringExtras); + } + } |