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