Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 85cc8f60 authored by Kyunglyul Hyun's avatar Kyunglyul Hyun
Browse files

Do not send write requestif tcb is closed

If tcb is closed, the mtu resets to 0.
Although I couldn't find a exact path but
gatt_send_write can be invoked after a tcb is closed.

This change prevents this scenario by rejecting
the request.

Flag: strict bound check
Bug: 365910287
Test: atest GattClientTest

Change-Id: I1943dff545cba51bdc50a2d22dd335c1bdb5eaa6
parent 9bb9aa3c
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
@@ -637,4 +637,32 @@ public class GattClientTest {
        // We should fail because we reached the limit.
        assertThat(failed).isTrue();
    }

    @Test
    public void writeCharacteristic_disconnected_shouldNotCrash() {
        registerGattService();

        BluetoothGattCallback gattCallback = mock(BluetoothGattCallback.class);

        BluetoothGatt gatt = connectGattAndWaitConnection(gattCallback);

        try {
            gatt.discoverServices();
            verify(gattCallback, timeout(10000)).onServicesDiscovered(any(), eq(GATT_SUCCESS));

            BluetoothGattCharacteristic characteristic =
                    gatt.getService(TEST_SERVICE_UUID).getCharacteristic(TEST_CHARACTERISTIC_UUID);

            byte[] newValue = new byte[] {13};

            gatt.writeCharacteristic(
                    characteristic, newValue, BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
            // TODO(b/370607862): disconnect from the remote
            gatt.disconnect();
            gatt.close();
        } finally {
            // it's okay to close twice.
            gatt.close();
        }
    }
}
+9 −2
Original line number Diff line number Diff line
@@ -249,7 +249,7 @@ void gatt_act_write(tGATT_CLCB* p_clcb, uint8_t sec_act) {
    }

    case GATT_WRITE: {
      if (attr.len <= (payload_size - GATT_HDR_SIZE)) {
      if ((attr.len + GATT_HDR_SIZE) <= payload_size) {
        p_clcb->s_handle = attr.handle;

        tGATT_STATUS rt = gatt_send_write_msg(tcb, p_clcb, GATT_REQ_WRITE, attr.handle, attr.len, 0,
@@ -346,7 +346,14 @@ void gatt_send_prepare_write(tGATT_TCB& tcb, tGATT_CLCB* p_clcb) {
  uint16_t to_send = p_attr->len - p_attr->offset;

  uint16_t payload_size = gatt_tcb_get_payload_size(tcb, p_clcb->cid);
  if (to_send > (payload_size - GATT_WRITE_LONG_HDR_SIZE)) { /* 2 = uint16_t offset bytes  */

  if (payload_size <= GATT_WRITE_LONG_HDR_SIZE) {
    log::error("too small mtu size {}, possibly due to disconnection", payload_size);
    gatt_end_operation(p_clcb, GATT_ERROR, NULL);
    return;
  }

  if (to_send > (payload_size - GATT_WRITE_LONG_HDR_SIZE)) {
    to_send = payload_size - GATT_WRITE_LONG_HDR_SIZE;
  }