Skip to content

Commit f743d12

Browse files
alwa-nordichenrikbrixandersen
authored andcommitted
Bluetooth: Check buffer length in GATT rsp functions
Add length checks local to the parsing function. This removes the need for a separate data validation step. Signed-off-by: Aleksander Wasaznik <[email protected]> (cherry picked from commit 3eeb8f8)
1 parent a9fbf48 commit f743d12

File tree

1 file changed

+79
-8
lines changed

1 file changed

+79
-8
lines changed

subsys/bluetooth/host/gatt.c

Lines changed: 79 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3910,7 +3910,7 @@ static uint16_t parse_include(struct bt_conn *conn, const void *pdu,
39103910
struct bt_gatt_discover_params *params,
39113911
uint16_t length)
39123912
{
3913-
const struct bt_att_read_type_rsp *rsp = pdu;
3913+
const struct bt_att_read_type_rsp *rsp;
39143914
uint16_t handle = 0U;
39153915
struct bt_gatt_include value;
39163916
union {
@@ -3919,6 +3919,13 @@ static uint16_t parse_include(struct bt_conn *conn, const void *pdu,
39193919
struct bt_uuid_128 u128;
39203920
} u;
39213921

3922+
if (length < sizeof(*rsp)) {
3923+
LOG_WRN("Parse err");
3924+
goto done;
3925+
}
3926+
3927+
rsp = pdu;
3928+
39223929
/* Data can be either in UUID16 or UUID128 */
39233930
switch (rsp->len) {
39243931
case 8: /* UUID16 */
@@ -4003,14 +4010,21 @@ static uint16_t parse_characteristic(struct bt_conn *conn, const void *pdu,
40034010
struct bt_gatt_discover_params *params,
40044011
uint16_t length)
40054012
{
4006-
const struct bt_att_read_type_rsp *rsp = pdu;
4013+
const struct bt_att_read_type_rsp *rsp;
40074014
uint16_t handle = 0U;
40084015
union {
40094016
struct bt_uuid uuid;
40104017
struct bt_uuid_16 u16;
40114018
struct bt_uuid_128 u128;
40124019
} u;
40134020

4021+
if (length < sizeof(*rsp)) {
4022+
LOG_WRN("Parse err");
4023+
goto done;
4024+
}
4025+
4026+
rsp = pdu;
4027+
40144028
/* Data can be either in UUID16 or UUID128 */
40154029
switch (rsp->len) {
40164030
case 7: /* UUID16 */
@@ -4084,7 +4098,7 @@ static uint16_t parse_read_std_char_desc(struct bt_conn *conn, const void *pdu,
40844098
struct bt_gatt_discover_params *params,
40854099
uint16_t length)
40864100
{
4087-
const struct bt_att_read_type_rsp *rsp = pdu;
4101+
const struct bt_att_read_type_rsp *rsp;
40884102
uint16_t handle = 0U;
40894103
uint16_t uuid_val;
40904104

@@ -4094,6 +4108,13 @@ static uint16_t parse_read_std_char_desc(struct bt_conn *conn, const void *pdu,
40944108

40954109
uuid_val = BT_UUID_16(params->uuid)->val;
40964110

4111+
if (length < sizeof(*rsp)) {
4112+
LOG_WRN("Parse err");
4113+
goto done;
4114+
}
4115+
4116+
rsp = pdu;
4117+
40974118
/* Parse characteristics found */
40984119
for (length--, pdu = rsp->data; length >= rsp->len;
40994120
length -= rsp->len, pdu = (const uint8_t *)pdu + rsp->len) {
@@ -4103,9 +4124,16 @@ static uint16_t parse_read_std_char_desc(struct bt_conn *conn, const void *pdu,
41034124
struct bt_gatt_cep cep;
41044125
struct bt_gatt_scc scc;
41054126
} value;
4106-
const struct bt_att_data *data = pdu;
4127+
const struct bt_att_data *data;
41074128
struct bt_gatt_attr attr;
41084129

4130+
if (length < sizeof(*data)) {
4131+
LOG_WRN("Parse err dat");
4132+
goto done;
4133+
}
4134+
4135+
data = pdu;
4136+
41094137
handle = sys_le16_to_cpu(data->handle);
41104138
/* Handle 0 is invalid */
41114139
if (!handle) {
@@ -4114,17 +4142,39 @@ static uint16_t parse_read_std_char_desc(struct bt_conn *conn, const void *pdu,
41144142

41154143
switch (uuid_val) {
41164144
case BT_UUID_GATT_CEP_VAL:
4145+
if (length < sizeof(*data) + sizeof(uint16_t)) {
4146+
LOG_WRN("Parse err cep");
4147+
goto done;
4148+
}
4149+
41174150
value.cep.properties = sys_get_le16(data->value);
41184151
break;
41194152
case BT_UUID_GATT_CCC_VAL:
4153+
if (length < sizeof(*data) + sizeof(uint16_t)) {
4154+
LOG_WRN("Parse err ccc");
4155+
goto done;
4156+
}
4157+
41204158
value.ccc.flags = sys_get_le16(data->value);
41214159
break;
41224160
case BT_UUID_GATT_SCC_VAL:
4161+
if (length < sizeof(*data) + sizeof(uint16_t)) {
4162+
LOG_WRN("Parse err scc");
4163+
goto done;
4164+
}
4165+
41234166
value.scc.flags = sys_get_le16(data->value);
41244167
break;
41254168
case BT_UUID_GATT_CPF_VAL:
41264169
{
4127-
struct gatt_cpf *cpf = (struct gatt_cpf *)data->value;
4170+
struct gatt_cpf *cpf;
4171+
4172+
if (length < sizeof(*data) + sizeof(*cpf)) {
4173+
LOG_WRN("Parse err cpf");
4174+
goto done;
4175+
}
4176+
4177+
cpf = (void *)data->value;
41284178

41294179
value.cpf.format = cpf->format;
41304180
value.cpf.exponent = cpf->exponent;
@@ -4227,14 +4277,21 @@ static uint16_t parse_service(struct bt_conn *conn, const void *pdu,
42274277
struct bt_gatt_discover_params *params,
42284278
uint16_t length)
42294279
{
4230-
const struct bt_att_read_group_rsp *rsp = pdu;
4280+
const struct bt_att_read_group_rsp *rsp;
42314281
uint16_t start_handle, end_handle = 0U;
42324282
union {
42334283
struct bt_uuid uuid;
42344284
struct bt_uuid_16 u16;
42354285
struct bt_uuid_128 u128;
42364286
} u;
42374287

4288+
if (length < sizeof(*rsp)) {
4289+
LOG_WRN("Parse err");
4290+
goto done;
4291+
}
4292+
4293+
rsp = pdu;
4294+
42384295
/* Data can be either in UUID16 or UUID128 */
42394296
switch (rsp->len) {
42404297
case 6: /* UUID16 */
@@ -4365,7 +4422,7 @@ static void gatt_find_info_rsp(struct bt_conn *conn, int err,
43654422
const void *pdu, uint16_t length,
43664423
void *user_data)
43674424
{
4368-
const struct bt_att_find_info_rsp *rsp = pdu;
4425+
const struct bt_att_find_info_rsp *rsp;
43694426
struct bt_gatt_discover_params *params = user_data;
43704427
uint16_t handle = 0U;
43714428
uint16_t len;
@@ -4387,6 +4444,13 @@ static void gatt_find_info_rsp(struct bt_conn *conn, int err,
43874444
goto done;
43884445
}
43894446

4447+
if (length < sizeof(*rsp)) {
4448+
LOG_WRN("Parse err");
4449+
goto done;
4450+
}
4451+
4452+
rsp = pdu;
4453+
43904454
/* Data can be either in UUID16 or UUID128 */
43914455
switch (rsp->format) {
43924456
case BT_ATT_INFO_16:
@@ -4992,7 +5056,7 @@ static void gatt_prepare_write_rsp(struct bt_conn *conn, int err,
49925056
void *user_data)
49935057
{
49945058
struct bt_gatt_write_params *params = user_data;
4995-
const struct bt_att_prepare_write_rsp *rsp = pdu;
5059+
const struct bt_att_prepare_write_rsp *rsp;
49965060
size_t len;
49975061
bool data_valid;
49985062

@@ -5004,6 +5068,13 @@ static void gatt_prepare_write_rsp(struct bt_conn *conn, int err,
50045068
return;
50055069
}
50065070

5071+
if (length < sizeof(*rsp)) {
5072+
LOG_WRN("Parse err");
5073+
goto fail;
5074+
}
5075+
5076+
rsp = pdu;
5077+
50075078
len = length - sizeof(*rsp);
50085079
if (len > params->length) {
50095080
LOG_ERR("Incorrect length, canceling write");

0 commit comments

Comments
 (0)