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
diff --git a/services/core/java/com/android/server/pm/Computer.java b/services/core/java/com/android/server/pm/Computer.java
index 1bce0cd..4ab58b7 100644
--- a/services/core/java/com/android/server/pm/Computer.java
+++ b/services/core/java/com/android/server/pm/Computer.java
@@ -217,11 +217,16 @@
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);
boolean shouldFilterApplication(@Nullable PackageStateInternal ps, int callingUid,
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 ed1be24..c5661a3 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 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 @@
}
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 @@
}
/**
- * @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,13 +2765,22 @@
final ArraySet<PackageStateInternal> packageStates =
(ArraySet<PackageStateInternal>) 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 b3b9846..22f6c0a 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 @@
@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;