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

Commit 70dd7c6e authored by Billy Huang's avatar Billy Huang
Browse files

opp: validate that content uri belongs to current user

Most helpers in ContentProvider are hidden.
Use ContentProvider.createContentUriForUser which
is callable by modules to validate the uri.

Bug: 296915500
Flag: EXEMPT fix for vulnerability
Test: atest GoogleBluetoothInstrumentationTests:BluetoothOppSendFileInfoTest#generateFileInfo_withContentUriForOtherUser_returnsSendFileInfoError
Ignore-AOSP-First: fix for undisclosed vulnerability
Change-Id: I13e3747b17017066c1bd3cc8cd5796eab2c3eb4f
parent 4d6603a1
Loading
Loading
Loading
Loading
+20 −1
Original line number Diff line number Diff line
@@ -34,12 +34,14 @@ package com.android.bluetooth.opp;

import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothProtoEnums;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.database.sqlite.SQLiteException;
import android.net.Uri;
import android.os.UserHandle;
import android.provider.OpenableColumns;
import android.util.EventLog;
import android.util.Log;
@@ -58,7 +60,7 @@ import java.io.IOException;
 * This class stores information about a single sending file It will only be used for outbound
 * share.
 */
// Next tag value for ContentProfileErrorReportUtils.report(): 15
// Next tag value for ContentProfileErrorReportUtils.report(): 16
public class BluetoothOppSendFileInfo {
    private static final String TAG = "BluetoothOppSendFileInfo";

@@ -124,6 +126,23 @@ public class BluetoothOppSendFileInfo {
                return SEND_FILE_INFO_ERROR;
            }

            try {
                // Use module-visible API to confirm that content uri is valid for the current user.
                // Content uris for a different user are invalid.
                // Uris pointing either implicitly or explicitly to content for the current user
                // will be valid.
                ContentProvider.createContentUriForUser(
                        uri, UserHandle.getUserHandleForUid(UserHandle.myUserId()));
            } catch (IllegalArgumentException e) {
                Log.e(TAG, "Uri: " + uri + " is invalid for user " + UserHandle.myUserId(), e);
                ContentProfileErrorReportUtils.report(
                        BluetoothProfile.OPP,
                        BluetoothProtoEnums.BLUETOOTH_OPP_SEND_FILE_INFO,
                        BluetoothStatsLog.BLUETOOTH_CONTENT_PROFILE_ERROR_REPORTED__TYPE__LOG_ERROR,
                        15);
                return SEND_FILE_INFO_ERROR;
            }

            contentType = contentResolver.getType(uri);
            Cursor metadataCursor;
            try {
+30 −0
Original line number Diff line number Diff line
@@ -119,6 +119,36 @@ public class BluetoothOppSendFileInfoTest {
        assertThat(info).isEqualTo(BluetoothOppSendFileInfo.SEND_FILE_INFO_ERROR);
    }

    @Test
    public void generateFileInfo_withContentUriForOtherUser_returnsSendFileInfoError()
            throws Exception {
        String type = "image/jpeg";
        Uri uri = Uri.parse("content://11@media/external/images/media/1");

        long fileLength = 1000;
        String fileName = "pic.jpg";

        FileInputStream fs = mock(FileInputStream.class);
        AssetFileDescriptor fd = mock(AssetFileDescriptor.class);
        doReturn(fileLength).when(fd).getLength();
        doReturn(fs).when(fd).createInputStream();

        doReturn(fd).when(mCallProxy).contentResolverOpenAssetFileDescriptor(any(), eq(uri), any());

        mCursor =
                new MatrixCursor(new String[] {OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE});
        mCursor.addRow(new Object[] {fileName, fileLength});

        doReturn(mCursor)
                .when(mCallProxy)
                .contentResolverQuery(any(), eq(uri), any(), any(), any(), any());

        BluetoothOppSendFileInfo info =
                BluetoothOppSendFileInfo.generateFileInfo(mContext, uri, type, true);

        assertThat(info).isEqualTo(BluetoothOppSendFileInfo.SEND_FILE_INFO_ERROR);
    }

    @Test
    public void generateFileInfo_withoutPermissionForAccessingUri_returnsSendFileInfoError() {
        String type = "text/plain";