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

Commit 0590bd00 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 rvc-qpr-dev

parents 41cce389 5c72cd48
Loading
Loading
Loading
Loading
+45 −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;
@@ -31,13 +33,18 @@ 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;

import java.io.PrintWriter;

import java.util.Arrays;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean;


public final class Helper {

@@ -71,6 +78,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 −3
Original line number Diff line number Diff line
@@ -141,8 +141,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);
@@ -220,6 +221,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);
@@ -298,7 +302,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
@@ -361,8 +361,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;