Skip to content

Commit 0fe9756

Browse files
Thalleycarlescufi
authored andcommitted
Bluetooth: BAP: Add validation of qos_pref
The QoS preference defined by ASCS has some specified limits and values that we should enforce. Given the current API we cannot return an error to the unicast server if it supplies invalid values, so we have to resort to a LOG_ERR. For the unicast client we treat invalid QoS preferences similar to other invalid data in the notifications. This also adds additional documentation in the bt_audio_codec_qos_pref struct. Signed-off-by: Emil Gydesen <[email protected]>
1 parent d578c59 commit 0fe9756

File tree

5 files changed

+109
-4
lines changed

5 files changed

+109
-4
lines changed

include/zephyr/bluetooth/audio/audio.h

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -978,13 +978,22 @@ struct bt_audio_codec_qos_pref {
978978
*/
979979
bool unframed_supported;
980980

981-
/** Preferred PHY */
981+
/**
982+
* @brief Preferred PHY bitfield
983+
*
984+
* Bitfield consisting of one or more of @ref BT_GAP_LE_PHY_1M, @ref BT_GAP_LE_PHY_2M and
985+
* @ref BT_GAP_LE_PHY_CODED.
986+
*/
982987
uint8_t phy;
983988

984989
/** Preferred Retransmission Number */
985990
uint8_t rtn;
986991

987-
/** Preferred Transport Latency */
992+
/**
993+
* Preferred Transport Latency
994+
*
995+
* Value range @ref BT_ISO_LATENCY_MIN to @ref BT_ISO_LATENCY_MAX
996+
*/
988997
uint16_t latency;
989998

990999
/**
@@ -1010,14 +1019,15 @@ struct bt_audio_codec_qos_pref {
10101019
/**
10111020
* @brief Preferred minimum Presentation Delay
10121021
*
1013-
* Value range 0 to @ref BT_AUDIO_PD_MAX.
1022+
* Value range @ref bt_audio_codec_qos_pref.pd_min to @ref bt_audio_codec_qos_pref.pd_max.
10141023
*/
10151024
uint32_t pref_pd_min;
10161025

10171026
/**
10181027
* @brief Preferred maximum Presentation Delay
10191028
*
1020-
* Value range 0 to @ref BT_AUDIO_PD_MAX.
1029+
* Value range @ref bt_audio_codec_qos_pref.pd_min to @ref bt_audio_codec_qos_pref.pd_max,
1030+
* and higher than @ref bt_audio_codec_qos_pref.pref_pd_min
10211031
*/
10221032
uint32_t pref_pd_max;
10231033
};

subsys/bluetooth/audio/ascs.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1631,6 +1631,16 @@ static int ase_config(struct bt_ascs_ase *ase, const struct bt_ascs_config *cfg)
16311631
BT_BAP_ASCS_REASON_NONE);
16321632
}
16331633

1634+
if (err == 0 && !bt_audio_valid_qos_pref(&ase->ep.qos_pref)) {
1635+
LOG_ERR("Invalid QoS preferences");
1636+
1637+
/* If the upper layers provide an invalid QoS preferences we reject the
1638+
* request from the client, as it would not be able to parse the result
1639+
* as valid anyways
1640+
*/
1641+
err = -EINVAL;
1642+
}
1643+
16341644
if (err) {
16351645
ascs_app_rsp_warn_valid(&rsp);
16361646

@@ -1662,6 +1672,16 @@ static int ase_config(struct bt_ascs_ase *ase, const struct bt_ascs_config *cfg)
16621672
BT_BAP_ASCS_REASON_NONE);
16631673
}
16641674

1675+
if (err == 0 && !bt_audio_valid_qos_pref(&ase->ep.qos_pref)) {
1676+
LOG_ERR("Invalid QoS preferences");
1677+
1678+
/* If the upper layers provide an invalid QoS preferences we reject the
1679+
* request from the client, as it would not be able to parse the result
1680+
* as valid anyways
1681+
*/
1682+
err = -EINVAL;
1683+
}
1684+
16651685
if (err || stream == NULL) {
16661686
ascs_app_rsp_warn_valid(&rsp);
16671687

subsys/bluetooth/audio/bap_stream.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <zephyr/autoconf.h>
1717
#include <zephyr/bluetooth/bluetooth.h>
1818
#include <zephyr/bluetooth/conn.h>
19+
#include <zephyr/bluetooth/gap.h>
1920
#include <zephyr/bluetooth/gatt.h>
2021
#include <zephyr/bluetooth/hci.h>
2122
#include <zephyr/bluetooth/hci_types.h>
@@ -264,6 +265,69 @@ bool bt_audio_valid_codec_cfg(const struct bt_audio_codec_cfg *codec_cfg)
264265
return true;
265266
}
266267

