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 | |
| 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')
| -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 += "\ |
