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

Commit 22b3403e authored by Hugh Chen's avatar Hugh Chen Committed by android-build-team Robot
Browse files

RESTRICT AUTOMERGE Fix unable to send file via OPP

Bluetooth app will indicate BluetoothOppReceiver to receive
device picker intent. But for fix the security issue we
removed the setClassName() method in ag/14111132 to avoid attack.
It causes BluetoothOppReceiver cannot receive the intent.

This CL will compare to calling package name with launch package name.
If they are not equal, the setClassName() will not invoke.

Bug: 186490534
Bug: 179386960
Bug: 179386068

Test: make RunSettingsRoboTests -j56
Change-Id: Ia51528f2a44ab73edbc86899ca0846d3262fe1f0
(cherry picked from commit bb5be240)
(cherry picked from commit 51755e9a)
parent 81d00b73
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -27,12 +27,15 @@ import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.UserManager;
import android.util.Log;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuInflater;

import androidx.annotation.VisibleForTesting;

import com.android.settings.R;
import com.android.settings.password.PasswordUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.core.AbstractPreferenceController;

@@ -50,6 +53,12 @@ public final class DevicePickerFragment extends DeviceListPreferenceFragment {
    BluetoothProgressCategory mAvailableDevicesCategory;
    @VisibleForTesting
    Context mContext;
    @VisibleForTesting
    String mLaunchPackage;
    @VisibleForTesting
    String mLaunchClass;
    @VisibleForTesting
    String mCallingAppPackageName;

    private boolean mNeedAuth;
    private boolean mScanAllowed;
@@ -64,6 +73,8 @@ public final class DevicePickerFragment extends DeviceListPreferenceFragment {
        mNeedAuth = intent.getBooleanExtra(BluetoothDevicePicker.EXTRA_NEED_AUTH, false);
        setFilter(intent.getIntExtra(BluetoothDevicePicker.EXTRA_FILTER_TYPE,
                BluetoothDevicePicker.FILTER_TYPE_ALL));
        mLaunchPackage = intent.getStringExtra(BluetoothDevicePicker.EXTRA_LAUNCH_PACKAGE);
        mLaunchClass = intent.getStringExtra(BluetoothDevicePicker.EXTRA_LAUNCH_CLASS);
        mAvailableDevicesCategory = (BluetoothProgressCategory) findPreference(KEY_BT_DEVICE_LIST);
    }

@@ -83,6 +94,12 @@ public final class DevicePickerFragment extends DeviceListPreferenceFragment {
        getActivity().setTitle(getString(R.string.device_picker));
        UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
        mScanAllowed = !um.hasUserRestriction(DISALLOW_CONFIG_BLUETOOTH);
        mCallingAppPackageName = PasswordUtils.getCallingAppPackageName(
                getActivity().getActivityToken());
        if (!TextUtils.equals(mCallingAppPackageName, mLaunchPackage)) {
            Log.w(TAG, "sendDevicePickedIntent() launch package name is not equivalent to"
                    + " calling package name!");
        }
        mContext = getContext();
        setHasOptionsMenu(true);
    }
@@ -189,6 +206,11 @@ public final class DevicePickerFragment extends DeviceListPreferenceFragment {
    private void sendDevicePickedIntent(BluetoothDevice device) {
        Intent intent = new Intent(BluetoothDevicePicker.ACTION_DEVICE_SELECTED);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        if (mLaunchPackage != null && mLaunchClass != null) {
            if (TextUtils.equals(mCallingAppPackageName, mLaunchPackage)) {
                intent.setClassName(mLaunchPackage, mLaunchClass);
            }
        }

        mContext.sendBroadcast(intent, Manifest.permission.BLUETOOTH_ADMIN);
    }
+25 −1
Original line number Diff line number Diff line
@@ -16,8 +16,11 @@

package com.android.settings.bluetooth;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -66,16 +69,37 @@ public class DevicePickerFragmentTest {
    }

    @Test
    public void sendBroadcastWithPermission() {
    public void callingPackageIsEqualToLaunchPackage_sendBroadcastToLaunchPackage() {
        final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
        final BluetoothDevice bluetoothDevice = mock(BluetoothDevice.class);
        final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
        when(cachedDevice.getDevice()).thenReturn(bluetoothDevice);
        mFragment.mSelectedDevice = bluetoothDevice;
        mFragment.mLaunchPackage = "com.android.settings";
        mFragment.mLaunchClass = "com.android.settings.bluetooth.BluetoothPermissionActivity";
        mFragment.mCallingAppPackageName = "com.android.settings";

        mFragment.onDeviceBondStateChanged(cachedDevice, BluetoothDevice.BOND_BONDED);

        verify(mContext).sendBroadcast(intentCaptor.capture(),
                eq("android.permission.BLUETOOTH_ADMIN"));
        assertThat(intentCaptor.getValue().getComponent().getPackageName())
                .isEqualTo(mFragment.mLaunchPackage);
    }

    @Test
    public void callingPackageIsNotEqualToLaunchPackage_broadcastNotSend() {
        final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
        final BluetoothDevice bluetoothDevice = mock(BluetoothDevice.class);
        final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
        when(cachedDevice.getDevice()).thenReturn(bluetoothDevice);
        mFragment.mSelectedDevice = bluetoothDevice;
        mFragment.mLaunchPackage = "com.fake.settings";
        mFragment.mLaunchClass = "com.android.settings.bluetooth.BluetoothPermissionActivity";
        mFragment.mCallingAppPackageName = "com.android.settings";

        mFragment.onDeviceBondStateChanged(cachedDevice, BluetoothDevice.BOND_BONDED);

        verify(mContext, never()).sendBroadcast(intentCaptor.capture());
    }
}