diff options
author | Armin Kuster <akuster@mvista.com> | 2016-07-09 11:55:29 -0700 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2016-07-27 08:29:58 +0100 |
commit | 2596de9179c644d294b7418552f0ed255b7653b0 (patch) | |
tree | 1f0e19dfd563b7e56f679747900fb05a6420f083 /meta/recipes-core | |
parent | 118380bc5d01e52b5edc574abb4176f6e70a54a6 (diff) | |
download | poky-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>
Diffstat (limited to 'meta/recipes-core')
-rw-r--r-- | meta/recipes-core/glibc/glibc/CVE-2016-3706.patch | 226 | ||||
-rw-r--r-- | meta/recipes-core/glibc/glibc_2.22.bb | 1 |
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 @@ | |||
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 | Signed-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 | |||
25 | Index: 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] | ||
43 | Index: 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 | |||
62 | Index: 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 | ||
53 | SRC_URI += "\ | 54 | SRC_URI += "\ |