From f727d5cf2ab9a88857c2d412f84f496ea4311f9b Mon Sep 17 00:00:00 2001 From: Hugh Chen Date: Fri, 12 Mar 2021 10:40:20 +0800 Subject: [PATCH] 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 bb5be240c0982f2e098978fec187fc735c0e7ad9) --- .../bluetooth/DevicePickerFragment.java | 33 +++++++++++++++++++ .../bluetooth/DevicePickerFragmentTest.java | 26 ++++++++++++++- 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/com/android/settings/bluetooth/DevicePickerFragment.java b/src/com/android/settings/bluetooth/DevicePickerFragment.java index 90d43e5374a..f720aefc29e 100644 --- a/src/com/android/settings/bluetooth/DevicePickerFragment.java +++ b/src/com/android/settings/bluetooth/DevicePickerFragment.java @@ -19,13 +19,18 @@ package com.android.settings.bluetooth; import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH; import android.Manifest; +import android.app.ActivityManager; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevicePicker; import android.content.Context; import android.content.Intent; import android.os.Bundle; +import android.os.IBinder; +import android.os.RemoteException; import android.os.UserManager; +import android.util.Log; +import android.text.TextUtils; import android.support.annotation.VisibleForTesting; import android.view.Menu; import android.view.MenuInflater; @@ -49,6 +54,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; @@ -63,6 +74,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); } @@ -82,6 +95,11 @@ 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 = 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); } @@ -182,7 +200,22 @@ 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); } + + private String getCallingAppPackageName(IBinder activityToken) { + String pkg = null; + try { + pkg = ActivityManager.getService().getLaunchedFromPackage(activityToken); + } catch (RemoteException e) { + Log.v(TAG, "Could not talk to activity manager.", e); + } + return pkg; + } } diff --git a/tests/robotests/src/com/android/settings/bluetooth/DevicePickerFragmentTest.java b/tests/robotests/src/com/android/settings/bluetooth/DevicePickerFragmentTest.java index bb77b7d6741..2bae7c18e6c 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/DevicePickerFragmentTest.java +++ b/tests/robotests/src/com/android/settings/bluetooth/DevicePickerFragmentTest.java @@ -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; @@ -68,16 +71,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 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 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()); } }