Fix OOB writes in gatt_sr.cc At various points in gatt_sr.cc, the output of the gatt_tcb_get_payload_size function is used without checking for a positive length. However, in exceptional cases it is possible for the channel to be closed at the time the function is called, which will lead to a zero length and cause an OOB write in subsequent processing. Fix all of these. Bug: 364026473 Bug: 364027038 Bug: 364027949 Bug: 364025411 Test: m libbluetooth Test: researcher POC Flag: EXEMPT trivial validity checks Tag: #security Ignore-AOSP-First: Security (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:7de5617f7d5266fe57c990c428621b5d4e92728a) Merged-In: I9b30499d4aed6ab42f3cdb2c0de7df2c1a827404 Change-Id: I9b30499d4aed6ab42f3cdb2c0de7df2c1a827404
diff --git a/system/stack/gatt/gatt_sr.cc b/system/stack/gatt/gatt_sr.cc index 10342dd..0ddb99d 100644 --- a/system/stack/gatt/gatt_sr.cc +++ b/system/stack/gatt/gatt_sr.cc
@@ -768,6 +768,11 @@ uint16_t payload_size = gatt_tcb_get_payload_size(tcb, cid); + // This can happen if the channel is already closed. + if (payload_size == 0) { + return; + } + uint16_t msg_len = (uint16_t)(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET); BT_HDR* p_msg = (BT_HDR*)osi_calloc(msg_len); reason = gatt_build_primary_service_rsp(p_msg, tcb, cid, op_code, s_hdl, e_hdl, p_data, value); @@ -800,6 +805,12 @@ } uint16_t payload_size = gatt_tcb_get_payload_size(tcb, cid); + + // This can happen if the channel is already closed. + if (payload_size == 0) { + return; + } + uint16_t buf_len = (uint16_t)(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET); BT_HDR* p_msg = (BT_HDR*)osi_calloc(buf_len); @@ -945,6 +956,11 @@ uint16_t payload_size = gatt_tcb_get_payload_size(tcb, cid); + // This can happen if the channel is already closed. + if (payload_size == 0) { + return; + } + size_t msg_len = sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET; BT_HDR* p_msg = (BT_HDR*)osi_calloc(msg_len); uint8_t* p = (uint8_t*)(p_msg + 1) + L2CAP_MIN_OFFSET; @@ -1092,6 +1108,11 @@ uint8_t* p_data) { uint16_t payload_size = gatt_tcb_get_payload_size(tcb, cid); + // This can happen if the channel is already closed. + if (payload_size == 0) { + return; + } + size_t buf_len = sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET; uint16_t offset = 0;