Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c06c0306 authored by Todd Kennedy's avatar Todd Kennedy
Browse files

Filter instant app content providers

Only expose the correct content providers depending upon which
component defines/exposes them.

Change-Id: I283c787165e33d9515068487f83de6d28616b427
Fixes: 35871462
Test: cts-tradefed run commandAndExit cts-dev -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.EphemeralTest
parent 13acf25c
Loading
Loading
Loading
Loading
+133 −14
Original line number Diff line number Diff line
@@ -7094,17 +7094,23 @@ public class PackageManagerService extends IPackageManager.Stub {
                // used when either 1) the service is in an instant application and the
                // caller is not the same instant application or 2) the calling package is
                // ephemeral and the activity is not visible to ephemeral applications.
                final boolean matchInstantApp =
                        (flags & PackageManager.MATCH_INSTANT) != 0;
                final boolean matchVisibleToInstantAppOnly =
                        (flags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
                final boolean isCallerInstantApp =
                        instantAppPkgName != null;
                final boolean isTargetSameInstantApp =
                        comp.getPackageName().equals(instantAppPkgName);
                final boolean isTargetInstantApp =
                        (si.applicationInfo.privateFlags
                                & ApplicationInfo.PRIVATE_FLAG_INSTANT) != 0;
                final boolean isTargetHiddenFromInstantApp =
                        (si.flags & ServiceInfo.FLAG_VISIBLE_TO_EPHEMERAL) == 0;
                final boolean blockResolution =
                        !isTargetSameInstantApp
                        && ((matchVisibleToInstantAppOnly && isCallerInstantApp
                        && ((!matchInstantApp && !isCallerInstantApp && isTargetInstantApp)
                                || (matchVisibleToInstantAppOnly && isCallerInstantApp
                                        && isTargetHiddenFromInstantApp));
                if (!blockResolution) {
                    final ResolveInfo ri = new ResolveInfo();
@@ -7191,6 +7197,7 @@ public class PackageManagerService extends IPackageManager.Stub {
            Intent intent, String resolvedType, int flags, int userId) {
        if (!sUserManager.exists(userId)) return Collections.emptyList();
        final int callingUid = Binder.getCallingUid();
        final String instantAppPkgName = getInstantAppPackageName(callingUid);
        flags = updateFlagsForResolve(flags, userId, intent, callingUid,
                false /*includeInstantApps*/);
        ComponentName comp = intent.getComponent();
@@ -7204,10 +7211,34 @@ public class PackageManagerService extends IPackageManager.Stub {
            final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
            final ProviderInfo pi = getProviderInfo(comp, flags, userId);
            if (pi != null) {
                // When specifying an explicit component, we prevent the provider from being
                // used when either 1) the provider is in an instant application and the
                // caller is not the same instant application or 2) the calling package is an
                // instant application and the provider is not visible to instant applications.
                final boolean matchInstantApp =
                        (flags & PackageManager.MATCH_INSTANT) != 0;
                final boolean matchVisibleToInstantAppOnly =
                        (flags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
                final boolean isCallerInstantApp =
                        instantAppPkgName != null;
                final boolean isTargetSameInstantApp =
                        comp.getPackageName().equals(instantAppPkgName);
                final boolean isTargetInstantApp =
                        (pi.applicationInfo.privateFlags
                                & ApplicationInfo.PRIVATE_FLAG_INSTANT) != 0;
                final boolean isTargetHiddenFromInstantApp =
                        (pi.flags & ProviderInfo.FLAG_VISIBLE_TO_EPHEMERAL) == 0;
                final boolean blockResolution =
                        !isTargetSameInstantApp
                        && ((!matchInstantApp && !isCallerInstantApp && isTargetInstantApp)
                                || (matchVisibleToInstantAppOnly && isCallerInstantApp
                                        && isTargetHiddenFromInstantApp));
                if (!blockResolution) {
                    final ResolveInfo ri = new ResolveInfo();
                    ri.providerInfo = pi;
                    list.add(ri);
                }
            }
            return list;
        }
@@ -7215,17 +7246,67 @@ public class PackageManagerService extends IPackageManager.Stub {
        synchronized (mPackages) {
            String pkgName = intent.getPackage();
            if (pkgName == null) {
                return mProviders.queryIntent(intent, resolvedType, flags, userId);
                return applyPostContentProviderResolutionFilter(
                        mProviders.queryIntent(intent, resolvedType, flags, userId),
                        instantAppPkgName);
            }
            final PackageParser.Package pkg = mPackages.get(pkgName);
            if (pkg != null) {
                return mProviders.queryIntentForPackage(
                        intent, resolvedType, flags, pkg.providers, userId);
                return applyPostContentProviderResolutionFilter(
                        mProviders.queryIntentForPackage(
                        intent, resolvedType, flags, pkg.providers, userId),
                        instantAppPkgName);
            }
            return Collections.emptyList();
        }
    }
    private List<ResolveInfo> applyPostContentProviderResolutionFilter(
            List<ResolveInfo> resolveInfos, String instantAppPkgName) {
        // TODO: When adding on-demand split support for non-instant applications, remove
        // this check and always apply post filtering
        if (instantAppPkgName == null) {
            return resolveInfos;
        }
        for (int i = resolveInfos.size() - 1; i >= 0; i--) {
            final ResolveInfo info = resolveInfos.get(i);
            final boolean isEphemeralApp = info.providerInfo.applicationInfo.isInstantApp();
            // allow providers that are defined in the provided package
            if (isEphemeralApp && instantAppPkgName.equals(info.providerInfo.packageName)) {
                if (info.providerInfo.splitName != null
                        && !ArrayUtils.contains(info.providerInfo.applicationInfo.splitNames,
                                info.providerInfo.splitName)) {
                    // requested provider is defined in a split that hasn't been installed yet.
                    // add the installer to the resolve list
                    if (DEBUG_EPHEMERAL) {
                        Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list");
                    }
                    final ResolveInfo installerInfo = new ResolveInfo(mInstantAppInstallerInfo);
                    installerInfo.auxiliaryInfo = new AuxiliaryResolveInfo(
                            info.providerInfo.packageName, info.providerInfo.splitName,
                            info.providerInfo.applicationInfo.versionCode);
                    // make sure this resolver is the default
                    installerInfo.isDefault = true;
                    installerInfo.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART
                            | IntentFilter.MATCH_ADJUSTMENT_NORMAL;
                    // add a non-generic filter
                    installerInfo.filter = new IntentFilter();
                    // load resources from the correct package
                    installerInfo.resolvePackageName = info.getComponentInfo().packageName;
                    resolveInfos.set(i, installerInfo);
                }
                continue;
            }
            // allow providers that have been explicitly exposed to instant applications
            if (!isEphemeralApp
                    && ((info.providerInfo.flags & ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL) != 0)) {
                continue;
            }
            resolveInfos.remove(i);
        }
        return resolveInfos;
    }
    @Override
    public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId) {
        if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
@@ -7557,17 +7638,38 @@ public class PackageManagerService extends IPackageManager.Stub {
    public ProviderInfo resolveContentProvider(String name, int flags, int userId) {
        if (!sUserManager.exists(userId)) return null;
        flags = updateFlagsForComponent(flags, userId, name);
        final String instantAppPkgName = getInstantAppPackageName(Binder.getCallingUid());
        // reader
        synchronized (mPackages) {
            final PackageParser.Provider provider = mProvidersByAuthority.get(name);
            PackageSetting ps = provider != null
                    ? mSettings.mPackages.get(provider.owner.packageName)
                    : null;
            return ps != null
                    && mSettings.isEnabledAndMatchLPr(provider.info, flags, userId)
                    ? PackageParser.generateProviderInfo(provider, flags,
                            ps.readUserState(userId), userId)
                    : null;
            if (ps != null) {
                final boolean isInstantApp = ps.getInstantApp(userId);
                // normal application; filter out instant application provider
                if (instantAppPkgName == null && isInstantApp) {
                    return null;
                }
                // instant application; filter out other instant applications
                if (instantAppPkgName != null
                        && isInstantApp
                        && !provider.owner.packageName.equals(instantAppPkgName)) {
                    return null;
                }
                // instant application; filter out non-exposed provider
                if (instantAppPkgName != null
                        && (provider.info.flags & ProviderInfo.FLAG_VISIBLE_TO_EPHEMERAL) == 0) {
                    return null;
                }
                // provider not enabled
                if (!mSettings.isEnabledAndMatchLPr(provider.info, flags, userId)) {
                    return null;
                }
                return PackageParser.generateProviderInfo(
                        provider, flags, ps.readUserState(userId), userId);
            }
            return null;
        }
    }
@@ -12772,8 +12874,26 @@ public class PackageManagerService extends IPackageManager.Stub {
            if (ps == null) {
                return null;
            }
            final PackageUserState userState = ps.readUserState(userId);
            final boolean matchVisibleToInstantApp =
                    (mFlags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
            final boolean isInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0;
            // throw out filters that aren't visible to instant applications
            if (matchVisibleToInstantApp
                    && !(info.isVisibleToInstantApp() || userState.instantApp)) {
                return null;
            }
            // throw out instant application filters if we're not explicitly requesting them
            if (!isInstantApp && userState.instantApp) {
                return null;
            }
            // throw out instant application filters if updates are available; will trigger
            // instant application resolution
            if (userState.instantApp && ps.isUpdateAvailable()) {
                return null;
            }
            ProviderInfo pi = PackageParser.generateProviderInfo(provider, mFlags,
                    ps.readUserState(userId), userId);
                    userState, userId);
            if (pi == null) {
                return null;
            }
@@ -23338,7 +23458,6 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
                    intent, resolvedType, flags, userId, callingUid, true /*includeInstantApps*/);
        }
        @Override
        public void addIsolatedUid(int isolatedUid, int ownerUid) {
            synchronized (mPackages) {