From 6628f4e7b86cc5878c004981e4913430dffe2937 Mon Sep 17 00:00:00 2001 From: Danny Epstein Date: Fri, 12 Feb 2021 16:36:58 -0800 Subject: [PATCH] DO NOT MERGE Chk QUERY_ALL_PACKAGES when resolving When resolving intents, check whether QUERY_ALL_PACKAGES permission was granted, as well as whether the caller is a system process, to determine whether filtering may occur. This allows prefered activity records to be deleted by non-system processes if they have QUERY_ALL_PACKAGES permission. Before this change, configuring a custom activity resolver doesn't work properly because it's not allowed to delete the record of the last chosen app before writing a new record. Test: Create a custom activity resolver, choose an app just once, choose another app next time, verify it defaults to the other app after that. Bug: 173543124 Change-Id: If4dfea0374352b5e903d15e87e90baf012abf40b --- .../server/pm/PackageManagerService.java | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 40723e073ba10..b54706e7b6bed 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -20,6 +20,7 @@ import static android.Manifest.permission.DELETE_PACKAGES; import static android.Manifest.permission.INSTALL_PACKAGES; import static android.Manifest.permission.MANAGE_DEVICE_ADMINS; import static android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS; +import static android.Manifest.permission.QUERY_ALL_PACKAGES; import static android.Manifest.permission.READ_EXTERNAL_STORAGE; import static android.Manifest.permission.REQUEST_DELETE_PACKAGES; import static android.Manifest.permission.SET_HARMFUL_APP_WARNINGS; @@ -28,6 +29,7 @@ import static android.app.AppOpsManager.MODE_ALLOWED; import static android.app.AppOpsManager.MODE_DEFAULT; import static android.app.AppOpsManager.MODE_IGNORED; import static android.content.Intent.ACTION_MAIN; +import static android.content.Intent.CATEGORY_BROWSABLE; import static android.content.Intent.CATEGORY_DEFAULT; import static android.content.Intent.CATEGORY_HOME; import static android.content.Intent.EXTRA_LONG_VERSION_CODE; @@ -35,8 +37,6 @@ import static android.content.Intent.EXTRA_PACKAGE_NAME; import static android.content.Intent.EXTRA_VERSION_CODE; import static android.content.pm.PackageManager.CERT_INPUT_RAW_X509; import static android.content.pm.PackageManager.CERT_INPUT_SHA256; -import static android.content.Intent.CATEGORY_BROWSABLE; -import static android.content.Intent.CATEGORY_DEFAULT; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED; @@ -6456,14 +6456,10 @@ public class PackageManagerService extends IPackageManager.Stub true /*allowDynamicSplits*/); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); - final boolean queryMayBeFiltered = - UserHandle.getAppId(filterCallingUid) >= Process.FIRST_APPLICATION_UID - && !resolveForStart; - final ResolveInfo bestChoice = chooseBestActivity( intent, resolvedType, flags, privateResolveFlags, query, userId, - queryMayBeFiltered); + queryMayBeFiltered(filterCallingUid, resolveForStart)); final boolean nonBrowserOnly = (privateResolveFlags & PackageManagerInternal.RESOLVE_NON_BROWSER_ONLY) != 0; if (nonBrowserOnly && bestChoice != null && bestChoice.handleAllWebDataURI) { @@ -6475,6 +6471,25 @@ public class PackageManagerService extends IPackageManager.Stub } } + /** + * Returns whether the query may be filtered to packages which are visible to the caller. + * Filtering occurs except in the following cases: + * + * + * @param filterCallingUid the UID of the calling application + * @param queryForStart whether query is to start an app + * @return whether filtering may occur + */ + private boolean queryMayBeFiltered(int filterCallingUid, boolean queryForStart) { + return UserHandle.getAppId(filterCallingUid) >= Process.FIRST_APPLICATION_UID + && checkUidPermission(QUERY_ALL_PACKAGES, filterCallingUid) != PERMISSION_GRANTED + && !queryForStart; + } + @Override public ResolveInfo findPersistentPreferredActivity(Intent intent, int userId) { if (!UserHandle.isSameApp(Binder.getCallingUid(), Process.SYSTEM_UID)) { @@ -6840,7 +6855,7 @@ public class PackageManagerService extends IPackageManager.Stub boolean removeMatches, boolean debug, int userId) { return findPreferredActivityNotLocked( intent, resolvedType, flags, query, priority, always, removeMatches, debug, userId, - UserHandle.getAppId(Binder.getCallingUid()) >= Process.FIRST_APPLICATION_UID); + queryMayBeFiltered(Binder.getCallingUid(), /* queryForStart= */ false)); } // TODO: handle preferred activities missing while user has amnesia