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

Commit ac74dc42 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Further improvements when app forges package info for autofill:"

parents 1c231975 637e05ee
Loading
Loading
Loading
Loading
+25 −23
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import android.view.View;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.Preconditions;

import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -428,7 +429,7 @@ public final class AutofillManager {
     * @hide
     */
    public AutofillManager(Context context, IAutoFillManager service) {
        mContext = context;
        mContext = Preconditions.checkNotNull(context, "context cannot be null");
        mService = service;
    }

@@ -457,7 +458,7 @@ public final class AutofillManager {
            if (mSessionId != NO_SESSION) {
                ensureServiceClientAddedIfNeededLocked();

                final AutofillClient client = getClientLocked();
                final AutofillClient client = getClient();
                if (client != null) {
                    try {
                        final boolean sessionWasRestored = mService.restoreSession(mSessionId,
@@ -1093,7 +1094,8 @@ public final class AutofillManager {
        }
    }

    private AutofillClient getClientLocked() {
    // Note: don't need to use locked suffix because mContext is final.
    private AutofillClient getClient() {
        final AutofillClient client = mContext.getAutofillClient();
        if (client == null && sDebug) {
            Log.d(TAG, "No AutofillClient for " + mContext.getPackageName() + " on context "
@@ -1156,16 +1158,16 @@ public final class AutofillManager {
            return;
        }
        try {
            final AutofillClient client = getClientLocked();
            final AutofillClient client = getClient();
            if (client == null) return; // NOTE: getClient() already logd it..

            mSessionId = mService.startSession(mContext.getActivityToken(),
                    mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(),
                    mCallback != null, flags, client.getComponentName());
            if (mSessionId != NO_SESSION) {
                mState = STATE_ACTIVE;
            }
            if (client != null) {
            client.autofillCallbackResetableStateAvailable();
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
@@ -1217,7 +1219,9 @@ public final class AutofillManager {

        try {
            if (restartIfNecessary) {
                final AutofillClient client = getClientLocked();
                final AutofillClient client = getClient();
                if (client == null) return; // NOTE: getClient() already logd it..

                final int newId = mService.updateOrRestartSession(mContext.getActivityToken(),
                        mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(),
                        mCallback != null, flags, client.getComponentName(), mSessionId, action);
@@ -1225,10 +1229,8 @@ public final class AutofillManager {
                    if (sDebug) Log.d(TAG, "Session restarted: " + mSessionId + "=>" + newId);
                    mSessionId = newId;
                    mState = (mSessionId == NO_SESSION) ? STATE_UNKNOWN : STATE_ACTIVE;
                    if (client != null) {
                    client.autofillCallbackResetableStateAvailable();
                }
                }
            } else {
                mService.updateSession(mSessionId, id, bounds, value, action, flags,
                        mContext.getUserId());
@@ -1240,7 +1242,7 @@ public final class AutofillManager {
    }

    private void ensureServiceClientAddedIfNeededLocked() {
        if (getClientLocked() == null) {
        if (getClient() == null) {
            return;
        }

@@ -1323,7 +1325,7 @@ public final class AutofillManager {
        AutofillCallback callback = null;
        synchronized (mLock) {
            if (mSessionId == sessionId) {
                AutofillClient client = getClientLocked();
                AutofillClient client = getClient();

                if (client != null) {
                    if (client.autofillCallbackRequestShowFillUi(anchor, width, height,
@@ -1348,7 +1350,7 @@ public final class AutofillManager {
            Intent fillInIntent) {
        synchronized (mLock) {
            if (sessionId == mSessionId) {
                AutofillClient client = getClientLocked();
                final AutofillClient client = getClient();
                if (client != null) {
                    client.autofillCallbackAuthenticate(authenticationId, intent, fillInIntent);
                }
@@ -1413,7 +1415,7 @@ public final class AutofillManager {
                return;
            }

            final AutofillClient client = getClientLocked();
            final AutofillClient client = getClient();
            if (client == null) {
                return;
            }
@@ -1590,7 +1592,7 @@ public final class AutofillManager {
            // 1. If local and remote session id are off sync the UI would be stuck shown
            // 2. There is a race between the user state being destroyed due the fill
            //    service being uninstalled and the UI being dismissed.
            AutofillClient client = getClientLocked();
            AutofillClient client = getClient();
            if (client != null) {
                if (client.autofillCallbackRequestHideFillUi() && mCallback != null) {
                    callback = mCallback;
@@ -1620,7 +1622,7 @@ public final class AutofillManager {

        AutofillCallback callback = null;
        synchronized (mLock) {
            if (mSessionId == sessionId && getClientLocked() != null) {
            if (mSessionId == sessionId && getClient() != null) {
                callback = mCallback;
            }
        }
@@ -1677,7 +1679,7 @@ public final class AutofillManager {
     * @return The view or {@code null} if view was not found
     */
    private View findView(@NonNull AutofillId autofillId) {
        final AutofillClient client = getClientLocked();
        final AutofillClient client = getClient();

        if (client == null) {
            return null;
@@ -1711,7 +1713,7 @@ public final class AutofillManager {
        pw.print(pfx); pw.print("sessionId: "); pw.println(mSessionId);
        pw.print(pfx); pw.print("state: "); pw.println(getStateAsStringLocked());
        pw.print(pfx); pw.print("context: "); pw.println(mContext);
        pw.print(pfx); pw.print("client: "); pw.println(getClientLocked());
        pw.print(pfx); pw.print("client: "); pw.println(getClient());
        pw.print(pfx); pw.print("enabled: "); pw.println(mEnabled);
        pw.print(pfx); pw.print("hasService: "); pw.println(mService != null);
        pw.print(pfx); pw.print("hasCallback: "); pw.println(mCallback != null);
@@ -1758,7 +1760,7 @@ public final class AutofillManager {
    }

    private void post(Runnable runnable) {
        final AutofillClient client = getClientLocked();
        final AutofillClient client = getClient();
        if (client == null) {
            if (sVerbose) Log.v(TAG, "ignoring post() because client is null");
            return;
@@ -1841,7 +1843,7 @@ public final class AutofillManager {
         * @param trackedIds The views to be tracked
         */
        TrackedViews(@Nullable AutofillId[] trackedIds) {
            final AutofillClient client = getClientLocked();
            final AutofillClient client = getClient();
            if (trackedIds != null && client != null) {
                final boolean[] isVisible;

@@ -1882,7 +1884,7 @@ public final class AutofillManager {
         * @param isVisible visible if the view is visible in the view hierarchy.
         */
        void notifyViewVisibilityChanged(@NonNull AutofillId id, boolean isVisible) {
            AutofillClient client = getClientLocked();
            AutofillClient client = getClient();

            if (sDebug) {
                Log.d(TAG, "notifyViewVisibilityChanged(): id=" + id + " isVisible="
@@ -1919,7 +1921,7 @@ public final class AutofillManager {
        void onVisibleForAutofillLocked() {
            // The visibility of the views might have changed while the client was not be visible,
            // hence update the visibility state for all views.
            AutofillClient client = getClientLocked();
            AutofillClient client = getClient();
            ArraySet<AutofillId> updatedVisibleTrackedIds = null;
            ArraySet<AutofillId> updatedInvisibleTrackedIds = null;
            if (client != null) {
+13 −0
Original line number Diff line number Diff line
@@ -4138,6 +4138,19 @@ message MetricsEvent {
    // OS: O
    FIELD_NOTIFICATION_GROUP_SUMMARY = 947;

    // An app attempted to forge a different component name in the AssisStructure that would be
    // passed to the autofill service.
    // OS: O (security patch)
    // Package: Real package of the app being autofilled
    // Tag FIELD_AUTOFILL_SERVICE: Package of the autofill service that processed the request
    // TAG FIELD_AUTOFILL_FORGED_COMPONENT_NAME: Component name being forged
    AUTOFILL_FORGED_COMPONENT_ATTEMPT = 948;

    // FIELD - The component that an app tried tro forged.
    // Type: string
    // OS: O (security patch)
    FIELD_AUTOFILL_FORGED_COMPONENT_NAME = 949;

    // ---- End O Constants, all O constants go above this line ----

    // OPEN: Settings > System > Languages & input > Advanced > Lift to open camera
+32 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ServiceInfo;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
@@ -43,6 +44,7 @@ import android.os.Looper;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.service.autofill.AutofillService;
@@ -465,6 +467,8 @@ final class AutofillManagerServiceImpl {
            sessionId = sRandom.nextInt();
        } while (sessionId == NO_SESSION || mSessions.indexOfKey(sessionId) >= 0);

        assertCallerLocked(componentName);

        final Session newSession = new Session(this, mUi, mContext, mHandlerCaller, mUserId, mLock,
                sessionId, uid, activityToken, appCallbackToken, hasCallback,
                mUiLatencyHistory, mInfo.getServiceInfo().getComponentName(), componentName);
@@ -473,6 +477,34 @@ final class AutofillManagerServiceImpl {
        return newSession;
    }

    /**
     * Asserts the component is owned by the caller.
     */
    private void assertCallerLocked(@NonNull ComponentName componentName) {
        final PackageManager pm = mContext.getPackageManager();
        final int callingUid = Binder.getCallingUid();
        final int packageUid;
        try {
            packageUid = pm.getPackageUidAsUser(componentName.getPackageName(),
                    UserHandle.getCallingUserId());
        } catch (NameNotFoundException e) {
            throw new SecurityException("Could not verify UID for " + componentName);
        }
        if (callingUid != packageUid) {
            final String[] packages = pm.getPackagesForUid(callingUid);
            final String callingPackage = packages != null ? packages[0] : "uid-" + callingUid;
            Slog.w(TAG, "App (package=" + callingPackage + ", UID=" + callingUid
                    + ") passed component (" + componentName + ") owned by UID " + packageUid);
            mMetricsLogger.write(
                    Helper.newLogMaker(MetricsEvent.AUTOFILL_FORGED_COMPONENT_ATTEMPT,
                            callingPackage, getServicePackageName())
                    .addTaggedData(MetricsEvent.FIELD_AUTOFILL_FORGED_COMPONENT_NAME,
                            componentName == null ? "null" : componentName.flattenToShortString()));

            throw new SecurityException("Invalid component: " + componentName);
        }
    }

    /**
     * Restores a session after an activity was temporarily destroyed.
     *
+8 −3
Original line number Diff line number Diff line
@@ -238,10 +238,15 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                structure.ensureData();

                // Sanitize structure before it's sent to service.
                if (!mComponentName.equals(structure.getActivityComponent())) {
                final ComponentName componentNameFromApp = structure.getActivityComponent();
                if (!mComponentName.equals(componentNameFromApp)) {
                    Slog.w(TAG, "Activity " + mComponentName + " forged different component on "
                            + "AssistStructure: " + structure.getActivityComponent());
                            + "AssistStructure: " + componentNameFromApp);
                    structure.setActivityComponent(mComponentName);
                    mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_FORGED_COMPONENT_ATTEMPT)
                            .addTaggedData(MetricsEvent.FIELD_AUTOFILL_FORGED_COMPONENT_NAME,
                                    componentNameFromApp == null ? "null"
                                            : componentNameFromApp.flattenToShortString()));
                }
                structure.sanitizeForParceling(true);

@@ -1706,7 +1711,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                break;
            case ACTION_VIEW_ENTERED:
                if (sVerbose && virtualBounds != null) {
                    Slog.w(TAG, "entered on virtual child " + id + ": " + virtualBounds);
                    Slog.v(TAG, "entered on virtual child " + id + ": " + virtualBounds);
                }
                requestNewFillResponseIfNecessaryLocked(id, viewState, flags);