Skip to content

Commit 5245307

Browse files
lylezhu2012kartben
authored andcommitted
Bluetooth: GATT: Check len of response before parsing response PDU
In function `parse_read_by_uuid()`, the response length is not checked before parsing the response PDU. There is a potential issue that the `len` will be underflowed if the `len` is less than the size of `struct bt_att_data`. Check the length before parsing the response PDU. If the length is less then the size of `struct bt_att_data`, notify the upper layer with the error `BT_ATT_ERR_INVALID_PDU` and stop the parsing. Signed-off-by: Lyle Zhu <[email protected]>
1 parent 7f94595 commit 5245307

File tree

2 files changed

+14
-2
lines changed

2 files changed

+14
-2
lines changed

include/zephyr/bluetooth/gatt.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1897,6 +1897,9 @@ struct bt_gatt_read_params;
18971897
* When reading using by_uuid, `params->start_handle` is the attribute handle
18981898
* for this `data` item.
18991899
*
1900+
* If the received data length is invalid, the callback will called with the
1901+
* error @ref BT_ATT_ERR_INVALID_PDU.
1902+
*
19001903
* @param conn Connection object.
19011904
* @param err ATT error code.
19021905
* @param params Read parameters used.
@@ -2005,6 +2008,8 @@ struct bt_gatt_read_params {
20052008
* The Response comes in callback @p params->func. The callback is run from
20062009
* the context specified by 'config BT_RECV_CONTEXT'.
20072010
* @p params must remain valid until start of callback.
2011+
* If the received data length is invalid, the callback @p params->func will
2012+
* called with the error @ref BT_ATT_ERR_INVALID_PDU.
20082013
*
20092014
* @param conn Connection object.
20102015
* @param params Read parameters.

subsys/bluetooth/host/gatt.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4776,6 +4776,15 @@ static void parse_read_by_uuid(struct bt_conn *conn,
47764776
uint16_t handle;
47774777
uint16_t len;
47784778

4779+
len = MIN(rsp->len, length);
4780+
if (len < sizeof(struct bt_att_data)) {
4781+
LOG_WRN("Bad peer: ATT read-by-uuid rsp: invalid ATTR PDU len %u", len);
4782+
params->func(conn, BT_ATT_ERR_INVALID_PDU, params, NULL, 0);
4783+
return;
4784+
}
4785+
4786+
len -= sizeof(struct bt_att_data);
4787+
47794788
handle = sys_le16_to_cpu(data->handle);
47804789

47814790
/* Handle 0 is invalid */
@@ -4784,8 +4793,6 @@ static void parse_read_by_uuid(struct bt_conn *conn,
47844793
return;
47854794
}
47864795

4787-
len = rsp->len > length ? length - 2 : rsp->len - 2;
4788-
47894796
LOG_DBG("handle 0x%04x len %u value %u", handle, rsp->len, len);
47904797

47914798
if (!IN_RANGE(handle, req_start_handle, req_end_handle)) {

0 commit comments

Comments
 (0)