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

Commit eec6f271 authored by Andre Eisenbach's avatar Andre Eisenbach Committed by Android Git Automerger
Browse files

am 227c69ce: LE: Improved handling of illegal GATT PDUs

* commit '227c69ce':
  LE: Improved handling of illegal GATT PDUs
parents 55e14845 227c69ce
Loading
Loading
Loading
Loading
+46 −11
Original line number Diff line number Diff line
@@ -34,6 +34,13 @@
#define GATT_READ_CHAR_VALUE_HDL    (GATT_READ_CHAR_VALUE | 0x80)
#define GATT_READ_INC_SRV_UUID128   (GATT_DISC_INC_SRVC   | 0x90)

#define GATT_PREP_WRITE_RSP_MIN_LEN 4
#define GATT_NOTIFICATION_MIN_LEN 2
#define GATT_WRITE_RSP_MIN_LEN  2
#define GATT_INFO_RSP_MIN_LEN   1
#define GATT_MTU_RSP_MIN_LEN    2
#define GATT_READ_BY_TYPE_RSP_MIN_LEN    1

/********************************************************************************
**                       G L O B A L      G A T T       D A T A                 *
*********************************************************************************/
@@ -444,6 +451,12 @@ void gatt_process_read_info_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_c
    tGATT_DISC_RES  result;
    UINT8   *p = p_data, uuid_len = 0, type;

    if (len < GATT_INFO_RSP_MIN_LEN)
    {
        GATT_TRACE_ERROR0("invalid Info Response PDU received, discard.");
        gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
        return;
    }
    /* unexpected response */
    if (p_clcb->operation != GATTC_OPTYPE_DISCOVERY || p_clcb->op_subtype != GATT_DISC_CHAR_DSCPT)
        return;
@@ -583,6 +596,13 @@ void gatt_process_prep_write_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op

    GATT_TRACE_ERROR2("value resp op_code = %s len = %d", gatt_dbg_op_name(op_code), len);

    if (len < GATT_PREP_WRITE_RSP_MIN_LEN)
    {
        GATT_TRACE_ERROR0("illegal prepare write response length, discard");
        gatt_end_operation(p_clcb, GATT_INVALID_PDU, &value);
        return;
    }

    STREAM_TO_UINT16 (value.handle, p);
    STREAM_TO_UINT16 (value.offset, p);

