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

Commit 44c0ac96 authored by Christophe Pinelli's avatar Christophe Pinelli Committed by Android (Google) Code Review
Browse files

Merge "Verify that the component is exported"

parents 3acc70a6 80a78df0
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -4216,13 +4216,23 @@ public class ActivityManager {
        }
    }*/

    /** @hide
     * Determines whether the given UID can access unexported components
     * @param uid the calling UID
     * @return true if the calling UID is ROOT or SYSTEM
     */
    public static boolean canAccessUnexportedComponents(int uid) {
        final int appId = UserHandle.getAppId(uid);
        return (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID);
    }

    /** @hide */
    @UnsupportedAppUsage
    public static int checkComponentPermission(String permission, int uid,
            int owningUid, boolean exported) {
        // Root, system server get to do everything.
        final int appId = UserHandle.getAppId(uid);
        if (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID) {
        if (canAccessUnexportedComponents(uid)) {
            return PackageManager.PERMISSION_GRANTED;
        }
        // Isolated processes don't get any permissions.
+8 −0
Original line number Diff line number Diff line
@@ -576,6 +576,14 @@ public abstract class PackageManagerInternal {
            @PrivateResolveFlags long privateResolveFlags, int userId, boolean resolveForStart,
            int filterCallingUid);

    /**
     * Resolves an exported activity intent, allowing instant apps to be resolved.
     */
    public abstract ResolveInfo resolveIntentExported(Intent intent, String resolvedType,
            @PackageManager.ResolveInfoFlagsBits long flags,
            @PrivateResolveFlags long privateResolveFlags, int userId, boolean resolveForStart,
            int filterCallingUid);

    /**
    * Resolves a service intent, allowing instant apps to be resolved.
    */
+68 −0
Original line number Diff line number Diff line
@@ -215,6 +215,7 @@ import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetManagerInternal;
import android.compat.annotation.ChangeId;
import android.compat.annotation.Disabled;
import android.compat.annotation.EnabledAfter;
import android.content.AttributionSource;
import android.content.AutofillOptions;
import android.content.BroadcastReceiver;
@@ -584,6 +585,17 @@ public class ActivityManagerService extends IActivityManager.Stub
    @Disabled
    private static final long DYNAMIC_RECEIVER_EXPLICIT_EXPORT_REQUIRED = 161145287L;
    /**
     * Apps targeting Android U and above will need to export components in order to invoke them
     * through implicit intents.
     *
     * If a component is not exported and invoked, it will be removed from the list of receivers.
     * This applies specifically to activities and broadcasts.
     */
    @ChangeId
    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
    public static final long IMPLICIT_INTENTS_ONLY_MATCH_EXPORTED_COMPONENTS = 229362273;
    /**
     * The maximum number of bytes that {@link #setProcessStateSummary} accepts.
     *
@@ -12378,6 +12390,58 @@ public class ActivityManagerService extends IActivityManager.Stub
        return false;
    }
    /**
     * Filters out non-exported components in a given list of broadcast filters
     * @param intent the original intent
     * @param callingUid the calling UID
     * @param query the list of broadcast filters
     * @param platformCompat the instance of platform compat
     */
    private static void filterNonExportedComponents(Intent intent, int callingUid,
            List query, PlatformCompat platformCompat, String callerPackage) {
        if (query == null
                || intent.getPackage() != null
                || intent.getComponent() != null
                || ActivityManager.canAccessUnexportedComponents(callingUid)) {
            return;
        }
        for (int i = query.size() - 1; i >= 0; i--) {
            String componentInfo;
            ResolveInfo resolveInfo;
            BroadcastFilter broadcastFilter;
            if (query.get(i) instanceof ResolveInfo) {
                resolveInfo = (ResolveInfo) query.get(i);
                if (resolveInfo.getComponentInfo().exported) {
                    continue;
                }
                componentInfo = resolveInfo.getComponentInfo()
                        .getComponentName().flattenToShortString();
            } else if (query.get(i) instanceof BroadcastFilter) {
                broadcastFilter = (BroadcastFilter) query.get(i);
                if (broadcastFilter.exported) {
                    continue;
                }
                componentInfo = broadcastFilter.packageName;
            } else {
                continue;
            }
            if (!platformCompat.isChangeEnabledByUid(
                    IMPLICIT_INTENTS_ONLY_MATCH_EXPORTED_COMPONENTS, callingUid)) {
                Slog.w(TAG, "Non-exported component not filtered out "
                        + "(will be filtered out once the app targets U+)- intent: "
                        + intent.getAction() + ", component: "
                        + componentInfo + ", sender: "
                        + callerPackage);
                return;
            }
            Slog.w(TAG, "Non-exported component filtered out - intent: "
                    + intent.getAction() + ", component: "
                    + componentInfo + ", sender: "
                    + callerPackage);
            query.remove(i);
        }
    }
    /**
     * Main code for cleaning up a process when it has gone away.  This is
     * called both as a result of the process dying, or directly when stopping
@@ -14217,6 +14281,8 @@ public class ActivityManagerService extends IActivityManager.Stub
            }
        }
        filterNonExportedComponents(intent, callingUid, registeredReceivers,
                mPlatformCompat, callerPackage);
        int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
        if (!ordered && NR > 0) {
            // If we are not serializing this broadcast, then send the
@@ -14319,6 +14385,8 @@ public class ActivityManagerService extends IActivityManager.Stub
        if ((receivers != null && receivers.size() > 0)
                || resultTo != null) {
            BroadcastQueue queue = broadcastQueueForIntent(intent);
            filterNonExportedComponents(intent, callingUid, receivers,
                    mPlatformCompat, callerPackage);
            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,
                    callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
                    requiredPermissions, excludedPermissions, excludedPackages, appOp, brOptions,
+14 −0
Original line number Diff line number Diff line
@@ -465,6 +465,20 @@ abstract class PackageManagerInternalBase extends PackageManagerInternal {
                filterCallingUid);
    }

    /**
     * @deprecated similar to {@link resolveIntent} but limits the matches to exported components.
     */
    @Override
    @Deprecated
    public final ResolveInfo resolveIntentExported(Intent intent, String resolvedType,
            @PackageManager.ResolveInfoFlagsBits long flags,
            @PackageManagerInternal.PrivateResolveFlags long privateResolveFlags, int userId,
            boolean resolveForStart, int filterCallingUid) {
        return getResolveIntentHelper().resolveIntentInternal(snapshot(),
                intent, resolvedType, flags, privateResolveFlags, userId, resolveForStart,
                filterCallingUid, true);
    }

    @Override
    @Deprecated
    public final ResolveInfo resolveService(Intent intent, String resolvedType,
+51 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ import android.util.Slog;

import com.android.internal.app.ResolverActivity;
import com.android.internal.util.ArrayUtils;
import com.android.server.am.ActivityManagerService;
import com.android.server.compat.PlatformCompat;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
@@ -100,6 +101,38 @@ final class ResolveIntentHelper {
        mInstantAppInstallerActivitySupplier = instantAppInstallerActivitySupplier;
    }

    private static void filterNonExportedComponents(Intent intent, int filterCallingUid,
            List<ResolveInfo> query, PlatformCompat platformCompat, Computer computer) {
        if (query == null
                || intent.getPackage() != null
                || intent.getComponent() != null
                || ActivityManager.canAccessUnexportedComponents(filterCallingUid)) {
            return;
        }
        AndroidPackage caller = computer.getPackage(filterCallingUid);
        String callerPackage = caller == null ? "Not specified" : caller.getPackageName();
        for (int i = query.size() - 1; i >= 0; i--) {
            if (!query.get(i).getComponentInfo().exported) {
                if (!platformCompat.isChangeEnabledByUid(
                        ActivityManagerService.IMPLICIT_INTENTS_ONLY_MATCH_EXPORTED_COMPONENTS,
                        filterCallingUid)) {
                    Slog.w(TAG, "Non-exported component not filtered out "
                            + "(will be filtered out once the app targets U+)- intent: "
                            + intent.getAction() + ", component: "
                            + query.get(i).getComponentInfo()
                            .getComponentName().flattenToShortString()
                            + ", starter: " + callerPackage);
                    return;
                }
                Slog.w(TAG, "Non-exported component filtered out - intent: "
                        + intent.getAction() + ", component: "
                        + query.get(i).getComponentInfo().getComponentName().flattenToShortString()
                        + ", starter: " + callerPackage);
                query.remove(i);
            }
        }
    }

    /**
     * Normally instant apps can only be resolved when they're visible to the caller.
     * However, if {@code resolveForStart} is {@code true}, all instant apps are visible
@@ -109,6 +142,20 @@ final class ResolveIntentHelper {
            @PackageManager.ResolveInfoFlagsBits long flags,
            @PackageManagerInternal.PrivateResolveFlags long privateResolveFlags, int userId,
            boolean resolveForStart, int filterCallingUid) {
        return resolveIntentInternal(computer, intent, resolvedType, flags,
                privateResolveFlags, userId, resolveForStart, filterCallingUid, false);
    }

    /**
     * Normally instant apps can only be resolved when they're visible to the caller.
     * However, if {@code resolveForStart} is {@code true}, all instant apps are visible
     * since we need to allow the system to start any installed application.
     * Allows picking exported components only.
     */
    public ResolveInfo resolveIntentInternal(Computer computer, Intent intent, String resolvedType,
            @PackageManager.ResolveInfoFlagsBits long flags,
            @PackageManagerInternal.PrivateResolveFlags long privateResolveFlags, int userId,
            boolean resolveForStart, int filterCallingUid, boolean exportedComponentsOnly) {
        try {
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveIntent");

@@ -124,6 +171,10 @@ final class ResolveIntentHelper {
            final List<ResolveInfo> query = computer.queryIntentActivitiesInternal(intent,
                    resolvedType, flags, privateResolveFlags, filterCallingUid, userId,
                    resolveForStart, true /*allowDynamicSplits*/);
            if (exportedComponentsOnly) {
                filterNonExportedComponents(intent, filterCallingUid, query,
                        mPlatformCompat, computer);
            }
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

            final boolean queryMayBeFiltered =
Loading