From c13b9153175f77d6a2bfe59940455e7355f3bb53 Mon Sep 17 00:00:00 2001 From: Rhed Jao Date: Fri, 15 Apr 2022 14:55:36 +0800 Subject: [PATCH] Add filtering uninstalled package flag to the shouldFilterApplication A lot of APIs in PackageManager return different results between an unknown package and the package that is uninstalled in the current user. An app can detect package's existence via this side-channel leakage. To fix these issues, this CL adds an extra flag to the shouldFilterApplication() to support filtering uninstalled package. APIs with the vulnerability can enable the flag when they invoke application access filtering. (The fixes for those APIs are separated into other CLs.) Bug: 214394643 Test: atest AppEnumerationTests Change-Id: I2875765b631c247539955c1d5dc864798e54896c --- .../java/com/android/server/pm/Computer.java | 5 +++ .../com/android/server/pm/ComputerEngine.java | 44 ++++++++++++++----- .../server/pm/PackageManagerService.java | 5 +-- 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/services/core/java/com/android/server/pm/Computer.java b/services/core/java/com/android/server/pm/Computer.java index 1bce0cd2e4bae..4ab58b7947e26 100644 --- a/services/core/java/com/android/server/pm/Computer.java +++ b/services/core/java/com/android/server/pm/Computer.java @@ -215,6 +215,9 @@ public interface Computer extends PackageDataSnapshot { boolean isInstantApp(String packageName, int userId); boolean isInstantAppInternal(String packageName, @UserIdInt int userId, int callingUid); boolean isSameProfileGroup(@UserIdInt int callerUserId, @UserIdInt int userId); + boolean shouldFilterApplication(@Nullable PackageStateInternal ps, int callingUid, + @Nullable ComponentName component, @PackageManager.ComponentType int componentType, + int userId, boolean filterUninstall); boolean shouldFilterApplication(@Nullable PackageStateInternal ps, int callingUid, @Nullable ComponentName component, @PackageManager.ComponentType int componentType, int userId); @@ -222,6 +225,8 @@ public interface Computer extends PackageDataSnapshot { int userId); boolean shouldFilterApplication(@NonNull SharedUserSetting sus, int callingUid, int userId); + boolean shouldFilterApplicationIncludingUninstalled(@Nullable PackageStateInternal ps, + int callingUid, int userId); int checkUidPermission(String permName, int uid); int getPackageUidInternal(String packageName, long flags, int userId, int callingUid); long updateFlagsForApplication(long flags, int userId); diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java index ed1be2478a9be..c5661a3dc253f 100644 --- a/services/core/java/com/android/server/pm/ComputerEngine.java +++ b/services/core/java/com/android/server/pm/ComputerEngine.java @@ -2675,7 +2675,7 @@ public class ComputerEngine implements Computer { */ public final boolean shouldFilterApplication(@Nullable PackageStateInternal ps, int callingUid, @Nullable ComponentName component, - @PackageManager.ComponentType int componentType, int userId) { + @PackageManager.ComponentType int componentType, int userId, boolean filterUninstall) { if (Process.isSdkSandboxUid(callingUid)) { int clientAppUid = Process.getAppUidForSdkSandboxUid(callingUid); // SDK sandbox should be able to see it's client app @@ -2689,9 +2689,11 @@ public class ComputerEngine implements Computer { } final String instantAppPkgName = getInstantAppPackageName(callingUid); final boolean callerIsInstantApp = instantAppPkgName != null; - if (ps == null) { - // pretend the application exists, but, needs to be filtered - return callerIsInstantApp; + if (ps == null + || (filterUninstall && !ps.getUserStateOrDefault(userId).isInstalled())) { + // If caller is instant app and ps is null, pretend the application exists, + // but, needs to be filtered + return (callerIsInstantApp || filterUninstall); } // if the target and caller are the same application, don't filter if (isCallerSameApp(ps.getPackageName(), callingUid)) { @@ -2736,15 +2738,26 @@ public class ComputerEngine implements Computer { } /** - * @see #shouldFilterApplication(PackageStateInternal, int, ComponentName, int, int) + * @see #shouldFilterApplication(PackageStateInternal, int, ComponentName, int, int, boolean) */ - public final boolean shouldFilterApplication( - @Nullable PackageStateInternal ps, int callingUid, int userId) { - return shouldFilterApplication(ps, callingUid, null, TYPE_UNKNOWN, userId); + public final boolean shouldFilterApplication(@Nullable PackageStateInternal ps, + int callingUid, @Nullable ComponentName component, + @PackageManager.ComponentType int componentType, int userId) { + return shouldFilterApplication( + ps, callingUid, component, componentType, userId, false /* filterUninstall */); } /** - * @see #shouldFilterApplication(PackageStateInternal, int, ComponentName, int, int) + * @see #shouldFilterApplication(PackageStateInternal, int, ComponentName, int, int, boolean) + */ + public final boolean shouldFilterApplication( + @Nullable PackageStateInternal ps, int callingUid, int userId) { + return shouldFilterApplication( + ps, callingUid, null, TYPE_UNKNOWN, userId, false /* filterUninstall */); + } + + /** + * @see #shouldFilterApplication(PackageStateInternal, int, ComponentName, int, int, boolean) */ public final boolean shouldFilterApplication(@NonNull SharedUserSetting sus, int callingUid, int userId) { @@ -2752,12 +2765,21 @@ public class ComputerEngine implements Computer { final ArraySet packageStates = (ArraySet) sus.getPackageStates(); for (int index = packageStates.size() - 1; index >= 0 && filterApp; index--) { - filterApp &= shouldFilterApplication(packageStates.valueAt(index), - callingUid, /* component */ null, TYPE_UNKNOWN, userId); + filterApp &= shouldFilterApplication(packageStates.valueAt(index), callingUid, + null /* component */, TYPE_UNKNOWN, userId, false /* filterUninstall */); } return filterApp; } + /** + * @see #shouldFilterApplication(PackageStateInternal, int, ComponentName, int, int, boolean) + */ + public final boolean shouldFilterApplicationIncludingUninstalled( + @Nullable PackageStateInternal ps, int callingUid, int userId) { + return shouldFilterApplication( + ps, callingUid, null, TYPE_UNKNOWN, userId, true /* filterUninstall */); + } + /** * Verification statuses are ordered from the worse to the best, except for * INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER, which is the worse. diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index b3b9846f7e8df..22f6c0afa7af4 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -6617,9 +6617,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService @UserIdInt int userId) { PackageStateInternal packageState = computer.getPackageStateInternal(packageName, callingUid); - if (packageState == null - || computer.shouldFilterApplication(packageState, callingUid, userId) - || !packageState.getUserStateOrDefault(userId).isInstalled()) { + if (computer.shouldFilterApplicationIncludingUninstalled( + packageState, callingUid, userId)) { return null; } else { return packageState;