aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Delwiche <delwiche@google.com>2022-10-11 21:23:22 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-04-19 16:53:31 +0000
commit494b9e2cc4f96bb03b25a3896a4099ea409dca33 (patch)
treec9584de82004d3b0e44f7c13a345f587a6d55a26
parentd03ad447546e1f71b55782d75a0251ec0b63d6b9 (diff)
downloadbt-494b9e2cc4f96bb03b25a3896a4099ea409dca33.tar.gz
Prevent use-after-free of HID reports
BTA sends the the HID report pointer to BTIF and deallocates it immediately. This is now prevented by providing a deep copy callback function for HID reports when tranferring context from BTA to BTIF. This is a backport of change Icef7a7ed1185b4283ee4fe4f812ca154d8f1b825, already merged on T for b/227620181. Bug: 228837201 Test: Validated against researcher POC, ran BT unit tests, played audio manually. Tag: #security Ignore-AOSP-First: Security (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:874c495c886cd8722625756dc5fd0634b16b4f42) Merged-In: Ib837f395883de2369207f1b3b974d6bff02dcb19 Change-Id: Ib837f395883de2369207f1b3b974d6bff02dcb19
-rw-r--r--btif/src/btif_hh.cc50
1 files changed, 45 insertions, 5 deletions
diff --git a/btif/src/btif_hh.cc b/btif/src/btif_hh.cc
index 5380fa566..97479e040 100644
--- a/btif/src/btif_hh.cc
+++ b/btif/src/btif_hh.cc
@@ -1095,6 +1095,38 @@ static void btif_hh_upstreams_evt(uint16_t event, char* p_param) {
/*******************************************************************************
*
+ * Function btif_hh_hsdata_rpt_copy_cb
+ *
+ * Description Deep copies the tBTA_HH_HSDATA structure
+ *
+ * Returns void
+ *
+ ******************************************************************************/
+
+static void btif_hh_hsdata_rpt_copy_cb(uint16_t event, char* p_dest,
+ char* p_src) {
+ tBTA_HH_HSDATA* p_dst_data = (tBTA_HH_HSDATA*)p_dest;
+ tBTA_HH_HSDATA* p_src_data = (tBTA_HH_HSDATA*)p_src;
+ BT_HDR* hdr;
+
+ if (!p_src) {
+ BTIF_TRACE_ERROR("%s: Nothing to copy", __func__);
+ return;
+ }
+
+ memcpy(p_dst_data, p_src_data, sizeof(tBTA_HH_HSDATA));
+
+ hdr = p_src_data->rsp_data.p_rpt_data;
+ if (hdr != NULL) {
+ uint8_t* p_data = ((uint8_t*)p_dst_data) + sizeof(tBTA_HH_HSDATA);
+ memcpy(p_data, hdr, BT_HDR_SIZE + hdr->offset + hdr->len);
+
+ p_dst_data->rsp_data.p_rpt_data = (BT_HDR*)p_data;
+ }
+}
+
+/*******************************************************************************
+ *
* Function bte_hh_evt
*
* Description Switches context from BTE to BTIF for all HH events
@@ -1106,6 +1138,7 @@ static void btif_hh_upstreams_evt(uint16_t event, char* p_param) {
void bte_hh_evt(tBTA_HH_EVT event, tBTA_HH* p_data) {
bt_status_t status;
int param_len = 0;
+ tBTIF_COPY_CBACK* p_copy_cback = NULL;
if (BTA_HH_ENABLE_EVT == event)
param_len = sizeof(tBTA_HH_STATUS);
@@ -1117,11 +1150,18 @@ void bte_hh_evt(tBTA_HH_EVT event, tBTA_HH* p_data) {
param_len = sizeof(tBTA_HH_CBDATA);
else if (BTA_HH_GET_DSCP_EVT == event)
param_len = sizeof(tBTA_HH_DEV_DSCP_INFO);
- else if ((BTA_HH_GET_PROTO_EVT == event) || (BTA_HH_GET_RPT_EVT == event) ||
- (BTA_HH_GET_IDLE_EVT == event))
+ else if ((BTA_HH_GET_PROTO_EVT == event) || (BTA_HH_GET_IDLE_EVT == event))
+ param_len = sizeof(tBTA_HH_HSDATA);
+ else if (BTA_HH_GET_RPT_EVT == event) {
+ BT_HDR* hdr = p_data->hs_data.rsp_data.p_rpt_data;
param_len = sizeof(tBTA_HH_HSDATA);
- else if ((BTA_HH_SET_PROTO_EVT == event) || (BTA_HH_SET_RPT_EVT == event) ||
- (BTA_HH_VC_UNPLUG_EVT == event) || (BTA_HH_SET_IDLE_EVT == event))
+
+ if (hdr != NULL) {
+ p_copy_cback = btif_hh_hsdata_rpt_copy_cb;
+ param_len += BT_HDR_SIZE + hdr->offset + hdr->len;
+ }
+ } else if ((BTA_HH_SET_PROTO_EVT == event) || (BTA_HH_SET_RPT_EVT == event) ||
+ (BTA_HH_VC_UNPLUG_EVT == event) || (BTA_HH_SET_IDLE_EVT == event))
param_len = sizeof(tBTA_HH_CBDATA);
else if ((BTA_HH_ADD_DEV_EVT == event) || (BTA_HH_RMV_DEV_EVT == event))
param_len = sizeof(tBTA_HH_DEV_INFO);
@@ -1130,7 +1170,7 @@ void bte_hh_evt(tBTA_HH_EVT event, tBTA_HH* p_data) {
/* switch context to btif task context (copy full union size for convenience)
*/
status = btif_transfer_context(btif_hh_upstreams_evt, (uint16_t)event,
- (char*)p_data, param_len, NULL);
+ (char*)p_data, param_len, p_copy_cback);
/* catch any failed context transfers */
ASSERTC(status == BT_STATUS_SUCCESS, "context transfer failed", status);