diff -Nru glibc-2.21/debian/changelog glibc-2.21/debian/changelog --- glibc-2.21/debian/changelog 2016-02-16 16:43:05.000000000 +0000 +++ glibc-2.21/debian/changelog 2016-04-09 06:00:53.000000000 +0000 @@ -1,3 +1,56 @@ +glibc (2.21-0ubuntu4.2) wily-security; urgency=medium + + * SECURITY UPDATE: buffer overflow in gethostbyname_r and related + functions + - debian/patches/any/CVE-2015-1781.diff: take alignment padding + into account when computing if buffer is too small. + - CVE-2015-1781 + * SECURITY UPDATE: glibc Name Service Switch (NSS) denial of sevice + - debian/patches/any/CVE-2014-8121-1.diff: do not close NSS files + database during iteration. + - debian/patches/any/CVE-2014-8121-2.diff: Separate internal state + between getXXent and getXXbyYY NSS calls. + - CVE-2014-8121 + * SECURITY UPDATE: glibc unbounded stack usage in NaN strtod + conversion + - debian/patches/any/CVE-2014-9761-1.diff: Refactor strtod parsing + of NaN payloads. + - debian/patches/any/CVE-2014-9761-1.diff: Fix nan functions + handling of payload strings + - CVE-2014-9761 + * SECURITY UPDATE: out of range data to strftime() causes segfault + (denial of service) + - debian/patches/any/CVE-2015-8776.diff: add range checks to + strftime() processing + - CVE-2015-8776 + * SECURITY UPDATE: glibc honors LD_POINTER_GUARD env for setuid + AT_SECURE programs (e.g. setuid), allowing disabling of pointer + mangling + - debian/patches/any/CVE-2015-8777.diff: Always enable pointer + guard + - CVE-2015-8777 + * SECURITY UPDATE: integer overflow in hcreate and hcreate_r + - debian/patches/any/CVE-2015-8778.diff: check for large inputs + - CVE-2015-8778 + * SECURITY UPDATE: unbounded stack allocation in catopen() + - debian/patches/any/CVE-2015-8779.diff: stop using unbounded + alloca() + - CVE-2015-8779 + * SECURITY UPDATE: Stack overflow in _nss_dns_getnetbyname_r + - debian/patches/any/CVE-2016-3075.diff: do not make unneeded + memory copy on the stack. + - CVE-2016-3075 + * SECURITY UPDATE: pt_chown privilege escalation + - debian/patches/any/CVE-2016-2856.diff: grantpt: trust the kernel + about pty group and permission mode + - debian/sysdeps/linux.mk: don't build pt_chown + - debian/rules.d/debhelper.mk: only install pt_chown when built. + - CVE-2016-2856, CVE-2013-2207 + * debian/debhelper.in/libc.postinst: add reboot notifications for + security updates (LP: #1546457) + + -- Steve Beattie Fri, 08 Apr 2016 09:44:34 -0700 + glibc (2.21-0ubuntu4.1) wily-security; urgency=medium * SECURITY UPDATE: glibc getaddrinfo stack-based buffer overflow diff -Nru glibc-2.21/debian/debhelper.in/libc.postinst glibc-2.21/debian/debhelper.in/libc.postinst --- glibc-2.21/debian/debhelper.in/libc.postinst 2015-03-16 16:06:52.000000000 +0000 +++ glibc-2.21/debian/debhelper.in/libc.postinst 2016-04-08 16:44:29.000000000 +0000 @@ -185,6 +185,15 @@ else echo "Nothing to restart." fi + else + + # Here we issue the reboot notification for upgrades and + # security updates. We do want services to be restarted when we + # update for a security issue, but planned by the + # sysadmin, not automatically. (LP: #1546457) + if [ -x /usr/share/update-notifier/notify-reboot-required ]; then + /usr/share/update-notifier/notify-reboot-required + fi fi # end upgrading and $preversion lt 2.21 fi # Upgrading diff -Nru glibc-2.21/debian/patches/any/CVE-2014-8121-1.diff glibc-2.21/debian/patches/any/CVE-2014-8121-1.diff --- glibc-2.21/debian/patches/any/CVE-2014-8121-1.diff 1970-01-01 00:00:00.000000000 +0000 +++ glibc-2.21/debian/patches/any/CVE-2014-8121-1.diff 2016-03-31 05:19:24.000000000 +0000 @@ -0,0 +1,229 @@ +From 03d2730b44cc2236318fd978afa2651753666c55 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Wed, 29 Apr 2015 14:41:25 +0200 +Subject: [PATCH] CVE-2014-8121: Do not close NSS files database during iteration [BZ #18007] +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf8 +Content-Transfer-Encoding: 8bit + +Robin Hack discovered Samba would enter an infinite loop processing +certain quota-related requests. We eventually tracked this down to a +glibc issue. + +Running a (simplified) test case under strace shows that /etc/passwd +is continuously opened and closed: + +… +open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3 +lseek(3, 0, SEEK_CUR) = 0 +read(3, "root:x:0:0:root:/root:/bin/bash\n"..., 4096) = 2717 +lseek(3, 2717, SEEK_SET) = 2717 +close(3) = 0 +open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3 +lseek(3, 0, SEEK_CUR) = 0 +lseek(3, 0, SEEK_SET) = 0 +read(3, "root:x:0:0:root:/root:/bin/bash\n"..., 4096) = 2717 +lseek(3, 2717, SEEK_SET) = 2717 +close(3) = 0 +open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3 +lseek(3, 0, SEEK_CUR) = 0 +… + +The lookup function implementation in +nss/nss_files/files-XXX.c:DB_LOOKUP has code to prevent that. It is +supposed skip closing the input file if it was already open. + + /* Reset file pointer to beginning or open file. */ \ + status = internal_setent (keep_stream); \ + \ + if (status == NSS_STATUS_SUCCESS) \ + { \ + /* Tell getent function that we have repositioned the file pointer. */ \ + last_use = getby; \ + \ + while ((status = internal_getent (result, buffer, buflen, errnop \ + H_ERRNO_ARG EXTRA_ARGS_VALUE)) \ + == NSS_STATUS_SUCCESS) \ + { break_if_match } \ + \ + if (! keep_stream) \ + internal_endent (); \ + } \ + +keep_stream is initialized from the stayopen flag in internal_setent. +internal_setent is called from the set*ent implementation as: + + status = internal_setent (stayopen); + +However, for non-host database, this flag is always 0, per the +STAYOPEN magic in nss/getXXent_r.c. + +Thus, the fix is this: + +- status = internal_setent (stayopen); ++ status = internal_setent (1); + +This is not a behavioral change even for the hosts database (where the +application can specify the stayopen flag) because with a call to +sethostent(0), the file handle is still not closed in the +implementation of gethostent. + +[Note: patch differs from upstream commit in that the entries in the +Changelog and NEWS files were dropped to avoid patch conflicts -- sbeattie] + +--- + nss/Makefile | 2 + nss/nss_files/files-XXX.c | 2 + nss/tst-nss-getpwent.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 120 insertions(+), 2 deletions(-) + create mode 100644 nss/tst-nss-getpwent.c + +Index: b/nss/Makefile +=================================================================== +--- a/nss/Makefile ++++ b/nss/Makefile +@@ -39,7 +39,7 @@ install-bin := getent makedb + makedb-modules = xmalloc hash-string + extra-objs += $(makedb-modules:=.o) + +-tests = test-netdb tst-nss-test1 test-digits-dots ++tests = test-netdb tst-nss-test1 test-digits-dots tst-nss-getpwent + xtests = bug-erange + + # Specify rules for the nss_* modules. We have some services. +Index: b/nss/nss_files/files-XXX.c +=================================================================== +--- a/nss/nss_files/files-XXX.c ++++ b/nss/nss_files/files-XXX.c +@@ -134,7 +134,7 @@ CONCAT(_nss_files_set,ENTNAME) (int stay + + __libc_lock_lock (lock); + +- status = internal_setent (stayopen); ++ status = internal_setent (1); + + if (status == NSS_STATUS_SUCCESS && fgetpos (stream, &position) < 0) + { +Index: b/nss/tst-nss-getpwent.c +=================================================================== +--- /dev/null ++++ b/nss/tst-nss-getpwent.c +@@ -0,0 +1,118 @@ ++/* 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 ++#include ++#include ++#include ++#include ++ ++int ++do_test (void) ++{ ++ /* Count the number of entries in the password database, and fetch ++ data from the first and last entries. */ ++ size_t count = 0; ++ struct passwd * pw; ++ char *first_name = NULL; ++ uid_t first_uid = 0; ++ char *last_name = NULL; ++ uid_t last_uid = 0; ++ setpwent (); ++ while ((pw = getpwent ()) != NULL) ++ { ++ if (first_name == NULL) ++ { ++ first_name = strdup (pw->pw_name); ++ if (first_name == NULL) ++ { ++ printf ("strdup: %m\n"); ++ return 1; ++ } ++ first_uid = pw->pw_uid; ++ } ++ ++ free (last_name); ++ last_name = strdup (pw->pw_name); ++ if (last_name == NULL) ++ { ++ printf ("strdup: %m\n"); ++ return 1; ++ } ++ last_uid = pw->pw_uid; ++ ++count; ++ } ++ endpwent (); ++ ++ if (count == 0) ++ { ++ printf ("No entries in the password database.\n"); ++ return 0; ++ } ++ ++ /* Try again, this time interleaving with name-based and UID-based ++ lookup operations. The counts do not match if the interleaved ++ lookups affected the enumeration. */ ++ size_t new_count = 0; ++ setpwent (); ++ while ((pw = getpwent ()) != NULL) ++ { ++ if (new_count == count) ++ { ++ printf ("Additional entry in the password database.\n"); ++ return 1; ++ } ++ ++new_count; ++ struct passwd *pw2 = getpwnam (first_name); ++ if (pw2 == NULL) ++ { ++ printf ("getpwnam (%s) failed: %m\n", first_name); ++ return 1; ++ } ++ pw2 = getpwnam (last_name); ++ if (pw2 == NULL) ++ { ++ printf ("getpwnam (%s) failed: %m\n", last_name); ++ return 1; ++ } ++ pw2 = getpwuid (first_uid); ++ if (pw2 == NULL) ++ { ++ printf ("getpwuid (%llu) failed: %m\n", ++ (unsigned long long) first_uid); ++ return 1; ++ } ++ pw2 = getpwuid (last_uid); ++ if (pw2 == NULL) ++ { ++ printf ("getpwuid (%llu) failed: %m\n", ++ (unsigned long long) last_uid); ++ return 1; ++ } ++ } ++ endpwent (); ++ if (new_count < count) ++ { ++ printf ("Missing entry in the password database.\n"); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++#define TEST_FUNCTION do_test () ++#include "../test-skeleton.c" diff -Nru glibc-2.21/debian/patches/any/CVE-2014-8121-2.diff glibc-2.21/debian/patches/any/CVE-2014-8121-2.diff --- glibc-2.21/debian/patches/any/CVE-2014-8121-2.diff 1970-01-01 00:00:00.000000000 +0000 +++ glibc-2.21/debian/patches/any/CVE-2014-8121-2.diff 2016-03-31 05:22:54.000000000 +0000 @@ -0,0 +1,697 @@ +From b13b96ca05a132a12dc5f3712b99e626670716bf Mon Sep 17 00:00:00 2001 +From: Andreas Schwab +Date: Wed, 25 Mar 2015 16:35:46 +0100 +Subject: [PATCH] Separate internal state between getXXent and getXXbyYY NSS calls (bug 18007) + +2015-05-11 Andreas Schwab + + [BZ #18007] + * nis/nss_compat/compat-grp.c (internal_endgrent): Don't call + nss_endgrent. + (_nss_compat_endgrent): Call nss_endgrent. + * nis/nss_compat/compat-pwd.c (internal_endpwent): Don't call + nss_endpwent. + (_nss_compat_endpwent): Call nss_endpwent. + * nis/nss_compat/compat-spwd.c (internal_setspent): Add parameter + needent, call nss_setspent only if non-zero. + (_nss_compat_setspent, _nss_compat_getspent_r): Pass non-zero. + (internal_endspent): Don't call nss_endspent. + (_nss_compat_endspent): Call nss_endspent. + * nss/nss_files/files-XXX.c (position, last_use, keep_stream): + Remove. All uses removed. + (internal_setent): Remove parameter stayopen, add parameter + stream. Use it instead of global variable. + (CONCAT(_nss_files_set,ENTNAME)): Pass global stream. + (internal_endent, internal_getent): Add parameter stream. Use it + instead of global variable. + (CONCAT(_nss_files_end,ENTNAME)) + (CONCAT(_nss_files_get,ENTNAME_r)): Pass global stream. + (_nss_files_get##name##_r): Pass local stream. Remove locking. + * nss/nss_files/files-alias.c (position, last_use): Remove. All + uses removed. + (internal_setent, internal_endent): Add parameter stream. Use it + instead of global variable. + (_nss_files_setaliasent, _nss_files_endaliasent): Pass global + stream. + (get_next_alias): Add parameter stream. + (_nss_files_getaliasent_r): Pass global stream. + (_nss_files_getaliasbyname_r): Pass local stream. Remove locking. + * nss/nss_files/files-hosts.c (_nss_files_gethostbyname3_r) + (_nss_files_gethostbyname4_r): Pass local stream to + internal_setent, internal_getent and internal_endent. Remove + locking. + +[Note: patch differs from upstream commit in that the entries in the +Changelog and NEWS files were dropped to avoid patch conflicts -- sbeattie] + +--- + nis/nss_compat/compat-grp.c | 6 +- + nis/nss_compat/compat-pwd.c | 6 +- + nis/nss_compat/compat-spwd.c | 16 +++--- + nss/nss_files/files-XXX.c | 109 ++++++++++--------------------------------- + nss/nss_files/files-alias.c | 90 +++++++++++------------------------ + nss/nss_files/files-hosts.c | 35 ++++--------- + 6 files changed, 81 insertions(+), 181 deletions(-) + +Index: b/nis/nss_compat/compat-grp.c +=================================================================== +--- a/nis/nss_compat/compat-grp.c ++++ b/nis/nss_compat/compat-grp.c +@@ -194,9 +194,6 @@ _nss_compat_setgrent (int stayopen) + static enum nss_status + internal_endgrent (ent_t *ent) + { +- if (nss_endgrent) +- nss_endgrent (); +- + if (ent->stream != NULL) + { + fclose (ent->stream); +@@ -222,6 +219,9 @@ _nss_compat_endgrent (void) + + __libc_lock_lock (lock); + ++ if (nss_endgrent) ++ nss_endgrent (); ++ + result = internal_endgrent (&ext_ent); + + __libc_lock_unlock (lock); +Index: b/nis/nss_compat/compat-pwd.c +=================================================================== +--- a/nis/nss_compat/compat-pwd.c ++++ b/nis/nss_compat/compat-pwd.c +@@ -311,9 +311,6 @@ _nss_compat_setpwent (int stayopen) + static enum nss_status + internal_endpwent (ent_t *ent) + { +- if (nss_endpwent) +- nss_endpwent (); +- + if (ent->stream != NULL) + { + fclose (ent->stream); +@@ -346,6 +343,9 @@ _nss_compat_endpwent (void) + + __libc_lock_lock (lock); + ++ if (nss_endpwent) ++ nss_endpwent (); ++ + result = internal_endpwent (&ext_ent); + + __libc_lock_unlock (lock); +Index: b/nis/nss_compat/compat-spwd.c +=================================================================== +--- a/nis/nss_compat/compat-spwd.c ++++ b/nis/nss_compat/compat-spwd.c +@@ -169,7 +169,7 @@ copy_spwd_changes (struct spwd *dest, st + } + + static enum nss_status +-internal_setspent (ent_t *ent, int stayopen) ++internal_setspent (ent_t *ent, int stayopen, int needent) + { + enum nss_status status = NSS_STATUS_SUCCESS; + +@@ -239,7 +239,7 @@ internal_setspent (ent_t *ent, int stayo + + give_spwd_free (&ent->pwd); + +- if (status == NSS_STATUS_SUCCESS && nss_setspent) ++ if (needent && status == NSS_STATUS_SUCCESS && nss_setspent) + ent->setent_status = nss_setspent (stayopen); + + return status; +@@ -256,7 +256,7 @@ _nss_compat_setspent (int stayopen) + if (ni == NULL) + init_nss_interface (); + +- result = internal_setspent (&ext_ent, stayopen); ++ result = internal_setspent (&ext_ent, stayopen, 1); + + __libc_lock_unlock (lock); + +@@ -267,9 +267,6 @@ _nss_compat_setspent (int stayopen) + static enum nss_status + internal_endspent (ent_t *ent) + { +- if (nss_endspent) +- nss_endspent (); +- + if (ent->stream != NULL) + { + fclose (ent->stream); +@@ -303,6 +300,9 @@ _nss_compat_endspent (void) + + __libc_lock_lock (lock); + ++ if (nss_endspent) ++ nss_endspent (); ++ + result = internal_endspent (&ext_ent); + + __libc_lock_unlock (lock); +@@ -658,7 +658,7 @@ _nss_compat_getspent_r (struct spwd *pwd + init_nss_interface (); + + if (ext_ent.stream == NULL) +- result = internal_setspent (&ext_ent, 1); ++ result = internal_setspent (&ext_ent, 1, 1); + + if (result == NSS_STATUS_SUCCESS) + result = internal_getspent_r (pwd, &ext_ent, buffer, buflen, errnop); +@@ -830,7 +830,7 @@ _nss_compat_getspnam_r (const char *name + + __libc_lock_unlock (lock); + +- result = internal_setspent (&ent, 0); ++ result = internal_setspent (&ent, 0, 0); + + if (result == NSS_STATUS_SUCCESS) + result = internal_getspnam_r (name, pwd, &ent, buffer, buflen, errnop); +Index: b/nss/nss_files/files-XXX.c +=================================================================== +--- a/nss/nss_files/files-XXX.c ++++ b/nss/nss_files/files-XXX.c +@@ -60,24 +60,23 @@ + /* Locks the static variables in this file. */ + __libc_lock_define_initialized (static, lock) + +-/* Maintenance of the shared stream open on the database file. */ ++/* Maintenance of the stream open on the database file. For getXXent ++ operations the stream needs to be held open across calls, the other ++ getXXbyYY operations all use their own stream. */ + + static FILE *stream; +-static fpos_t position; +-static enum { nouse, getent, getby } last_use; +-static int keep_stream; + + /* Open database file if not already opened. */ + static enum nss_status +-internal_setent (int stayopen) ++internal_setent (FILE **stream) + { + enum nss_status status = NSS_STATUS_SUCCESS; + +- if (stream == NULL) ++ if (*stream == NULL) + { +- stream = fopen (DATAFILE, "rce"); ++ *stream = fopen (DATAFILE, "rce"); + +- if (stream == NULL) ++ if (*stream == NULL) + status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; + else + { +@@ -90,7 +89,7 @@ internal_setent (int stayopen) + int result; + int flags; + +- result = flags = fcntl (fileno (stream), F_GETFD, 0); ++ result = flags = fcntl (fileno (*stream), F_GETFD, 0); + if (result >= 0) + { + # ifdef O_CLOEXEC +@@ -100,15 +99,15 @@ internal_setent (int stayopen) + # endif + { + flags |= FD_CLOEXEC; +- result = fcntl (fileno (stream), F_SETFD, flags); ++ result = fcntl (fileno (*stream), F_SETFD, flags); + } + } + if (result < 0) + { + /* Something went wrong. Close the stream and return a + failure. */ +- fclose (stream); +- stream = NULL; ++ fclose (*stream); ++ *stream = NULL; + status = NSS_STATUS_UNAVAIL; + } + } +@@ -116,11 +115,7 @@ internal_setent (int stayopen) + } + } + else +- rewind (stream); +- +- /* Remember STAYOPEN flag. */ +- if (stream != NULL) +- keep_stream |= stayopen; ++ rewind (*stream); + + return status; + } +@@ -134,16 +129,7 @@ CONCAT(_nss_files_set,ENTNAME) (int stay + + __libc_lock_lock (lock); + +- status = internal_setent (1); +- +- if (status == NSS_STATUS_SUCCESS && fgetpos (stream, &position) < 0) +- { +- fclose (stream); +- stream = NULL; +- status = NSS_STATUS_UNAVAIL; +- } +- +- last_use = getent; ++ status = internal_setent (&stream); + + __libc_lock_unlock (lock); + +@@ -153,12 +139,12 @@ CONCAT(_nss_files_set,ENTNAME) (int stay + + /* Close the database file. */ + static void +-internal_endent (void) ++internal_endent (FILE **stream) + { +- if (stream != NULL) ++ if (*stream != NULL) + { +- fclose (stream); +- stream = NULL; ++ fclose (*stream); ++ *stream = NULL; + } + } + +@@ -169,10 +155,7 @@ CONCAT(_nss_files_end,ENTNAME) (void) + { + __libc_lock_lock (lock); + +- internal_endent (); +- +- /* Reset STAYOPEN flag. */ +- keep_stream = 0; ++ internal_endent (&stream); + + __libc_lock_unlock (lock); + +@@ -227,7 +210,7 @@ get_contents (char *linebuf, size_t len, + + /* Parsing the database file into `struct STRUCTURE' data structures. */ + static enum nss_status +-internal_getent (struct STRUCTURE *result, ++internal_getent (FILE *stream, struct STRUCTURE *result, + char *buffer, size_t buflen, int *errnop H_ERRNO_PROTO + EXTRA_ARGS_DECL) + { +@@ -300,45 +283,14 @@ CONCAT(_nss_files_get,ENTNAME_r) (struct + { + int save_errno = errno; + +- status = internal_setent (0); ++ status = internal_setent (&stream); + + __set_errno (save_errno); +- +- if (status == NSS_STATUS_SUCCESS && fgetpos (stream, &position) < 0) +- { +- fclose (stream); +- stream = NULL; +- status = NSS_STATUS_UNAVAIL; +- } + } + + if (status == NSS_STATUS_SUCCESS) +- { +- /* If the last use was not by the getent function we need the +- position the stream. */ +- if (last_use != getent) +- { +- if (fsetpos (stream, &position) < 0) +- status = NSS_STATUS_UNAVAIL; +- else +- last_use = getent; +- } +- +- if (status == NSS_STATUS_SUCCESS) +- { +- status = internal_getent (result, buffer, buflen, errnop +- H_ERRNO_ARG EXTRA_ARGS_VALUE); +- +- /* Remember this position if we were successful. If the +- operation failed we give the user a chance to repeat the +- operation (perhaps the buffer was too small). */ +- if (status == NSS_STATUS_SUCCESS) +- fgetpos (stream, &position); +- else +- /* We must make sure we reposition the stream the next call. */ +- last_use = nouse; +- } +- } ++ status = internal_getent (stream, result, buffer, buflen, errnop ++ H_ERRNO_ARG EXTRA_ARGS_VALUE); + + __libc_lock_unlock (lock); + +@@ -364,27 +316,20 @@ _nss_files_get##name##_r (proto, + size_t buflen, int *errnop H_ERRNO_PROTO) \ + { \ + enum nss_status status; \ ++ FILE *stream = NULL; \ + \ +- __libc_lock_lock (lock); \ +- \ +- /* Reset file pointer to beginning or open file. */ \ +- status = internal_setent (keep_stream); \ ++ /* Open file. */ \ ++ status = internal_setent (&stream); \ + \ + if (status == NSS_STATUS_SUCCESS) \ + { \ +- /* Tell getent function that we have repositioned the file pointer. */ \ +- last_use = getby; \ +- \ +- while ((status = internal_getent (result, buffer, buflen, errnop \ ++ while ((status = internal_getent (stream, result, buffer, buflen, errnop \ + H_ERRNO_ARG EXTRA_ARGS_VALUE)) \ + == NSS_STATUS_SUCCESS) \ + { break_if_match } \ + \ +- if (! keep_stream) \ +- internal_endent (); \ ++ internal_endent (&stream); \ + } \ + \ +- __libc_lock_unlock (lock); \ +- \ + return status; \ + } +Index: b/nss/nss_files/files-alias.c +=================================================================== +--- a/nss/nss_files/files-alias.c ++++ b/nss/nss_files/files-alias.c +@@ -33,23 +33,23 @@ + /* Locks the static variables in this file. */ + __libc_lock_define_initialized (static, lock) + +-/* Maintenance of the shared stream open on the database file. */ ++/* Maintenance of the stream open on the database file. For getXXent ++ operations the stream needs to be held open across calls, the other ++ getXXbyYY operations all use their own stream. */ + + static FILE *stream; +-static fpos_t position; +-static enum { nouse, getent, getby } last_use; + + + static enum nss_status +-internal_setent (void) ++internal_setent (FILE **stream) + { + enum nss_status status = NSS_STATUS_SUCCESS; + +- if (stream == NULL) ++ if (*stream == NULL) + { +- stream = fopen ("/etc/aliases", "rce"); ++ *stream = fopen ("/etc/aliases", "rce"); + +- if (stream == NULL) ++ if (*stream == NULL) + status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; + else + { +@@ -62,7 +62,7 @@ internal_setent (void) + int result; + int flags; + +- result = flags = fcntl (fileno (stream), F_GETFD, 0); ++ result = flags = fcntl (fileno (*stream), F_GETFD, 0); + if (result >= 0) + { + # ifdef O_CLOEXEC +@@ -72,14 +72,14 @@ internal_setent (void) + # endif + { + flags |= FD_CLOEXEC; +- result = fcntl (fileno (stream), F_SETFD, flags); ++ result = fcntl (fileno (*stream), F_SETFD, flags); + } + } + if (result < 0) + { + /* Something went wrong. Close the stream and return a + failure. */ +- fclose (stream); ++ fclose (*stream); + stream = NULL; + status = NSS_STATUS_UNAVAIL; + } +@@ -88,7 +88,7 @@ internal_setent (void) + } + } + else +- rewind (stream); ++ rewind (*stream); + + return status; + } +@@ -102,16 +102,7 @@ _nss_files_setaliasent (void) + + __libc_lock_lock (lock); + +- status = internal_setent (); +- +- if (status == NSS_STATUS_SUCCESS && fgetpos (stream, &position) < 0) +- { +- fclose (stream); +- stream = NULL; +- status = NSS_STATUS_UNAVAIL; +- } +- +- last_use = getent; ++ status = internal_setent (&stream); + + __libc_lock_unlock (lock); + +@@ -121,12 +112,12 @@ _nss_files_setaliasent (void) + + /* Close the database file. */ + static void +-internal_endent (void) ++internal_endent (FILE **stream) + { +- if (stream != NULL) ++ if (*stream != NULL) + { +- fclose (stream); +- stream = NULL; ++ fclose (*stream); ++ *stream = NULL; + } + } + +@@ -137,7 +128,7 @@ _nss_files_endaliasent (void) + { + __libc_lock_lock (lock); + +- internal_endent (); ++ internal_endent (&stream); + + __libc_lock_unlock (lock); + +@@ -146,7 +137,7 @@ _nss_files_endaliasent (void) + + /* Parsing the database file into `struct aliasent' data structures. */ + static enum nss_status +-get_next_alias (const char *match, struct aliasent *result, ++get_next_alias (FILE *stream, const char *match, struct aliasent *result, + char *buffer, size_t buflen, int *errnop) + { + enum nss_status status = NSS_STATUS_NOTFOUND; +@@ -397,35 +388,16 @@ _nss_files_getaliasent_r (struct aliasen + + /* Be prepared that the set*ent function was not called before. */ + if (stream == NULL) +- status = internal_setent (); ++ status = internal_setent (&stream); + + if (status == NSS_STATUS_SUCCESS) + { +- /* If the last use was not by the getent function we need the +- position the stream. */ +- if (last_use != getent) +- { +- if (fsetpos (stream, &position) < 0) +- status = NSS_STATUS_UNAVAIL; +- else +- last_use = getent; +- } +- +- if (status == NSS_STATUS_SUCCESS) +- { +- result->alias_local = 1; ++ result->alias_local = 1; + +- /* Read lines until we get a definite result. */ +- do +- status = get_next_alias (NULL, result, buffer, buflen, errnop); +- while (status == NSS_STATUS_RETURN); +- +- /* If we successfully read an entry remember this position. */ +- if (status == NSS_STATUS_SUCCESS) +- fgetpos (stream, &position); +- else +- last_use = nouse; +- } ++ /* Read lines until we get a definite result. */ ++ do ++ status = get_next_alias (stream, NULL, result, buffer, buflen, errnop); ++ while (status == NSS_STATUS_RETURN); + } + + __libc_lock_unlock (lock); +@@ -440,6 +412,7 @@ _nss_files_getaliasbyname_r (const char + { + /* Return next entry in host file. */ + enum nss_status status = NSS_STATUS_SUCCESS; ++ FILE *stream = NULL; + + if (name == NULL) + { +@@ -447,11 +420,8 @@ _nss_files_getaliasbyname_r (const char + return NSS_STATUS_UNAVAIL; + } + +- __libc_lock_lock (lock); +- +- /* Open the stream or rest it. */ +- status = internal_setent (); +- last_use = getby; ++ /* Open the stream. */ ++ status = internal_setent (&stream); + + if (status == NSS_STATUS_SUCCESS) + { +@@ -459,13 +429,11 @@ _nss_files_getaliasbyname_r (const char + + /* Read lines until we get a definite result. */ + do +- status = get_next_alias (name, result, buffer, buflen, errnop); ++ status = get_next_alias (stream, name, result, buffer, buflen, errnop); + while (status == NSS_STATUS_RETURN); + } + +- internal_endent (); +- +- __libc_lock_unlock (lock); ++ internal_endent (&stream); + + return status; + } +Index: b/nss/nss_files/files-hosts.c +=================================================================== +--- a/nss/nss_files/files-hosts.c ++++ b/nss/nss_files/files-hosts.c +@@ -120,14 +120,13 @@ _nss_files_gethostbyname3_r (const char + char *buffer, size_t buflen, int *errnop, + int *herrnop, int32_t *ttlp, char **canonp) + { ++ FILE *stream = NULL; + uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct hostent_data); + buffer += pad; + buflen = buflen > pad ? buflen - pad : 0; + +- __libc_lock_lock (lock); +- +- /* Reset file pointer to beginning or open file. */ +- enum nss_status status = internal_setent (keep_stream); ++ /* Open file. */ ++ enum nss_status status = internal_setent (&stream); + + if (status == NSS_STATUS_SUCCESS) + { +@@ -135,10 +134,7 @@ _nss_files_gethostbyname3_r (const char + addresses to IPv6 addresses really the right thing to do? */ + int flags = ((_res.options & RES_USE_INET6) ? AI_V4MAPPED : 0); + +- /* Tell getent function that we have repositioned the file pointer. */ +- last_use = getby; +- +- while ((status = internal_getent (result, buffer, buflen, errnop, ++ while ((status = internal_getent (stream, result, buffer, buflen, errnop, + herrnop, af, flags)) + == NSS_STATUS_SUCCESS) + { +@@ -165,7 +161,7 @@ _nss_files_gethostbyname3_r (const char + bufferend = (char *) &result->h_aliases[naliases + 1]; + + again: +- while ((status = internal_getent (&tmp_result_buf, tmp_buffer, ++ while ((status = internal_getent (stream, &tmp_result_buf, tmp_buffer, + tmp_buflen, errnop, herrnop, af, + flags)) + == NSS_STATUS_SUCCESS) +@@ -341,15 +337,12 @@ _nss_files_gethostbyname3_r (const char + free (tmp_buffer); + } + +- if (! keep_stream) +- internal_endent (); ++ internal_endent (&stream); + } + + if (canonp && status == NSS_STATUS_SUCCESS) + *canonp = result->h_name; + +- __libc_lock_unlock (lock); +- + return status; + } + +@@ -378,16 +371,13 @@ _nss_files_gethostbyname4_r (const char + char *buffer, size_t buflen, int *errnop, + int *herrnop, int32_t *ttlp) + { +- __libc_lock_lock (lock); ++ FILE *stream = NULL; + +- /* Reset file pointer to beginning or open file. */ +- enum nss_status status = internal_setent (keep_stream); ++ /* Open file. */ ++ enum nss_status status = internal_setent (&stream); + + if (status == NSS_STATUS_SUCCESS) + { +- /* Tell getent function that we have repositioned the file pointer. */ +- last_use = getby; +- + bool any = false; + bool got_canon = false; + while (1) +@@ -399,7 +389,7 @@ _nss_files_gethostbyname4_r (const char + buflen = buflen > pad ? buflen - pad : 0; + + struct hostent result; +- status = internal_getent (&result, buffer, buflen, errnop, ++ status = internal_getent (stream, &result, buffer, buflen, errnop, + herrnop, AF_UNSPEC, 0); + if (status != NSS_STATUS_SUCCESS) + break; +@@ -475,8 +465,7 @@ _nss_files_gethostbyname4_r (const char + status = NSS_STATUS_SUCCESS; + } + +- if (! keep_stream) +- internal_endent (); ++ internal_endent (&stream); + } + else if (status == NSS_STATUS_TRYAGAIN) + { +@@ -489,7 +478,5 @@ _nss_files_gethostbyname4_r (const char + *herrnop = HOST_NOT_FOUND; + } + +- __libc_lock_unlock (lock); +- + return status; + } diff -Nru glibc-2.21/debian/patches/any/CVE-2014-9761-1.diff glibc-2.21/debian/patches/any/CVE-2014-9761-1.diff --- glibc-2.21/debian/patches/any/CVE-2014-9761-1.diff 1970-01-01 00:00:00.000000000 +0000 +++ glibc-2.21/debian/patches/any/CVE-2014-9761-1.diff 2016-03-31 05:39:16.000000000 +0000 @@ -0,0 +1,990 @@ +From e02cabecf0d025ec4f4ddee290bdf7aadb873bb3 Mon Sep 17 00:00:00 2001 +From: Joseph Myers +Date: Tue, 24 Nov 2015 22:24:52 +0000 +Subject: [PATCH] Refactor strtod parsing of NaN payloads. + +The nan* functions handle their string argument by constructing a +NAN(...) string on the stack as a VLA and passing it to strtod +functions. + +This approach has problems discussed in bug 16961 and bug 16962: the +stack usage is unbounded, and it gives incorrect results in certain +cases where the argument is not a valid n-char-sequence. + +The natural fix for both issues is to refactor the NaN payload parsing +out of strtod into a separate function that the nan* functions can +call directly, so that no temporary string needs constructing on the +stack at all. This patch does that refactoring in preparation for +fixing those bugs (but without actually using the new functions from +nan* - which will also require exporting them from libc at version +GLIBC_PRIVATE). This patch is not intended to change any user-visible +behavior, so no tests are added (fixes for the above bugs will of +course add tests for them). + +This patch builds on my recent fixes for strtol and strtod issues in +Turkish locales. Given those fixes, the parsing of NaN payloads is +locale-independent; thus, the new functions do not need to take a +locale_t argument. + +Tested for x86_64, x86, mips64 and powerpc. + + * stdlib/strtod_nan.c: New file. + * stdlib/strtod_nan_double.h: Likewise. + * stdlib/strtod_nan_float.h: Likewise. + * stdlib/strtod_nan_main.c: Likewise. + * stdlib/strtod_nan_narrow.h: Likewise. + * stdlib/strtod_nan_wide.h: Likewise. + * stdlib/strtof_nan.c: Likewise. + * stdlib/strtold_nan.c: Likewise. + * sysdeps/ieee754/ldbl-128/strtod_nan_ldouble.h: Likewise. + * sysdeps/ieee754/ldbl-128ibm/strtod_nan_ldouble.h: Likewise. + * sysdeps/ieee754/ldbl-96/strtod_nan_ldouble.h: Likewise. + * wcsmbs/wcstod_nan.c: Likewise. + * wcsmbs/wcstof_nan.c: Likewise. + * wcsmbs/wcstold_nan.c: Likewise. + * stdlib/Makefile (routines): Add strtof_nan, strtod_nan and + strtold_nan. + * wcsmbs/Makefile (routines): Add wcstod_nan, wcstold_nan and + wcstof_nan. + * include/stdlib.h (__strtof_nan): Declare and use + libc_hidden_proto. + (__strtod_nan): Likewise. + (__strtold_nan): Likewise. + (__wcstof_nan): Likewise. + (__wcstod_nan): Likewise. + (__wcstold_nan): Likewise. + * include/wchar.h (____wcstoull_l_internal): Declare. + * stdlib/strtod_l.c: Do not include . + (____strtoull_l_internal): Remove declaration. + (STRTOF_NAN): Define macro. + (SET_MANTISSA): Remove macro. + (STRTOULL): Likewise. + (____STRTOF_INTERNAL): Use STRTOF_NAN to parse NaN payload. + * stdlib/strtof_l.c (____strtoull_l_internal): Remove declaration. + (STRTOF_NAN): Define macro. + (SET_MANTISSA): Remove macro. + * sysdeps/ieee754/ldbl-128/strtold_l.c (STRTOF_NAN): Define macro. + (SET_MANTISSA): Remove macro. + * sysdeps/ieee754/ldbl-128ibm/strtold_l.c (STRTOF_NAN): Define + macro. + (SET_MANTISSA): Remove macro. + * sysdeps/ieee754/ldbl-64-128/strtold_l.c (STRTOF_NAN): Define + macro. + (SET_MANTISSA): Remove macro. + * sysdeps/ieee754/ldbl-96/strtold_l.c (STRTOF_NAN): Define macro. + (SET_MANTISSA): Remove macro. + * wcsmbs/wcstod_l.c (____wcstoull_l_internal): Remove declaration. + * wcsmbs/wcstof_l.c (____wcstoull_l_internal): Likewise. + * wcsmbs/wcstold_l.c (____wcstoull_l_internal): Likewise. + +[Note: patch differs from upstream commit in that the entries in the +Changelog were dropped to avoid patch conflicts, and adjust +stdlib/strtod_l.c hunk 5 change to match existing code. -- sbeattie] + +--- + ChangeLog | 49 +++++++++++++++++ + include/stdlib.h | 18 ++++++ + include/wchar.h | 3 + + stdlib/Makefile | 1 + + stdlib/strtod_l.c | 48 +++------------- + stdlib/strtod_nan.c | 24 ++++++++ + stdlib/strtod_nan_double.h | 30 ++++++++++ + stdlib/strtod_nan_float.h | 29 ++++++++++ + stdlib/strtod_nan_main.c | 63 ++++++++++++++++++++++ + stdlib/strtod_nan_narrow.h | 22 ++++++++ + stdlib/strtod_nan_wide.h | 22 ++++++++ + stdlib/strtof_l.c | 11 +--- + stdlib/strtof_nan.c | 24 ++++++++ + stdlib/strtold_nan.c | 30 ++++++++++ + sysdeps/ieee754/ldbl-128/strtod_nan_ldouble.h | 33 +++++++++++ + sysdeps/ieee754/ldbl-128/strtold_l.c | 13 +---- + sysdeps/ieee754/ldbl-128ibm/strtod_nan_ldouble.h | 30 ++++++++++ + sysdeps/ieee754/ldbl-128ibm/strtold_l.c | 10 +--- + sysdeps/ieee754/ldbl-64-128/strtold_l.c | 13 +---- + sysdeps/ieee754/ldbl-96/strtod_nan_ldouble.h | 30 ++++++++++ + sysdeps/ieee754/ldbl-96/strtold_l.c | 10 +--- + wcsmbs/Makefile | 1 + + wcsmbs/wcstod_l.c | 3 - + wcsmbs/wcstod_nan.c | 23 ++++++++ + wcsmbs/wcstof_l.c | 3 - + wcsmbs/wcstof_nan.c | 23 ++++++++ + wcsmbs/wcstold_l.c | 3 - + wcsmbs/wcstold_nan.c | 30 ++++++++++ + 28 files changed, 504 insertions(+), 95 deletions(-) + create mode 100644 stdlib/strtod_nan.c + create mode 100644 stdlib/strtod_nan_double.h + create mode 100644 stdlib/strtod_nan_float.h + create mode 100644 stdlib/strtod_nan_main.c + create mode 100644 stdlib/strtod_nan_narrow.h + create mode 100644 stdlib/strtod_nan_wide.h + create mode 100644 stdlib/strtof_nan.c + create mode 100644 stdlib/strtold_nan.c + create mode 100644 sysdeps/ieee754/ldbl-128/strtod_nan_ldouble.h + create mode 100644 sysdeps/ieee754/ldbl-128ibm/strtod_nan_ldouble.h + create mode 100644 sysdeps/ieee754/ldbl-96/strtod_nan_ldouble.h + create mode 100644 wcsmbs/wcstod_nan.c + create mode 100644 wcsmbs/wcstof_nan.c + create mode 100644 wcsmbs/wcstold_nan.c + +diff --git a/include/stdlib.h b/include/stdlib.h +index dcb83a5..352339e 100644 +--- a/include/stdlib.h ++++ b/include/stdlib.h +@@ -203,6 +203,24 @@ libc_hidden_proto (strtoll) + libc_hidden_proto (strtoul) + libc_hidden_proto (strtoull) + ++extern float __strtof_nan (const char *, char **, char) internal_function; ++extern double __strtod_nan (const char *, char **, char) internal_function; ++extern long double __strtold_nan (const char *, char **, char) ++ internal_function; ++extern float __wcstof_nan (const wchar_t *, wchar_t **, wchar_t) ++ internal_function; ++extern double __wcstod_nan (const wchar_t *, wchar_t **, wchar_t) ++ internal_function; ++extern long double __wcstold_nan (const wchar_t *, wchar_t **, wchar_t) ++ internal_function; ++ ++libc_hidden_proto (__strtof_nan) ++libc_hidden_proto (__strtod_nan) ++libc_hidden_proto (__strtold_nan) ++libc_hidden_proto (__wcstof_nan) ++libc_hidden_proto (__wcstod_nan) ++libc_hidden_proto (__wcstold_nan) ++ + extern char *__ecvt (double __value, int __ndigit, int *__restrict __decpt, + int *__restrict __sign); + extern char *__fcvt (double __value, int __ndigit, int *__restrict __decpt, +diff --git a/include/wchar.h b/include/wchar.h +index 67d0248..0f33d09 100644 +--- a/include/wchar.h ++++ b/include/wchar.h +@@ -52,6 +52,9 @@ extern unsigned long long int __wcstoull_internal (const wchar_t * + __restrict __endptr, + int __base, + int __group) __THROW; ++extern unsigned long long int ____wcstoull_l_internal (const wchar_t *, ++ wchar_t **, int, int, ++ __locale_t); + libc_hidden_proto (__wcstof_internal) + libc_hidden_proto (__wcstod_internal) + libc_hidden_proto (__wcstold_internal) +diff --git a/stdlib/Makefile b/stdlib/Makefile +index 10d9406..d7ae165 100644 +--- a/stdlib/Makefile ++++ b/stdlib/Makefile +@@ -50,6 +50,7 @@ routines := \ + strtol_l strtoul_l strtoll_l strtoull_l \ + strtof strtod strtold \ + strtof_l strtod_l strtold_l \ ++ strtof_nan strtod_nan strtold_nan \ + system canonicalize \ + a64l l64a \ + rpmatch strfmon strfmon_l getsubopt xpg_basename fmtmsg \ +diff --git a/stdlib/strtod_l.c b/stdlib/strtod_l.c +index 7307d98..2169291 100644 +--- a/stdlib/strtod_l.c ++++ b/stdlib/strtod_l.c +@@ -20,8 +20,6 @@ + #include + + extern double ____strtod_l_internal (const char *, char **, int, __locale_t); +-extern unsigned long long int ____strtoull_l_internal (const char *, char **, +- int, int, __locale_t); + + /* Configuration part. These macros are defined by `strtold.c', + `strtof.c', `wcstod.c', `wcstold.c', and `wcstof.c' to produce the +@@ -33,27 +31,20 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **, + # ifdef USE_WIDE_CHAR + # define STRTOF wcstod_l + # define __STRTOF __wcstod_l ++# define STRTOF_NAN __wcstod_nan + # else + # define STRTOF strtod_l + # define __STRTOF __strtod_l ++# define STRTOF_NAN __strtod_nan + # endif + # define MPN2FLOAT __mpn_construct_double + # define FLOAT_HUGE_VAL HUGE_VAL +-# define SET_MANTISSA(flt, mant) \ +- do { union ieee754_double u; \ +- u.d = (flt); \ +- u.ieee_nan.mantissa0 = (mant) >> 32; \ +- u.ieee_nan.mantissa1 = (mant); \ +- if ((u.ieee.mantissa0 | u.ieee.mantissa1) != 0) \ +- (flt) = u.d; \ +- } while (0) + #endif + /* End of configuration part. */ + + #include + #include + #include +-#include + #include "../locale/localeinfo.h" + #include + #include +@@ -105,7 +96,6 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **, + # define TOLOWER_C(Ch) __towlower_l ((Ch), _nl_C_locobj_ptr) + # define STRNCASECMP(S1, S2, N) \ + __wcsncasecmp_l ((S1), (S2), (N), _nl_C_locobj_ptr) +-# define STRTOULL(S, E, B) ____wcstoull_l_internal ((S), (E), (B), 0, loc) + #else + # define STRING_TYPE char + # define CHAR_TYPE char +@@ -117,7 +107,6 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **, + # define TOLOWER_C(Ch) __tolower_l ((Ch), _nl_C_locobj_ptr) + # define STRNCASECMP(S1, S2, N) \ + __strncasecmp_l ((S1), (S2), (N), _nl_C_locobj_ptr) +-# define STRTOULL(S, E, B) ____strtoull_l_internal ((S), (E), (B), 0, loc) + #endif + + +@@ -649,33 +638,14 @@ ____STRTOF_INTERNAL (const STRING_TYPE *nptr, STRING_TYPE **endptr, int group, + if (*cp == L_('(')) + { + const STRING_TYPE *startp = cp; +- do +- ++cp; +- while ((*cp >= L_('0') && *cp <= L_('9')) +- || ({ CHAR_TYPE lo = TOLOWER (*cp); +- lo >= L_('a') && lo <= L_('z'); }) +- || *cp == L_('_')); +- +- if (*cp != L_(')')) +- /* The closing brace is missing. Only match the NAN +- part. */ +- cp = startp; ++ STRING_TYPE *endp; ++ retval = STRTOF_NAN (cp + 1, &endp, L_(')')); ++ if (*endp == L_(')')) ++ /* Consume the closing parenthesis. */ ++ cp = endp + 1; + else +- { +- /* This is a system-dependent way to specify the +- bitmask used for the NaN. We expect it to be +- a number which is put in the mantissa of the +- number. */ +- STRING_TYPE *endp; +- unsigned long long int mant; +- +- mant = STRTOULL (startp + 1, &endp, 0); +- if (endp == cp) +- SET_MANTISSA (retval, mant); +- +- /* Consume the closing brace. */ +- ++cp; +- } ++ /* Only match the NAN part. */ ++ cp = startp; + } + + if (endptr != NULL) +diff --git a/stdlib/strtod_nan.c b/stdlib/strtod_nan.c +new file mode 100644 +index 0000000..2a0a89f +--- /dev/null ++++ b/stdlib/strtod_nan.c +@@ -0,0 +1,24 @@ ++/* Convert string for NaN payload to corresponding NaN. Narrow ++ strings, double. ++ 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 ++#include ++ ++#define STRTOD_NAN __strtod_nan ++#include +diff --git a/stdlib/strtod_nan_double.h b/stdlib/strtod_nan_double.h +new file mode 100644 +index 0000000..f5bdb03 +--- /dev/null ++++ b/stdlib/strtod_nan_double.h +@@ -0,0 +1,30 @@ ++/* Convert string for NaN payload to corresponding NaN. For double. ++ Copyright (C) 1997-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 ++ . */ ++ ++#define FLOAT double ++#define SET_MANTISSA(flt, mant) \ ++ do \ ++ { \ ++ union ieee754_double u; \ ++ u.d = (flt); \ ++ u.ieee_nan.mantissa0 = (mant) >> 32; \ ++ u.ieee_nan.mantissa1 = (mant); \ ++ if ((u.ieee.mantissa0 | u.ieee.mantissa1) != 0) \ ++ (flt) = u.d; \ ++ } \ ++ while (0) +diff --git a/stdlib/strtod_nan_float.h b/stdlib/strtod_nan_float.h +new file mode 100644 +index 0000000..4c52de8 +--- /dev/null ++++ b/stdlib/strtod_nan_float.h +@@ -0,0 +1,29 @@ ++/* Convert string for NaN payload to corresponding NaN. For float. ++ Copyright (C) 1997-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 ++ . */ ++ ++#define FLOAT float ++#define SET_MANTISSA(flt, mant) \ ++ do \ ++ { \ ++ union ieee754_float u; \ ++ u.f = (flt); \ ++ u.ieee_nan.mantissa = (mant); \ ++ if (u.ieee.mantissa != 0) \ ++ (flt) = u.f; \ ++ } \ ++ while (0) +diff --git a/stdlib/strtod_nan_main.c b/stdlib/strtod_nan_main.c +new file mode 100644 +index 0000000..bc37a63 +--- /dev/null ++++ b/stdlib/strtod_nan_main.c +@@ -0,0 +1,63 @@ ++/* Convert string for NaN payload to corresponding NaN. ++ Copyright (C) 1997-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 ++#include ++#include ++#include ++#include ++ ++ ++/* If STR starts with an optional n-char-sequence as defined by ISO C ++ (a sequence of ASCII letters, digits and underscores), followed by ++ ENDC, return a NaN whose payload is set based on STR. Otherwise, ++ return a default NAN. If ENDPTR is not NULL, set *ENDPTR to point ++ to the character after the initial n-char-sequence. */ ++ ++internal_function ++FLOAT ++STRTOD_NAN (const STRING_TYPE *str, STRING_TYPE **endptr, STRING_TYPE endc) ++{ ++ const STRING_TYPE *cp = str; ++ ++ while ((*cp >= L_('0') && *cp <= L_('9')) ++ || (*cp >= L_('A') && *cp <= L_('Z')) ++ || (*cp >= L_('a') && *cp <= L_('z')) ++ || *cp == L_('_')) ++ ++cp; ++ ++ FLOAT retval = NAN; ++ if (*cp != endc) ++ goto out; ++ ++ /* This is a system-dependent way to specify the bitmask used for ++ the NaN. We expect it to be a number which is put in the ++ mantissa of the number. */ ++ STRING_TYPE *endp; ++ unsigned long long int mant; ++ ++ mant = STRTOULL (str, &endp, 0); ++ if (endp == cp) ++ SET_MANTISSA (retval, mant); ++ ++ out: ++ if (endptr != NULL) ++ *endptr = (STRING_TYPE *) cp; ++ return retval; ++} ++libc_hidden_def (STRTOD_NAN) +diff --git a/stdlib/strtod_nan_narrow.h b/stdlib/strtod_nan_narrow.h +new file mode 100644 +index 0000000..bd77045 +--- /dev/null ++++ b/stdlib/strtod_nan_narrow.h +@@ -0,0 +1,22 @@ ++/* Convert string for NaN payload to corresponding NaN. Narrow strings. ++ Copyright (C) 1997-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 ++ . */ ++ ++#define STRING_TYPE char ++#define L_(Ch) Ch ++#define STRTOULL(S, E, B) ____strtoull_l_internal ((S), (E), (B), 0, \ ++ _nl_C_locobj_ptr) +diff --git a/stdlib/strtod_nan_wide.h b/stdlib/strtod_nan_wide.h +new file mode 100644 +index 0000000..783fbf4 +--- /dev/null ++++ b/stdlib/strtod_nan_wide.h +@@ -0,0 +1,22 @@ ++/* Convert string for NaN payload to corresponding NaN. Wide strings. ++ Copyright (C) 1997-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 ++ . */ ++ ++#define STRING_TYPE wchar_t ++#define L_(Ch) L##Ch ++#define STRTOULL(S, E, B) ____wcstoull_l_internal ((S), (E), (B), 0, \ ++ _nl_C_locobj_ptr) +diff --git a/stdlib/strtof_l.c b/stdlib/strtof_l.c +index 2a8646a..491256f 100644 +--- a/stdlib/strtof_l.c ++++ b/stdlib/strtof_l.c +@@ -20,26 +20,19 @@ + #include + + extern float ____strtof_l_internal (const char *, char **, int, __locale_t); +-extern unsigned long long int ____strtoull_l_internal (const char *, char **, +- int, int, __locale_t); + + #define FLOAT float + #define FLT FLT + #ifdef USE_WIDE_CHAR + # define STRTOF wcstof_l + # define __STRTOF __wcstof_l ++# define STRTOF_NAN __wcstof_nan + #else + # define STRTOF strtof_l + # define __STRTOF __strtof_l ++# define STRTOF_NAN __strtof_nan + #endif + #define MPN2FLOAT __mpn_construct_float + #define FLOAT_HUGE_VAL HUGE_VALF +-#define SET_MANTISSA(flt, mant) \ +- do { union ieee754_float u; \ +- u.f = (flt); \ +- u.ieee_nan.mantissa = (mant); \ +- if (u.ieee.mantissa != 0) \ +- (flt) = u.f; \ +- } while (0) + + #include "strtod_l.c" +diff --git a/stdlib/strtof_nan.c b/stdlib/strtof_nan.c +new file mode 100644 +index 0000000..b971310 +--- /dev/null ++++ b/stdlib/strtof_nan.c +@@ -0,0 +1,24 @@ ++/* Convert string for NaN payload to corresponding NaN. Narrow ++ strings, float. ++ 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 ++#include ++ ++#define STRTOD_NAN __strtof_nan ++#include +diff --git a/stdlib/strtold_nan.c b/stdlib/strtold_nan.c +new file mode 100644 +index 0000000..dd43032 +--- /dev/null ++++ b/stdlib/strtold_nan.c +@@ -0,0 +1,30 @@ ++/* Convert string for NaN payload to corresponding NaN. Narrow ++ strings, long double. ++ 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 ++ ++/* This function is unused if long double and double have the same ++ representation. */ ++#ifndef __NO_LONG_DOUBLE_MATH ++# include ++# include ++ ++# define STRTOD_NAN __strtold_nan ++# include ++#endif +diff --git a/sysdeps/ieee754/ldbl-128/strtod_nan_ldouble.h b/sysdeps/ieee754/ldbl-128/strtod_nan_ldouble.h +new file mode 100644 +index 0000000..e0da4e2 +--- /dev/null ++++ b/sysdeps/ieee754/ldbl-128/strtod_nan_ldouble.h +@@ -0,0 +1,33 @@ ++/* Convert string for NaN payload to corresponding NaN. For ldbl-128. ++ Copyright (C) 1997-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 ++ . */ ++ ++#define FLOAT long double ++#define SET_MANTISSA(flt, mant) \ ++ do \ ++ { \ ++ union ieee854_long_double u; \ ++ u.d = (flt); \ ++ u.ieee_nan.mantissa0 = 0; \ ++ u.ieee_nan.mantissa1 = 0; \ ++ u.ieee_nan.mantissa2 = (mant) >> 32; \ ++ u.ieee_nan.mantissa3 = (mant); \ ++ if ((u.ieee.mantissa0 | u.ieee.mantissa1 \ ++ | u.ieee.mantissa2 | u.ieee.mantissa3) != 0) \ ++ (flt) = u.d; \ ++ } \ ++ while (0) +diff --git a/sysdeps/ieee754/ldbl-128/strtold_l.c b/sysdeps/ieee754/ldbl-128/strtold_l.c +index d1ae57e..0b2ed27 100644 +--- a/sysdeps/ieee754/ldbl-128/strtold_l.c ++++ b/sysdeps/ieee754/ldbl-128/strtold_l.c +@@ -25,22 +25,13 @@ + #ifdef USE_WIDE_CHAR + # define STRTOF wcstold_l + # define __STRTOF __wcstold_l ++# define STRTOF_NAN __wcstold_nan + #else + # define STRTOF strtold_l + # define __STRTOF __strtold_l ++# define STRTOF_NAN __strtold_nan + #endif + #define MPN2FLOAT __mpn_construct_long_double + #define FLOAT_HUGE_VAL HUGE_VALL +-#define SET_MANTISSA(flt, mant) \ +- do { union ieee854_long_double u; \ +- u.d = (flt); \ +- u.ieee_nan.mantissa0 = 0; \ +- u.ieee_nan.mantissa1 = 0; \ +- u.ieee_nan.mantissa2 = (mant) >> 32; \ +- u.ieee_nan.mantissa3 = (mant); \ +- if ((u.ieee.mantissa0 | u.ieee.mantissa1 \ +- | u.ieee.mantissa2 | u.ieee.mantissa3) != 0) \ +- (flt) = u.d; \ +- } while (0) + + #include +diff --git a/sysdeps/ieee754/ldbl-128ibm/strtod_nan_ldouble.h b/sysdeps/ieee754/ldbl-128ibm/strtod_nan_ldouble.h +new file mode 100644 +index 0000000..876a4bb +--- /dev/null ++++ b/sysdeps/ieee754/ldbl-128ibm/strtod_nan_ldouble.h +@@ -0,0 +1,30 @@ ++/* Convert string for NaN payload to corresponding NaN. For ldbl-128ibm. ++ Copyright (C) 1997-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 ++ . */ ++ ++#define FLOAT long double ++#define SET_MANTISSA(flt, mant) \ ++ do \ ++ { \ ++ union ibm_extended_long_double u; \ ++ u.ld = (flt); \ ++ u.d[0].ieee_nan.mantissa0 = (mant) >> 32; \ ++ u.d[0].ieee_nan.mantissa1 = (mant); \ ++ if ((u.d[0].ieee.mantissa0 | u.d[0].ieee.mantissa1) != 0) \ ++ (flt) = u.ld; \ ++ } \ ++ while (0) +diff --git a/sysdeps/ieee754/ldbl-128ibm/strtold_l.c b/sysdeps/ieee754/ldbl-128ibm/strtold_l.c +index 3e2f69e..6cd963b 100644 +--- a/sysdeps/ieee754/ldbl-128ibm/strtold_l.c ++++ b/sysdeps/ieee754/ldbl-128ibm/strtold_l.c +@@ -30,25 +30,19 @@ extern long double ____new_wcstold_l (const wchar_t *, wchar_t **, __locale_t); + # define STRTOF __new_wcstold_l + # define __STRTOF ____new_wcstold_l + # define ____STRTOF_INTERNAL ____wcstold_l_internal ++# define STRTOF_NAN __wcstold_nan + #else + extern long double ____new_strtold_l (const char *, char **, __locale_t); + # define STRTOF __new_strtold_l + # define __STRTOF ____new_strtold_l + # define ____STRTOF_INTERNAL ____strtold_l_internal ++# define STRTOF_NAN __strtold_nan + #endif + extern __typeof (__STRTOF) STRTOF; + libc_hidden_proto (__STRTOF) + libc_hidden_proto (STRTOF) + #define MPN2FLOAT __mpn_construct_long_double + #define FLOAT_HUGE_VAL HUGE_VALL +-# define SET_MANTISSA(flt, mant) \ +- do { union ibm_extended_long_double u; \ +- u.ld = (flt); \ +- u.d[0].ieee_nan.mantissa0 = (mant) >> 32; \ +- u.d[0].ieee_nan.mantissa1 = (mant); \ +- if ((u.d[0].ieee.mantissa0 | u.d[0].ieee.mantissa1) != 0) \ +- (flt) = u.ld; \ +- } while (0) + + #include + +diff --git a/sysdeps/ieee754/ldbl-64-128/strtold_l.c b/sysdeps/ieee754/ldbl-64-128/strtold_l.c +index 3944a43..6cd963b 100644 +--- a/sysdeps/ieee754/ldbl-64-128/strtold_l.c ++++ b/sysdeps/ieee754/ldbl-64-128/strtold_l.c +@@ -30,28 +30,19 @@ extern long double ____new_wcstold_l (const wchar_t *, wchar_t **, __locale_t); + # define STRTOF __new_wcstold_l + # define __STRTOF ____new_wcstold_l + # define ____STRTOF_INTERNAL ____wcstold_l_internal ++# define STRTOF_NAN __wcstold_nan + #else + extern long double ____new_strtold_l (const char *, char **, __locale_t); + # define STRTOF __new_strtold_l + # define __STRTOF ____new_strtold_l + # define ____STRTOF_INTERNAL ____strtold_l_internal ++# define STRTOF_NAN __strtold_nan + #endif + extern __typeof (__STRTOF) STRTOF; + libc_hidden_proto (__STRTOF) + libc_hidden_proto (STRTOF) + #define MPN2FLOAT __mpn_construct_long_double + #define FLOAT_HUGE_VAL HUGE_VALL +-#define SET_MANTISSA(flt, mant) \ +- do { union ieee854_long_double u; \ +- u.d = (flt); \ +- u.ieee_nan.mantissa0 = 0; \ +- u.ieee_nan.mantissa1 = 0; \ +- u.ieee_nan.mantissa2 = (mant) >> 32; \ +- u.ieee_nan.mantissa3 = (mant); \ +- if ((u.ieee.mantissa0 | u.ieee.mantissa1 \ +- | u.ieee.mantissa2 | u.ieee.mantissa3) != 0) \ +- (flt) = u.d; \ +- } while (0) + + #include + +diff --git a/sysdeps/ieee754/ldbl-96/strtod_nan_ldouble.h b/sysdeps/ieee754/ldbl-96/strtod_nan_ldouble.h +new file mode 100644 +index 0000000..6f03359 +--- /dev/null ++++ b/sysdeps/ieee754/ldbl-96/strtod_nan_ldouble.h +@@ -0,0 +1,30 @@ ++/* Convert string for NaN payload to corresponding NaN. For ldbl-96. ++ Copyright (C) 1997-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 ++ . */ ++ ++#define FLOAT long double ++#define SET_MANTISSA(flt, mant) \ ++ do \ ++ { \ ++ union ieee854_long_double u; \ ++ u.d = (flt); \ ++ u.ieee_nan.mantissa0 = (mant) >> 32; \ ++ u.ieee_nan.mantissa1 = (mant); \ ++ if ((u.ieee.mantissa0 | u.ieee.mantissa1) != 0) \ ++ (flt) = u.d; \ ++ } \ ++ while (0) +diff --git a/sysdeps/ieee754/ldbl-96/strtold_l.c b/sysdeps/ieee754/ldbl-96/strtold_l.c +index c082e74..db92242 100644 +--- a/sysdeps/ieee754/ldbl-96/strtold_l.c ++++ b/sysdeps/ieee754/ldbl-96/strtold_l.c +@@ -25,19 +25,13 @@ + #ifdef USE_WIDE_CHAR + # define STRTOF wcstold_l + # define __STRTOF __wcstold_l ++# define STRTOF_NAN __wcstold_nan + #else + # define STRTOF strtold_l + # define __STRTOF __strtold_l ++# define STRTOF_NAN __strtold_nan + #endif + #define MPN2FLOAT __mpn_construct_long_double + #define FLOAT_HUGE_VAL HUGE_VALL +-#define SET_MANTISSA(flt, mant) \ +- do { union ieee854_long_double u; \ +- u.d = (flt); \ +- u.ieee_nan.mantissa0 = (mant) >> 32; \ +- u.ieee_nan.mantissa1 = (mant); \ +- if ((u.ieee.mantissa0 | u.ieee.mantissa1) != 0) \ +- (flt) = u.d; \ +- } while (0) + + #include +diff --git a/wcsmbs/Makefile b/wcsmbs/Makefile +index 773cfdb..e5de439 100644 +--- a/wcsmbs/Makefile ++++ b/wcsmbs/Makefile +@@ -33,6 +33,7 @@ routines := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \ + wcstol wcstoul wcstoll wcstoull wcstod wcstold wcstof \ + wcstol_l wcstoul_l wcstoll_l wcstoull_l \ + wcstod_l wcstold_l wcstof_l \ ++ wcstod_nan wcstold_nan wcstof_nan \ + wcscoll wcsxfrm \ + wcwidth wcswidth \ + wcscoll_l wcsxfrm_l \ +diff --git a/wcsmbs/wcstod_l.c b/wcsmbs/wcstod_l.c +index 9c026d8..0fe820c 100644 +--- a/wcsmbs/wcstod_l.c ++++ b/wcsmbs/wcstod_l.c +@@ -23,9 +23,6 @@ + + extern double ____wcstod_l_internal (const wchar_t *, wchar_t **, int, + __locale_t); +-extern unsigned long long int ____wcstoull_l_internal (const wchar_t *, +- wchar_t **, int, int, +- __locale_t); + + #define USE_WIDE_CHAR 1 + +diff --git a/wcsmbs/wcstod_nan.c b/wcsmbs/wcstod_nan.c +new file mode 100644 +index 0000000..b3dd6af +--- /dev/null ++++ b/wcsmbs/wcstod_nan.c +@@ -0,0 +1,23 @@ ++/* Convert string for NaN payload to corresponding NaN. Wide strings, double. ++ 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 "../stdlib/strtod_nan_wide.h" ++#include "../stdlib/strtod_nan_double.h" ++ ++#define STRTOD_NAN __wcstod_nan ++#include "../stdlib/strtod_nan_main.c" +diff --git a/wcsmbs/wcstof_l.c b/wcsmbs/wcstof_l.c +index bcf9834..392ea49 100644 +--- a/wcsmbs/wcstof_l.c ++++ b/wcsmbs/wcstof_l.c +@@ -25,8 +25,5 @@ + + extern float ____wcstof_l_internal (const wchar_t *, wchar_t **, int, + __locale_t); +-extern unsigned long long int ____wcstoull_l_internal (const wchar_t *, +- wchar_t **, int, int, +- __locale_t); + + #include +diff --git a/wcsmbs/wcstof_nan.c b/wcsmbs/wcstof_nan.c +new file mode 100644 +index 0000000..c5f667a +--- /dev/null ++++ b/wcsmbs/wcstof_nan.c +@@ -0,0 +1,23 @@ ++/* Convert string for NaN payload to corresponding NaN. Wide strings, float. ++ 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 "../stdlib/strtod_nan_wide.h" ++#include "../stdlib/strtod_nan_float.h" ++ ++#define STRTOD_NAN __wcstof_nan ++#include "../stdlib/strtod_nan_main.c" +diff --git a/wcsmbs/wcstold_l.c b/wcsmbs/wcstold_l.c +index 8df93af..f5d0554 100644 +--- a/wcsmbs/wcstold_l.c ++++ b/wcsmbs/wcstold_l.c +@@ -24,8 +24,5 @@ + + extern long double ____wcstold_l_internal (const wchar_t *, wchar_t **, int, + __locale_t); +-extern unsigned long long int ____wcstoull_l_internal (const wchar_t *, +- wchar_t **, int, int, +- __locale_t); + + #include +diff --git a/wcsmbs/wcstold_nan.c b/wcsmbs/wcstold_nan.c +new file mode 100644 +index 0000000..ef905d3 +--- /dev/null ++++ b/wcsmbs/wcstold_nan.c +@@ -0,0 +1,30 @@ ++/* Convert string for NaN payload to corresponding NaN. Wide strings, ++ long double. ++ 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 ++ ++/* This function is unused if long double and double have the same ++ representation. */ ++#ifndef __NO_LONG_DOUBLE_MATH ++# include "../stdlib/strtod_nan_wide.h" ++# include ++ ++# define STRTOD_NAN __wcstold_nan ++# include "../stdlib/strtod_nan_main.c" ++#endif +-- +1.7.1 + diff -Nru glibc-2.21/debian/patches/any/CVE-2014-9761-2.diff glibc-2.21/debian/patches/any/CVE-2014-9761-2.diff --- glibc-2.21/debian/patches/any/CVE-2014-9761-2.diff 1970-01-01 00:00:00.000000000 +0000 +++ glibc-2.21/debian/patches/any/CVE-2014-9761-2.diff 2016-03-31 21:28:18.000000000 +0000 @@ -0,0 +1,337 @@ +From 8f5e8b01a1da2a207228f2072c934fa5918554b8 Mon Sep 17 00:00:00 2001 +From: Joseph Myers +Date: Fri, 4 Dec 2015 20:36:28 +0000 +Subject: [PATCH] Fix nan functions handling of payload strings (bug 16961, bug 16962). + +The nan, nanf and nanl functions handle payload strings by doing e.g.: + + if (tagp[0] != '\0') + { + char buf[6 + strlen (tagp)]; + sprintf (buf, "NAN(%s)", tagp); + return strtod (buf, NULL); + } + +This is an unbounded stack allocation based on the length of the +argument. Furthermore, if the argument starts with an n-char-sequence +followed by ')', that n-char-sequence is wrongly treated as +significant for determining the payload of the resulting NaN, when ISO +C says the call should be equivalent to strtod ("NAN", NULL), without +being affected by that initial n-char-sequence. This patch fixes both +those problems by using the __strtod_nan etc. functions recently +factored out of strtod etc. for that purpose, with those functions +being exported from libc at version GLIBC_PRIVATE. + +Tested for x86_64, x86, mips64 and powerpc. + + [BZ #16961] + [BZ #16962] + * math/s_nan.c (__nan): Use __strtod_nan instead of constructing a + string on the stack for strtod. + * math/s_nanf.c (__nanf): Use __strtof_nan instead of constructing + a string on the stack for strtof. + * math/s_nanl.c (__nanl): Use __strtold_nan instead of + constructing a string on the stack for strtold. + * stdlib/Versions (libc): Add __strtof_nan, __strtod_nan and + __strtold_nan to GLIBC_PRIVATE. + * math/test-nan-overflow.c: New file. + * math/test-nan-payload.c: Likewise. + * math/Makefile (tests): Add test-nan-overflow and + test-nan-payload. + +[Note: patch differs from upstream commit in that the entries in +the Changelog and NEWS were dropped to avoid patch conflicts. Also, +math/Makefile patch was modified to compensate for missing tests. + -- sbeattie] + +--- + math/Makefile | 1 + math/s_nan.c | 9 --- + math/s_nanf.c | 9 --- + math/s_nanl.c | 9 --- + math/test-nan-overflow.c | 66 +++++++++++++++++++++++++ + math/test-nan-payload.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++ + stdlib/Versions | 1 + 7 files changed, 193 insertions(+), 24 deletions(-) + create mode 100644 math/test-nan-overflow.c + create mode 100644 math/test-nan-payload.c + +Index: b/math/Makefile +=================================================================== +--- a/math/Makefile ++++ b/math/Makefile +@@ -91,6 +91,7 @@ tests = test-matherr test-fenv atest-exp + test-tgmath-ret bug-nextafter bug-nexttoward bug-tgmath1 \ + test-tgmath-int test-powl tst-CMPLX tst-CMPLX2 test-snan \ + test-fenv-tls test-fenv-preserve test-fenv-return test-fenvinline \ ++ test-nan-overflow test-nan-payload \ + $(tests-static) + tests-static = test-fpucw-static test-fpucw-ieee-static + # We do the `long double' tests only if this data type is available. +Index: b/math/s_nan.c +=================================================================== +--- a/math/s_nan.c ++++ b/math/s_nan.c +@@ -28,14 +28,7 @@ + double + __nan (const char *tagp) + { +- if (tagp[0] != '\0') +- { +- char buf[6 + strlen (tagp)]; +- sprintf (buf, "NAN(%s)", tagp); +- return strtod (buf, NULL); +- } +- +- return NAN; ++ return __strtod_nan (tagp, NULL, 0); + } + weak_alias (__nan, nan) + #ifdef NO_LONG_DOUBLE +Index: b/math/s_nanf.c +=================================================================== +--- a/math/s_nanf.c ++++ b/math/s_nanf.c +@@ -28,13 +28,6 @@ + float + __nanf (const char *tagp) + { +- if (tagp[0] != '\0') +- { +- char buf[6 + strlen (tagp)]; +- sprintf (buf, "NAN(%s)", tagp); +- return strtof (buf, NULL); +- } +- +- return NAN; ++ return __strtof_nan (tagp, NULL, 0); + } + weak_alias (__nanf, nanf) +Index: b/math/s_nanl.c +=================================================================== +--- a/math/s_nanl.c ++++ b/math/s_nanl.c +@@ -28,13 +28,6 @@ + long double + __nanl (const char *tagp) + { +- if (tagp[0] != '\0') +- { +- char buf[6 + strlen (tagp)]; +- sprintf (buf, "NAN(%s)", tagp); +- return strtold (buf, NULL); +- } +- +- return NAN; ++ return __strtold_nan (tagp, NULL, 0); + } + weak_alias (__nanl, nanl) +Index: b/math/test-nan-overflow.c +=================================================================== +--- /dev/null ++++ b/math/test-nan-overflow.c +@@ -0,0 +1,66 @@ ++/* Test nan functions stack overflow (bug 16962). ++ 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 ++#include ++#include ++#include ++ ++#define STACK_LIM 1048576 ++#define STRING_SIZE (2 * STACK_LIM) ++ ++static int ++do_test (void) ++{ ++ int result = 0; ++ struct rlimit lim; ++ getrlimit (RLIMIT_STACK, &lim); ++ lim.rlim_cur = STACK_LIM; ++ setrlimit (RLIMIT_STACK, &lim); ++ char *nanstr = malloc (STRING_SIZE); ++ if (nanstr == NULL) ++ { ++ puts ("malloc failed, cannot test"); ++ return 77; ++ } ++ memset (nanstr, '0', STRING_SIZE - 1); ++ nanstr[STRING_SIZE - 1] = 0; ++#define NAN_TEST(TYPE, FUNC) \ ++ do \ ++ { \ ++ char *volatile p = nanstr; \ ++ volatile TYPE v = FUNC (p); \ ++ if (isnan (v)) \ ++ puts ("PASS: " #FUNC); \ ++ else \ ++ { \ ++ puts ("FAIL: " #FUNC); \ ++ result = 1; \ ++ } \ ++ } \ ++ while (0) ++ NAN_TEST (float, nanf); ++ NAN_TEST (double, nan); ++#ifndef NO_LONG_DOUBLE ++ NAN_TEST (long double, nanl); ++#endif ++ return result; ++} ++ ++#define TEST_FUNCTION do_test () ++#include "../test-skeleton.c" +Index: b/math/test-nan-payload.c +=================================================================== +--- /dev/null ++++ b/math/test-nan-payload.c +@@ -0,0 +1,122 @@ ++/* Test nan functions payload handling (bug 16961). ++ 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 ++#include ++#include ++#include ++#include ++ ++/* Avoid built-in functions. */ ++#define WRAP_NAN(FUNC, STR) \ ++ ({ const char *volatile wns = (STR); FUNC (wns); }) ++#define WRAP_STRTO(FUNC, STR) \ ++ ({ const char *volatile wss = (STR); FUNC (wss, NULL); }) ++ ++#define CHECK_IS_NAN(TYPE, A) \ ++ do \ ++ { \ ++ if (isnan (A)) \ ++ puts ("PASS: " #TYPE " " #A); \ ++ else \ ++ { \ ++ puts ("FAIL: " #TYPE " " #A); \ ++ result = 1; \ ++ } \ ++ } \ ++ while (0) ++ ++#define CHECK_SAME_NAN(TYPE, A, B) \ ++ do \ ++ { \ ++ if (memcmp (&(A), &(B), sizeof (A)) == 0) \ ++ puts ("PASS: " #TYPE " " #A " = " #B); \ ++ else \ ++ { \ ++ puts ("FAIL: " #TYPE " " #A " = " #B); \ ++ result = 1; \ ++ } \ ++ } \ ++ while (0) ++ ++#define CHECK_DIFF_NAN(TYPE, A, B) \ ++ do \ ++ { \ ++ if (memcmp (&(A), &(B), sizeof (A)) != 0) \ ++ puts ("PASS: " #TYPE " " #A " != " #B); \ ++ else \ ++ { \ ++ puts ("FAIL: " #TYPE " " #A " != " #B); \ ++ result = 1; \ ++ } \ ++ } \ ++ while (0) ++ ++/* Cannot test payloads by memcmp for formats where NaNs have padding ++ bits. */ ++#define CAN_TEST_EQ(MANT_DIG) ((MANT_DIG) != 64 && (MANT_DIG) != 106) ++ ++#define RUN_TESTS(TYPE, SFUNC, FUNC, MANT_DIG) \ ++ do \ ++ { \ ++ TYPE n123 = WRAP_NAN (FUNC, "123"); \ ++ CHECK_IS_NAN (TYPE, n123); \ ++ TYPE s123 = WRAP_STRTO (SFUNC, "NAN(123)"); \ ++ CHECK_IS_NAN (TYPE, s123); \ ++ TYPE n456 = WRAP_NAN (FUNC, "456"); \ ++ CHECK_IS_NAN (TYPE, n456); \ ++ TYPE s456 = WRAP_STRTO (SFUNC, "NAN(456)"); \ ++ CHECK_IS_NAN (TYPE, s456); \ ++ TYPE n123x = WRAP_NAN (FUNC, "123)"); \ ++ CHECK_IS_NAN (TYPE, n123x); \ ++ TYPE nemp = WRAP_NAN (FUNC, ""); \ ++ CHECK_IS_NAN (TYPE, nemp); \ ++ TYPE semp = WRAP_STRTO (SFUNC, "NAN()"); \ ++ CHECK_IS_NAN (TYPE, semp); \ ++ TYPE sx = WRAP_STRTO (SFUNC, "NAN"); \ ++ CHECK_IS_NAN (TYPE, sx); \ ++ if (CAN_TEST_EQ (MANT_DIG)) \ ++ CHECK_SAME_NAN (TYPE, n123, s123); \ ++ if (CAN_TEST_EQ (MANT_DIG)) \ ++ CHECK_SAME_NAN (TYPE, n456, s456); \ ++ if (CAN_TEST_EQ (MANT_DIG)) \ ++ CHECK_SAME_NAN (TYPE, nemp, semp); \ ++ if (CAN_TEST_EQ (MANT_DIG)) \ ++ CHECK_SAME_NAN (TYPE, n123x, sx); \ ++ CHECK_DIFF_NAN (TYPE, n123, n456); \ ++ CHECK_DIFF_NAN (TYPE, n123, nemp); \ ++ CHECK_DIFF_NAN (TYPE, n123, n123x); \ ++ CHECK_DIFF_NAN (TYPE, n456, nemp); \ ++ CHECK_DIFF_NAN (TYPE, n456, n123x); \ ++ } \ ++ while (0) ++ ++static int ++do_test (void) ++{ ++ int result = 0; ++ RUN_TESTS (float, strtof, nanf, FLT_MANT_DIG); ++ RUN_TESTS (double, strtod, nan, DBL_MANT_DIG); ++#ifndef NO_LONG_DOUBLE ++ RUN_TESTS (long double, strtold, nanl, LDBL_MANT_DIG); ++#endif ++ return result; ++} ++ ++#define TEST_FUNCTION do_test () ++#include "../test-skeleton.c" +Index: b/stdlib/Versions +=================================================================== +--- a/stdlib/Versions ++++ b/stdlib/Versions +@@ -118,5 +118,6 @@ libc { + # Used from other libraries + __libc_secure_getenv; + __call_tls_dtors; ++ __strtof_nan; __strtod_nan; __strtold_nan; + } + } diff -Nru glibc-2.21/debian/patches/any/CVE-2015-1781.diff glibc-2.21/debian/patches/any/CVE-2015-1781.diff --- glibc-2.21/debian/patches/any/CVE-2015-1781.diff 1970-01-01 00:00:00.000000000 +0000 +++ glibc-2.21/debian/patches/any/CVE-2015-1781.diff 2016-03-31 05:47:14.000000000 +0000 @@ -0,0 +1,36 @@ +From 2959eda9272a033863c271aff62095abd01bd4e3 Mon Sep 17 00:00:00 2001 +From: Arjun Shankar +Date: Tue, 21 Apr 2015 14:06:31 +0200 +Subject: [PATCH] CVE-2015-1781: resolv/nss_dns/dns-host.c buffer overflow [BZ#18287] + + [BZ #18287] + * resolv/nss_dns/dns-host.c (getanswer_r): Adjust buffer length + based on padding. (CVE-2015-1781) + +* A buffer overflow in gethostbyname_r and related functions performing DNS + requests has been fixed. If the NSS functions were called with a + misaligned buffer, the buffer length change due to pointer alignment was + not taken into account. This could result in application crashes or, + potentially arbitrary code execution, using crafted, but syntactically + valid DNS responses. (CVE-2015-1781) + +[Note: patch differs from upstream commit in that the entries in +the Changelog and NEWS were dropped to avoid patch conflicts. -- sbeattie] +--- + resolv/nss_dns/dns-host.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +Index: b/resolv/nss_dns/dns-host.c +=================================================================== +--- a/resolv/nss_dns/dns-host.c ++++ b/resolv/nss_dns/dns-host.c +@@ -615,7 +615,8 @@ getanswer_r (const querybuf *answer, int + int have_to_map = 0; + uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data); + buffer += pad; +- if (__glibc_unlikely (buflen < sizeof (struct host_data) + pad)) ++ buflen = buflen > pad ? buflen - pad : 0; ++ if (__glibc_unlikely (buflen < sizeof (struct host_data))) + { + /* The buffer is too small. */ + too_small: diff -Nru glibc-2.21/debian/patches/any/CVE-2015-8776.diff glibc-2.21/debian/patches/any/CVE-2015-8776.diff --- glibc-2.21/debian/patches/any/CVE-2015-8776.diff 1970-01-01 00:00:00.000000000 +0000 +++ glibc-2.21/debian/patches/any/CVE-2015-8776.diff 2016-03-31 05:59:50.000000000 +0000 @@ -0,0 +1,136 @@ +From d36c75fc0d44deec29635dd239b0fbd206ca49b7 Mon Sep 17 00:00:00 2001 +From: Paul Pluzhnikov +Date: Sat, 26 Sep 2015 13:27:48 -0700 +Subject: [PATCH] Fix BZ #18985 -- out of range data to strftime() causes a segfault + + [BZ #18985] + * time/strftime_l.c (a_wkday, f_wkday, a_month, f_month): Range check. + (__strftime_internal): Likewise. + * time/tst-strftime.c (do_bz18985): New test. + (do_test): Call it. + +[Note: patch differs from upstream commit in that the entries in +the Changelog and NEWS were dropped to avoid patch conflicts. -- sbeattie] +--- + time/strftime_l.c | 20 +++++++++++++------- + time/tst-strftime.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 64 insertions(+), 8 deletions(-) + +Index: b/time/strftime_l.c +=================================================================== +--- a/time/strftime_l.c ++++ b/time/strftime_l.c +@@ -510,13 +510,17 @@ __strftime_internal (s, maxsize, format, + 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 @@ __strftime_internal (s, maxsize, format, + # 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 @@ __strftime_internal (s, maxsize, format, + *tzset_called = true; + } + # endif +- zone = tzname[tp->tm_isdst]; ++ zone = tp->tm_isdst <= 1 ? tzname[tp->tm_isdst] : "?"; + } + #endif + if (! zone) +Index: b/time/tst-strftime.c +=================================================================== +--- a/time/tst-strftime.c ++++ b/time/tst-strftime.c +@@ -4,6 +4,56 @@ + #include + + ++static int ++do_bz18985 (void) ++{ ++ char buf[1000]; ++ struct tm ttm; ++ int rc, ret = 0; ++ ++ memset (&ttm, 1, sizeof (ttm)); ++ ttm.tm_zone = NULL; /* Dereferenced directly if non-NULL. */ ++ rc = strftime (buf, sizeof (buf), "%a %A %b %B %c %z %Z", &ttm); ++ ++ if (rc == 66) ++ { ++ const char expected[] ++ = "? ? ? ? ? ? 16843009 16843009:16843009:16843009 16844909 +467836 ?"; ++ if (0 != strcmp (buf, expected)) ++ { ++ printf ("expected:\n %s\ngot:\n %s\n", expected, buf); ++ ret += 1; ++ } ++ } ++ else ++ { ++ printf ("expected 66, got %d\n", rc); ++ ret += 1; ++ } ++ ++ /* Check negative values as well. */ ++ memset (&ttm, 0xFF, sizeof (ttm)); ++ ttm.tm_zone = NULL; /* Dereferenced directly if non-NULL. */ ++ rc = strftime (buf, sizeof (buf), "%a %A %b %B %c %z %Z", &ttm); ++ ++ if (rc == 30) ++ { ++ const char expected[] = "? ? ? ? ? ? -1 -1:-1:-1 1899 "; ++ if (0 != strcmp (buf, expected)) ++ { ++ printf ("expected:\n %s\ngot:\n %s\n", expected, buf); ++ ret += 1; ++ } ++ } ++ else ++ { ++ printf ("expected 30, got %d\n", rc); ++ ret += 1; ++ } ++ ++ return ret; ++} ++ + static struct + { + const char *fmt; +@@ -104,7 +154,7 @@ do_test (void) + } + } + +- return result; ++ return result + do_bz18985 (); + } + + #define TEST_FUNCTION do_test () diff -Nru glibc-2.21/debian/patches/any/CVE-2015-8777.diff glibc-2.21/debian/patches/any/CVE-2015-8777.diff --- glibc-2.21/debian/patches/any/CVE-2015-8777.diff 1970-01-01 00:00:00.000000000 +0000 +++ glibc-2.21/debian/patches/any/CVE-2015-8777.diff 2016-03-31 06:01:26.000000000 +0000 @@ -0,0 +1,83 @@ +From a014cecd82b71b70a6a843e250e06b541ad524f7 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 15 Oct 2015 09:23:07 +0200 +Subject: [PATCH] Always enable pointer guard [BZ #18928] + +Honoring the LD_POINTER_GUARD environment variable in AT_SECURE mode +has security implications. This commit enables pointer guard +unconditionally, and the environment variable is now ignored. + + [BZ #18928] + * sysdeps/generic/ldsodefs.h (struct rtld_global_ro): Remove + _dl_pointer_guard member. + * elf/rtld.c (_rtld_global_ro): Remove _dl_pointer_guard + initializer. + (security_init): Always set up pointer guard. + (process_envvars): Do not process LD_POINTER_GUARD. + +* The LD_POINTER_GUARD environment variable can no longer be used to + disable the pointer guard feature. It is always enabled. + +[Note: patch differs from upstream commit in that the entries in +the Changelog and NEWS were dropped to avoid patch conflicts. -- sbeattie] +--- + elf/rtld.c | 15 ++++----------- + sysdeps/generic/ldsodefs.h | 3 --- + 2 files changed, 4 insertions(+), 14 deletions(-) + +Index: b/elf/rtld.c +=================================================================== +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -162,7 +162,6 @@ struct rtld_global_ro _rtld_global_ro at + ._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 @@ security_init (void) + #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 +@@ -2473,9 +2469,6 @@ process_envvars (enum mode *modep) + 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: +Index: b/sysdeps/generic/ldsodefs.h +=================================================================== +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -593,9 +593,6 @@ struct rtld_global_ro + /* 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) diff -Nru glibc-2.21/debian/patches/any/CVE-2015-8778.diff glibc-2.21/debian/patches/any/CVE-2015-8778.diff --- glibc-2.21/debian/patches/any/CVE-2015-8778.diff 1970-01-01 00:00:00.000000000 +0000 +++ glibc-2.21/debian/patches/any/CVE-2015-8778.diff 2016-03-31 06:05:39.000000000 +0000 @@ -0,0 +1,50 @@ +From 2f5c1750558fe64bac361f52d6827ab1bcfe52bc Mon Sep 17 00:00:00 2001 +From: =?utf8?q?Ond=C5=99ej=20B=C3=ADlka?= +Date: Sat, 11 Jul 2015 17:44:10 +0200 +Subject: [PATCH] Handle overflow in __hcreate_r + +Hi, + +As in bugzilla entry there is overflow in hsearch when looking for prime +number as SIZE_MAX - 1 is divisible by 5. We fix that by rejecting large +inputs before looking for prime. + + * misc/hsearch_r.c (__hcreate_r): Handle overflow. + +[Note: patch differs from upstream commit in that the entries in +the Changelog were dropped to avoid patch conflicts. -- sbeattie] +--- + ChangeLog | 10 ++++++++++ + misc/hsearch_r.c | 9 ++++++++- + 2 files changed, 18 insertions(+), 1 deletions(-) + +diff --git a/misc/hsearch_r.c b/misc/hsearch_r.c +index 9f55e84..559df29 100644 +--- a/misc/hsearch_r.c ++++ b/misc/hsearch_r.c +@@ -19,7 +19,7 @@ + #include + #include + #include +- ++#include + #include + + /* [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986 +@@ -73,6 +73,13 @@ __hcreate_r (nel, htab) + return 0; + } + ++ if (nel >= SIZE_MAX / sizeof (_ENTRY)) ++ { ++ __set_errno (ENOMEM); ++ return 0; ++ } ++ ++ + /* There is still another table active. Return with error. */ + if (htab->table != NULL) + return 0; +-- +1.7.1 + diff -Nru glibc-2.21/debian/patches/any/CVE-2015-8779.diff glibc-2.21/debian/patches/any/CVE-2015-8779.diff --- glibc-2.21/debian/patches/any/CVE-2015-8779.diff 1970-01-01 00:00:00.000000000 +0000 +++ glibc-2.21/debian/patches/any/CVE-2015-8779.diff 2016-03-31 06:07:25.000000000 +0000 @@ -0,0 +1,231 @@ +From 0f58539030e436449f79189b6edab17d7479796e Mon Sep 17 00:00:00 2001 +From: Paul Pluzhnikov +Date: Sat, 8 Aug 2015 15:53:03 -0700 +Subject: [PATCH] Fix BZ #17905 + + [BZ #17905] + * catgets/Makefile (tst-catgets-mem): New test. + * catgets/catgets.c (catopen): Don't use unbounded alloca. + * catgets/open_catalog.c (__open_catalog): Likewise. + * catgets/tst-catgets.c (do_bz17905): Test unbounded alloca. + +[Note: patch differs from upstream commit in that the entries in +the Changelog and NEWS were dropped to avoid patch conflicts. -- sbeattie] +--- + catgets/Makefile | 9 ++++++++- + catgets/catgets.c | 19 ++++++++++++------- + catgets/open_catalog.c | 23 ++++++++++++++--------- + catgets/tst-catgets.c | 31 +++++++++++++++++++++++++++++++ + 4 files changed, 65 insertions(+), 17 deletions(-) + +Index: b/catgets/Makefile +=================================================================== +--- a/catgets/Makefile ++++ b/catgets/Makefile +@@ -34,6 +34,7 @@ test-srcs = test-gencat + ifeq ($(run-built-tests),yes) + tests-special += $(objpfx)de/libc.cat $(objpfx)test1.cat $(objpfx)test2.cat \ + $(objpfx)sample.SJIS.cat $(objpfx)test-gencat.out ++tests-special += $(objpfx)tst-catgets-mem.out + endif + + gencat-modules = xmalloc +@@ -50,9 +51,11 @@ catgets-CPPFLAGS := -DNLSPATH='"$(msgcat + + generated += de.msg test1.cat test1.h test2.cat test2.h sample.SJIS.cat \ + test-gencat.h ++generated += tst-catgets.mtrace tst-catgets-mem.out ++ + generated-dirs += de + +-tst-catgets-ENV = NLSPATH="$(objpfx)%l/%N.cat" LANG=de ++tst-catgets-ENV = NLSPATH="$(objpfx)%l/%N.cat" LANG=de MALLOC_TRACE=$(objpfx)tst-catgets.mtrace + + ifeq ($(run-built-tests),yes) + # This test just checks whether the program produces any error or not. +@@ -86,4 +89,8 @@ $(objpfx)test-gencat.out: test-gencat.sh + $(objpfx)sample.SJIS.cat: sample.SJIS $(objpfx)gencat + $(built-program-cmd) -H $(objpfx)test-gencat.h < $(word 1,$^) > $@; \ + $(evaluate-test) ++ ++$(objpfx)tst-catgets-mem.out: $(objpfx)tst-catgets.out ++ $(common-objpfx)malloc/mtrace $(objpfx)tst-catgets.mtrace > $@; \ ++ $(evaluate-test) + endif +Index: b/catgets/catgets.c +=================================================================== +--- a/catgets/catgets.c ++++ b/catgets/catgets.c +@@ -16,7 +16,6 @@ + License along with the GNU C Library; if not, see + . */ + +-#include + #include + #include + #include +@@ -35,6 +34,7 @@ catopen (const char *cat_name, int flag) + __nl_catd result; + const char *env_var = NULL; + const char *nlspath = NULL; ++ char *tmp = NULL; + + if (strchr (cat_name, '/') == NULL) + { +@@ -54,7 +54,10 @@ catopen (const char *cat_name, int flag) + { + /* 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 @@ catopen (const char *cat_name, int flag) + + 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; + } + +Index: b/catgets/open_catalog.c +=================================================================== +--- a/catgets/open_catalog.c ++++ b/catgets/open_catalog.c +@@ -47,6 +47,7 @@ __open_catalog (const char *cat_name, co + 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 @@ __open_catalog (const char *cat_name, co + 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 @@ __open_catalog (const char *cat_name, co + + /* 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 @@ __open_catalog (const char *cat_name, co + /* Release the lock again. */ + close_unlock_return: + close_not_cancel_no_status (fd); ++ free (buf); + + return result; + } +Index: b/catgets/tst-catgets.c +=================================================================== +--- a/catgets/tst-catgets.c ++++ b/catgets/tst-catgets.c +@@ -1,7 +1,10 @@ ++#include + #include + #include + #include ++#include + #include ++#include + + + static const char *msgs[] = +@@ -12,6 +15,33 @@ static const char *msgs[] = + }; + #define nmsgs (sizeof (msgs) / sizeof (msgs[0])) + ++ ++/* Test for unbounded alloca. */ ++static int ++do_bz17905 (void) ++{ ++ char *buf; ++ struct rlimit rl; ++ nl_catd result; ++ ++ const int sz = 1024 * 1024; ++ ++ getrlimit (RLIMIT_STACK, &rl); ++ rl.rlim_cur = sz; ++ setrlimit (RLIMIT_STACK, &rl); ++ ++ buf = malloc (sz + 1); ++ memset (buf, 'A', sz); ++ buf[sz] = '\0'; ++ setenv ("NLSPATH", buf, 1); ++ ++ result = catopen (buf, NL_CAT_LOCALE); ++ assert (result == (nl_catd) -1); ++ ++ free (buf); ++ return 0; ++} ++ + #define ROUNDS 5 + + static int +@@ -62,6 +92,7 @@ do_test (void) + } + } + ++ result += do_bz17905 (); + return result; + } + diff -Nru glibc-2.21/debian/patches/any/CVE-2016-2856.diff glibc-2.21/debian/patches/any/CVE-2016-2856.diff --- glibc-2.21/debian/patches/any/CVE-2016-2856.diff 1970-01-01 00:00:00.000000000 +0000 +++ glibc-2.21/debian/patches/any/CVE-2016-2856.diff 2016-04-02 08:22:05.000000000 +0000 @@ -0,0 +1,106 @@ +From 77356912e83601fd0240d22fe4d960348b82b5c3 Mon Sep 17 00:00:00 2001 +From: Aurelien Jarno +Date: Thu, 10 Dec 2015 22:33:10 +0100 +Subject: [PATCH] grantpt: trust the kernel about pty group and permission mode + +According to POSIX the grantpt() function does the following: + + The grantpt() function shall change the mode and ownership of the + slave pseudo-terminal device associated with its master + pseudo-terminal counterpart. The fildes argument is a file descriptor + that refers to a master pseudo-terminal device. The user ID of the + slave shall be set to the real UID of the calling process and the + group ID shall be set to an unspecified group ID. The permission + mode of the slave pseudo-terminal shall be set to readable and + writable by the owner, and writable by the group. + +Historically the GNU libc has been responsible to setup the permission +mode to 0620 and the group to 'tty' usually number 5, using the pt_chown +helper, badly known for its security issues. With the creation of the +devpts filesytem in the Linux kernel, this responsibility has been moved +to the Linux kernel. The system is responsible to mount the devpts +filesystem in /dev/pts with the options gid=5 and mode=0620. In that +case the GNU libc has nothing to do and pt_chown is not need anymore. So +far so good. + +The problem is that by default the devpts filesystem is shared between +all mounts, and that contrary to other filesystem, the mount options are +honored at the second mount, including for the default mount options. +Given it corresponds to mode=0600 without gid parameter (that is the +filesystem GID of the creating process), it's common to see systems +where the devpts filesystem is mounted using these options. It is enough +to run a "mount -t devpts devpts /mychroot/dev/pts" to come into this +situation, and it's unfortunately wrongly used in a lot of scripts +dealing with chroots, or for creating virtual machines images. + +When this happens the GNU libc tries to fix the group and permission +mode of the pty nodes, and given it fails to do so for non-root users, +grantpt() almost always fail. It means users are not able to open new +terminals. + +This patch changes grantpt() to not enforce this anymore, while still +enforcing minimum security measures to the permission mode. Therefore +the responsibility to follow POSIX is now shared at the system level, +i.e. kernel + system scripts + GNU libc. It stops trying to change the +group, and makes the pty node readable and writable by the owner, and +writable by the group only when originally writable and when the group +is the tty one. + +As a result, on a system wrongly mounted with gid=0 and mode=0600, the +pty nodes won't be accessible by the tty group, but the grantpt() +function will succeed and users will have a working system. The system +is not fully POSIX compliant (which might be an admin choice to default +to "mesg n" mode), but the GNU libc is not to blame here, as without the +pt_chown helper it can't do anything. + +With this patch there should not be any reason left to build the GNU +libc with the --enable-pt_chown configure option on a GNU/Linux system. + + [BZ #19347] + * sysdeps/unix/grantpt.c [!HAVE_PT_CHOWN] (grantpt): Do not try + to change the group of the device to the tty group. +--- + sysdeps/unix/grantpt.c | 22 ++++++++++++++++++++-- + 1 file changed, 20 insertions(+), 2 deletions(-) + +Index: b/sysdeps/unix/grantpt.c +=================================================================== +--- a/sysdeps/unix/grantpt.c ++++ b/sysdeps/unix/grantpt.c +@@ -155,6 +155,7 @@ grantpt (int fd) + } + gid_t gid = tty_gid == -1 ? __getgid () : tty_gid; + ++#if HAVE_PT_CHOWN + /* Make sure the group of the device is that special group. */ + if (st.st_gid != gid) + { +@@ -164,9 +165,26 @@ grantpt (int fd) + + /* Make sure the permission mode is set to readable and writable by + the owner, and writable by the group. */ +- if ((st.st_mode & ACCESSPERMS) != (S_IRUSR|S_IWUSR|S_IWGRP)) ++ mode_t mode = S_IRUSR|S_IWUSR|S_IWGRP; ++#else ++ /* When built without pt_chown, we have delegated the creation of the ++ pty node with the right group and permission mode to the kernel, and ++ non-root users are unlikely to be able to change it. Therefore let's ++ consider that POSIX enforcement is the responsibility of the whole ++ system and not only the GNU libc. Thus accept different group or ++ permission mode. */ ++ ++ /* Make sure the permission is set to readable and writable by the ++ owner. For security reasons, make it writable by the group only ++ when originally writable and when the group of the device is that ++ special group. */ ++ mode_t mode = S_IRUSR|S_IWUSR| ++ ((st.st_gid == gid) ? (st.st_mode & S_IWGRP) : 0); ++#endif ++ ++ if ((st.st_mode & ACCESSPERMS) != mode) + { +- if (__chmod (buf, S_IRUSR|S_IWUSR|S_IWGRP) < 0) ++ if (__chmod (buf, mode) < 0) + goto helper; + } + diff -Nru glibc-2.21/debian/patches/any/CVE-2016-3075.diff glibc-2.21/debian/patches/any/CVE-2016-3075.diff --- glibc-2.21/debian/patches/any/CVE-2016-3075.diff 1970-01-01 00:00:00.000000000 +0000 +++ glibc-2.21/debian/patches/any/CVE-2016-3075.diff 2016-03-31 06:22:44.000000000 +0000 @@ -0,0 +1,42 @@ +From 317b199b4aff8cfa27f2302ab404d2bb5032b9a4 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Tue, 29 Mar 2016 12:57:56 +0200 +Subject: [PATCH] CVE-2016-3075: Stack overflow in _nss_dns_getnetbyname_r [BZ #19879] + +The defensive copy is not needed because the name may not alias the +output buffer. + + [BZ #19879] + CVE-2016-3075 + * resolv/nss_dns/dns-network.c (_nss_dns_getnetbyname_r): Do not + copy name. + +[Note: patch differs from upstream commit in that the entries in +the Changelog and NEWS were dropped to avoid patch conflicts. -- sbeattie] +--- + resolv/nss_dns/dns-network.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +Index: b/resolv/nss_dns/dns-network.c +=================================================================== +--- a/resolv/nss_dns/dns-network.c ++++ b/resolv/nss_dns/dns-network.c +@@ -118,17 +118,14 @@ _nss_dns_getnetbyname_r (const char *nam + } net_buffer; + querybuf *orig_net_buffer; + int anslen; +- char *qbuf; + enum nss_status status; + + if (__res_maybe_init (&_res, 0) == -1) + return NSS_STATUS_UNAVAIL; + +- qbuf = strdupa (name); +- + net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024); + +- anslen = __libc_res_nsearch (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf, ++ anslen = __libc_res_nsearch (&_res, name, C_IN, T_PTR, net_buffer.buf->buf, + 1024, &net_buffer.ptr, NULL, NULL, NULL, NULL); + if (anslen < 0) + { diff -Nru glibc-2.21/debian/patches/series glibc-2.21/debian/patches/series --- glibc-2.21/debian/patches/series 2016-02-16 16:42:32.000000000 +0000 +++ glibc-2.21/debian/patches/series 2016-04-02 08:21:28.000000000 +0000 @@ -263,3 +263,14 @@ ubuntu/local-warn-bsd-source.diff any/CVE-2015-7547.diff +any/CVE-2014-8121-1.diff +any/CVE-2014-8121-2.diff +any/CVE-2014-9761-1.diff +any/CVE-2014-9761-2.diff +any/CVE-2015-1781.diff +any/CVE-2015-8776.diff +any/CVE-2015-8777.diff +any/CVE-2015-8778.diff +any/CVE-2015-8779.diff +any/CVE-2016-3075.diff +any/CVE-2016-2856.diff diff -Nru glibc-2.21/debian/rules.d/debhelper.mk glibc-2.21/debian/rules.d/debhelper.mk --- glibc-2.21/debian/rules.d/debhelper.mk 2015-03-19 22:15:39.000000000 +0000 +++ glibc-2.21/debian/rules.d/debhelper.mk 2016-04-02 08:45:38.000000000 +0000 @@ -170,6 +170,7 @@ case $$y in \ *.install) \ sed -e "s/^#.*//" -i $$y ; \ + $(if $(filter $(pt_chown),no),sed -e "/pt_chown/d" -i $$y ;) \ ;; \ esac; \ done diff -Nru glibc-2.21/debian/sysdeps/linux.mk glibc-2.21/debian/sysdeps/linux.mk --- glibc-2.21/debian/sysdeps/linux.mk 2015-03-19 21:13:02.000000000 +0000 +++ glibc-2.21/debian/sysdeps/linux.mk 2016-04-02 08:25:34.000000000 +0000 @@ -3,7 +3,7 @@ libc = libc6 # Build and expect pt_chown on this platform -pt_chown = yes +pt_chown = no # NPTL Config threads = yes