summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCatalin Enache <catalin.enache@windriver.com>2021-03-23 19:37:57 -0400
committerRichard Purdie <richard.purdie@linuxfoundation.org>2021-04-06 22:45:36 +0100
commit4ea2ccd7e9f74df8346e35022dea107f4e00ef86 (patch)
tree5f4597766bd5fbbd35e1749aac8f7d58d7496ed8
parent5568e334d70213d611fd34910bdf4e4b00f09e99 (diff)
downloadpoky-4ea2ccd7e9f74df8346e35022dea107f4e00ef86.tar.gz
connman: fix CVE-2021-26675, CVE-2021-26676
A stack-based buffer overflow in dnsproxy in ConnMan before 1.39 could be used by network adjacent attackers to execute code. gdhcp in ConnMan before 1.39 could be used by network-adjacent. attackers to leak sensitive stack information, allowing further exploitation of bugs in gdhcp. References: https://nvd.nist.gov/vuln/detail/CVE-2021-26675 https://nvd.nist.gov/vuln/detail/CVE-2021-26676 Upstream patches: https://git.kernel.org/pub/scm/network/connman/connman.git/commit/?id=e4079a20f617a4b076af503f6e4e8b0304c9f2cb https://git.kernel.org/pub/scm/network/connman/connman.git/commit/?id=58d397ba74873384aee449690a9070bacd5676fa https://git.kernel.org/pub/scm/network/connman/connman.git/commit/?id=a74524b3e3fad81b0fd1084ffdf9f2ea469cd9b1 (From OE-Core rev: 3c78000aaf8e4ee8ffb7674f5c286e2c110f167b) Signed-off-by: Catalin Enache <catalin.enache@windriver.com> Signed-off-by: Randy MacLeod <Randy.MacLeod@windriver.com> Signed-off-by: Steve Sakoman <steve@sakoman.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--meta/recipes-connectivity/connman/connman/CVE-2021-26675.patch62
-rw-r--r--meta/recipes-connectivity/connman/connman/CVE-2021-26676-0001.patch231
-rw-r--r--meta/recipes-connectivity/connman/connman/CVE-2021-26676-0002.patch33
-rw-r--r--meta/recipes-connectivity/connman/connman_1.37.bb3
4 files changed, 329 insertions, 0 deletions
diff --git a/meta/recipes-connectivity/connman/connman/CVE-2021-26675.patch b/meta/recipes-connectivity/connman/connman/CVE-2021-26675.patch
new file mode 100644
index 0000000000..2648a832ca
--- /dev/null
+++ b/meta/recipes-connectivity/connman/connman/CVE-2021-26675.patch
@@ -0,0 +1,62 @@
1From e4079a20f617a4b076af503f6e4e8b0304c9f2cb Mon Sep 17 00:00:00 2001
2From: Colin Wee <cwee@tesla.com>
3Date: Thu, 28 Jan 2021 19:41:53 +0100
4Subject: [PATCH] dnsproxy: Add length checks to prevent buffer overflow
5
6Fixes: CVE-2021-26675
7
8Upstream-Status: Backport
9CVE: CVE-2021-26675
10
11Reference to upstream patch:
12https://git.kernel.org/pub/scm/network/connman/connman.git/commit/?id=e4079a20f617a4b076af503f6e4e8b0304c9f2cb
13
14Signed-off-by: Catalin Enache <catalin.enache@windriver.com>
15---
16 src/dnsproxy.c | 14 +++++++++++---
17 1 file changed, 11 insertions(+), 3 deletions(-)
18
19diff --git a/src/dnsproxy.c b/src/dnsproxy.c
20index a7bf87a1..4f5c897f 100644
21--- a/src/dnsproxy.c
22+++ b/src/dnsproxy.c
23@@ -1767,6 +1767,7 @@ static char *uncompress(int16_t field_count, char *start, char *end,
24 char **uncompressed_ptr)
25 {
26 char *uptr = *uncompressed_ptr; /* position in result buffer */
27+ char * const uncomp_end = uncompressed + uncomp_len - 1;
28
29 debug("count %d ptr %p end %p uptr %p", field_count, ptr, end, uptr);
30
31@@ -1787,12 +1788,15 @@ static char *uncompress(int16_t field_count, char *start, char *end,
32 * tmp buffer.
33 */
34
35- ulen = strlen(name);
36- strncpy(uptr, name, uncomp_len - (uptr - uncompressed));
37-
38 debug("pos %d ulen %d left %d name %s", pos, ulen,
39 (int)(uncomp_len - (uptr - uncompressed)), uptr);
40
41+ ulen = strlen(name);
42+ if ((uptr + ulen + 1) > uncomp_end) {
43+ goto out;
44+ }
45+ strncpy(uptr, name, uncomp_len - (uptr - uncompressed));
46+
47 uptr += ulen;
48 *uptr++ = '\0';
49
50@@ -1802,6 +1806,10 @@ static char *uncompress(int16_t field_count, char *start, char *end,
51 * We copy also the fixed portion of the result (type, class,
52 * ttl, address length and the address)
53 */
54+ if ((uptr + NS_RRFIXEDSZ) > uncomp_end) {
55+ debug("uncompressed data too large for buffer");
56+ goto out;
57+ }
58 memcpy(uptr, ptr, NS_RRFIXEDSZ);
59
60 dns_type = uptr[0] << 8 | uptr[1];
61--
622.17.1
diff --git a/meta/recipes-connectivity/connman/connman/CVE-2021-26676-0001.patch b/meta/recipes-connectivity/connman/connman/CVE-2021-26676-0001.patch
new file mode 100644
index 0000000000..4104e4bfc6
--- /dev/null
+++ b/meta/recipes-connectivity/connman/connman/CVE-2021-26676-0001.patch
@@ -0,0 +1,231 @@
1From 58d397ba74873384aee449690a9070bacd5676fa Mon Sep 17 00:00:00 2001
2From: Colin Wee <cwee@tesla.com>
3Date: Thu, 28 Jan 2021 19:39:14 +0100
4Subject: [PATCH] gdhcp: Avoid reading invalid data in dhcp_get_option
5
6Upstream-Status: Backport
7CVE: CVE-2021-26676
8
9Reference to upstream patch:
10https://git.kernel.org/pub/scm/network/connman/connman.git/commit/?id=58d397ba74873384aee449690a9070bacd5676fa
11
12Signed-off-by: Catalin Enache <catalin.enache@windriver.com>
13---
14 gdhcp/client.c | 20 +++++++++++---------
15 gdhcp/common.c | 24 +++++++++++++++++++-----
16 gdhcp/common.h | 2 +-
17 gdhcp/server.c | 12 +++++++-----
18 4 files changed, 38 insertions(+), 20 deletions(-)
19
20diff --git a/gdhcp/client.c b/gdhcp/client.c
21index 09dfe5ec..6a5613e7 100644
22--- a/gdhcp/client.c
23+++ b/gdhcp/client.c
24@@ -1629,12 +1629,12 @@ static void start_request(GDHCPClient *dhcp_client)
25 NULL);
26 }
27
28-static uint32_t get_lease(struct dhcp_packet *packet)
29+static uint32_t get_lease(struct dhcp_packet *packet, uint16_t packet_len)
30 {
31 uint8_t *option;
32 uint32_t lease_seconds;
33
34- option = dhcp_get_option(packet, DHCP_LEASE_TIME);
35+ option = dhcp_get_option(packet, packet_len, DHCP_LEASE_TIME);
36 if (!option)
37 return 3600;
38
39@@ -2226,7 +2226,8 @@ static void get_dhcpv6_request(GDHCPClient *dhcp_client,
40 }
41 }
42
43-static void get_request(GDHCPClient *dhcp_client, struct dhcp_packet *packet)
44+static void get_request(GDHCPClient *dhcp_client, struct dhcp_packet *packet,
45+ uint16_t packet_len)
46 {
47 GDHCPOptionType type;
48 GList *list, *value_list;
49@@ -2237,7 +2238,7 @@ static void get_request(GDHCPClient *dhcp_client, struct dhcp_packet *packet)
50 for (list = dhcp_client->request_list; list; list = list->next) {
51 code = (uint8_t) GPOINTER_TO_INT(list->data);
52
53- option = dhcp_get_option(packet, code);
54+ option = dhcp_get_option(packet, packet_len, code);
55 if (!option) {
56 g_hash_table_remove(dhcp_client->code_value_hash,
57 GINT_TO_POINTER((int) code));
58@@ -2297,6 +2298,7 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
59 re = dhcp_recv_l2_packet(&packet,
60 dhcp_client->listener_sockfd,
61 &dst_addr);
62+ pkt_len = (uint16_t)(unsigned int)re;
63 xid = packet.xid;
64 } else if (dhcp_client->listen_mode == L3) {
65 if (dhcp_client->type == G_DHCP_IPV6) {
66@@ -2361,7 +2363,7 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
67 dhcp_client->status_code = status;
68 }
69 } else {
70- message_type = dhcp_get_option(&packet, DHCP_MESSAGE_TYPE);
71+ message_type = dhcp_get_option(&packet, pkt_len, DHCP_MESSAGE_TYPE);
72 if (!message_type)
73 return TRUE;
74 }
75@@ -2378,7 +2380,7 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
76 dhcp_client->timeout = 0;
77 dhcp_client->retry_times = 0;
78
79- option = dhcp_get_option(&packet, DHCP_SERVER_ID);
80+ option = dhcp_get_option(&packet, pkt_len, DHCP_SERVER_ID);
81 dhcp_client->server_ip = get_be32(option);
82 dhcp_client->requested_ip = ntohl(packet.yiaddr);
83
84@@ -2428,9 +2430,9 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
85
86 remove_timeouts(dhcp_client);
87
88- dhcp_client->lease_seconds = get_lease(&packet);
89+ dhcp_client->lease_seconds = get_lease(&packet, pkt_len);
90
91- get_request(dhcp_client, &packet);
92+ get_request(dhcp_client, &packet, pkt_len);
93
94 switch_listening_mode(dhcp_client, L_NONE);
95
96@@ -2438,7 +2440,7 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
97 dhcp_client->assigned_ip = get_ip(packet.yiaddr);
98
99 if (dhcp_client->state == REBOOTING) {
100- option = dhcp_get_option(&packet,
101+ option = dhcp_get_option(&packet, pkt_len,
102 DHCP_SERVER_ID);
103 dhcp_client->server_ip = get_be32(option);
104 }
105diff --git a/gdhcp/common.c b/gdhcp/common.c
106index 1d667d17..c8916aa8 100644
107--- a/gdhcp/common.c
108+++ b/gdhcp/common.c
109@@ -73,18 +73,21 @@ GDHCPOptionType dhcp_get_code_type(uint8_t code)
110 return OPTION_UNKNOWN;
111 }
112
113-uint8_t *dhcp_get_option(struct dhcp_packet *packet, int code)
114+uint8_t *dhcp_get_option(struct dhcp_packet *packet, uint16_t packet_len, int code)
115 {
116 int len, rem;
117- uint8_t *optionptr;
118+ uint8_t *optionptr, *options_end;
119+ size_t options_len;
120 uint8_t overload = 0;
121
122 /* option bytes: [code][len][data1][data2]..[dataLEN] */
123 optionptr = packet->options;
124 rem = sizeof(packet->options);
125+ options_len = packet_len - (sizeof(*packet) - sizeof(packet->options));
126+ options_end = optionptr + options_len - 1;
127
128 while (1) {
129- if (rem <= 0)
130+ if ((rem <= 0) && (optionptr + OPT_CODE > options_end))
131 /* Bad packet, malformed option field */
132 return NULL;
133
134@@ -115,14 +118,25 @@ uint8_t *dhcp_get_option(struct dhcp_packet *packet, int code)
135 break;
136 }
137
138+ if (optionptr + OPT_LEN > options_end) {
139+ /* bad packet, would read length field from OOB */
140+ return NULL;
141+ }
142+
143 len = 2 + optionptr[OPT_LEN];
144
145 rem -= len;
146 if (rem < 0)
147 continue; /* complain and return NULL */
148
149- if (optionptr[OPT_CODE] == code)
150- return optionptr + OPT_DATA;
151+ if (optionptr[OPT_CODE] == code) {
152+ if (optionptr + len > options_end) {
153+ /* bad packet, option length points OOB */
154+ return NULL;
155+ } else {
156+ return optionptr + OPT_DATA;
157+ }
158+ }
159
160 if (optionptr[OPT_CODE] == DHCP_OPTION_OVERLOAD)
161 overload |= optionptr[OPT_DATA];
162diff --git a/gdhcp/common.h b/gdhcp/common.h
163index 9660231c..8f63fd75 100644
164--- a/gdhcp/common.h
165+++ b/gdhcp/common.h
166@@ -179,7 +179,7 @@ struct in6_pktinfo {
167 };
168 #endif
169
170-uint8_t *dhcp_get_option(struct dhcp_packet *packet, int code);
171+uint8_t *dhcp_get_option(struct dhcp_packet *packet, uint16_t packet_len, int code);
172 uint8_t *dhcpv6_get_option(struct dhcpv6_packet *packet, uint16_t pkt_len,
173 int code, uint16_t *option_len, int *option_count);
174 uint8_t *dhcpv6_get_sub_option(unsigned char *option, uint16_t max_len,
175diff --git a/gdhcp/server.c b/gdhcp/server.c
176index 85405f19..52ea2a55 100644
177--- a/gdhcp/server.c
178+++ b/gdhcp/server.c
179@@ -413,7 +413,7 @@ error:
180 }
181
182
183-static uint8_t check_packet_type(struct dhcp_packet *packet)
184+static uint8_t check_packet_type(struct dhcp_packet *packet, uint16_t packet_len)
185 {
186 uint8_t *type;
187
188@@ -423,7 +423,7 @@ static uint8_t check_packet_type(struct dhcp_packet *packet)
189 if (packet->op != BOOTREQUEST)
190 return 0;
191
192- type = dhcp_get_option(packet, DHCP_MESSAGE_TYPE);
193+ type = dhcp_get_option(packet, packet_len, DHCP_MESSAGE_TYPE);
194
195 if (!type)
196 return 0;
197@@ -651,6 +651,7 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
198 struct dhcp_lease *lease;
199 uint32_t requested_nip = 0;
200 uint8_t type, *server_id_option, *request_ip_option;
201+ uint16_t packet_len;
202 int re;
203
204 if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
205@@ -661,12 +662,13 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
206 re = dhcp_recv_l3_packet(&packet, dhcp_server->listener_sockfd);
207 if (re < 0)
208 return TRUE;
209+ packet_len = (uint16_t)(unsigned int)re;
210
211- type = check_packet_type(&packet);
212+ type = check_packet_type(&packet, packet_len);
213 if (type == 0)
214 return TRUE;
215
216- server_id_option = dhcp_get_option(&packet, DHCP_SERVER_ID);
217+ server_id_option = dhcp_get_option(&packet, packet_len, DHCP_SERVER_ID);
218 if (server_id_option) {
219 uint32_t server_nid =
220 get_unaligned((const uint32_t *) server_id_option);
221@@ -675,7 +677,7 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
222 return TRUE;
223 }
224
225- request_ip_option = dhcp_get_option(&packet, DHCP_REQUESTED_IP);
226+ request_ip_option = dhcp_get_option(&packet, packet_len, DHCP_REQUESTED_IP);
227 if (request_ip_option)
228 requested_nip = get_be32(request_ip_option);
229
230--
2312.17.1
diff --git a/meta/recipes-connectivity/connman/connman/CVE-2021-26676-0002.patch b/meta/recipes-connectivity/connman/connman/CVE-2021-26676-0002.patch
new file mode 100644
index 0000000000..ce909ec293
--- /dev/null
+++ b/meta/recipes-connectivity/connman/connman/CVE-2021-26676-0002.patch
@@ -0,0 +1,33 @@
1From a74524b3e3fad81b0fd1084ffdf9f2ea469cd9b1 Mon Sep 17 00:00:00 2001
2From: Colin Wee <cwee@tesla.com>
3Date: Thu, 28 Jan 2021 19:41:09 +0100
4Subject: [PATCH] gdhcp: Avoid leaking stack data via unitiialized variable
5
6Fixes: CVE-2021-26676
7
8Upstream-Status: Backport
9CVE: CVE-2021-26676
10
11Reference to upstream patch:
12https://git.kernel.org/pub/scm/network/connman/connman.git/commit/?id=a74524b3e3fad81b0fd1084ffdf9f2ea469cd9b1
13
14Signed-off-by: Catalin Enache <catalin.enache@windriver.com>
15---
16 gdhcp/client.c | 2 +-
17 1 file changed, 1 insertion(+), 1 deletion(-)
18
19diff --git a/gdhcp/client.c b/gdhcp/client.c
20index 6a5613e7..c7b85e58 100644
21--- a/gdhcp/client.c
22+++ b/gdhcp/client.c
23@@ -2270,7 +2270,7 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
24 {
25 GDHCPClient *dhcp_client = user_data;
26 struct sockaddr_in dst_addr = { 0 };
27- struct dhcp_packet packet;
28+ struct dhcp_packet packet = { 0 };
29 struct dhcpv6_packet *packet6 = NULL;
30 uint8_t *message_type = NULL, *client_id = NULL, *option,
31 *server_id = NULL;
32--
332.17.1
diff --git a/meta/recipes-connectivity/connman/connman_1.37.bb b/meta/recipes-connectivity/connman/connman_1.37.bb
index 00852bf0d6..bdab4c4f18 100644
--- a/meta/recipes-connectivity/connman/connman_1.37.bb
+++ b/meta/recipes-connectivity/connman/connman_1.37.bb
@@ -6,6 +6,9 @@ SRC_URI = "${KERNELORG_MIRROR}/linux/network/${BPN}/${BP}.tar.xz \
6 file://0001-gweb-fix-segfault-with-musl-v1.1.21.patch \ 6 file://0001-gweb-fix-segfault-with-musl-v1.1.21.patch \
7 file://connman \ 7 file://connman \
8 file://no-version-scripts.patch \ 8 file://no-version-scripts.patch \
9 file://CVE-2021-26675.patch \
10 file://CVE-2021-26676-0001.patch \
11 file://CVE-2021-26676-0002.patch \
9" 12"
10 13
11SRC_URI_append_libc-musl = " file://0002-resolve-musl-does-not-implement-res_ninit.patch" 14SRC_URI_append_libc-musl = " file://0002-resolve-musl-does-not-implement-res_ninit.patch"