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 <haavard.reierstad@nordicsemi.no>
This commit is contained in:
Håvard Reierstad 2024-11-04 12:41:00 +01:00 committed by Anas Nashif
parent 43149c1056
commit 68361eacfa
1 changed files with 22 additions and 12 deletions

View File

@ -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, bool bt_gatt_is_subscribed(struct bt_conn *conn,
const struct bt_gatt_attr *attr, uint16_t ccc_type) 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(conn, "invalid parameter\n");
__ASSERT(attr, "invalid parameter\n"); __ASSERT(attr, "invalid parameter\n");
@ -3484,8 +3486,7 @@ bool bt_gatt_is_subscribed(struct bt_conn *conn,
/* Check if attribute is a characteristic declaration */ /* Check if attribute is a characteristic declaration */
if (!bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CHRC)) { if (!bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CHRC)) {
uint8_t properties = 0; uint8_t properties;
ssize_t len;
if (!attr->read) { if (!attr->read) {
LOG_ERR("Read method not set"); LOG_ERR("Read method not set");
@ -3494,7 +3495,7 @@ bool bt_gatt_is_subscribed(struct bt_conn *conn,
/* The charactestic properties is the first byte of the attribute value */ /* The charactestic properties is the first byte of the attribute value */
len = attr->read(NULL, attr, &properties, sizeof(properties), 0); len = attr->read(NULL, attr, &properties, sizeof(properties), 0);
if (len < 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; return false;
} else if (len != sizeof(properties)) { } else if (len != sizeof(properties)) {
LOG_ERR("Invalid read length: %zd", len); LOG_ERR("Invalid read length: %zd", len);
@ -3532,16 +3533,25 @@ bool bt_gatt_is_subscribed(struct bt_conn *conn,
return false; return false;
} }
ccc = attr->user_data; if (!attr->read) {
LOG_ERR("Read method not set");
return false;
}
/* Check if the connection is subscribed */ len = attr->read(conn, attr, ccc_bits_encoded, sizeof(ccc_bits_encoded), 0);
for (size_t i = 0; i < BT_GATT_CCC_MAX; i++) { if (len < 0) {
const struct bt_gatt_ccc_cfg *cfg = &ccc->cfg[i]; 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_bits = sys_get_le16(ccc_bits_encoded);
(ccc_type & ccc->cfg[i].value)) {
return true; /* Check if the CCC bits match the subscription type */
} if (ccc_bits & ccc_type) {
return true;
} }
return false; return false;