268+
bool bt_audio_valid_qos_pref(const struct bt_audio_codec_qos_pref *qos_pref)
269+
{
270+
const uint8_t phy_mask = BT_GAP_LE_PHY_1M | BT_GAP_LE_PHY_2M | BT_GAP_LE_PHY_CODED;
271+
272+
if ((qos_pref->phy & (~phy_mask)) != 0U) {
273+
LOG_DBG("Invalid phy: %u", qos_pref->phy);
274+
275+
return false;
276+
}
277+
278+
if (!IN_RANGE(qos_pref->latency, BT_ISO_LATENCY_MIN, BT_ISO_LATENCY_MAX)) {
279+
LOG_DBG("Invalid latency: %u", qos_pref->latency);
280+
281+
return false;
282+
}
283+
284+
if (qos_pref->pd_min > BT_AUDIO_PD_MAX) {
285+
LOG_DBG("Invalid pd_min: %u", qos_pref->pd_min);
286+
287+
return false;
288+
}
289+
290+
if (qos_pref->pd_max > BT_AUDIO_PD_MAX) {
291+
LOG_DBG("Invalid pd_min: %u", qos_pref->pd_min);
292+
293+
return false;
294+
}
295+
296+
if (qos_pref->pd_max < qos_pref->pd_min) {
297+
LOG_DBG("Invalid combination of pd_min %u and pd_max: %u", qos_pref->pd_min,
298+
qos_pref->pd_max);
299+
300+
return false;
301+
}
302+
303+
/* The absolute minimum and maximum values of pref_pd_min and pref_pd_max are implicitly
304+
* checked using the bounds of pd_min and pd_max, so we can just compare the preferences
305+
* to the min and max values that have been bound checked already
306+
*/
307+
if (!IN_RANGE(qos_pref->pref_pd_min, qos_pref->pd_min, qos_pref->pd_max)) {
308+
LOG_DBG("Invalid combination of pref_pd_min %u, pd_min %u and pd_max: %u",
309+
qos_pref->pref_pd_min, qos_pref->pd_min, qos_pref->pd_max);
310+
311+
return false;
312+
}
313+
314+
if (qos_pref->pref_pd_max < qos_pref->pref_pd_min) {
315+
LOG_DBG("Invalid combination of pref_pd_min %u and pref_pd_max: %u",
316+
qos_pref->pref_pd_min, qos_pref->pref_pd_max);
317+
318+
return false;
319+
}
320+
321+
if (!IN_RANGE(qos_pref->pref_pd_max, qos_pref->pd_min, qos_pref->pd_max)) {
322+
LOG_DBG("Invalid combination of pref_pd_max %u, pd_min %u and pd_max: %u",
323+
qos_pref->pref_pd_max, qos_pref->pd_min, qos_pref->pd_max);
324+
325+
return false;
326+
}
327+
328+
return true;
329+
}
330+
267331
#if defined(CONFIG_BT_AUDIO_TX)
268332
static bool bt_bap_stream_can_send(const struct bt_bap_stream *stream)
269333
{

subsys/bluetooth/audio/bap_stream.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ void bt_bap_stream_detach(struct bt_bap_stream *stream);
3232

3333
enum bt_bap_ascs_reason bt_audio_verify_qos(const struct bt_audio_codec_qos *qos);
3434
bool bt_audio_valid_codec_cfg(const struct bt_audio_codec_cfg *codec_cfg);
35+
bool bt_audio_valid_qos_pref(const struct bt_audio_codec_qos_pref *qos_pref);
3536
bool bt_bap_stream_can_disconnect(const struct bt_bap_stream *stream);
3637

3738
enum bt_bap_ascs_reason bt_bap_stream_verify_qos(const struct bt_bap_stream *stream,

subsys/bluetooth/audio/bap_unicast_client.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,16 @@ static void unicast_client_ep_config_state(struct bt_bap_ep *ep, struct net_buf_
740740
pref->latency, pref->pd_min, pref->pd_max, pref->pref_pd_min, pref->pref_pd_max,
741741
stream->codec_cfg->id);
742742

743+
if (!bt_audio_valid_qos_pref(pref)) {
744+
LOG_DBG("Invalid QoS preferences");
745+
memset(pref, 0, sizeof(*pref));
746+
747+
/* If the sever provide an invalid QoS preferences we treat it as an error and do
748+
* nothing
749+
*/
750+
return;
751+
}
752+
743753
unicast_client_ep_set_codec_cfg(ep, cfg->codec.id, sys_le16_to_cpu(cfg->codec.cid),
744754
sys_le16_to_cpu(cfg->codec.vid), cc, cfg->cc_len, NULL);
745755

0 commit comments

Comments
 (0)