From b50cdde5f009ca1e8a548605c8b364d860110b67 Mon Sep 17 00:00:00 2001 From: Tobias Thierer Date: Mon, 19 Oct 2020 19:37:30 +0100 Subject: [PATCH] BackupManagerService: Make new behavior conditional on ChangeId. Base CL ag/12885739 introduced unconditional enforcement of the BACKUP permission for callers of BackupManagerService.isBackupServiceActive() in the service, but dropped the enforcement on the app process side (BackupManager). This CL makes the behavior change conditional on a compat ChangeId. Bug: 158482162 Test: Manually checked that an app similar to the code sample from http://b/158482162#comment1 can reproduce the behavior. This is true both before the base CL and after this CL, when the app targets an old SDK version (26). Test: Checked that both (a) before this CL, (b) after this CL where the change is manually enabled for the app via the below commands, the app runs into a SecurityException instead: $ adb shell am compat enable 158482162 com.example.tester $ adb shell dumpsys platform_compat | grep 158482162 ChangeId(158482162; name=IS_BACKUP_SERVICE_ACTIVE_ENFORCE_PERMISSION_IN_SERVICE; enableSinceTargetSdk=31; packageOverrides={com.example.tester=true}) Change-Id: I58e5d2a0b438296137fd76720636c8fdce740ded Merged-In: I58e5d2a0b438296137fd76720636c8fdce740ded (cherry picked from commit 7671f0d95c7e92a2342ed05a053a38d8aa16a17f) --- .../android/app/backup/BackupManager.java | 20 +++++++++++++++++++ .../server/backup/BackupManagerService.java | 9 +++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java index 56e9c36fe4b4c..acaea5fdd6098 100644 --- a/core/java/android/app/backup/BackupManager.java +++ b/core/java/android/app/backup/BackupManager.java @@ -21,10 +21,14 @@ import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.TestApi; +import android.app.compat.CompatChanges; +import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledAfter; import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Message; @@ -391,6 +395,17 @@ public class BackupManager { return false; } + + /** + * If this change is enabled, the {@code BACKUP} permission needed for + * {@code isBackupServiceActive()} will be enforced on the service end + * rather than client-side in {@link BackupManager}. + * @hide + */ + @ChangeId + @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.R) + public static final long IS_BACKUP_SERVICE_ACTIVE_ENFORCE_PERMISSION_IN_SERVICE = 158482162; + /** * Report whether the backup mechanism is currently active. * When it is inactive, the device will not perform any backup operations, nor will it @@ -401,6 +416,11 @@ public class BackupManager { @SystemApi @RequiresPermission(android.Manifest.permission.BACKUP) public boolean isBackupServiceActive(UserHandle user) { + if (!CompatChanges.isChangeEnabled( + IS_BACKUP_SERVICE_ACTIVE_ENFORCE_PERMISSION_IN_SERVICE)) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, + "isBackupServiceActive"); + } checkServiceBinder(); if (sService != null) { try { diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index 19ada753f33d7..445297a839ba6 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -30,6 +30,7 @@ import android.app.backup.IBackupObserver; import android.app.backup.IFullBackupRestoreObserver; import android.app.backup.IRestoreSession; import android.app.backup.ISelectBackupTransportCallback; +import android.app.compat.CompatChanges; import android.app.job.JobParameters; import android.app.job.JobScheduler; import android.app.job.JobService; @@ -506,8 +507,12 @@ public class BackupManagerService extends IBackupManager.Stub { */ @Override public boolean isBackupServiceActive(int userId) { - mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, - "isBackupServiceActive"); + int callingUid = Binder.getCallingUid(); + if (CompatChanges.isChangeEnabled( + BackupManager.IS_BACKUP_SERVICE_ACTIVE_ENFORCE_PERMISSION_IN_SERVICE, callingUid)) { + mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, + "isBackupServiceActive"); + } synchronized (mStateLock) { return !mGlobalDisable && isBackupActivatedForUser(userId); }