From 1147c6c02b22987390c01f9d8a56d61c2f3727d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Buchm=C3=BCller?= Date: Wed, 17 Feb 2016 11:42:30 +0100 Subject: [PATCH] glibc: add patches from LFS (upstream patches) The upstream patch addresses CVE-2015-7547 --- srcpkgs/glibc/patches/glibc-2.22-fhs-1.patch | 72 + .../patches/glibc-2.22-largefile-1.patch | 67 + .../patches/glibc-2.22-upstream_fixes-1.patch | 1434 +++++++++++++++++ .../glibc-2.22-upstream_i386_fix-1.patch | 55 + srcpkgs/glibc/template | 2 +- 5 files changed, 1629 insertions(+), 1 deletion(-) create mode 100644 srcpkgs/glibc/patches/glibc-2.22-fhs-1.patch create mode 100644 srcpkgs/glibc/patches/glibc-2.22-largefile-1.patch create mode 100644 srcpkgs/glibc/patches/glibc-2.22-upstream_fixes-1.patch create mode 100644 srcpkgs/glibc/patches/glibc-2.22-upstream_i386_fix-1.patch diff --git a/srcpkgs/glibc/patches/glibc-2.22-fhs-1.patch b/srcpkgs/glibc/patches/glibc-2.22-fhs-1.patch new file mode 100644 index 0000000000..bbee2fcd57 --- /dev/null +++ b/srcpkgs/glibc/patches/glibc-2.22-fhs-1.patch @@ -0,0 +1,72 @@ +Submitted By: Armin K. +Date: 2013-02-11 +Initial Package Version: 2.17 +Upstream Status: Not Applicable +Origin: Self +Description: This patch removes references to /var/db directory which is not part + of FHS and replaces them with more suitable directories in /var + hierarchy - /var/cache/nscd for nscd and /var/lib/nss_db for nss_db. + +--- Makeconfig 2012-12-25 04:02:13.000000000 +0100 ++++ Makeconfig 2013-02-11 01:32:32.500667439 +0100 +@@ -250,7 +250,7 @@ + + # Directory for the database files and Makefile for nss_db. + ifndef vardbdir +-vardbdir = $(localstatedir)/db ++vardbdir = $(localstatedir)/lib/nss_db + endif + inst_vardbdir = $(install_root)$(vardbdir) + +--- nscd/nscd.h 2012-12-25 04:02:13.000000000 +0100 ++++ nscd/nscd.h 2013-02-11 01:32:32.500667439 +0100 +@@ -112,11 +112,11 @@ + + + /* Paths of the file for the persistent storage. */ +-#define _PATH_NSCD_PASSWD_DB "/var/db/nscd/passwd" +-#define _PATH_NSCD_GROUP_DB "/var/db/nscd/group" +-#define _PATH_NSCD_HOSTS_DB "/var/db/nscd/hosts" +-#define _PATH_NSCD_SERVICES_DB "/var/db/nscd/services" +-#define _PATH_NSCD_NETGROUP_DB "/var/db/nscd/netgroup" ++#define _PATH_NSCD_PASSWD_DB "/var/cache/nscd/passwd" ++#define _PATH_NSCD_GROUP_DB "/var/cache/nscd/group" ++#define _PATH_NSCD_HOSTS_DB "/var/cache/nscd/hosts" ++#define _PATH_NSCD_SERVICES_DB "/var/cache/nscd/services" ++#define _PATH_NSCD_NETGROUP_DB "/var/cache/nscd/netgroup" + + /* Path used when not using persistent storage. */ + #define _PATH_NSCD_XYZ_DB_TMP "/var/run/nscd/dbXXXXXX" +--- nss/db-Makefile 2012-12-25 04:02:13.000000000 +0100 ++++ nss/db-Makefile 2013-02-11 01:32:32.500667439 +0100 +@@ -22,7 +22,7 @@ + /etc/rpc /etc/services /etc/shadow /etc/gshadow \ + /etc/netgroup) + +-VAR_DB = /var/db ++VAR_DB = /var/lib/nss_db + + AWK = awk + MAKEDB = makedb --quiet +--- sysdeps/generic/paths.h 2012-12-25 04:02:13.000000000 +0100 ++++ sysdeps/generic/paths.h 2013-02-11 01:32:32.500667439 +0100 +@@ -68,7 +68,7 @@ + /* Provide trailing slash, since mostly used for building pathnames. */ + #define _PATH_DEV "/dev/" + #define _PATH_TMP "/tmp/" +-#define _PATH_VARDB "/var/db/" ++#define _PATH_VARDB "/var/lib/nss_db/" + #define _PATH_VARRUN "/var/run/" + #define _PATH_VARTMP "/var/tmp/" + +--- sysdeps/unix/sysv/linux/paths.h 2012-12-25 04:02:13.000000000 +0100 ++++ sysdeps/unix/sysv/linux/paths.h 2013-02-11 01:32:32.504000831 +0100 +@@ -68,7 +68,7 @@ + /* Provide trailing slash, since mostly used for building pathnames. */ + #define _PATH_DEV "/dev/" + #define _PATH_TMP "/tmp/" +-#define _PATH_VARDB "/var/db/" ++#define _PATH_VARDB "/var/lib/nss_db/" + #define _PATH_VARRUN "/var/run/" + #define _PATH_VARTMP "/var/tmp/" + diff --git a/srcpkgs/glibc/patches/glibc-2.22-largefile-1.patch b/srcpkgs/glibc/patches/glibc-2.22-largefile-1.patch new file mode 100644 index 0000000000..eed6f44e30 --- /dev/null +++ b/srcpkgs/glibc/patches/glibc-2.22-largefile-1.patch @@ -0,0 +1,67 @@ +Submitted By: Bruce Dubbs +Date: 2015-11-06 +Initial Package Version: 2.22 +Upstream Status: Committted +Origin: Upstream Git +Description: This patch fixes a problem when an application accesses + files greater than 2 GB. + +X-Git-Url: https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blobdiff_plain;f=io%2Ftest-lfs.c;h=b6ebae403c850bc0db852121af930d6f6ebab86d;hp=539c2a2b14c3f7876a03e87678d4bc32ec9993d0;hb=561a9f11a974a447acb3dd03550a05df701a900e;hpb=19742d3d5f8fb0cdc95b20c32fbee503d1048286 + +diff --git a/io/test-lfs.c b/io/test-lfs.c +index 539c2a2..b6ebae4 100644 +--- io/test-lfs.c ++++ io/test-lfs.c +@@ -144,7 +144,7 @@ test_ftello (void) + int + do_test (int argc, char *argv[]) + { +- int ret; ++ int ret, fd2; + struct stat64 statbuf; + + ret = lseek64 (fd, TWO_GB+100, SEEK_SET); +@@ -195,6 +195,25 @@ do_test (int argc, char *argv[]) + error (EXIT_FAILURE, 0, "stat reported size %lld instead of %lld.", + (long long int) statbuf.st_size, (TWO_GB + 100 + 5)); + ++ fd2 = openat64 (AT_FDCWD, name, O_RDWR); ++ if (fd2 == -1) ++ { ++ if (errno == ENOSYS) ++ { ++ /* Silently ignore this test. */ ++ error (0, 0, "openat64 is not supported"); ++ } ++ else ++ error (EXIT_FAILURE, errno, "openat64 failed to open big file"); ++ } ++ else ++ { ++ ret = close (fd2); ++ ++ if (ret == -1) ++ error (EXIT_FAILURE, errno, "error closing file"); ++ } ++ + test_ftello (); + + return 0; +X-Git-Url: https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blobdiff_plain;f=sysdeps%2Funix%2Fsysv%2Flinux%2Fopenat.c;h=ad8e31d6cfc6d30104894a0c6df0ed37b205bb66;hp=677712330e8a01fc39c873b11a07224e5e73ee14;hb=561a9f11a974a447acb3dd03550a05df701a900e;hpb=19742d3d5f8fb0cdc95b20c32fbee503d1048286 + +diff --git a/sysdeps/unix/sysv/linux/openat.c b/sysdeps/unix/sysv/linux/openat.c +index 6777123..ad8e31d 100644 +--- sysdeps/unix/sysv/linux/openat.c ++++ sysdeps/unix/sysv/linux/openat.c +@@ -68,6 +68,11 @@ __OPENAT (int fd, const char *file, int oflag, ...) + va_end (arg); + } + ++ /* We have to add the O_LARGEFILE flag for openat64. */ ++#ifdef MORE_OFLAGS ++ oflag |= MORE_OFLAGS; ++#endif ++ + return SYSCALL_CANCEL (openat, fd, file, oflag, mode); + } + libc_hidden_def (__OPENAT) diff --git a/srcpkgs/glibc/patches/glibc-2.22-upstream_fixes-1.patch b/srcpkgs/glibc/patches/glibc-2.22-upstream_fixes-1.patch new file mode 100644 index 0000000000..6b87a90f4c --- /dev/null +++ b/srcpkgs/glibc/patches/glibc-2.22-upstream_fixes-1.patch @@ -0,0 +1,1434 @@ +Submitted By: Armin K. +Date: 2016-02-16 +Initial Package Version: 2.22 +Upstream Status: Committed +Origin: Upstream +Description: Various fixes identified upstream + +--- catgets/catgets.c 2015-08-05 08:42:21.000000000 +0200 ++++ catgets/catgets.c 2016-02-16 18:13:26.984538556 +0100 +@@ -16,7 +16,6 @@ + License along with the GNU C Library; if not, see + . */ + +-#include + #include + #include + #include +@@ -35,6 +34,7 @@ + __nl_catd result; + const char *env_var = NULL; + const char *nlspath = NULL; ++ char *tmp = NULL; + + if (strchr (cat_name, '/') == NULL) + { +@@ -54,7 +54,10 @@ + { + /* Append the system dependent directory. */ + size_t len = strlen (nlspath) + 1 + sizeof NLSPATH; +- char *tmp = alloca (len); ++ tmp = malloc (len); ++ ++ if (__glibc_unlikely (tmp == NULL)) ++ return (nl_catd) -1; + + __stpcpy (__stpcpy (__stpcpy (tmp, nlspath), ":"), NLSPATH); + nlspath = tmp; +@@ -65,16 +68,18 @@ + + result = (__nl_catd) malloc (sizeof (*result)); + if (result == NULL) +- /* We cannot get enough memory. */ +- return (nl_catd) -1; +- +- if (__open_catalog (cat_name, nlspath, env_var, result) != 0) ++ { ++ /* We cannot get enough memory. */ ++ result = (nl_catd) -1; ++ } ++ else if (__open_catalog (cat_name, nlspath, env_var, result) != 0) + { + /* Couldn't open the file. */ + free ((void *) result); +- return (nl_catd) -1; ++ result = (nl_catd) -1; + } + ++ free (tmp); + return (nl_catd) result; + } + +--- catgets/open_catalog.c 2015-08-05 08:42:21.000000000 +0200 ++++ catgets/open_catalog.c 2016-02-16 18:13:26.985538577 +0100 +@@ -47,6 +47,7 @@ + size_t tab_size; + const char *lastp; + int result = -1; ++ char *buf = NULL; + + if (strchr (cat_name, '/') != NULL || nlspath == NULL) + fd = open_not_cancel_2 (cat_name, O_RDONLY); +@@ -57,23 +58,23 @@ + if (__glibc_unlikely (bufact + (n) >= bufmax)) \ + { \ + char *old_buf = buf; \ +- bufmax += 256 + (n); \ +- buf = (char *) alloca (bufmax); \ +- memcpy (buf, old_buf, bufact); \ ++ bufmax += (bufmax < 256 + (n)) ? 256 + (n) : bufmax; \ ++ buf = realloc (buf, bufmax); \ ++ if (__glibc_unlikely (buf == NULL)) \ ++ { \ ++ free (old_buf); \ ++ return -1; \ ++ } \ + } + + /* The RUN_NLSPATH variable contains a colon separated list of + descriptions where we expect to find catalogs. We have to + recognize certain % substitutions and stop when we found the + first existing file. */ +- char *buf; + size_t bufact; +- size_t bufmax; ++ size_t bufmax = 0; + size_t len; + +- buf = NULL; +- bufmax = 0; +- + fd = -1; + while (*run_nlspath != '\0') + { +@@ -188,7 +189,10 @@ + + /* Avoid dealing with directories and block devices */ + if (__builtin_expect (fd, 0) < 0) +- return -1; ++ { ++ free (buf); ++ return -1; ++ } + + if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &st), 0) < 0) + goto close_unlock_return; +@@ -325,6 +329,7 @@ + /* Release the lock again. */ + close_unlock_return: + close_not_cancel_no_status (fd); ++ free (buf); + + return result; + } +--- elf/dl-close.c 2015-08-05 08:42:21.000000000 +0200 ++++ elf/dl-close.c 2016-02-16 18:13:26.985538577 +0100 +@@ -144,6 +144,14 @@ + char done[nloaded]; + struct link_map *maps[nloaded]; + ++ /* Clear DF_1_NODELETE to force object deletion. We don't need to touch ++ l_tls_dtor_count because forced object deletion only happens when an ++ error occurs during object load. Destructor registration for TLS ++ non-POD objects should not have happened till then for this ++ object. */ ++ if (force) ++ map->l_flags_1 &= ~DF_1_NODELETE; ++ + /* Run over the list and assign indexes to the link maps and enter + them into the MAPS array. */ + int idx = 0; +@@ -153,13 +161,6 @@ + maps[idx] = l; + ++idx; + +- /* Clear DF_1_NODELETE to force object deletion. We don't need to touch +- l_tls_dtor_count because forced object deletion only happens when an +- error occurs during object load. Destructor registration for TLS +- non-POD objects should not have happened till then for this +- object. */ +- if (force) +- l->l_flags_1 &= ~DF_1_NODELETE; + } + assert (idx == nloaded); + +--- elf/dl-load.c 2015-08-05 08:42:21.000000000 +0200 ++++ elf/dl-load.c 2016-02-16 18:13:26.985538577 +0100 +@@ -42,6 +42,7 @@ + #include + #include + #include ++#include + + + #include +@@ -1471,9 +1472,13 @@ + ignore only ELF files for other architectures. Non-ELF files and + ELF files with different header information cause fatal errors since + this could mean there is something wrong in the installation and the +- user might want to know about this. */ ++ user might want to know about this. ++ ++ If FD is not -1, then the file is already open and FD refers to it. ++ In that case, FD is consumed for both successful and error returns. */ + static int +-open_verify (const char *name, struct filebuf *fbp, struct link_map *loader, ++open_verify (const char *name, int fd, ++ struct filebuf *fbp, struct link_map *loader, + int whatcode, int mode, bool *found_other_class, bool free_name) + { + /* This is the expected ELF header. */ +@@ -1514,6 +1519,7 @@ + if (__glibc_unlikely (GLRO(dl_naudit) > 0) && whatcode != 0 + && loader->l_auditing == 0) + { ++ const char *original_name = name; + struct audit_ifaces *afct = GLRO(dl_audit); + for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) + { +@@ -1528,11 +1534,21 @@ + + afct = afct->next; + } ++ ++ if (fd != -1 && name != original_name && strcmp (name, original_name)) ++ { ++ /* An audit library changed what we're supposed to open, ++ so FD no longer matches it. */ ++ __close (fd); ++ fd = -1; ++ } + } + #endif + +- /* Open the file. We always open files read-only. */ +- int fd = __open (name, O_RDONLY | O_CLOEXEC); ++ if (fd == -1) ++ /* Open the file. We always open files read-only. */ ++ fd = __open (name, O_RDONLY | O_CLOEXEC); ++ + if (fd != -1) + { + ElfW(Ehdr) *ehdr; +@@ -1801,7 +1817,7 @@ + if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS)) + _dl_debug_printf (" trying file=%s\n", buf); + +- fd = open_verify (buf, fbp, loader, whatcode, mode, ++ fd = open_verify (buf, -1, fbp, loader, whatcode, mode, + found_other_class, false); + if (this_dir->status[cnt] == unknown) + { +@@ -2041,6 +2057,20 @@ + &loader->l_runpath_dirs, &realname, &fb, loader, + LA_SER_RUNPATH, &found_other_class); + ++ if (fd == -1) ++ { ++ realname = _dl_sysdep_open_object (name, namelen, &fd); ++ if (realname != NULL) ++ { ++ fd = open_verify (realname, fd, ++ &fb, loader ?: GL(dl_ns)[nsid]._ns_loaded, ++ LA_SER_CONFIG, mode, &found_other_class, ++ false); ++ if (fd == -1) ++ free (realname); ++ } ++ } ++ + #ifdef USE_LDCONFIG + if (fd == -1 + && (__glibc_likely ((mode & __RTLD_SECURE) == 0) +@@ -2086,7 +2116,7 @@ + + if (cached != NULL) + { +- fd = open_verify (cached, ++ fd = open_verify (cached, -1, + &fb, loader ?: GL(dl_ns)[nsid]._ns_loaded, + LA_SER_CONFIG, mode, &found_other_class, + false); +@@ -2121,7 +2151,7 @@ + fd = -1; + else + { +- fd = open_verify (realname, &fb, ++ fd = open_verify (realname, -1, &fb, + loader ?: GL(dl_ns)[nsid]._ns_loaded, 0, mode, + &found_other_class, true); + if (__glibc_unlikely (fd == -1)) +--- elf/dl-lookup.c 2015-08-05 08:42:21.000000000 +0200 ++++ elf/dl-lookup.c 2016-02-16 18:13:26.985538577 +0100 +@@ -1016,6 +1016,18 @@ + #ifdef SHARED + if (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK) + { ++/* ELF_RTYPE_CLASS_XXX must match RTYPE_CLASS_XXX used by prelink with ++ LD_TRACE_PRELINKING. */ ++#define RTYPE_CLASS_VALID 8 ++#define RTYPE_CLASS_PLT (8|1) ++#define RTYPE_CLASS_COPY (8|2) ++#define RTYPE_CLASS_TLS (8|4) ++#if ELF_RTYPE_CLASS_PLT != 0 && ELF_RTYPE_CLASS_PLT != 1 ++# error ELF_RTYPE_CLASS_PLT must be 0 or 1! ++#endif ++#if ELF_RTYPE_CLASS_COPY != 0 && ELF_RTYPE_CLASS_COPY != 2 ++# error ELF_RTYPE_CLASS_COPY must be 0 or 2! ++#endif + int conflict = 0; + struct sym_val val = { NULL, NULL }; + +@@ -1071,12 +1083,17 @@ + + if (value->s) + { ++ /* Keep only ELF_RTYPE_CLASS_PLT and ELF_RTYPE_CLASS_COPY ++ bits since since prelink only uses them. */ ++ type_class &= ELF_RTYPE_CLASS_PLT | ELF_RTYPE_CLASS_COPY; + if (__glibc_unlikely (ELFW(ST_TYPE) (value->s->st_info) + == STT_TLS)) +- type_class = 4; ++ /* Clear the RTYPE_CLASS_VALID bit in RTYPE_CLASS_TLS. */ ++ type_class = RTYPE_CLASS_TLS & ~RTYPE_CLASS_VALID; + else if (__glibc_unlikely (ELFW(ST_TYPE) (value->s->st_info) + == STT_GNU_IFUNC)) +- type_class |= 8; ++ /* Set the RTYPE_CLASS_VALID bit. */ ++ type_class |= RTYPE_CLASS_VALID; + } + + if (conflict +--- elf/dl-sysdep-open.h 1970-01-01 01:00:00.000000000 +0100 ++++ elf/dl-sysdep-open.h 2016-02-16 18:13:26.986538597 +0100 +@@ -0,0 +1,45 @@ ++/* System-specific call to open a shared object by name. Stub version. ++ Copyright (C) 2015 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifndef _DL_SYSDEP_OPEN_H ++#define _DL_SYSDEP_OPEN_H 1 ++ ++#include ++#include ++ ++/* NAME is a name without slashes, as it appears in a DT_NEEDED entry ++ or a dlopen call's argument or suchlike. NAMELEN is (strlen (NAME) + 1). ++ ++ Find NAME in an OS-dependent fashion, and return its "real" name. ++ Optionally fill in *FD with a file descriptor open on that file (or ++ else leave its initial value of -1). The return value is a new ++ malloc'd string, which will be free'd by the caller. If NAME is ++ resolved to an actual file that can be opened, then the return ++ value should name that file (and if *FD was not set, then a normal ++ __open call on that string will be made). If *FD was set by some ++ other means than a normal open and there is no "real" name to use, ++ then __strdup (NAME) is fine (modulo error checking). */ ++ ++static inline char * ++_dl_sysdep_open_object (const char *name, size_t namelen, int *fd) ++{ ++ assert (*fd == -1); ++ return NULL; ++} ++ ++#endif /* dl-sysdep-open.h */ +--- elf/rtld.c 2015-08-05 08:42:21.000000000 +0200 ++++ elf/rtld.c 2016-02-16 18:13:26.986538597 +0100 +@@ -162,7 +162,6 @@ + ._dl_hwcap_mask = HWCAP_IMPORTANT, + ._dl_lazy = 1, + ._dl_fpu_control = _FPU_DEFAULT, +- ._dl_pointer_guard = 1, + ._dl_pagesize = EXEC_PAGESIZE, + ._dl_inhibit_cache = 0, + +@@ -709,15 +708,12 @@ + #endif + + /* Set up the pointer guard as well, if necessary. */ +- if (GLRO(dl_pointer_guard)) +- { +- uintptr_t pointer_chk_guard = _dl_setup_pointer_guard (_dl_random, +- stack_chk_guard); ++ uintptr_t pointer_chk_guard ++ = _dl_setup_pointer_guard (_dl_random, stack_chk_guard); + #ifdef THREAD_SET_POINTER_GUARD +- THREAD_SET_POINTER_GUARD (pointer_chk_guard); ++ THREAD_SET_POINTER_GUARD (pointer_chk_guard); + #endif +- __pointer_chk_guard_local = pointer_chk_guard; +- } ++ __pointer_chk_guard_local = pointer_chk_guard; + + /* We do not need the _dl_random value anymore. The less + information we leave behind, the better, so clear the +@@ -2471,9 +2467,6 @@ + GLRO(dl_use_load_bias) = envline[14] == '1' ? -1 : 0; + break; + } +- +- if (memcmp (envline, "POINTER_GUARD", 13) == 0) +- GLRO(dl_pointer_guard) = envline[14] != '0'; + break; + + case 14: +--- locale/categories.def 2015-08-05 08:42:21.000000000 +0200 ++++ locale/categories.def 2016-02-16 18:13:26.986538597 +0100 +@@ -58,7 +58,6 @@ + DEFINE_ELEMENT (_NL_COLLATE_COLLSEQMB, "collate-collseqmb", std, wstring) + DEFINE_ELEMENT (_NL_COLLATE_COLLSEQWC, "collate-collseqwc", std, wstring) + DEFINE_ELEMENT (_NL_COLLATE_CODESET, "collate-codeset", std, string) +- DEFINE_ELEMENT (_NL_COLLATE_ENCODING_TYPE, "collate-encoding-type", std, word) + ), NO_POSTLOAD) + + +--- locale/C-collate.c 2015-08-05 08:42:21.000000000 +0200 ++++ locale/C-collate.c 2016-02-16 18:13:26.986538597 +0100 +@@ -144,8 +144,6 @@ + /* _NL_COLLATE_COLLSEQWC */ + { .string = (const char *) collseqwc }, + /* _NL_COLLATE_CODESET */ +- { .string = _nl_C_codeset }, +- /* _NL_COLLATE_ENCODING_TYPE */ +- { .word = __cet_8bit } ++ { .string = _nl_C_codeset } + } + }; +--- locale/langinfo.h 2015-08-05 08:42:21.000000000 +0200 ++++ locale/langinfo.h 2016-02-16 18:13:26.986538597 +0100 +@@ -255,7 +255,6 @@ + _NL_COLLATE_COLLSEQMB, + _NL_COLLATE_COLLSEQWC, + _NL_COLLATE_CODESET, +- _NL_COLLATE_ENCODING_TYPE, + _NL_NUM_LC_COLLATE, + + /* LC_CTYPE category: character classification. +--- locale/loadlocale.c 2015-08-05 08:42:21.000000000 +0200 ++++ locale/loadlocale.c 2016-02-16 18:13:26.987538617 +0100 +@@ -121,9 +121,10 @@ + switch (category) + { + #define CATTEST(cat) \ +- case LC_##cat: \ +- assert (cnt < (sizeof (_nl_value_type_LC_##cat) \ +- / sizeof (_nl_value_type_LC_##cat[0]))); \ ++ case LC_##cat: \ ++ if (cnt >= (sizeof (_nl_value_type_LC_##cat) \ ++ / sizeof (_nl_value_type_LC_##cat[0]))) \ ++ goto puntdata; \ + break + CATTEST (NUMERIC); + CATTEST (TIME); +--- locale/localeinfo.h 2015-08-05 08:42:21.000000000 +0200 ++++ locale/localeinfo.h 2016-02-16 18:13:26.987538617 +0100 +@@ -110,14 +110,6 @@ + sort_mask + }; + +-/* Collation encoding type. */ +-enum collation_encoding_type +-{ +- __cet_other, +- __cet_8bit, +- __cet_utf8 +-}; +- + /* We can map the types of the entries into a few categories. */ + enum value_type + { +--- locale/programs/ld-collate.c 2015-08-05 08:42:21.000000000 +0200 ++++ locale/programs/ld-collate.c 2016-02-16 18:13:26.987538617 +0100 +@@ -32,7 +32,6 @@ + #include "linereader.h" + #include "locfile.h" + #include "elem-hash.h" +-#include "../localeinfo.h" + + /* Uncomment the following line in the production version. */ + /* #define NDEBUG 1 */ +@@ -2131,8 +2130,6 @@ + /* The words have to be handled specially. */ + if (idx == _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_SIZEMB)) + add_locale_uint32 (&file, 0); +- else if (idx == _NL_ITEM_INDEX (_NL_COLLATE_ENCODING_TYPE)) +- add_locale_uint32 (&file, __cet_other); + else + add_locale_empty (&file); + } +@@ -2496,12 +2493,6 @@ + add_locale_raw_data (&file, collate->mbseqorder, 256); + add_locale_collseq_table (&file, &collate->wcseqorder); + add_locale_string (&file, charmap->code_set_name); +- if (strcmp (charmap->code_set_name, "UTF-8") == 0) +- add_locale_uint32 (&file, __cet_utf8); +- else if (charmap->mb_cur_max == 1) +- add_locale_uint32 (&file, __cet_8bit); +- else +- add_locale_uint32 (&file, __cet_other); + write_locale_data (output_path, LC_COLLATE, "LC_COLLATE", &file); + + obstack_free (&weightpool, NULL); +--- math/Makefile 2015-08-05 08:42:21.000000000 +0200 ++++ math/Makefile 2016-02-16 18:13:26.988538638 +0100 +@@ -98,7 +98,7 @@ + (echo '/* GNU ld script'; echo '*/';\ + cat $<; \ + echo 'GROUP ( $(slibdir)/libm.so$(libm.so-version) ' \ +- 'AS_NEEDED ( $(slibdir)/libmvec.so$(libmvec.so-version) ) )' \ ++ 'AS_NEEDED ( $(libdir)/libmvec_nonshared.a $(slibdir)/libmvec.so$(libmvec.so-version) ) )' \ + ) > $@ + endif + +--- misc/hsearch_r.c 2015-08-05 08:42:21.000000000 +0200 ++++ misc/hsearch_r.c 2016-02-16 18:13:26.988538638 +0100 +@@ -19,7 +19,7 @@ + #include + #include + #include +- ++#include + #include + + /* [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986 +@@ -46,15 +46,12 @@ + isprime (unsigned int number) + { + /* no even number will be passed */ +- unsigned int div = 3; +- +- while (div * div < number && number % div != 0) +- div += 2; +- +- return number % div != 0; ++ for (unsigned int div = 3; div <= number / div; div += 2) ++ if (number % div == 0) ++ return 0; ++ return 1; + } + +- + /* Before using the hash table we must allocate memory for it. + Test for an existing table are done. We allocate one element + more as the found prime number says. This is done for more effective +@@ -81,10 +78,19 @@ + use will not work. */ + if (nel < 3) + nel = 3; +- /* Change nel to the first prime number not smaller as nel. */ +- nel |= 1; /* make odd */ +- while (!isprime (nel)) +- nel += 2; ++ ++ /* Change nel to the first prime number in the range [nel, UINT_MAX - 2], ++ The '- 2' means 'nel += 2' cannot overflow. */ ++ for (nel |= 1; ; nel += 2) ++ { ++ if (UINT_MAX - 2 < nel) ++ { ++ __set_errno (ENOMEM); ++ return 0; ++ } ++ if (isprime (nel)) ++ break; ++ } + + htab->size = nel; + htab->filled = 0; +--- misc/mntent_r.c 2015-08-05 08:42:21.000000000 +0200 ++++ misc/mntent_r.c 2016-02-16 18:13:26.988538638 +0100 +@@ -136,7 +136,9 @@ + end_ptr = strchr (buffer, '\n'); + if (end_ptr != NULL) /* chop newline */ + { +- while (end_ptr[-1] == ' ' || end_ptr[-1] == '\t') ++ /* Do not walk past the start of buffer if it's all whitespace. */ ++ while (end_ptr != buffer ++ && (end_ptr[-1] == ' ' || end_ptr[-1] == '\t')) + end_ptr--; + *end_ptr = '\0'; + } +--- misc/regexp.h 2015-08-05 08:42:21.000000000 +0200 ++++ misc/regexp.h 2016-02-16 18:13:26.988538638 +0100 +@@ -19,10 +19,11 @@ + #ifndef _REGEXP_H + #define _REGEXP_H 1 + +-/* The contents of this header file were standardized in the +- Single Unix Specification, Version 2 (1997) but marked as +- LEGACY; new applications were already being encouraged to +- use instead. POSIX.1-2001 removed this header. ++/* The contents of this header file were originally standardized in ++ the Single Unix Specification, Issue 3 (1992). In Issue 4 (1994) ++ the header was marked as TO BE WITHDRAWN, and new applications ++ were encouraged to use instead. It was officially ++ withdrawn from the standard in Issue 6 (aka POSIX.1-2001). + + This header is provided only for backward compatibility. + It will be removed in the next release of the GNU C Library. +--- misc/sys/param.h 2015-08-05 08:42:21.000000000 +0200 ++++ misc/sys/param.h 2016-02-16 18:13:26.988538638 +0100 +@@ -50,6 +50,9 @@ + #if !defined NOFILE && defined OPEN_MAX + # define NOFILE OPEN_MAX + #endif ++#if !defined MAXHOSTNAMELEN && defined HOST_NAME_MAX ++# define MAXHOSTNAMELEN HOST_NAME_MAX ++#endif + #ifndef NCARGS + # ifdef ARG_MAX + # define NCARGS ARG_MAX +--- resolv/nss_dns/dns-host.c 2015-08-05 08:42:21.000000000 +0200 ++++ resolv/nss_dns/dns-host.c 2016-02-16 18:13:26.989538658 +0100 +@@ -1031,7 +1031,10 @@ + int h_namelen = 0; + + if (ancount == 0) +- return NSS_STATUS_NOTFOUND; ++ { ++ *h_errnop = HOST_NOT_FOUND; ++ return NSS_STATUS_NOTFOUND; ++ } + + while (ancount-- > 0 && cp < end_of_message && had_error == 0) + { +@@ -1208,7 +1211,14 @@ + /* Special case here: if the resolver sent a result but it only + contains a CNAME while we are looking for a T_A or T_AAAA record, + we fail with NOTFOUND instead of TRYAGAIN. */ +- return canon == NULL ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND; ++ if (canon != NULL) ++ { ++ *h_errnop = HOST_NOT_FOUND; ++ return NSS_STATUS_NOTFOUND; ++ } ++ ++ *h_errnop = NETDB_INTERNAL; ++ return NSS_STATUS_TRYAGAIN; + } + + +@@ -1222,11 +1232,101 @@ + + enum nss_status status = NSS_STATUS_NOTFOUND; + ++ /* Combining the NSS status of two distinct queries requires some ++ compromise and attention to symmetry (A or AAAA queries can be ++ returned in any order). What follows is a breakdown of how this ++ code is expected to work and why. We discuss only SUCCESS, ++ TRYAGAIN, NOTFOUND and UNAVAIL, since they are the only returns ++ that apply (though RETURN and MERGE exist). We make a distinction ++ between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable). ++ A recoverable TRYAGAIN is almost always due to buffer size issues ++ and returns ERANGE in errno and the caller is expected to retry ++ with a larger buffer. ++ ++ Lastly, you may be tempted to make significant changes to the ++ conditions in this code to bring about symmetry between responses. ++ Please don't change anything without due consideration for ++ expected application behaviour. Some of the synthesized responses ++ aren't very well thought out and sometimes appear to imply that ++ IPv4 responses are always answer 1, and IPv6 responses are always ++ answer 2, but that's not true (see the implemetnation of send_dg ++ and send_vc to see response can arrive in any order, particlarly ++ for UDP). However, we expect it holds roughly enough of the time ++ that this code works, but certainly needs to be fixed to make this ++ a more robust implementation. ++ ++ ---------------------------------------------- ++ | Answer 1 Status / | Synthesized | Reason | ++ | Answer 2 Status | Status | | ++ |--------------------------------------------| ++ | SUCCESS/SUCCESS | SUCCESS | [1] | ++ | SUCCESS/TRYAGAIN | TRYAGAIN | [5] | ++ | SUCCESS/TRYAGAIN' | SUCCESS | [1] | ++ | SUCCESS/NOTFOUND | SUCCESS | [1] | ++ | SUCCESS/UNAVAIL | SUCCESS | [1] | ++ | TRYAGAIN/SUCCESS | TRYAGAIN | [2] | ++ | TRYAGAIN/TRYAGAIN | TRYAGAIN | [2] | ++ | TRYAGAIN/TRYAGAIN' | TRYAGAIN | [2] | ++ | TRYAGAIN/NOTFOUND | TRYAGAIN | [2] | ++ | TRYAGAIN/UNAVAIL | TRYAGAIN | [2] | ++ | TRYAGAIN'/SUCCESS | SUCCESS | [3] | ++ | TRYAGAIN'/TRYAGAIN | TRYAGAIN | [3] | ++ | TRYAGAIN'/TRYAGAIN' | TRYAGAIN' | [3] | ++ | TRYAGAIN'/NOTFOUND | TRYAGAIN' | [3] | ++ | TRYAGAIN'/UNAVAIL | UNAVAIL | [3] | ++ | NOTFOUND/SUCCESS | SUCCESS | [3] | ++ | NOTFOUND/TRYAGAIN | TRYAGAIN | [3] | ++ | NOTFOUND/TRYAGAIN' | TRYAGAIN' | [3] | ++ | NOTFOUND/NOTFOUND | NOTFOUND | [3] | ++ | NOTFOUND/UNAVAIL | UNAVAIL | [3] | ++ | UNAVAIL/SUCCESS | UNAVAIL | [4] | ++ | UNAVAIL/TRYAGAIN | UNAVAIL | [4] | ++ | UNAVAIL/TRYAGAIN' | UNAVAIL | [4] | ++ | UNAVAIL/NOTFOUND | UNAVAIL | [4] | ++ | UNAVAIL/UNAVAIL | UNAVAIL | [4] | ++ ---------------------------------------------- ++ ++ [1] If the first response is a success we return success. ++ This ignores the state of the second answer and in fact ++ incorrectly sets errno and h_errno to that of the second ++ answer. However because the response is a success we ignore ++ *errnop and *h_errnop (though that means you touched errno on ++ success). We are being conservative here and returning the ++ likely IPv4 response in the first answer as a success. ++ ++ [2] If the first response is a recoverable TRYAGAIN we return ++ that instead of looking at the second response. The ++ expectation here is that we have failed to get an IPv4 response ++ and should retry both queries. ++ ++ [3] If the first response was not a SUCCESS and the second ++ response is not NOTFOUND (had a SUCCESS, need to TRYAGAIN, ++ or failed entirely e.g. TRYAGAIN' and UNAVAIL) then use the ++ result from the second response, otherwise the first responses ++ status is used. Again we have some odd side-effects when the ++ second response is NOTFOUND because we overwrite *errnop and ++ *h_errnop that means that a first answer of NOTFOUND might see ++ its *errnop and *h_errnop values altered. Whether it matters ++ in practice that a first response NOTFOUND has the wrong ++ *errnop and *h_errnop is undecided. ++ ++ [4] If the first response is UNAVAIL we return that instead of ++ looking at the second response. The expectation here is that ++ it will have failed similarly e.g. configuration failure. ++ ++ [5] Testing this code is complicated by the fact that truncated ++ second response buffers might be returned as SUCCESS if the ++ first answer is a SUCCESS. To fix this we add symmetry to ++ TRYAGAIN with the second response. If the second response ++ is a recoverable error we now return TRYAGIN even if the first ++ response was SUCCESS. */ ++ + if (anslen1 > 0) + status = gaih_getanswer_slice(answer1, anslen1, qname, + &pat, &buffer, &buflen, + errnop, h_errnop, ttlp, + &first); ++ + if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND + || (status == NSS_STATUS_TRYAGAIN + /* We want to look at the second answer in case of an +@@ -1242,8 +1342,15 @@ + &pat, &buffer, &buflen, + errnop, h_errnop, ttlp, + &first); ++ /* Use the second response status in some cases. */ + if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND) + status = status2; ++ /* Do not return a truncated second response (unless it was ++ unavoidable e.g. unrecoverable TRYAGAIN). */ ++ if (status == NSS_STATUS_SUCCESS ++ && (status2 == NSS_STATUS_TRYAGAIN ++ && *errnop == ERANGE && *h_errnop != NO_RECOVERY)) ++ status = NSS_STATUS_TRYAGAIN; + } + + return status; +--- resolv/res_query.c 2015-08-05 08:42:21.000000000 +0200 ++++ resolv/res_query.c 2016-02-16 18:13:26.989538658 +0100 +@@ -396,6 +396,7 @@ + { + free (*answerp2); + *answerp2 = NULL; ++ *nanswerp2 = 0; + *answerp2_malloced = 0; + } + } +@@ -447,6 +448,7 @@ + { + free (*answerp2); + *answerp2 = NULL; ++ *nanswerp2 = 0; + *answerp2_malloced = 0; + } + +@@ -521,6 +523,7 @@ + { + free (*answerp2); + *answerp2 = NULL; ++ *nanswerp2 = 0; + *answerp2_malloced = 0; + } + if (saved_herrno != -1) +--- resolv/res_send.c 2015-08-05 08:42:21.000000000 +0200 ++++ resolv/res_send.c 2016-02-16 18:13:26.990538679 +0100 +@@ -1,3 +1,20 @@ ++/* Copyright (C) 2016 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ + /* + * Copyright (c) 1985, 1989, 1993 + * The Regents of the University of California. All rights reserved. +@@ -363,6 +380,8 @@ + #ifdef USE_HOOKS + if (__glibc_unlikely (statp->qhook || statp->rhook)) { + if (anssiz < MAXPACKET && ansp) { ++ /* Always allocate MAXPACKET, callers expect ++ this specific size. */ + u_char *buf = malloc (MAXPACKET); + if (buf == NULL) + return (-1); +@@ -638,6 +657,77 @@ + return (struct sockaddr *) (void *) &statp->nsaddr_list[n]; + } + ++/* The send_vc function is responsible for sending a DNS query over TCP ++ to the nameserver numbered NS from the res_state STATP i.e. ++ EXT(statp).nssocks[ns]. The function supports sending both IPv4 and ++ IPv6 queries at the same serially on the same socket. ++ ++ Please note that for TCP there is no way to disable sending both ++ queries, unlike UDP, which honours RES_SNGLKUP and RES_SNGLKUPREOP ++ and sends the queries serially and waits for the result after each ++ sent query. This implemetnation should be corrected to honour these ++ options. ++ ++ Please also note that for TCP we send both queries over the same ++ socket one after another. This technically violates best practice ++ since the server is allowed to read the first query, respond, and ++ then close the socket (to service another client). If the server ++ does this, then the remaining second query in the socket data buffer ++ will cause the server to send the client an RST which will arrive ++ asynchronously and the client's OS will likely tear down the socket ++ receive buffer resulting in a potentially short read and lost ++ response data. This will force the client to retry the query again, ++ and this process may repeat until all servers and connection resets ++ are exhausted and then the query will fail. It's not known if this ++ happens with any frequency in real DNS server implementations. This ++ implementation should be corrected to use two sockets by default for ++ parallel queries. ++ ++ The query stored in BUF of BUFLEN length is sent first followed by ++ the query stored in BUF2 of BUFLEN2 length. Queries are sent ++ serially on the same socket. ++ ++ Answers to the query are stored firstly in *ANSP up to a max of ++ *ANSSIZP bytes. If more than *ANSSIZP bytes are needed and ANSCP ++ is non-NULL (to indicate that modifying the answer buffer is allowed) ++ then malloc is used to allocate a new response buffer and ANSCP and ++ ANSP will both point to the new buffer. If more than *ANSSIZP bytes ++ are needed but ANSCP is NULL, then as much of the response as ++ possible is read into the buffer, but the results will be truncated. ++ When truncation happens because of a small answer buffer the DNS ++ packets header feild TC will bet set to 1, indicating a truncated ++ message and the rest of the socket data will be read and discarded. ++ ++ Answers to the query are stored secondly in *ANSP2 up to a max of ++ *ANSSIZP2 bytes, with the actual response length stored in ++ *RESPLEN2. If more than *ANSSIZP bytes are needed and ANSP2 ++ is non-NULL (required for a second query) then malloc is used to ++ allocate a new response buffer, *ANSSIZP2 is set to the new buffer ++ size and *ANSP2_MALLOCED is set to 1. ++ ++ The ANSP2_MALLOCED argument will eventually be removed as the ++ change in buffer pointer can be used to detect the buffer has ++ changed and that the caller should use free on the new buffer. ++ ++ Note that the answers may arrive in any order from the server and ++ therefore the first and second answer buffers may not correspond to ++ the first and second queries. ++ ++ It is not supported to call this function with a non-NULL ANSP2 ++ but a NULL ANSCP. Put another way, you can call send_vc with a ++ single unmodifiable buffer or two modifiable buffers, but no other ++ combination is supported. ++ ++ It is the caller's responsibility to free the malloc allocated ++ buffers by detecting that the pointers have changed from their ++ original values i.e. *ANSCP or *ANSP2 has changed. ++ ++ If errors are encountered then *TERRNO is set to an appropriate ++ errno value and a zero result is returned for a recoverable error, ++ and a less-than zero result is returned for a non-recoverable error. ++ ++ If no errors are encountered then *TERRNO is left unmodified and ++ a the length of the first response in bytes is returned. */ + static int + send_vc(res_state statp, + const u_char *buf, int buflen, const u_char *buf2, int buflen2, +@@ -647,11 +737,7 @@ + { + const HEADER *hp = (HEADER *) buf; + const HEADER *hp2 = (HEADER *) buf2; +- u_char *ans = *ansp; +- int orig_anssizp = *anssizp; +- // XXX REMOVE +- // int anssiz = *anssizp; +- HEADER *anhp = (HEADER *) ans; ++ HEADER *anhp = (HEADER *) *ansp; + struct sockaddr *nsap = get_nsaddr (statp, ns); + int truncating, connreset, n; + /* On some architectures compiler might emit a warning indicating +@@ -743,6 +829,8 @@ + * Receive length & response + */ + int recvresp1 = 0; ++ /* Skip the second response if there is no second query. ++ To do that we mark the second response as received. */ + int recvresp2 = buf2 == NULL; + uint16_t rlen16; + read_len: +@@ -779,40 +867,14 @@ + u_char **thisansp; + int *thisresplenp; + if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) { ++ /* We have not received any responses ++ yet or we only have one response to ++ receive. */ + thisanssizp = anssizp; + thisansp = anscp ?: ansp; + assert (anscp != NULL || ansp2 == NULL); + thisresplenp = &resplen; + } else { +- if (*anssizp != MAXPACKET) { +- /* No buffer allocated for the first +- reply. We can try to use the rest +- of the user-provided buffer. */ +-#if __GNUC_PREREQ (4, 7) +- DIAG_PUSH_NEEDS_COMMENT; +- DIAG_IGNORE_NEEDS_COMMENT (5, "-Wmaybe-uninitialized"); +-#endif +-#if _STRING_ARCH_unaligned +- *anssizp2 = orig_anssizp - resplen; +- *ansp2 = *ansp + resplen; +-#else +- int aligned_resplen +- = ((resplen + __alignof__ (HEADER) - 1) +- & ~(__alignof__ (HEADER) - 1)); +- *anssizp2 = orig_anssizp - aligned_resplen; +- *ansp2 = *ansp + aligned_resplen; +-#endif +-#if __GNUC_PREREQ (4, 7) +- DIAG_POP_NEEDS_COMMENT; +-#endif +- } else { +- /* The first reply did not fit into the +- user-provided buffer. Maybe the second +- answer will. */ +- *anssizp2 = orig_anssizp; +- *ansp2 = *ansp; +- } +- + thisanssizp = anssizp2; + thisansp = ansp2; + thisresplenp = resplen2; +@@ -820,10 +882,14 @@ + anhp = (HEADER *) *thisansp; + + *thisresplenp = rlen; +- if (rlen > *thisanssizp) { +- /* Yes, we test ANSCP here. If we have two buffers +- both will be allocatable. */ +- if (__glibc_likely (anscp != NULL)) { ++ /* Is the answer buffer too small? */ ++ if (*thisanssizp < rlen) { ++ /* If the current buffer is non-NULL and it's not ++ pointing at the static user-supplied buffer then ++ we can reallocate it. */ ++ if (thisansp != NULL && thisansp != ansp) { ++ /* Always allocate MAXPACKET, callers expect ++ this specific size. */ + u_char *newp = malloc (MAXPACKET); + if (newp == NULL) { + *terrno = ENOMEM; +@@ -835,6 +901,9 @@ + if (thisansp == ansp2) + *ansp2_malloced = 1; + anhp = (HEADER *) newp; ++ /* A uint16_t can't be larger than MAXPACKET ++ thus it's safe to allocate MAXPACKET but ++ read RLEN bytes instead. */ + len = rlen; + } else { + Dprint(statp->options & RES_DEBUG, +@@ -997,6 +1066,66 @@ + return 1; + } + ++/* The send_dg function is responsible for sending a DNS query over UDP ++ to the nameserver numbered NS from the res_state STATP i.e. ++ EXT(statp).nssocks[ns]. The function supports IPv4 and IPv6 queries ++ along with the ability to send the query in parallel for both stacks ++ (default) or serially (RES_SINGLKUP). It also supports serial lookup ++ with a close and reopen of the socket used to talk to the server ++ (RES_SNGLKUPREOP) to work around broken name servers. ++ ++ The query stored in BUF of BUFLEN length is sent first followed by ++ the query stored in BUF2 of BUFLEN2 length. Queries are sent ++ in parallel (default) or serially (RES_SINGLKUP or RES_SNGLKUPREOP). ++ ++ Answers to the query are stored firstly in *ANSP up to a max of ++ *ANSSIZP bytes. If more than *ANSSIZP bytes are needed and ANSCP ++ is non-NULL (to indicate that modifying the answer buffer is allowed) ++ then malloc is used to allocate a new response buffer and ANSCP and ++ ANSP will both point to the new buffer. If more than *ANSSIZP bytes ++ are needed but ANSCP is NULL, then as much of the response as ++ possible is read into the buffer, but the results will be truncated. ++ When truncation happens because of a small answer buffer the DNS ++ packets header feild TC will bet set to 1, indicating a truncated ++ message, while the rest of the UDP packet is discarded. ++ ++ Answers to the query are stored secondly in *ANSP2 up to a max of ++ *ANSSIZP2 bytes, with the actual response length stored in ++ *RESPLEN2. If more than *ANSSIZP bytes are needed and ANSP2 ++ is non-NULL (required for a second query) then malloc is used to ++ allocate a new response buffer, *ANSSIZP2 is set to the new buffer ++ size and *ANSP2_MALLOCED is set to 1. ++ ++ The ANSP2_MALLOCED argument will eventually be removed as the ++ change in buffer pointer can be used to detect the buffer has ++ changed and that the caller should use free on the new buffer. ++ ++ Note that the answers may arrive in any order from the server and ++ therefore the first and second answer buffers may not correspond to ++ the first and second queries. ++ ++ It is not supported to call this function with a non-NULL ANSP2 ++ but a NULL ANSCP. Put another way, you can call send_vc with a ++ single unmodifiable buffer or two modifiable buffers, but no other ++ combination is supported. ++ ++ It is the caller's responsibility to free the malloc allocated ++ buffers by detecting that the pointers have changed from their ++ original values i.e. *ANSCP or *ANSP2 has changed. ++ ++ If an answer is truncated because of UDP datagram DNS limits then ++ *V_CIRCUIT is set to 1 and the return value non-zero to indicate to ++ the caller to retry with TCP. The value *GOTSOMEWHERE is set to 1 ++ if any progress was made reading a response from the nameserver and ++ is used by the caller to distinguish between ECONNREFUSED and ++ ETIMEDOUT (the latter if *GOTSOMEWHERE is 1). ++ ++ If errors are encountered then *TERRNO is set to an appropriate ++ errno value and a zero result is returned for a recoverable error, ++ and a less-than zero result is returned for a non-recoverable error. ++ ++ If no errors are encountered then *TERRNO is left unmodified and ++ a the length of the first response in bytes is returned. */ + static int + send_dg(res_state statp, + const u_char *buf, int buflen, const u_char *buf2, int buflen2, +@@ -1006,8 +1135,6 @@ + { + const HEADER *hp = (HEADER *) buf; + const HEADER *hp2 = (HEADER *) buf2; +- u_char *ans = *ansp; +- int orig_anssizp = *anssizp; + struct timespec now, timeout, finish; + struct pollfd pfd[1]; + int ptimeout; +@@ -1040,6 +1167,8 @@ + int need_recompute = 0; + int nwritten = 0; + int recvresp1 = 0; ++ /* Skip the second response if there is no second query. ++ To do that we mark the second response as received. */ + int recvresp2 = buf2 == NULL; + pfd[0].fd = EXT(statp).nssocks[ns]; + pfd[0].events = POLLOUT; +@@ -1203,55 +1332,56 @@ + int *thisresplenp; + + if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) { ++ /* We have not received any responses ++ yet or we only have one response to ++ receive. */ + thisanssizp = anssizp; + thisansp = anscp ?: ansp; + assert (anscp != NULL || ansp2 == NULL); + thisresplenp = &resplen; + } else { +- if (*anssizp != MAXPACKET) { +- /* No buffer allocated for the first +- reply. We can try to use the rest +- of the user-provided buffer. */ +-#if _STRING_ARCH_unaligned +- *anssizp2 = orig_anssizp - resplen; +- *ansp2 = *ansp + resplen; +-#else +- int aligned_resplen +- = ((resplen + __alignof__ (HEADER) - 1) +- & ~(__alignof__ (HEADER) - 1)); +- *anssizp2 = orig_anssizp - aligned_resplen; +- *ansp2 = *ansp + aligned_resplen; +-#endif +- } else { +- /* The first reply did not fit into the +- user-provided buffer. Maybe the second +- answer will. */ +- *anssizp2 = orig_anssizp; +- *ansp2 = *ansp; +- } +- + thisanssizp = anssizp2; + thisansp = ansp2; + thisresplenp = resplen2; + } + + if (*thisanssizp < MAXPACKET +- /* Yes, we test ANSCP here. If we have two buffers +- both will be allocatable. */ +- && anscp ++ /* If the current buffer is non-NULL and it's not ++ pointing at the static user-supplied buffer then ++ we can reallocate it. */ ++ && (thisansp != NULL && thisansp != ansp) + #ifdef FIONREAD ++ /* Is the size too small? */ + && (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0 + || *thisanssizp < *thisresplenp) + #endif + ) { ++ /* Always allocate MAXPACKET, callers expect ++ this specific size. */ + u_char *newp = malloc (MAXPACKET); + if (newp != NULL) { +- *anssizp = MAXPACKET; +- *thisansp = ans = newp; ++ *thisanssizp = MAXPACKET; ++ *thisansp = newp; + if (thisansp == ansp2) + *ansp2_malloced = 1; + } + } ++ /* We could end up with truncation if anscp was NULL ++ (not allowed to change caller's buffer) and the ++ response buffer size is too small. This isn't a ++ reliable way to detect truncation because the ioctl ++ may be an inaccurate report of the UDP message size. ++ Therefore we use this only to issue debug output. ++ To do truncation accurately with UDP we need ++ MSG_TRUNC which is only available on Linux. We ++ can abstract out the Linux-specific feature in the ++ future to detect truncation. */ ++ if (__glibc_unlikely (*thisanssizp < *thisresplenp)) { ++ Dprint(statp->options & RES_DEBUG, ++ (stdout, ";; response may be truncated (UDP)\n") ++ ); ++ } ++ + HEADER *anhp = (HEADER *) *thisansp; + socklen_t fromlen = sizeof(struct sockaddr_in6); + assert (sizeof(from) <= fromlen); +--- stdlib/cxa_thread_atexit_impl.c 2015-08-05 08:42:21.000000000 +0200 ++++ stdlib/cxa_thread_atexit_impl.c 2016-02-16 18:13:26.990538679 +0100 +@@ -98,6 +98,10 @@ + int + __cxa_thread_atexit_impl (dtor_func func, void *obj, void *dso_symbol) + { ++#ifdef PTR_MANGLE ++ PTR_MANGLE (func); ++#endif ++ + /* Prepend. */ + struct dtor_list *new = calloc (1, sizeof (struct dtor_list)); + new->func = func; +@@ -142,9 +146,13 @@ + while (tls_dtor_list) + { + struct dtor_list *cur = tls_dtor_list; ++ dtor_func func = cur->func; ++#ifdef PTR_DEMANGLE ++ PTR_DEMANGLE (func); ++#endif + + tls_dtor_list = tls_dtor_list->next; +- cur->func (cur->obj); ++ func (cur->obj); + + /* Ensure that the MAP dereference happens before + l_tls_dtor_count decrement. That way, we protect this access from a +--- string/strcoll_l.c 2015-08-05 08:42:21.000000000 +0200 ++++ string/strcoll_l.c 2016-02-16 18:13:26.990538679 +0100 +@@ -29,7 +29,6 @@ + # define STRING_TYPE char + # define USTRING_TYPE unsigned char + # define STRCOLL __strcoll_l +-# define STRDIFF __strdiff + # define STRCMP strcmp + # define WEIGHT_H "../locale/weight.h" + # define SUFFIX MB +@@ -42,20 +41,6 @@ + #include "../locale/localeinfo.h" + #include WEIGHT_H + +-#define MASK_UTF8_7BIT (1 << 7) +-#define MASK_UTF8_START (3 << 6) +- +-size_t +-STRDIFF (const STRING_TYPE *s, const STRING_TYPE *t) +-{ +- size_t n; +- +- for (n = 0; *s != '\0' && *s++ == *t++; ++n) +- continue; +- +- return n; +-} +- + /* Track status while looking for sequences in a string. */ + typedef struct + { +@@ -269,29 +254,9 @@ + const USTRING_TYPE *extra; + const int32_t *indirect; + +- /* In case there is no locale specific sort order (C / POSIX). */ + if (nrules == 0) + return STRCMP (s1, s2); + +- /* Fast forward to the position of the first difference. Needs to be +- encoding aware as the byte-by-byte comparison can stop in the middle +- of a char sequence for multibyte encodings like UTF-8. */ +- uint_fast32_t encoding = +- current->values[_NL_ITEM_INDEX (_NL_COLLATE_ENCODING_TYPE)].word; +- if (encoding != __cet_other) +- { +- size_t diff = STRDIFF (s1, s2); +- if (diff > 0) +- { +- if (encoding == __cet_utf8 && (*(s1 + diff) & MASK_UTF8_7BIT) != 0) +- do +- diff--; +- while (diff > 0 && (*(s1 + diff) & MASK_UTF8_START) != MASK_UTF8_START); +- s1 += diff; +- s2 += diff; +- } +- } +- + /* Catch empty strings. */ + if (__glibc_unlikely (*s1 == '\0') || __glibc_unlikely (*s2 == '\0')) + return (*s1 != '\0') - (*s2 != '\0'); +@@ -358,8 +323,7 @@ + byte-level comparison to ensure that we don't waste time + going through multiple passes for totally equal strings + before proceeding to subsequent passes. */ +- if (pass == 0 && encoding == __cet_other && +- STRCMP (s1, s2) == 0) ++ if (pass == 0 && STRCMP (s1, s2) == 0) + return result; + else + break; +--- sysdeps/generic/ldsodefs.h 2015-08-05 08:42:21.000000000 +0200 ++++ sysdeps/generic/ldsodefs.h 2016-02-16 18:13:26.990538679 +0100 +@@ -592,9 +592,6 @@ + /* List of auditing interfaces. */ + struct audit_ifaces *_dl_audit; + unsigned int _dl_naudit; +- +- /* 0 if internal pointer values should not be guarded, 1 if they should. */ +- EXTERN int _dl_pointer_guard; + }; + # define __rtld_global_attribute__ + # if IS_IN (rtld) +--- sysdeps/posix/opendir.c 2015-08-05 08:42:21.000000000 +0200 ++++ sysdeps/posix/opendir.c 2016-02-16 18:13:26.990538679 +0100 +@@ -105,7 +105,7 @@ + tryopen_o_directory (); + + /* We can skip the expensive `stat' call if O_DIRECTORY works. */ +- return o_directory_works > 0; ++ return o_directory_works < 0; + #endif + return true; + } +--- sysdeps/x86/fpu/bits/math-vector.h 2015-08-05 08:42:21.000000000 +0200 ++++ sysdeps/x86/fpu/bits/math-vector.h 2016-02-16 18:13:26.991538699 +0100 +@@ -53,34 +53,5 @@ + # undef __DECL_SIMD_powf + # define __DECL_SIMD_powf __DECL_SIMD_x86_64 + +-/* Workaround to exclude unnecessary symbol aliases in libmvec +- while GCC creates the vector names based on scalar asm name. +- Corresponding discussion started at +- . */ +-__asm__ ("_ZGVbN2v___log_finite = _ZGVbN2v_log"); +-__asm__ ("_ZGVcN4v___log_finite = _ZGVcN4v_log"); +-__asm__ ("_ZGVdN4v___log_finite = _ZGVdN4v_log"); +-__asm__ ("_ZGVeN8v___log_finite = _ZGVeN8v_log"); +-__asm__ ("_ZGVbN4v___logf_finite = _ZGVbN4v_logf"); +-__asm__ ("_ZGVcN8v___logf_finite = _ZGVcN8v_logf"); +-__asm__ ("_ZGVdN8v___logf_finite = _ZGVdN8v_logf"); +-__asm__ ("_ZGVeN16v___logf_finite = _ZGVeN16v_logf"); +-__asm__ ("_ZGVbN2v___exp_finite = _ZGVbN2v_exp"); +-__asm__ ("_ZGVcN4v___exp_finite = _ZGVcN4v_exp"); +-__asm__ ("_ZGVdN4v___exp_finite = _ZGVdN4v_exp"); +-__asm__ ("_ZGVeN8v___exp_finite = _ZGVeN8v_exp"); +-__asm__ ("_ZGVbN4v___expf_finite = _ZGVbN4v_expf"); +-__asm__ ("_ZGVcN8v___expf_finite = _ZGVcN8v_expf"); +-__asm__ ("_ZGVdN8v___expf_finite = _ZGVdN8v_expf"); +-__asm__ ("_ZGVeN16v___expf_finite = _ZGVeN16v_expf"); +-__asm__ ("_ZGVbN2vv___pow_finite = _ZGVbN2vv_pow"); +-__asm__ ("_ZGVcN4vv___pow_finite = _ZGVcN4vv_pow"); +-__asm__ ("_ZGVdN4vv___pow_finite = _ZGVdN4vv_pow"); +-__asm__ ("_ZGVeN8vv___pow_finite = _ZGVeN8vv_pow"); +-__asm__ ("_ZGVbN4vv___powf_finite = _ZGVbN4vv_powf"); +-__asm__ ("_ZGVcN8vv___powf_finite = _ZGVcN8vv_powf"); +-__asm__ ("_ZGVdN8vv___powf_finite = _ZGVdN8vv_powf"); +-__asm__ ("_ZGVeN16vv___powf_finite = _ZGVeN16vv_powf"); +- + # endif + #endif +--- sysdeps/x86_64/fpu/Makefile 2015-08-05 08:42:21.000000000 +0200 ++++ sysdeps/x86_64/fpu/Makefile 2016-02-16 18:13:26.991538699 +0100 +@@ -20,7 +20,10 @@ + svml_d_pow_data svml_s_powf4_core svml_s_powf8_core_avx \ + svml_s_powf8_core svml_s_powf16_core svml_s_powf_data \ + svml_s_sincosf4_core svml_s_sincosf8_core_avx \ +- svml_s_sincosf8_core svml_s_sincosf16_core init-arch ++ svml_s_sincosf8_core svml_s_sincosf16_core init-arch \ ++ svml_finite_alias ++ ++libmvec-static-only-routines = svml_finite_alias + endif + + # Variables for libmvec tests. +--- sysdeps/x86_64/fpu/svml_finite_alias.S 1970-01-01 01:00:00.000000000 +0100 ++++ sysdeps/x86_64/fpu/svml_finite_alias.S 2016-02-16 18:13:26.991538699 +0100 +@@ -0,0 +1,59 @@ ++/* These aliases added as workaround to exclude unnecessary symbol ++ aliases in libmvec.so while compiler creates the vector names ++ based on scalar asm name. Corresponding discussion is at ++ . ++ Copyright (C) 2015 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++#define ALIAS_IMPL(alias, target) \ ++ENTRY (alias); \ ++ call target; \ ++ ret; \ ++END (alias) ++ ++ .text ++ALIAS_IMPL (_ZGVbN2v___log_finite, _ZGVbN2v_log) ++ALIAS_IMPL (_ZGVcN4v___log_finite, _ZGVcN4v_log) ++ALIAS_IMPL (_ZGVdN4v___log_finite, _ZGVdN4v_log) ++ALIAS_IMPL (_ZGVeN8v___log_finite, _ZGVeN8v_log) ++ ++ALIAS_IMPL (_ZGVbN4v___logf_finite, _ZGVbN4v_logf) ++ALIAS_IMPL (_ZGVcN8v___logf_finite, _ZGVcN8v_logf) ++ALIAS_IMPL (_ZGVdN8v___logf_finite, _ZGVdN8v_logf) ++ALIAS_IMPL (_ZGVeN16v___logf_finite, _ZGVeN16v_logf) ++ ++ALIAS_IMPL (_ZGVbN2v___exp_finite, _ZGVbN2v_exp) ++ALIAS_IMPL (_ZGVcN4v___exp_finite, _ZGVcN4v_exp) ++ALIAS_IMPL (_ZGVdN4v___exp_finite, _ZGVdN4v_exp) ++ALIAS_IMPL (_ZGVeN8v___exp_finite, _ZGVeN8v_exp) ++ ++ALIAS_IMPL (_ZGVbN4v___expf_finite, _ZGVbN4v_expf) ++ALIAS_IMPL (_ZGVcN8v___expf_finite, _ZGVcN8v_expf) ++ALIAS_IMPL (_ZGVdN8v___expf_finite, _ZGVdN8v_expf) ++ALIAS_IMPL (_ZGVeN16v___expf_finite, _ZGVeN16v_expf) ++ ++ALIAS_IMPL (_ZGVbN2vv___pow_finite, _ZGVbN2vv_pow) ++ALIAS_IMPL (_ZGVcN4vv___pow_finite, _ZGVcN4vv_pow) ++ALIAS_IMPL (_ZGVdN4vv___pow_finite, _ZGVdN4vv_pow) ++ALIAS_IMPL (_ZGVeN8vv___pow_finite, _ZGVeN8vv_pow) ++ ++ALIAS_IMPL (_ZGVbN4vv___powf_finite, _ZGVbN4vv_powf) ++ALIAS_IMPL (_ZGVcN8vv___powf_finite, _ZGVcN8vv_powf) ++ALIAS_IMPL (_ZGVdN8vv___powf_finite, _ZGVdN8vv_powf) ++ALIAS_IMPL (_ZGVeN16vv___powf_finite, _ZGVeN16vv_powf) +--- time/strftime_l.c 2015-08-05 08:42:21.000000000 +0200 ++++ time/strftime_l.c 2016-02-16 18:13:26.991538699 +0100 +@@ -510,13 +510,17 @@ + only a few elements. Dereference the pointers only if the format + requires this. Then it is ok to fail if the pointers are invalid. */ + # define a_wkday \ +- ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday)) ++ ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \ ++ ? "?" : _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))) + # define f_wkday \ +- ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday)) ++ ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \ ++ ? "?" : _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))) + # define a_month \ +- ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon)) ++ ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \ ++ ? "?" : _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))) + # define f_month \ +- ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon)) ++ ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \ ++ ? "?" : _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))) + # define ampm \ + ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \ + ? NLW(PM_STR) : NLW(AM_STR))) +@@ -526,8 +530,10 @@ + # define ap_len STRLEN (ampm) + #else + # if !HAVE_STRFTIME +-# define f_wkday (weekday_name[tp->tm_wday]) +-# define f_month (month_name[tp->tm_mon]) ++# define f_wkday (tp->tm_wday < 0 || tp->tm_wday > 6 \ ++ ? "?" : weekday_name[tp->tm_wday]) ++# define f_month (tp->tm_mon < 0 || tp->tm_mon > 11 \ ++ ? "?" : month_name[tp->tm_mon]) + # define a_wkday f_wkday + # define a_month f_month + # define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11)) +@@ -1321,7 +1327,7 @@ + *tzset_called = true; + } + # endif +- zone = tzname[tp->tm_isdst]; ++ zone = tp->tm_isdst <= 1 ? tzname[tp->tm_isdst] : "?"; + } + #endif + if (! zone) +--- wcsmbs/wcscoll_l.c 2015-08-05 08:42:21.000000000 +0200 ++++ wcsmbs/wcscoll_l.c 2016-02-16 18:13:26.991538699 +0100 +@@ -23,7 +23,6 @@ + #define STRING_TYPE wchar_t + #define USTRING_TYPE wint_t + #define STRCOLL __wcscoll_l +-#define STRDIFF __wcsdiff + #define STRCMP __wcscmp + #define WEIGHT_H "../locale/weightwc.h" + #define SUFFIX WC diff --git a/srcpkgs/glibc/patches/glibc-2.22-upstream_i386_fix-1.patch b/srcpkgs/glibc/patches/glibc-2.22-upstream_i386_fix-1.patch new file mode 100644 index 0000000000..782c3e6d4b --- /dev/null +++ b/srcpkgs/glibc/patches/glibc-2.22-upstream_i386_fix-1.patch @@ -0,0 +1,55 @@ +Submitted By: Bruce Dubbs +Date: 2015-08-23 +Initial Package Version: 2.22 +Upstream Status: In repository +Origin: https://github.molgen.mpg.de/git-mirror/glibc +Description: This patch fixes a build problem on 32-bit systems. + +commit a08e80d1143f6b0386d5bc8cc7b8ed576091dbf3 +Author: Andrew Senkevich +Date: Wed Aug 19 16:54:28 2015 +0300 + + [BZ #18796] + * scripts/test-installation.pl: Don't add -lmvec to build options if + libmvec wasn't built. + +diff --git a/scripts/test-installation.pl b/scripts/test-installation.pl +index cac1562..79b2b3e 100755 +--- scripts/test-installation.pl ++++ scripts/test-installation.pl +@@ -80,16 +80,25 @@ arglist: while (@ARGV) { + # We expect none or one argument. + if ($#ARGV == -1) { + $soversions="soversions.mk"; ++ $config="config.make"; + } elsif ($#ARGV == 0) { + if (-d $ARGV[0]) { + $soversions = "$ARGV[0]/soversions.mk"; ++ $config = "$ARGV[0]/config.make"; + } else { +- $soversions = $ARGV[0]; ++ $soversions = $dir = $ARGV[0]; ++ $dir =~ s!/?[^/]*/*$!!; ++ $config = $dir . "/config.make"; + } + } else { + die "Wrong number of arguments."; + } + ++if (system ("grep -q \"build-mathvec = yes\" $config") == 0) { ++ $build_mathvec = 1; ++} else { ++ $build_mathvec = 0; ++} + + # Read names and versions of all shared libraries that are part of + # glibc +@@ -111,6 +120,8 @@ while () { + # - libthread_db since it contains unresolved references + # - it's just a test NSS module + # - We don't provide the libgcc so we don't test it ++ # - libmvec if it wasn't built ++ next if ($build_mathvec == 0 && $name eq "mvec"); + if ($name ne "nss_ldap" && $name ne "db1" + && !($name =~/^nss1_/) && $name ne "thread_db" + && $name ne "nss_test1" && $name ne "libgcc_s") { diff --git a/srcpkgs/glibc/template b/srcpkgs/glibc/template index 57b39df78b..c374a2b4ed 100644 --- a/srcpkgs/glibc/template +++ b/srcpkgs/glibc/template @@ -1,7 +1,7 @@ # Template file for 'glibc' pkgname=glibc version=2.22 -revision=3 +revision=4 bootstrap=yes short_desc="The GNU C library" maintainer="Juan RP "