From 752c7f707c3cc1eb12eadc13bc336a5c484d4bdf Mon Sep 17 00:00:00 2001 From: Hitendra Prajapati Date: Wed, 28 Sep 2022 10:45:53 +0530 Subject: [PATCH] CVE-2022-39176 Upstream-Status: Backport [https://launchpad.net/ubuntu/+source/bluez/5.53-0ubuntu3.6] CVE: CVE-2022-39176 Signed-off-by: Hitendra Prajapati --- profiles/audio/avdtp.c | 56 +++++++++++++++++++++++++++--------------- profiles/audio/avrcp.c | 8 ++++++ 2 files changed, 44 insertions(+), 20 deletions(-) diff --git a/profiles/audio/avdtp.c b/profiles/audio/avdtp.c index 782268c..0adf413 100644 --- a/profiles/audio/avdtp.c +++ b/profiles/audio/avdtp.c @@ -1261,43 +1261,53 @@ struct avdtp_remote_sep *avdtp_find_remote_sep(struct avdtp *session, return NULL; } -static GSList *caps_to_list(uint8_t *data, int size, +static GSList *caps_to_list(uint8_t *data, size_t size, struct avdtp_service_capability **codec, gboolean *delay_reporting) { + struct avdtp_service_capability *cap; GSList *caps; - int processed; if (delay_reporting) *delay_reporting = FALSE; - for (processed = 0, caps = NULL; processed + 2 <= size;) { - struct avdtp_service_capability *cap; - uint8_t length, category; + if (size < sizeof(*cap)) + return NULL; + + for (caps = NULL; size >= sizeof(*cap);) { + struct avdtp_service_capability *cpy; - category = data[0]; - length = data[1]; + cap = (struct avdtp_service_capability *)data; - if (processed + 2 + length > size) { + if (sizeof(*cap) + cap->length > size) { error("Invalid capability data in getcap resp"); break; } - cap = g_malloc(sizeof(struct avdtp_service_capability) + - length); - memcpy(cap, data, 2 + length); + if (cap->category == AVDTP_MEDIA_CODEC && + cap->length < sizeof(**codec)) { + error("Invalid codec data in getcap resp"); + break; + } + + cpy = btd_malloc(sizeof(*cpy) + cap->length); + memcpy(cpy, cap, sizeof(*cap) + cap->length); - processed += 2 + length; - data += 2 + length; + size -= sizeof(*cap) + cap->length; + data += sizeof(*cap) + cap->length; - caps = g_slist_append(caps, cap); + caps = g_slist_append(caps, cpy); - if (category == AVDTP_MEDIA_CODEC && - length >= - sizeof(struct avdtp_media_codec_capability)) - *codec = cap; - else if (category == AVDTP_DELAY_REPORTING && delay_reporting) - *delay_reporting = TRUE; + switch (cap->category) { + case AVDTP_MEDIA_CODEC: + if (codec) + *codec = cpy; + break; + case AVDTP_DELAY_REPORTING: + if (delay_reporting) + *delay_reporting = TRUE; + break; + } } return caps; @@ -1494,6 +1504,12 @@ static gboolean avdtp_setconf_cmd(struct avdtp *session, uint8_t transaction, &stream->codec, &stream->delay_reporting); + if (!stream->caps || !stream->codec) { + err = AVDTP_UNSUPPORTED_CONFIGURATION; + category = 0x00; + goto failed_stream; + } + /* Verify that the Media Transport capability's length = 0. Reject otherwise */ for (l = stream->caps; l != NULL; l = g_slist_next(l)) { struct avdtp_service_capability *cap = l->data; diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c index d9471c0..0233d53 100644 --- a/profiles/audio/avrcp.c +++ b/profiles/audio/avrcp.c @@ -1916,6 +1916,14 @@ static size_t handle_vendordep_pdu(struct avctp *conn, uint8_t transaction, goto err_metadata; } + operands += sizeof(*pdu); + operand_count -= sizeof(*pdu); + + if (pdu->params_len != operand_count) { + DBG("AVRCP PDU parameters length don't match"); + pdu->params_len = operand_count; + } + for (handler = session->control_handlers; handler->pdu_id; handler++) { if (handler->pdu_id == pdu->pdu_id) break; -- 2.25.1