From e6393c95716e5ad9bfb52931eb6e4f23f7640f01 Mon Sep 17 00:00:00 2001 From: Todd Kennedy Date: Tue, 16 May 2017 15:47:01 -0700 Subject: [PATCH] Filter package related info This is one of many CLs to go through the PackageManager API surface and filter access depending upon the requested information and the caller. In this change, we filter ActivityInfo, ApplicationInfo and PackageInfo. Bug: 35871369 Test: bit FrameworksCoreTests:android.content.pm.PackageManagerTests Test: cts-tradefed run commandAndExit cts-dev -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.EphemeralTest Change-Id: Iaefd73f912ab1c7e1844e72625388455f783a362 --- packages/SystemUI/AndroidManifest.xml | 3 + .../pm/EphemeralResolverConnection.java | 2 +- .../server/pm/PackageManagerService.java | 123 ++++++++++++++---- 3 files changed, 105 insertions(+), 23 deletions(-) diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 5460304e86784..79b02a5286e02 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -187,6 +187,9 @@ + + + + * Access may be limited based upon whether the calling or target applications + * are instant applications. + * + * @see #canAccessInstantApps(int) + */ + private boolean filterAppAccessLPr(@NonNull PackageSetting ps, int callingUid, + @Nullable ComponentName component, boolean componentVisibleToInstantApp, int userId) { + // if we're in an isolated process, get the real calling UID + if (Process.isIsolated(callingUid)) { + callingUid = mIsolatedOwners.get(callingUid); + } + // if the target and caller are the same application, don't filter + if (isCallerSameApp(ps.name, callingUid)) { + return false; + } + final String instantAppPkgName = getInstantAppPackageName(callingUid); + final boolean callerIsInstantApp = instantAppPkgName != null; + if (callerIsInstantApp) { + // request for a specific component; if it hasn't been explicitly exposed, filter + if (component != null) { + return !componentVisibleToInstantApp; + } + // request for application; if no components have been explicitly exposed, filter + return !ps.pkg.visibleToInstantApps; + } + if (ps.getInstantApp(userId)) { + // caller can see all components of all instant applications, don't filter + if (canAccessInstantApps(callingUid)) { + return false; + } + // request for a specific instant application component, filter + if (component != null) { + return true; + } + // request for an instant application; if the caller hasn't been granted access, filter + return !mInstantAppRegistry.isInstantAccessGranted( + userId, UserHandle.getAppId(callingUid), ps.appId); + } + return false; + } + + /** + * @see #filterAppAccessLPr(PackageSetting, int, ComponentName, boolean, int) + */ + private boolean filterAppAccessLPr(@NonNull PackageSetting ps, int callingUid, int userId) { + return filterAppAccessLPr(ps, callingUid, null, false, userId); + } + private boolean filterSharedLibPackageLPr(@Nullable PackageSetting ps, int uid, int userId, int flags) { // Callers can access only the libs they depend on, otherwise they need to explicitly @@ -3890,6 +3952,9 @@ public class PackageManagerService extends IPackageManager.Stub if (filterSharedLibPackageLPr(ps, uid, userId, flags)) { return null; } + if (filterAppAccessLPr(ps, uid, userId)) { + return null; + } if (ps.pkg == null) { final PackageInfo pInfo = generatePackageInfo(ps, flags, userId); if (pInfo != null) { @@ -3931,6 +3996,9 @@ public class PackageManagerService extends IPackageManager.Stub if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) { return null; } + if (filterAppAccessLPr(ps, Binder.getCallingUid(), userId)) { + return null; + } // Note: isEnabledLP() does not apply here - always return info ApplicationInfo ai = PackageParser.generateApplicationInfo( p, flags, ps.readUserState(userId), userId); @@ -4230,15 +4298,15 @@ public class PackageManagerService extends IPackageManager.Stub */ int updateFlagsForResolve(int flags, int userId, Intent intent, int callingUid) { return updateFlagsForResolve(flags, userId, intent, callingUid, - false /*includeInstantApps*/, false /*onlyExposedExplicitly*/); + false /*wantInstantApps*/, false /*onlyExposedExplicitly*/); } int updateFlagsForResolve(int flags, int userId, Intent intent, int callingUid, - boolean includeInstantApps) { + boolean wantInstantApps) { return updateFlagsForResolve(flags, userId, intent, callingUid, - includeInstantApps, false /*onlyExposedExplicitly*/); + wantInstantApps, false /*onlyExposedExplicitly*/); } int updateFlagsForResolve(int flags, int userId, Intent intent, int callingUid, - boolean includeInstantApps, boolean onlyExposedExplicitly) { + boolean wantInstantApps, boolean onlyExposedExplicitly) { // Safe mode means we shouldn't match any third-party components if (mSafeMode) { flags |= PackageManager.MATCH_SYSTEM_ONLY; @@ -4251,18 +4319,11 @@ public class PackageManagerService extends IPackageManager.Stub flags |= PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY; flags |= PackageManager.MATCH_INSTANT; } else { - // Otherwise, prevent leaking ephemeral components - final boolean isSpecialProcess = - callingUid == Process.SYSTEM_UID - || callingUid == Process.SHELL_UID - || callingUid == 0; final boolean allowMatchInstant = - (includeInstantApps + (wantInstantApps && Intent.ACTION_VIEW.equals(intent.getAction()) && hasWebURI(intent)) - || isSpecialProcess - || mContext.checkCallingOrSelfPermission( - android.Manifest.permission.ACCESS_INSTANT_APPS) == PERMISSION_GRANTED; + || canAccessInstantApps(callingUid); flags &= ~(PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY | PackageManager.MATCH_EXPLICITLY_VISIBLE_ONLY); if (!allowMatchInstant) { @@ -4293,8 +4354,9 @@ public class PackageManagerService extends IPackageManager.Stub @Override public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) { if (!sUserManager.exists(userId)) return null; + final int callingUid = Binder.getCallingUid(); flags = updateFlagsForComponent(flags, userId, component); - enforceCrossUserPermission(Binder.getCallingUid(), userId, + enforceCrossUserPermission(callingUid, userId, false /* requireFullPermission */, false /* checkShell */, "get activity info"); synchronized (mPackages) { PackageParser.Activity a = mActivities.mActivities.get(component); @@ -4303,6 +4365,11 @@ public class PackageManagerService extends IPackageManager.Stub if (a != null && mSettings.isEnabledAndMatchLPr(a.info, flags, userId)) { PackageSetting ps = mSettings.mPackages.get(component.getPackageName()); if (ps == null) return null; + final boolean visibleToInstantApp = + (a.info.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0; + if (filterAppAccessLPr(ps, callingUid, component, visibleToInstantApp, userId)) { + return null; + } return generateActivityInfo(a, flags, ps.readUserState(userId), userId); } if (mResolveComponentName.equals(component)) { @@ -4467,8 +4534,9 @@ public class PackageManagerService extends IPackageManager.Stub @Override public ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) { if (!sUserManager.exists(userId)) return null; + final int callingUid = Binder.getCallingUid(); flags = updateFlagsForComponent(flags, userId, component); - enforceCrossUserPermission(Binder.getCallingUid(), userId, + enforceCrossUserPermission(callingUid, userId, false /* requireFullPermission */, false /* checkShell */, "get service info"); synchronized (mPackages) { PackageParser.Service s = mServices.mServices.get(component); @@ -4477,6 +4545,11 @@ public class PackageManagerService extends IPackageManager.Stub if (s != null && mSettings.isEnabledAndMatchLPr(s.info, flags, userId)) { PackageSetting ps = mSettings.mPackages.get(component.getPackageName()); if (ps == null) return null; + final boolean visibleToInstantApp = + (s.info.flags & ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0; + if (filterAppAccessLPr(ps, callingUid, component, visibleToInstantApp, userId)) { + return null; + } ServiceInfo si = PackageParser.generateServiceInfo(s, flags, ps.readUserState(userId), userId); if (si != null) { @@ -4491,8 +4564,9 @@ public class PackageManagerService extends IPackageManager.Stub @Override public ProviderInfo getProviderInfo(ComponentName component, int flags, int userId) { if (!sUserManager.exists(userId)) return null; + final int callingUid = Binder.getCallingUid(); flags = updateFlagsForComponent(flags, userId, component); - enforceCrossUserPermission(Binder.getCallingUid(), userId, + enforceCrossUserPermission(callingUid, userId, false /* requireFullPermission */, false /* checkShell */, "get provider info"); synchronized (mPackages) { PackageParser.Provider p = mProviders.mProviders.get(component); @@ -4501,6 +4575,11 @@ public class PackageManagerService extends IPackageManager.Stub if (p != null && mSettings.isEnabledAndMatchLPr(p.info, flags, userId)) { PackageSetting ps = mSettings.mPackages.get(component.getPackageName()); if (ps == null) return null; + final boolean visibleToInstantApp = + (p.info.flags & ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0; + if (filterAppAccessLPr(ps, callingUid, component, visibleToInstantApp, userId)) { + return null; + } ProviderInfo pi = PackageParser.generateProviderInfo(p, flags, ps.readUserState(userId), userId); if (pi != null) {