summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArmin Kuster <akuster@mvista.com>2016-07-09 11:55:29 -0700
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-07-27 08:29:58 +0100
commit2596de9179c644d294b7418552f0ed255b7653b0 (patch)
tree1f0e19dfd563b7e56f679747900fb05a6420f083
parent118380bc5d01e52b5edc574abb4176f6e70a54a6 (diff)
downloadpoky-2596de9179c644d294b7418552f0ed255b7653b0.tar.gz
glibc: Security Fix for CVE-2016-3706
(From OE-Core rev: 0c82ab38064baaf25169d75ddccaa3926b62c7e3) Signed-off-by: Armin Kuster <akuster@mvista.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--meta/recipes-core/glibc/glibc/CVE-2016-3706.patch226
-rw-r--r--meta/recipes-core/glibc/glibc_2.22.bb1
2 files changed, 227 insertions, 0 deletions
diff --git a/meta/recipes-core/glibc/glibc/CVE-2016-3706.patch b/meta/recipes-core/glibc/glibc/CVE-2016-3706.patch
new file mode 100644
index 0000000000..5d3c5cb7af
--- /dev/null
+++ b/meta/recipes-core/glibc/glibc/CVE-2016-3706.patch
@@ -0,0 +1,226 @@
1From 4ab2ab03d4351914ee53248dc5aef4a8c88ff8b9 Mon Sep 17 00:00:00 2001
2From: Florian Weimer <fweimer@redhat.com>
3Date: Fri, 29 Apr 2016 10:35:34 +0200
4Subject: [PATCH] CVE-2016-3706: getaddrinfo: stack overflow in hostent
5 conversion [BZ #20010]
6
7When converting a struct hostent response to struct gaih_addrtuple, the
8gethosts macro (which is called from gaih_inet) used alloca, without
9malloc fallback for large responses. This commit changes this code to
10use calloc unconditionally.
11
12This commit also consolidated a second hostent-to-gaih_addrtuple
13conversion loop (in gaih_inet) to use the new conversion function.
14
15Upstream-Status: Backport
16CVE: CVE-2016-3706
17Signed-off-by: Armin Kuster <akuster@mvista.com>
18
19---
20 ChangeLog | 10 ++++
21 NEWS | 5 +-
22 sysdeps/posix/getaddrinfo.c | 130 +++++++++++++++++++++++---------------------
23 3 files changed, 83 insertions(+), 62 deletions(-)
24
25Index: git/ChangeLog
26===================================================================
27--- git.orig/ChangeLog
28+++ git/ChangeLog
29@@ -1,3 +1,13 @@
30+2016-04-29 Florian Weimer <fweimer@redhat.com>
31+
32+ [BZ #20010]
33+ CVE-2016-3706
34+ * sysdeps/posix/getaddrinfo.c
35+ (convert_hostent_to_gaih_addrtuple): New function.
36+ (gethosts): Call convert_hostent_to_gaih_addrtuple.
37+ (gaih_inet): Use convert_hostent_to_gaih_addrtuple to convert
38+ AF_INET data.
39+
40 2016-01-27 Paul Eggert <eggert@cs.ucla.edu>
41
42 [BZ #18240]
43Index: git/NEWS
44===================================================================
45--- git.orig/NEWS
46+++ git/NEWS
47@@ -2,6 +2,14 @@ GNU C Library NEWS -- history of user-vi
48 Copyright (C) 1992-2015 Free Software Foundation, Inc.
49 See the end for copying conditions.
50
51+Security related changes:
52+
53+[Add security related changes here]
54+ * Previously, getaddrinfo copied large amounts of address data to the stack,
55+ even after the fix for CVE-2013-4458 has been applied, potentially
56+ resulting in a stack overflow. getaddrinfo now uses a heap allocation
57+ instead. Reported by Michael Petlan. (CVE-2016-3706)
58+
59 Please send GNU C library bug reports via <http://sourceware.org/bugzilla/>
60 using `glibc' in the "product" field.
61
62Index: git/sysdeps/posix/getaddrinfo.c
63===================================================================
64--- git.orig/sysdeps/posix/getaddrinfo.c
65+++ git/sysdeps/posix/getaddrinfo.c
66@@ -168,9 +168,58 @@ gaih_inet_serv (const char *servicename,
67 return 0;
68 }
69
70+/* Convert struct hostent to a list of struct gaih_addrtuple objects.
71+ h_name is not copied, and the struct hostent object must not be
72+ deallocated prematurely. *RESULT must be NULL or a pointer to an
73+ object allocated using malloc, which is freed. */
74+static bool
75+convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
76+ int family,
77+ struct hostent *h,
78+ struct gaih_addrtuple **result)
79+{
80+ free (*result);
81+ *result = NULL;
82+
83+ /* Count the number of addresses in h->h_addr_list. */
84+ size_t count = 0;
85+ for (char **p = h->h_addr_list; *p != NULL; ++p)
86+ ++count;
87+
88+ /* Report no data if no addresses are available, or if the incoming
89+ address size is larger than what we can store. */
90+ if (count == 0 || h->h_length > sizeof (((struct gaih_addrtuple) {}).addr))
91+ return true;
92+
93+ struct gaih_addrtuple *array = calloc (count, sizeof (*array));
94+ if (array == NULL)
95+ return false;
96+
97+ for (size_t i = 0; i < count; ++i)
98+ {
99+ if (family == AF_INET && req->ai_family == AF_INET6)
100+ {
101+ /* Perform address mapping. */
102+ array[i].family = AF_INET6;
103+ memcpy(array[i].addr + 3, h->h_addr_list[i], sizeof (uint32_t));
104+ array[i].addr[2] = htonl (0xffff);
105+ }
106+ else
107+ {
108+ array[i].family = family;
109+ memcpy (array[i].addr, h->h_addr_list[i], h->h_length);
110+ }
111+ array[i].next = array + i + 1;
112+ }
113+ array[0].name = h->h_name;
114+ array[count - 1].next = NULL;
115+
116+ *result = array;
117+ return true;
118+}
119+
120 #define gethosts(_family, _type) \
121 { \
122- int i; \
123 int herrno; \
124 struct hostent th; \
125 struct hostent *h; \
126@@ -219,36 +268,23 @@ gaih_inet_serv (const char *servicename,
127 } \
128 else if (h != NULL) \
129 { \
130- for (i = 0; h->h_addr_list[i]; i++) \
131+ /* Make sure that addrmem can be freed. */ \
132+ if (!malloc_addrmem) \
133+ addrmem = NULL; \
134+ if (!convert_hostent_to_gaih_addrtuple (req, _family,h, &addrmem)) \
135 { \
136- if (*pat == NULL) \
137- { \
138- *pat = __alloca (sizeof (struct gaih_addrtuple)); \
139- (*pat)->scopeid = 0; \
140- } \
141- uint32_t *addr = (*pat)->addr; \
142- (*pat)->next = NULL; \
143- (*pat)->name = i == 0 ? strdupa (h->h_name) : NULL; \
144- if (_family == AF_INET && req->ai_family == AF_INET6) \
145- { \
146- (*pat)->family = AF_INET6; \
147- addr[3] = *(uint32_t *) h->h_addr_list[i]; \
148- addr[2] = htonl (0xffff); \
149- addr[1] = 0; \
150- addr[0] = 0; \
151- } \
152- else \
153- { \
154- (*pat)->family = _family; \
155- memcpy (addr, h->h_addr_list[i], sizeof(_type)); \
156- } \
157- pat = &((*pat)->next); \
158+ _res.options |= old_res_options & RES_USE_INET6; \
159+ result = -EAI_SYSTEM; \
160+ goto free_and_return; \
161 } \
162+ *pat = addrmem; \
163+ /* The conversion uses malloc unconditionally. */ \
164+ malloc_addrmem = true; \
165 \
166 if (localcanon != NULL && canon == NULL) \
167 canon = strdupa (localcanon); \
168 \
169- if (_family == AF_INET6 && i > 0) \
170+ if (_family == AF_INET6 && *pat != NULL) \
171 got_ipv6 = true; \
172 } \
173 }
174@@ -612,44 +648,16 @@ gaih_inet (const char *name, const struc
175 {
176 if (h != NULL)
177 {
178- int i;
179- /* We found data, count the number of addresses. */
180- for (i = 0; h->h_addr_list[i]; ++i)
181- ;
182- if (i > 0 && *pat != NULL)
183- --i;
184-
185- if (__libc_use_alloca (alloca_used
186- + i * sizeof (struct gaih_addrtuple)))
187- addrmem = alloca_account (i * sizeof (struct gaih_addrtuple),
188- alloca_used);
189- else
190+ /* We found data, convert it. */
191+ if (!convert_hostent_to_gaih_addrtuple
192+ (req, AF_INET, h, &addrmem))
193 {
194- addrmem = malloc (i
195- * sizeof (struct gaih_addrtuple));
196- if (addrmem == NULL)
197- {
198- result = -EAI_MEMORY;
199- goto free_and_return;
200- }
201- malloc_addrmem = true;
202- }
203-
204- /* Now convert it into the list. */
205- struct gaih_addrtuple *addrfree = addrmem;
206- for (i = 0; h->h_addr_list[i]; ++i)
207- {
208- if (*pat == NULL)
209- {
210- *pat = addrfree++;
211- (*pat)->scopeid = 0;
212- }
213- (*pat)->next = NULL;
214- (*pat)->family = AF_INET;
215- memcpy ((*pat)->addr, h->h_addr_list[i],
216- h->h_length);
217- pat = &((*pat)->next);
218+ result = -EAI_MEMORY;
219+ goto free_and_return;
220 }
221+ *pat = addrmem;
222+ /* The conversion uses malloc unconditionally. */
223+ malloc_addrmem = true;
224 }
225 }
226 else
diff --git a/meta/recipes-core/glibc/glibc_2.22.bb b/meta/recipes-core/glibc/glibc_2.22.bb
index 7b25847392..4cf2ed7dbf 100644
--- a/meta/recipes-core/glibc/glibc_2.22.bb
+++ b/meta/recipes-core/glibc/glibc_2.22.bb
@@ -48,6 +48,7 @@ SRC_URI = "${GLIBC_GIT_URI};branch=${SRCBRANCH};name=glibc \
48 file://CVE-2015-8776.patch \ 48 file://CVE-2015-8776.patch \
49 file://CVE-2015-7547.patch \ 49 file://CVE-2015-7547.patch \
50 file://CVE-2015-8778.patch \ 50 file://CVE-2015-8778.patch \
51 file://CVE-2016-3706.patch \
51" 52"
52 53
53SRC_URI += "\ 54SRC_URI += "\