Skip to content

Commit

Permalink
Bluetooth: AVDTP: Check buffer length before pulling it
Browse files Browse the repository at this point in the history
Check the remaining data length of net buffer before pulling data from
it.

Fixes zephyrproject-rtos/zephyr#83024

(cherry picked from commit 830c1f8)

Original-Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
GitOrigin-RevId: 830c1f8
Cr-Build-Id: 8728219973957200769
Cr-Build-Url: https://cr-buildbucket.appspot.com/build/8728219973957200769
Copybot-Job-Name: zephyr-main-copybot-downstream
Change-Id: I7f45c0bc084722cc2f71a06363567874e2de27c8
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/zephyr/+/6104909
Commit-Queue: Jonathon Murphy <jpmurphy@google.com>
Reviewed-by: Dawid Niedźwiecki <dawidn@google.com>
Tested-by: ChromeOS Prod (Robot) <chromeos-ci-prod@chromeos-bot.iam.gserviceaccount.com>
Tested-by: Dawid Niedźwiecki <dawidn@google.com>
  • Loading branch information
Lyle Zhu authored and Chromeos LUCI committed Dec 20, 2024
1 parent c766274 commit 5bad668
Showing 1 changed file with 81 additions and 3 deletions.
84 changes: 81 additions & 3 deletions subsys/bluetooth/host/classic/avdtp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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,
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 5bad668

Please sign in to comment.