From c7468e64bb5e821563a910ccd8e5693c179c9da4 Mon Sep 17 00:00:00 2001
From: Brian Delwiche <delwiche@google.com>
Date: Thu, 12 Sep 2024 17:26:55 +0000
Subject: [PATCH] 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 commit 7de5617f7d5266fe57c990c428621b5d4e92728a)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:130861eadc3d9eda593df949666e561dd1f020fc)
Merged-In: I9b30499d4aed6ab42f3cdb2c0de7df2c1a827404
Change-Id: I9b30499d4aed6ab42f3cdb2c0de7df2c1a827404
---
 system/stack/gatt/gatt_sr.cc | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/system/stack/gatt/gatt_sr.cc b/system/stack/gatt/gatt_sr.cc
index 3b3fb342a71..46aa4bb469e 100644
--- a/system/stack/gatt/gatt_sr.cc
+++ b/system/stack/gatt/gatt_sr.cc
@@ -734,6 +734,11 @@ void gatts_process_primary_service_req(tGATT_TCB& tcb, uint16_t cid,
 
   uint16_t payload_size = gatt_tcb_get_payload_size_tx(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);
@@ -769,6 +774,12 @@ static void gatts_process_find_info(tGATT_TCB& tcb, uint16_t cid,
   }
 
   uint16_t payload_size = gatt_tcb_get_payload_size_tx(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);
 
@@ -909,6 +920,11 @@ static void gatts_process_read_by_type_req(tGATT_TCB& tcb, uint16_t cid,
 
   uint16_t payload_size = gatt_tcb_get_payload_size_tx(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;
@@ -1056,6 +1072,11 @@ static void gatts_process_read_req(tGATT_TCB& tcb, uint16_t cid,
                                    uint8_t* p_data) {
   uint16_t payload_size = gatt_tcb_get_payload_size_tx(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;
 
-- 
GitLab