Skip to content

Commit

Permalink
Bluetooth: Host: Fix unsafe ccc cast
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
HaavardRei authored and nashif committed Nov 16, 2024
1 parent 43149c1 commit 68361ea
Showing 1 changed file with 22 additions and 12 deletions.
34 changes: 22 additions & 12 deletions subsys/bluetooth/host/gatt.c
Original file line number Diff line number Diff line change
Expand Up @@ -3473,7 +3473,9 @@ static uint8_t disconnected_cb(const struct bt_gatt_attr *attr, uint16_t handle,
bool bt_gatt_is_subscribed(struct bt_conn *conn,
const struct bt_gatt_attr *attr, uint16_t ccc_type)
{
const struct _bt_gatt_ccc *ccc;
uint16_t ccc_bits;
uint8_t ccc_bits_encoded[sizeof(ccc_bits)];
ssize_t len;

__ASSERT(conn, "invalid parameter\n");
__ASSERT(attr, "invalid parameter\n");
Expand All @@ -3484,8 +3486,7 @@ bool bt_gatt_is_subscribed(struct bt_conn *conn,

/* Check if attribute is a characteristic declaration */
if (!bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CHRC)) {
uint8_t properties = 0;
ssize_t len;
uint8_t properties;

if (!attr->read) {
LOG_ERR("Read method not set");
Expand All @@ -3494,7 +3495,7 @@ bool bt_gatt_is_subscribed(struct bt_conn *conn,
/* The charactestic properties is the first byte of the attribute value */
len = attr->read(NULL, attr, &properties, sizeof(properties), 0);
if (len < 0) {
LOG_ERR("Failed to read attribute (err %zd)", len);
LOG_ERR("Failed to read attribute %p (err %zd)", attr, len);
return false;
} else if (len != sizeof(properties)) {
LOG_ERR("Invalid read length: %zd", len);
Expand Down Expand Up @@ -3532,16 +3533,25 @@ bool bt_gatt_is_subscribed(struct bt_conn *conn,
return false;
}

ccc = attr->user_data;
if (!attr->read) {
LOG_ERR("Read method not set");
return false;
}

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

if (bt_conn_is_peer_addr_le(conn, cfg->id, &cfg->peer) &&
(ccc_type & ccc->cfg[i].value)) {
return true;
}
ccc_bits = sys_get_le16(ccc_bits_encoded);

/* Check if the CCC bits match the subscription type */
if (ccc_bits & ccc_type) {
return true;
}

return false;
Expand Down

0 comments on commit 68361ea

Please sign in to comment.