@@ -628,6 +648,12 @@ void gatt_process_notification(tGATT_TCB *p_tcb, UINT8 op_code,

    GATT_TRACE_DEBUG0("gatt_process_notification ");

    if (len < GATT_NOTIFICATION_MIN_LEN)
    {
        GATT_TRACE_ERROR0("illegal notification PDU length, discard");
        return;
    }

    STREAM_TO_UINT16 (value.handle, p);
    value.len = len - 2;
    memcpy (value.value, p, value.len);
@@ -708,6 +734,13 @@ void gatt_process_read_by_type_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8
    if (((!p_clcb->p_reg) || (!p_clcb->p_reg->app_cb.p_disc_res_cb)) && (p_clcb->operation == GATTC_OPTYPE_DISCOVERY))
        return;

    if (len < GATT_READ_BY_TYPE_RSP_MIN_LEN)
    {
        GATT_TRACE_ERROR0("Illegal ReadByType/ReadByGroupType Response length, discard");
        gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
        return;
    }

    STREAM_TO_UINT8(value_len, p);

    if ((value_len > (p_tcb->payload_size - 2)) || (value_len > (len-1))  )
@@ -979,15 +1012,8 @@ void gatt_process_read_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
** Returns          void
**
*******************************************************************************/
void gatt_process_handle_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code, UINT16 len, UINT8 *p_data)
void gatt_process_handle_rsp(tGATT_CLCB *p_clcb)
{
    UINT16      handle;
    UINT8       * p= p_data;

    STREAM_TO_UINT16(handle, p);
    len -= 2;

    if (op_code == GATT_RSP_WRITE)
    gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
}
/*******************************************************************************
@@ -1003,13 +1029,22 @@ void gatt_process_handle_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code
void gatt_process_mtu_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data)
{
    UINT16 mtu;
    tGATT_STATUS    status = GATT_SUCCESS;

    if (len < GATT_MTU_RSP_MIN_LEN)
    {
        GATT_TRACE_ERROR0("invalid MTU response PDU received, discard.");
        status = GATT_INVALID_PDU;
    }
    else
    {
    STREAM_TO_UINT16(mtu, p_data);

    if (mtu < p_tcb->payload_size && mtu >= GATT_DEF_BLE_MTU_SIZE)
        p_tcb->payload_size = mtu;
    }

    gatt_end_operation(p_clcb, p_clcb->status, NULL);
    gatt_end_operation(p_clcb, status, NULL);
}
/*******************************************************************************
**
@@ -1161,7 +1196,7 @@ void gatt_client_handle_server_rsp (tGATT_TCB *p_tcb, UINT8 op_code,
                break;

            case GATT_RSP_WRITE:
                gatt_process_handle_rsp(p_tcb, p_clcb, op_code, len, p_data);
                gatt_process_handle_rsp(p_clcb);
                break;

            case GATT_RSP_PREPARE_WRITE:
+57 −40
Original line number Diff line number Diff line
@@ -29,6 +29,8 @@
#include "gatt_int.h"
#include "l2c_api.h"

#define GATT_MTU_REQ_MIN_LEN        2


/*******************************************************************************
**
@@ -545,8 +547,8 @@ static tGATT_STATUS gatt_build_primary_service_rsp (BT_HDR *p_msg, tGATT_TCB *p_
            p_rcb->s_hdl <= e_hdl &&
            p_rcb->type == GATT_UUID_PRI_SERVICE)
        {
            p_uuid = gatts_get_service_uuid (p_rcb->p_db);

            if ((p_uuid = gatts_get_service_uuid (p_rcb->p_db)) != NULL)
            {
                if (op_code == GATT_REQ_READ_BY_GRP_TYPE)
                    handle_len = 4 + p_uuid->len;

@@ -593,6 +595,7 @@ static tGATT_STATUS gatt_build_primary_service_rsp (BT_HDR *p_msg, tGATT_TCB *p_
                else
                    break;
            }
        }
        p_srv = p_srv->p_next;
    }
    p_msg->offset = L2CAP_MIN_OFFSET;
@@ -730,6 +733,8 @@ static tGATT_STATUS gatts_validate_packet_format(UINT8 op_code, UINT16 *p_len,
                reason = GATT_INVALID_PDU;
        }
    }
    else
        reason = GATT_INVALID_PDU;

    *p_data     = p;
    *p_len      = len;
@@ -901,15 +906,19 @@ static void gatts_process_mtu_req (tGATT_TCB *p_tcb, UINT16 len, UINT8 *p_data)
    BT_HDR        *p_buf;
    UINT16   conn_id;

    STREAM_TO_UINT16 (mtu, p);

    /* BR/EDR conenction, send error response */
    if (p_tcb->att_lcid != L2CAP_ATT_CID)
    {
        gatt_send_error_rsp (p_tcb, GATT_REQ_NOT_SUPPORTED, GATT_REQ_MTU, 0, FALSE);
    }
    else if (len < GATT_MTU_REQ_MIN_LEN)
    {
        GATT_TRACE_ERROR0("invalid MTU request PDU received.");
        gatt_send_error_rsp (p_tcb, GATT_INVALID_PDU, GATT_REQ_MTU, 0, FALSE);
    }
    else
    {
        STREAM_TO_UINT16 (mtu, p);
        /* mtu must be greater than default MTU which is 23/48 */
        if (mtu < GATT_DEF_BLE_MTU_SIZE)
            p_tcb->payload_size = GATT_DEF_BLE_MTU_SIZE;
@@ -1231,14 +1240,22 @@ static void gatts_process_read_req(tGATT_TCB *p_tcb, tGATT_SR_REG *p_rcb, UINT8
void gatts_process_attribute_req (tGATT_TCB *p_tcb, UINT8 op_code,
                                  UINT16 len, UINT8 *p_data)
{
    UINT16          handle;
    UINT16          handle = 0;
    UINT8           *p = p_data, i;
    tGATT_SR_REG    *p_rcb = gatt_cb.sr_reg;
    tGATT_STATUS    status = GATT_INVALID_HANDLE;
    tGATT_ATTR16    *p_attr;

    if (len < 2)
    {
        GATT_TRACE_ERROR0("Illegal PDU length, discard request");
        status = GATT_INVALID_PDU;
    }
    else
    {
        STREAM_TO_UINT16(handle, p);
        len -= 2;
    }

#if GATT_CONFORMANCE_TESTING == TRUE
    gatt_cb.handle = handle;