Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)

Merge #15447: glibc security updates

(cherry picked from commit 45a14c873b90023e83cd9a97b642f206da1ac432)

+809
+5
pkgs/development/libraries/glibc/common.nix
··· 49 "/bin:/usr/bin", which is inappropriate on NixOS machines. This 50 patch extends the search path by "/run/current-system/sw/bin". */ 51 ./fix_path_attribute_in_getconf.patch 52 ]; 53 54 postPatch =
··· 49 "/bin:/usr/bin", which is inappropriate on NixOS machines. This 50 patch extends the search path by "/run/current-system/sw/bin". */ 51 ./fix_path_attribute_in_getconf.patch 52 + 53 + ./cve-2016-3075.patch 54 + ./glob-simplify-interface.patch 55 + ./cve-2016-1234.patch 56 + ./cve-2016-3706.patch 57 ]; 58 59 postPatch =
+372
pkgs/development/libraries/glibc/cve-2016-1234.patch
···
··· 1 + commit c87db3fcbdf890990b44d956621763538c878cd3 2 + Author: Florian Weimer <fweimer@redhat.com> 3 + Date: Wed May 4 12:09:35 2016 +0200 4 + 5 + CVE-2016-1234: glob: Do not copy d_name field of struct dirent [BZ #19779] 6 + 7 + Instead, we store the data we need from the return value of 8 + readdir in an object of the new type struct readdir_result. 9 + This type is independent of the layout of struct dirent. 10 + 11 + (cherry picked from commit 5171f3079f2cc53e0548fc4967361f4d1ce9d7ea) 12 + 13 + diff --git a/posix/bug-glob2.c b/posix/bug-glob2.c 14 + index 0fdc5d0..5873e08 100644 15 + --- a/posix/bug-glob2.c 16 + +++ b/posix/bug-glob2.c 17 + @@ -40,6 +40,17 @@ 18 + # define PRINTF(fmt, args...) 19 + #endif 20 + 21 + +#define LONG_NAME \ 22 + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ 23 + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ 24 + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ 25 + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ 26 + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ 27 + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ 28 + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ 29 + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ 30 + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ 31 + + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 32 + 33 + static struct 34 + { 35 + @@ -58,6 +69,7 @@ static struct 36 + { ".", 3, DT_DIR, 0755 }, 37 + { "..", 3, DT_DIR, 0755 }, 38 + { "a", 3, DT_REG, 0644 }, 39 + + { LONG_NAME, 3, DT_REG, 0644 }, 40 + { "unreadable", 2, DT_DIR, 0111 }, 41 + { ".", 3, DT_DIR, 0111 }, 42 + { "..", 3, DT_DIR, 0755 }, 43 + @@ -75,7 +87,7 @@ typedef struct 44 + int level; 45 + int idx; 46 + struct dirent d; 47 + - char room_for_dirent[NAME_MAX]; 48 + + char room_for_dirent[sizeof (LONG_NAME)]; 49 + } my_DIR; 50 + 51 + 52 + diff --git a/posix/glob.c b/posix/glob.c 53 + index 9ae76ac..ea4b0b6 100644 54 + --- a/posix/glob.c 55 + +++ b/posix/glob.c 56 + @@ -24,7 +24,9 @@ 57 + #include <errno.h> 58 + #include <sys/types.h> 59 + #include <sys/stat.h> 60 + +#include <stdbool.h> 61 + #include <stddef.h> 62 + +#include <stdint.h> 63 + 64 + /* Outcomment the following line for production quality code. */ 65 + /* #define NDEBUG 1 */ 66 + @@ -73,69 +75,8 @@ 67 + # endif /* HAVE_VMSDIR_H */ 68 + #endif 69 + 70 + - 71 + -/* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available 72 + - if the `d_type' member for `struct dirent' is available. 73 + - HAVE_STRUCT_DIRENT_D_TYPE plays the same role in GNULIB. */ 74 + -#if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE 75 + -/* True if the directory entry D must be of type T. */ 76 + -# define DIRENT_MUST_BE(d, t) ((d)->d_type == (t)) 77 + - 78 + -/* True if the directory entry D might be a symbolic link. */ 79 + -# define DIRENT_MIGHT_BE_SYMLINK(d) \ 80 + - ((d)->d_type == DT_UNKNOWN || (d)->d_type == DT_LNK) 81 + - 82 + -/* True if the directory entry D might be a directory. */ 83 + -# define DIRENT_MIGHT_BE_DIR(d) \ 84 + - ((d)->d_type == DT_DIR || DIRENT_MIGHT_BE_SYMLINK (d)) 85 + - 86 + -#else /* !HAVE_D_TYPE */ 87 + -# define DIRENT_MUST_BE(d, t) false 88 + -# define DIRENT_MIGHT_BE_SYMLINK(d) true 89 + -# define DIRENT_MIGHT_BE_DIR(d) true 90 + -#endif /* HAVE_D_TYPE */ 91 + - 92 + -/* If the system has the `struct dirent64' type we use it internally. */ 93 + -#if defined _LIBC && !defined COMPILE_GLOB64 94 + - 95 + -# if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__ 96 + -# define CONVERT_D_INO(d64, d32) 97 + -# else 98 + -# define CONVERT_D_INO(d64, d32) \ 99 + - (d64)->d_ino = (d32)->d_ino; 100 + -# endif 101 + - 102 + -# ifdef _DIRENT_HAVE_D_TYPE 103 + -# define CONVERT_D_TYPE(d64, d32) \ 104 + - (d64)->d_type = (d32)->d_type; 105 + -# else 106 + -# define CONVERT_D_TYPE(d64, d32) 107 + -# endif 108 + - 109 + -# define CONVERT_DIRENT_DIRENT64(d64, d32) \ 110 + - strcpy ((d64)->d_name, (d32)->d_name); \ 111 + - CONVERT_D_INO (d64, d32) \ 112 + - CONVERT_D_TYPE (d64, d32) 113 + -#endif 114 + - 115 + - 116 + -#if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__ 117 + -/* Posix does not require that the d_ino field be present, and some 118 + - systems do not provide it. */ 119 + -# define REAL_DIR_ENTRY(dp) 1 120 + -#else 121 + -# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0) 122 + -#endif /* POSIX */ 123 + - 124 + #include <stdlib.h> 125 + #include <string.h> 126 + - 127 + -/* NAME_MAX is usually defined in <dirent.h> or <limits.h>. */ 128 + -#include <limits.h> 129 + -#ifndef NAME_MAX 130 + -# define NAME_MAX (sizeof (((struct dirent *) 0)->d_name)) 131 + -#endif 132 + - 133 + #include <alloca.h> 134 + 135 + #ifdef _LIBC 136 + @@ -180,8 +121,111 @@ 137 + 138 + static const char *next_brace_sub (const char *begin, int flags) __THROWNL; 139 + 140 + +/* A representation of a directory entry which does not depend on the 141 + + layout of struct dirent, or the size of ino_t. */ 142 + +struct readdir_result 143 + +{ 144 + + const char *name; 145 + +# if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE 146 + + uint8_t type; 147 + +# endif 148 + + bool skip_entry; 149 + +}; 150 + + 151 + +# if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE 152 + +/* Initializer based on the d_type member of struct dirent. */ 153 + +# define D_TYPE_TO_RESULT(source) (source)->d_type, 154 + + 155 + +/* True if the directory entry D might be a symbolic link. */ 156 + +static bool 157 + +readdir_result_might_be_symlink (struct readdir_result d) 158 + +{ 159 + + return d.type == DT_UNKNOWN || d.type == DT_LNK; 160 + +} 161 + + 162 + +/* True if the directory entry D might be a directory. */ 163 + +static bool 164 + +readdir_result_might_be_dir (struct readdir_result d) 165 + +{ 166 + + return d.type == DT_DIR || readdir_result_might_be_symlink (d); 167 + +} 168 + +# else /* defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE */ 169 + +# define D_TYPE_TO_RESULT(source) 170 + + 171 + +/* If we do not have type information, symbolic links and directories 172 + + are always a possibility. */ 173 + + 174 + +static bool 175 + +readdir_result_might_be_symlink (struct readdir_result d) 176 + +{ 177 + + return true; 178 + +} 179 + + 180 + +static bool 181 + +readdir_result_might_be_dir (struct readdir_result d) 182 + +{ 183 + + return true; 184 + +} 185 + + 186 + +# endif /* defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE */ 187 + + 188 + +# if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__ 189 + +/* Initializer for skip_entry. POSIX does not require that the d_ino 190 + + field be present, and some systems do not provide it. */ 191 + +# define D_INO_TO_RESULT(source) false, 192 + +# else 193 + +# define D_INO_TO_RESULT(source) (source)->d_ino == 0, 194 + +# endif 195 + + 196 + +/* Construct an initializer for a struct readdir_result object from a 197 + + struct dirent *. No copy of the name is made. */ 198 + +#define READDIR_RESULT_INITIALIZER(source) \ 199 + + { \ 200 + + source->d_name, \ 201 + + D_TYPE_TO_RESULT (source) \ 202 + + D_INO_TO_RESULT (source) \ 203 + + } 204 + + 205 + #endif /* !defined _LIBC || !defined GLOB_ONLY_P */ 206 + 207 + +/* Call gl_readdir on STREAM. This macro can be overridden to reduce 208 + + type safety if an old interface version needs to be supported. */ 209 + +#ifndef GL_READDIR 210 + +# define GL_READDIR(pglob, stream) ((pglob)->gl_readdir (stream)) 211 + +#endif 212 + + 213 + +/* Extract name and type from directory entry. No copy of the name is 214 + + made. If SOURCE is NULL, result name is NULL. Keep in sync with 215 + + convert_dirent64 below. */ 216 + +static struct readdir_result 217 + +convert_dirent (const struct dirent *source) 218 + +{ 219 + + if (source == NULL) 220 + + { 221 + + struct readdir_result result = { NULL, }; 222 + + return result; 223 + + } 224 + + struct readdir_result result = READDIR_RESULT_INITIALIZER (source); 225 + + return result; 226 + +} 227 + + 228 + +#ifndef COMPILE_GLOB64 229 + +/* Like convert_dirent, but works on struct dirent64 instead. Keep in 230 + + sync with convert_dirent above. */ 231 + +static struct readdir_result 232 + +convert_dirent64 (const struct dirent64 *source) 233 + +{ 234 + + if (source == NULL) 235 + + { 236 + + struct readdir_result result = { NULL, }; 237 + + return result; 238 + + } 239 + + struct readdir_result result = READDIR_RESULT_INITIALIZER (source); 240 + + return result; 241 + +} 242 + +#endif 243 + + 244 + + 245 + #ifndef attribute_hidden 246 + # define attribute_hidden 247 + #endif 248 + @@ -1538,55 +1582,36 @@ glob_in_dir (const char *pattern, const char *directory, int flags, 249 + 250 + while (1) 251 + { 252 + - const char *name; 253 + -#if defined _LIBC && !defined COMPILE_GLOB64 254 + - struct dirent64 *d; 255 + - union 256 + - { 257 + - struct dirent64 d64; 258 + - char room [offsetof (struct dirent64, d_name[0]) 259 + - + NAME_MAX + 1]; 260 + - } 261 + - d64buf; 262 + - 263 + - if (__glibc_unlikely (flags & GLOB_ALTDIRFUNC)) 264 + - { 265 + - struct dirent *d32 = (*pglob->gl_readdir) (stream); 266 + - if (d32 != NULL) 267 + - { 268 + - CONVERT_DIRENT_DIRENT64 (&d64buf.d64, d32); 269 + - d = &d64buf.d64; 270 + - } 271 + - else 272 + - d = NULL; 273 + - } 274 + - else 275 + - d = __readdir64 (stream); 276 + + struct readdir_result d; 277 + + { 278 + + if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)) 279 + + d = convert_dirent (GL_READDIR (pglob, stream)); 280 + + else 281 + + { 282 + +#ifdef COMPILE_GLOB64 283 + + d = convert_dirent (__readdir (stream)); 284 + #else 285 + - struct dirent *d = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0) 286 + - ? ((struct dirent *) 287 + - (*pglob->gl_readdir) (stream)) 288 + - : __readdir (stream)); 289 + + d = convert_dirent64 (__readdir64 (stream)); 290 + #endif 291 + - if (d == NULL) 292 + + } 293 + + } 294 + + if (d.name == NULL) 295 + break; 296 + - if (! REAL_DIR_ENTRY (d)) 297 + + if (d.skip_entry) 298 + continue; 299 + 300 + /* If we shall match only directories use the information 301 + provided by the dirent call if possible. */ 302 + - if ((flags & GLOB_ONLYDIR) && !DIRENT_MIGHT_BE_DIR (d)) 303 + + if ((flags & GLOB_ONLYDIR) && !readdir_result_might_be_dir (d)) 304 + continue; 305 + 306 + - name = d->d_name; 307 + - 308 + - if (fnmatch (pattern, name, fnm_flags) == 0) 309 + + if (fnmatch (pattern, d.name, fnm_flags) == 0) 310 + { 311 + /* If the file we found is a symlink we have to 312 + make sure the target file exists. */ 313 + - if (!DIRENT_MIGHT_BE_SYMLINK (d) 314 + - || link_exists_p (dfd, directory, dirlen, name, pglob, 315 + - flags)) 316 + + if (!readdir_result_might_be_symlink (d) 317 + + || link_exists_p (dfd, directory, dirlen, d.name, 318 + + pglob, flags)) 319 + { 320 + if (cur == names->count) 321 + { 322 + @@ -1606,7 +1631,7 @@ glob_in_dir (const char *pattern, const char *directory, int flags, 323 + names = newnames; 324 + cur = 0; 325 + } 326 + - names->name[cur] = strdup (d->d_name); 327 + + names->name[cur] = strdup (d.name); 328 + if (names->name[cur] == NULL) 329 + goto memory_error; 330 + ++cur; 331 + diff --git a/sysdeps/unix/sysv/linux/i386/glob64.c b/sysdeps/unix/sysv/linux/i386/glob64.c 332 + index b4fcd1a..802c957 100644 333 + --- a/sysdeps/unix/sysv/linux/i386/glob64.c 334 + +++ b/sysdeps/unix/sysv/linux/i386/glob64.c 335 + @@ -1,3 +1,21 @@ 336 + +/* Two glob variants with 64-bit support, for dirent64 and __olddirent64. 337 + + Copyright (C) 1998-2016 Free Software Foundation, Inc. 338 + + This file is part of the GNU C Library. 339 + + 340 + + The GNU C Library is free software; you can redistribute it and/or 341 + + modify it under the terms of the GNU Lesser General Public 342 + + License as published by the Free Software Foundation; either 343 + + version 2.1 of the License, or (at your option) any later version. 344 + + 345 + + The GNU C Library is distributed in the hope that it will be useful, 346 + + but WITHOUT ANY WARRANTY; without even the implied warranty of 347 + + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 348 + + Lesser General Public License for more details. 349 + + 350 + + You should have received a copy of the GNU Lesser General Public 351 + + License along with the GNU C Library; if not, see 352 + + <http://www.gnu.org/licenses/>. */ 353 + + 354 + #include <dirent.h> 355 + #include <glob.h> 356 + #include <sys/stat.h> 357 + @@ -38,11 +56,15 @@ int __old_glob64 (const char *__pattern, int __flags, 358 + 359 + #undef dirent 360 + #define dirent __old_dirent64 361 + +#undef GL_READDIR 362 + +# define GL_READDIR(pglob, stream) \ 363 + + ((struct __old_dirent64 *) (pglob)->gl_readdir (stream)) 364 + #undef __readdir 365 + #define __readdir(dirp) __old_readdir64 (dirp) 366 + #undef glob 367 + #define glob(pattern, flags, errfunc, pglob) \ 368 + __old_glob64 (pattern, flags, errfunc, pglob) 369 + +#define convert_dirent __old_convert_dirent 370 + #define glob_in_dir __old_glob_in_dir 371 + #define GLOB_ATTRIBUTE attribute_compat_text_section 372 +
+35
pkgs/development/libraries/glibc/cve-2016-3075.patch
···
··· 1 + commit 146b58d11fddbef15b888906e3be4f33900c416f 2 + Author: Florian Weimer <fweimer@redhat.com> 3 + Date: Tue Mar 29 12:57:56 2016 +0200 4 + 5 + CVE-2016-3075: Stack overflow in _nss_dns_getnetbyname_r [BZ #19879] 6 + 7 + The defensive copy is not needed because the name may not alias the 8 + output buffer. 9 + 10 + (cherry picked from commit 317b199b4aff8cfa27f2302ab404d2bb5032b9a4) 11 + (cherry picked from commit 883dceebc8f11921a9890211a4e202e5be17562f) 12 + 13 + diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c 14 + index 2eb2f67..8f301a7 100644 15 + --- a/resolv/nss_dns/dns-network.c 16 + +++ b/resolv/nss_dns/dns-network.c 17 + @@ -118,17 +118,14 @@ _nss_dns_getnetbyname_r (const char *name, struct netent *result, 18 + } net_buffer; 19 + querybuf *orig_net_buffer; 20 + int anslen; 21 + - char *qbuf; 22 + enum nss_status status; 23 + 24 + if (__res_maybe_init (&_res, 0) == -1) 25 + return NSS_STATUS_UNAVAIL; 26 + 27 + - qbuf = strdupa (name); 28 + - 29 + net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024); 30 + 31 + - anslen = __libc_res_nsearch (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf, 32 + + anslen = __libc_res_nsearch (&_res, name, C_IN, T_PTR, net_buffer.buf->buf, 33 + 1024, &net_buffer.ptr, NULL, NULL, NULL, NULL); 34 + if (anslen < 0) 35 + {
+181
pkgs/development/libraries/glibc/cve-2016-3706.patch
···
··· 1 + commit 1a8a7c12950a0026a3c406a7cb1608f96aa1460e 2 + Author: Florian Weimer <fweimer@redhat.com> 3 + Date: Fri Apr 29 10:35:34 2016 +0200 4 + 5 + CVE-2016-3706: getaddrinfo: stack overflow in hostent 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 + (cherry picked from commit 4ab2ab03d4351914ee53248dc5aef4a8c88ff8b9) 16 + 17 + diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c 18 + index 1ef3f20..fed2d3b 100644 19 + --- a/sysdeps/posix/getaddrinfo.c 20 + +++ b/sysdeps/posix/getaddrinfo.c 21 + @@ -168,9 +168,58 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp, 22 + return 0; 23 + } 24 + 25 + +/* Convert struct hostent to a list of struct gaih_addrtuple objects. 26 + + h_name is not copied, and the struct hostent object must not be 27 + + deallocated prematurely. *RESULT must be NULL or a pointer to an 28 + + object allocated using malloc, which is freed. */ 29 + +static bool 30 + +convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, 31 + + int family, 32 + + struct hostent *h, 33 + + struct gaih_addrtuple **result) 34 + +{ 35 + + free (*result); 36 + + *result = NULL; 37 + + 38 + + /* Count the number of addresses in h->h_addr_list. */ 39 + + size_t count = 0; 40 + + for (char **p = h->h_addr_list; *p != NULL; ++p) 41 + + ++count; 42 + + 43 + + /* Report no data if no addresses are available, or if the incoming 44 + + address size is larger than what we can store. */ 45 + + if (count == 0 || h->h_length > sizeof (((struct gaih_addrtuple) {}).addr)) 46 + + return true; 47 + + 48 + + struct gaih_addrtuple *array = calloc (count, sizeof (*array)); 49 + + if (array == NULL) 50 + + return false; 51 + + 52 + + for (size_t i = 0; i < count; ++i) 53 + + { 54 + + if (family == AF_INET && req->ai_family == AF_INET6) 55 + + { 56 + + /* Perform address mapping. */ 57 + + array[i].family = AF_INET6; 58 + + memcpy(array[i].addr + 3, h->h_addr_list[i], sizeof (uint32_t)); 59 + + array[i].addr[2] = htonl (0xffff); 60 + + } 61 + + else 62 + + { 63 + + array[i].family = family; 64 + + memcpy (array[i].addr, h->h_addr_list[i], h->h_length); 65 + + } 66 + + array[i].next = array + i + 1; 67 + + } 68 + + array[0].name = h->h_name; 69 + + array[count - 1].next = NULL; 70 + + 71 + + *result = array; 72 + + return true; 73 + +} 74 + + 75 + #define gethosts(_family, _type) \ 76 + { \ 77 + - int i; \ 78 + int herrno; \ 79 + struct hostent th; \ 80 + struct hostent *h; \ 81 + @@ -219,36 +268,23 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp, 82 + } \ 83 + else if (h != NULL) \ 84 + { \ 85 + - for (i = 0; h->h_addr_list[i]; i++) \ 86 + + /* Make sure that addrmem can be freed. */ \ 87 + + if (!malloc_addrmem) \ 88 + + addrmem = NULL; \ 89 + + if (!convert_hostent_to_gaih_addrtuple (req, _family,h, &addrmem)) \ 90 + { \ 91 + - if (*pat == NULL) \ 92 + - { \ 93 + - *pat = __alloca (sizeof (struct gaih_addrtuple)); \ 94 + - (*pat)->scopeid = 0; \ 95 + - } \ 96 + - uint32_t *addr = (*pat)->addr; \ 97 + - (*pat)->next = NULL; \ 98 + - (*pat)->name = i == 0 ? strdupa (h->h_name) : NULL; \ 99 + - if (_family == AF_INET && req->ai_family == AF_INET6) \ 100 + - { \ 101 + - (*pat)->family = AF_INET6; \ 102 + - addr[3] = *(uint32_t *) h->h_addr_list[i]; \ 103 + - addr[2] = htonl (0xffff); \ 104 + - addr[1] = 0; \ 105 + - addr[0] = 0; \ 106 + - } \ 107 + - else \ 108 + - { \ 109 + - (*pat)->family = _family; \ 110 + - memcpy (addr, h->h_addr_list[i], sizeof(_type)); \ 111 + - } \ 112 + - pat = &((*pat)->next); \ 113 + + _res.options |= old_res_options & RES_USE_INET6; \ 114 + + result = -EAI_SYSTEM; \ 115 + + goto free_and_return; \ 116 + } \ 117 + + *pat = addrmem; \ 118 + + /* The conversion uses malloc unconditionally. */ \ 119 + + malloc_addrmem = true; \ 120 + \ 121 + if (localcanon != NULL && canon == NULL) \ 122 + canon = strdupa (localcanon); \ 123 + \ 124 + - if (_family == AF_INET6 && i > 0) \ 125 + + if (_family == AF_INET6 && *pat != NULL) \ 126 + got_ipv6 = true; \ 127 + } \ 128 + } 129 + @@ -612,44 +648,16 @@ gaih_inet (const char *name, const struct gaih_service *service, 130 + { 131 + if (h != NULL) 132 + { 133 + - int i; 134 + - /* We found data, count the number of addresses. */ 135 + - for (i = 0; h->h_addr_list[i]; ++i) 136 + - ; 137 + - if (i > 0 && *pat != NULL) 138 + - --i; 139 + - 140 + - if (__libc_use_alloca (alloca_used 141 + - + i * sizeof (struct gaih_addrtuple))) 142 + - addrmem = alloca_account (i * sizeof (struct gaih_addrtuple), 143 + - alloca_used); 144 + - else 145 + - { 146 + - addrmem = malloc (i 147 + - * sizeof (struct gaih_addrtuple)); 148 + - if (addrmem == NULL) 149 + - { 150 + - result = -EAI_MEMORY; 151 + - goto free_and_return; 152 + - } 153 + - malloc_addrmem = true; 154 + - } 155 + - 156 + - /* Now convert it into the list. */ 157 + - struct gaih_addrtuple *addrfree = addrmem; 158 + - for (i = 0; h->h_addr_list[i]; ++i) 159 + + /* We found data, convert it. */ 160 + + if (!convert_hostent_to_gaih_addrtuple 161 + + (req, AF_INET, h, &addrmem)) 162 + { 163 + - if (*pat == NULL) 164 + - { 165 + - *pat = addrfree++; 166 + - (*pat)->scopeid = 0; 167 + - } 168 + - (*pat)->next = NULL; 169 + - (*pat)->family = AF_INET; 170 + - memcpy ((*pat)->addr, h->h_addr_list[i], 171 + - h->h_length); 172 + - pat = &((*pat)->next); 173 + + result = -EAI_MEMORY; 174 + + goto free_and_return; 175 + } 176 + + *pat = addrmem; 177 + + /* The conversion uses malloc unconditionally. */ 178 + + malloc_addrmem = true; 179 + } 180 + } 181 + else
+216
pkgs/development/libraries/glibc/glob-simplify-interface.patch
···
··· 1 + commit 68302147ee061c69eb447e243ad9a18ef4cfbc4c 2 + Author: Florian Weimer <fweimer@redhat.com> 3 + Date: Fri Apr 29 09:33:07 2016 +0200 4 + 5 + glob: Simplify the interface for the GLOB_ALTDIRFUNC callback gl_readdir 6 + 7 + Previously, application code had to set up the d_namlen member if 8 + the target supported it, involving conditional compilation. After 9 + this change, glob will use the length of the string in d_name instead 10 + of d_namlen to determine the file name length. All glibc targets 11 + provide the d_type and d_ino members, and setting them as needed for 12 + gl_readdir is straightforward. 13 + 14 + Changing the behavior with regards to d_ino is left to a future 15 + cleanup. 16 + 17 + (cherry picked from commit 137fe72eca6923a00381a3ca9f0e7672c1f85e3f) 18 + 19 + diff --git a/manual/examples/mkdirent.c b/manual/examples/mkdirent.c 20 + new file mode 100644 21 + index 0000000..f8400f4 22 + --- /dev/null 23 + +++ b/manual/examples/mkdirent.c 24 + @@ -0,0 +1,42 @@ 25 + +/* Example for creating a struct dirent object for use with glob. 26 + + Copyright (C) 2016 Free Software Foundation, Inc. 27 + + 28 + + This program is free software; you can redistribute it and/or 29 + + modify it under the terms of the GNU General Public License 30 + + as published by the Free Software Foundation; either version 2 31 + + of the License, or (at your option) any later version. 32 + + 33 + + This program is distributed in the hope that it will be useful, 34 + + but WITHOUT ANY WARRANTY; without even the implied warranty of 35 + + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 36 + + GNU General Public License for more details. 37 + + 38 + + You should have received a copy of the GNU General Public License 39 + + along with this program; if not, if not, see <http://www.gnu.org/licenses/>. 40 + +*/ 41 + + 42 + +#include <dirent.h> 43 + +#include <errno.h> 44 + +#include <stddef.h> 45 + +#include <stdlib.h> 46 + +#include <string.h> 47 + + 48 + +struct dirent * 49 + +mkdirent (const char *name) 50 + +{ 51 + + size_t dirent_size = offsetof (struct dirent, d_name) + 1; 52 + + size_t name_length = strlen (name); 53 + + size_t total_size = dirent_size + name_length; 54 + + if (total_size < dirent_size) 55 + + { 56 + + errno = ENOMEM; 57 + + return NULL; 58 + + } 59 + + struct dirent *result = malloc (total_size); 60 + + if (result == NULL) 61 + + return NULL; 62 + + result->d_type = DT_UNKNOWN; 63 + + result->d_ino = 1; /* Do not skip this entry. */ 64 + + memcpy (result->d_name, name, name_length + 1); 65 + + return result; 66 + +} 67 + diff --git a/manual/pattern.texi b/manual/pattern.texi 68 + index d1b9275..565e7eb 100644 69 + --- a/manual/pattern.texi 70 + +++ b/manual/pattern.texi 71 + @@ -237,7 +237,44 @@ function used to read the contents of a directory. It is used if the 72 + @code{GLOB_ALTDIRFUNC} bit is set in the flag parameter. The type of 73 + this field is @w{@code{struct dirent *(*) (void *)}}. 74 + 75 + -This is a GNU extension. 76 + +An implementation of @code{gl_readdir} needs to initialize the following 77 + +members of the @code{struct dirent} object: 78 + + 79 + +@table @code 80 + +@item d_type 81 + +This member should be set to the file type of the entry if it is known. 82 + +Otherwise, the value @code{DT_UNKNOWN} can be used. The @code{glob} 83 + +function may use the specified file type to avoid callbacks in cases 84 + +where the file type indicates that the data is not required. 85 + + 86 + +@item d_ino 87 + +This member needs to be non-zero, otherwise @code{glob} may skip the 88 + +current entry and call the @code{gl_readdir} callback function again to 89 + +retrieve another entry. 90 + + 91 + +@item d_name 92 + +This member must be set to the name of the entry. It must be 93 + +null-terminated. 94 + +@end table 95 + + 96 + +The example below shows how to allocate a @code{struct dirent} object 97 + +containing a given name. 98 + + 99 + +@smallexample 100 + +@include mkdirent.c.texi 101 + +@end smallexample 102 + + 103 + +The @code{glob} function reads the @code{struct dirent} members listed 104 + +above and makes a copy of the file name in the @code{d_name} member 105 + +immediately after the @code{gl_readdir} callback function returns. 106 + +Future invocations of any of the callback functions may dealloacte or 107 + +reuse the buffer. It is the responsibility of the caller of the 108 + +@code{glob} function to allocate and deallocate the buffer, around the 109 + +call to @code{glob} or using the callback functions. For example, an 110 + +application could allocate the buffer in the @code{gl_readdir} callback 111 + +function, and deallocate it in the @code{gl_closedir} callback function. 112 + + 113 + +The @code{gl_readdir} member is a GNU extension. 114 + 115 + @item gl_opendir 116 + The address of an alternative implementation of the @code{opendir} 117 + diff --git a/posix/bug-glob2.c b/posix/bug-glob2.c 118 + index ddf5ec9..0fdc5d0 100644 119 + --- a/posix/bug-glob2.c 120 + +++ b/posix/bug-glob2.c 121 + @@ -193,7 +193,7 @@ my_readdir (void *gdir) 122 + return NULL; 123 + } 124 + 125 + - dir->d.d_ino = dir->idx; 126 + + dir->d.d_ino = 1; /* glob should not skip this entry. */ 127 + 128 + #ifdef _DIRENT_HAVE_D_TYPE 129 + dir->d.d_type = filesystem[dir->idx].type; 130 + diff --git a/posix/glob.c b/posix/glob.c 131 + index 0c04c3c..9ae76ac 100644 132 + --- a/posix/glob.c 133 + +++ b/posix/glob.c 134 + @@ -57,10 +57,8 @@ 135 + 136 + #if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__ 137 + # include <dirent.h> 138 + -# define NAMLEN(dirent) strlen((dirent)->d_name) 139 + #else 140 + # define dirent direct 141 + -# define NAMLEN(dirent) (dirent)->d_namlen 142 + # ifdef HAVE_SYS_NDIR_H 143 + # include <sys/ndir.h> 144 + # endif 145 + @@ -76,12 +74,6 @@ 146 + #endif 147 + 148 + 149 + -/* In GNU systems, <dirent.h> defines this macro for us. */ 150 + -#ifdef _D_NAMLEN 151 + -# undef NAMLEN 152 + -# define NAMLEN(d) _D_NAMLEN(d) 153 + -#endif 154 + - 155 + /* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available 156 + if the `d_type' member for `struct dirent' is available. 157 + HAVE_STRUCT_DIRENT_D_TYPE plays the same role in GNULIB. */ 158 + @@ -105,12 +97,6 @@ 159 + 160 + /* If the system has the `struct dirent64' type we use it internally. */ 161 + #if defined _LIBC && !defined COMPILE_GLOB64 162 + -# if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__ 163 + -# define CONVERT_D_NAMLEN(d64, d32) 164 + -# else 165 + -# define CONVERT_D_NAMLEN(d64, d32) \ 166 + - (d64)->d_namlen = (d32)->d_namlen; 167 + -# endif 168 + 169 + # if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__ 170 + # define CONVERT_D_INO(d64, d32) 171 + @@ -127,8 +113,7 @@ 172 + # endif 173 + 174 + # define CONVERT_DIRENT_DIRENT64(d64, d32) \ 175 + - memcpy ((d64)->d_name, (d32)->d_name, NAMLEN (d32) + 1); \ 176 + - CONVERT_D_NAMLEN (d64, d32) \ 177 + + strcpy ((d64)->d_name, (d32)->d_name); \ 178 + CONVERT_D_INO (d64, d32) \ 179 + CONVERT_D_TYPE (d64, d32) 180 + #endif 181 + @@ -1554,7 +1539,6 @@ glob_in_dir (const char *pattern, const char *directory, int flags, 182 + while (1) 183 + { 184 + const char *name; 185 + - size_t len; 186 + #if defined _LIBC && !defined COMPILE_GLOB64 187 + struct dirent64 *d; 188 + union 189 + @@ -1622,12 +1606,10 @@ glob_in_dir (const char *pattern, const char *directory, int flags, 190 + names = newnames; 191 + cur = 0; 192 + } 193 + - len = NAMLEN (d); 194 + - names->name[cur] = (char *) malloc (len + 1); 195 + + names->name[cur] = strdup (d->d_name); 196 + if (names->name[cur] == NULL) 197 + goto memory_error; 198 + - *((char *) mempcpy (names->name[cur++], name, len)) 199 + - = '\0'; 200 + + ++cur; 201 + ++nfound; 202 + } 203 + } 204 + diff --git a/posix/tst-gnuglob.c b/posix/tst-gnuglob.c 205 + index 992b997..b7b859b 100644 206 + --- a/posix/tst-gnuglob.c 207 + +++ b/posix/tst-gnuglob.c 208 + @@ -211,7 +211,7 @@ my_readdir (void *gdir) 209 + return NULL; 210 + } 211 + 212 + - dir->d.d_ino = dir->idx; 213 + + dir->d.d_ino = 1; /* glob should not skip this entry. */ 214 + 215 + #ifdef _DIRENT_HAVE_D_TYPE 216 + dir->d.d_type = filesystem[dir->idx].type;