Skip to content

Commit 6567d6e

Browse files
ThalleyMaureenHelm
authored andcommitted
Bluetooth: ASCS: Validate num_ases in CP requests
Add validation of the number of ASEs in control point write requests. This validates that the number of ASEs in the control point is not greater than the total number of ASEs we support. This also validates that the GATT MTU is large enough to hold all the responses from the write since those can only be sent as notifications and never be truncated. Finally this validates and updates the size of the buffer used to hold the responses, which may be an optimization for some builds. Signed-off-by: Emil Gydesen <[email protected]> (cherry picked from commit 7b0784c)
1 parent 9ab5868 commit 6567d6e

File tree

2 files changed

+297
-44
lines changed

2 files changed

+297
-44
lines changed

subsys/bluetooth/audio/ascs.c

Lines changed: 91 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ LOG_MODULE_REGISTER(bt_ascs, CONFIG_BT_ASCS_LOG_LEVEL);
4242
(CONFIG_BT_ASCS_ASE_SNK_COUNT + \
4343
CONFIG_BT_ASCS_ASE_SRC_COUNT)
4444

45+
#define NTF_HEADER_SIZE (3) /* opcode (1) + handle (2) */
46+
4547
BUILD_ASSERT(CONFIG_BT_ASCS_MAX_ACTIVE_ASES <= MAX(MAX_ASES_SESSIONS,
4648
CONFIG_BT_ISO_MAX_CHAN),
4749
"Max active ASEs are set to more than actual number of ASEs or ISOs");
@@ -84,8 +86,9 @@ static struct bt_ascs_ase {
8486
* writing
8587
*/
8688
BUILD_ASSERT(
87-
BT_ATT_BUF_SIZE - 3 >= ASE_BUF_SIZE ||
88-
DIV_ROUND_UP(ASE_BUF_SIZE, (BT_ATT_BUF_SIZE - 3)) <= CONFIG_BT_ATT_PREPARE_COUNT,
89+
(BT_ATT_BUF_SIZE - NTF_HEADER_SIZE) >= ASE_BUF_SIZE ||
90+
DIV_ROUND_UP(ASE_BUF_SIZE, (BT_ATT_BUF_SIZE - NTF_HEADER_SIZE)) <=
91+
CONFIG_BT_ATT_PREPARE_COUNT,
8992
"CONFIG_BT_ATT_PREPARE_COUNT not large enough to cover the maximum supported ASCS value");
9093

9194
/* It is mandatory to support long writes in ASCS unconditionally, and thus
@@ -174,9 +177,19 @@ static void ase_free(struct bt_ascs_ase *ase)
174177
(void)k_work_cancel_delayable(&ase->state_transition_work);
175178
}
176179

180+
static uint16_t get_max_ntf_size(struct bt_conn *conn)
181+
{
182+
const uint16_t mtu = conn == NULL ? 0 : bt_gatt_get_mtu(conn);
183+
184+
if (mtu > NTF_HEADER_SIZE) {
185+
return mtu - NTF_HEADER_SIZE;
186+
}
187+
188+
return 0U;
189+
}
190+
177191
static int ase_state_notify(struct bt_ascs_ase *ase)
178192
{
179-
const uint8_t att_ntf_header_size = 3; /* opcode (1) + handle (2) */
180193
struct bt_conn *conn = ase->conn;
181194
struct bt_conn_info conn_info;
182195
uint16_t max_ntf_size;
@@ -202,7 +215,7 @@ static int ase_state_notify(struct bt_ascs_ase *ase)
202215

203216
ascs_ep_get_status(&ase->ep, &ase_buf);
204217

205-
max_ntf_size = bt_gatt_get_mtu(conn) - att_ntf_header_size;
218+
max_ntf_size = get_max_ntf_size(conn);
206219

207220
ntf_size = MIN(max_ntf_size, ase_buf.len);
208221
if (ntf_size < ase_buf.len) {
@@ -1079,29 +1092,37 @@ static void ascs_ase_cfg_changed(const struct bt_gatt_attr *attr,
10791092
LOG_DBG("attr %p value 0x%04x", attr, value);
10801093
}
10811094

1082-
NET_BUF_SIMPLE_DEFINE_STATIC(rsp_buf, CONFIG_BT_L2CAP_TX_MTU);
1095+
#define CP_RSP_BUF_SIZE \
1096+
(sizeof(struct bt_ascs_cp_rsp) + (ASE_COUNT * sizeof(struct bt_ascs_cp_ase_rsp)))
1097+
1098+
/* Ensure that the cp_rsp_buf can fit in any notification
1099+
* (sizeof buffer - header for notification)
1100+
*/
1101+
BUILD_ASSERT(BT_ATT_BUF_SIZE - NTF_HEADER_SIZE >= CP_RSP_BUF_SIZE,
1102+
"BT_ATT_BUF_SIZE not large enough to hold responses for all ASEs");
1103+
NET_BUF_SIMPLE_DEFINE_STATIC(cp_rsp_buf, CP_RSP_BUF_SIZE);
10831104

10841105
static void ascs_cp_rsp_init(uint8_t op)
10851106
{
10861107
struct bt_ascs_cp_rsp *rsp;
10871108

1088-
net_buf_simple_reset(&rsp_buf);
1109+
net_buf_simple_reset(&cp_rsp_buf);
10891110

1090-
rsp = net_buf_simple_add(&rsp_buf, sizeof(*rsp));
1111+
rsp = net_buf_simple_add(&cp_rsp_buf, sizeof(*rsp));
10911112
rsp->op = op;
10921113
rsp->num_ase = 0;
10931114
}
10941115

10951116
/* Add response to an opcode/ASE ID */
10961117
static void ascs_cp_rsp_add(uint8_t id, uint8_t code, uint8_t reason)
10971118
{
1098-
struct bt_ascs_cp_rsp *rsp = (void *)rsp_buf.__buf;
1119+
struct bt_ascs_cp_rsp *rsp = (void *)cp_rsp_buf.__buf;
10991120
struct bt_ascs_cp_ase_rsp *ase_rsp;
11001121

11011122
LOG_DBG("id 0x%02x code %s (0x%02x) reason %s (0x%02x)", id,
11021123
bt_ascs_rsp_str(code), code, bt_ascs_reason_str(reason), reason);
11031124

1104-
if (rsp->num_ase == 0xff) {
1125+
if (rsp->num_ase == BT_ASCS_UNSUPP_OR_LENGTH_ERR_NUM_ASE) {
11051126
return;
11061127
}
11071128

@@ -1118,7 +1139,7 @@ static void ascs_cp_rsp_add(uint8_t id, uint8_t code, uint8_t reason)
11181139
break;
11191140
}
11201141

1121-
ase_rsp = net_buf_simple_add(&rsp_buf, sizeof(*ase_rsp));
1142+
ase_rsp = net_buf_simple_add(&cp_rsp_buf, sizeof(*ase_rsp));
11221143
ase_rsp->id = id;
11231144
ase_rsp->code = code;
11241145
ase_rsp->reason = reason;
@@ -1727,7 +1748,42 @@ int bt_ascs_config_ase(struct bt_conn *conn, struct bt_bap_stream *stream,
17271748
return 0;
17281749
}
17291750

1730-
static bool is_valid_config_len(struct net_buf_simple *buf)
1751+
static uint16_t get_max_ase_rsp_for_conn(struct bt_conn *conn)
1752+
{
1753+
const uint16_t max_ntf_size = get_max_ntf_size(conn);
1754+
const size_t rsp_hdr_size = sizeof(struct bt_ascs_cp_rsp);
1755+
1756+
if (max_ntf_size > rsp_hdr_size) {
1757+
return (max_ntf_size - rsp_hdr_size) / sizeof(struct bt_ascs_cp_ase_rsp);
1758+
}
1759+
1760+
return 0U;
1761+
}
1762+
1763+
static bool is_valid_num_ases(struct bt_conn *conn, uint8_t num_ases)
1764+
{
1765+
const uint16_t max_ase_rsp = get_max_ase_rsp_for_conn(conn);
1766+
1767+
if (num_ases < 1U) {
1768+
LOG_WRN("Number_of_ASEs parameter value is less than 1");
1769+
return false;
1770+
} else if (num_ases > ASE_COUNT) {
1771+
/* If the request is for more ASEs than we have, we just reject the request */
1772+
LOG_DBG("Number_of_ASEs parameter value (%u) is greater than %d", num_ases,
1773+
ASE_COUNT);
1774+
return false;
1775+
} else if (num_ases > max_ase_rsp) {
1776+
/* If the request is for more ASEs than we can respond to, we reject the request */
1777+
LOG_DBG("Number_of_ASEs parameter value (%u) is greater than what we can respond "
1778+
"to (%u) based on the MTU",
1779+
num_ases, max_ase_rsp);
1780+
return false;
1781+
}
1782+
1783+
return true;
1784+
}
1785+
1786+
static bool is_valid_config_len(struct bt_conn *conn, struct net_buf_simple *buf)
17311787
{
17321788
const struct bt_ascs_config_op *op;
17331789
struct net_buf_simple_state state;
@@ -1740,8 +1796,7 @@ static bool is_valid_config_len(struct net_buf_simple *buf)
17401796
}
17411797

17421798
op = net_buf_simple_pull_mem(buf, sizeof(*op));
1743-
if (op->num_ases < 1) {
1744-
LOG_WRN("Number_of_ASEs parameter value is less than 1");
1799+
if (!is_valid_num_ases(conn, op->num_ases)) {
17451800
return false;
17461801
}
17471802

@@ -1777,7 +1832,7 @@ static ssize_t ascs_config(struct bt_conn *conn, struct net_buf_simple *buf)
17771832
const struct bt_ascs_config_op *req;
17781833
const struct bt_ascs_config *cfg;
17791834

1780-
if (!is_valid_config_len(buf)) {
1835+
if (!is_valid_config_len(conn, buf)) {
17811836
return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
17821837
}
17831838

@@ -1945,7 +2000,7 @@ static void ase_qos(struct bt_ascs_ase *ase, uint8_t cig_id, uint8_t cis_id,
19452000
*rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_SUCCESS, BT_BAP_ASCS_REASON_NONE);
19462001
}
19472002

1948-
static bool is_valid_qos_len(struct net_buf_simple *buf)
2003+
static bool is_valid_qos_len(struct bt_conn *conn, struct net_buf_simple *buf)
19492004
{
19502005
const struct bt_ascs_qos_op *op;
19512006
struct net_buf_simple_state state;
@@ -1959,8 +2014,7 @@ static bool is_valid_qos_len(struct net_buf_simple *buf)
19592014
}
19602015

19612016
op = net_buf_simple_pull_mem(buf, sizeof(*op));
1962-
if (op->num_ases < 1) {
1963-
LOG_WRN("Number_of_ASEs parameter value is less than 1");
2017+
if (!is_valid_num_ases(conn, op->num_ases)) {
19642018
return false;
19652019
}
19662020

@@ -1986,7 +2040,7 @@ static ssize_t ascs_qos(struct bt_conn *conn, struct net_buf_simple *buf)
19862040
{
19872041
const struct bt_ascs_qos_op *req;
19882042

1989-
if (!is_valid_qos_len(buf)) {
2043+
if (!is_valid_qos_len(conn, buf)) {
19902044
return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
19912045
}
19922046

@@ -2327,7 +2381,7 @@ static int ase_enable(struct bt_ascs_ase *ase, struct bt_ascs_metadata *meta)
23272381
return 0;
23282382
}
23292383

2330-
static bool is_valid_enable_len(struct net_buf_simple *buf)
2384+
static bool is_valid_enable_len(struct bt_conn *conn, struct net_buf_simple *buf)
23312385
{
23322386
const struct bt_ascs_enable_op *op;
23332387
struct net_buf_simple_state state;
@@ -2340,8 +2394,7 @@ static bool is_valid_enable_len(struct net_buf_simple *buf)
23402394
}
23412395

23422396
op = net_buf_simple_pull_mem(buf, sizeof(*op));
2343-
if (op->num_ases < 1) {
2344-
LOG_WRN("Number_of_ASEs parameter value is less than 1");
2397+
if (!is_valid_num_ases(conn, op->num_ases)) {
23452398
return false;
23462399
}
23472400

@@ -2378,7 +2431,7 @@ static ssize_t ascs_enable(struct bt_conn *conn, struct net_buf_simple *buf)
23782431
struct bt_ascs_metadata *meta;
23792432
int i;
23802433

2381-
if (!is_valid_enable_len(buf)) {
2434+
if (!is_valid_enable_len(conn, buf)) {
23822435
return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
23832436
}
23842437

@@ -2472,7 +2525,7 @@ static void ase_start(struct bt_ascs_ase *ase)
24722525
ascs_cp_rsp_success(ASE_ID(ase));
24732526
}
24742527

2475-
static bool is_valid_start_len(struct net_buf_simple *buf)
2528+
static bool is_valid_start_len(struct bt_conn *conn, struct net_buf_simple *buf)
24762529
{
24772530
const struct bt_ascs_start_op *op;
24782531
struct net_buf_simple_state state;
@@ -2485,8 +2538,7 @@ static bool is_valid_start_len(struct net_buf_simple *buf)
24852538
}
24862539

24872540
op = net_buf_simple_pull_mem(buf, sizeof(*op));
2488-
if (op->num_ases < 1) {
2489-
LOG_WRN("Number_of_ASEs parameter value is less than 1");
2541+
if (!is_valid_num_ases(conn, op->num_ases)) {
24902542
return false;
24912543
}
24922544

@@ -2505,7 +2557,7 @@ static ssize_t ascs_start(struct bt_conn *conn, struct net_buf_simple *buf)
25052557
const struct bt_ascs_start_op *req;
25062558
int i;
25072559

2508-
if (!is_valid_start_len(buf)) {
2560+
if (!is_valid_start_len(conn, buf)) {
25092561
return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
25102562
}
25112563

@@ -2555,7 +2607,7 @@ static ssize_t ascs_start(struct bt_conn *conn, struct net_buf_simple *buf)
25552607
return buf->size;
25562608
}
25572609

2558-
static bool is_valid_disable_len(struct net_buf_simple *buf)
2610+
static bool is_valid_disable_len(struct bt_conn *conn, struct net_buf_simple *buf)
25592611
{
25602612
const struct bt_ascs_disable_op *op;
25612613
struct net_buf_simple_state state;
@@ -2568,8 +2620,7 @@ static bool is_valid_disable_len(struct net_buf_simple *buf)
25682620
}
25692621

25702622
op = net_buf_simple_pull_mem(buf, sizeof(*op));
2571-
if (op->num_ases < 1) {
2572-
LOG_WRN("Number_of_ASEs parameter value is less than 1");
2623+
if (!is_valid_num_ases(conn, op->num_ases)) {
25732624
return false;
25742625
}
25752626

@@ -2587,7 +2638,7 @@ static ssize_t ascs_disable(struct bt_conn *conn, struct net_buf_simple *buf)
25872638
{
25882639
const struct bt_ascs_disable_op *req;
25892640

2590-
if (!is_valid_disable_len(buf)) {
2641+
if (!is_valid_disable_len(conn, buf)) {
25912642
return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
25922643
}
25932644

@@ -2685,7 +2736,7 @@ static void ase_stop(struct bt_ascs_ase *ase)
26852736
ascs_cp_rsp_success(ASE_ID(ase));
26862737
}
26872738

2688-
static bool is_valid_stop_len(struct net_buf_simple *buf)
2739+
static bool is_valid_stop_len(struct bt_conn *conn, struct net_buf_simple *buf)
26892740
{
26902741
const struct bt_ascs_stop_op *op;
26912742
struct net_buf_simple_state state;
@@ -2698,7 +2749,7 @@ static bool is_valid_stop_len(struct net_buf_simple *buf)
26982749
}
26992750

27002751
op = net_buf_simple_pull_mem(buf, sizeof(*op));
2701-
if (op->num_ases < 1) {
2752+
if (op->num_ases < 1U) {
27022753
LOG_WRN("Number_of_ASEs parameter value is less than 1");
27032754
return false;
27042755
}
@@ -2718,7 +2769,7 @@ static ssize_t ascs_stop(struct bt_conn *conn, struct net_buf_simple *buf)
27182769
const struct bt_ascs_start_op *req;
27192770
int i;
27202771

2721-
if (!is_valid_stop_len(buf)) {
2772+
if (!is_valid_stop_len(conn, buf)) {
27222773
return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
27232774
}
27242775

@@ -2768,7 +2819,7 @@ static ssize_t ascs_stop(struct bt_conn *conn, struct net_buf_simple *buf)
27682819
return buf->size;
27692820
}
27702821

2771-
static bool is_valid_metadata_len(struct net_buf_simple *buf)
2822+
static bool is_valid_metadata_len(struct bt_conn *conn, struct net_buf_simple *buf)
27722823
{
27732824
const struct bt_ascs_metadata_op *op;
27742825
struct net_buf_simple_state state;
@@ -2781,8 +2832,7 @@ static bool is_valid_metadata_len(struct net_buf_simple *buf)
27812832
}
27822833

27832834
op = net_buf_simple_pull_mem(buf, sizeof(*op));
2784-
if (op->num_ases < 1) {
2785-
LOG_WRN("Number_of_ASEs parameter value is less than 1");
2835+
if (!is_valid_num_ases(conn, op->num_ases)) {
27862836
return false;
27872837
}
27882838

@@ -2819,7 +2869,7 @@ static ssize_t ascs_metadata(struct bt_conn *conn, struct net_buf_simple *buf)
28192869
struct bt_ascs_metadata *meta;
28202870
int i;
28212871

2822-
if (!is_valid_metadata_len(buf)) {
2872+
if (!is_valid_metadata_len(conn, buf)) {
28232873
return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
28242874
}
28252875

@@ -2862,7 +2912,7 @@ static ssize_t ascs_metadata(struct bt_conn *conn, struct net_buf_simple *buf)
28622912
return buf->size;
28632913
}
28642914

2865-
static bool is_valid_release_len(struct net_buf_simple *buf)
2915+
static bool is_valid_release_len(struct bt_conn *conn, struct net_buf_simple *buf)
28662916
{
28672917
const struct bt_ascs_release_op *op;
28682918
struct net_buf_simple_state state;
@@ -2875,8 +2925,7 @@ static bool is_valid_release_len(struct net_buf_simple *buf)
28752925
}
28762926

28772927
op = net_buf_simple_pull_mem(buf, sizeof(*op));
2878-
if (op->num_ases < 1) {
2879-
LOG_WRN("Number_of_ASEs parameter value is less than 1");
2928+
if (!is_valid_num_ases(conn, op->num_ases)) {
28802929
return false;
28812930
}
28822931

@@ -2895,7 +2944,7 @@ static ssize_t ascs_release(struct bt_conn *conn, struct net_buf_simple *buf)
28952944
const struct bt_ascs_release_op *req;
28962945
int i;
28972946

2898-
if (!is_valid_release_len(buf)) {
2947+
if (!is_valid_release_len(conn, buf)) {
28992948
return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
29002949
}
29012950

@@ -3003,7 +3052,7 @@ static ssize_t ascs_cp_write(struct bt_conn *conn,
30033052
}
30043053

30053054
respond:
3006-
control_point_notify(conn, rsp_buf.data, rsp_buf.len);
3055+
control_point_notify(conn, cp_rsp_buf.data, cp_rsp_buf.len);
30073056

30083057
return len;
30093058
}

0 commit comments

Comments
 (0)