summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack He <siyuanh@google.com>2022-04-21 19:18:06 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2022-04-21 19:18:06 +0000
commitc24f5b9f8fff1718cfd4f34cd16fb0dcd11aa34b (patch)
tree09bf35ff1bbaa79bb2ea621b47d3c3b498b59ea2
parente677ade8a3973f29601c88afdb1b5566aafd4f81 (diff)
parent63dea920a871a0c25239060e992dc7933f399317 (diff)
Merge "Check length of advertising data" am: 63dea920a8
Original change: https://android-review.googlesource.com/c/platform/packages/modules/Bluetooth/+/2063152 Change-Id: Ib5ad263053a241983d666ceeb552765e6bee1e66 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--android/app/src/com/android/bluetooth/gatt/AdvertiseHelper.java20
-rw-r--r--android/app/src/com/android/bluetooth/gatt/AdvertiseManager.java59
-rw-r--r--system/gd/hci/le_advertising_manager.cc27
3 files changed, 97 insertions, 9 deletions
diff --git a/android/app/src/com/android/bluetooth/gatt/AdvertiseHelper.java b/android/app/src/com/android/bluetooth/gatt/AdvertiseHelper.java
index 5f48a07657..90a52bf2aa 100644
--- a/android/app/src/com/android/bluetooth/gatt/AdvertiseHelper.java
+++ b/android/app/src/com/android/bluetooth/gatt/AdvertiseHelper.java
@@ -71,6 +71,7 @@ class AdvertiseHelper {
type = COMPLETE_LOCAL_NAME;
}
+ check_length(type, nameLength + 1);
ret.write(nameLength + 1);
ret.write(type);
ret.write(nameBytes, 0, nameLength);
@@ -92,6 +93,7 @@ class AdvertiseHelper {
System.arraycopy(manufacturerData, 0, concated, 2, manufacturerData.length);
}
+ check_length(MANUFACTURER_SPECIFIC_DATA, concated.length + 1);
ret.write(concated.length + 1);
ret.write(MANUFACTURER_SPECIFIC_DATA);
ret.write(concated, 0, concated.length);
@@ -121,18 +123,21 @@ class AdvertiseHelper {
}
if (serviceUuids16.size() != 0) {
+ check_length(COMPLETE_LIST_16_BIT_SERVICE_UUIDS, serviceUuids16.size() + 1);
ret.write(serviceUuids16.size() + 1);
ret.write(COMPLETE_LIST_16_BIT_SERVICE_UUIDS);
ret.write(serviceUuids16.toByteArray(), 0, serviceUuids16.size());
}
if (serviceUuids32.size() != 0) {
+ check_length(COMPLETE_LIST_32_BIT_SERVICE_UUIDS, serviceUuids32.size() + 1);
ret.write(serviceUuids32.size() + 1);
ret.write(COMPLETE_LIST_32_BIT_SERVICE_UUIDS);
ret.write(serviceUuids32.toByteArray(), 0, serviceUuids32.size());
}
if (serviceUuids128.size() != 0) {
+ check_length(COMPLETE_LIST_128_BIT_SERVICE_UUIDS, serviceUuids32.size() + 1);
ret.write(serviceUuids128.size() + 1);
ret.write(COMPLETE_LIST_128_BIT_SERVICE_UUIDS);
ret.write(serviceUuids128.toByteArray(), 0, serviceUuids128.size());
@@ -156,14 +161,17 @@ class AdvertiseHelper {
}
if (uuid.length == BluetoothUuid.UUID_BYTES_16_BIT) {
+ check_length(SERVICE_DATA_16_BIT_UUID, concated.length + 1);
ret.write(concated.length + 1);
ret.write(SERVICE_DATA_16_BIT_UUID);
ret.write(concated, 0, concated.length);
} else if (uuid.length == BluetoothUuid.UUID_BYTES_32_BIT) {
+ check_length(SERVICE_DATA_32_BIT_UUID, concated.length + 1);
ret.write(concated.length + 1);
ret.write(SERVICE_DATA_32_BIT_UUID);
ret.write(concated, 0, concated.length);
} else /*if (uuid.length == BluetoothUuid.UUID_BYTES_128_BIT)*/ {
+ check_length(SERVICE_DATA_128_BIT_UUID, concated.length + 1);
ret.write(concated.length + 1);
ret.write(SERVICE_DATA_128_BIT_UUID);
ret.write(concated, 0, concated.length);
@@ -190,18 +198,21 @@ class AdvertiseHelper {
}
if (serviceUuids16.size() != 0) {
+ check_length(LIST_16_BIT_SERVICE_SOLICITATION_UUIDS, serviceUuids16.size() + 1);
ret.write(serviceUuids16.size() + 1);
ret.write(LIST_16_BIT_SERVICE_SOLICITATION_UUIDS);
ret.write(serviceUuids16.toByteArray(), 0, serviceUuids16.size());
}
if (serviceUuids32.size() != 0) {
+ check_length(LIST_32_BIT_SERVICE_SOLICITATION_UUIDS, serviceUuids32.size() + 1);
ret.write(serviceUuids32.size() + 1);
ret.write(LIST_32_BIT_SERVICE_SOLICITATION_UUIDS);
ret.write(serviceUuids32.toByteArray(), 0, serviceUuids32.size());
}
if (serviceUuids128.size() != 0) {
+ check_length(LIST_128_BIT_SERVICE_SOLICITATION_UUIDS, serviceUuids128.size() + 1);
ret.write(serviceUuids128.size() + 1);
ret.write(LIST_128_BIT_SERVICE_SOLICITATION_UUIDS);
ret.write(serviceUuids128.toByteArray(), 0, serviceUuids128.size());
@@ -209,6 +220,7 @@ class AdvertiseHelper {
}
for (TransportDiscoveryData transportDiscoveryData : data.getTransportDiscoveryData()) {
+ check_length(TRANSPORT_DISCOVERY_DATA, transportDiscoveryData.totalBytes() + 1);
ret.write(transportDiscoveryData.totalBytes() + 1);
ret.write(TRANSPORT_DISCOVERY_DATA);
ret.write(transportDiscoveryData.toByteArray(),
@@ -216,4 +228,12 @@ class AdvertiseHelper {
}
return ret.toByteArray();
}
+
+ static void check_length(int type, int length) {
+ if (length > 255) {
+ Log.w(TAG, "Length of data with type " + Integer.toString(type, 16)
+ + " is grater than 255");
+ throw new IllegalArgumentException("Length of data is grater than 255");
+ }
+ }
}
diff --git a/android/app/src/com/android/bluetooth/gatt/AdvertiseManager.java b/android/app/src/com/android/bluetooth/gatt/AdvertiseManager.java
index b76d8619d8..e02fd6f73f 100644
--- a/android/app/src/com/android/bluetooth/gatt/AdvertiseManager.java
+++ b/android/app/src/com/android/bluetooth/gatt/AdvertiseManager.java
@@ -16,6 +16,7 @@
package com.android.bluetooth.gatt;
+import android.bluetooth.le.AdvertiseCallback;
import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.AdvertisingSetParameters;
import android.bluetooth.le.IAdvertisingSetCallback;
@@ -195,9 +196,12 @@ class AdvertiseManager {
}
String deviceName = AdapterService.getAdapterService().getName();
- byte[] advDataBytes = AdvertiseHelper.advertiseDataToBytes(advertiseData, deviceName);
- byte[] scanResponseBytes = AdvertiseHelper.advertiseDataToBytes(scanResponse, deviceName);
- byte[] periodicDataBytes = AdvertiseHelper.advertiseDataToBytes(periodicData, deviceName);
+ try {
+ byte[] advDataBytes = AdvertiseHelper.advertiseDataToBytes(advertiseData, deviceName);
+ byte[] scanResponseBytes =
+ AdvertiseHelper.advertiseDataToBytes(scanResponse, deviceName);
+ byte[] periodicDataBytes =
+ AdvertiseHelper.advertiseDataToBytes(periodicData, deviceName);
int cbId = --sTempRegistrationId;
mAdvertisers.put(binder, new AdvertiserInfo(cbId, deathRecipient, callback));
@@ -207,6 +211,16 @@ class AdvertiseManager {
}
startAdvertisingSetNative(parameters, advDataBytes, scanResponseBytes, periodicParameters,
periodicDataBytes, duration, maxExtAdvEvents, cbId);
+
+ } catch (IllegalArgumentException e) {
+ try {
+ binder.unlinkToDeath(deathRecipient, 0);
+ callback.onAdvertisingSetStarted(0x00, 0x00,
+ AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE);
+ } catch (RemoteException exception) {
+ Log.e(TAG, "Failed to callback:" + Log.getStackTraceString(exception));
+ }
+ }
}
void onOwnAddressRead(int advertiserId, int addressType, String address)
@@ -280,8 +294,17 @@ class AdvertiseManager {
return;
}
String deviceName = AdapterService.getAdapterService().getName();
- setAdvertisingDataNative(advertiserId,
- AdvertiseHelper.advertiseDataToBytes(data, deviceName));
+ try {
+ setAdvertisingDataNative(advertiserId,
+ AdvertiseHelper.advertiseDataToBytes(data, deviceName));
+ } catch (IllegalArgumentException e) {
+ try {
+ onAdvertisingDataSet(advertiserId,
+ AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE);
+ } catch (Exception exception) {
+ Log.e(TAG, "Failed to callback:" + Log.getStackTraceString(exception));
+ }
+ }
}
void setScanResponseData(int advertiserId, AdvertiseData data) {
@@ -291,8 +314,17 @@ class AdvertiseManager {
return;
}
String deviceName = AdapterService.getAdapterService().getName();
- setScanResponseDataNative(advertiserId,
- AdvertiseHelper.advertiseDataToBytes(data, deviceName));
+ try {
+ setScanResponseDataNative(advertiserId,
+ AdvertiseHelper.advertiseDataToBytes(data, deviceName));
+ } catch (IllegalArgumentException e) {
+ try {
+ onScanResponseDataSet(advertiserId,
+ AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE);
+ } catch (Exception exception) {
+ Log.e(TAG, "Failed to callback:" + Log.getStackTraceString(exception));
+ }
+ }
}
void setAdvertisingParameters(int advertiserId, AdvertisingSetParameters parameters) {
@@ -321,8 +353,17 @@ class AdvertiseManager {
return;
}
String deviceName = AdapterService.getAdapterService().getName();
- setPeriodicAdvertisingDataNative(advertiserId,
- AdvertiseHelper.advertiseDataToBytes(data, deviceName));
+ try {
+ setPeriodicAdvertisingDataNative(advertiserId,
+ AdvertiseHelper.advertiseDataToBytes(data, deviceName));
+ } catch (IllegalArgumentException e) {
+ try {
+ onPeriodicAdvertisingDataSet(advertiserId,
+ AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE);
+ } catch (Exception exception) {
+ Log.e(TAG, "Failed to callback:" + Log.getStackTraceString(exception));
+ }
+ }
}
void setPeriodicAdvertisingEnable(int advertiserId, boolean enable) {
diff --git a/system/gd/hci/le_advertising_manager.cc b/system/gd/hci/le_advertising_manager.cc
index c43eee9ff6..a64666b86b 100644
--- a/system/gd/hci/le_advertising_manager.cc
+++ b/system/gd/hci/le_advertising_manager.cc
@@ -351,6 +351,14 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
return;
}
+ // check extended advertising data is valid before start advertising
+ if (!check_extended_advertising_data(config.advertisement) ||
+ !check_extended_advertising_data(config.scan_response)) {
+ advertising_callbacks_->OnAdvertisingSetStarted(
+ reg_id, id, le_physical_channel_tx_power_, AdvertisingCallback::AdvertisingStatus::DATA_TOO_LARGE);
+ return;
+ }
+
if (!address_manager_registered) {
le_address_manager_->Register(this);
address_manager_registered = true;
@@ -629,6 +637,25 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
}
}
+ bool check_extended_advertising_data(std::vector<GapData> data) {
+ uint16_t data_len = 0;
+ // check data size
+ for (size_t i = 0; i < data.size(); i++) {
+ if (data[i].size() > kLeMaximumFragmentLength) {
+ LOG_WARN("AD data len shall not greater than %d", kLeMaximumFragmentLength);
+ return false;
+ }
+ data_len += data[i].size();
+ }
+
+ if (data_len > le_maximum_advertising_data_length_) {
+ LOG_WARN(
+ "advertising data len exceeds le_maximum_advertising_data_length_ %d", le_maximum_advertising_data_length_);
+ return false;
+ }
+ return true;
+ };
+
void set_data(AdvertiserId advertiser_id, bool set_scan_rsp, std::vector<GapData> data) {
if (!set_scan_rsp && advertising_sets_[advertiser_id].connectable) {
GapData gap_data;