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
This commit is contained in:
Rhed Jao
2022-04-15 14:55:36 +08:00
parent 9fcc8c501b
commit c13b915317
3 changed files with 40 additions and 14 deletions

View File

@@ -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);

View File

@@ -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<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.

View File

@@ -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;