summaryrefslogtreecommitdiffstats
path: root/meta/recipes-connectivity/bluez5/bluez5/CVE-2022-39176.patch
blob: 7bd1f5f80fae19c2d77fbd874ee20e195ce62ae0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
From 752c7f707c3cc1eb12eadc13bc336a5c484d4bdf Mon Sep 17 00:00:00 2001
From: Hitendra Prajapati <hprajapati@mvista.com>
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 <hprajapati@mvista.com>
---
 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