Merge "Fix use-after-free while setting advertisement data."
diff --git a/btif/include/btif_gatt_multi_adv_util.h b/btif/include/btif_gatt_multi_adv_util.h
index 4b44a51..fd1426f 100644
--- a/btif/include/btif_gatt_multi_adv_util.h
+++ b/btif/include/btif_gatt_multi_adv_util.h
@@ -83,13 +83,14 @@
BOOLEAN stop_timer);
// Free a buffer and reset *buf to NULL.
extern void btif_gattc_cleanup(void** buf);
-extern BOOLEAN btif_gattc_copy_datacb(int arrindex, btif_adv_data_t *p_adv_data,
+extern BOOLEAN btif_gattc_copy_datacb(int arrindex, const btif_adv_data_t *p_adv_data,
BOOLEAN bInstData);
extern void btif_gattc_adv_data_packager(int client_if, bool set_scan_rsp,
bool include_name, bool include_txpower, int min_interval, int max_interval,
int appearance, int manufacturer_len, char* manufacturer_data,
int service_data_len, char* service_data, int service_uuid_len,
char* service_uuid, btif_adv_data_t *p_multi_adv_inst);
+extern void btif_gattc_adv_data_cleanup(const btif_adv_data_t* adv);
void btif_multi_adv_timer_ctrl(int client_if, TIMER_CBACK cb);
#endif
diff --git a/btif/src/btif_gatt_client.c b/btif/src/btif_gatt_client.c
index df766c1..171725c 100644
--- a/btif/src/btif_gatt_client.c
+++ b/btif/src/btif_gatt_client.c
@@ -1058,6 +1058,23 @@
(char*) &btif_cb, sizeof(btgatt_adv_filter_cb_t), NULL);
}
+static void btgattc_free_event_data(UINT16 event, char *event_data)
+{
+ switch (event)
+ {
+ case BTIF_GATTC_ADV_INSTANCE_SET_DATA:
+ case BTIF_GATTC_SET_ADV_DATA:
+ {
+ const btif_adv_data_t *adv_data = (btif_adv_data_t*) event_data;
+ btif_gattc_adv_data_cleanup(adv_data);
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
static void btgattc_handle_event(uint16_t event, char* p_param)
{
tBTA_GATT_STATUS status;
@@ -1502,14 +1519,11 @@
case BTIF_GATTC_SET_ADV_DATA:
{
- btif_adv_data_t *p_adv_data = (btif_adv_data_t*) p_param;
- int cbindex = CLNT_IF_IDX;
- if (cbindex >= 0 && NULL != p_adv_data)
+ const btif_adv_data_t *p_adv_data = (btif_adv_data_t*) p_param;
+ const int cbindex = CLNT_IF_IDX;
+ if (cbindex >= 0 && btif_gattc_copy_datacb(cbindex, p_adv_data, false))
{
btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
- if (!btif_gattc_copy_datacb(cbindex, p_adv_data, false))
- return;
-
if (!p_adv_data->set_scan_rsp)
{
BTA_DmBleSetAdvConfig(p_multi_adv_data_cb->inst_cb[cbindex].mask,
@@ -1520,8 +1534,13 @@
BTA_DmBleSetScanRsp(p_multi_adv_data_cb->inst_cb[cbindex].mask,
&p_multi_adv_data_cb->inst_cb[cbindex].data, bta_gattc_set_adv_data_cback);
}
- break;
}
+ else
+ {
+ BTIF_TRACE_ERROR("%s:%s: failed to get instance data cbindex: %d",
+ __func__, "BTIF_GATTC_SET_ADV_DATA", cbindex);
+ }
+ break;
}
case BTIF_GATTC_ADV_INSTANCE_ENABLE:
@@ -1578,19 +1597,23 @@
btif_adv_data_t *p_adv_data = (btif_adv_data_t*) p_param;
int cbindex = btif_gattc_obtain_idx_for_datacb(p_adv_data->client_if, CLNT_IF_IDX);
int inst_id = btif_multi_adv_instid_for_clientif(p_adv_data->client_if);
- if (inst_id < 0 || cbindex < 0)
+ if (inst_id >= 0 && cbindex >= 0 && btif_gattc_copy_datacb(cbindex, p_adv_data, true))
{
- BTIF_TRACE_ERROR("%s invalid index in BTIF_GATTC_SETADV_INST_DATA", __FUNCTION__);
- return;
+ btgatt_multi_adv_common_data *p_multi_adv_data_cb =
+ btif_obtain_multi_adv_data_cb();
+ BTA_BleCfgAdvInstData(
+ (UINT8)inst_id,
+ p_multi_adv_data_cb->inst_cb[cbindex].is_scan_rsp,
+ p_multi_adv_data_cb->inst_cb[cbindex].mask,
+ &p_multi_adv_data_cb->inst_cb[cbindex].data);
}
-
- if (!btif_gattc_copy_datacb(cbindex, p_adv_data, true))
- return;
-
- btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
- BTA_BleCfgAdvInstData((UINT8)inst_id, p_multi_adv_data_cb->inst_cb[cbindex].is_scan_rsp,
- p_multi_adv_data_cb->inst_cb[cbindex].mask,
- &p_multi_adv_data_cb->inst_cb[cbindex].data);
+ else
+ {
+ BTIF_TRACE_ERROR(
+ "%s:%s: failed to get invalid instance data: inst_id:%d "
+ "cbindex:%d",
+ __func__, "BTIF_GATTC_ADV_INSTANCE_SET_DATA", inst_id, cbindex);
+ }
break;
}
@@ -1666,6 +1689,8 @@
LOG_ERROR("%s: Unknown event (%d)!", __FUNCTION__, event);
break;
}
+
+ btgattc_free_event_data(event, p_param);
}
/*******************************************************************************
@@ -1732,6 +1757,44 @@
(char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
}
+static void btif_gattc_deep_copy(UINT16 event, char *p_dest, char *p_src)
+{
+ switch (event)
+ {
+ case BTIF_GATTC_ADV_INSTANCE_SET_DATA:
+ case BTIF_GATTC_SET_ADV_DATA:
+ {
+ const btif_adv_data_t *src = (btif_adv_data_t*) p_src;
+ btif_adv_data_t *dst = (btif_adv_data_t*) p_dest;
+ memcpy(dst, src, sizeof(*src));
+
+ if (src->p_manufacturer_data)
+ {
+ dst->p_manufacturer_data = GKI_getbuf(src->manufacturer_len);
+ memcpy(dst->p_manufacturer_data, src->p_manufacturer_data,
+ src->manufacturer_len);
+ }
+
+ if (src->p_service_data)
+ {
+ dst->p_service_data = GKI_getbuf(src->service_data_len);
+ memcpy(dst->p_service_data, src->p_service_data, src->service_data_len);
+ }
+
+ if (src->p_service_uuid)
+ {
+ dst->p_service_uuid = GKI_getbuf(src->service_uuid_len);
+ memcpy(dst->p_service_uuid, src->p_service_uuid, src->service_uuid_len);
+ }
+ break;
+ }
+
+ default:
+ ASSERTC(false, "Unhandled deep copy", event);
+ break;
+ }
+}
+
static bt_status_t btif_gattc_set_adv_data(int client_if, bool set_scan_rsp, bool include_name,
bool include_txpower, int min_interval, int max_interval, int appearance,
uint16_t manufacturer_len, char* manufacturer_data,
@@ -1739,8 +1802,6 @@
uint16_t service_uuid_len, char* service_uuid)
{
CHECK_BTGATT_INIT();
- bt_status_t status =0;
-
btif_adv_data_t adv_data;
btif_gattc_adv_data_packager(client_if, set_scan_rsp, include_name,
@@ -1748,18 +1809,9 @@
manufacturer_data, service_data_len, service_data, service_uuid_len, service_uuid,
&adv_data);
- status = btif_transfer_context(btgattc_handle_event, BTIF_GATTC_SET_ADV_DATA,
- (char*) &adv_data, sizeof(btif_adv_data_t), NULL);
-
- if (NULL != adv_data.p_service_data)
- GKI_freebuf(adv_data.p_service_data);
-
- if (NULL != adv_data.p_service_uuid)
- GKI_freebuf(adv_data.p_service_uuid);
-
- if (NULL != adv_data.p_manufacturer_data)
- GKI_freebuf(adv_data.p_manufacturer_data);
-
+ bt_status_t status = btif_transfer_context(btgattc_handle_event, BTIF_GATTC_SET_ADV_DATA,
+ (char*) &adv_data, sizeof(adv_data), btif_gattc_deep_copy);
+ btif_gattc_adv_data_cleanup(&adv_data);
return status;
}
@@ -2141,28 +2193,21 @@
{
CHECK_BTGATT_INIT();
- int min_interval = 0, max_interval = 0;
- bt_status_t status =0;
-
btif_adv_data_t multi_adv_data_inst;
- memset(&multi_adv_data_inst, 0, sizeof(btif_adv_data_t));
+ memset(&multi_adv_data_inst, 0, sizeof(multi_adv_data_inst));
+
+ const int min_interval = 0;
+ const int max_interval = 0;
btif_gattc_adv_data_packager(client_if, set_scan_rsp, include_name, incl_txpower,
min_interval, max_interval, appearance, manufacturer_len, manufacturer_data,
service_data_len, service_data, service_uuid_len, service_uuid, &multi_adv_data_inst);
- status = btif_transfer_context(btgattc_handle_event, BTIF_GATTC_ADV_INSTANCE_SET_DATA,
- (char*) &multi_adv_data_inst, sizeof(btif_adv_data_t), NULL);
-
- if (NULL != multi_adv_data_inst.p_service_data)
- GKI_freebuf(multi_adv_data_inst.p_service_data);
-
- if (NULL != multi_adv_data_inst.p_service_uuid)
- GKI_freebuf(multi_adv_data_inst.p_service_uuid);
-
- if (NULL != multi_adv_data_inst.p_manufacturer_data)
- GKI_freebuf(multi_adv_data_inst.p_manufacturer_data);
-
+ bt_status_t status = btif_transfer_context(
+ btgattc_handle_event, BTIF_GATTC_ADV_INSTANCE_SET_DATA,
+ (char *)&multi_adv_data_inst, sizeof(multi_adv_data_inst),
+ btif_gattc_deep_copy);
+ btif_gattc_adv_data_cleanup(&multi_adv_data_inst);
return status;
}
diff --git a/btif/src/btif_gatt_multi_adv_util.c b/btif/src/btif_gatt_multi_adv_util.c
index 4837474..63bca08 100644
--- a/btif/src/btif_gatt_multi_adv_util.c
+++ b/btif/src/btif_gatt_multi_adv_util.c
@@ -252,8 +252,21 @@
}
}
-BOOLEAN btif_gattc_copy_datacb(int cbindex, btif_adv_data_t *p_adv_data, BOOLEAN bInstData)
+void btif_gattc_adv_data_cleanup(const btif_adv_data_t* adv)
{
+ if (adv->p_service_data)
+ GKI_freebuf(adv->p_service_data);
+
+ if (adv->p_service_uuid)
+ GKI_freebuf(adv->p_service_uuid);
+
+ if (adv->p_manufacturer_data)
+ GKI_freebuf(adv->p_manufacturer_data);
+}
+
+
+BOOLEAN btif_gattc_copy_datacb(int cbindex, const btif_adv_data_t *p_adv_data,
+ BOOLEAN bInstData) {
btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
if (NULL == p_multi_adv_data_cb || cbindex < 0)
return false;
@@ -377,18 +390,18 @@
}
}
- if (p_adv_data->service_uuid_len > 0 && NULL != p_adv_data->p_service_uuid)
+ if (p_adv_data->service_uuid_len && p_adv_data->p_service_uuid)
{
UINT16 *p_uuid_out16 = NULL;
UINT32 *p_uuid_out32 = NULL;
- while (p_adv_data->service_uuid_len >= LEN_UUID_128)
+ for (int position = 0; position < p_adv_data->service_uuid_len; position += LEN_UUID_128)
{
bt_uuid_t uuid;
- memset(&uuid, 0, sizeof(bt_uuid_t));
- memcpy(&uuid.uu, p_adv_data->p_service_uuid, LEN_UUID_128);
+ memset(&uuid, 0, sizeof(uuid));
+ memcpy(&uuid.uu, p_adv_data->p_service_uuid + position, LEN_UUID_128);
tBT_UUID bt_uuid;
- memset(&bt_uuid, 0, sizeof(tBT_UUID));
+ memset(&bt_uuid, 0, sizeof(bt_uuid));
btif_to_bta_uuid(&bt_uuid, &uuid);
switch(bt_uuid.len)
@@ -467,9 +480,6 @@
default:
break;
}
-
- p_adv_data->p_service_uuid += LEN_UUID_128;
- p_adv_data->service_uuid_len -= LEN_UUID_128;
}
}