wok-4.x annotate glibc/stuff/patches/glibc-2.22-CVE-2016-3706.patch @ rev 12476

Up glibc (2.22) with CVE patchs
author Stanislas Leduc <shann@slitaz.org>
date Wed Mar 15 11:41:38 2023 +0000 (15 months ago)
parents
children
rev   line source
shann@12476 1 From 4ab2ab03d4351914ee53248dc5aef4a8c88ff8b9 Mon Sep 17 00:00:00 2001
shann@12476 2 From: Florian Weimer <fweimer@redhat.com>
shann@12476 3 Date: Fri, 29 Apr 2016 10:35:34 +0200
shann@12476 4 Subject: [PATCH] CVE-2016-3706: getaddrinfo: stack overflow in hostent
shann@12476 5 conversion [BZ #20010]
shann@12476 6
shann@12476 7 When converting a struct hostent response to struct gaih_addrtuple, the
shann@12476 8 gethosts macro (which is called from gaih_inet) used alloca, without
shann@12476 9 malloc fallback for large responses. This commit changes this code to
shann@12476 10 use calloc unconditionally.
shann@12476 11
shann@12476 12 This commit also consolidated a second hostent-to-gaih_addrtuple
shann@12476 13 conversion loop (in gaih_inet) to use the new conversion function.
shann@12476 14
shann@12476 15 diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
shann@12476 16 index 1ef3f20..fed2d3b 100644
shann@12476 17 --- a/sysdeps/posix/getaddrinfo.c
shann@12476 18 +++ b/sysdeps/posix/getaddrinfo.c
shann@12476 19 @@ -168,9 +168,58 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
shann@12476 20 return 0;
shann@12476 21 }
shann@12476 22
shann@12476 23 +/* Convert struct hostent to a list of struct gaih_addrtuple objects.
shann@12476 24 + h_name is not copied, and the struct hostent object must not be
shann@12476 25 + deallocated prematurely. *RESULT must be NULL or a pointer to an
shann@12476 26 + object allocated using malloc, which is freed. */
shann@12476 27 +static bool
shann@12476 28 +convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
shann@12476 29 + int family,
shann@12476 30 + struct hostent *h,
shann@12476 31 + struct gaih_addrtuple **result)
shann@12476 32 +{
shann@12476 33 + free (*result);
shann@12476 34 + *result = NULL;
shann@12476 35 +
shann@12476 36 + /* Count the number of addresses in h->h_addr_list. */
shann@12476 37 + size_t count = 0;
shann@12476 38 + for (char **p = h->h_addr_list; *p != NULL; ++p)
shann@12476 39 + ++count;
shann@12476 40 +
shann@12476 41 + /* Report no data if no addresses are available, or if the incoming
shann@12476 42 + address size is larger than what we can store. */
shann@12476 43 + if (count == 0 || h->h_length > sizeof (((struct gaih_addrtuple) {}).addr))
shann@12476 44 + return true;
shann@12476 45 +
shann@12476 46 + struct gaih_addrtuple *array = calloc (count, sizeof (*array));
shann@12476 47 + if (array == NULL)
shann@12476 48 + return false;
shann@12476 49 +
shann@12476 50 + for (size_t i = 0; i < count; ++i)
shann@12476 51 + {
shann@12476 52 + if (family == AF_INET && req->ai_family == AF_INET6)
shann@12476 53 + {
shann@12476 54 + /* Perform address mapping. */
shann@12476 55 + array[i].family = AF_INET6;
shann@12476 56 + memcpy(array[i].addr + 3, h->h_addr_list[i], sizeof (uint32_t));
shann@12476 57 + array[i].addr[2] = htonl (0xffff);
shann@12476 58 + }
shann@12476 59 + else
shann@12476 60 + {
shann@12476 61 + array[i].family = family;
shann@12476 62 + memcpy (array[i].addr, h->h_addr_list[i], h->h_length);
shann@12476 63 + }
shann@12476 64 + array[i].next = array + i + 1;
shann@12476 65 + }
shann@12476 66 + array[0].name = h->h_name;
shann@12476 67 + array[count - 1].next = NULL;
shann@12476 68 +
shann@12476 69 + *result = array;
shann@12476 70 + return true;
shann@12476 71 +}
shann@12476 72 +
shann@12476 73 #define gethosts(_family, _type) \
shann@12476 74 { \
shann@12476 75 - int i; \
shann@12476 76 int herrno; \
shann@12476 77 struct hostent th; \
shann@12476 78 struct hostent *h; \
shann@12476 79 @@ -219,36 +268,23 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
shann@12476 80 } \
shann@12476 81 else if (h != NULL) \
shann@12476 82 { \
shann@12476 83 - for (i = 0; h->h_addr_list[i]; i++) \
shann@12476 84 + /* Make sure that addrmem can be freed. */ \
shann@12476 85 + if (!malloc_addrmem) \
shann@12476 86 + addrmem = NULL; \
shann@12476 87 + if (!convert_hostent_to_gaih_addrtuple (req, _family,h, &addrmem)) \
shann@12476 88 { \
shann@12476 89 - if (*pat == NULL) \
shann@12476 90 - { \
shann@12476 91 - *pat = __alloca (sizeof (struct gaih_addrtuple)); \
shann@12476 92 - (*pat)->scopeid = 0; \
shann@12476 93 - } \
shann@12476 94 - uint32_t *addr = (*pat)->addr; \
shann@12476 95 - (*pat)->next = NULL; \
shann@12476 96 - (*pat)->name = i == 0 ? strdupa (h->h_name) : NULL; \
shann@12476 97 - if (_family == AF_INET && req->ai_family == AF_INET6) \
shann@12476 98 - { \
shann@12476 99 - (*pat)->family = AF_INET6; \
shann@12476 100 - addr[3] = *(uint32_t *) h->h_addr_list[i]; \
shann@12476 101 - addr[2] = htonl (0xffff); \
shann@12476 102 - addr[1] = 0; \
shann@12476 103 - addr[0] = 0; \
shann@12476 104 - } \
shann@12476 105 - else \
shann@12476 106 - { \
shann@12476 107 - (*pat)->family = _family; \
shann@12476 108 - memcpy (addr, h->h_addr_list[i], sizeof(_type)); \
shann@12476 109 - } \
shann@12476 110 - pat = &((*pat)->next); \
shann@12476 111 + _res.options |= old_res_options & RES_USE_INET6; \
shann@12476 112 + result = -EAI_SYSTEM; \
shann@12476 113 + goto free_and_return; \
shann@12476 114 } \
shann@12476 115 + *pat = addrmem; \
shann@12476 116 + /* The conversion uses malloc unconditionally. */ \
shann@12476 117 + malloc_addrmem = true; \
shann@12476 118 \
shann@12476 119 if (localcanon != NULL && canon == NULL) \
shann@12476 120 canon = strdupa (localcanon); \
shann@12476 121 \
shann@12476 122 - if (_family == AF_INET6 && i > 0) \
shann@12476 123 + if (_family == AF_INET6 && *pat != NULL) \
shann@12476 124 got_ipv6 = true; \
shann@12476 125 } \
shann@12476 126 }
shann@12476 127 @@ -612,44 +648,16 @@ gaih_inet (const char *name, const struct gaih_service *service,
shann@12476 128 {
shann@12476 129 if (h != NULL)
shann@12476 130 {
shann@12476 131 - int i;
shann@12476 132 - /* We found data, count the number of addresses. */
shann@12476 133 - for (i = 0; h->h_addr_list[i]; ++i)
shann@12476 134 - ;
shann@12476 135 - if (i > 0 && *pat != NULL)
shann@12476 136 - --i;
shann@12476 137 -
shann@12476 138 - if (__libc_use_alloca (alloca_used
shann@12476 139 - + i * sizeof (struct gaih_addrtuple)))
shann@12476 140 - addrmem = alloca_account (i * sizeof (struct gaih_addrtuple),
shann@12476 141 - alloca_used);
shann@12476 142 - else
shann@12476 143 - {
shann@12476 144 - addrmem = malloc (i
shann@12476 145 - * sizeof (struct gaih_addrtuple));
shann@12476 146 - if (addrmem == NULL)
shann@12476 147 - {
shann@12476 148 - result = -EAI_MEMORY;
shann@12476 149 - goto free_and_return;
shann@12476 150 - }
shann@12476 151 - malloc_addrmem = true;
shann@12476 152 - }
shann@12476 153 -
shann@12476 154 - /* Now convert it into the list. */
shann@12476 155 - struct gaih_addrtuple *addrfree = addrmem;
shann@12476 156 - for (i = 0; h->h_addr_list[i]; ++i)
shann@12476 157 + /* We found data, convert it. */
shann@12476 158 + if (!convert_hostent_to_gaih_addrtuple
shann@12476 159 + (req, AF_INET, h, &addrmem))
shann@12476 160 {
shann@12476 161 - if (*pat == NULL)
shann@12476 162 - {
shann@12476 163 - *pat = addrfree++;
shann@12476 164 - (*pat)->scopeid = 0;
shann@12476 165 - }
shann@12476 166 - (*pat)->next = NULL;
shann@12476 167 - (*pat)->family = AF_INET;
shann@12476 168 - memcpy ((*pat)->addr, h->h_addr_list[i],
shann@12476 169 - h->h_length);
shann@12476 170 - pat = &((*pat)->next);
shann@12476 171 + result = -EAI_MEMORY;
shann@12476 172 + goto free_and_return;
shann@12476 173 }
shann@12476 174 + *pat = addrmem;
shann@12476 175 + /* The conversion uses malloc unconditionally. */
shann@12476 176 + malloc_addrmem = true;
shann@12476 177 }
shann@12476 178 }
shann@12476 179 else
shann@12476 180 --
shann@12476 181 2.9.3
shann@12476 182