summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Yu <yunicorn@google.com>2023-06-20 21:24:36 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-08-11 21:07:04 +0000
commit142a5a270c70e557235488b5a4f583b1869b275a (patch)
tree0c852698d79c7b50bcaf2349170fdb7d67610752
parent0ceaf8ccb95dad9a5444fe66a128f08a004bb5e8 (diff)
downloadbase-142a5a270c70e557235488b5a4f583b1869b275a.tar.gz
[DO NOT MERGE] Verify URI Permissions in Autofill RemoteViews
Check permissions of URI inside of FillResponse's RemoteViews. If the current user does not have the required permissions to view the URI, the RemoteView is dropped from displaying. This fixes a security spill in which a user can view content of another user through a malicious Autofill provider. Bug: 283137865 Fixes: b/283264674 b/281666022 b/281665050 b/281848557 b/281533566 b/281534749 b/283101289 Test: Verified by POC app attached in bugs Test: atest CtsAutoFillServiceTestCases (added new tests) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:5c72cd48097f7cdaa62e9eb1a0aeddbb941ec981) Merged-In: I6f4d2a35e89bbed7bd9e07bf5cd3e2d68b20af9a Change-Id: I6f4d2a35e89bbed7bd9e07bf5cd3e2d68b20af9a
-rw-r--r--services/autofill/java/com/android/server/autofill/Helper.java45
-rw-r--r--services/autofill/java/com/android/server/autofill/ui/FillUi.java11
-rw-r--r--services/autofill/java/com/android/server/autofill/ui/SaveUi.java3
3 files changed, 54 insertions, 5 deletions
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index 80b0375a229d..8954a0c39091 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -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;
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index 890208720f97..b35fd92e366d 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -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);
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index 1c3116699b2d..7b45ef881e94 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -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;