From 35252ce57883a4e1be629e1eab98b6755c4fc5c3 Mon Sep 17 00:00:00 2001 From: Achim Thesmann Date: Thu, 4 May 2023 05:15:55 +0000 Subject: [PATCH] Use calling package name for CompatChange. For shared UID the calling package name is require to determine the correct target SDK. Change-Id: I45038a16702558898f5dd749292ed76e995878ec Test: atest BackgroundActivityLaunchTest Bug: 281124275 --- .../server/am/PendingIntentRecord.java | 19 ++++---- .../server/wm/ActivityTaskManagerService.java | 45 +++++++++++++++++-- .../wm/BackgroundActivityStartController.java | 14 ++++-- .../server/wm/WindowProcessController.java | 6 +++ .../server/wm/ActivityStarterTests.java | 2 +- 5 files changed, 70 insertions(+), 16 deletions(-) diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java index cb26c134f74ab..04db6c02d0712 100644 --- a/services/core/java/com/android/server/am/PendingIntentRecord.java +++ b/services/core/java/com/android/server/am/PendingIntentRecord.java @@ -348,21 +348,22 @@ public final class PendingIntentRecord extends IIntentSender.Stub { * use caller's BAL permission. */ public static BackgroundStartPrivileges getBackgroundStartPrivilegesAllowedByCaller( - @Nullable ActivityOptions activityOptions, int callingUid) { + @Nullable ActivityOptions activityOptions, int callingUid, + @Nullable String callingPackage) { if (activityOptions == null) { // since the ActivityOptions were not created by the app itself, determine the default // for the app - return getDefaultBackgroundStartPrivileges(callingUid); + return getDefaultBackgroundStartPrivileges(callingUid, callingPackage); } return getBackgroundStartPrivilegesAllowedByCaller(activityOptions.toBundle(), - callingUid); + callingUid, callingPackage); } private static BackgroundStartPrivileges getBackgroundStartPrivilegesAllowedByCaller( - @Nullable Bundle options, int callingUid) { + @Nullable Bundle options, int callingUid, @Nullable String callingPackage) { if (options == null || !options.containsKey( ActivityOptions.KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED)) { - return getDefaultBackgroundStartPrivileges(callingUid); + return getDefaultBackgroundStartPrivileges(callingUid, callingPackage); } return options.getBoolean(ActivityOptions.KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED) ? BackgroundStartPrivileges.ALLOW_BAL @@ -381,8 +382,10 @@ public final class PendingIntentRecord extends IIntentSender.Stub { android.Manifest.permission.LOG_COMPAT_CHANGE }) public static BackgroundStartPrivileges getDefaultBackgroundStartPrivileges( - int callingUid) { - boolean isChangeEnabledForApp = CompatChanges.isChangeEnabled( + int callingUid, @Nullable String callingPackage) { + boolean isChangeEnabledForApp = callingPackage != null ? CompatChanges.isChangeEnabled( + DEFAULT_RESCIND_BAL_PRIVILEGES_FROM_PENDING_INTENT_SENDER, callingPackage, + UserHandle.getUserHandleForUid(callingUid)) : CompatChanges.isChangeEnabled( DEFAULT_RESCIND_BAL_PRIVILEGES_FROM_PENDING_INTENT_SENDER, callingUid); if (isChangeEnabledForApp) { return BackgroundStartPrivileges.ALLOW_FGS; @@ -638,7 +641,7 @@ public final class PendingIntentRecord extends IIntentSender.Stub { // temporarily allow receivers and services to open activities from background if the // PendingIntent.send() caller was foreground at the time of sendInner() call if (uid != callingUid && controller.mAtmInternal.isUidForeground(callingUid)) { - return getBackgroundStartPrivilegesAllowedByCaller(options, callingUid); + return getBackgroundStartPrivilegesAllowedByCaller(options, callingUid, null); } return BackgroundStartPrivileges.NONE; } diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index f35343c987117..9af6471e93cf1 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -5334,15 +5334,54 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { return null; } - WindowProcessController getProcessController(int pid, int uid) { + /** + * Returns the {@link WindowProcessController} for the app process for the given uid and pid. + * + * If no such {@link WindowProcessController} is found, it does not belong to an app, or the + * pid does not match the uid {@code null} is returned. + */ + @Nullable WindowProcessController getProcessController(int pid, int uid) { + return UserHandle.isApp(uid) ? getProcessControllerInternal(pid, uid) : null; + } + + /** + * Returns the {@link WindowProcessController} for the given uid and pid. + * + * If no such {@link WindowProcessController} is found or the pid does not match the uid + * {@code null} is returned. + */ + private @Nullable WindowProcessController getProcessControllerInternal(int pid, int uid) { final WindowProcessController proc = mProcessMap.getProcess(pid); - if (proc == null) return null; - if (UserHandle.isApp(uid) && proc.mUid == uid) { + if (proc == null) { + return null; + } + if (proc.mUid == uid) { return proc; } return null; } + /** + * Returns the package name if (and only if) the package name can be uniquely determined. + * Otherwise returns {@code null}. + * + * The provided pid must match the provided uid, otherwise this also returns null. + */ + @Nullable String getPackageNameIfUnique(int uid, int pid) { + WindowProcessController processController = getProcessControllerInternal(pid, uid); + if (processController == null) { + Slog.w(TAG, "callingPackage for (uid=" + uid + ", pid=" + pid + ") has no WPC"); + return null; + } + List realCallingPackages = processController.getPackageList(); + if (realCallingPackages.size() == 1) { + return realCallingPackages.get(0); + } + Slog.w(TAG, "callingPackage for (uid=" + uid + ", pid=" + pid + ") is ambiguous: " + + realCallingPackages); + return null; + } + /** A uid is considered to be foreground if it has a visible non-toast window. */ @HotPath(caller = HotPath.START_SERVICE) boolean hasActiveVisibleWindow(int uid) { diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java index 1a3d6730fe203..f1c7b7fe717a9 100644 --- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java +++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java @@ -180,7 +180,8 @@ public class BackgroundActivityStartController { Intent intent, ActivityOptions checkedOptions) { return checkBackgroundActivityStart(callingUid, callingPid, callingPackage, - realCallingUid, realCallingPid, callerApp, originatingPendingIntent, + realCallingUid, realCallingPid, + callerApp, originatingPendingIntent, backgroundStartPrivileges, intent, checkedOptions) == BAL_BLOCK; } @@ -288,11 +289,13 @@ public class BackgroundActivityStartController { } } + String realCallingPackage = mService.getPackageNameIfUnique(realCallingUid, realCallingPid); + // Legacy behavior allows to use caller foreground state to bypass BAL restriction. // The options here are the options passed by the sender and not those on the intent. final BackgroundStartPrivileges balAllowedByPiSender = PendingIntentRecord.getBackgroundStartPrivilegesAllowedByCaller( - checkedOptions, realCallingUid); + checkedOptions, realCallingUid, realCallingPackage); final boolean logVerdictChangeByPiDefaultChange = checkedOptions == null || checkedOptions.getPendingIntentBackgroundActivityStartMode() @@ -452,8 +455,11 @@ public class BackgroundActivityStartController { // If we are here, it means all exemptions not based on PI sender failed, so we'll block // unless resultIfPiSenderAllowsBal is an allow and the PI sender allows BAL - String realCallingPackage = callingUid == realCallingUid ? callingPackage : - mService.mContext.getPackageManager().getNameForUid(realCallingUid); + if (realCallingPackage == null) { + realCallingPackage = (callingUid == realCallingUid ? callingPackage : + mService.mContext.getPackageManager().getNameForUid(realCallingUid)) + + "[debugOnly]"; + } String stateDumpLog = " [callingPackage: " + callingPackage + "; callingUid: " + callingUid diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java index dbd9e4b8ea68a..3672820c13ad9 100644 --- a/services/core/java/com/android/server/wm/WindowProcessController.java +++ b/services/core/java/com/android/server/wm/WindowProcessController.java @@ -721,6 +721,12 @@ public class WindowProcessController extends ConfigurationContainer getPackageList() { + synchronized (mPkgList) { + return new ArrayList<>(mPkgList); + } + } + void addActivityIfNeeded(ActivityRecord r) { // even if we already track this activity, note down that it has been launched setLastActivityLaunchTime(r); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java index 95fc0faf50ba9..235e553bb126d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java @@ -928,7 +928,7 @@ public class ActivityStarterTests extends WindowTestsBase { anyInt(), anyInt())); doReturn(BackgroundStartPrivileges.allowBackgroundActivityStarts(null)).when( () -> PendingIntentRecord.getBackgroundStartPrivilegesAllowedByCaller( - anyObject(), anyInt())); + anyObject(), anyInt(), anyObject())); runAndVerifyBackgroundActivityStartsSubtest( "allowed_notAborted", false, UNIMPORTANT_UID, false, PROCESS_STATE_BOUND_TOP,