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

Commit b9743c8a authored by Tim Yu's avatar Tim Yu Committed by Android (Google) Code Review
Browse files

Merge "[DO NOT MERGE] Verify URI Permissions in Autofill RemoteViews" into tm-qpr-dev-plus-aosp

parents 71fb10ba b898176d
Loading
Loading
Loading
Loading
+43 −0
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.server.autofill;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.assist.AssistStructure;
import android.app.assist.AssistStructure.ViewNode;
import android.app.assist.AssistStructure.WindowNode;
@@ -34,6 +36,7 @@ import android.view.View;
import android.view.WindowManager;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillValue;
import android.widget.RemoteViews;

import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.ArrayUtils;
@@ -42,6 +45,8 @@ import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicBoolean;


public final class Helper {

@@ -75,6 +80,44 @@ public final class Helper {
        throw new UnsupportedOperationException("contains static members only");
    }

    private static boolean checkRemoteViewUriPermissions(
            @UserIdInt int userId, @NonNull RemoteViews rView) {
        final AtomicBoolean permissionsOk = new AtomicBoolean(true);

        rView.visitUris(uri -> {
            int uriOwnerId = android.content.ContentProvider.getUserIdFromUri(uri);
            boolean allowed = uriOwnerId == userId;
            permissionsOk.set(allowed && permissionsOk.get());
        });

        return permissionsOk.get();
    }

    /**
     * Checks the URI permissions of the remote view,
     * to see if the current userId is able to access it.
     *
     * Returns the RemoteView that is passed if user is able, null otherwise.
     *
     * TODO: instead of returning a null remoteview when
     * the current userId cannot access an URI,
     * return a new RemoteView with the URI removed.
     */
    public static @Nullable RemoteViews sanitizeRemoteView(RemoteViews rView) {
        if (rView == null) return null;

        int userId = ActivityManager.getCurrentUser();

        boolean ok = checkRemoteViewUriPermissions(userId, rView);
        if (!ok) {
            Slog.w(TAG,
                    "sanitizeRemoteView() user: " + userId
                    + " tried accessing resource that does not belong to them");
        }
        return (ok ? rView : null);
    }


    @Nullable
    static AutofillId[] toArray(@Nullable ArraySet<AutofillId> set) {
        if (set == null) return null;
+8 −4
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ import android.widget.TextView;

import com.android.internal.R;
import com.android.server.autofill.AutofillManagerService;
import com.android.server.autofill.Helper;

import java.io.PrintWriter;
import java.util.ArrayList;
@@ -197,7 +198,8 @@ final class DialogFillUi {
    }

    private void setHeader(View decor, FillResponse response) {
        final RemoteViews presentation = response.getDialogHeader();
        final RemoteViews presentation =
                Helper.sanitizeRemoteView(response.getDialogHeader());
        if (presentation == null) {
            return;
        }
@@ -232,9 +234,10 @@ final class DialogFillUi {
    }

    private void initialAuthenticationLayout(View decor, FillResponse response) {
        RemoteViews presentation = response.getDialogPresentation();
        RemoteViews presentation = Helper.sanitizeRemoteView(
                response.getDialogPresentation());
        if (presentation == null) {
            presentation = response.getPresentation();
            presentation = Helper.sanitizeRemoteView(response.getPresentation());
        }
        if (presentation == null) {
            throw new RuntimeException("No presentation for fill dialog authentication");
@@ -278,7 +281,8 @@ final class DialogFillUi {
            final Dataset dataset = response.getDatasets().get(i);
            final int index = dataset.getFieldIds().indexOf(focusedViewId);
            if (index >= 0) {
                RemoteViews presentation = dataset.getFieldDialogPresentation(index);
                RemoteViews presentation = Helper.sanitizeRemoteView(
                        dataset.getFieldDialogPresentation(index));
                if (presentation == null) {
                    if (sDebug) {
                        Slog.w(TAG, "not displaying UI on field " + focusedViewId + " because "
+8 −3
Original line number Diff line number Diff line
@@ -144,8 +144,9 @@ final class FillUi {

        final LayoutInflater inflater = LayoutInflater.from(mContext);

        final RemoteViews headerPresentation = response.getHeader();
        final RemoteViews footerPresentation = response.getFooter();
        final RemoteViews headerPresentation = Helper.sanitizeRemoteView(response.getHeader());
        final RemoteViews footerPresentation = Helper.sanitizeRemoteView(response.getFooter());

        final ViewGroup decor;
        if (mFullScreen) {
            decor = (ViewGroup) inflater.inflate(R.layout.autofill_dataset_picker_fullscreen, null);
@@ -223,6 +224,9 @@ final class FillUi {
            ViewGroup container = decor.findViewById(R.id.autofill_dataset_picker);
            final View content;
            try {
                if (Helper.sanitizeRemoteView(response.getPresentation()) == null) {
                    throw new RuntimeException("Permission error accessing RemoteView");
                }
                content = response.getPresentation().applyWithTheme(
                        mContext, decor, interceptionHandler, mThemeId);
                container.addView(content);
@@ -302,7 +306,8 @@ final class FillUi {
                final Dataset dataset = response.getDatasets().get(i);
                final int index = dataset.getFieldIds().indexOf(focusedViewId);
                if (index >= 0) {
                    final RemoteViews presentation = dataset.getFieldPresentation(index);
                    final RemoteViews presentation = Helper.sanitizeRemoteView(
                            dataset.getFieldPresentation(index));
                    if (presentation == null) {
                        Slog.w(TAG, "not displaying UI on field " + focusedViewId + " because "
                                + "service didn't provide a presentation for it on " + dataset);
+1 −2
Original line number Diff line number Diff line
@@ -368,8 +368,7 @@ final class SaveUi {
            return false;
        }
        writeLog(MetricsEvent.AUTOFILL_SAVE_CUSTOM_DESCRIPTION);

        final RemoteViews template = customDescription.getPresentation();
        final RemoteViews template = Helper.sanitizeRemoteView(customDescription.getPresentation());
        if (template == null) {
            Slog.w(TAG, "No remote view on custom description");
            return false;