Skip to content

Commit efd8ac6

Browse files
committed
Bluetooth: Host: Fix unsafe ccc cast
Changes the implementation of `bt_gatt_is_subscribed` to use the attribute read method instead of casting the user data pointer when extracting the CCC Attribute Value. Signed-off-by: Håvard Reierstad <[email protected]>
1 parent 0389a63 commit efd8ac6

File tree

1 file changed

+22
-12
lines changed

1 file changed

+22
-12
lines changed

subsys/bluetooth/host/gatt.c

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3464,7 +3464,9 @@ static uint8_t disconnected_cb(const struct bt_gatt_attr *attr, uint16_t handle,
34643464
bool bt_gatt_is_subscribed(struct bt_conn *conn,
34653465
const struct bt_gatt_attr *attr, uint16_t ccc_type)
34663466
{
3467-
const struct _bt_gatt_ccc *ccc;
3467+
uint16_t ccc_bits;
3468+
uint8_t ccc_bits_encoded[sizeof(ccc_bits)];
3469+
ssize_t len;
34683470

34693471
__ASSERT(conn, "invalid parameter\n");
34703472
__ASSERT(attr, "invalid parameter\n");
@@ -3475,8 +3477,7 @@ bool bt_gatt_is_subscribed(struct bt_conn *conn,
34753477

34763478
/* Check if attribute is a characteristic declaration */
34773479
if (!bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CHRC)) {
3478-
uint8_t properties = 0;
3479-
ssize_t len;
3480+
uint8_t properties;
34803481

34813482
if (!attr->read) {
34823483
LOG_ERR("Read method not set");
@@ -3485,7 +3486,7 @@ bool bt_gatt_is_subscribed(struct bt_conn *conn,
34853486
/* The charactestic properties is the first byte of the attribute value */
34863487
len = attr->read(NULL, attr, &properties, sizeof(properties), 0);
34873488
if (len < 0) {
3488-
LOG_ERR("Failed to read attribute (err %zd)", len);
3489+
LOG_ERR("Failed to read attribute %p (err %zd)", attr, len);
34893490
return false;
34903491
} else if (len != sizeof(properties)) {
34913492
LOG_ERR("Invalid read length: %zd", len);
@@ -3523,16 +3524,25 @@ bool bt_gatt_is_subscribed(struct bt_conn *conn,
35233524
return false;
35243525
}
35253526

3526-
ccc = attr->user_data;
3527+
if (!attr->read) {
3528+
LOG_ERR("Read method not set");
3529+
return false;
3530+
}
35273531

3528-
/* Check if the connection is subscribed */
3529-
for (size_t i = 0; i < BT_GATT_CCC_MAX; i++) {
3530-
const struct bt_gatt_ccc_cfg *cfg = &ccc->cfg[i];
3532+
len = attr->read(conn, attr, ccc_bits_encoded, sizeof(ccc_bits_encoded), 0);
3533+
if (len < 0) {
3534+
LOG_ERR("Failed to read attribute %p (err %zd)", attr, len);
3535+
return false;
3536+
} else if (len != sizeof(ccc_bits_encoded)) {
3537+
LOG_ERR("Invalid read length: %zd", len);
3538+
return false;
3539+
}
35313540

3532-
if (bt_conn_is_peer_addr_le(conn, cfg->id, &cfg->peer) &&
3533-
(ccc_type & ccc->cfg[i].value)) {
3534-
return true;
3535-
}
3541+
ccc_bits = sys_get_le16(ccc_bits_encoded);
3542+
3543+
/* Check if the CCC bits match the subscription type */
3544+
if (ccc_bits & ccc_type) {
3545+
return true;
35363546
}
35373547

35383548
return false;

0 commit comments

Comments
 (0)