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

Commit 890e1870 authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Avoid calling self through public APIs.

We'd like to enforce that all incoming Binder calls have valid
AttributionSource UID information, but this uncovered trouble in
cases where the Bluetooth stack was calling back into itself.

We could solve this with Binder.clearCallingIdentity(), but making
that widespread change risks data leakage.  Instead, this change
replaces all places where ProfileService calls BluetoothAdapter
with direct calls to the internal AdapterService.

We also pivot to obtaining all BluetoothDevice instances using
the getAnonymousDevice() method which removes any AttributionSource
to ensure they can't be accidentally used locally; these instances
are always returned back to remote callers where the relevant source
is populated by Attributable.setAttributionSource().

Bug: 188391719
Test: atest BluetoothInstrumentationTests
Change-Id: Idb55693557c0c6ab689d9e37f3e2e9ab4587da12
parent d03df10f
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -523,7 +523,7 @@ public class A2dpSinkService extends ProfileService {
    public native void informAudioTrackGainNative(float gain);

    private void onConnectionStateChanged(byte[] address, int state) {
        StackEvent event = StackEvent.connectionStateChanged(getDevice(address), state);
        StackEvent event = StackEvent.connectionStateChanged(getAnonymousDevice(address), state);
        A2dpSinkStateMachine stateMachine = getOrCreateStateMachine(event.mDevice);
        stateMachine.sendMessage(A2dpSinkStateMachine.STACK_EVENT, event);
    }
@@ -545,7 +545,7 @@ public class A2dpSinkService extends ProfileService {
    }

    private void onAudioConfigChanged(byte[] address, int sampleRate, int channelCount) {
        StackEvent event = StackEvent.audioConfigChanged(getDevice(address), sampleRate,
        StackEvent event = StackEvent.audioConfigChanged(getAnonymousDevice(address), sampleRate,
                channelCount);
        A2dpSinkStateMachine stateMachine = getOrCreateStateMachine(event.mDevice);
        stateMachine.sendMessage(A2dpSinkStateMachine.STACK_EVENT, event);
+25 −28
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.util.Log;
import com.android.bluetooth.R;
import com.android.bluetooth.Utils;
import com.android.bluetooth.a2dpsink.A2dpSinkService;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.ProfileService;

import java.util.ArrayList;
@@ -98,7 +99,8 @@ public class AvrcpControllerService extends ProfileService {

    static BrowseTree sBrowseTree;
    private static AvrcpControllerService sService;
    private final BluetoothAdapter mAdapter;

    private AdapterService mAdapterService;

    protected Map<BluetoothDevice, AvrcpControllerStateMachine> mDeviceStateMap =
            new ConcurrentHashMap<>(1);
@@ -131,14 +133,10 @@ public class AvrcpControllerService extends ProfileService {
        classInitNative();
    }

    public AvrcpControllerService() {
        super();
        mAdapter = BluetoothAdapter.getDefaultAdapter();
    }

    @Override
    protected synchronized boolean start() {
        initNative();
        mAdapterService = AdapterService.getAdapterService();
        mCoverArtEnabled = getResources().getBoolean(R.bool.avrcp_controller_enable_cover_art);
        if (mCoverArtEnabled) {
            mCoverArtManager = new AvrcpCoverArtManager(this, new ImageDownloadCallback());
@@ -449,7 +447,7 @@ public class AvrcpControllerService extends ProfileService {
    // Called by JNI when a device has connected or disconnected.
    private synchronized void onConnectionStateChanged(boolean remoteControlConnected,
            boolean browsingConnected, byte[] address) {
        BluetoothDevice device = mAdapter.getRemoteDevice(address);
        BluetoothDevice device = getAnonymousDevice(address);
        if (DBG) {
            Log.d(TAG, "onConnectionStateChanged " + remoteControlConnected + " "
                    + browsingConnected + device);
@@ -483,7 +481,7 @@ public class AvrcpControllerService extends ProfileService {

    // Called by JNI to notify Avrcp of a remote device's Cover Art PSM
    private void getRcPsm(byte[] address, int psm) {
        BluetoothDevice device = mAdapter.getRemoteDevice(address);
        BluetoothDevice device = getAnonymousDevice(address);
        if (DBG) Log.d(TAG, "getRcPsm(device=" + device + ", psm=" + psm + ")");
        AvrcpControllerStateMachine stateMachine = getOrCreateStateMachine(device);
        if (stateMachine != null) {
@@ -502,7 +500,7 @@ public class AvrcpControllerService extends ProfileService {
        if (DBG) {
            Log.d(TAG, "handleRegisterNotificationAbsVol");
        }
        BluetoothDevice device = mAdapter.getRemoteDevice(address);
        BluetoothDevice device = getAnonymousDevice(address);
        AvrcpControllerStateMachine stateMachine = getStateMachine(device);
        if (stateMachine != null) {
            stateMachine.sendMessage(
@@ -515,7 +513,7 @@ public class AvrcpControllerService extends ProfileService {
        if (DBG) {
            Log.d(TAG, "handleSetAbsVolume ");
        }
        BluetoothDevice device = mAdapter.getRemoteDevice(address);
        BluetoothDevice device = getAnonymousDevice(address);
        AvrcpControllerStateMachine stateMachine = getStateMachine(device);
        if (stateMachine != null) {
            stateMachine.sendMessage(AvrcpControllerStateMachine.MESSAGE_PROCESS_SET_ABS_VOL_CMD,
@@ -530,7 +528,7 @@ public class AvrcpControllerService extends ProfileService {
            Log.d(TAG, "onTrackChanged");
        }

        BluetoothDevice device = mAdapter.getRemoteDevice(address);
        BluetoothDevice device = getAnonymousDevice(address);
        AvrcpControllerStateMachine stateMachine = getStateMachine(device);
        if (stateMachine != null) {
            AvrcpItem.Builder aib = new AvrcpItem.Builder();
@@ -556,7 +554,7 @@ public class AvrcpControllerService extends ProfileService {
        if (DBG) {
            Log.d(TAG, "onPlayPositionChanged pos " + currSongPosition);
        }
        BluetoothDevice device = mAdapter.getRemoteDevice(address);
        BluetoothDevice device = getAnonymousDevice(address);
        AvrcpControllerStateMachine stateMachine = getStateMachine(device);
        if (stateMachine != null) {
            stateMachine.sendMessage(
@@ -570,7 +568,7 @@ public class AvrcpControllerService extends ProfileService {
        if (DBG) {
            Log.d(TAG, "onPlayStatusChanged " + playStatus);
        }
        BluetoothDevice device = mAdapter.getRemoteDevice(address);
        BluetoothDevice device = getAnonymousDevice(address);
        AvrcpControllerStateMachine stateMachine = getStateMachine(device);
        if (stateMachine != null) {
            stateMachine.sendMessage(
@@ -585,7 +583,7 @@ public class AvrcpControllerService extends ProfileService {
        if (DBG) {
            Log.d(TAG, "handlePlayerAppSetting rspLen = " + rspLen);
        }
        BluetoothDevice device = mAdapter.getRemoteDevice(address);
        BluetoothDevice device = getAnonymousDevice(address);
        AvrcpControllerStateMachine stateMachine = getStateMachine(device);
        if (stateMachine != null) {
            PlayerApplicationSettings supportedSettings =
@@ -601,7 +599,7 @@ public class AvrcpControllerService extends ProfileService {
        if (DBG) {
            Log.d(TAG, "onPlayerAppSettingChanged ");
        }
        BluetoothDevice device = mAdapter.getRemoteDevice(address);
        BluetoothDevice device = getAnonymousDevice(address);
        AvrcpControllerStateMachine stateMachine = getStateMachine(device);
        if (stateMachine != null) {

@@ -617,7 +615,7 @@ public class AvrcpControllerService extends ProfileService {
        if (DBG) {
            Log.d(TAG," onAvailablePlayerChanged");
        }
        BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address);
        BluetoothDevice device = getAnonymousDevice(address);

        AvrcpControllerStateMachine stateMachine = getStateMachine(device);
        if (stateMachine != null) {
@@ -632,7 +630,7 @@ public class AvrcpControllerService extends ProfileService {
                    + items.length + " items.");
        }

        BluetoothDevice device = mAdapter.getRemoteDevice(address);
        BluetoothDevice device = getAnonymousDevice(address);
        List<AvrcpItem> itemsList = new ArrayList<>();
        for (AvrcpItem item : items) {
            if (VDBG) Log.d(TAG, item.toString());
@@ -663,7 +661,7 @@ public class AvrcpControllerService extends ProfileService {
            itemsList.add(item);
        }

        BluetoothDevice device = mAdapter.getRemoteDevice(address);
        BluetoothDevice device = getAnonymousDevice(address);
        AvrcpControllerStateMachine stateMachine = getStateMachine(device);
        if (stateMachine != null) {
            stateMachine.sendMessage(AvrcpControllerStateMachine.MESSAGE_PROCESS_GET_PLAYER_ITEMS,
@@ -679,7 +677,7 @@ public class AvrcpControllerService extends ProfileService {
                    + " attrids: " + attrIds + " attrVals: " + attrVals);
        }

        BluetoothDevice device = mAdapter.getRemoteDevice(address);
        BluetoothDevice device = getAnonymousDevice(address);
        AvrcpItem.Builder aib = new AvrcpItem.Builder().fromAvrcpAttributeArray(attrIds, attrVals);
        aib.setDevice(device);
        aib.setItemType(AvrcpItem.TYPE_MEDIA);
@@ -698,7 +696,7 @@ public class AvrcpControllerService extends ProfileService {
                    + name + " playable " + playable);
        }

        BluetoothDevice device = mAdapter.getRemoteDevice(address);
        BluetoothDevice device = getAnonymousDevice(address);
        AvrcpItem.Builder aib = new AvrcpItem.Builder();
        aib.setDevice(device);
        aib.setItemType(AvrcpItem.TYPE_FOLDER);
@@ -719,8 +717,7 @@ public class AvrcpControllerService extends ProfileService {
                            + transportFlags + " play status " + playStatus + " player type "
                            + playerType);
        }

        BluetoothDevice device = mAdapter.getRemoteDevice(address);
        BluetoothDevice device = getAnonymousDevice(address);
        AvrcpPlayer.Builder apb = new AvrcpPlayer.Builder();
        apb.setDevice(device);
        apb.setPlayerId(id);
@@ -735,7 +732,7 @@ public class AvrcpControllerService extends ProfileService {
        if (DBG) {
            Log.d(TAG, "handleChangeFolderRsp count: " + count);
        }
        BluetoothDevice device = mAdapter.getRemoteDevice(address);
        BluetoothDevice device = getAnonymousDevice(address);
        AvrcpControllerStateMachine stateMachine = getStateMachine(device);
        if (stateMachine != null) {
            stateMachine.sendMessage(AvrcpControllerStateMachine.MESSAGE_PROCESS_FOLDER_PATH,
@@ -747,7 +744,7 @@ public class AvrcpControllerService extends ProfileService {
        if (DBG) {
            Log.d(TAG, "handleSetBrowsedPlayerRsp depth: " + depth);
        }
        BluetoothDevice device = mAdapter.getRemoteDevice(address);
        BluetoothDevice device = getAnonymousDevice(address);

        AvrcpControllerStateMachine stateMachine = getStateMachine(device);
        if (stateMachine != null) {
@@ -760,7 +757,7 @@ public class AvrcpControllerService extends ProfileService {
        if (DBG) {
            Log.d(TAG, "handleSetAddressedPlayerRsp status: " + status);
        }
        BluetoothDevice device = mAdapter.getRemoteDevice(address);
        BluetoothDevice device = getAnonymousDevice(address);

        AvrcpControllerStateMachine stateMachine = getStateMachine(device);
        if (stateMachine != null) {
@@ -773,7 +770,7 @@ public class AvrcpControllerService extends ProfileService {
        if (DBG) {
            Log.d(TAG, "handleAddressedPlayerChanged id: " + id);
        }
        BluetoothDevice device = mAdapter.getRemoteDevice(address);
        BluetoothDevice device = getAnonymousDevice(address);

        AvrcpControllerStateMachine stateMachine = getStateMachine(device);
        if (stateMachine != null) {
@@ -786,7 +783,7 @@ public class AvrcpControllerService extends ProfileService {
        if (DBG) {
            Log.d(TAG, "handleNowPlayingContentChanged");
        }
        BluetoothDevice device = mAdapter.getRemoteDevice(address);
        BluetoothDevice device = getAnonymousDevice(address);

        AvrcpControllerStateMachine stateMachine = getStateMachine(device);
        if (stateMachine != null) {
@@ -867,7 +864,7 @@ public class AvrcpControllerService extends ProfileService {
    List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
        if (DBG) Log.d(TAG, "getDevicesMatchingConnectionStates" + Arrays.toString(states));
        List<BluetoothDevice> deviceList = new ArrayList<>();
        Set<BluetoothDevice> bondedDevices = mAdapter.getBondedDevices();
        BluetoothDevice[] bondedDevices = mAdapterService.getBondedDevices();
        int connectionState;
        for (BluetoothDevice device : bondedDevices) {
            connectionState = getConnectionState(device);
+4 −0
Original line number Diff line number Diff line
@@ -2455,6 +2455,10 @@ public class AdapterService extends Service {

    // ----API Methods--------

    public boolean isEnabled() {
        return getState() == BluetoothAdapter.STATE_ON;
    }

    public int getState() {
        if (mAdapterProperties != null) {
            return mAdapterProperties.getState();
+27 −5
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.app.ActivityManager;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Attributable;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -338,10 +339,31 @@ public abstract class ProfileService extends Service {
        stopSelf();
    }

    protected BluetoothDevice getDevice(byte[] address) {
        if (mAdapter != null) {
            return mAdapter.getRemoteDevice(Utils.getAddressStringFromByte(address));
    /**
     * Returns a {@link BluetoothDevice} instance for the given address, but
     * with any {@link AttributionSource} details removed, making it "anonymous"
     * and not suitable for local use within this process.
     * <p>
     * The returned object is intended to be returned to a remote caller for
     * actual use, where {@link Attributable#setAttributionSource} will populate
     * it accurately.
     */
    protected BluetoothDevice getAnonymousDevice(String address) {
        return Attributable.setAttributionSource(
                BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address), null);
    }
        return null;

    /**
     * Returns a {@link BluetoothDevice} instance for the given address, but
     * with any {@link AttributionSource} details removed, making it "anonymous"
     * and not suitable for local use within this process.
     * <p>
     * The returned object is intended to be returned to a remote caller for
     * actual use, where {@link Attributable#setAttributionSource} will populate
     * it accurately.
     */
    protected BluetoothDevice getAnonymousDevice(byte[] address) {
        return Attributable.setAttributionSource(
                BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address), null);
    }
}
+7 −11
Original line number Diff line number Diff line
@@ -207,7 +207,6 @@ public class GattService extends ProfileService {
     */
    private final Map<Integer, Set<Integer>> mRestrictedHandles = new HashMap<>();

    private BluetoothAdapter mAdapter;
    private AdapterService mAdapterService;
    private AdvertiseManager mAdvertiseManager;
    private PeriodicScanManager mPeriodicScanManager;
@@ -261,7 +260,6 @@ public class GattService extends ProfileService {
                getContentResolver(), "bluetooth_sanitized_exposure_notification_supported", 1);

        initializeNative();
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        mAdapterService = AdapterService.getAdapterService();
        mCompanionManager = ICompanionDeviceManager.Stub.asInterface(
                ServiceManager.getService(Context.COMPANION_DEVICE_SERVICE));
@@ -1162,7 +1160,7 @@ public class GattService extends ProfileService {
                continue;
            }

            BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address);
            BluetoothDevice device = getAnonymousDevice(address);

            ScanSettings settings = client.settings;
            byte[] scanRecordData;
@@ -1935,7 +1933,7 @@ public class GattService extends ProfileService {
                    extractBytes(batchRecord, i * TRUNCATED_RESULT_SIZE, TRUNCATED_RESULT_SIZE);
            byte[] address = extractBytes(record, 0, 6);
            reverse(address);
            BluetoothDevice device = mAdapter.getRemoteDevice(address);
            BluetoothDevice device = getAnonymousDevice(address);
            int rssi = record[8];
            long timestampNanos = now - parseTimestampNanos(extractBytes(record, 9, 2));
            results.add(new ScanResult(device, ScanRecord.parseFromBytes(new byte[0]), rssi,
@@ -1962,7 +1960,7 @@ public class GattService extends ProfileService {
            byte[] address = extractBytes(batchRecord, position, 6);
            // TODO: remove temp hack.
            reverse(address);
            BluetoothDevice device = mAdapter.getRemoteDevice(address);
            BluetoothDevice device = getAnonymousDevice(address);
            position += 6;
            // Skip address type.
            position++;
@@ -2040,8 +2038,7 @@ public class GattService extends ProfileService {
            return;
        }

        BluetoothDevice device =
                BluetoothAdapter.getDefaultAdapter().getRemoteDevice(trackingInfo.getAddress());
        BluetoothDevice device = getAnonymousDevice(trackingInfo.getAddress());
        int advertiserState = trackingInfo.getAdvState();
        ScanResult result =
                new ScanResult(device, ScanRecord.parseFromBytes(trackingInfo.getResult()),
@@ -2159,7 +2156,7 @@ public class GattService extends ProfileService {

        // Add paired LE devices

        Set<BluetoothDevice> bondedDevices = mAdapter.getBondedDevices();
        BluetoothDevice[] bondedDevices = mAdapterService.getBondedDevices();
        for (BluetoothDevice device : bondedDevices) {
            if (getDeviceType(device) != AbstractionLayer.BT_DEVICE_TYPE_BREDR) {
                deviceStates.put(device, BluetoothProfile.STATE_DISCONNECTED);
@@ -2173,7 +2170,7 @@ public class GattService extends ProfileService {
        connectedDevices.addAll(mServerMap.getConnectedDevices());

        for (String address : connectedDevices) {
            BluetoothDevice device = mAdapter.getRemoteDevice(address);
            BluetoothDevice device = getAnonymousDevice(address);
            if (device != null) {
                deviceStates.put(device, BluetoothProfile.STATE_CONNECTED);
            }
@@ -3649,9 +3646,8 @@ public class GattService extends ProfileService {
    }

    private boolean needsPrivilegedPermissionForScan(ScanSettings settings) {
        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
        // BLE scan only mode needs special permission.
        if (adapter.getState() != BluetoothAdapter.STATE_ON) {
        if (mAdapterService.getState() != BluetoothAdapter.STATE_ON) {
            return true;
        }

Loading