Bluetooth: AVDTP: Check buffer length before pulling it

Check the remaining data length of net buffer before pulling data from
it.

Fixes https://github.com/zephyrproject-rtos/zephyr/issues/83024

Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
This commit is contained in:
Lyle Zhu 2024-12-16 16:37:19 +08:00 committed by Benjamin Cabé
parent dbc6a50698
commit 830c1f8134

View file

@ -231,6 +231,11 @@ static void avdtp_discover_handler(struct bt_avdtp *session,
DISCOVER_REQ(session->req)->status = 0;
DISCOVER_REQ(session->req)->buf = buf;
} else if (msg_type == BT_AVDTP_REJECT) {
if (buf->len < 1) {
LOG_WRN("Invalid RSP frame");
return;
}
DISCOVER_REQ(session->req)->status = net_buf_pull_u8(buf);
} else if (msg_type == BT_AVDTP_GEN_REJECT) {
DISCOVER_REQ(session->req)->status = BT_AVDTP_NOT_SUPPORTED_COMMAND;
@ -266,6 +271,11 @@ static void avdtp_get_capabilities_handler(struct bt_avdtp *session,
struct bt_avdtp_sep *sep;
uint8_t error_code = 0;
if (buf->len < 1) {
LOG_WRN("Invalid ACP SEID");
return;
}
sep = avdtp_get_sep(net_buf_pull_u8(buf) >> 2);
if ((sep == NULL) || (session->ops->get_capabilities_ind == NULL)) {
err = -ENOTSUP;
@ -320,6 +330,11 @@ static void avdtp_get_capabilities_handler(struct bt_avdtp *session,
GET_CAP_REQ(session->req)->buf = buf;
}
} else if (msg_type == BT_AVDTP_REJECT) {
if (buf->len < 1) {
LOG_WRN("Invalid RSP frame");
return;
}
GET_CAP_REQ(session->req)->status = net_buf_pull_u8(buf);
} else if (msg_type == BT_AVDTP_GEN_REJECT) {
GET_CAP_REQ(session->req)->status = BT_AVDTP_NOT_SUPPORTED_COMMAND;
@ -342,6 +357,11 @@ static void avdtp_process_configuration(struct bt_avdtp *session,
struct net_buf *rsp_buf;
uint8_t error_code = 0;
if (buf->len < 1) {
LOG_WRN("Invalid ACP SEID");
return;
}
sep = avdtp_get_sep(net_buf_pull_u8(buf) >> 2);
if ((sep == NULL) || (session->ops->set_configuration_ind == NULL)) {
err = -ENOTSUP;
@ -352,6 +372,11 @@ static void avdtp_process_configuration(struct bt_avdtp *session,
} else {
uint8_t int_seid;
if (buf->len < 1) {
LOG_WRN("Invalid INT SEID");
return;
}
/* INT Stream Endpoint ID */
int_seid = net_buf_pull_u8(buf);
err = session->ops->set_configuration_ind(session,
@ -399,6 +424,11 @@ static void avdtp_process_configuration(struct bt_avdtp *session,
SET_CONF_REQ(req)->status = 0;
SET_CONF_REQ(req)->sep->state = AVDTP_CONFIGURED;
} else if (msg_type == BT_AVDTP_REJECT) {
if (buf->len < 2) {
LOG_WRN("Invalid RSP frame");
return;
}
/* Service Category */
net_buf_pull_u8(buf);
SET_CONF_REQ(req)->status = net_buf_pull_u8(buf);
@ -458,6 +488,11 @@ static void avdtp_open_handler(struct bt_avdtp *session,
struct net_buf *rsp_buf;
uint8_t error_code = 0;
if (buf->len < 1) {
LOG_WRN("Invalid ACP SEID");
return;
}
sep = avdtp_get_sep(net_buf_pull_u8(buf) >> 2);
if ((sep == NULL) || (session->ops->open_ind == NULL)) {
err = -ENOTSUP;
@ -510,6 +545,11 @@ static void avdtp_open_handler(struct bt_avdtp *session,
return;
}
} else if (msg_type == BT_AVDTP_REJECT) {
if (buf->len < 1) {
LOG_WRN("Invalid RSP frame");
return;
}
OPEN_REQ(req)->status = net_buf_pull_u8(buf);
} else if (msg_type == BT_AVDTP_GEN_REJECT) {
OPEN_REQ(req)->status = BT_AVDTP_NOT_SUPPORTED_COMMAND;
@ -535,6 +575,11 @@ static void avdtp_start_handler(struct bt_avdtp *session,
struct net_buf *rsp_buf;
uint8_t error_code = 0;
if (buf->len < 1) {
LOG_WRN("Invalid ACP SEID");
return;
}
sep = avdtp_get_sep(net_buf_pull_u8(buf) >> 2);
if ((sep == NULL) || (session->ops->start_ind == NULL)) {
err = -ENOTSUP;
@ -584,6 +629,11 @@ static void avdtp_start_handler(struct bt_avdtp *session,
} else if (msg_type == BT_AVDTP_REJECT) {
uint8_t acp_seid;
if (buf->len < 2) {
LOG_WRN("Invalid RSP frame");
return;
}
acp_seid = net_buf_pull_u8(buf);
if (acp_seid != START_REQ(req)->acp_stream_ep_id) {
return;
@ -611,6 +661,11 @@ static void avdtp_close_handler(struct bt_avdtp *session,
struct net_buf *rsp_buf;
uint8_t error_code = 0;
if (buf->len < 1) {
LOG_WRN("Invalid ACP SEID");
return;
}
sep = avdtp_get_sep(net_buf_pull_u8(buf) >> 2);
if ((sep == NULL) || (session->ops->close_ind == NULL)) {
err = -ENOTSUP;
@ -660,6 +715,11 @@ static void avdtp_suspend_handler(struct bt_avdtp *session,
struct net_buf *rsp_buf;
uint8_t error_code = 0;
if (buf->len < 1) {
LOG_WRN("Invalid ACP SEID");
return;
}
sep = avdtp_get_sep(net_buf_pull_u8(buf) >> 2);
if ((sep == NULL) || (session->ops->suspend_ind == NULL)) {
err = -ENOTSUP;
@ -708,6 +768,11 @@ static void avdtp_abort_handler(struct bt_avdtp *session,
struct net_buf *rsp_buf;
uint8_t error_code = 0;
if (buf->len < 1) {
LOG_WRN("Invalid ACP SEID");
return;
}
sep = avdtp_get_sep(net_buf_pull_u8(buf) >> 2);
if ((sep == NULL) || (session->ops->abort_ind == NULL)) {
err = -ENOTSUP;
@ -1201,19 +1266,32 @@ int bt_avdtp_parse_capability_codec(struct net_buf *buf,
case BT_AVDTP_SERVICE_HEADER_COMPRESSION:
case BT_AVDTP_SERVICE_MULTIPLEXING:
case BT_AVDTP_SERVICE_DELAY_REPORTING:
if (buf->len < 1) {
return -EINVAL;
}
length = net_buf_pull_u8(buf);
if (buf->len < length) {
return -EINVAL;
}
if (length > 0) {
net_buf_pull_mem(buf, length);
}
break;
case BT_AVDTP_SERVICE_MEDIA_CODEC:
if (buf->len < 1) {
return -EINVAL;
}
length = net_buf_pull_u8(buf);
if (buf->len < length) {
return -EINVAL;
}
if (length > 3) {
data = net_buf_pull_u8(buf);
if (net_buf_tailroom(buf) < (length - 1)) {
return -EINVAL;
}
if (data == BT_AVDTP_AUDIO) {
data = net_buf_pull_u8(buf);
*codec_type = data;