# HG changeset patch # User Stanislas Leduc # Date 1678880498 0 # Node ID 82efffdfec116cfc293edc8891db6d49229db1a9 # Parent eece3e29fb61f6c4e660b7844edb610232481280 Up glibc (2.22) with CVE patchs diff -r eece3e29fb61 -r 82efffdfec11 glibc-base/receipt --- a/glibc-base/receipt Wed Mar 15 08:07:13 2023 +0000 +++ b/glibc-base/receipt Wed Mar 15 11:41:38 2023 +0000 @@ -1,7 +1,7 @@ # SliTaz package receipt. PACKAGE="glibc-base" -VERSION="2.21" +VERSION="2.22" CATEGORY="base-system" SHORT_DESC="GNU libc minimal libraries and UTF-8 support for SliTaz." WEB_SITE="http://www.gnu.org/software/libc/" diff -r eece3e29fb61 -r 82efffdfec11 glibc-base/stuff/wanted-files.list --- a/glibc-base/stuff/wanted-files.list Wed Mar 15 08:07:13 2023 +0000 +++ b/glibc-base/stuff/wanted-files.list Wed Mar 15 11:41:38 2023 +0000 @@ -1,18 +1,18 @@ -/lib/libutil-2.21.so -/lib/libnss_dns-2.21.so -/lib/libnsl-2.21.so -/lib/libanl-2.21.so -/lib/libm-2.21.so -/lib/libpthread-2.21.so +/lib/libutil-2.22.so +/lib/libnss_dns-2.22.so +/lib/libnsl-2.22.so +/lib/libanl-2.22.so +/lib/libm-2.22.so +/lib/libpthread-2.22.so /lib/libthread_db-1.0.so -/lib/libnss_compat-2.21.so -/lib/libc-2.21.so -/lib/librt-2.21.so -/lib/libcrypt-2.21.so -/lib/ld-2.21.so -/lib/libresolv-2.21.so -/lib/libnss_files-2.21.so -/lib/libdl-2.21.so +/lib/libnss_compat-2.22.so +/lib/libc-2.22.so +/lib/librt-2.22.so +/lib/libcrypt-2.22.so +/lib/ld-2.22.so +/lib/libresolv-2.22.so +/lib/libnss_files-2.22.so +/lib/libdl-2.22.so /usr/lib/gconv/UNICODE.so /usr/lib/gconv/gconv-modules diff -r eece3e29fb61 -r 82efffdfec11 glibc-dev/receipt --- a/glibc-dev/receipt Wed Mar 15 08:07:13 2023 +0000 +++ b/glibc-dev/receipt Wed Mar 15 11:41:38 2023 +0000 @@ -1,7 +1,7 @@ # SliTaz package receipt. PACKAGE="glibc-dev" -VERSION="2.21" +VERSION="2.22" CATEGORY="development" SHORT_DESC="The GNU C libraries devel files (Part of SliTaz toolchain)." MAINTAINER="pankso@slitaz.org" diff -r eece3e29fb61 -r 82efffdfec11 glibc-extra-samba/receipt --- a/glibc-extra-samba/receipt Wed Mar 15 08:07:13 2023 +0000 +++ b/glibc-extra-samba/receipt Wed Mar 15 11:41:38 2023 +0000 @@ -1,7 +1,7 @@ # SliTaz package receipt. PACKAGE="glibc-extra-samba" -VERSION="2.21" +VERSION="2.22" CATEGORY="base-system" SHORT_DESC="GNU libc extra gconv modules for samba." WEB_SITE="http://gcc.gnu.org/" diff -r eece3e29fb61 -r 82efffdfec11 glibc-locale/receipt --- a/glibc-locale/receipt Wed Mar 15 08:07:13 2023 +0000 +++ b/glibc-locale/receipt Wed Mar 15 11:41:38 2023 +0000 @@ -1,7 +1,7 @@ # SliTaz package receipt. PACKAGE="glibc-locale" -VERSION="2.21" +VERSION="2.22" CATEGORY="system-tools" SHORT_DESC="The GNU C libraries locale files and utilities (see also locale-*)." MAINTAINER="pankso@slitaz.org" diff -r eece3e29fb61 -r 82efffdfec11 glibc/receipt --- a/glibc/receipt Wed Mar 15 08:07:13 2023 +0000 +++ b/glibc/receipt Wed Mar 15 11:41:38 2023 +0000 @@ -1,7 +1,7 @@ # SliTaz package receipt. PACKAGE="glibc" -VERSION="2.21" +VERSION="2.22" CATEGORY="meta" SHORT_DESC="The GNU C libraries. This package is used to compile the libc." MAINTAINER="pankso@slitaz.org" @@ -14,6 +14,41 @@ # Genpkg order for tazwok. COOK_OPT="genpkg=glibc-base:glibc-extra-samba:glib-locale:glibc-dev" + +# Apply glibc patches CVE +apply_cve_patchs() +{ + while read file; do + [ -f done.$file ] && continue + echo "Apply $file..." + patch -p1 < $stuff/patches/$PACKAGE-$VERSION-CVE-$file || return 1 + touch done.$file + done < +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. + +diff -Naur a/include/stdlib.h b/include/stdlib.h +--- a/include/stdlib.h 2017-09-15 15:37:06.011900628 +0530 ++++ b/include/stdlib.h 2017-09-15 15:37:13.851729724 +0530 +@@ -203,6 +203,24 @@ + 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 -Naur a/include/wchar.h b/include/wchar.h +--- a/include/wchar.h 2017-09-15 15:37:06.011900628 +0530 ++++ b/include/wchar.h 2017-09-15 15:37:13.851729724 +0530 +@@ -52,6 +52,9 @@ + __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 -Naur a/math/Makefile b/math/Makefile +--- a/math/Makefile 2017-09-15 15:37:06.039900018 +0530 ++++ b/math/Makefile 2017-09-15 15:41:38.669965657 +0530 +@@ -108,6 +108,7 @@ + test-tgmath-ret bug-nextafter bug-nexttoward bug-tgmath1 \ + test-tgmath-int test-tgmath2 test-powl tst-CMPLX tst-CMPLX2 test-snan \ + test-fenv-tls test-fenv-preserve test-fenv-return test-fenvinline \ ++ test-signgam-ullong-init 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 and +diff -Naur a/math/s_nan.c b/math/s_nan.c +--- a/math/s_nan.c 2017-09-15 15:37:06.051899756 +0530 ++++ b/math/s_nan.c 2017-09-15 15:38:10.122503550 +0530 +@@ -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 +diff -Naur a/math/s_nanf.c b/math/s_nanf.c +--- a/math/s_nanf.c 2017-09-15 15:37:06.051899756 +0530 ++++ b/math/s_nanf.c 2017-09-15 15:38:10.122503550 +0530 +@@ -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) +diff -Naur a/math/s_nanl.c b/math/s_nanl.c +--- a/math/s_nanl.c 2017-09-15 15:37:06.051899756 +0530 ++++ b/math/s_nanl.c 2017-09-15 15:38:10.122503550 +0530 +@@ -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) +diff -Naur a/math/test-nan-overflow.c b/math/test-nan-overflow.c +--- a/math/test-nan-overflow.c 1970-01-01 05:30:00.000000000 +0530 ++++ b/math/test-nan-overflow.c 2017-09-15 15:38:10.122503550 +0530 +@@ -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" +diff -Naur a/math/test-nan-payload.c b/math/test-nan-payload.c +--- a/math/test-nan-payload.c 1970-01-01 05:30:00.000000000 +0530 ++++ b/math/test-nan-payload.c 2017-09-15 15:38:10.122503550 +0530 +@@ -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" +diff -Naur a/stdlib/Makefile b/stdlib/Makefile +--- a/stdlib/Makefile 2017-09-15 15:37:06.079899146 +0530 ++++ b/stdlib/Makefile 2017-09-15 15:37:13.851729724 +0530 +@@ -50,6 +50,7 @@ + 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 -Naur a/stdlib/strtod_l.c b/stdlib/strtod_l.c +--- a/stdlib/strtod_l.c 2017-09-15 15:37:06.079899146 +0530 ++++ b/stdlib/strtod_l.c 2017-09-15 15:37:13.851729724 +0530 +@@ -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 @@ + # 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 +@@ -104,7 +95,6 @@ + # 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 +@@ -116,7 +106,6 @@ + # 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 + + +@@ -655,33 +644,14 @@ + 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 -Naur a/stdlib/strtod_nan.c b/stdlib/strtod_nan.c +--- a/stdlib/strtod_nan.c 1970-01-01 05:30:00.000000000 +0530 ++++ b/stdlib/strtod_nan.c 2017-09-15 15:37:13.851729724 +0530 +@@ -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 -Naur a/stdlib/strtod_nan_double.h b/stdlib/strtod_nan_double.h +--- a/stdlib/strtod_nan_double.h 1970-01-01 05:30:00.000000000 +0530 ++++ b/stdlib/strtod_nan_double.h 2017-09-15 15:37:13.851729724 +0530 +@@ -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 -Naur a/stdlib/strtod_nan_float.h b/stdlib/strtod_nan_float.h +--- a/stdlib/strtod_nan_float.h 1970-01-01 05:30:00.000000000 +0530 ++++ b/stdlib/strtod_nan_float.h 2017-09-15 15:37:13.851729724 +0530 +@@ -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 -Naur a/stdlib/strtod_nan_main.c b/stdlib/strtod_nan_main.c +--- a/stdlib/strtod_nan_main.c 1970-01-01 05:30:00.000000000 +0530 ++++ b/stdlib/strtod_nan_main.c 2017-09-15 15:37:13.851729724 +0530 +@@ -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 -Naur a/stdlib/strtod_nan_narrow.h b/stdlib/strtod_nan_narrow.h +--- a/stdlib/strtod_nan_narrow.h 1970-01-01 05:30:00.000000000 +0530 ++++ b/stdlib/strtod_nan_narrow.h 2017-09-15 15:37:13.851729724 +0530 +@@ -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 -Naur a/stdlib/strtod_nan_wide.h b/stdlib/strtod_nan_wide.h +--- a/stdlib/strtod_nan_wide.h 1970-01-01 05:30:00.000000000 +0530 ++++ b/stdlib/strtod_nan_wide.h 2017-09-15 15:37:13.851729724 +0530 +@@ -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 -Naur a/stdlib/strtof_l.c b/stdlib/strtof_l.c +--- a/stdlib/strtof_l.c 2017-09-15 15:37:06.079899146 +0530 ++++ b/stdlib/strtof_l.c 2017-09-15 15:37:13.855729636 +0530 +@@ -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 -Naur a/stdlib/strtof_nan.c b/stdlib/strtof_nan.c +--- a/stdlib/strtof_nan.c 1970-01-01 05:30:00.000000000 +0530 ++++ b/stdlib/strtof_nan.c 2017-09-15 15:37:13.855729636 +0530 +@@ -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 -Naur a/stdlib/strtold_nan.c b/stdlib/strtold_nan.c +--- a/stdlib/strtold_nan.c 1970-01-01 05:30:00.000000000 +0530 ++++ b/stdlib/strtold_nan.c 2017-09-15 15:37:13.855729636 +0530 +@@ -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 -Naur a/stdlib/Versions b/stdlib/Versions +--- a/stdlib/Versions 2017-09-15 15:37:06.079899146 +0530 ++++ b/stdlib/Versions 2017-09-15 15:38:10.122503550 +0530 +@@ -118,5 +118,6 @@ + # Used from other libraries + __libc_secure_getenv; + __call_tls_dtors; ++ __strtof_nan; __strtod_nan; __strtold_nan; + } + } +diff -Naur a/sysdeps/ieee754/ldbl-128/strtod_nan_ldouble.h b/sysdeps/ieee754/ldbl-128/strtod_nan_ldouble.h +--- a/sysdeps/ieee754/ldbl-128/strtod_nan_ldouble.h 1970-01-01 05:30:00.000000000 +0530 ++++ b/sysdeps/ieee754/ldbl-128/strtod_nan_ldouble.h 2017-09-15 15:37:13.855729636 +0530 +@@ -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 -Naur a/sysdeps/ieee754/ldbl-128/strtold_l.c b/sysdeps/ieee754/ldbl-128/strtold_l.c +--- a/sysdeps/ieee754/ldbl-128/strtold_l.c 2017-09-15 15:37:06.107898535 +0530 ++++ b/sysdeps/ieee754/ldbl-128/strtold_l.c 2017-09-15 15:37:13.855729636 +0530 +@@ -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 -Naur a/sysdeps/ieee754/ldbl-128ibm/strtod_nan_ldouble.h b/sysdeps/ieee754/ldbl-128ibm/strtod_nan_ldouble.h +--- a/sysdeps/ieee754/ldbl-128ibm/strtod_nan_ldouble.h 1970-01-01 05:30:00.000000000 +0530 ++++ b/sysdeps/ieee754/ldbl-128ibm/strtod_nan_ldouble.h 2017-09-15 15:37:13.855729636 +0530 +@@ -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 -Naur a/sysdeps/ieee754/ldbl-128ibm/strtold_l.c b/sysdeps/ieee754/ldbl-128ibm/strtold_l.c +--- a/sysdeps/ieee754/ldbl-128ibm/strtold_l.c 2017-09-15 15:37:06.107898535 +0530 ++++ b/sysdeps/ieee754/ldbl-128ibm/strtold_l.c 2017-09-15 15:37:13.855729636 +0530 +@@ -30,25 +30,19 @@ + # 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 -Naur a/sysdeps/ieee754/ldbl-64-128/strtold_l.c b/sysdeps/ieee754/ldbl-64-128/strtold_l.c +--- a/sysdeps/ieee754/ldbl-64-128/strtold_l.c 2017-09-15 15:37:06.111898448 +0530 ++++ b/sysdeps/ieee754/ldbl-64-128/strtold_l.c 2017-09-15 15:37:13.855729636 +0530 +@@ -30,28 +30,19 @@ + # 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 -Naur a/sysdeps/ieee754/ldbl-96/strtod_nan_ldouble.h b/sysdeps/ieee754/ldbl-96/strtod_nan_ldouble.h +--- a/sysdeps/ieee754/ldbl-96/strtod_nan_ldouble.h 1970-01-01 05:30:00.000000000 +0530 ++++ b/sysdeps/ieee754/ldbl-96/strtod_nan_ldouble.h 2017-09-15 15:37:13.855729636 +0530 +@@ -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 -Naur a/sysdeps/ieee754/ldbl-96/strtold_l.c b/sysdeps/ieee754/ldbl-96/strtold_l.c +--- a/sysdeps/ieee754/ldbl-96/strtold_l.c 2017-09-15 15:37:06.111898448 +0530 ++++ b/sysdeps/ieee754/ldbl-96/strtold_l.c 2017-09-15 15:37:13.855729636 +0530 +@@ -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 -Naur a/wcsmbs/Makefile b/wcsmbs/Makefile +--- a/wcsmbs/Makefile 2017-09-15 15:37:06.219896093 +0530 ++++ b/wcsmbs/Makefile 2017-09-15 15:37:13.855729636 +0530 +@@ -33,6 +33,7 @@ + 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 -Naur a/wcsmbs/wcstod_l.c b/wcsmbs/wcstod_l.c +--- a/wcsmbs/wcstod_l.c 2017-09-15 15:37:06.211896267 +0530 ++++ b/wcsmbs/wcstod_l.c 2017-09-15 15:37:13.855729636 +0530 +@@ -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 -Naur a/wcsmbs/wcstod_nan.c b/wcsmbs/wcstod_nan.c +--- a/wcsmbs/wcstod_nan.c 1970-01-01 05:30:00.000000000 +0530 ++++ b/wcsmbs/wcstod_nan.c 2017-09-15 15:37:13.855729636 +0530 +@@ -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 -Naur a/wcsmbs/wcstof_l.c b/wcsmbs/wcstof_l.c +--- a/wcsmbs/wcstof_l.c 2017-09-15 15:37:06.211896267 +0530 ++++ b/wcsmbs/wcstof_l.c 2017-09-15 15:37:13.855729636 +0530 +@@ -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 -Naur a/wcsmbs/wcstof_nan.c b/wcsmbs/wcstof_nan.c +--- a/wcsmbs/wcstof_nan.c 1970-01-01 05:30:00.000000000 +0530 ++++ b/wcsmbs/wcstof_nan.c 2017-09-15 15:37:13.855729636 +0530 +@@ -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 -Naur a/wcsmbs/wcstold_l.c b/wcsmbs/wcstold_l.c +--- a/wcsmbs/wcstold_l.c 2017-09-15 15:37:06.219896093 +0530 ++++ b/wcsmbs/wcstold_l.c 2017-09-15 15:37:13.859729550 +0530 +@@ -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 -Naur a/wcsmbs/wcstold_nan.c b/wcsmbs/wcstold_nan.c +--- a/wcsmbs/wcstold_nan.c 1970-01-01 05:30:00.000000000 +0530 ++++ b/wcsmbs/wcstold_nan.c 2017-09-15 15:37:13.859729550 +0530 +@@ -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 diff -r eece3e29fb61 -r 82efffdfec11 glibc/stuff/patches/glibc-2.22-CVE-2015-5180.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/glibc/stuff/patches/glibc-2.22-CVE-2015-5180.patch Wed Mar 15 11:41:38 2023 +0000 @@ -0,0 +1,71 @@ +diff -Naur a/include/arpa/nameser_compat.h b/include/arpa/nameser_compat.h +--- a/include/arpa/nameser_compat.h 2018-01-04 15:53:54.033670066 +0530 ++++ b/include/arpa/nameser_compat.h 2018-01-04 15:54:15.437444821 +0530 +@@ -1,8 +1,8 @@ + #ifndef _ARPA_NAMESER_COMPAT_ + #include + +-/* Picksome unused number to represent lookups of IPv4 and IPv6 (i.e., +- T_A and T_AAAA). */ +-#define T_UNSPEC 62321 ++/* The number is outside the 16-bit RR type range and is used ++ internally by the implementation. */ ++#define T_QUERY_A_AND_AAAA 439963904 + + #endif +diff -Naur a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c +--- a/resolv/nss_dns/dns-host.c 2018-01-04 15:53:54.101669342 +0530 ++++ b/resolv/nss_dns/dns-host.c 2018-01-04 15:54:15.437444821 +0530 +@@ -312,7 +312,7 @@ + + int olderr = errno; + enum nss_status status; +- int n = __libc_res_nsearch (&_res, name, C_IN, T_UNSPEC, ++ int n = __libc_res_nsearch (&_res, name, C_IN, T_QUERY_A_AND_AAAA, + host_buffer.buf->buf, 2048, &host_buffer.ptr, + &ans2p, &nans2p, &resplen2, &ans2p_malloced); + if (n >= 0) +diff -Naur a/resolv/res_mkquery.c b/resolv/res_mkquery.c +--- a/resolv/res_mkquery.c 2018-01-04 15:53:54.101669342 +0530 ++++ b/resolv/res_mkquery.c 2018-01-04 15:54:15.437444821 +0530 +@@ -110,6 +110,10 @@ + int n; + u_char *dnptrs[20], **dpp, **lastdnptr; + ++ if (class < 0 || class > 65535 ++ || type < 0 || type > 65535) ++ return -1; ++ + #ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; res_nmkquery(%s, %s, %s, %s)\n", +diff -Naur a/resolv/res_query.c b/resolv/res_query.c +--- a/resolv/res_query.c 2018-01-04 15:53:54.101669342 +0530 ++++ b/resolv/res_query.c 2018-01-04 15:54:15.437444821 +0530 +@@ -127,7 +127,7 @@ + int n, use_malloc = 0; + u_int oflags = statp->_flags; + +- size_t bufsize = (type == T_UNSPEC ? 2 : 1) * QUERYSIZE; ++ size_t bufsize = (type == T_QUERY_A_AND_AAAA ? 2 : 1) * QUERYSIZE; + u_char *buf = alloca (bufsize); + u_char *query1 = buf; + int nquery1 = -1; +@@ -142,7 +142,7 @@ + printf(";; res_query(%s, %d, %d)\n", name, class, type); + #endif + +- if (type == T_UNSPEC) ++ if (type == T_QUERY_A_AND_AAAA) + { + n = res_nmkquery(statp, QUERY, name, class, T_A, NULL, 0, NULL, + query1, bufsize); +@@ -195,7 +195,7 @@ + if (__builtin_expect (n <= 0, 0) && !use_malloc) { + /* Retry just in case res_nmkquery failed because of too + short buffer. Shouldn't happen. */ +- bufsize = (type == T_UNSPEC ? 2 : 1) * MAXPACKET; ++ bufsize = (type == T_QUERY_A_AND_AAAA ? 2 : 1) * MAXPACKET; + buf = malloc (bufsize); + if (buf != NULL) { + query1 = buf; diff -r eece3e29fb61 -r 82efffdfec11 glibc/stuff/patches/glibc-2.22-CVE-2015-7547-getaddrinfo-stack-based-buffer-overflow.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/glibc/stuff/patches/glibc-2.22-CVE-2015-7547-getaddrinfo-stack-based-buffer-overflow.patch Wed Mar 15 11:41:38 2023 +0000 @@ -0,0 +1,617 @@ +Based on: + +From b995d95a5943785be3ab862b2d3276f3b4a22481 Mon Sep 17 00:00:00 2001 +From: Carlos O'Donell +Date: Tue, 16 Feb 2016 21:26:37 -0500 +Subject: [PATCH] CVE-2015-7547: getaddrinfo() stack-based buffer overflow (Bug + 18665). + +* A stack-based buffer overflow was found in libresolv when invoked from + libnss_dns, allowing specially crafted DNS responses to seize control + of execution flow in the DNS client. The buffer overflow occurs in + the functions send_dg (send datagram) and send_vc (send TCP) for the + NSS module libnss_dns.so.2 when calling getaddrinfo with AF_UNSPEC + family. The use of AF_UNSPEC triggers the low-level resolver code to + send out two parallel queries for A and AAAA. A mismanagement of the + buffers used for those queries could result in the response of a query + writing beyond the alloca allocated buffer created by + _nss_dns_gethostbyname4_r. Buffer management is simplified to remove + the overflow. Thanks to the Google Security Team and Red Hat for + reporting the security impact of this issue, and Robert Holiday of + Ciena for reporting the related bug 18665. (CVE-2015-7547) + +See also: +https://sourceware.org/ml/libc-alpha/2016-02/msg00416.html +https://sourceware.org/ml/libc-alpha/2016-02/msg00418.html + +(cherry picked from commit e9db92d3acfe1822d56d11abcea5bfc4c41cf6ca) +--- + ChangeLog | 15 +++ + NEWS | 14 +++ + resolv/nss_dns/dns-host.c | 111 ++++++++++++++++++- + resolv/res_query.c | 3 + + resolv/res_send.c | 264 ++++++++++++++++++++++++++++++++++------------ + 5 files changed, 338 insertions(+), 69 deletions(-) + +diff --git a/NEWS b/NEWS +index d1daf9b..81ceeae 100644 +--- a/NEWS ++++ b/NEWS +@@ -7,6 +7,20 @@ using `glibc' in the "product" field. + + Version 2.22.1 + ++* A stack-based buffer overflow was found in libresolv when invoked from ++ libnss_dns, allowing specially crafted DNS responses to seize control ++ of execution flow in the DNS client. The buffer overflow occurs in ++ the functions send_dg (send datagram) and send_vc (send TCP) for the ++ NSS module libnss_dns.so.2 when calling getaddrinfo with AF_UNSPEC ++ family. The use of AF_UNSPEC triggers the low-level resolver code to ++ send out two parallel queries for A and AAAA. A mismanagement of the ++ buffers used for those queries could result in the response of a query ++ writing beyond the alloca allocated buffer created by ++ _nss_dns_gethostbyname4_r. Buffer management is simplified to remove ++ the overflow. Thanks to the Google Security Team and Red Hat for ++ reporting the security impact of this issue, and Robert Holiday of ++ Ciena for reporting the related bug 18665. (CVE-2015-7547) ++ + * The following bugs are resolved with this release: + + 17905, 18420, 18421, 18480, 18589, 18743, 18778, 18781, 18787, 18796, +diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c +index 357ac04..a0fe9a8 100644 +--- a/resolv/nss_dns/dns-host.c ++++ b/resolv/nss_dns/dns-host.c +@@ -1031,7 +1031,10 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname, + int h_namelen = 0; + + if (ancount == 0) +- return NSS_STATUS_NOTFOUND; ++ { ++ *h_errnop = HOST_NOT_FOUND; ++ return NSS_STATUS_NOTFOUND; ++ } + + while (ancount-- > 0 && cp < end_of_message && had_error == 0) + { +@@ -1208,7 +1211,14 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname, + /* Special case here: if the resolver sent a result but it only + contains a CNAME while we are looking for a T_A or T_AAAA record, + we fail with NOTFOUND instead of TRYAGAIN. */ +- return canon == NULL ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND; ++ if (canon != NULL) ++ { ++ *h_errnop = HOST_NOT_FOUND; ++ return NSS_STATUS_NOTFOUND; ++ } ++ ++ *h_errnop = NETDB_INTERNAL; ++ return NSS_STATUS_TRYAGAIN; + } + + +@@ -1222,11 +1232,101 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2, + + enum nss_status status = NSS_STATUS_NOTFOUND; + ++ /* Combining the NSS status of two distinct queries requires some ++ compromise and attention to symmetry (A or AAAA queries can be ++ returned in any order). What follows is a breakdown of how this ++ code is expected to work and why. We discuss only SUCCESS, ++ TRYAGAIN, NOTFOUND and UNAVAIL, since they are the only returns ++ that apply (though RETURN and MERGE exist). We make a distinction ++ between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable). ++ A recoverable TRYAGAIN is almost always due to buffer size issues ++ and returns ERANGE in errno and the caller is expected to retry ++ with a larger buffer. ++ ++ Lastly, you may be tempted to make significant changes to the ++ conditions in this code to bring about symmetry between responses. ++ Please don't change anything without due consideration for ++ expected application behaviour. Some of the synthesized responses ++ aren't very well thought out and sometimes appear to imply that ++ IPv4 responses are always answer 1, and IPv6 responses are always ++ answer 2, but that's not true (see the implementation of send_dg ++ and send_vc to see response can arrive in any order, particularly ++ for UDP). However, we expect it holds roughly enough of the time ++ that this code works, but certainly needs to be fixed to make this ++ a more robust implementation. ++ ++ ---------------------------------------------- ++ | Answer 1 Status / | Synthesized | Reason | ++ | Answer 2 Status | Status | | ++ |--------------------------------------------| ++ | SUCCESS/SUCCESS | SUCCESS | [1] | ++ | SUCCESS/TRYAGAIN | TRYAGAIN | [5] | ++ | SUCCESS/TRYAGAIN' | SUCCESS | [1] | ++ | SUCCESS/NOTFOUND | SUCCESS | [1] | ++ | SUCCESS/UNAVAIL | SUCCESS | [1] | ++ | TRYAGAIN/SUCCESS | TRYAGAIN | [2] | ++ | TRYAGAIN/TRYAGAIN | TRYAGAIN | [2] | ++ | TRYAGAIN/TRYAGAIN' | TRYAGAIN | [2] | ++ | TRYAGAIN/NOTFOUND | TRYAGAIN | [2] | ++ | TRYAGAIN/UNAVAIL | TRYAGAIN | [2] | ++ | TRYAGAIN'/SUCCESS | SUCCESS | [3] | ++ | TRYAGAIN'/TRYAGAIN | TRYAGAIN | [3] | ++ | TRYAGAIN'/TRYAGAIN' | TRYAGAIN' | [3] | ++ | TRYAGAIN'/NOTFOUND | TRYAGAIN' | [3] | ++ | TRYAGAIN'/UNAVAIL | UNAVAIL | [3] | ++ | NOTFOUND/SUCCESS | SUCCESS | [3] | ++ | NOTFOUND/TRYAGAIN | TRYAGAIN | [3] | ++ | NOTFOUND/TRYAGAIN' | TRYAGAIN' | [3] | ++ | NOTFOUND/NOTFOUND | NOTFOUND | [3] | ++ | NOTFOUND/UNAVAIL | UNAVAIL | [3] | ++ | UNAVAIL/SUCCESS | UNAVAIL | [4] | ++ | UNAVAIL/TRYAGAIN | UNAVAIL | [4] | ++ | UNAVAIL/TRYAGAIN' | UNAVAIL | [4] | ++ | UNAVAIL/NOTFOUND | UNAVAIL | [4] | ++ | UNAVAIL/UNAVAIL | UNAVAIL | [4] | ++ ---------------------------------------------- ++ ++ [1] If the first response is a success we return success. ++ This ignores the state of the second answer and in fact ++ incorrectly sets errno and h_errno to that of the second ++ answer. However because the response is a success we ignore ++ *errnop and *h_errnop (though that means you touched errno on ++ success). We are being conservative here and returning the ++ likely IPv4 response in the first answer as a success. ++ ++ [2] If the first response is a recoverable TRYAGAIN we return ++ that instead of looking at the second response. The ++ expectation here is that we have failed to get an IPv4 response ++ and should retry both queries. ++ ++ [3] If the first response was not a SUCCESS and the second ++ response is not NOTFOUND (had a SUCCESS, need to TRYAGAIN, ++ or failed entirely e.g. TRYAGAIN' and UNAVAIL) then use the ++ result from the second response, otherwise the first responses ++ status is used. Again we have some odd side-effects when the ++ second response is NOTFOUND because we overwrite *errnop and ++ *h_errnop that means that a first answer of NOTFOUND might see ++ its *errnop and *h_errnop values altered. Whether it matters ++ in practice that a first response NOTFOUND has the wrong ++ *errnop and *h_errnop is undecided. ++ ++ [4] If the first response is UNAVAIL we return that instead of ++ looking at the second response. The expectation here is that ++ it will have failed similarly e.g. configuration failure. ++ ++ [5] Testing this code is complicated by the fact that truncated ++ second response buffers might be returned as SUCCESS if the ++ first answer is a SUCCESS. To fix this we add symmetry to ++ TRYAGAIN with the second response. If the second response ++ is a recoverable error we now return TRYAGIN even if the first ++ response was SUCCESS. */ ++ + if (anslen1 > 0) + status = gaih_getanswer_slice(answer1, anslen1, qname, + &pat, &buffer, &buflen, + errnop, h_errnop, ttlp, + &first); ++ + if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND + || (status == NSS_STATUS_TRYAGAIN + /* We want to look at the second answer in case of an +@@ -1242,8 +1342,15 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2, + &pat, &buffer, &buflen, + errnop, h_errnop, ttlp, + &first); ++ /* Use the second response status in some cases. */ + if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND) + status = status2; ++ /* Do not return a truncated second response (unless it was ++ unavoidable e.g. unrecoverable TRYAGAIN). */ ++ if (status == NSS_STATUS_SUCCESS ++ && (status2 == NSS_STATUS_TRYAGAIN ++ && *errnop == ERANGE && *h_errnop != NO_RECOVERY)) ++ status = NSS_STATUS_TRYAGAIN; + } + + return status; +diff --git a/resolv/res_query.c b/resolv/res_query.c +index 4a9b3b3..95470a9 100644 +--- a/resolv/res_query.c ++++ b/resolv/res_query.c +@@ -396,6 +396,7 @@ __libc_res_nsearch(res_state statp, + { + free (*answerp2); + *answerp2 = NULL; ++ *nanswerp2 = 0; + *answerp2_malloced = 0; + } + } +@@ -447,6 +448,7 @@ __libc_res_nsearch(res_state statp, + { + free (*answerp2); + *answerp2 = NULL; ++ *nanswerp2 = 0; + *answerp2_malloced = 0; + } + +@@ -521,6 +523,7 @@ __libc_res_nsearch(res_state statp, + { + free (*answerp2); + *answerp2 = NULL; ++ *nanswerp2 = 0; + *answerp2_malloced = 0; + } + if (saved_herrno != -1) +diff --git a/resolv/res_send.c b/resolv/res_send.c +index 5e53cc2..6511bb1 100644 +--- a/resolv/res_send.c ++++ b/resolv/res_send.c +@@ -1,3 +1,20 @@ ++/* Copyright (C) 2016 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ + /* + * Copyright (c) 1985, 1989, 1993 + * The Regents of the University of California. All rights reserved. +@@ -363,6 +380,8 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen, + #ifdef USE_HOOKS + if (__glibc_unlikely (statp->qhook || statp->rhook)) { + if (anssiz < MAXPACKET && ansp) { ++ /* Always allocate MAXPACKET, callers expect ++ this specific size. */ + u_char *buf = malloc (MAXPACKET); + if (buf == NULL) + return (-1); +@@ -638,6 +657,77 @@ get_nsaddr (res_state statp, int n) + return (struct sockaddr *) (void *) &statp->nsaddr_list[n]; + } + ++/* The send_vc function is responsible for sending a DNS query over TCP ++ to the nameserver numbered NS from the res_state STATP i.e. ++ EXT(statp).nssocks[ns]. The function supports sending both IPv4 and ++ IPv6 queries at the same serially on the same socket. ++ ++ Please note that for TCP there is no way to disable sending both ++ queries, unlike UDP, which honours RES_SNGLKUP and RES_SNGLKUPREOP ++ and sends the queries serially and waits for the result after each ++ sent query. This implemetnation should be corrected to honour these ++ options. ++ ++ Please also note that for TCP we send both queries over the same ++ socket one after another. This technically violates best practice ++ since the server is allowed to read the first query, respond, and ++ then close the socket (to service another client). If the server ++ does this, then the remaining second query in the socket data buffer ++ will cause the server to send the client an RST which will arrive ++ asynchronously and the client's OS will likely tear down the socket ++ receive buffer resulting in a potentially short read and lost ++ response data. This will force the client to retry the query again, ++ and this process may repeat until all servers and connection resets ++ are exhausted and then the query will fail. It's not known if this ++ happens with any frequency in real DNS server implementations. This ++ implementation should be corrected to use two sockets by default for ++ parallel queries. ++ ++ The query stored in BUF of BUFLEN length is sent first followed by ++ the query stored in BUF2 of BUFLEN2 length. Queries are sent ++ serially on the same socket. ++ ++ Answers to the query are stored firstly in *ANSP up to a max of ++ *ANSSIZP bytes. If more than *ANSSIZP bytes are needed and ANSCP ++ is non-NULL (to indicate that modifying the answer buffer is allowed) ++ then malloc is used to allocate a new response buffer and ANSCP and ++ ANSP will both point to the new buffer. If more than *ANSSIZP bytes ++ are needed but ANSCP is NULL, then as much of the response as ++ possible is read into the buffer, but the results will be truncated. ++ When truncation happens because of a small answer buffer the DNS ++ packets header field TC will bet set to 1, indicating a truncated ++ message and the rest of the socket data will be read and discarded. ++ ++ Answers to the query are stored secondly in *ANSP2 up to a max of ++ *ANSSIZP2 bytes, with the actual response length stored in ++ *RESPLEN2. If more than *ANSSIZP bytes are needed and ANSP2 ++ is non-NULL (required for a second query) then malloc is used to ++ allocate a new response buffer, *ANSSIZP2 is set to the new buffer ++ size and *ANSP2_MALLOCED is set to 1. ++ ++ The ANSP2_MALLOCED argument will eventually be removed as the ++ change in buffer pointer can be used to detect the buffer has ++ changed and that the caller should use free on the new buffer. ++ ++ Note that the answers may arrive in any order from the server and ++ therefore the first and second answer buffers may not correspond to ++ the first and second queries. ++ ++ It is not supported to call this function with a non-NULL ANSP2 ++ but a NULL ANSCP. Put another way, you can call send_vc with a ++ single unmodifiable buffer or two modifiable buffers, but no other ++ combination is supported. ++ ++ It is the caller's responsibility to free the malloc allocated ++ buffers by detecting that the pointers have changed from their ++ original values i.e. *ANSCP or *ANSP2 has changed. ++ ++ If errors are encountered then *TERRNO is set to an appropriate ++ errno value and a zero result is returned for a recoverable error, ++ and a less-than zero result is returned for a non-recoverable error. ++ ++ If no errors are encountered then *TERRNO is left unmodified and ++ a the length of the first response in bytes is returned. */ + static int + send_vc(res_state statp, + const u_char *buf, int buflen, const u_char *buf2, int buflen2, +@@ -647,11 +737,7 @@ send_vc(res_state statp, + { + const HEADER *hp = (HEADER *) buf; + const HEADER *hp2 = (HEADER *) buf2; +- u_char *ans = *ansp; +- int orig_anssizp = *anssizp; +- // XXX REMOVE +- // int anssiz = *anssizp; +- HEADER *anhp = (HEADER *) ans; ++ HEADER *anhp = (HEADER *) *ansp; + struct sockaddr *nsap = get_nsaddr (statp, ns); + int truncating, connreset, n; + /* On some architectures compiler might emit a warning indicating +@@ -743,6 +829,8 @@ send_vc(res_state statp, + * Receive length & response + */ + int recvresp1 = 0; ++ /* Skip the second response if there is no second query. ++ To do that we mark the second response as received. */ + int recvresp2 = buf2 == NULL; + uint16_t rlen16; + read_len: +@@ -779,40 +867,14 @@ send_vc(res_state statp, + u_char **thisansp; + int *thisresplenp; + if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) { ++ /* We have not received any responses ++ yet or we only have one response to ++ receive. */ + thisanssizp = anssizp; + thisansp = anscp ?: ansp; + assert (anscp != NULL || ansp2 == NULL); + thisresplenp = &resplen; + } else { +- if (*anssizp != MAXPACKET) { +- /* No buffer allocated for the first +- reply. We can try to use the rest +- of the user-provided buffer. */ +-#if __GNUC_PREREQ (4, 7) +- DIAG_PUSH_NEEDS_COMMENT; +- DIAG_IGNORE_NEEDS_COMMENT (5, "-Wmaybe-uninitialized"); +-#endif +-#if _STRING_ARCH_unaligned +- *anssizp2 = orig_anssizp - resplen; +- *ansp2 = *ansp + resplen; +-#else +- int aligned_resplen +- = ((resplen + __alignof__ (HEADER) - 1) +- & ~(__alignof__ (HEADER) - 1)); +- *anssizp2 = orig_anssizp - aligned_resplen; +- *ansp2 = *ansp + aligned_resplen; +-#endif +-#if __GNUC_PREREQ (4, 7) +- DIAG_POP_NEEDS_COMMENT; +-#endif +- } else { +- /* The first reply did not fit into the +- user-provided buffer. Maybe the second +- answer will. */ +- *anssizp2 = orig_anssizp; +- *ansp2 = *ansp; +- } +- + thisanssizp = anssizp2; + thisansp = ansp2; + thisresplenp = resplen2; +@@ -820,10 +882,14 @@ send_vc(res_state statp, + anhp = (HEADER *) *thisansp; + + *thisresplenp = rlen; +- if (rlen > *thisanssizp) { +- /* Yes, we test ANSCP here. If we have two buffers +- both will be allocatable. */ +- if (__glibc_likely (anscp != NULL)) { ++ /* Is the answer buffer too small? */ ++ if (*thisanssizp < rlen) { ++ /* If the current buffer is not the the static ++ user-supplied buffer then we can reallocate ++ it. */ ++ if (thisansp != NULL && thisansp != ansp) { ++ /* Always allocate MAXPACKET, callers expect ++ this specific size. */ + u_char *newp = malloc (MAXPACKET); + if (newp == NULL) { + *terrno = ENOMEM; +@@ -835,6 +901,9 @@ send_vc(res_state statp, + if (thisansp == ansp2) + *ansp2_malloced = 1; + anhp = (HEADER *) newp; ++ /* A uint16_t can't be larger than MAXPACKET ++ thus it's safe to allocate MAXPACKET but ++ read RLEN bytes instead. */ + len = rlen; + } else { + Dprint(statp->options & RES_DEBUG, +@@ -997,6 +1066,66 @@ reopen (res_state statp, int *terrno, int ns) + return 1; + } + ++/* The send_dg function is responsible for sending a DNS query over UDP ++ to the nameserver numbered NS from the res_state STATP i.e. ++ EXT(statp).nssocks[ns]. The function supports IPv4 and IPv6 queries ++ along with the ability to send the query in parallel for both stacks ++ (default) or serially (RES_SINGLKUP). It also supports serial lookup ++ with a close and reopen of the socket used to talk to the server ++ (RES_SNGLKUPREOP) to work around broken name servers. ++ ++ The query stored in BUF of BUFLEN length is sent first followed by ++ the query stored in BUF2 of BUFLEN2 length. Queries are sent ++ in parallel (default) or serially (RES_SINGLKUP or RES_SNGLKUPREOP). ++ ++ Answers to the query are stored firstly in *ANSP up to a max of ++ *ANSSIZP bytes. If more than *ANSSIZP bytes are needed and ANSCP ++ is non-NULL (to indicate that modifying the answer buffer is allowed) ++ then malloc is used to allocate a new response buffer and ANSCP and ++ ANSP will both point to the new buffer. If more than *ANSSIZP bytes ++ are needed but ANSCP is NULL, then as much of the response as ++ possible is read into the buffer, but the results will be truncated. ++ When truncation happens because of a small answer buffer the DNS ++ packets header field TC will bet set to 1, indicating a truncated ++ message, while the rest of the UDP packet is discarded. ++ ++ Answers to the query are stored secondly in *ANSP2 up to a max of ++ *ANSSIZP2 bytes, with the actual response length stored in ++ *RESPLEN2. If more than *ANSSIZP bytes are needed and ANSP2 ++ is non-NULL (required for a second query) then malloc is used to ++ allocate a new response buffer, *ANSSIZP2 is set to the new buffer ++ size and *ANSP2_MALLOCED is set to 1. ++ ++ The ANSP2_MALLOCED argument will eventually be removed as the ++ change in buffer pointer can be used to detect the buffer has ++ changed and that the caller should use free on the new buffer. ++ ++ Note that the answers may arrive in any order from the server and ++ therefore the first and second answer buffers may not correspond to ++ the first and second queries. ++ ++ It is not supported to call this function with a non-NULL ANSP2 ++ but a NULL ANSCP. Put another way, you can call send_vc with a ++ single unmodifiable buffer or two modifiable buffers, but no other ++ combination is supported. ++ ++ It is the caller's responsibility to free the malloc allocated ++ buffers by detecting that the pointers have changed from their ++ original values i.e. *ANSCP or *ANSP2 has changed. ++ ++ If an answer is truncated because of UDP datagram DNS limits then ++ *V_CIRCUIT is set to 1 and the return value non-zero to indicate to ++ the caller to retry with TCP. The value *GOTSOMEWHERE is set to 1 ++ if any progress was made reading a response from the nameserver and ++ is used by the caller to distinguish between ECONNREFUSED and ++ ETIMEDOUT (the latter if *GOTSOMEWHERE is 1). ++ ++ If errors are encountered then *TERRNO is set to an appropriate ++ errno value and a zero result is returned for a recoverable error, ++ and a less-than zero result is returned for a non-recoverable error. ++ ++ If no errors are encountered then *TERRNO is left unmodified and ++ a the length of the first response in bytes is returned. */ + static int + send_dg(res_state statp, + const u_char *buf, int buflen, const u_char *buf2, int buflen2, +@@ -1006,8 +1135,6 @@ send_dg(res_state statp, + { + const HEADER *hp = (HEADER *) buf; + const HEADER *hp2 = (HEADER *) buf2; +- u_char *ans = *ansp; +- int orig_anssizp = *anssizp; + struct timespec now, timeout, finish; + struct pollfd pfd[1]; + int ptimeout; +@@ -1040,6 +1167,8 @@ send_dg(res_state statp, + int need_recompute = 0; + int nwritten = 0; + int recvresp1 = 0; ++ /* Skip the second response if there is no second query. ++ To do that we mark the second response as received. */ + int recvresp2 = buf2 == NULL; + pfd[0].fd = EXT(statp).nssocks[ns]; + pfd[0].events = POLLOUT; +@@ -1203,55 +1332,56 @@ send_dg(res_state statp, + int *thisresplenp; + + if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) { ++ /* We have not received any responses ++ yet or we only have one response to ++ receive. */ + thisanssizp = anssizp; + thisansp = anscp ?: ansp; + assert (anscp != NULL || ansp2 == NULL); + thisresplenp = &resplen; + } else { +- if (*anssizp != MAXPACKET) { +- /* No buffer allocated for the first +- reply. We can try to use the rest +- of the user-provided buffer. */ +-#if _STRING_ARCH_unaligned +- *anssizp2 = orig_anssizp - resplen; +- *ansp2 = *ansp + resplen; +-#else +- int aligned_resplen +- = ((resplen + __alignof__ (HEADER) - 1) +- & ~(__alignof__ (HEADER) - 1)); +- *anssizp2 = orig_anssizp - aligned_resplen; +- *ansp2 = *ansp + aligned_resplen; +-#endif +- } else { +- /* The first reply did not fit into the +- user-provided buffer. Maybe the second +- answer will. */ +- *anssizp2 = orig_anssizp; +- *ansp2 = *ansp; +- } +- + thisanssizp = anssizp2; + thisansp = ansp2; + thisresplenp = resplen2; + } + + if (*thisanssizp < MAXPACKET +- /* Yes, we test ANSCP here. If we have two buffers +- both will be allocatable. */ +- && anscp ++ /* If the current buffer is not the the static ++ user-supplied buffer then we can reallocate ++ it. */ ++ && (thisansp != NULL && thisansp != ansp) + #ifdef FIONREAD ++ /* Is the size too small? */ + && (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0 + || *thisanssizp < *thisresplenp) + #endif + ) { ++ /* Always allocate MAXPACKET, callers expect ++ this specific size. */ + u_char *newp = malloc (MAXPACKET); + if (newp != NULL) { +- *anssizp = MAXPACKET; +- *thisansp = ans = newp; ++ *thisanssizp = MAXPACKET; ++ *thisansp = newp; + if (thisansp == ansp2) + *ansp2_malloced = 1; + } + } ++ /* We could end up with truncation if anscp was NULL ++ (not allowed to change caller's buffer) and the ++ response buffer size is too small. This isn't a ++ reliable way to detect truncation because the ioctl ++ may be an inaccurate report of the UDP message size. ++ Therefore we use this only to issue debug output. ++ To do truncation accurately with UDP we need ++ MSG_TRUNC which is only available on Linux. We ++ can abstract out the Linux-specific feature in the ++ future to detect truncation. */ ++ if (__glibc_unlikely (*thisanssizp < *thisresplenp)) { ++ Dprint(statp->options & RES_DEBUG, ++ (stdout, ";; response may be truncated (UDP)\n") ++ ); ++ } ++ + HEADER *anhp = (HEADER *) *thisansp; + socklen_t fromlen = sizeof(struct sockaddr_in6); + assert (sizeof(from) <= fromlen); +-- +1.9.4 + diff -r eece3e29fb61 -r 82efffdfec11 glibc/stuff/patches/glibc-2.22-CVE-2015-8776.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/glibc/stuff/patches/glibc-2.22-CVE-2015-8776.patch Wed Mar 15 11:41:38 2023 +0000 @@ -0,0 +1,127 @@ +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 + +diff --git a/time/strftime_l.c b/time/strftime_l.c +index b48ef34..4eb647c 100644 +--- a/time/strftime_l.c ++++ b/time/strftime_l.c +@@ -510,13 +510,17 @@ __strftime_internal (s, maxsize, format, tp, tzset_called ut_argument + 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, tp, tzset_called ut_argument + # 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, tp, tzset_called ut_argument + *tzset_called = true; + } + # endif +- zone = tzname[tp->tm_isdst]; ++ zone = tp->tm_isdst <= 1 ? tzname[tp->tm_isdst] : "?"; + } + #endif + if (! zone) +diff --git a/time/tst-strftime.c b/time/tst-strftime.c +index 374fba4..af3ff72 100644 +--- 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 () +-- +2.9.3 + diff -r eece3e29fb61 -r 82efffdfec11 glibc/stuff/patches/glibc-2.22-CVE-2015-8777.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/glibc/stuff/patches/glibc-2.22-CVE-2015-8777.patch Wed Mar 15 11:41:38 2023 +0000 @@ -0,0 +1,85 @@ +Based on: +https://sourceware.org/bugzilla/show_bug.cgi?id=18928 +https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=patch;h=dc22a1ec157d02529a0b17986679d3f1c122985e + +From dc22a1ec157d02529a0b17986679d3f1c122985e 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. + +--- + elf/rtld.c | 15 ++++----------- + sysdeps/generic/ldsodefs.h | 3 --- + 2 files changed, 4 insertions(+), 14 deletions(-) + +diff --git a/elf/rtld.c b/elf/rtld.c +index 5043046..6c2632d 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -162,7 +162,6 @@ struct rtld_global_ro _rtld_global_ro attribute_relro = + ._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 +@@ -2472,9 +2468,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: +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 7a0fe8d..78e3a97 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -592,9 +592,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) +-- +2.17.1 + diff -r eece3e29fb61 -r 82efffdfec11 glibc/stuff/patches/glibc-2.22-CVE-2015-8778.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/glibc/stuff/patches/glibc-2.22-CVE-2015-8778.patch Wed Mar 15 11:41:38 2023 +0000 @@ -0,0 +1,171 @@ +Based on: +https://sourceware.org/bugzilla/show_bug.cgi?id=18240 +https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=patch;h=bae7c7c764413b23e61cb099ce33be4c4ee259bb + +From 287de30e170cb765ed326d23d22791a81aab6e0f Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 28 Jan 2016 13:59:11 +0100 +Subject: [PATCH] Improve check against integer wraparound in hcreate_r [BZ + #18240] +--- + misc/Makefile | 3 +- + misc/bug18240.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++ + misc/hsearch_r.c | 30 +++++++++++-------- + 3 files changed, 95 insertions(+), 13 deletions(-) + create mode 100644 misc/bug18240.c + +diff --git a/misc/Makefile b/misc/Makefile +index aecb0da..704c2e5 100644 +--- a/misc/Makefile ++++ b/misc/Makefile +@@ -76,7 +76,8 @@ install-lib := libg.a + gpl2lgpl := error.c error.h + + tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch \ +- tst-error1 tst-pselect tst-insremque tst-mntent2 bug-hsearch1 ++ tst-error1 tst-pselect tst-insremque tst-mntent2 bug-hsearch1 \ ++ bug18240 + ifeq ($(run-built-tests),yes) + tests-special += $(objpfx)tst-error1-mem.out + endif +diff --git a/misc/bug18240.c b/misc/bug18240.c +new file mode 100644 +index 0000000..4b26865 +--- /dev/null ++++ b/misc/bug18240.c +@@ -0,0 +1,75 @@ ++/* Test integer wraparound in hcreate. ++ Copyright (C) 2016 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static void ++test_size (size_t size) ++{ ++ int res = hcreate (size); ++ if (res == 0) ++ { ++ if (errno == ENOMEM) ++ return; ++ printf ("error: hcreate (%zu): %m\n", size); ++ exit (1); ++ } ++ char *keys[100]; ++ for (int i = 0; i < 100; ++i) ++ { ++ if (asprintf (keys + i, "%d", i) < 0) ++ { ++ printf ("error: asprintf: %m\n"); ++ exit (1); ++ } ++ ENTRY e = { keys[i], (char *) "value" }; ++ if (hsearch (e, ENTER) == NULL) ++ { ++ printf ("error: hsearch (\"%s\"): %m\n", keys[i]); ++ exit (1); ++ } ++ } ++ hdestroy (); ++ ++ for (int i = 0; i < 100; ++i) ++ free (keys[i]); ++} ++ ++static int ++do_test (void) ++{ ++ test_size (500); ++ test_size (-1); ++ test_size (-3); ++ test_size (INT_MAX - 2); ++ test_size (INT_MAX - 1); ++ test_size (INT_MAX); ++ test_size (((unsigned) INT_MAX) + 1); ++ test_size (UINT_MAX - 2); ++ test_size (UINT_MAX - 1); ++ test_size (UINT_MAX); ++ return 0; ++} ++ ++#define TEST_FUNCTION do_test () ++#include "../test-skeleton.c" +diff --git a/misc/hsearch_r.c b/misc/hsearch_r.c +index 9f55e84..661f0f6 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 +@@ -46,15 +46,12 @@ static int + isprime (unsigned int number) + { + /* no even number will be passed */ +- unsigned int div = 3; +- +- while (div * div < number && number % div != 0) +- div += 2; +- +- return number % div != 0; ++ for (unsigned int div = 3; div <= number / div; div += 2) ++ if (number % div == 0) ++ return 0; ++ return 1; + } + +- + /* Before using the hash table we must allocate memory for it. + Test for an existing table are done. We allocate one element + more as the found prime number says. This is done for more effective +@@ -81,10 +78,19 @@ __hcreate_r (nel, htab) + use will not work. */ + if (nel < 3) + nel = 3; +- /* Change nel to the first prime number not smaller as nel. */ +- nel |= 1; /* make odd */ +- while (!isprime (nel)) +- nel += 2; ++ ++ /* Change nel to the first prime number in the range [nel, UINT_MAX - 2], ++ The '- 2' means 'nel += 2' cannot overflow. */ ++ for (nel |= 1; ; nel += 2) ++ { ++ if (UINT_MAX - 2 < nel) ++ { ++ __set_errno (ENOMEM); ++ return 0; ++ } ++ if (isprime (nel)) ++ break; ++ } + + htab->size = nel; + htab->filled = 0; +-- +2.17.1 + diff -r eece3e29fb61 -r 82efffdfec11 glibc/stuff/patches/glibc-2.22-CVE-2015-8779.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/glibc/stuff/patches/glibc-2.22-CVE-2015-8779.patch Wed Mar 15 11:41:38 2023 +0000 @@ -0,0 +1,231 @@ +Based on: +https://sourceware.org/bugzilla/show_bug.cgi?id=17905 +https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=patch;h=0f58539030e436449f79189b6edab17d7479796e +https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=patch;h=7565d2a862683a3c26ffb1f32351b8c5ab9f7b31 + +From afd269312ea8aef752b8e4c2531bdd920a085708 Mon Sep 17 00:00:00 2001 +From: Paul Pluzhnikov +Date: Sat, 8 Aug 2015 15:53:03 -0700 +Subject: [PATCH] Fix BZ #17905 + +--- + catgets/Makefile | 9 ++++++++- + catgets/catgets.c | 19 ++++++++++++------- + catgets/open_catalog.c | 23 ++++++++++++++--------- + catgets/tst-catgets.c | 31 +++++++++++++++++++++++++++++++ + 4 files changed, 65 insertions(+), 17 deletions(-) + +diff --git a/catgets/Makefile b/catgets/Makefile +index 4624a88..56de38b 100644 +--- 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='"$(msgcatdir)/%L/%N:$(msgcatdir)/%L/LC_MESSAGES/% + + 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)test-gencat \ + $(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 +diff --git a/catgets/catgets.c b/catgets/catgets.c +index cf93d56..4be452d 100644 +--- 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; + } + +diff --git a/catgets/open_catalog.c b/catgets/open_catalog.c +index e069416..9f4d776 100644 +--- a/catgets/open_catalog.c ++++ b/catgets/open_catalog.c +@@ -47,6 +47,7 @@ __open_catalog (const char *cat_name, const char *nlspath, const char *env_var, + 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, const char *nlspath, const char *env_var, + 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, const char *nlspath, const char *env_var, + + /* 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, const char *nlspath, const char *env_var, + /* Release the lock again. */ + close_unlock_return: + close_not_cancel_no_status (fd); ++ free (buf); + + return result; + } +diff --git a/catgets/tst-catgets.c b/catgets/tst-catgets.c +index a0a4089..0886938 100644 +--- 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; + } + +-- +2.17.1 + diff -r eece3e29fb61 -r 82efffdfec11 glibc/stuff/patches/glibc-2.22-CVE-2016-1234.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/glibc/stuff/patches/glibc-2.22-CVE-2016-1234.patch Wed Mar 15 11:41:38 2023 +0000 @@ -0,0 +1,384 @@ +Based on: + +https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=patch;h=5171f3079f2cc53e0548fc4967361f4d1ce9d7ea + +From 5171f3079f2cc53e0548fc4967361f4d1ce9d7ea Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Wed, 4 May 2016 12:09:35 +0200 +Subject: [PATCH] CVE-2016-1234: glob: Do not copy d_name field of struct + dirent [BZ #19779] + +Instead, we store the data we need from the return value of +readdir in an object of the new type struct readdir_result. +This type is independent of the layout of struct dirent. + +diff -Naur a/posix/bug-glob2.c b/posix/bug-glob2.c +--- a/posix/bug-glob2.c 2017-08-24 19:56:49.025759608 +0530 ++++ b/posix/bug-glob2.c 2017-08-24 20:04:01.171777373 +0530 +@@ -40,6 +40,17 @@ + # define PRINTF(fmt, args...) + #endif + ++#define LONG_NAME \ ++ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ ++ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ ++ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ ++ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ ++ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ ++ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ ++ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ ++ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ ++ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ ++ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + static struct + { +@@ -58,6 +69,7 @@ + { ".", 3, DT_DIR, 0755 }, + { "..", 3, DT_DIR, 0755 }, + { "a", 3, DT_REG, 0644 }, ++ { LONG_NAME, 3, DT_REG, 0644 }, + { "unreadable", 2, DT_DIR, 0111 }, + { ".", 3, DT_DIR, 0111 }, + { "..", 3, DT_DIR, 0755 }, +@@ -75,7 +87,7 @@ + int level; + int idx; + struct dirent d; +- char room_for_dirent[NAME_MAX]; ++ char room_for_dirent[sizeof (LONG_NAME)]; + } my_DIR; + + +diff -Naur a/posix/glob.c b/posix/glob.c +--- a/posix/glob.c 2017-08-24 19:56:49.025759608 +0530 ++++ b/posix/glob.c 2017-08-24 20:11:58.123495376 +0530 +@@ -24,7 +24,9 @@ + #include + #include + #include ++#include + #include ++#include + + /* Outcomment the following line for production quality code. */ + /* #define NDEBUG 1 */ +@@ -82,75 +84,8 @@ + # define NAMLEN(d) _D_NAMLEN(d) + #endif + +-/* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available +- if the `d_type' member for `struct dirent' is available. +- HAVE_STRUCT_DIRENT_D_TYPE plays the same role in GNULIB. */ +-#if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE +-/* True if the directory entry D must be of type T. */ +-# define DIRENT_MUST_BE(d, t) ((d)->d_type == (t)) +- +-/* True if the directory entry D might be a symbolic link. */ +-# define DIRENT_MIGHT_BE_SYMLINK(d) \ +- ((d)->d_type == DT_UNKNOWN || (d)->d_type == DT_LNK) +- +-/* True if the directory entry D might be a directory. */ +-# define DIRENT_MIGHT_BE_DIR(d) \ +- ((d)->d_type == DT_DIR || DIRENT_MIGHT_BE_SYMLINK (d)) +- +-#else /* !HAVE_D_TYPE */ +-# define DIRENT_MUST_BE(d, t) false +-# define DIRENT_MIGHT_BE_SYMLINK(d) true +-# define DIRENT_MIGHT_BE_DIR(d) true +-#endif /* HAVE_D_TYPE */ +- +-/* If the system has the `struct dirent64' type we use it internally. */ +-#if defined _LIBC && !defined COMPILE_GLOB64 +-# if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__ +-# define CONVERT_D_NAMLEN(d64, d32) +-# else +-# define CONVERT_D_NAMLEN(d64, d32) \ +- (d64)->d_namlen = (d32)->d_namlen; +-# endif +- +-# if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__ +-# define CONVERT_D_INO(d64, d32) +-# else +-# define CONVERT_D_INO(d64, d32) \ +- (d64)->d_ino = (d32)->d_ino; +-# endif +- +-# ifdef _DIRENT_HAVE_D_TYPE +-# define CONVERT_D_TYPE(d64, d32) \ +- (d64)->d_type = (d32)->d_type; +-# else +-# define CONVERT_D_TYPE(d64, d32) +-# endif +- +-# define CONVERT_DIRENT_DIRENT64(d64, d32) \ +- memcpy ((d64)->d_name, (d32)->d_name, NAMLEN (d32) + 1); \ +- CONVERT_D_NAMLEN (d64, d32) \ +- CONVERT_D_INO (d64, d32) \ +- CONVERT_D_TYPE (d64, d32) +-#endif +- +- +-#if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__ +-/* Posix does not require that the d_ino field be present, and some +- systems do not provide it. */ +-# define REAL_DIR_ENTRY(dp) 1 +-#else +-# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0) +-#endif /* POSIX */ +- + #include + #include +- +-/* NAME_MAX is usually defined in or . */ +-#include +-#ifndef NAME_MAX +-# define NAME_MAX (sizeof (((struct dirent *) 0)->d_name)) +-#endif +- + #include + + #ifdef _LIBC +@@ -195,8 +130,111 @@ + + static const char *next_brace_sub (const char *begin, int flags) __THROWNL; + ++/* A representation of a directory entry which does not depend on the ++ layout of struct dirent, or the size of ino_t. */ ++struct readdir_result ++{ ++ const char *name; ++# if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE ++ uint8_t type; ++# endif ++ bool skip_entry; ++}; ++ ++# if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE ++/* Initializer based on the d_type member of struct dirent. */ ++# define D_TYPE_TO_RESULT(source) (source)->d_type, ++ ++/* True if the directory entry D might be a symbolic link. */ ++static bool ++readdir_result_might_be_symlink (struct readdir_result d) ++{ ++ return d.type == DT_UNKNOWN || d.type == DT_LNK; ++} ++ ++/* True if the directory entry D might be a directory. */ ++static bool ++readdir_result_might_be_dir (struct readdir_result d) ++{ ++ return d.type == DT_DIR || readdir_result_might_be_symlink (d); ++} ++# else /* defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE */ ++# define D_TYPE_TO_RESULT(source) ++ ++/* If we do not have type information, symbolic links and directories ++ are always a possibility. */ ++ ++static bool ++readdir_result_might_be_symlink (struct readdir_result d) ++{ ++ return true; ++} ++ ++static bool ++readdir_result_might_be_dir (struct readdir_result d) ++{ ++ return true; ++} ++ ++# endif /* defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE */ ++ ++# if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__ ++/* Initializer for skip_entry. POSIX does not require that the d_ino ++ field be present, and some systems do not provide it. */ ++# define D_INO_TO_RESULT(source) false, ++# else ++# define D_INO_TO_RESULT(source) (source)->d_ino == 0, ++# endif ++ ++/* Construct an initializer for a struct readdir_result object from a ++ struct dirent *. No copy of the name is made. */ ++#define READDIR_RESULT_INITIALIZER(source) \ ++ { \ ++ source->d_name, \ ++ D_TYPE_TO_RESULT (source) \ ++ D_INO_TO_RESULT (source) \ ++ } ++ + #endif /* !defined _LIBC || !defined GLOB_ONLY_P */ + ++/* Call gl_readdir on STREAM. This macro can be overridden to reduce ++ type safety if an old interface version needs to be supported. */ ++#ifndef GL_READDIR ++# define GL_READDIR(pglob, stream) ((pglob)->gl_readdir (stream)) ++#endif ++ ++/* Extract name and type from directory entry. No copy of the name is ++ made. If SOURCE is NULL, result name is NULL. Keep in sync with ++ convert_dirent64 below. */ ++static struct readdir_result ++convert_dirent (const struct dirent *source) ++{ ++ if (source == NULL) ++ { ++ struct readdir_result result = { NULL, }; ++ return result; ++ } ++ struct readdir_result result = READDIR_RESULT_INITIALIZER (source); ++ return result; ++} ++ ++#ifndef COMPILE_GLOB64 ++/* Like convert_dirent, but works on struct dirent64 instead. Keep in ++ sync with convert_dirent above. */ ++static struct readdir_result ++convert_dirent64 (const struct dirent64 *source) ++{ ++ if (source == NULL) ++ { ++ struct readdir_result result = { NULL, }; ++ return result; ++ } ++ struct readdir_result result = READDIR_RESULT_INITIALIZER (source); ++ return result; ++} ++#endif ++ ++ + #ifndef attribute_hidden + # define attribute_hidden + #endif +@@ -1561,56 +1599,36 @@ + + while (1) + { +- const char *name; +- size_t len; +-#if defined _LIBC && !defined COMPILE_GLOB64 +- struct dirent64 *d; +- union +- { +- struct dirent64 d64; +- char room [offsetof (struct dirent64, d_name[0]) +- + NAME_MAX + 1]; +- } +- d64buf; +- +- if (__glibc_unlikely (flags & GLOB_ALTDIRFUNC)) +- { +- struct dirent *d32 = (*pglob->gl_readdir) (stream); +- if (d32 != NULL) +- { +- CONVERT_DIRENT_DIRENT64 (&d64buf.d64, d32); +- d = &d64buf.d64; +- } +- else +- d = NULL; +- } +- else +- d = __readdir64 (stream); ++ struct readdir_result d; ++ { ++ if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)) ++ d = convert_dirent (GL_READDIR (pglob, stream)); ++ else ++ { ++#ifdef COMPILE_GLOB64 ++ d = convert_dirent (__readdir (stream)); + #else +- struct dirent *d = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0) +- ? ((struct dirent *) +- (*pglob->gl_readdir) (stream)) +- : __readdir (stream)); ++ d = convert_dirent64 (__readdir64 (stream)); + #endif +- if (d == NULL) ++ } ++ } ++ if (d.name == NULL) + break; +- if (! REAL_DIR_ENTRY (d)) ++ if (d.skip_entry) + continue; + + /* If we shall match only directories use the information + provided by the dirent call if possible. */ +- if ((flags & GLOB_ONLYDIR) && !DIRENT_MIGHT_BE_DIR (d)) ++ if ((flags & GLOB_ONLYDIR) && !readdir_result_might_be_dir (d)) + continue; + +- name = d->d_name; +- +- if (fnmatch (pattern, name, fnm_flags) == 0) ++ if (fnmatch (pattern, d.name, fnm_flags) == 0) + { + /* If the file we found is a symlink we have to + make sure the target file exists. */ +- if (!DIRENT_MIGHT_BE_SYMLINK (d) +- || link_exists_p (dfd, directory, dirlen, name, pglob, +- flags)) ++ if (!readdir_result_might_be_symlink (d) ++ || link_exists_p (dfd, directory, dirlen, d.name, ++ pglob, flags)) + { + if (cur == names->count) + { +@@ -1630,12 +1648,10 @@ + names = newnames; + cur = 0; + } +- len = NAMLEN (d); +- names->name[cur] = (char *) malloc (len + 1); ++ names->name[cur] = strdup (d.name); + if (names->name[cur] == NULL) + goto memory_error; +- *((char *) mempcpy (names->name[cur++], name, len)) +- = '\0'; ++ ++cur; + ++nfound; + } + } +diff -Naur a/sysdeps/unix/sysv/linux/i386/glob64.c b/sysdeps/unix/sysv/linux/i386/glob64.c +--- a/sysdeps/unix/sysv/linux/i386/glob64.c 2017-08-24 19:56:49.193740138 +0530 ++++ b/sysdeps/unix/sysv/linux/i386/glob64.c 2017-08-24 20:04:01.175781134 +0530 +@@ -1,3 +1,21 @@ ++/* Two glob variants with 64-bit support, for dirent64 and __olddirent64. ++ Copyright (C) 1998-2016 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ + #include + #include + #include +@@ -38,11 +56,15 @@ + + #undef dirent + #define dirent __old_dirent64 ++#undef GL_READDIR ++# define GL_READDIR(pglob, stream) \ ++ ((struct __old_dirent64 *) (pglob)->gl_readdir (stream)) + #undef __readdir + #define __readdir(dirp) __old_readdir64 (dirp) + #undef glob + #define glob(pattern, flags, errfunc, pglob) \ + __old_glob64 (pattern, flags, errfunc, pglob) ++#define convert_dirent __old_convert_dirent + #define glob_in_dir __old_glob_in_dir + #define GLOB_ATTRIBUTE attribute_compat_text_section + diff -r eece3e29fb61 -r 82efffdfec11 glibc/stuff/patches/glibc-2.22-CVE-2016-3075.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/glibc/stuff/patches/glibc-2.22-CVE-2016-3075.patch Wed Mar 15 11:41:38 2023 +0000 @@ -0,0 +1,35 @@ +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. + +diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c +index 2eb2f67..8f301a7 100644 +--- a/resolv/nss_dns/dns-network.c ++++ b/resolv/nss_dns/dns-network.c +@@ -118,17 +118,14 @@ _nss_dns_getnetbyname_r (const char *name, struct netent *result, + } 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) + { +-- +2.9.3 + diff -r eece3e29fb61 -r 82efffdfec11 glibc/stuff/patches/glibc-2.22-CVE-2016-3706.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/glibc/stuff/patches/glibc-2.22-CVE-2016-3706.patch Wed Mar 15 11:41:38 2023 +0000 @@ -0,0 +1,182 @@ +From 4ab2ab03d4351914ee53248dc5aef4a8c88ff8b9 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Fri, 29 Apr 2016 10:35:34 +0200 +Subject: [PATCH] CVE-2016-3706: getaddrinfo: stack overflow in hostent + conversion [BZ #20010] + +When converting a struct hostent response to struct gaih_addrtuple, the +gethosts macro (which is called from gaih_inet) used alloca, without +malloc fallback for large responses. This commit changes this code to +use calloc unconditionally. + +This commit also consolidated a second hostent-to-gaih_addrtuple +conversion loop (in gaih_inet) to use the new conversion function. + +diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c +index 1ef3f20..fed2d3b 100644 +--- a/sysdeps/posix/getaddrinfo.c ++++ b/sysdeps/posix/getaddrinfo.c +@@ -168,9 +168,58 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp, + return 0; + } + ++/* Convert struct hostent to a list of struct gaih_addrtuple objects. ++ h_name is not copied, and the struct hostent object must not be ++ deallocated prematurely. *RESULT must be NULL or a pointer to an ++ object allocated using malloc, which is freed. */ ++static bool ++convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, ++ int family, ++ struct hostent *h, ++ struct gaih_addrtuple **result) ++{ ++ free (*result); ++ *result = NULL; ++ ++ /* Count the number of addresses in h->h_addr_list. */ ++ size_t count = 0; ++ for (char **p = h->h_addr_list; *p != NULL; ++p) ++ ++count; ++ ++ /* Report no data if no addresses are available, or if the incoming ++ address size is larger than what we can store. */ ++ if (count == 0 || h->h_length > sizeof (((struct gaih_addrtuple) {}).addr)) ++ return true; ++ ++ struct gaih_addrtuple *array = calloc (count, sizeof (*array)); ++ if (array == NULL) ++ return false; ++ ++ for (size_t i = 0; i < count; ++i) ++ { ++ if (family == AF_INET && req->ai_family == AF_INET6) ++ { ++ /* Perform address mapping. */ ++ array[i].family = AF_INET6; ++ memcpy(array[i].addr + 3, h->h_addr_list[i], sizeof (uint32_t)); ++ array[i].addr[2] = htonl (0xffff); ++ } ++ else ++ { ++ array[i].family = family; ++ memcpy (array[i].addr, h->h_addr_list[i], h->h_length); ++ } ++ array[i].next = array + i + 1; ++ } ++ array[0].name = h->h_name; ++ array[count - 1].next = NULL; ++ ++ *result = array; ++ return true; ++} ++ + #define gethosts(_family, _type) \ + { \ +- int i; \ + int herrno; \ + struct hostent th; \ + struct hostent *h; \ +@@ -219,36 +268,23 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp, + } \ + else if (h != NULL) \ + { \ +- for (i = 0; h->h_addr_list[i]; i++) \ ++ /* Make sure that addrmem can be freed. */ \ ++ if (!malloc_addrmem) \ ++ addrmem = NULL; \ ++ if (!convert_hostent_to_gaih_addrtuple (req, _family,h, &addrmem)) \ + { \ +- if (*pat == NULL) \ +- { \ +- *pat = __alloca (sizeof (struct gaih_addrtuple)); \ +- (*pat)->scopeid = 0; \ +- } \ +- uint32_t *addr = (*pat)->addr; \ +- (*pat)->next = NULL; \ +- (*pat)->name = i == 0 ? strdupa (h->h_name) : NULL; \ +- if (_family == AF_INET && req->ai_family == AF_INET6) \ +- { \ +- (*pat)->family = AF_INET6; \ +- addr[3] = *(uint32_t *) h->h_addr_list[i]; \ +- addr[2] = htonl (0xffff); \ +- addr[1] = 0; \ +- addr[0] = 0; \ +- } \ +- else \ +- { \ +- (*pat)->family = _family; \ +- memcpy (addr, h->h_addr_list[i], sizeof(_type)); \ +- } \ +- pat = &((*pat)->next); \ ++ _res.options |= old_res_options & RES_USE_INET6; \ ++ result = -EAI_SYSTEM; \ ++ goto free_and_return; \ + } \ ++ *pat = addrmem; \ ++ /* The conversion uses malloc unconditionally. */ \ ++ malloc_addrmem = true; \ + \ + if (localcanon != NULL && canon == NULL) \ + canon = strdupa (localcanon); \ + \ +- if (_family == AF_INET6 && i > 0) \ ++ if (_family == AF_INET6 && *pat != NULL) \ + got_ipv6 = true; \ + } \ + } +@@ -612,44 +648,16 @@ gaih_inet (const char *name, const struct gaih_service *service, + { + if (h != NULL) + { +- int i; +- /* We found data, count the number of addresses. */ +- for (i = 0; h->h_addr_list[i]; ++i) +- ; +- if (i > 0 && *pat != NULL) +- --i; +- +- if (__libc_use_alloca (alloca_used +- + i * sizeof (struct gaih_addrtuple))) +- addrmem = alloca_account (i * sizeof (struct gaih_addrtuple), +- alloca_used); +- else +- { +- addrmem = malloc (i +- * sizeof (struct gaih_addrtuple)); +- if (addrmem == NULL) +- { +- result = -EAI_MEMORY; +- goto free_and_return; +- } +- malloc_addrmem = true; +- } +- +- /* Now convert it into the list. */ +- struct gaih_addrtuple *addrfree = addrmem; +- for (i = 0; h->h_addr_list[i]; ++i) ++ /* We found data, convert it. */ ++ if (!convert_hostent_to_gaih_addrtuple ++ (req, AF_INET, h, &addrmem)) + { +- if (*pat == NULL) +- { +- *pat = addrfree++; +- (*pat)->scopeid = 0; +- } +- (*pat)->next = NULL; +- (*pat)->family = AF_INET; +- memcpy ((*pat)->addr, h->h_addr_list[i], +- h->h_length); +- pat = &((*pat)->next); ++ result = -EAI_MEMORY; ++ goto free_and_return; + } ++ *pat = addrmem; ++ /* The conversion uses malloc unconditionally. */ ++ malloc_addrmem = true; + } + } + else +-- +2.9.3 + diff -r eece3e29fb61 -r 82efffdfec11 glibc/stuff/patches/glibc-2.22-CVE-2016-4429.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/glibc/stuff/patches/glibc-2.22-CVE-2016-4429.patch Wed Mar 15 11:41:38 2023 +0000 @@ -0,0 +1,51 @@ +Based on: + +https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=patch;h=bc779a1a5b3035133024b21e2f339fe4219fb11c + +From bc779a1a5b3035133024b21e2f339fe4219fb11c Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Mon, 23 May 2016 20:18:34 +0200 +Subject: [PATCH] CVE-2016-4429: sunrpc: Do not use alloca in clntudp_call [BZ + #20112] + +The call is technically in a loop, and under certain circumstances +(which are quite difficult to reproduce in a test case), alloca +can be invoked repeatedly during a single call to clntudp_call. +As a result, the available stack space can be exhausted (even +though individual alloca sizes are bounded implicitly by what +can fit into a UDP packet, as a side effect of the earlier +successful send operation). + +diff -Naur a/sunrpc/clnt_udp.c b/sunrpc/clnt_udp.c +--- a/sunrpc/clnt_udp.c 2017-08-24 20:21:20.731588445 +0530 ++++ b/sunrpc/clnt_udp.c 2017-08-24 20:20:30.188928541 +0530 +@@ -420,9 +420,15 @@ + struct sock_extended_err *e; + struct sockaddr_in err_addr; + struct iovec iov; +- char *cbuf = (char *) alloca (outlen + 256); ++ char *cbuf = malloc (outlen + 256); + int ret; + ++ if (cbuf == NULL) ++ { ++ cu->cu_error.re_errno = errno; ++ return (cu->cu_error.re_status = RPC_CANTRECV); ++ } ++ + iov.iov_base = cbuf + 256; + iov.iov_len = outlen; + msg.msg_name = (void *) &err_addr; +@@ -447,10 +453,12 @@ + cmsg = CMSG_NXTHDR (&msg, cmsg)) + if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR) + { ++ free (cbuf); + e = (struct sock_extended_err *) CMSG_DATA(cmsg); + cu->cu_error.re_errno = e->ee_errno; + return (cu->cu_error.re_status = RPC_CANTRECV); + } ++ free (cbuf); + } + #endif + do diff -r eece3e29fb61 -r 82efffdfec11 glibc/stuff/patches/glibc-2.22-CVE-2016-5417.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/glibc/stuff/patches/glibc-2.22-CVE-2016-5417.patch Wed Mar 15 11:41:38 2023 +0000 @@ -0,0 +1,19 @@ +Based on + +From 5e7fdabd7df1fc6c56d104e61390bf5a6b526c38 Mon Sep 17 00:00:00 2001 +From: Andreas Schwab +Date: Wed, 18 Nov 2015 15:45:59 +0100 +Subject: [PATCH] Fix resource leak in resolver (bug 19257) + +diff -Naur a/resolv/res_init.c b/resolv/res_init.c +--- a/resolv/res_init.c 2017-12-15 12:47:48.763854624 +0530 ++++ b/resolv/res_init.c 2017-12-15 12:48:54.047853203 +0530 +@@ -593,7 +593,7 @@ + statp->_vcsock = -1; + statp->_flags &= ~(RES_F_VC | RES_F_CONN); + } +- for (ns = 0; ns < statp->_u._ext.nscount; ns++) ++ for (ns = 0; ns < statp->nscount; ns++) + if (statp->_u._ext.nsaddrs[ns]) { + if (statp->_u._ext.nssocks[ns] != -1) { + close_not_cancel_no_status(statp->_u._ext.nssocks[ns]); diff -r eece3e29fb61 -r 82efffdfec11 glibc/stuff/patches/glibc-2.22-CVE-2016-6323.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/glibc/stuff/patches/glibc-2.22-CVE-2016-6323.patch Wed Mar 15 11:41:38 2023 +0000 @@ -0,0 +1,30 @@ +Based on + +From 9e2ff6c9cc54c0b4402b8d49e4abe7000fde7617 Mon Sep 17 00:00:00 2001 +From: Andreas Schwab +Date: Mon, 8 Aug 2016 09:29:18 +0200 +Subject: [PATCH] arm: mark __startcontext as .cantunwind (bug 20435) + +diff -Naur a/sysdeps/unix/sysv/linux/arm/setcontext.S b/sysdeps/unix/sysv/linux/arm/setcontext.S +--- a/sysdeps/unix/sysv/linux/arm/setcontext.S 2017-12-18 12:08:38.222265391 +0530 ++++ b/sysdeps/unix/sysv/linux/arm/setcontext.S 2017-12-18 12:09:15.202264587 +0530 +@@ -86,12 +86,19 @@ + + /* Called when a makecontext() context returns. Start the + context in R4 or fall through to exit(). */ ++ /* Unwind descriptors are looked up based on PC - 2, so we have to ++ make sure to mark the instruction preceding the __startcontext ++ label as .cantunwind. */ ++ .fnstart ++ .cantunwind ++ nop + ENTRY(__startcontext) + movs r0, r4 + bne PLTJMP(__setcontext) + + @ New context was 0 - exit + b PLTJMP(HIDDEN_JUMPTARGET(exit)) ++ .fnend + END(__startcontext) + + #ifdef PIC diff -r eece3e29fb61 -r 82efffdfec11 glibc/stuff/patches/glibc-2.22-CVE-2017-1000366.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/glibc/stuff/patches/glibc-2.22-CVE-2017-1000366.patch Wed Mar 15 11:41:38 2023 +0000 @@ -0,0 +1,37 @@ +Based on: +https://sourceware.org/bugzilla/show_bug.cgi?id=CVE-2017-1000366 +https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=patch;h=efa26d9c13a6fabd34a05139e1d8b2e441b2fae9 + +From efa26d9c13a6fabd34a05139e1d8b2e441b2fae9 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Mon, 19 Jun 2017 18:34:53 +0200 +Subject: [PATCH] CVE-2017-1000366: Ignore LD_LIBRARY_PATH for AT_SECURE=1 + programs [BZ #21624] + +LD_LIBRARY_PATH can only be used to reorder system search paths, which +is not useful functionality. + +This makes an exploitable unbounded alloca in _dl_init_paths unreachable +for AT_SECURE=1 programs. + +--- + elf/rtld.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/elf/rtld.c b/elf/rtld.c +index 69873c2..5043046 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -2441,7 +2441,8 @@ process_envvars (enum mode *modep) + + case 12: + /* The library search path. */ +- if (memcmp (envline, "LIBRARY_PATH", 12) == 0) ++ if (!__libc_enable_secure ++ && memcmp (envline, "LIBRARY_PATH", 12) == 0) + { + library_path = &envline[13]; + break; +-- +2.17.1 + diff -r eece3e29fb61 -r 82efffdfec11 glibc/stuff/patches/glibc-2.22-CVE-2017-12133.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/glibc/stuff/patches/glibc-2.22-CVE-2017-12133.patch Wed Mar 15 11:41:38 2023 +0000 @@ -0,0 +1,133 @@ +Based on: +https://sourceware.org/bugzilla/show_bug.cgi?id=21115 +https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=patch;h=d42eed4a044e5e10dfb885cf9891c2518a72a491 + +From d42eed4a044e5e10dfb885cf9891c2518a72a491 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Mon, 27 Feb 2017 19:05:13 +0100 +Subject: [PATCH] sunrpc: Avoid use-after-free read access in clntudp_call [BZ + #21115] + +After commit bc779a1a5b3035133024b21e2f339fe4219fb11c +(CVE-2016-4429: sunrpc: Do not use alloca in clntudp_call +[BZ #20112]), ancillary data is stored on the heap, +but it is accessed after it has been freed. + +The test case must be run under a heap debugger such as valgrind +to observe the invalid access. A malloc implementation which +immediately calls munmap on free would catch this bug as well. + +--- + sunrpc/Makefile | 3 +- + sunrpc/clnt_udp.c | 2 +- + sunrpc/tst-udp-error.c | 62 ++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 65 insertions(+), 2 deletions(-) + create mode 100644 sunrpc/tst-udp-error.c + +diff --git a/sunrpc/Makefile b/sunrpc/Makefile +index 60caa0a..4f74f27 100644 +--- a/sunrpc/Makefile ++++ b/sunrpc/Makefile +@@ -96,7 +96,7 @@ rpcgen-objs = rpc_main.o rpc_hout.o rpc_cout.o rpc_parse.o \ + extra-objs = $(rpcgen-objs) $(addprefix cross-,$(rpcgen-objs)) + others += rpcgen + +-tests = tst-xdrmem tst-xdrmem2 test-rpcent ++tests = tst-xdrmem tst-xdrmem2 test-rpcent tst-udp-error + xtests := tst-getmyaddr + + ifeq ($(have-thread-library),yes) +@@ -153,6 +153,7 @@ BUILD_CPPFLAGS += $(sunrpc-CPPFLAGS) + $(objpfx)tst-getmyaddr: $(common-objpfx)linkobj/libc.so + $(objpfx)tst-xdrmem: $(common-objpfx)linkobj/libc.so + $(objpfx)tst-xdrmem2: $(common-objpfx)linkobj/libc.so ++$(objpfx)tst-udp-error: $(common-objpfx)linkobj/libc.so + + $(objpfx)rpcgen: $(addprefix $(objpfx),$(rpcgen-objs)) + +diff --git a/sunrpc/clnt_udp.c b/sunrpc/clnt_udp.c +index c818caf..30613e3 100644 +--- a/sunrpc/clnt_udp.c ++++ b/sunrpc/clnt_udp.c +@@ -453,9 +453,9 @@ send_again: + cmsg = CMSG_NXTHDR (&msg, cmsg)) + if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR) + { +- free (cbuf); + e = (struct sock_extended_err *) CMSG_DATA(cmsg); + cu->cu_error.re_errno = e->ee_errno; ++ free (cbuf); + return (cu->cu_error.re_status = RPC_CANTRECV); + } + free (cbuf); +diff --git a/sunrpc/tst-udp-error.c b/sunrpc/tst-udp-error.c +new file mode 100644 +index 0000000..1efc02f +--- /dev/null ++++ b/sunrpc/tst-udp-error.c +@@ -0,0 +1,62 @@ ++/* Check for use-after-free in clntudp_call (bug 21115). ++ Copyright (C) 2017 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 ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ support_become_root (); ++ support_enter_network_namespace (); ++ ++ /* Obtain a likely-unused port number. */ ++ struct sockaddr_in sin = ++ { ++ .sin_family = AF_INET, ++ .sin_addr.s_addr = htonl (INADDR_LOOPBACK), ++ }; ++ { ++ int fd = xsocket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); ++ xbind (fd, (struct sockaddr *) &sin, sizeof (sin)); ++ socklen_t sinlen = sizeof (sin); ++ xgetsockname (fd, (struct sockaddr *) &sin, &sinlen); ++ /* Close the socket, so that we will receive an error below. */ ++ close (fd); ++ } ++ ++ int sock = RPC_ANYSOCK; ++ CLIENT *clnt = clntudp_create ++ (&sin, 1, 2, (struct timeval) { 1, 0 }, &sock); ++ TEST_VERIFY_EXIT (clnt != NULL); ++ TEST_VERIFY (clnt_call (clnt, 3, ++ (xdrproc_t) xdr_void, NULL, ++ (xdrproc_t) xdr_void, NULL, ++ ((struct timeval) { 3, 0 })) ++ == RPC_CANTRECV); ++ clnt_destroy (clnt); ++ ++ return 0; ++} ++ ++#include +-- +2.17.1 + diff -r eece3e29fb61 -r 82efffdfec11 glibc/stuff/patches/glibc-2.22-CVE-2017-15670.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/glibc/stuff/patches/glibc-2.22-CVE-2017-15670.patch Wed Mar 15 11:41:38 2023 +0000 @@ -0,0 +1,19 @@ +Based on: + +From c369d66e5426a30e4725b100d5cd28e372754f90 Mon Sep 17 00:00:00 2001 +From: Paul Eggert +Date: Fri, 20 Oct 2017 18:41:14 +0200 +Subject: [PATCH] CVE-2017-15670: glob: Fix one-byte overflow [BZ #22320] + +diff -Naur a/posix/glob.c b/posix/glob.c +--- a/posix/glob.c 2017-11-02 15:37:04.841879958 +0530 ++++ b/posix/glob.c 2017-11-02 15:37:28.866595784 +0530 +@@ -868,7 +868,7 @@ + *p = '\0'; + } + else +- *((char *) mempcpy (newp, dirname + 1, end_name - dirname)) ++ *((char *) mempcpy (newp, dirname + 1, end_name - dirname - 1)) + = '\0'; + user_name = newp; + } diff -r eece3e29fb61 -r 82efffdfec11 glibc/stuff/patches/glibc-2.22-CVE-2017-15671.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/glibc/stuff/patches/glibc-2.22-CVE-2017-15671.patch Wed Mar 15 11:41:38 2023 +0000 @@ -0,0 +1,198 @@ +Based on: +https://sourceware.org/bugzilla/show_bug.cgi?id=22325 +https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=patch;h=e80fc1fc98bf614eb01cf8325503df3a1451a99c + +From e80fc1fc98bf614eb01cf8325503df3a1451a99c Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Sat, 21 Oct 2017 18:03:30 +0200 +Subject: [PATCH] glob: Add new test tst-glob-tilde + +The new test checks for memory leaks (see bug 22325) and attempts +to trigger the buffer overflow in bug 22320 +--- + posix/Makefile | 11 +++- + posix/tst-glob-tilde.c | 136 +++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 145 insertions(+), 2 deletions(-) + create mode 100644 posix/tst-glob-tilde.c + +diff --git a/posix/Makefile b/posix/Makefile +index 15e8818..de18693 100644 +--- a/posix/Makefile ++++ b/posix/Makefile +@@ -87,7 +87,7 @@ tests := tstgetopt testfnm runtests runptests \ + bug-getopt1 bug-getopt2 bug-getopt3 bug-getopt4 \ + bug-getopt5 tst-getopt_long1 bug-regex34 bug-regex35 \ + tst-pathconf tst-getaddrinfo4 tst-rxspencer-no-utf8 \ +- tst-fnmatch3 bug-regex36 tst-getaddrinfo5 ++ tst-fnmatch3 bug-regex36 tst-getaddrinfo5 tst-glob-tilde + xtests := bug-ga2 + ifeq (yes,$(build-shared)) + test-srcs := globtest +@@ -130,7 +130,8 @@ tests-special += $(objpfx)bug-regex2-mem.out $(objpfx)bug-regex14-mem.out \ + $(objpfx)tst-rxspencer-no-utf8-mem.out $(objpfx)tst-pcre-mem.out \ + $(objpfx)tst-boost-mem.out $(objpfx)tst-getconf.out \ + $(objpfx)bug-glob2-mem.out $(objpfx)tst-vfork3-mem.out \ +- $(objpfx)tst-fnmatch-mem.out $(objpfx)bug-regex36-mem.out ++ $(objpfx)tst-fnmatch-mem.out $(objpfx)bug-regex36-mem.out \ ++ $(objpfx)tst-glob-tilde-mem.out + xtests-special += $(objpfx)bug-ga2-mem.out + endif + +@@ -307,6 +308,12 @@ $(objpfx)bug-glob2-mem.out: $(objpfx)bug-glob2.out + $(common-objpfx)malloc/mtrace $(objpfx)bug-glob2.mtrace > $@; \ + $(evaluate-test) + ++tst-glob-tilde-ENV = MALLOC_TRACE=$(objpfx)tst-glob-tilde.mtrace ++ ++$(objpfx)tst-glob-tilde-mem.out: $(objpfx)tst-glob-tilde.out ++ $(common-objpfx)malloc/mtrace $(objpfx)tst-glob-tilde.mtrace > $@; \ ++ $(evaluate-test) ++ + $(inst_libexecdir)/getconf: $(inst_bindir)/getconf \ + $(objpfx)getconf.speclist FORCE + $(addprefix $(..)./scripts/mkinstalldirs ,\ +diff --git a/posix/tst-glob-tilde.c b/posix/tst-glob-tilde.c +new file mode 100644 +index 0000000..9518b4a +--- /dev/null ++++ b/posix/tst-glob-tilde.c +@@ -0,0 +1,136 @@ ++/* Check for GLOB_TIDLE heap allocation issues (bug 22320, bug 22325). ++ Copyright (C) 2017 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 ++#include ++#include ++#include ++ ++/* Flag which indicates whether to pass the GLOB_ONLYDIR flag. */ ++static int do_onlydir; ++ ++/* Flag which indicates whether to pass the GLOB_NOCHECK flag. */ ++static int do_nocheck; ++ ++/* Flag which indicates whether to pass the GLOB_MARK flag. */ ++static int do_mark; ++ ++static void ++one_test (const char *prefix, const char *middle, const char *suffix) ++{ ++ char *pattern = xasprintf ("%s%s%s", prefix, middle, suffix); ++ int flags = GLOB_TILDE; ++ if (do_onlydir) ++ flags |= GLOB_ONLYDIR; ++ if (do_nocheck) ++ flags |= GLOB_NOCHECK; ++ if (do_mark) ++ flags |= GLOB_MARK; ++ glob_t gl; ++ /* This glob call might result in crashes or memory leaks. */ ++ if (glob (pattern, flags, NULL, &gl) == 0) ++ globfree (&gl); ++ free (pattern); ++} ++ ++enum ++ { ++ /* The largest base being tested. */ ++ largest_base_size = 500000, ++ ++ /* The actual size is the base size plus a variable whose absolute ++ value is not greater than this. This helps malloc to trigger ++ overflows. */ ++ max_size_skew = 16, ++ ++ /* The maximum string length supported by repeating_string ++ below. */ ++ repeat_size = largest_base_size + max_size_skew, ++ }; ++ ++/* Used to construct strings which repeat a single character 'x'. */ ++static char *repeat; ++ ++/* Return a string of SIZE characters. */ ++const char * ++repeating_string (int size) ++{ ++ TEST_VERIFY (size >= 0); ++ TEST_VERIFY (size <= repeat_size); ++ const char *repeated_shifted = repeat + repeat_size - size; ++ TEST_VERIFY (strlen (repeated_shifted) == size); ++ return repeated_shifted; ++} ++ ++static int ++do_test (void) ++{ ++ /* Avoid network-based NSS modules and initialize nss_files with a ++ dummy lookup. This has to come before mtrace because NSS does ++ not free all memory. */ ++ __nss_configure_lookup ("passwd", "files"); ++ (void) getpwnam ("root"); ++ ++ mtrace (); ++ ++ repeat = xmalloc (repeat_size + 1); ++ memset (repeat, 'x', repeat_size); ++ repeat[repeat_size] = '\0'; ++ ++ /* These numbers control the size of the user name. The values ++ cover the minimum (0), a typical size (8), a large ++ stack-allocated size (100000), and a somewhat large ++ heap-allocated size (largest_base_size). */ ++ static const int base_sizes[] = { 0, 8, 100, 100000, largest_base_size, -1 }; ++ ++ for (do_onlydir = 0; do_onlydir < 2; ++do_onlydir) ++ for (do_nocheck = 0; do_nocheck < 2; ++do_nocheck) ++ for (do_mark = 0; do_mark < 2; ++do_mark) ++ for (int base_idx = 0; base_sizes[base_idx] >= 0; ++base_idx) ++ { ++ for (int size_skew = -max_size_skew; size_skew <= max_size_skew; ++ ++size_skew) ++ { ++ int size = base_sizes[base_idx] + size_skew; ++ if (size < 0) ++ continue; ++ ++ const char *user_name = repeating_string (size); ++ one_test ("~", user_name, "/a/b"); ++ } ++ ++ const char *user_name = repeating_string (base_sizes[base_idx]); ++ one_test ("~", user_name, ""); ++ one_test ("~", user_name, "/"); ++ one_test ("~", user_name, "/a"); ++ one_test ("~", user_name, "/*/*"); ++ one_test ("~", user_name, "\\/"); ++ one_test ("/~", user_name, ""); ++ one_test ("*/~", user_name, "/a/b"); ++ } ++ ++ free (repeat); ++ ++ return 0; ++} ++ ++#include +-- +2.17.1 + diff -r eece3e29fb61 -r 82efffdfec11 glibc/stuff/patches/glibc-2.22-CVE-2017-15804.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/glibc/stuff/patches/glibc-2.22-CVE-2017-15804.patch Wed Mar 15 11:41:38 2023 +0000 @@ -0,0 +1,26 @@ +Based on: + +From a159b53fa059947cc2548e3b0d5bdcf7b9630ba8 Mon Sep 17 00:00:00 2001 +From: Paul Eggert +Date: Sun, 22 Oct 2017 10:00:57 +0200 +Subject: [PATCH] glob: Fix buffer overflow during GLOB_TILDE unescaping + +diff -Naur a/posix/glob.c b/posix/glob.c +--- a/posix/glob.c 2017-12-07 18:57:12.370562751 +0530 ++++ b/posix/glob.c 2017-12-07 18:57:51.246561905 +0530 +@@ -848,11 +848,11 @@ + char *p = mempcpy (newp, dirname + 1, + unescape - dirname - 1); + char *q = unescape; +- while (*q != '\0') ++ while (q != end_name) + { + if (*q == '\\') + { +- if (q[1] == '\0') ++ if (q + 1 == end_name) + { + /* "~fo\\o\\" unescape to user_name "foo\\", + but "~fo\\o\\/" unescape to user_name + + diff -r eece3e29fb61 -r 82efffdfec11 glibc/stuff/patches/glibc-2.22-CVE-2017-16997.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/glibc/stuff/patches/glibc-2.22-CVE-2017-16997.patch Wed Mar 15 11:41:38 2023 +0000 @@ -0,0 +1,113 @@ +Based on: + +From 4ebd0c4191c6073cc8a7c5fdcf1d182c4719bcbb Mon Sep 17 00:00:00 2001 +From: Aurelien Jarno +Date: Sat, 30 Dec 2017 10:54:23 +0100 +Subject: [PATCH] elf: Check for empty tokens before dynamic string token + expansion [BZ #22625] + +The fillin_rpath function in elf/dl-load.c loops over each RPATH or +RUNPATH tokens and interprets empty tokens as the current directory +("./"). In practice the check for empty token is done *after* the +dynamic string token expansion. The expansion process can return an +empty string for the $ORIGIN token if __libc_enable_secure is set +or if the path of the binary can not be determined (/proc not mounted). + +Fix that by moving the check for empty tokens before the dynamic string +token expansion. In addition, check for NULL pointer or empty strings +return by expand_dynamic_string_token. + +The above changes highlighted a bug in decompose_rpath, an empty array +is represented by the first element being NULL at the fillin_rpath +level, but by using a -1 pointer in decompose_rpath and other functions. + +Changelog: + [BZ #22625] + * elf/dl-load.c (fillin_rpath): Check for empty tokens before dynamic + string token expansion. Check for NULL pointer or empty string possibly + returned by expand_dynamic_string_token. + (decompose_rpath): Check for empty path after dynamic string + token expansion. +(cherry picked from commit 3e3c904daef69b8bf7d5cc07f793c9f07c3553ef) +--- + ChangeLog | 10 ++++++++++ + NEWS | 4 ++++ + elf/dl-load.c | 49 +++++++++++++++++++++++++++++++++---------------- + 3 files changed, 47 insertions(+), 16 deletions(-) + +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -431,32 +431,41 @@ fillin_rpath (char *rpath, struct r_sear + { + char *cp; + size_t nelems = 0; +- char *to_free; + + while ((cp = __strsep (&rpath, sep)) != NULL) + { + struct r_search_path_elem *dirp; ++ char *to_free = NULL; ++ size_t len = 0; + +- to_free = cp = expand_dynamic_string_token (l, cp, 1); ++ /* `strsep' can pass an empty string. */ ++ if (*cp != '\0') ++ { ++ to_free = cp = expand_dynamic_string_token (l, cp, 1); + +- size_t len = strlen (cp); ++ /* expand_dynamic_string_token can return NULL in case of empty ++ path or memory allocation failure. */ ++ if (cp == NULL) ++ continue; ++ ++ /* Compute the length after dynamic string token expansion and ++ ignore empty paths. */ ++ len = strlen (cp); ++ if (len == 0) ++ { ++ free (to_free); ++ continue; ++ } + +- /* `strsep' can pass an empty string. This has to be +- interpreted as `use the current directory'. */ +- if (len == 0) +- { +- static const char curwd[] = "./"; +- cp = (char *) curwd; ++ /* Remove trailing slashes (except for "/"). */ ++ while (len > 1 && cp[len - 1] == '/') ++ --len; ++ ++ /* Now add one if there is none so far. */ ++ if (len > 0 && cp[len - 1] != '/') ++ cp[len++] = '/'; + } + +- /* Remove trailing slashes (except for "/"). */ +- while (len > 1 && cp[len - 1] == '/') +- --len; +- +- /* Now add one if there is none so far. */ +- if (len > 0 && cp[len - 1] != '/') +- cp[len++] = '/'; +- + /* Make sure we don't use untrusted directories if we run SUID. */ + if (__glibc_unlikely (check_trusted) && !is_trusted_path (cp, len)) + { +@@ -619,6 +628,14 @@ decompose_rpath (struct r_search_path_st + necessary. */ + free (copy); + ++ /* There is no path after expansion. */ ++ if (result[0] == NULL) ++ { ++ free (result); ++ sps->dirs = (struct r_search_path_elem **) -1; ++ return false; ++ } ++ + sps->dirs = result; + /* The caller will change this value if we haven't used a real malloc. */ + sps->malloced = 1; diff -r eece3e29fb61 -r 82efffdfec11 glibc/stuff/patches/glibc-2.22-CVE-2017-18269.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/glibc/stuff/patches/glibc-2.22-CVE-2017-18269.patch Wed Mar 15 11:41:38 2023 +0000 @@ -0,0 +1,158 @@ +From cd66c0e584c6d692bc8347b5e72723d02b8a8ada Mon Sep 17 00:00:00 2001 +From: Andrew Senkevich +Date: Fri, 23 Mar 2018 16:19:45 +0100 +Subject: [PATCH] Fix i386 memmove issue (bug 22644). + + [BZ #22644] + * sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S: Fixed + branch conditions. + * string/test-memmove.c (do_test2): New testcase. +--- + string/test-memmove.c | 58 ++++++++++++++++++++++ + .../i386/i686/multiarch/memcpy-sse2-unaligned.S | 12 ++--- + 3 files changed, 72 insertions(+), 6 deletions(-) + +diff --git a/string/test-memmove.c b/string/test-memmove.c +index edc7a4c..64e3651 100644 +--- a/string/test-memmove.c ++++ b/string/test-memmove.c +@@ -24,6 +24,7 @@ + # define TEST_NAME "memmove" + #endif + #include "test-string.h" ++#include + + char *simple_memmove (char *, const char *, size_t); + +@@ -245,6 +246,60 @@ do_random_tests (void) + } + } + ++static void ++do_test2 (void) ++{ ++ size_t size = 0x20000000; ++ uint32_t * large_buf; ++ ++ large_buf = mmap ((void*) 0x70000000, size, PROT_READ | PROT_WRITE, ++ MAP_PRIVATE | MAP_ANON, -1, 0); ++ ++ if (large_buf == MAP_FAILED) ++ error (EXIT_UNSUPPORTED, errno, "Large mmap failed"); ++ ++ if ((uintptr_t) large_buf > 0x80000000 - 128 ++ || 0x80000000 - (uintptr_t) large_buf > 0x20000000) ++ { ++ error (0, 0, "Large mmap allocated improperly"); ++ ret = EXIT_UNSUPPORTED; ++ munmap ((void *) large_buf, size); ++ return; ++ } ++ ++ size_t bytes_move = 0x80000000 - (uintptr_t) large_buf; ++ size_t arr_size = bytes_move / sizeof (uint32_t); ++ size_t i; ++ ++ FOR_EACH_IMPL (impl, 0) ++ { ++ for (i = 0; i < arr_size; i++) ++ large_buf[i] = (uint32_t) i; ++ ++ uint32_t * dst = &large_buf[33]; ++ ++#ifdef TEST_BCOPY ++ CALL (impl, (char *) large_buf, (char *) dst, bytes_move); ++#else ++ CALL (impl, (char *) dst, (char *) large_buf, bytes_move); ++#endif ++ ++ for (i = 0; i < arr_size; i++) ++ { ++ if (dst[i] != (uint32_t) i) ++ { ++ error (0, 0, ++ "Wrong result in function %s dst \"%p\" src \"%p\" offset \"%zd\"", ++ impl->name, dst, large_buf, i); ++ ret = 1; ++ break; ++ } ++ } ++ } ++ ++ munmap ((void *) large_buf, size); ++} ++ + int + test_main (void) + { +@@ -284,6 +339,9 @@ test_main (void) + } + + do_random_tests (); ++ ++ do_test2 (); ++ + return ret; + } + +diff --git a/sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S b/sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S +index 9c3bbe7..9aa17de 100644 +--- a/sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S ++++ b/sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S +@@ -72,7 +72,7 @@ ENTRY (MEMCPY) + cmp %edx, %eax + + # ifdef USE_AS_MEMMOVE +- jg L(check_forward) ++ ja L(check_forward) + + L(mm_len_0_or_more_backward): + /* Now do checks for lengths. We do [0..16], [16..32], [32..64], [64..128] +@@ -81,7 +81,7 @@ L(mm_len_0_or_more_backward): + jbe L(mm_len_0_16_bytes_backward) + + cmpl $32, %ecx +- jg L(mm_len_32_or_more_backward) ++ ja L(mm_len_32_or_more_backward) + + /* Copy [0..32] and return. */ + movdqu (%eax), %xmm0 +@@ -92,7 +92,7 @@ L(mm_len_0_or_more_backward): + + L(mm_len_32_or_more_backward): + cmpl $64, %ecx +- jg L(mm_len_64_or_more_backward) ++ ja L(mm_len_64_or_more_backward) + + /* Copy [0..64] and return. */ + movdqu (%eax), %xmm0 +@@ -107,7 +107,7 @@ L(mm_len_32_or_more_backward): + + L(mm_len_64_or_more_backward): + cmpl $128, %ecx +- jg L(mm_len_128_or_more_backward) ++ ja L(mm_len_128_or_more_backward) + + /* Copy [0..128] and return. */ + movdqu (%eax), %xmm0 +@@ -132,7 +132,7 @@ L(mm_len_128_or_more_backward): + add %ecx, %eax + cmp %edx, %eax + movl SRC(%esp), %eax +- jle L(forward) ++ jbe L(forward) + PUSH (%esi) + PUSH (%edi) + PUSH (%ebx) +@@ -269,7 +269,7 @@ L(check_forward): + add %edx, %ecx + cmp %eax, %ecx + movl LEN(%esp), %ecx +- jle L(forward) ++ jbe L(forward) + + /* Now do checks for lengths. We do [0..16], [0..32], [0..64], [0..128] + separately. */ +-- +2.9.3 + diff -r eece3e29fb61 -r 82efffdfec11 glibc/stuff/patches/glibc-2.22-CVE-2018-1000001.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/glibc/stuff/patches/glibc-2.22-CVE-2018-1000001.patch Wed Mar 15 11:41:38 2023 +0000 @@ -0,0 +1,154 @@ +Based on: +https://sourceware.org/bugzilla/show_bug.cgi?id=22679 +https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=patch;h=771c846a71d9ee14aa3b91fd184026482da585d9 + +From 771c846a71d9ee14aa3b91fd184026482da585d9 Mon Sep 17 00:00:00 2001 +From: "Dmitry V. Levin" +Date: Sun, 7 Jan 2018 02:03:41 +0000 +Subject: [PATCH] linux: make getcwd(3) fail if it cannot obtain an absolute + path [BZ #22679] + +Currently getcwd(3) can succeed without returning an absolute path +because the underlying getcwd syscall, starting with linux commit +v2.6.36-rc1~96^2~2, may succeed without returning an absolute path. + +This is a conformance issue because "The getcwd() function shall +place an absolute pathname of the current working directory +in the array pointed to by buf, and return buf". + +This is also a security issue because a non-absolute path returned +by getcwd(3) causes a buffer underflow in realpath(3). + +Fix this by checking the path returned by getcwd syscall and falling +back to generic_getcwd if the path is not absolute, effectively making +getcwd(3) fail with ENOENT. The error code is chosen for consistency +with the case when the current directory is unlinked. + +[BZ #22679] +CVE-2018-1000001 +* sysdeps/unix/sysv/linux/getcwd.c (__getcwd): Fall back to +generic_getcwd if the path returned by getcwd syscall is not absolute. +* io/tst-getcwd-abspath.c: New test. +* io/Makefile (tests): Add tst-getcwd-abspath. +--- + io/Makefile | 2 +- + io/tst-getcwd-abspath.c | 66 ++++++++++++++++++++++++++++++++ + sysdeps/unix/sysv/linux/getcwd.c | 8 ++-- + 3 files changed, 71 insertions(+), 5 deletions(-) + create mode 100644 io/tst-getcwd-abspath.c + +diff --git a/io/Makefile b/io/Makefile +index 613dce0..c50be28 100644 +--- a/io/Makefile ++++ b/io/Makefile +@@ -71,7 +71,7 @@ tests := test-utime test-stat test-stat2 test-lfs tst-getcwd \ + tst-renameat tst-fchownat tst-fchmodat tst-faccessat \ + tst-symlinkat tst-linkat tst-readlinkat tst-mkdirat \ + tst-mknodat tst-mkfifoat tst-ttyname_r bug-ftw5 \ +- tst-posix_fallocate ++ tst-posix_fallocate tst-getcwd-abspath + + ifeq ($(run-built-tests),yes) + tests-special += $(objpfx)ftwtest.out +diff --git a/io/tst-getcwd-abspath.c b/io/tst-getcwd-abspath.c +new file mode 100644 +index 0000000..3a3636f +--- /dev/null ++++ b/io/tst-getcwd-abspath.c +@@ -0,0 +1,66 @@ ++/* BZ #22679 getcwd(3) should not succeed without returning an absolute path. ++ ++ Copyright (C) 2018 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 ++#include ++#include ++#include ++#include ++#include ++ ++static char *chroot_dir; ++ ++/* The actual test. Run it in a subprocess, so that the test harness ++ can remove the temporary directory in --direct mode. */ ++static void ++getcwd_callback (void *closure) ++{ ++ xchroot (chroot_dir); ++ ++ errno = 0; ++ char *cwd = getcwd (NULL, 0); ++ TEST_COMPARE (errno, ENOENT); ++ TEST_VERIFY (cwd == NULL); ++ ++ errno = 0; ++ cwd = realpath (".", NULL); ++ TEST_COMPARE (errno, ENOENT); ++ TEST_VERIFY (cwd == NULL); ++ ++ _exit (0); ++} ++ ++static int ++do_test (void) ++{ ++ support_become_root (); ++ if (!support_can_chroot ()) ++ return EXIT_UNSUPPORTED; ++ ++ chroot_dir = support_create_temp_directory ("tst-getcwd-abspath-"); ++ support_isolate_in_subprocess (getcwd_callback, NULL); ++ ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/unix/sysv/linux/getcwd.c b/sysdeps/unix/sysv/linux/getcwd.c +index 5caee92..4a4c8f0 100644 +--- a/sysdeps/unix/sysv/linux/getcwd.c ++++ b/sysdeps/unix/sysv/linux/getcwd.c +@@ -76,7 +76,7 @@ __getcwd (char *buf, size_t size) + int retval; + + retval = INLINE_SYSCALL (getcwd, 2, path, alloc_size); +- if (retval >= 0) ++ if (retval > 0 && path[0] == '/') + { + #ifndef NO_ALLOCATION + if (buf == NULL && size == 0) +@@ -92,10 +92,10 @@ __getcwd (char *buf, size_t size) + return buf; + } + +- /* The system call cannot handle paths longer than a page. +- Neither can the magic symlink in /proc/self. Just use the ++ /* The system call either cannot handle paths longer than a page ++ or can succeed without returning an absolute path. Just use the + generic implementation right away. */ +- if (errno == ENAMETOOLONG) ++ if (retval >= 0 || errno == ENAMETOOLONG) + { + #ifndef NO_ALLOCATION + if (buf == NULL && size == 0) +-- +2.17.1 + diff -r eece3e29fb61 -r 82efffdfec11 glibc/stuff/patches/glibc-2.22-CVE-2018-11236.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/glibc/stuff/patches/glibc-2.22-CVE-2018-11236.patch Wed Mar 15 11:41:38 2023 +0000 @@ -0,0 +1,143 @@ +Based on: +https://sourceware.org/bugzilla/show_bug.cgi?id=22786 +https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=patch;h=af7519f7b35024224c163e32a89fb247b0c446fc + +From af7519f7b35024224c163e32a89fb247b0c446fc Mon Sep 17 00:00:00 2001 +From: Paul Pluzhnikov +Date: Tue, 8 May 2018 18:12:41 -0700 +Subject: [PATCH] Fix path length overflow in realpath [BZ #22786] + +Integer addition overflow may cause stack buffer overflow +when realpath() input length is close to SSIZE_MAX. +--- + stdlib/Makefile | 2 +- + stdlib/canonicalize.c | 2 +- + stdlib/test-bz22786.c | 90 +++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 92 insertions(+), 2 deletions(-) + create mode 100644 stdlib/test-bz22786.c + +diff --git a/stdlib/Makefile b/stdlib/Makefile +index a925479..482c587 100644 +--- a/stdlib/Makefile ++++ b/stdlib/Makefile +@@ -75,7 +75,7 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \ + tst-makecontext3 bug-getcontext bug-fmtmsg1 \ + tst-secure-getenv tst-strtod-overflow tst-strtod-round \ + tst-tininess tst-strtod-underflow tst-tls-atexit \ +- tst-setcontext3 tst-tls-atexit-nodelete ++ tst-setcontext3 tst-tls-atexit-nodelete test-bz22786 + tests-static := tst-secure-getenv + + modules-names = tst-tls-atexit-lib +diff --git a/stdlib/canonicalize.c b/stdlib/canonicalize.c +index 6f4f74d..509beb1 100644 +--- a/stdlib/canonicalize.c ++++ b/stdlib/canonicalize.c +@@ -181,7 +181,7 @@ __realpath (const char *name, char *resolved) + extra_buf = __alloca (path_max); + + len = strlen (end); +- if ((long int) (n + len) >= path_max) ++ if (path_max - n <= len) + { + __set_errno (ENAMETOOLONG); + goto error; +diff --git a/stdlib/test-bz22786.c b/stdlib/test-bz22786.c +new file mode 100644 +index 0000000..e7837f9 +--- /dev/null ++++ b/stdlib/test-bz22786.c +@@ -0,0 +1,90 @@ ++/* Bug 22786: test for buffer overflow in realpath. ++ Copyright (C) 2018 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 ++ . */ ++ ++/* This file must be run from within a directory called "stdlib". */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ const char dir[] = "bz22786"; ++ const char lnk[] = "bz22786/symlink"; ++ ++ rmdir (dir); ++ if (mkdir (dir, 0755) != 0 && errno != EEXIST) ++ { ++ printf ("mkdir %s: %m\n", dir); ++ return EXIT_FAILURE; ++ } ++ if (symlink (".", lnk) != 0 && errno != EEXIST) ++ { ++ printf ("symlink (%s, %s): %m\n", dir, lnk); ++ return EXIT_FAILURE; ++ } ++ ++ const size_t path_len = (size_t) INT_MAX + 1; ++ ++ DIAG_PUSH_NEEDS_COMMENT; ++#if __GNUC_PREREQ (7, 0) ++ /* GCC 7 warns about too-large allocations; here we need such ++ allocation to succeed for the test to work. */ ++ DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than="); ++#endif ++ char *path = malloc (path_len); ++ DIAG_POP_NEEDS_COMMENT; ++ ++ if (path == NULL) ++ { ++ printf ("malloc (%zu): %m\n", path_len); ++ return EXIT_UNSUPPORTED; ++ } ++ ++ /* Construct very long path = "bz22786/symlink/aaaa....." */ ++ char *p = mempcpy (path, lnk, sizeof (lnk) - 1); ++ *(p++) = '/'; ++ memset (p, 'a', path_len - (path - p) - 2); ++ p[path_len - (path - p) - 1] = '\0'; ++ ++ /* This call crashes before the fix for bz22786 on 32-bit platforms. */ ++ p = realpath (path, NULL); ++ ++ if (p != NULL || errno != ENAMETOOLONG) ++ { ++ printf ("realpath: %s (%m)", p); ++ return EXIT_FAILURE; ++ } ++ ++ /* Cleanup. */ ++ unlink (lnk); ++ rmdir (dir); ++ ++ return 0; ++} ++ ++#define TEST_FUNCTION do_test ++#include +-- +2.17.1 + diff -r eece3e29fb61 -r 82efffdfec11 glibc/stuff/patches/glibc-2.22-CVE-2018-6485.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/glibc/stuff/patches/glibc-2.22-CVE-2018-6485.patch Wed Mar 15 11:41:38 2023 +0000 @@ -0,0 +1,345 @@ +Based on: +https://sourceware.org/bugzilla/show_bug.cgi?id=22343 +https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=patch;h=9331dbdcd7aa8e997eb4caa9b1b0cb6c804320c8 + +From 9331dbdcd7aa8e997eb4caa9b1b0cb6c804320c8 Mon Sep 17 00:00:00 2001 +From: Arjun Shankar +Date: Thu, 18 Jan 2018 16:47:06 +0000 +Subject: [PATCH] Fix integer overflows in internal memalign and malloc [BZ + #22343] [BZ #22774] + +When posix_memalign is called with an alignment less than MALLOC_ALIGNMENT +and a requested size close to SIZE_MAX, it falls back to malloc code +(because the alignment of a block returned by malloc is sufficient to +satisfy the call). In this case, an integer overflow in _int_malloc leads +to posix_memalign incorrectly returning successfully. + +Upon fixing this and writing a somewhat thorough regression test, it was +discovered that when posix_memalign is called with an alignment larger than +MALLOC_ALIGNMENT (so it uses _int_memalign instead) and a requested size +close to SIZE_MAX, a different integer overflow in _int_memalign leads to +posix_memalign incorrectly returning successfully. + +Both integer overflows affect other memory allocation functions that use +_int_malloc (one affected malloc in x86) or _int_memalign as well. + +This commit fixes both integer overflows. In addition to this, it adds a +regression test to guard against false successful allocations by the +following memory allocation functions when called with too-large allocation +sizes and, where relevant, various valid alignments: +malloc, realloc, calloc, memalign, posix_memalign, aligned_alloc, valloc, +and pvalloc. +--- + malloc/Makefile | 2 +- + malloc/malloc.c | 30 +++-- + malloc/tst-malloc-too-large.c | 237 ++++++++++++++++++++++++++++++++++ + 3 files changed, 260 insertions(+), 9 deletions(-) + create mode 100644 malloc/tst-malloc-too-large.c + +diff --git a/malloc/Makefile b/malloc/Makefile +index 67ed293..8627344 100644 +--- a/malloc/Makefile ++++ b/malloc/Makefile +@@ -28,7 +28,7 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \ + tst-mallocstate tst-mcheck tst-mallocfork tst-trim1 \ + tst-malloc-usable tst-realloc tst-posix_memalign \ + tst-pvalloc tst-memalign tst-mallopt tst-scratch_buffer \ +- tst-malloc-backtrace ++ tst-malloc-backtrace tst-malloc-too-large + test-srcs = tst-mtrace + + routines = malloc morecore mcheck mtrace obstack \ +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 452f036..1ed5e01 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -1252,14 +1252,21 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + MINSIZE : \ + ((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK) + +-/* Same, except also perform argument check */ +- +-#define checked_request2size(req, sz) \ +- if (REQUEST_OUT_OF_RANGE (req)) { \ +- __set_errno (ENOMEM); \ +- return 0; \ +- } \ +- (sz) = request2size (req); ++/* Same, except also perform an argument and result check. First, we check ++ that the padding done by request2size didn't result in an integer ++ overflow. Then we check (using REQUEST_OUT_OF_RANGE) that the resulting ++ size isn't so large that a later alignment would lead to another integer ++ overflow. */ ++#define checked_request2size(req, sz) \ ++({ \ ++ (sz) = request2size (req); \ ++ if (((sz) < (req)) \ ++ || REQUEST_OUT_OF_RANGE (sz)) \ ++ { \ ++ __set_errno (ENOMEM); \ ++ return 0; \ ++ } \ ++}) + + /* + --------------- Physical chunk operations --------------- +@@ -4410,6 +4417,13 @@ _int_memalign (mstate av, size_t alignment, size_t bytes) + */ + + ++ /* Check for overflow. */ ++ if (nb > SIZE_MAX - alignment - MINSIZE) ++ { ++ __set_errno (ENOMEM); ++ return 0; ++ } ++ + /* Call malloc with worst case padding to hit alignment. */ + + m = (char *) (_int_malloc (av, nb + alignment + MINSIZE)); +diff --git a/malloc/tst-malloc-too-large.c b/malloc/tst-malloc-too-large.c +new file mode 100644 +index 0000000..1f7bf29 +--- /dev/null ++++ b/malloc/tst-malloc-too-large.c +@@ -0,0 +1,237 @@ ++/* Test and verify that too-large memory allocations fail with ENOMEM. ++ Copyright (C) 2018 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 ++ . */ ++ ++/* Bug 22375 reported a regression in malloc where if after malloc'ing then ++ free'ing a small block of memory, malloc is then called with a really ++ large size argument (close to SIZE_MAX): instead of returning NULL and ++ setting errno to ENOMEM, malloc incorrectly returns the previously ++ allocated block instead. Bug 22343 reported a similar case where ++ posix_memalign incorrectly returns successfully when called with an with ++ a really large size argument. ++ ++ Both of these were caused by integer overflows in the allocator when it ++ was trying to pad the requested size to allow for book-keeping or ++ alignment. This test guards against such bugs by repeatedly allocating ++ and freeing small blocks of memory then trying to allocate various block ++ sizes larger than the memory bus width of 64-bit targets, or almost ++ as large as SIZE_MAX on 32-bit targets supported by glibc. In each case, ++ it verifies that such impossibly large allocations correctly fail. */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++/* This function prepares for each 'too-large memory allocation' test by ++ performing a small successful malloc/free and resetting errno prior to ++ the actual test. */ ++static void ++test_setup (void) ++{ ++ void *volatile ptr = malloc (16); ++ TEST_VERIFY_EXIT (ptr != NULL); ++ free (ptr); ++ errno = 0; ++} ++ ++ ++/* This function tests each of: ++ - malloc (SIZE) ++ - realloc (PTR_FOR_REALLOC, SIZE) ++ - for various values of NMEMB: ++ - calloc (NMEMB, SIZE/NMEMB) ++ - calloc (SIZE/NMEMB, NMEMB) ++ and precedes each of these tests with a small malloc/free before it. */ ++static void ++test_large_allocations (size_t size) ++{ ++ void * ptr_to_realloc; ++ ++ test_setup (); ++ TEST_VERIFY (malloc (size) == NULL); ++ TEST_VERIFY (errno == ENOMEM); ++ ++ ptr_to_realloc = malloc (16); ++ TEST_VERIFY_EXIT (ptr_to_realloc != NULL); ++ test_setup (); ++ TEST_VERIFY (realloc (ptr_to_realloc, size) == NULL); ++ TEST_VERIFY (errno == ENOMEM); ++ free (ptr_to_realloc); ++ ++ for (size_t nmemb = 1; nmemb <= 8; nmemb *= 2) ++ if ((size % nmemb) == 0) ++ { ++ test_setup (); ++ TEST_VERIFY (calloc (nmemb, size / nmemb) == NULL); ++ TEST_VERIFY (errno == ENOMEM); ++ ++ test_setup (); ++ TEST_VERIFY (calloc (size / nmemb, nmemb) == NULL); ++ TEST_VERIFY (errno == ENOMEM); ++ } ++ else ++ break; ++} ++ ++ ++static long pagesize; ++ ++/* This function tests the following aligned memory allocation functions ++ using several valid alignments and precedes each allocation test with a ++ small malloc/free before it: ++ memalign, posix_memalign, aligned_alloc, valloc, pvalloc. */ ++static void ++test_large_aligned_allocations (size_t size) ++{ ++ /* ptr stores the result of posix_memalign but since all those calls ++ should fail, posix_memalign should never change ptr. We set it to ++ NULL here and later on we check that it remains NULL after each ++ posix_memalign call. */ ++ void * ptr = NULL; ++ ++ size_t align; ++ ++ /* All aligned memory allocation functions expect an alignment that is a ++ power of 2. Given this, we test each of them with every valid ++ alignment from 1 thru PAGESIZE. */ ++ for (align = 1; align <= pagesize; align *= 2) ++ { ++ test_setup (); ++ TEST_VERIFY (memalign (align, size) == NULL); ++ TEST_VERIFY (errno == ENOMEM); ++ ++ /* posix_memalign expects an alignment that is a power of 2 *and* a ++ multiple of sizeof (void *). */ ++ if ((align % sizeof (void *)) == 0) ++ { ++ test_setup (); ++ TEST_VERIFY (posix_memalign (&ptr, align, size) == ENOMEM); ++ TEST_VERIFY (ptr == NULL); ++ } ++ ++ /* aligned_alloc expects a size that is a multiple of alignment. */ ++ if ((size % align) == 0) ++ { ++ test_setup (); ++ TEST_VERIFY (aligned_alloc (align, size) == NULL); ++ TEST_VERIFY (errno == ENOMEM); ++ } ++ } ++ ++ /* Both valloc and pvalloc return page-aligned memory. */ ++ ++ test_setup (); ++ TEST_VERIFY (valloc (size) == NULL); ++ TEST_VERIFY (errno == ENOMEM); ++ ++ test_setup (); ++ TEST_VERIFY (pvalloc (size) == NULL); ++ TEST_VERIFY (errno == ENOMEM); ++} ++ ++ ++#define FOURTEEN_ON_BITS ((1UL << 14) - 1) ++#define FIFTY_ON_BITS ((1UL << 50) - 1) ++ ++ ++static int ++do_test (void) ++{ ++ ++#if __WORDSIZE >= 64 ++ ++ /* This test assumes that none of the supported targets have an address ++ bus wider than 50 bits, and that therefore allocations for sizes wider ++ than 50 bits will fail. Here, we ensure that the assumption continues ++ to be true in the future when we might have address buses wider than 50 ++ bits. */ ++ ++ struct rlimit alloc_size_limit ++ = { ++ .rlim_cur = FIFTY_ON_BITS, ++ .rlim_max = FIFTY_ON_BITS ++ }; ++ ++ setrlimit (RLIMIT_AS, &alloc_size_limit); ++ ++#endif /* __WORDSIZE >= 64 */ ++ ++ DIAG_PUSH_NEEDS_COMMENT; ++#if __GNUC_PREREQ (7, 0) ++ /* GCC 7 warns about too-large allocations; here we want to test ++ that they fail. */ ++ DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than="); ++#endif ++ ++ /* Aligned memory allocation functions need to be tested up to alignment ++ size equivalent to page size, which should be a power of 2. */ ++ pagesize = sysconf (_SC_PAGESIZE); ++ TEST_VERIFY_EXIT (powerof2 (pagesize)); ++ ++ /* Loop 1: Ensure that all allocations with SIZE close to SIZE_MAX, i.e. ++ in the range (SIZE_MAX - 2^14, SIZE_MAX], fail. ++ ++ We can expect that this range of allocation sizes will always lead to ++ an allocation failure on both 64 and 32 bit targets, because: ++ ++ 1. no currently supported 64-bit target has an address bus wider than ++ 50 bits -- and (2^64 - 2^14) is much wider than that; ++ ++ 2. on 32-bit targets, even though 2^32 is only 4 GB and potentially ++ addressable, glibc itself is more than 2^14 bytes in size, and ++ therefore once glibc is loaded, less than (2^32 - 2^14) bytes remain ++ available. */ ++ ++ for (size_t i = 0; i <= FOURTEEN_ON_BITS; i++) ++ { ++ test_large_allocations (SIZE_MAX - i); ++ test_large_aligned_allocations (SIZE_MAX - i); ++ } ++ ++#if __WORDSIZE >= 64 ++ /* On 64-bit targets, we need to test a much wider range of too-large ++ sizes, so we test at intervals of (1 << 50) that allocation sizes ++ ranging from SIZE_MAX down to (1 << 50) fail: ++ The 14 MSBs are decremented starting from "all ON" going down to 1, ++ the 50 LSBs are "all ON" and then "all OFF" during every iteration. */ ++ for (size_t msbs = FOURTEEN_ON_BITS; msbs >= 1; msbs--) ++ { ++ size_t size = (msbs << 50) | FIFTY_ON_BITS; ++ test_large_allocations (size); ++ test_large_aligned_allocations (size); ++ ++ size = msbs << 50; ++ test_large_allocations (size); ++ test_large_aligned_allocations (size); ++ } ++#endif /* __WORDSIZE >= 64 */ ++ ++ DIAG_POP_NEEDS_COMMENT; ++ ++ return 0; ++} ++ ++ ++#include +-- +2.17.1 +