From 7671f0d95c7e92a2342ed05a053a38d8aa16a17f 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 --- .../android/app/backup/BackupManager.java | 20 +++++++++++++++++++ .../server/backup/BackupManagerService.java | 10 +++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java index 50b1b3d4b8456..44a4b78e1afaf 100644 --- a/core/java/android/app/backup/BackupManager.java +++ b/core/java/android/app/backup/BackupManager.java @@ -21,10 +21,14 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; +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; @@ -435,6 +439,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 @@ -445,6 +460,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 250d834921e4c..ac6ed440093d8 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -32,6 +32,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; @@ -61,7 +62,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.DumpUtils; import com.android.server.SystemConfig; import com.android.server.SystemService; -import com.android.server.SystemService.TargetUser; import com.android.server.backup.utils.RandomAccessFileUtils; import java.io.File; @@ -509,8 +509,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); }