From 06263ee4efac6fdeae0ca5d9508e7556d02dd8c58c6e14fbe6e999f80524e32c Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Mon, 5 Feb 2018 10:33:11 +0000 Subject: [PATCH] Accepting request 572614 from home:Andreas_Schwab:Factory - Update to glibc 2.27 * Optimized x86-64 asin, atan2, exp, expf, log, pow, atan, sin, cosf, sinf, sincosf and tan with FMA * Optimized x86-64 trunc and truncf for processors with SSE4.1 * Optimized generic expf, exp2f, logf, log2f, powf, sinf, cosf and sincosf * In order to support faster and safer process termination the malloc API family of functions will no longer print a failure address and stack backtrace after detecting heap corruption * The abort function terminates the process immediately, without flushing stdio streams * On platforms where long double has the IEEE binary128 format (aarch64, alpha, mips64, riscv, s390 and sparc), the math library now implements _Float128 interfaces for that type, as defined by ISO/IEC TS 18661-3:2015 These are the same interfaces added in version 2.26 for some platforms where this format is supported but is not the format of long double * On platforms with support for _Float64x (aarch64, alpha, i386, ia64, mips64, powerpc64le, riscv, s390, sparc and x86_64), the math library now implements interfaces for that type, as defined by ISO/IEC TS 18661-3:2015 * The math library now implements interfaces for the _Float32, _Float64 and _Float32x types, as defined by ISO/IEC TS 18661-3:2015 * glibc now implements the memfd_create and mlock2 functions on Linux * Support for memory protection keys was added * The copy_file_range function was added * The ldconfig utility now processes `include' directives using the C/POSIX collation ordering * Support for two grammatical forms of month names has been added * Support for the RISC-V ISA running on Linux has been added * Statically compiled applications attempting to load locales compiled for the OBS-URL: https://build.opensuse.org/request/show/572614 OBS-URL: https://build.opensuse.org/package/show/Base:System/glibc?expand=0&rev=491 --- aarch64-cpu-features.patch | 18 - abort-no-flush.patch | 80 - add-locales.patch | 14 +- assert-pedantic.patch | 192 - dl-init-paths-overflow.patch | 90 - dl-runtime-resolve-opt-avx512f.patch | 26 - dl-runtime-resolve-xsave.patch | 851 --- dynarray-allocation.patch | 127 - eh-frame-zero-terminator.patch | 31 - falkor-memcpy-memmove.patch | 573 -- fillin-rpath-empty-tokens.patch | 88 - fix-locking-in-_IO_cleanup.patch | 162 +- fnmatch-collating-elements.patch | 50 +- getaddrinfo-errno.patch | 649 --- getcwd-absolute.patch | 34 - glibc-2.14-crypt.diff | 36 +- glibc-2.26.tar.xz | 3 - glibc-2.26.tar.xz.sig | 10 - glibc-2.27.tar.xz | 3 + glibc-2.27.tar.xz.sig | 16 + glibc-2.3.2.no_archive.diff | 18 +- glibc-2.3.3-nscd-db-path.diff | 8 +- glibc-2.3.90-langpackdir.diff | 8 +- glibc-2.4-china.diff | 12 +- glibc-2.4.90-no_NO.diff | 20 +- glibc-bindresvport-blacklist.diff | 6 +- glibc-c-utf8-locale.patch | 15 +- glibc-disable-gettext-for-c-utf8.patch | 8 +- glibc-fix-double-loopback.diff | 8 +- glibc-nodate.patch | 47 - glibc-nscd.conf.patch | 6 +- glibc-resolv-mdnshint.diff | 8 +- glibc-version.diff | 14 +- glibc.changes | 79 + glibc.keyring | 5 - glibc.spec | 168 +- glob-tilde-overflow.patch | 2244 -------- glob64-s390.patch | 6 - iconv-reset-input-buffer.patch | 34 +- ld-so-hwcap-x86-64.patch | 190 - ldd-system-interp.patch | 41 - libpthread-compat-wrappers.patch | 120 - malloc-tcache-check-overflow.patch | 21 - malloc-tcache-leak.patch | 179 - manpages.tar.bz2 | 4 +- math-c++-compat.patch | 271 - nearbyint-inexact.patch | 107 - nscd-libnsl.patch | 180 - nscd-server-user.patch | 6 +- nss-compat.patch | 6745 ------------------------ nss-db-path.patch | 20 +- nss-files-large-buffers.patch | 831 --- nss-files-long-lines-2.patch | 38 +- powerpc-elision-enable-envvar.patch | 41 - powerpc-hwcap-bits.patch | 15 - remove-nss-nis-compat.patch | 207 - resolv-conf-oom.patch | 44 - resolv-context-leak.patch | 53 - s390-elision-enable-envvar.patch | 31 - spawni-assert.patch | 71 - sysconf-uio-maxiov.patch | 125 - tst-tlsopt-powerpc.patch | 171 - x86-64-dl-platform.patch | 196 - 63 files changed, 308 insertions(+), 15166 deletions(-) delete mode 100644 aarch64-cpu-features.patch delete mode 100644 abort-no-flush.patch delete mode 100644 assert-pedantic.patch delete mode 100644 dl-init-paths-overflow.patch delete mode 100644 dl-runtime-resolve-opt-avx512f.patch delete mode 100644 dl-runtime-resolve-xsave.patch delete mode 100644 dynarray-allocation.patch delete mode 100644 eh-frame-zero-terminator.patch delete mode 100644 falkor-memcpy-memmove.patch delete mode 100644 fillin-rpath-empty-tokens.patch delete mode 100644 getaddrinfo-errno.patch delete mode 100644 getcwd-absolute.patch delete mode 100644 glibc-2.26.tar.xz delete mode 100644 glibc-2.26.tar.xz.sig create mode 100644 glibc-2.27.tar.xz create mode 100644 glibc-2.27.tar.xz.sig delete mode 100644 glibc-nodate.patch delete mode 100644 glob-tilde-overflow.patch delete mode 100644 glob64-s390.patch delete mode 100644 ld-so-hwcap-x86-64.patch delete mode 100644 ldd-system-interp.patch delete mode 100644 libpthread-compat-wrappers.patch delete mode 100644 malloc-tcache-check-overflow.patch delete mode 100644 malloc-tcache-leak.patch delete mode 100644 math-c++-compat.patch delete mode 100644 nearbyint-inexact.patch delete mode 100644 nscd-libnsl.patch delete mode 100644 nss-compat.patch delete mode 100644 nss-files-large-buffers.patch delete mode 100644 powerpc-elision-enable-envvar.patch delete mode 100644 powerpc-hwcap-bits.patch delete mode 100644 remove-nss-nis-compat.patch delete mode 100644 resolv-conf-oom.patch delete mode 100644 resolv-context-leak.patch delete mode 100644 s390-elision-enable-envvar.patch delete mode 100644 spawni-assert.patch delete mode 100644 sysconf-uio-maxiov.patch delete mode 100644 tst-tlsopt-powerpc.patch delete mode 100644 x86-64-dl-platform.patch diff --git a/aarch64-cpu-features.patch b/aarch64-cpu-features.patch deleted file mode 100644 index 9b23147..0000000 --- a/aarch64-cpu-features.patch +++ /dev/null @@ -1,18 +0,0 @@ -2017-10-10 Steve Ellcey - - * sysdeps/unix/sysv/linux/aarch64/cpu-features.c (get_midr_from_mcpu): - Use strcmp instead of tunable_is_name. - -Index: glibc-2.26/sysdeps/unix/sysv/linux/aarch64/cpu-features.c -=================================================================== ---- glibc-2.26.orig/sysdeps/unix/sysv/linux/aarch64/cpu-features.c -+++ glibc-2.26/sysdeps/unix/sysv/linux/aarch64/cpu-features.c -@@ -37,7 +37,7 @@ static uint64_t - get_midr_from_mcpu (const char *mcpu) - { - for (int i = 0; i < sizeof (cpu_list) / sizeof (struct cpu_list); i++) -- if (tunable_is_name (mcpu, cpu_list[i].name) == 0) -+ if (strcmp (mcpu, cpu_list[i].name) == 0) - return cpu_list[i].midr; - - return UINT64_MAX; diff --git a/abort-no-flush.patch b/abort-no-flush.patch deleted file mode 100644 index a32b6fe..0000000 --- a/abort-no-flush.patch +++ /dev/null @@ -1,80 +0,0 @@ -Don't close or flush stdio streams on abort - - [BZ #15436] - * stdlib/abort.c (abort): Don't call fflush and __fcloseall. - -Index: glibc-2.19/stdlib/abort.c -=================================================================== ---- glibc-2.19.orig/stdlib/abort.c -+++ glibc-2.19/stdlib/abort.c -@@ -30,9 +30,6 @@ - # define ABORT_INSTRUCTION - #endif - --#include --#define fflush(s) _IO_flush_all_lockp (0) -- - /* Exported variable to locate abort message in core files etc. */ - struct abort_msg_s *__abort_msg __attribute__ ((nocommon)); - libc_hidden_def (__abort_msg) -@@ -66,16 +63,8 @@ abort (void) - __sigprocmask (SIG_UNBLOCK, &sigs, 0); - } - -- /* Flush all streams. We cannot close them now because the user -- might have registered a handler for SIGABRT. */ -- if (stage == 1) -- { -- ++stage; -- fflush (NULL); -- } -- - /* Send signal which possibly calls a user handler. */ -- if (stage == 2) -+ if (stage == 1) - { - /* This stage is special: we must allow repeated calls of - `abort' when a user defined handler for SIGABRT is installed. -@@ -93,7 +82,7 @@ abort (void) - } - - /* There was a handler installed. Now remove it. */ -- if (stage == 3) -+ if (stage == 2) - { - ++stage; - memset (&act, '\0', sizeof (struct sigaction)); -@@ -103,30 +92,22 @@ abort (void) - __sigaction (SIGABRT, &act, NULL); - } - -- /* Now close the streams which also flushes the output the user -- defined handler might has produced. */ -- if (stage == 4) -- { -- ++stage; -- __fcloseall (); -- } -- - /* Try again. */ -- if (stage == 5) -+ if (stage == 3) - { - ++stage; - raise (SIGABRT); - } - - /* Now try to abort using the system specific command. */ -- if (stage == 6) -+ if (stage == 4) - { - ++stage; - ABORT_INSTRUCTION; - } - - /* If we can't signal ourselves and the abort instruction failed, exit. */ -- if (stage == 7) -+ if (stage == 5) - { - ++stage; - _exit (127); diff --git a/add-locales.patch b/add-locales.patch index 7a18cd1..bb2d61e 100644 --- a/add-locales.patch +++ b/add-locales.patch @@ -1,8 +1,8 @@ -Index: glibc-2.25/localedata/SUPPORTED +Index: glibc-2.27/localedata/SUPPORTED =================================================================== ---- glibc-2.25.orig/localedata/SUPPORTED -+++ glibc-2.25/localedata/SUPPORTED -@@ -129,6 +129,7 @@ en_CA.UTF-8/UTF-8 \ +--- glibc-2.27.orig/localedata/SUPPORTED ++++ glibc-2.27/localedata/SUPPORTED +@@ -135,6 +135,7 @@ en_CA.UTF-8/UTF-8 \ en_CA/ISO-8859-1 \ en_DK.UTF-8/UTF-8 \ en_DK/ISO-8859-1 \ @@ -10,15 +10,15 @@ Index: glibc-2.25/localedata/SUPPORTED en_GB.UTF-8/UTF-8 \ en_GB/ISO-8859-1 \ en_HK.UTF-8/UTF-8 \ -@@ -145,6 +146,7 @@ en_PH.UTF-8/UTF-8 \ - en_PH/ISO-8859-1 \ +@@ -152,6 +153,7 @@ en_PH/ISO-8859-1 \ + en_SC.UTF-8/UTF-8 \ en_SG.UTF-8/UTF-8 \ en_SG/ISO-8859-1 \ +en_US.ISO-8859-15/ISO-8859-15 \ en_US.UTF-8/UTF-8 \ en_US/ISO-8859-1 \ en_ZA.UTF-8/UTF-8 \ -@@ -269,6 +271,8 @@ it_IT/ISO-8859-1 \ +@@ -277,6 +279,8 @@ it_IT/ISO-8859-1 \ it_IT@euro/ISO-8859-15 \ iu_CA/UTF-8 \ ja_JP.EUC-JP/EUC-JP \ diff --git a/assert-pedantic.patch b/assert-pedantic.patch deleted file mode 100644 index 4d7c9d1..0000000 --- a/assert-pedantic.patch +++ /dev/null @@ -1,192 +0,0 @@ -2017-08-21 Florian Weimer - - [BZ #21972] - * assert/assert.h (assert): Use static_cast (bool) for C++. - Use the ternary operator in the warning branch for GNU C. - * assert/Makefile (tests): Add tst-assert-c++, tst-assert-g++. - (CFLAGS-tst-assert-c++.o): Compile in C++11 mode. - (CFLAGS-tst-assert-g++.o): Compile in GnU C++11 mode. - (LDLIBS-tst-assert-c++, LDLIBS-tst-assert-g++): Link with libstdc++. - * assert/tst-assert-c++.cc, assert/tst-assert-g++.cc: New files. - -2017-08-11 Florian Weimer - - [BZ #21242] - * assert/assert.h [__GNUC__ && !__STRICT_ANSI__] (assert): - Suppress pedantic warning resulting from statement expression. - (__ASSERT_FUNCTION): Add missing __extension__. - -Index: glibc-2.26/assert/Makefile -=================================================================== ---- glibc-2.26.orig/assert/Makefile -+++ glibc-2.26/assert/Makefile -@@ -25,6 +25,15 @@ include ../Makeconfig - headers := assert.h - - routines := assert assert-perr __assert --tests := test-assert test-assert-perr -+tests := test-assert test-assert-perr tst-assert-c++ tst-assert-g++ - - include ../Rules -+ -+ifeq ($(have-cxx-thread_local),yes) -+CFLAGS-tst-assert-c++.o = -std=c++11 -+LDLIBS-tst-assert-c++ = -lstdc++ -+CFLAGS-tst-assert-g++.o = -std=gnu++11 -+LDLIBS-tst-assert-g++ = -lstdc++ -+else -+tests-unsupported += tst-assert-c++ tst-assert-g++ -+endif -Index: glibc-2.26/assert/assert.h -=================================================================== ---- glibc-2.26.orig/assert/assert.h -+++ glibc-2.26/assert/assert.h -@@ -85,19 +85,29 @@ __END_DECLS - /* When possible, define assert so that it does not add extra - parentheses around EXPR. Otherwise, those added parentheses would - suppress warnings we'd expect to be detected by gcc's -Wparentheses. */ --# if !defined __GNUC__ || defined __STRICT_ANSI__ -+# if defined __cplusplus -+# define assert(expr) \ -+ (static_cast (expr) \ -+ ? void (0) \ -+ : __assert_fail (#expr, __FILE__, __LINE__, __ASSERT_FUNCTION)) -+# elif !defined __GNUC__ || defined __STRICT_ANSI__ - # define assert(expr) \ - ((expr) \ - ? __ASSERT_VOID_CAST (0) \ - : __assert_fail (#expr, __FILE__, __LINE__, __ASSERT_FUNCTION)) - # else -+/* The first occurrence of EXPR is not evaluated due to the sizeof, -+ but will trigger any pedantic warnings masked by the __extension__ -+ for the second occurrence. The ternary operator is required to -+ support function pointers and bit fields in this context, and to -+ suppress the evaluation of variable length arrays. */ - # define assert(expr) \ -- ({ \ -+ ((void) sizeof ((expr) ? 1 : 0), __extension__ ({ \ - if (expr) \ - ; /* empty */ \ - else \ - __assert_fail (#expr, __FILE__, __LINE__, __ASSERT_FUNCTION); \ -- }) -+ })) - # endif - - # ifdef __USE_GNU -@@ -113,7 +123,7 @@ __END_DECLS - C9x has a similar variable called __func__, but prefer the GCC one since - it demangles C++ function names. */ - # if defined __cplusplus ? __GNUC_PREREQ (2, 6) : __GNUC_PREREQ (2, 4) --# define __ASSERT_FUNCTION __PRETTY_FUNCTION__ -+# define __ASSERT_FUNCTION __extension__ __PRETTY_FUNCTION__ - # else - # if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L - # define __ASSERT_FUNCTION __func__ -Index: glibc-2.26/assert/tst-assert-c++.cc -=================================================================== ---- /dev/null -+++ glibc-2.26/assert/tst-assert-c++.cc -@@ -0,0 +1,78 @@ -+/* Tests for interactions between C++ and assert. -+ 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 -+ -+/* The C++ standard requires that if the assert argument is a constant -+ subexpression, then the assert itself is one, too. */ -+constexpr int -+check_constexpr () -+{ -+ return (assert (true), 1); -+} -+ -+/* Objects of this class can be contextually converted to bool, but -+ cannot be compared to int. */ -+struct no_int -+{ -+ no_int () = default; -+ no_int (const no_int &) = delete; -+ -+ explicit operator bool () const -+ { -+ return true; -+ } -+ -+ bool operator! () const; /* No definition. */ -+ template bool operator== (T) const; /* No definition. */ -+ template bool operator!= (T) const; /* No definition. */ -+}; -+ -+/* This class tests that operator== is not used by assert. */ -+struct bool_and_int -+{ -+ bool_and_int () = default; -+ bool_and_int (const no_int &) = delete; -+ -+ explicit operator bool () const -+ { -+ return true; -+ } -+ -+ bool operator! () const; /* No definition. */ -+ template bool operator== (T) const; /* No definition. */ -+ template bool operator!= (T) const; /* No definition. */ -+}; -+ -+static int -+do_test () -+{ -+ { -+ no_int value; -+ assert (value); -+ } -+ -+ { -+ bool_and_int value; -+ assert (value); -+ } -+ -+ return 0; -+} -+ -+#include -Index: glibc-2.26/assert/tst-assert-g++.cc -=================================================================== ---- /dev/null -+++ glibc-2.26/assert/tst-assert-g++.cc -@@ -0,0 +1,19 @@ -+/* Tests for interactions between C++ and assert. GNU C++11 version. -+ 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 diff --git a/dl-init-paths-overflow.patch b/dl-init-paths-overflow.patch deleted file mode 100644 index 40b2d18..0000000 --- a/dl-init-paths-overflow.patch +++ /dev/null @@ -1,90 +0,0 @@ -2017-12-18 Dmitry V. Levin - - [BZ #22627] - * elf/dl-load.c (_dl_init_paths): Remove _dl_dst_substitute preparatory - code and invocation. - -2017-12-14 Florian Weimer - - [BZ #22607] - CVE-2017-1000409 - * elf/dl-load.c (_dl_init_paths): Compute number of components in - the expanded path string. - -2017-12-14 Florian Weimer - - [BZ #22606] - CVE-2017-1000408 - * elf/dl-load.c (system_dirs): Update comment. - (_dl_init_paths): Use nsystem_dirs_len to compute the array size. - -Index: glibc-2.26/elf/dl-load.c -=================================================================== ---- glibc-2.26.orig/elf/dl-load.c -+++ glibc-2.26/elf/dl-load.c -@@ -103,7 +103,9 @@ static size_t ncapstr attribute_relro; - static size_t max_capstrlen attribute_relro; - - --/* Get the generated information about the trusted directories. */ -+/* Get the generated information about the trusted directories. Use -+ an array of concatenated strings to avoid relocations. See -+ gen-trusted-dirs.awk. */ - #include "trusted-dirs.h" - - static const char system_dirs[] = SYSTEM_DIRS; -@@ -688,9 +690,8 @@ _dl_init_paths (const char *llp) - + ncapstr * sizeof (enum r_dir_status)) - / sizeof (struct r_search_path_elem)); - -- rtld_search_dirs.dirs[0] = (struct r_search_path_elem *) -- malloc ((sizeof (system_dirs) / sizeof (system_dirs[0])) -- * round_size * sizeof (struct r_search_path_elem)); -+ rtld_search_dirs.dirs[0] = malloc (nsystem_dirs_len * round_size -+ * sizeof (*rtld_search_dirs.dirs[0])); - if (rtld_search_dirs.dirs[0] == NULL) - { - errstring = N_("cannot create cache for search path"); -@@ -776,37 +777,14 @@ _dl_init_paths (const char *llp) - - if (llp != NULL && *llp != '\0') - { -- size_t nllp; -- const char *cp = llp; -- char *llp_tmp; -- --#ifdef SHARED -- /* Expand DSTs. */ -- size_t cnt = DL_DST_COUNT (llp, 1); -- if (__glibc_likely (cnt == 0)) -- llp_tmp = strdupa (llp); -- else -- { -- /* Determine the length of the substituted string. */ -- size_t total = DL_DST_REQUIRED (l, llp, strlen (llp), cnt); -- -- /* Allocate the necessary memory. */ -- llp_tmp = (char *) alloca (total + 1); -- llp_tmp = _dl_dst_substitute (l, llp, llp_tmp, 1); -- } --#else -- llp_tmp = strdupa (llp); --#endif -+ char *llp_tmp = strdupa (llp); - - /* Decompose the LD_LIBRARY_PATH contents. First determine how many - elements it has. */ -- nllp = 1; -- while (*cp) -- { -- if (*cp == ':' || *cp == ';') -- ++nllp; -- ++cp; -- } -+ size_t nllp = 1; -+ for (const char *cp = llp_tmp; *cp != '\0'; ++cp) -+ if (*cp == ':' || *cp == ';') -+ ++nllp; - - env_path_list.dirs = (struct r_search_path_elem **) - malloc ((nllp + 1) * sizeof (struct r_search_path_elem *)); diff --git a/dl-runtime-resolve-opt-avx512f.patch b/dl-runtime-resolve-opt-avx512f.patch deleted file mode 100644 index d3bc303..0000000 --- a/dl-runtime-resolve-opt-avx512f.patch +++ /dev/null @@ -1,26 +0,0 @@ -2017-08-06 H.J. Lu - - [BZ #21871] - * sysdeps/x86/cpu-features.c (init_cpu_features): Set - bit_arch_Use_dl_runtime_resolve_opt only with AVX512F. - -Index: glibc-2.26/sysdeps/x86/cpu-features.c -=================================================================== ---- glibc-2.26.orig/sysdeps/x86/cpu-features.c -+++ glibc-2.26/sysdeps/x86/cpu-features.c -@@ -244,10 +244,13 @@ init_cpu_features (struct cpu_features * - |= bit_arch_Prefer_No_AVX512; - - /* To avoid SSE transition penalty, use _dl_runtime_resolve_slow. -- If XGETBV suports ECX == 1, use _dl_runtime_resolve_opt. */ -+ If XGETBV suports ECX == 1, use _dl_runtime_resolve_opt. -+ Use _dl_runtime_resolve_opt only with AVX512F since it is -+ slower than _dl_runtime_resolve_slow with AVX. */ - cpu_features->feature[index_arch_Use_dl_runtime_resolve_slow] - |= bit_arch_Use_dl_runtime_resolve_slow; -- if (cpu_features->max_cpuid >= 0xd) -+ if (CPU_FEATURES_ARCH_P (cpu_features, AVX512F_Usable) -+ && cpu_features->max_cpuid >= 0xd) - { - unsigned int eax; - diff --git a/dl-runtime-resolve-xsave.patch b/dl-runtime-resolve-xsave.patch deleted file mode 100644 index f28c508..0000000 --- a/dl-runtime-resolve-xsave.patch +++ /dev/null @@ -1,851 +0,0 @@ -2017-10-22 H.J. Lu - - [BZ #21265] - * sysdeps/x86/cpu-features-offsets.sym (XSAVE_STATE_SIZE_OFFSET): - New. - * sysdeps/x86/cpu-features.c: Include . - (get_common_indeces): Set xsave_state_size, xsave_state_full_size - and bit_arch_XSAVEC_Usable if needed. - (init_cpu_features): Remove bit_arch_Use_dl_runtime_resolve_slow - and bit_arch_Use_dl_runtime_resolve_opt. - * sysdeps/x86/cpu-features.h (bit_arch_Use_dl_runtime_resolve_opt): - Removed. - (bit_arch_Use_dl_runtime_resolve_slow): Likewise. - (bit_arch_Prefer_No_AVX512): Updated. - (bit_arch_MathVec_Prefer_No_AVX512): Likewise. - (bit_arch_XSAVEC_Usable): New. - (STATE_SAVE_OFFSET): Likewise. - (STATE_SAVE_MASK): Likewise. - [__ASSEMBLER__]: Include . - (cpu_features): Add xsave_state_size and xsave_state_full_size. - (index_arch_Use_dl_runtime_resolve_opt): Removed. - (index_arch_Use_dl_runtime_resolve_slow): Likewise. - (index_arch_XSAVEC_Usable): New. - * sysdeps/x86/cpu-tunables.c (TUNABLE_CALLBACK (set_hwcaps)): - Support XSAVEC_Usable. Remove Use_dl_runtime_resolve_slow. - * sysdeps/x86_64/Makefile (tst-x86_64-1-ENV): New if tunables - is enabled. - * sysdeps/x86_64/dl-machine.h (elf_machine_runtime_setup): - Replace _dl_runtime_resolve_sse, _dl_runtime_resolve_avx, - _dl_runtime_resolve_avx_slow, _dl_runtime_resolve_avx_opt, - _dl_runtime_resolve_avx512 and _dl_runtime_resolve_avx512_opt - with _dl_runtime_resolve_fxsave, _dl_runtime_resolve_xsave and - _dl_runtime_resolve_xsavec. - * sysdeps/x86_64/dl-trampoline.S (DL_RUNTIME_UNALIGNED_VEC_SIZE): - Removed. - (DL_RUNTIME_RESOLVE_REALIGN_STACK): Check STATE_SAVE_ALIGNMENT - instead of VEC_SIZE. - (REGISTER_SAVE_BND0): Removed. - (REGISTER_SAVE_BND1): Likewise. - (REGISTER_SAVE_BND3): Likewise. - (REGISTER_SAVE_RAX): Always defined to 0. - (VMOV): Removed. - (_dl_runtime_resolve_avx): Likewise. - (_dl_runtime_resolve_avx_slow): Likewise. - (_dl_runtime_resolve_avx_opt): Likewise. - (_dl_runtime_resolve_avx512): Likewise. - (_dl_runtime_resolve_avx512_opt): Likewise. - (_dl_runtime_resolve_sse): Likewise. - (_dl_runtime_resolve_sse_vex): Likewise. - (USE_FXSAVE): New. - (_dl_runtime_resolve_fxsave): Likewise. - (USE_XSAVE): Likewise. - (_dl_runtime_resolve_xsave): Likewise. - (USE_XSAVEC): Likewise. - (_dl_runtime_resolve_xsavec): Likewise. - * sysdeps/x86_64/dl-trampoline.h (_dl_runtime_resolve_avx512): - Removed. - (_dl_runtime_resolve_avx512_opt): Likewise. - (_dl_runtime_resolve_avx): Likewise. - (_dl_runtime_resolve_avx_opt): Likewise. - (_dl_runtime_resolve_sse): Likewise. - (_dl_runtime_resolve_sse_vex): Likewise. - (_dl_runtime_resolve_fxsave): New. - (_dl_runtime_resolve_xsave): Likewise. - (_dl_runtime_resolve_xsavec): Likewise. - -Index: glibc-2.26/sysdeps/x86/cpu-features-offsets.sym -=================================================================== ---- glibc-2.26.orig/sysdeps/x86/cpu-features-offsets.sym -+++ glibc-2.26/sysdeps/x86/cpu-features-offsets.sym -@@ -15,6 +15,7 @@ CPUID_ECX_OFFSET offsetof (struct cpuid_ - CPUID_EDX_OFFSET offsetof (struct cpuid_registers, edx) - FAMILY_OFFSET offsetof (struct cpu_features, family) - MODEL_OFFSET offsetof (struct cpu_features, model) -+XSAVE_STATE_SIZE_OFFSET offsetof (struct cpu_features, xsave_state_size) - FEATURE_OFFSET offsetof (struct cpu_features, feature) - FEATURE_SIZE sizeof (unsigned int) - -Index: glibc-2.26/sysdeps/x86/cpu-features.c -=================================================================== ---- glibc-2.26.orig/sysdeps/x86/cpu-features.c -+++ glibc-2.26/sysdeps/x86/cpu-features.c -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - - #if HAVE_TUNABLES - # define TUNABLE_NAMESPACE tune -@@ -103,6 +104,76 @@ get_common_indeces (struct cpu_features - } - } - } -+ -+ /* For _dl_runtime_resolve, set xsave_state_size to xsave area -+ size + integer register save size and align it to 64 bytes. */ -+ if (cpu_features->max_cpuid >= 0xd) -+ { -+ unsigned int eax, ebx, ecx, edx; -+ -+ __cpuid_count (0xd, 0, eax, ebx, ecx, edx); -+ if (ebx != 0) -+ { -+ unsigned int xsave_state_full_size -+ = ALIGN_UP (ebx + STATE_SAVE_OFFSET, 64); -+ -+ cpu_features->xsave_state_size -+ = xsave_state_full_size; -+ cpu_features->xsave_state_full_size -+ = xsave_state_full_size; -+ -+ __cpuid_count (0xd, 1, eax, ebx, ecx, edx); -+ -+ /* Check if XSAVEC is available. */ -+ if ((eax & (1 << 1)) != 0) -+ { -+ unsigned int xstate_comp_offsets[32]; -+ unsigned int xstate_comp_sizes[32]; -+ unsigned int i; -+ -+ xstate_comp_offsets[0] = 0; -+ xstate_comp_offsets[1] = 160; -+ xstate_comp_offsets[2] = 576; -+ xstate_comp_sizes[0] = 160; -+ xstate_comp_sizes[1] = 256; -+ -+ for (i = 2; i < 32; i++) -+ { -+ if ((STATE_SAVE_MASK & (1 << i)) != 0) -+ { -+ __cpuid_count (0xd, i, eax, ebx, ecx, edx); -+ xstate_comp_sizes[i] = eax; -+ } -+ else -+ { -+ ecx = 0; -+ xstate_comp_sizes[i] = 0; -+ } -+ -+ if (i > 2) -+ { -+ xstate_comp_offsets[i] -+ = (xstate_comp_offsets[i - 1] -+ + xstate_comp_sizes[i -1]); -+ if ((ecx & (1 << 1)) != 0) -+ xstate_comp_offsets[i] -+ = ALIGN_UP (xstate_comp_offsets[i], 64); -+ } -+ } -+ -+ /* Use XSAVEC. */ -+ unsigned int size -+ = xstate_comp_offsets[31] + xstate_comp_sizes[31]; -+ if (size) -+ { -+ cpu_features->xsave_state_size -+ = ALIGN_UP (size + STATE_SAVE_OFFSET, 64); -+ cpu_features->feature[index_arch_XSAVEC_Usable] -+ |= bit_arch_XSAVEC_Usable; -+ } -+ } -+ } -+ } - } - } - -@@ -242,23 +313,6 @@ init_cpu_features (struct cpu_features * - else - cpu_features->feature[index_arch_Prefer_No_AVX512] - |= bit_arch_Prefer_No_AVX512; -- -- /* To avoid SSE transition penalty, use _dl_runtime_resolve_slow. -- If XGETBV suports ECX == 1, use _dl_runtime_resolve_opt. -- Use _dl_runtime_resolve_opt only with AVX512F since it is -- slower than _dl_runtime_resolve_slow with AVX. */ -- cpu_features->feature[index_arch_Use_dl_runtime_resolve_slow] -- |= bit_arch_Use_dl_runtime_resolve_slow; -- if (CPU_FEATURES_ARCH_P (cpu_features, AVX512F_Usable) -- && cpu_features->max_cpuid >= 0xd) -- { -- unsigned int eax; -- -- __cpuid_count (0xd, 1, eax, ebx, ecx, edx); -- if ((eax & (1 << 2)) != 0) -- cpu_features->feature[index_arch_Use_dl_runtime_resolve_opt] -- |= bit_arch_Use_dl_runtime_resolve_opt; -- } - } - /* This spells out "AuthenticAMD". */ - else if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65) -Index: glibc-2.26/sysdeps/x86/cpu-features.h -=================================================================== ---- glibc-2.26.orig/sysdeps/x86/cpu-features.h -+++ glibc-2.26/sysdeps/x86/cpu-features.h -@@ -37,9 +37,8 @@ - #define bit_arch_Prefer_No_VZEROUPPER (1 << 17) - #define bit_arch_Fast_Unaligned_Copy (1 << 18) - #define bit_arch_Prefer_ERMS (1 << 19) --#define bit_arch_Use_dl_runtime_resolve_opt (1 << 20) --#define bit_arch_Use_dl_runtime_resolve_slow (1 << 21) --#define bit_arch_Prefer_No_AVX512 (1 << 22) -+#define bit_arch_Prefer_No_AVX512 (1 << 20) -+#define bit_arch_XSAVEC_Usable (1 << 21) - - /* CPUID Feature flags. */ - -@@ -88,6 +87,15 @@ - /* The current maximum size of the feature integer bit array. */ - #define FEATURE_INDEX_MAX 1 - -+/* Offset for fxsave/xsave area used by _dl_runtime_resolve. Also need -+ space to preserve RCX, RDX, RSI, RDI, R8, R9 and RAX. It must be -+ aligned to 16 bytes for fxsave and 64 bytes for xsave. */ -+#define STATE_SAVE_OFFSET (8 * 7 + 8) -+ -+/* Save SSE, AVX, AVX512, mask and bound registers. */ -+#define STATE_SAVE_MASK \ -+ ((1 << 1) | (1 << 2) | (1 << 3) | (1 << 5) | (1 << 6) | (1 << 7)) -+ - #ifdef __ASSEMBLER__ - - # include -@@ -123,8 +131,6 @@ - # define index_arch_Prefer_No_VZEROUPPER FEATURE_INDEX_1*FEATURE_SIZE - # define index_arch_Fast_Unaligned_Copy FEATURE_INDEX_1*FEATURE_SIZE - # define index_arch_Prefer_ERMS FEATURE_INDEX_1*FEATURE_SIZE --# define index_arch_Use_dl_runtime_resolve_opt FEATURE_INDEX_1*FEATURE_SIZE --# define index_arch_Use_dl_runtime_resolve_slow FEATURE_INDEX_1*FEATURE_SIZE - # define index_arch_Prefer_No_AVX512 FEATURE_INDEX_1*FEATURE_SIZE - - -@@ -214,6 +220,18 @@ struct cpu_features - } cpuid[COMMON_CPUID_INDEX_MAX]; - unsigned int family; - unsigned int model; -+ /* The state size for XSAVEC or XSAVE. The type must be unsigned long -+ int so that we use -+ -+ sub xsave_state_size_offset(%rip) %RSP_LP -+ -+ in _dl_runtime_resolve. */ -+ unsigned long int xsave_state_size; -+ /* The full state size for XSAVE when XSAVEC is disabled by -+ -+ GLIBC_TUNABLES=glibc.tune.hwcaps=-XSAVEC_Usable -+ */ -+ unsigned int xsave_state_full_size; - unsigned int feature[FEATURE_INDEX_MAX]; - /* Data cache size for use in memory and string routines, typically - L1 size. */ -@@ -326,9 +344,8 @@ extern const struct cpu_features *__get_ - # define index_arch_Prefer_No_VZEROUPPER FEATURE_INDEX_1 - # define index_arch_Fast_Unaligned_Copy FEATURE_INDEX_1 - # define index_arch_Prefer_ERMS FEATURE_INDEX_1 --# define index_arch_Use_dl_runtime_resolve_opt FEATURE_INDEX_1 --# define index_arch_Use_dl_runtime_resolve_slow FEATURE_INDEX_1 - # define index_arch_Prefer_No_AVX512 FEATURE_INDEX_1 -+# define index_arch_XSAVEC_Usable FEATURE_INDEX_1 - - #endif /* !__ASSEMBLER__ */ - -Index: glibc-2.26/sysdeps/x86/cpu-tunables.c -=================================================================== ---- glibc-2.26.orig/sysdeps/x86/cpu-tunables.c -+++ glibc-2.26/sysdeps/x86/cpu-tunables.c -@@ -240,6 +240,16 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_v - Slow_SSE4_2, SSE4_2, - disable, 11); - break; -+ case 13: -+ if (disable) -+ { -+ /* Update xsave_state_size to XSAVE state size. */ -+ cpu_features->xsave_state_size -+ = cpu_features->xsave_state_full_size; -+ CHECK_GLIBC_IFUNC_ARCH_OFF (n, cpu_features, -+ XSAVEC_Usable, 13); -+ } -+ break; - case 14: - if (disable) - { -@@ -308,13 +318,6 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_v - disable, 26); - } - break; -- case 27: -- { -- CHECK_GLIBC_IFUNC_ARCH_BOTH (n, cpu_features, -- Use_dl_runtime_resolve_slow, -- disable, 27); -- } -- break; - } - p += len + 1; - } -Index: glibc-2.26/sysdeps/x86_64/Makefile -=================================================================== ---- glibc-2.26.orig/sysdeps/x86_64/Makefile -+++ glibc-2.26/sysdeps/x86_64/Makefile -@@ -55,6 +55,10 @@ CFLAGS-tst-quad2pie.c = $(PIE-ccflag) - tests += tst-x86_64-1 - modules-names += x86_64/tst-x86_64mod-1 - LDFLAGS-tst-x86_64mod-1.so = -Wl,-soname,tst-x86_64mod-1.so -+ifneq (no,$(have-tunables)) -+# Test the state size for XSAVE when XSAVEC is disabled. -+tst-x86_64-1-ENV = GLIBC_TUNABLES=glibc.tune.hwcaps=-XSAVEC_Usable -+endif - - $(objpfx)tst-x86_64-1: $(objpfx)x86_64/tst-x86_64mod-1.so - -Index: glibc-2.26/sysdeps/x86_64/dl-machine.h -=================================================================== ---- glibc-2.26.orig/sysdeps/x86_64/dl-machine.h -+++ glibc-2.26/sysdeps/x86_64/dl-machine.h -@@ -66,12 +66,9 @@ static inline int __attribute__ ((unused - elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) - { - Elf64_Addr *got; -- extern void _dl_runtime_resolve_sse (ElfW(Word)) attribute_hidden; -- extern void _dl_runtime_resolve_avx (ElfW(Word)) attribute_hidden; -- extern void _dl_runtime_resolve_avx_slow (ElfW(Word)) attribute_hidden; -- extern void _dl_runtime_resolve_avx_opt (ElfW(Word)) attribute_hidden; -- extern void _dl_runtime_resolve_avx512 (ElfW(Word)) attribute_hidden; -- extern void _dl_runtime_resolve_avx512_opt (ElfW(Word)) attribute_hidden; -+ extern void _dl_runtime_resolve_fxsave (ElfW(Word)) attribute_hidden; -+ extern void _dl_runtime_resolve_xsave (ElfW(Word)) attribute_hidden; -+ extern void _dl_runtime_resolve_xsavec (ElfW(Word)) attribute_hidden; - extern void _dl_runtime_profile_sse (ElfW(Word)) attribute_hidden; - extern void _dl_runtime_profile_avx (ElfW(Word)) attribute_hidden; - extern void _dl_runtime_profile_avx512 (ElfW(Word)) attribute_hidden; -@@ -120,29 +117,14 @@ elf_machine_runtime_setup (struct link_m - /* This function will get called to fix up the GOT entry - indicated by the offset on the stack, and then jump to - the resolved address. */ -- if (HAS_ARCH_FEATURE (AVX512F_Usable)) -- { -- if (HAS_ARCH_FEATURE (Use_dl_runtime_resolve_opt)) -- *(ElfW(Addr) *) (got + 2) -- = (ElfW(Addr)) &_dl_runtime_resolve_avx512_opt; -- else -- *(ElfW(Addr) *) (got + 2) -- = (ElfW(Addr)) &_dl_runtime_resolve_avx512; -- } -- else if (HAS_ARCH_FEATURE (AVX_Usable)) -- { -- if (HAS_ARCH_FEATURE (Use_dl_runtime_resolve_opt)) -- *(ElfW(Addr) *) (got + 2) -- = (ElfW(Addr)) &_dl_runtime_resolve_avx_opt; -- else if (HAS_ARCH_FEATURE (Use_dl_runtime_resolve_slow)) -- *(ElfW(Addr) *) (got + 2) -- = (ElfW(Addr)) &_dl_runtime_resolve_avx_slow; -- else -- *(ElfW(Addr) *) (got + 2) -- = (ElfW(Addr)) &_dl_runtime_resolve_avx; -- } -+ if (GLRO(dl_x86_cpu_features).xsave_state_size != 0) -+ *(ElfW(Addr) *) (got + 2) -+ = (HAS_ARCH_FEATURE (XSAVEC_Usable) -+ ? (ElfW(Addr)) &_dl_runtime_resolve_xsavec -+ : (ElfW(Addr)) &_dl_runtime_resolve_xsave); - else -- *(ElfW(Addr) *) (got + 2) = (ElfW(Addr)) &_dl_runtime_resolve_sse; -+ *(ElfW(Addr) *) (got + 2) -+ = (ElfW(Addr)) &_dl_runtime_resolve_fxsave; - } - } - -Index: glibc-2.26/sysdeps/x86_64/dl-trampoline.S -=================================================================== ---- glibc-2.26.orig/sysdeps/x86_64/dl-trampoline.S -+++ glibc-2.26/sysdeps/x86_64/dl-trampoline.S -@@ -34,41 +34,24 @@ - # define DL_STACK_ALIGNMENT 8 - #endif - --#ifndef DL_RUNTIME_UNALIGNED_VEC_SIZE --/* The maximum size in bytes of unaligned vector load and store in the -- dynamic linker. Since SSE optimized memory/string functions with -- aligned SSE register load and store are used in the dynamic linker, -- we must set this to 8 so that _dl_runtime_resolve_sse will align the -- stack before calling _dl_fixup. */ --# define DL_RUNTIME_UNALIGNED_VEC_SIZE 8 --#endif -- --/* True if _dl_runtime_resolve should align stack to VEC_SIZE bytes. */ -+/* True if _dl_runtime_resolve should align stack for STATE_SAVE or align -+ stack to 16 bytes before calling _dl_fixup. */ - #define DL_RUNTIME_RESOLVE_REALIGN_STACK \ -- (VEC_SIZE > DL_STACK_ALIGNMENT \ -- && VEC_SIZE > DL_RUNTIME_UNALIGNED_VEC_SIZE) -- --/* Align vector register save area to 16 bytes. */ --#define REGISTER_SAVE_VEC_OFF 0 -+ (STATE_SAVE_ALIGNMENT > DL_STACK_ALIGNMENT \ -+ || 16 > DL_STACK_ALIGNMENT) - - /* Area on stack to save and restore registers used for parameter - passing when calling _dl_fixup. */ - #ifdef __ILP32__ --# define REGISTER_SAVE_RAX (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 8) - # define PRESERVE_BND_REGS_PREFIX - #else --/* Align bound register save area to 16 bytes. */ --# define REGISTER_SAVE_BND0 (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 8) --# define REGISTER_SAVE_BND1 (REGISTER_SAVE_BND0 + 16) --# define REGISTER_SAVE_BND2 (REGISTER_SAVE_BND1 + 16) --# define REGISTER_SAVE_BND3 (REGISTER_SAVE_BND2 + 16) --# define REGISTER_SAVE_RAX (REGISTER_SAVE_BND3 + 16) - # ifdef HAVE_MPX_SUPPORT - # define PRESERVE_BND_REGS_PREFIX bnd - # else - # define PRESERVE_BND_REGS_PREFIX .byte 0xf2 - # endif - #endif -+#define REGISTER_SAVE_RAX 0 - #define REGISTER_SAVE_RCX (REGISTER_SAVE_RAX + 8) - #define REGISTER_SAVE_RDX (REGISTER_SAVE_RCX + 8) - #define REGISTER_SAVE_RSI (REGISTER_SAVE_RDX + 8) -@@ -80,68 +63,56 @@ - - #define VEC_SIZE 64 - #define VMOVA vmovdqa64 --#if DL_RUNTIME_RESOLVE_REALIGN_STACK || VEC_SIZE <= DL_STACK_ALIGNMENT --# define VMOV vmovdqa64 --#else --# define VMOV vmovdqu64 --#endif - #define VEC(i) zmm##i --#define _dl_runtime_resolve _dl_runtime_resolve_avx512 - #define _dl_runtime_profile _dl_runtime_profile_avx512 - #include "dl-trampoline.h" --#undef _dl_runtime_resolve - #undef _dl_runtime_profile - #undef VEC --#undef VMOV - #undef VMOVA - #undef VEC_SIZE - - #define VEC_SIZE 32 - #define VMOVA vmovdqa --#if DL_RUNTIME_RESOLVE_REALIGN_STACK || VEC_SIZE <= DL_STACK_ALIGNMENT --# define VMOV vmovdqa --#else --# define VMOV vmovdqu --#endif - #define VEC(i) ymm##i --#define _dl_runtime_resolve _dl_runtime_resolve_avx --#define _dl_runtime_resolve_opt _dl_runtime_resolve_avx_opt - #define _dl_runtime_profile _dl_runtime_profile_avx - #include "dl-trampoline.h" --#undef _dl_runtime_resolve --#undef _dl_runtime_resolve_opt - #undef _dl_runtime_profile - #undef VEC --#undef VMOV - #undef VMOVA - #undef VEC_SIZE - - /* movaps/movups is 1-byte shorter. */ - #define VEC_SIZE 16 - #define VMOVA movaps --#if DL_RUNTIME_RESOLVE_REALIGN_STACK || VEC_SIZE <= DL_STACK_ALIGNMENT --# define VMOV movaps --#else --# define VMOV movups --#endif - #define VEC(i) xmm##i --#define _dl_runtime_resolve _dl_runtime_resolve_sse - #define _dl_runtime_profile _dl_runtime_profile_sse - #undef RESTORE_AVX - #include "dl-trampoline.h" --#undef _dl_runtime_resolve - #undef _dl_runtime_profile --#undef VMOV -+#undef VEC - #undef VMOVA -+#undef VEC_SIZE - --/* Used by _dl_runtime_resolve_avx_opt/_dl_runtime_resolve_avx512_opt -- to preserve the full vector registers with zero upper bits. */ --#define VMOVA vmovdqa --#if DL_RUNTIME_RESOLVE_REALIGN_STACK || VEC_SIZE <= DL_STACK_ALIGNMENT --# define VMOV vmovdqa --#else --# define VMOV vmovdqu --#endif --#define _dl_runtime_resolve _dl_runtime_resolve_sse_vex --#define _dl_runtime_resolve_opt _dl_runtime_resolve_avx512_opt -+#define USE_FXSAVE -+#define STATE_SAVE_ALIGNMENT 16 -+#define _dl_runtime_resolve _dl_runtime_resolve_fxsave -+#include "dl-trampoline.h" -+#undef _dl_runtime_resolve -+#undef USE_FXSAVE -+#undef STATE_SAVE_ALIGNMENT -+ -+#define USE_XSAVE -+#define STATE_SAVE_ALIGNMENT 64 -+#define _dl_runtime_resolve _dl_runtime_resolve_xsave -+#include "dl-trampoline.h" -+#undef _dl_runtime_resolve -+#undef USE_XSAVE -+#undef STATE_SAVE_ALIGNMENT -+ -+#define USE_XSAVEC -+#define STATE_SAVE_ALIGNMENT 64 -+#define _dl_runtime_resolve _dl_runtime_resolve_xsavec - #include "dl-trampoline.h" -+#undef _dl_runtime_resolve -+#undef USE_XSAVEC -+#undef STATE_SAVE_ALIGNMENT -Index: glibc-2.26/sysdeps/x86_64/dl-trampoline.h -=================================================================== ---- glibc-2.26.orig/sysdeps/x86_64/dl-trampoline.h -+++ glibc-2.26/sysdeps/x86_64/dl-trampoline.h -@@ -16,140 +16,47 @@ - License along with the GNU C Library; if not, see - . */ - --#undef REGISTER_SAVE_AREA_RAW --#ifdef __ILP32__ --/* X32 saves RCX, RDX, RSI, RDI, R8 and R9 plus RAX as well as VEC0 to -- VEC7. */ --# define REGISTER_SAVE_AREA_RAW (8 * 7 + VEC_SIZE * 8) --#else --/* X86-64 saves RCX, RDX, RSI, RDI, R8 and R9 plus RAX as well as -- BND0, BND1, BND2, BND3 and VEC0 to VEC7. */ --# define REGISTER_SAVE_AREA_RAW (8 * 7 + 16 * 4 + VEC_SIZE * 8) --#endif -+ .text -+#ifdef _dl_runtime_resolve - --#undef REGISTER_SAVE_AREA --#undef LOCAL_STORAGE_AREA --#undef BASE --#if DL_RUNTIME_RESOLVE_REALIGN_STACK --# define REGISTER_SAVE_AREA (REGISTER_SAVE_AREA_RAW + 8) --/* Local stack area before jumping to function address: RBX. */ --# define LOCAL_STORAGE_AREA 8 --# define BASE rbx --# if (REGISTER_SAVE_AREA % VEC_SIZE) != 0 --# error REGISTER_SAVE_AREA must be multples of VEC_SIZE --# endif --#else --# define REGISTER_SAVE_AREA REGISTER_SAVE_AREA_RAW --/* Local stack area before jumping to function address: All saved -- registers. */ --# define LOCAL_STORAGE_AREA REGISTER_SAVE_AREA --# define BASE rsp --# if (REGISTER_SAVE_AREA % 16) != 8 --# error REGISTER_SAVE_AREA must be odd multples of 8 --# endif --#endif -+# undef REGISTER_SAVE_AREA -+# undef LOCAL_STORAGE_AREA -+# undef BASE - -- .text --#ifdef _dl_runtime_resolve_opt --/* Use the smallest vector registers to preserve the full YMM/ZMM -- registers to avoid SSE transition penalty. */ -+# if (STATE_SAVE_ALIGNMENT % 16) != 0 -+# error STATE_SAVE_ALIGNMENT must be multples of 16 -+# endif - --# if VEC_SIZE == 32 --/* Check if the upper 128 bits in %ymm0 - %ymm7 registers are non-zero -- and preserve %xmm0 - %xmm7 registers with the zero upper bits. Since -- there is no SSE transition penalty on AVX512 processors which don't -- support XGETBV with ECX == 1, _dl_runtime_resolve_avx512_slow isn't -- provided. */ -- .globl _dl_runtime_resolve_avx_slow -- .hidden _dl_runtime_resolve_avx_slow -- .type _dl_runtime_resolve_avx_slow, @function -- .align 16 --_dl_runtime_resolve_avx_slow: -- cfi_startproc -- cfi_adjust_cfa_offset(16) # Incorporate PLT -- vorpd %ymm0, %ymm1, %ymm8 -- vorpd %ymm2, %ymm3, %ymm9 -- vorpd %ymm4, %ymm5, %ymm10 -- vorpd %ymm6, %ymm7, %ymm11 -- vorpd %ymm8, %ymm9, %ymm9 -- vorpd %ymm10, %ymm11, %ymm10 -- vpcmpeqd %xmm8, %xmm8, %xmm8 -- vorpd %ymm9, %ymm10, %ymm10 -- vptest %ymm10, %ymm8 -- # Preserve %ymm0 - %ymm7 registers if the upper 128 bits of any -- # %ymm0 - %ymm7 registers aren't zero. -- PRESERVE_BND_REGS_PREFIX -- jnc _dl_runtime_resolve_avx -- # Use vzeroupper to avoid SSE transition penalty. -- vzeroupper -- # Preserve %xmm0 - %xmm7 registers with the zero upper 128 bits -- # when the upper 128 bits of %ymm0 - %ymm7 registers are zero. -- PRESERVE_BND_REGS_PREFIX -- jmp _dl_runtime_resolve_sse_vex -- cfi_adjust_cfa_offset(-16) # Restore PLT adjustment -- cfi_endproc -- .size _dl_runtime_resolve_avx_slow, .-_dl_runtime_resolve_avx_slow -+# if (STATE_SAVE_OFFSET % STATE_SAVE_ALIGNMENT) != 0 -+# error STATE_SAVE_OFFSET must be multples of STATE_SAVE_ALIGNMENT - # endif - --/* Use XGETBV with ECX == 1 to check which bits in vector registers are -- non-zero and only preserve the non-zero lower bits with zero upper -- bits. */ -- .globl _dl_runtime_resolve_opt -- .hidden _dl_runtime_resolve_opt -- .type _dl_runtime_resolve_opt, @function -- .align 16 --_dl_runtime_resolve_opt: -- cfi_startproc -- cfi_adjust_cfa_offset(16) # Incorporate PLT -- pushq %rax -- cfi_adjust_cfa_offset(8) -- cfi_rel_offset(%rax, 0) -- pushq %rcx -- cfi_adjust_cfa_offset(8) -- cfi_rel_offset(%rcx, 0) -- pushq %rdx -- cfi_adjust_cfa_offset(8) -- cfi_rel_offset(%rdx, 0) -- movl $1, %ecx -- xgetbv -- movl %eax, %r11d -- popq %rdx -- cfi_adjust_cfa_offset(-8) -- cfi_restore (%rdx) -- popq %rcx -- cfi_adjust_cfa_offset(-8) -- cfi_restore (%rcx) -- popq %rax -- cfi_adjust_cfa_offset(-8) -- cfi_restore (%rax) --# if VEC_SIZE == 32 -- # For YMM registers, check if YMM state is in use. -- andl $bit_YMM_state, %r11d -- # Preserve %xmm0 - %xmm7 registers with the zero upper 128 bits if -- # YMM state isn't in use. -- PRESERVE_BND_REGS_PREFIX -- jz _dl_runtime_resolve_sse_vex --# elif VEC_SIZE == 16 -- # For ZMM registers, check if YMM state and ZMM state are in -- # use. -- andl $(bit_YMM_state | bit_ZMM0_15_state), %r11d -- cmpl $bit_YMM_state, %r11d -- # Preserve %zmm0 - %zmm7 registers if ZMM state is in use. -- PRESERVE_BND_REGS_PREFIX -- jg _dl_runtime_resolve_avx512 -- # Preserve %ymm0 - %ymm7 registers with the zero upper 256 bits if -- # ZMM state isn't in use. -- PRESERVE_BND_REGS_PREFIX -- je _dl_runtime_resolve_avx -- # Preserve %xmm0 - %xmm7 registers with the zero upper 384 bits if -- # neither YMM state nor ZMM state are in use. -+# if DL_RUNTIME_RESOLVE_REALIGN_STACK -+/* Local stack area before jumping to function address: RBX. */ -+# define LOCAL_STORAGE_AREA 8 -+# define BASE rbx -+# ifdef USE_FXSAVE -+/* Use fxsave to save XMM registers. */ -+# define REGISTER_SAVE_AREA (512 + STATE_SAVE_OFFSET) -+# if (REGISTER_SAVE_AREA % 16) != 0 -+# error REGISTER_SAVE_AREA must be multples of 16 -+# endif -+# endif - # else --# error Unsupported VEC_SIZE! -+# ifndef USE_FXSAVE -+# error USE_FXSAVE must be defined -+# endif -+/* Use fxsave to save XMM registers. */ -+# define REGISTER_SAVE_AREA (512 + STATE_SAVE_OFFSET + 8) -+/* Local stack area before jumping to function address: All saved -+ registers. */ -+# define LOCAL_STORAGE_AREA REGISTER_SAVE_AREA -+# define BASE rsp -+# if (REGISTER_SAVE_AREA % 16) != 8 -+# error REGISTER_SAVE_AREA must be odd multples of 8 -+# endif - # endif -- cfi_adjust_cfa_offset(-16) # Restore PLT adjustment -- cfi_endproc -- .size _dl_runtime_resolve_opt, .-_dl_runtime_resolve_opt --#endif -+ - .globl _dl_runtime_resolve - .hidden _dl_runtime_resolve - .type _dl_runtime_resolve, @function -@@ -157,21 +64,30 @@ _dl_runtime_resolve_opt: - cfi_startproc - _dl_runtime_resolve: - cfi_adjust_cfa_offset(16) # Incorporate PLT --#if DL_RUNTIME_RESOLVE_REALIGN_STACK --# if LOCAL_STORAGE_AREA != 8 --# error LOCAL_STORAGE_AREA must be 8 --# endif -+# if DL_RUNTIME_RESOLVE_REALIGN_STACK -+# if LOCAL_STORAGE_AREA != 8 -+# error LOCAL_STORAGE_AREA must be 8 -+# endif - pushq %rbx # push subtracts stack by 8. - cfi_adjust_cfa_offset(8) - cfi_rel_offset(%rbx, 0) - mov %RSP_LP, %RBX_LP - cfi_def_cfa_register(%rbx) -- and $-VEC_SIZE, %RSP_LP --#endif -+ and $-STATE_SAVE_ALIGNMENT, %RSP_LP -+# endif -+# ifdef REGISTER_SAVE_AREA - sub $REGISTER_SAVE_AREA, %RSP_LP --#if !DL_RUNTIME_RESOLVE_REALIGN_STACK -+# if !DL_RUNTIME_RESOLVE_REALIGN_STACK - cfi_adjust_cfa_offset(REGISTER_SAVE_AREA) --#endif -+# endif -+# else -+ # Allocate stack space of the required size to save the state. -+# if IS_IN (rtld) -+ sub _rtld_local_ro+RTLD_GLOBAL_RO_DL_X86_CPU_FEATURES_OFFSET+XSAVE_STATE_SIZE_OFFSET(%rip), %RSP_LP -+# else -+ sub _dl_x86_cpu_features+XSAVE_STATE_SIZE_OFFSET(%rip), %RSP_LP -+# endif -+# endif - # Preserve registers otherwise clobbered. - movq %rax, REGISTER_SAVE_RAX(%rsp) - movq %rcx, REGISTER_SAVE_RCX(%rsp) -@@ -180,59 +96,42 @@ _dl_runtime_resolve: - movq %rdi, REGISTER_SAVE_RDI(%rsp) - movq %r8, REGISTER_SAVE_R8(%rsp) - movq %r9, REGISTER_SAVE_R9(%rsp) -- VMOV %VEC(0), (REGISTER_SAVE_VEC_OFF)(%rsp) -- VMOV %VEC(1), (REGISTER_SAVE_VEC_OFF + VEC_SIZE)(%rsp) -- VMOV %VEC(2), (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 2)(%rsp) -- VMOV %VEC(3), (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 3)(%rsp) -- VMOV %VEC(4), (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 4)(%rsp) -- VMOV %VEC(5), (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 5)(%rsp) -- VMOV %VEC(6), (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 6)(%rsp) -- VMOV %VEC(7), (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 7)(%rsp) --#ifndef __ILP32__ -- # We also have to preserve bound registers. These are nops if -- # Intel MPX isn't available or disabled. --# ifdef HAVE_MPX_SUPPORT -- bndmov %bnd0, REGISTER_SAVE_BND0(%rsp) -- bndmov %bnd1, REGISTER_SAVE_BND1(%rsp) -- bndmov %bnd2, REGISTER_SAVE_BND2(%rsp) -- bndmov %bnd3, REGISTER_SAVE_BND3(%rsp) -+# ifdef USE_FXSAVE -+ fxsave STATE_SAVE_OFFSET(%rsp) - # else --# if REGISTER_SAVE_BND0 == 0 -- .byte 0x66,0x0f,0x1b,0x04,0x24 -+ movl $STATE_SAVE_MASK, %eax -+ xorl %edx, %edx -+ # Clear the XSAVE Header. -+# ifdef USE_XSAVE -+ movq %rdx, (STATE_SAVE_OFFSET + 512)(%rsp) -+ movq %rdx, (STATE_SAVE_OFFSET + 512 + 8)(%rsp) -+# endif -+ movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 2)(%rsp) -+ movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 3)(%rsp) -+ movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 4)(%rsp) -+ movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 5)(%rsp) -+ movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 6)(%rsp) -+ movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 7)(%rsp) -+# ifdef USE_XSAVE -+ xsave STATE_SAVE_OFFSET(%rsp) - # else -- .byte 0x66,0x0f,0x1b,0x44,0x24,REGISTER_SAVE_BND0 -+ xsavec STATE_SAVE_OFFSET(%rsp) - # endif -- .byte 0x66,0x0f,0x1b,0x4c,0x24,REGISTER_SAVE_BND1 -- .byte 0x66,0x0f,0x1b,0x54,0x24,REGISTER_SAVE_BND2 -- .byte 0x66,0x0f,0x1b,0x5c,0x24,REGISTER_SAVE_BND3 - # endif --#endif - # Copy args pushed by PLT in register. - # %rdi: link_map, %rsi: reloc_index - mov (LOCAL_STORAGE_AREA + 8)(%BASE), %RSI_LP - mov LOCAL_STORAGE_AREA(%BASE), %RDI_LP - call _dl_fixup # Call resolver. - mov %RAX_LP, %R11_LP # Save return value --#ifndef __ILP32__ -- # Restore bound registers. These are nops if Intel MPX isn't -- # avaiable or disabled. --# ifdef HAVE_MPX_SUPPORT -- bndmov REGISTER_SAVE_BND3(%rsp), %bnd3 -- bndmov REGISTER_SAVE_BND2(%rsp), %bnd2 -- bndmov REGISTER_SAVE_BND1(%rsp), %bnd1 -- bndmov REGISTER_SAVE_BND0(%rsp), %bnd0 -+ # Get register content back. -+# ifdef USE_FXSAVE -+ fxrstor STATE_SAVE_OFFSET(%rsp) - # else -- .byte 0x66,0x0f,0x1a,0x5c,0x24,REGISTER_SAVE_BND3 -- .byte 0x66,0x0f,0x1a,0x54,0x24,REGISTER_SAVE_BND2 -- .byte 0x66,0x0f,0x1a,0x4c,0x24,REGISTER_SAVE_BND1 --# if REGISTER_SAVE_BND0 == 0 -- .byte 0x66,0x0f,0x1a,0x04,0x24 --# else -- .byte 0x66,0x0f,0x1a,0x44,0x24,REGISTER_SAVE_BND0 --# endif -+ movl $STATE_SAVE_MASK, %eax -+ xorl %edx, %edx -+ xrstor STATE_SAVE_OFFSET(%rsp) - # endif --#endif -- # Get register content back. - movq REGISTER_SAVE_R9(%rsp), %r9 - movq REGISTER_SAVE_R8(%rsp), %r8 - movq REGISTER_SAVE_RDI(%rsp), %rdi -@@ -240,20 +139,12 @@ _dl_runtime_resolve: - movq REGISTER_SAVE_RDX(%rsp), %rdx - movq REGISTER_SAVE_RCX(%rsp), %rcx - movq REGISTER_SAVE_RAX(%rsp), %rax -- VMOV (REGISTER_SAVE_VEC_OFF)(%rsp), %VEC(0) -- VMOV (REGISTER_SAVE_VEC_OFF + VEC_SIZE)(%rsp), %VEC(1) -- VMOV (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 2)(%rsp), %VEC(2) -- VMOV (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 3)(%rsp), %VEC(3) -- VMOV (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 4)(%rsp), %VEC(4) -- VMOV (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 5)(%rsp), %VEC(5) -- VMOV (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 6)(%rsp), %VEC(6) -- VMOV (REGISTER_SAVE_VEC_OFF + VEC_SIZE * 7)(%rsp), %VEC(7) --#if DL_RUNTIME_RESOLVE_REALIGN_STACK -+# if DL_RUNTIME_RESOLVE_REALIGN_STACK - mov %RBX_LP, %RSP_LP - cfi_def_cfa_register(%rsp) - movq (%rsp), %rbx - cfi_restore(%rbx) --#endif -+# endif - # Adjust stack(PLT did 2 pushes) - add $(LOCAL_STORAGE_AREA + 16), %RSP_LP - cfi_adjust_cfa_offset(-(LOCAL_STORAGE_AREA + 16)) -@@ -262,11 +153,9 @@ _dl_runtime_resolve: - jmp *%r11 # Jump to function address. - cfi_endproc - .size _dl_runtime_resolve, .-_dl_runtime_resolve -+#endif - - --/* To preserve %xmm0 - %xmm7 registers, dl-trampoline.h is included -- twice, for _dl_runtime_resolve_sse and _dl_runtime_resolve_sse_vex. -- But we don't need another _dl_runtime_profile for XMM registers. */ - #if !defined PROF && defined _dl_runtime_profile - # if (LR_VECTOR_OFFSET % VEC_SIZE) != 0 - # error LR_VECTOR_OFFSET must be multples of VEC_SIZE diff --git a/dynarray-allocation.patch b/dynarray-allocation.patch deleted file mode 100644 index a67b56e..0000000 --- a/dynarray-allocation.patch +++ /dev/null @@ -1,127 +0,0 @@ -2017-08-30 Florian Weimer - - * malloc/dynarray_emplace_enlarge.c - (__libc_dynarray_emplace_enlarge): Set errno on overflow. - * malloc/dynarray_resize.c (__libc_dynarray_resize): Likewise. - * malloc/tst-dynarray.c (test_long_overflow): New function. - (do_test): Call it. - -2017-09-06 Florian Weimer - - * malloc/dynarray_emplace_enlarge.c - (__libc_dynarray_emplace_enlarge): Add missing else. - -Index: glibc-2.26/malloc/dynarray_emplace_enlarge.c -=================================================================== ---- glibc-2.26.orig/malloc/dynarray_emplace_enlarge.c -+++ glibc-2.26/malloc/dynarray_emplace_enlarge.c -@@ -17,6 +17,7 @@ - . */ - - #include -+#include - #include - #include - #include -@@ -32,7 +33,7 @@ __libc_dynarray_emplace_enlarge (struct - size. */ - if (element_size < 4) - new_allocated = 16; -- if (element_size < 8) -+ else if (element_size < 8) - new_allocated = 8; - else - new_allocated = 4; -@@ -43,8 +44,11 @@ __libc_dynarray_emplace_enlarge (struct - { - new_allocated = list->allocated + list->allocated / 2 + 1; - if (new_allocated <= list->allocated) -- /* Overflow. */ -- return false; -+ { -+ /* Overflow. */ -+ __set_errno (ENOMEM); -+ return false; -+ } - } - - size_t new_size; -Index: glibc-2.26/malloc/dynarray_resize.c -=================================================================== ---- glibc-2.26.orig/malloc/dynarray_resize.c -+++ glibc-2.26/malloc/dynarray_resize.c -@@ -17,6 +17,7 @@ - . */ - - #include -+#include - #include - #include - #include -@@ -38,7 +39,11 @@ __libc_dynarray_resize (struct dynarray_ - - size_t new_size_bytes; - if (check_mul_overflow_size_t (size, element_size, &new_size_bytes)) -- return false; -+ { -+ /* Overflow. */ -+ __set_errno (ENOMEM); -+ return false; -+ } - void *new_array; - if (list->array == scratch) - { -Index: glibc-2.26/malloc/tst-dynarray.c -=================================================================== ---- glibc-2.26.orig/malloc/tst-dynarray.c -+++ glibc-2.26/malloc/tst-dynarray.c -@@ -18,6 +18,9 @@ - - #include "tst-dynarray-shared.h" - -+#include -+#include -+ - #define DYNARRAY_STRUCT dynarray_long - #define DYNARRAY_ELEMENT long - #define DYNARRAY_PREFIX dynarray_long_ -@@ -463,6 +466,31 @@ test_long_init (void) - } - } - -+/* Test overflow in resize. */ -+static void -+test_long_overflow (void) -+{ -+ { -+ struct dynarray_long dyn; -+ dynarray_long_init (&dyn); -+ errno = EINVAL; -+ TEST_VERIFY (!dynarray_long_resize -+ (&dyn, (SIZE_MAX / sizeof (long)) + 1)); -+ TEST_VERIFY (errno == ENOMEM); -+ TEST_VERIFY (dynarray_long_has_failed (&dyn)); -+ } -+ -+ { -+ struct dynarray_long_noscratch dyn; -+ dynarray_long_noscratch_init (&dyn); -+ errno = EINVAL; -+ TEST_VERIFY (!dynarray_long_noscratch_resize -+ (&dyn, (SIZE_MAX / sizeof (long)) + 1)); -+ TEST_VERIFY (errno == ENOMEM); -+ TEST_VERIFY (dynarray_long_noscratch_has_failed (&dyn)); -+ } -+} -+ - /* Test NUL-terminated string construction with the add function and - the simple finalize function. */ - static void -@@ -538,6 +566,7 @@ do_test (void) - test_int (); - test_str (); - test_long_init (); -+ test_long_overflow (); - test_zstr (); - return 0; - } diff --git a/eh-frame-zero-terminator.patch b/eh-frame-zero-terminator.patch deleted file mode 100644 index 28a4c16..0000000 --- a/eh-frame-zero-terminator.patch +++ /dev/null @@ -1,31 +0,0 @@ -2017-08-31 H.J. Lu - - [BZ #22051] - * Makerules (build-module-helper-objlist): Filter out - $(elf-objpfx)sofini.os. - (build-shlib-objlist): Append $(elf-objpfx)sofini.os if it is - needed. - -Index: glibc-2.26/Makerules -=================================================================== ---- glibc-2.26.orig/Makerules -+++ glibc-2.26/Makerules -@@ -686,14 +686,17 @@ $(build-module-helper) -o $@ $(shlib-lds - $(call after-link,$@) - endef - -+# sofini.os must be placed last since it terminates .eh_frame section. - build-module-helper-objlist = \ - $(patsubst %_pic.a,$(whole-archive) %_pic.a $(no-whole-archive),\ - $(filter-out %.lds $(map-file) $(+preinit) $(+postinit) \ -+ $(elf-objpfx)sofini.os \ - $(link-libc-deps),$^)) - - build-module-objlist = $(build-module-helper-objlist) $(LDLIBS-$(@F:%.so=%).so) - build-shlib-objlist = $(build-module-helper-objlist) \ -- $(LDLIBS-$(@F:lib%.so=%).so) -+ $(LDLIBS-$(@F:lib%.so=%).so) \ -+ $(filter $(elf-objpfx)sofini.os,$^) - - # Don't try to use -lc when making libc.so itself. - # Also omits crti.o and crtn.o, which we do not want diff --git a/falkor-memcpy-memmove.patch b/falkor-memcpy-memmove.patch deleted file mode 100644 index 850a9c6..0000000 --- a/falkor-memcpy-memmove.patch +++ /dev/null @@ -1,573 +0,0 @@ -2017-10-10 Siddhesh Poyarekar - - * sysdeps/aarch64/multiarch/Makefile (sysdep_routines): Add - memmove_falkor. - * sysdeps/aarch64/multiarch/ifunc-impl-list.c - (__libc_ifunc_impl_list): Likewise. - * sysdeps/aarch64/multiarch/memmove.c: Likewise. - * sysdeps/aarch64/multiarch/memmove_falkor.S: New file. - - * benchtests/bench-memmove-walk.c: New file. - * benchtests/Makefile (string-benchset): Add it. - - * benchtests/bench-memset-walk.c: New file. - * benchtests/Makefile (string-benchset): Add it. - - * benchtests/bench-memcpy-walk.c: New file. - * benchtests/Makefile (string-benchset): Add it. - -2017-10-10 Siddhesh Poyarekar - - * manual/tunables.texi (Tunable glibc.tune.cpu): Add falkor. - * sysdeps/aarch64/multiarch/Makefile (sysdep_routines): Add - memcpy_falkor. - * sysdeps/aarch64/multiarch/ifunc-impl-list.c (MAX_IFUNC): - Bump. - (__libc_ifunc_impl_list): Add __memcpy_falkor. - * sysdeps/aarch64/multiarch/memcpy.c: Likewise. - * sysdeps/aarch64/multiarch/memcpy_falkor.S: New file. - * sysdeps/unix/sysv/linux/aarch64/cpu-features.c (cpu_list): - Add falkor. - * sysdeps/unix/sysv/linux/aarch64/cpu-features.h (IS_FALKOR): - New macro. - -Index: glibc-2.26/manual/tunables.texi -=================================================================== ---- glibc-2.26.orig/manual/tunables.texi -+++ glibc-2.26/manual/tunables.texi -@@ -267,7 +267,7 @@ This tunable is specific to i386 and x86 - @deftp Tunable glibc.tune.cpu - The @code{glibc.tune.cpu=xxx} tunable allows the user to tell @theglibc{} to - assume that the CPU is @code{xxx} where xxx may have one of these values: --@code{generic}, @code{thunderxt88}. -+@code{generic}, @code{falkor}, @code{thunderxt88}. - - This tunable is specific to aarch64. - @end deftp -Index: glibc-2.26/sysdeps/aarch64/multiarch/Makefile -=================================================================== ---- glibc-2.26.orig/sysdeps/aarch64/multiarch/Makefile -+++ glibc-2.26/sysdeps/aarch64/multiarch/Makefile -@@ -1,3 +1,4 @@ - ifeq ($(subdir),string) --sysdep_routines += memcpy_generic memcpy_thunderx -+sysdep_routines += memcpy_generic memcpy_thunderx memcpy_falkor \ -+ memmove_falkor - endif -Index: glibc-2.26/sysdeps/aarch64/multiarch/ifunc-impl-list.c -=================================================================== ---- glibc-2.26.orig/sysdeps/aarch64/multiarch/ifunc-impl-list.c -+++ glibc-2.26/sysdeps/aarch64/multiarch/ifunc-impl-list.c -@@ -25,7 +25,7 @@ - #include - - /* Maximum number of IFUNC implementations. */ --#define MAX_IFUNC 2 -+#define MAX_IFUNC 3 - - size_t - __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, -@@ -40,9 +40,11 @@ __libc_ifunc_impl_list (const char *name - /* Support sysdeps/aarch64/multiarch/memcpy.c and memmove.c. */ - IFUNC_IMPL (i, name, memcpy, - IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_thunderx) -+ IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_falkor) - IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_generic)) - IFUNC_IMPL (i, name, memmove, - IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_thunderx) -+ IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_falkor) - IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_generic)) - - return i; -Index: glibc-2.26/sysdeps/aarch64/multiarch/memcpy.c -=================================================================== ---- glibc-2.26.orig/sysdeps/aarch64/multiarch/memcpy.c -+++ glibc-2.26/sysdeps/aarch64/multiarch/memcpy.c -@@ -30,9 +30,14 @@ extern __typeof (__redirect_memcpy) __li - - extern __typeof (__redirect_memcpy) __memcpy_generic attribute_hidden; - extern __typeof (__redirect_memcpy) __memcpy_thunderx attribute_hidden; -+extern __typeof (__redirect_memcpy) __memcpy_falkor attribute_hidden; - - libc_ifunc (__libc_memcpy, -- IS_THUNDERX (midr) ? __memcpy_thunderx : __memcpy_generic); -+ (IS_THUNDERX (midr) -+ ? __memcpy_thunderx -+ : (IS_FALKOR (midr) -+ ? __memcpy_falkor -+ : __memcpy_generic))); - - # undef memcpy - strong_alias (__libc_memcpy, memcpy); -Index: glibc-2.26/sysdeps/aarch64/multiarch/memcpy_falkor.S -=================================================================== ---- /dev/null -+++ glibc-2.26/sysdeps/aarch64/multiarch/memcpy_falkor.S -@@ -0,0 +1,184 @@ -+/* Optimized memcpy for Qualcomm Falkor processor. -+ 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 -+ -+/* Assumptions: -+ -+ ARMv8-a, AArch64, falkor, unaligned accesses. */ -+ -+#define dstin x0 -+#define src x1 -+#define count x2 -+#define dst x3 -+#define srcend x4 -+#define dstend x5 -+#define A_l x6 -+#define A_lw w6 -+#define A_h x7 -+#define A_hw w7 -+#define tmp1 x14 -+ -+/* Copies are split into 3 main cases: -+ -+ 1. Small copies of up to 32 bytes -+ 2. Medium copies of 33..128 bytes which are fully unrolled -+ 3. Large copies of more than 128 bytes. -+ -+ Large copies align the sourceto a quad word and use an unrolled loop -+ processing 64 bytes per iteration. -+ -+ FALKOR-SPECIFIC DESIGN: -+ -+ The smallest copies (32 bytes or less) focus on optimal pipeline usage, -+ which is why the redundant copies of 0-3 bytes have been replaced with -+ conditionals, since the former would unnecessarily break across multiple -+ issue groups. The medium copy group has been enlarged to 128 bytes since -+ bumping up the small copies up to 32 bytes allows us to do that without -+ cost and also allows us to reduce the size of the prep code before loop64. -+ -+ All copies are done only via two registers r6 and r7. This is to ensure -+ that all loads hit a single hardware prefetcher which can get correctly -+ trained to prefetch a single stream. -+ -+ The non-temporal stores help optimize cache utilization. */ -+ -+#if IS_IN (libc) -+ENTRY_ALIGN (__memcpy_falkor, 6) -+ -+ cmp count, 32 -+ add srcend, src, count -+ add dstend, dstin, count -+ b.ls L(copy32) -+ ldp A_l, A_h, [src] -+ cmp count, 128 -+ stp A_l, A_h, [dstin] -+ b.hi L(copy_long) -+ -+ /* Medium copies: 33..128 bytes. */ -+ sub tmp1, count, 1 -+ ldp A_l, A_h, [src, 16] -+ stp A_l, A_h, [dstin, 16] -+ tbz tmp1, 6, 1f -+ ldp A_l, A_h, [src, 32] -+ stp A_l, A_h, [dstin, 32] -+ ldp A_l, A_h, [src, 48] -+ stp A_l, A_h, [dstin, 48] -+ ldp A_l, A_h, [srcend, -64] -+ stp A_l, A_h, [dstend, -64] -+ ldp A_l, A_h, [srcend, -48] -+ stp A_l, A_h, [dstend, -48] -+1: -+ ldp A_l, A_h, [srcend, -32] -+ stp A_l, A_h, [dstend, -32] -+ ldp A_l, A_h, [srcend, -16] -+ stp A_l, A_h, [dstend, -16] -+ ret -+ -+ .p2align 4 -+ /* Small copies: 0..32 bytes. */ -+L(copy32): -+ /* 16-32 */ -+ cmp count, 16 -+ b.lo 1f -+ ldp A_l, A_h, [src] -+ stp A_l, A_h, [dstin] -+ ldp A_l, A_h, [srcend, -16] -+ stp A_l, A_h, [dstend, -16] -+ ret -+ .p2align 4 -+1: -+ /* 8-15 */ -+ tbz count, 3, 1f -+ ldr A_l, [src] -+ str A_l, [dstin] -+ ldr A_l, [srcend, -8] -+ str A_l, [dstend, -8] -+ ret -+ .p2align 4 -+1: -+ /* 4-7 */ -+ tbz count, 2, 1f -+ ldr A_lw, [src] -+ str A_lw, [dstin] -+ ldr A_lw, [srcend, -4] -+ str A_lw, [dstend, -4] -+ ret -+ .p2align 4 -+1: -+ /* 2-3 */ -+ tbz count, 1, 1f -+ ldrh A_lw, [src] -+ strh A_lw, [dstin] -+ ldrh A_lw, [srcend, -2] -+ strh A_lw, [dstend, -2] -+ ret -+ .p2align 4 -+1: -+ /* 0-1 */ -+ tbz count, 0, 1f -+ ldrb A_lw, [src] -+ strb A_lw, [dstin] -+1: -+ ret -+ -+ /* Align SRC to 16 bytes and copy; that way at least one of the -+ accesses is aligned throughout the copy sequence. -+ -+ The count is off by 0 to 15 bytes, but this is OK because we trim -+ off the last 64 bytes to copy off from the end. Due to this the -+ loop never runs out of bounds. */ -+ .p2align 6 -+L(copy_long): -+ sub count, count, 64 + 16 -+ and tmp1, src, 15 -+ bic src, src, 15 -+ sub dst, dstin, tmp1 -+ add count, count, tmp1 -+ -+L(loop64): -+ ldp A_l, A_h, [src, 16]! -+ stnp A_l, A_h, [dst, 16] -+ ldp A_l, A_h, [src, 16]! -+ subs count, count, 64 -+ stnp A_l, A_h, [dst, 32] -+ ldp A_l, A_h, [src, 16]! -+ stnp A_l, A_h, [dst, 48] -+ ldp A_l, A_h, [src, 16]! -+ stnp A_l, A_h, [dst, 64] -+ add dst, dst, 64 -+ b.hi L(loop64) -+ -+ /* Write the last full set of 64 bytes. The remainder is at most 64 -+ bytes, so it is safe to always copy 64 bytes from the end even if -+ there is just 1 byte left. */ -+L(last64): -+ ldp A_l, A_h, [srcend, -64] -+ stnp A_l, A_h, [dstend, -64] -+ ldp A_l, A_h, [srcend, -48] -+ stnp A_l, A_h, [dstend, -48] -+ ldp A_l, A_h, [srcend, -32] -+ stnp A_l, A_h, [dstend, -32] -+ ldp A_l, A_h, [srcend, -16] -+ stnp A_l, A_h, [dstend, -16] -+ ret -+ -+END (__memcpy_falkor) -+libc_hidden_builtin_def (__memcpy_falkor) -+#endif -Index: glibc-2.26/sysdeps/aarch64/multiarch/memmove.c -=================================================================== ---- glibc-2.26.orig/sysdeps/aarch64/multiarch/memmove.c -+++ glibc-2.26/sysdeps/aarch64/multiarch/memmove.c -@@ -30,9 +30,14 @@ extern __typeof (__redirect_memmove) __l - - extern __typeof (__redirect_memmove) __memmove_generic attribute_hidden; - extern __typeof (__redirect_memmove) __memmove_thunderx attribute_hidden; -+extern __typeof (__redirect_memmove) __memmove_falkor attribute_hidden; - - libc_ifunc (__libc_memmove, -- IS_THUNDERX (midr) ? __memmove_thunderx : __memmove_generic); -+ (IS_THUNDERX (midr) -+ ? __memmove_thunderx -+ : (IS_FALKOR (midr) -+ ? __memmove_falkor -+ : __memmove_generic))); - - # undef memmove - strong_alias (__libc_memmove, memmove); -Index: glibc-2.26/sysdeps/aarch64/multiarch/memmove_falkor.S -=================================================================== ---- /dev/null -+++ glibc-2.26/sysdeps/aarch64/multiarch/memmove_falkor.S -@@ -0,0 +1,232 @@ -+/* 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 -+ -+/* Assumptions: ARMv8-a, AArch64, falkor, unaligned accesses. */ -+ -+#define dstin x0 -+#define src x1 -+#define count x2 -+#define dstlen x3 -+#define dst x3 -+#define srcend x4 -+#define dstend x5 -+#define A_l x6 -+#define A_lw w6 -+#define A_h x7 -+#define A_hw w7 -+#define B_l x8 -+#define B_lw w8 -+#define B_h x9 -+#define C_l x10 -+#define C_h x11 -+#define D_l x12 -+#define D_h x13 -+#define E_l src -+#define E_h count -+#define F_l srcend -+#define F_h dst -+#define tmp1 x14 -+ -+/* Alias with A_l and A_h to train the prefetcher. */ -+#define Q_l x22 -+#define Q_h x23 -+ -+/* RATIONALE: -+ -+ The copy has 4 distinct parts: -+ * Small copies of 16 bytes and under -+ * Medium sized copies of 17-96 bytes -+ * Large copies where the source address is higher than the destination -+ (forward copies) -+ * Large copies where the destination address is higher than the source -+ (copy backward, or move). -+ -+ We use only two registerpairs x6,x7 and x22,x23 for the copies and copy 32 -+ bytes at a time to correctly train the hardware prefetcher for better -+ throughput. */ -+ENTRY_ALIGN (__memmove_falkor, 6) -+ -+ sub tmp1, dstin, src -+ add srcend, src, count -+ add dstend, dstin, count -+ cmp count, 96 -+ ccmp tmp1, count, 2, hi -+ b.lo L(move_long) -+ -+ cmp count, 16 -+ b.ls L(copy16) -+ cmp count, 96 -+ b.hi L(copy_long) -+ -+ /* Medium copies: 17..96 bytes. */ -+ sub tmp1, count, 1 -+ ldp A_l, A_h, [src] -+ tbnz tmp1, 6, L(copy96) -+ ldp D_l, D_h, [srcend, -16] -+ tbz tmp1, 5, 1f -+ ldp B_l, B_h, [src, 16] -+ ldp C_l, C_h, [srcend, -32] -+ stp B_l, B_h, [dstin, 16] -+ stp C_l, C_h, [dstend, -32] -+1: -+ stp A_l, A_h, [dstin] -+ stp D_l, D_h, [dstend, -16] -+ ret -+ -+ .p2align 4 -+ /* Small copies: 0..16 bytes. */ -+L(copy16): -+ cmp count, 8 -+ b.lo 1f -+ ldr A_l, [src] -+ ldr A_h, [srcend, -8] -+ str A_l, [dstin] -+ str A_h, [dstend, -8] -+ ret -+ .p2align 4 -+1: -+ /* 4-7 */ -+ tbz count, 2, 1f -+ ldr A_lw, [src] -+ ldr A_hw, [srcend, -4] -+ str A_lw, [dstin] -+ str A_hw, [dstend, -4] -+ ret -+ .p2align 4 -+1: -+ /* 2-3 */ -+ tbz count, 1, 1f -+ ldrh A_lw, [src] -+ ldrh A_hw, [srcend, -2] -+ strh A_lw, [dstin] -+ strh A_hw, [dstend, -2] -+ ret -+ .p2align 4 -+1: -+ /* 0-1 */ -+ tbz count, 0, 1f -+ ldrb A_lw, [src] -+ strb A_lw, [dstin] -+1: ret -+ -+ .p2align 4 -+ /* Copy 64..96 bytes. Copy 64 bytes from the start and -+ 32 bytes from the end. */ -+L(copy96): -+ ldp B_l, B_h, [src, 16] -+ ldp C_l, C_h, [src, 32] -+ ldp D_l, D_h, [src, 48] -+ ldp E_l, E_h, [srcend, -32] -+ ldp F_l, F_h, [srcend, -16] -+ stp A_l, A_h, [dstin] -+ stp B_l, B_h, [dstin, 16] -+ stp C_l, C_h, [dstin, 32] -+ stp D_l, D_h, [dstin, 48] -+ stp E_l, E_h, [dstend, -32] -+ stp F_l, F_h, [dstend, -16] -+ ret -+ -+ /* Align SRC to 16 byte alignment so that we don't cross cache line -+ boundaries on both loads and stores. There are at least 96 bytes -+ to copy, so copy 16 bytes unaligned and then align. The loop -+ copies 32 bytes per iteration and prefetches one iteration ahead. */ -+ -+ .p2align 4 -+L(copy_long): -+ sub count, count, 64 + 16 /* Test and readjust count. */ -+ mov B_l, Q_l -+ mov B_h, Q_h -+ ldp A_l, A_h, [src] -+ and tmp1, src, 15 -+ bic src, src, 15 -+ sub dst, dstin, tmp1 -+ add count, count, tmp1 /* Count is now 16 too large. */ -+ ldp Q_l, Q_h, [src, 16]! -+ stp A_l, A_h, [dstin] -+ ldp A_l, A_h, [src, 16]! -+ -+L(loop64): -+ subs count, count, 32 -+ stp Q_l, Q_h, [dst, 16] -+ ldp Q_l, Q_h, [src, 16]! -+ stp A_l, A_h, [dst, 32]! -+ ldp A_l, A_h, [src, 16]! -+ b.hi L(loop64) -+ -+ /* Write the last full set of 32 bytes. The remainder is at most 32 -+ bytes, so it is safe to always copy 32 bytes from the end even if -+ there is just 1 byte left. */ -+L(last64): -+ ldp C_l, C_h, [srcend, -32] -+ stp Q_l, Q_h, [dst, 16] -+ ldp Q_l, Q_h, [srcend, -16] -+ stp A_l, A_h, [dst, 32] -+ stp C_l, C_h, [dstend, -32] -+ stp Q_l, Q_h, [dstend, -16] -+ mov Q_l, B_l -+ mov Q_h, B_h -+ ret -+ -+ .p2align 4 -+L(move_long): -+ cbz tmp1, 3f -+ -+ mov B_l, Q_l -+ mov B_h, Q_h -+ -+ /* Align SRCEND to 16 byte alignment so that we don't cross cache line -+ boundaries on both loads and stores. There are at least 96 bytes -+ to copy, so copy 16 bytes unaligned and then align. The loop -+ copies 32 bytes per iteration and prefetches one iteration ahead. */ -+ -+ ldp A_l, A_h, [srcend, -16] -+ and tmp1, srcend, 15 -+ sub srcend, srcend, tmp1 -+ ldp Q_l, Q_h, [srcend, -16]! -+ stp A_l, A_h, [dstend, -16] -+ sub count, count, tmp1 -+ ldp A_l, A_h, [srcend, -16]! -+ sub dstend, dstend, tmp1 -+ sub count, count, 64 -+ -+1: -+ subs count, count, 32 -+ stp Q_l, Q_h, [dstend, -16] -+ ldp Q_l, Q_h, [srcend, -16]! -+ stp A_l, A_h, [dstend, -32]! -+ ldp A_l, A_h, [srcend, -16]! -+ b.hi 1b -+ -+ /* Write the last full set of 32 bytes. The remainder is at most 32 -+ bytes, so it is safe to always copy 32 bytes from the start even if -+ there is just 1 byte left. */ -+2: -+ ldp C_l, C_h, [src, 16] -+ stp Q_l, Q_h, [dstend, -16] -+ ldp Q_l, Q_h, [src] -+ stp A_l, A_h, [dstend, -32] -+ stp C_l, C_h, [dstin, 16] -+ stp Q_l, Q_h, [dstin] -+ mov Q_l, B_l -+ mov Q_h, B_h -+3: ret -+ -+END (__memmove_falkor) -+libc_hidden_builtin_def (__memmove_falkor) -Index: glibc-2.26/sysdeps/unix/sysv/linux/aarch64/cpu-features.c -=================================================================== ---- glibc-2.26.orig/sysdeps/unix/sysv/linux/aarch64/cpu-features.c -+++ glibc-2.26/sysdeps/unix/sysv/linux/aarch64/cpu-features.c -@@ -28,6 +28,7 @@ struct cpu_list - }; - - static struct cpu_list cpu_list[] = { -+ {"falkor", 0x510FC000}, - {"thunderxt88", 0x430F0A10}, - {"generic", 0x0} - }; -Index: glibc-2.26/sysdeps/unix/sysv/linux/aarch64/cpu-features.h -=================================================================== ---- glibc-2.26.orig/sysdeps/unix/sysv/linux/aarch64/cpu-features.h -+++ glibc-2.26/sysdeps/unix/sysv/linux/aarch64/cpu-features.h -@@ -41,6 +41,9 @@ - #define IS_THUNDERX(midr) (MIDR_IMPLEMENTOR(midr) == 'C' \ - && MIDR_PARTNUM(midr) == 0x0a1) - -+#define IS_FALKOR(midr) (MIDR_IMPLEMENTOR(midr) == 'Q' \ -+ && MIDR_PARTNUM(midr) == 0xc00) -+ - struct cpu_features - { - uint64_t midr_el1; diff --git a/fillin-rpath-empty-tokens.patch b/fillin-rpath-empty-tokens.patch deleted file mode 100644 index 54b4530..0000000 --- a/fillin-rpath-empty-tokens.patch +++ /dev/null @@ -1,88 +0,0 @@ -2017-12-30 Aurelien Jarno - Dmitry V. Levin - - [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. - -Index: glibc-2.26/elf/dl-load.c -=================================================================== ---- glibc-2.26.orig/elf/dl-load.c -+++ glibc-2.26/elf/dl-load.c -@@ -435,32 +435,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)) - { -@@ -623,6 +632,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 --git a/fix-locking-in-_IO_cleanup.patch b/fix-locking-in-_IO_cleanup.patch index 72eabae..7c9f9da 100644 --- a/fix-locking-in-_IO_cleanup.patch +++ b/fix-locking-in-_IO_cleanup.patch @@ -1,19 +1,20 @@ -Always do locking when accessing streams +Always do locking when accessing streams (bug 15142) + +During exit, skip files that are currently locked to avoid deadlock. [BZ #15142] - * include/libio.h (_IO_ftrylockfile) [_IO_MTSAVE_IO]: Define. - * libio/genops.c (_IO_list_all_stamp): Delete. All uses removed. + * include/bits/libio.h (_IO_ftrylockfile) [_IO_MTSAVE_IO]: Define. * libio/genops.c (_IO_flush_all_lockp): Make static. Rename argument to skip_locked, callers changed. Skip files that are locked if skip_locked. (_IO_unbuffer_all): Lock files before access, but skip locked files. - * libio/libioP.h (_IO_flush_all_all_lockp): Don't declare. + * libio/libioP.h (_IO_flush_all_lockp): Don't declare. -Index: glibc-2.26/include/libio.h +Index: glibc-2.27/include/bits/libio.h =================================================================== ---- glibc-2.26.orig/include/libio.h -+++ glibc-2.26/include/libio.h +--- glibc-2.27.orig/include/bits/libio.h ++++ glibc-2.27/include/bits/libio.h @@ -33,11 +33,15 @@ libc_hidden_proto (_IO_vfscanf) if (((_fp)->_flags & _IO_USER_LOCK) == 0) _IO_lock_lock (*(_fp)->_lock) # define _IO_funlockfile(_fp) \ @@ -30,48 +31,11 @@ Index: glibc-2.26/include/libio.h # endif #endif /* _IO_MTSAFE_IO */ -Index: glibc-2.26/libio/genops.c +Index: glibc-2.27/libio/genops.c =================================================================== ---- glibc-2.26.orig/libio/genops.c -+++ glibc-2.26/libio/genops.c -@@ -38,10 +38,6 @@ - static _IO_lock_t list_all_lock = _IO_lock_initializer; - #endif - --/* Used to signal modifications to the list of FILE decriptors. */ --static int _IO_list_all_stamp; -- -- - static _IO_FILE *run_fp; - - #ifdef _IO_MTSAFE_IO -@@ -69,16 +65,12 @@ _IO_un_link (struct _IO_FILE_plus *fp) - if (_IO_list_all == NULL) - ; - else if (fp == _IO_list_all) -- { -- _IO_list_all = (struct _IO_FILE_plus *) _IO_list_all->file._chain; -- ++_IO_list_all_stamp; -- } -+ _IO_list_all = (struct _IO_FILE_plus *) _IO_list_all->file._chain; - else - for (f = &_IO_list_all->file._chain; *f; f = &(*f)->_chain) - if (*f == (_IO_FILE *) fp) - { - *f = fp->file._chain; -- ++_IO_list_all_stamp; - break; - } - fp->file._flags &= ~_IO_LINKED; -@@ -106,7 +98,6 @@ _IO_link_in (struct _IO_FILE_plus *fp) - #endif - fp->file._chain = (_IO_FILE *) _IO_list_all; - _IO_list_all = fp; -- ++_IO_list_all_stamp; - #ifdef _IO_MTSAFE_IO - _IO_funlockfile ((_IO_FILE *) fp); - run_fp = NULL; -@@ -789,25 +780,30 @@ _IO_get_column (_IO_FILE *fp) +--- glibc-2.27.orig/libio/genops.c ++++ glibc-2.27/libio/genops.c +@@ -744,8 +744,8 @@ _IO_get_column (_IO_FILE *fp) #endif @@ -82,20 +46,8 @@ Index: glibc-2.26/libio/genops.c { int result = 0; struct _IO_FILE *fp; -- int last_stamp; - - #ifdef _IO_MTSAFE_IO -- __libc_cleanup_region_start (do_lock, flush_cleanup, NULL); -- if (do_lock) -- _IO_lock_lock (list_all_lock); -+ _IO_cleanup_region_start_noarg (flush_cleanup); -+ _IO_lock_lock (list_all_lock); - #endif - -- last_stamp = _IO_list_all_stamp; -- fp = (_IO_FILE *) _IO_list_all; -- while (fp != NULL) -+ for (fp = (_IO_FILE *) _IO_list_all; fp != NULL; fp = fp->_chain) +@@ -758,7 +758,16 @@ _IO_flush_all_lockp (int do_lock) + for (fp = (_IO_FILE *) _IO_list_all; fp != NULL; fp = fp->_chain) { run_fp = fp; - if (do_lock) @@ -112,7 +64,7 @@ Index: glibc-2.26/libio/genops.c _IO_flockfile (fp); if (((fp->_mode <= 0 && fp->_IO_write_ptr > fp->_IO_write_base) -@@ -820,24 +816,13 @@ _IO_flush_all_lockp (int do_lock) +@@ -769,8 +778,7 @@ _IO_flush_all_lockp (int do_lock) && _IO_OVERFLOW (fp, EOF) == EOF) result = EOF; @@ -120,27 +72,9 @@ Index: glibc-2.26/libio/genops.c - _IO_funlockfile (fp); + _IO_funlockfile (fp); run_fp = NULL; -- -- if (last_stamp != _IO_list_all_stamp) -- { -- /* Something was added to the list. Start all over again. */ -- fp = (_IO_FILE *) _IO_list_all; -- last_stamp = _IO_list_all_stamp; -- } -- else -- fp = fp->_chain; } - #ifdef _IO_MTSAFE_IO -- if (do_lock) -- _IO_lock_unlock (list_all_lock); -- __libc_cleanup_region_end (0); -+ _IO_lock_unlock (list_all_lock); -+ _IO_cleanup_region_end (0); - #endif - - return result; -@@ -848,7 +833,7 @@ int +@@ -787,7 +795,7 @@ int _IO_flush_all (void) { /* We want locking. */ @@ -149,50 +83,8 @@ Index: glibc-2.26/libio/genops.c } libc_hidden_def (_IO_flush_all) -@@ -856,16 +841,13 @@ void - _IO_flush_all_linebuffered (void) - { - struct _IO_FILE *fp; -- int last_stamp; +@@ -852,22 +860,18 @@ _IO_unbuffer_all (void) - #ifdef _IO_MTSAFE_IO - _IO_cleanup_region_start_noarg (flush_cleanup); - _IO_lock_lock (list_all_lock); - #endif - -- last_stamp = _IO_list_all_stamp; -- fp = (_IO_FILE *) _IO_list_all; -- while (fp != NULL) -+ for (fp = (_IO_FILE *) _IO_list_all; fp != NULL; fp = fp->_chain) - { - run_fp = fp; - _IO_flockfile (fp); -@@ -875,15 +857,6 @@ _IO_flush_all_linebuffered (void) - - _IO_funlockfile (fp); - run_fp = NULL; -- -- if (last_stamp != _IO_list_all_stamp) -- { -- /* Something was added to the list. Start all over again. */ -- fp = (_IO_FILE *) _IO_list_all; -- last_stamp = _IO_list_all_stamp; -- } -- else -- fp = fp->_chain; - } - - #ifdef _IO_MTSAFE_IO -@@ -919,24 +892,26 @@ static void - _IO_unbuffer_all (void) - { - struct _IO_FILE *fp; -+ -+#ifdef _IO_MTSAFE_IO -+ _IO_cleanup_region_start_noarg (flush_cleanup); -+ _IO_lock_lock (list_all_lock); -+#endif -+ for (fp = (_IO_FILE *) _IO_list_all; fp; fp = fp->_chain) { + run_fp = fp; @@ -222,7 +114,7 @@ Index: glibc-2.26/libio/genops.c if (! dealloc_buffers && !(fp->_flags & _IO_USER_BUF)) { fp->_flags |= _IO_USER_BUF; -@@ -950,17 +925,20 @@ _IO_unbuffer_all (void) +@@ -881,16 +885,14 @@ _IO_unbuffer_all (void) if (fp->_mode > 0) _IO_wsetb (fp, NULL, NULL, 0); @@ -240,15 +132,9 @@ Index: glibc-2.26/libio/genops.c + _IO_funlockfile (fp); + run_fp = NULL; } -+ -+#ifdef _IO_MTSAFE_IO -+ _IO_lock_unlock (list_all_lock); -+ _IO_cleanup_region_end (0); -+#endif - } - -@@ -980,9 +958,9 @@ libc_freeres_fn (buffer_free) + #ifdef _IO_MTSAFE_IO +@@ -916,9 +918,9 @@ libc_freeres_fn (buffer_free) int _IO_cleanup (void) { @@ -261,11 +147,11 @@ Index: glibc-2.26/libio/genops.c /* We currently don't have a reliable mechanism for making sure that C++ static destructors are executed in the correct order. -Index: glibc-2.26/libio/libioP.h +Index: glibc-2.27/libio/libioP.h =================================================================== ---- glibc-2.26.orig/libio/libioP.h -+++ glibc-2.26/libio/libioP.h -@@ -507,7 +507,6 @@ extern int _IO_new_do_write (_IO_FILE *, +--- glibc-2.27.orig/libio/libioP.h ++++ glibc-2.27/libio/libioP.h +@@ -486,7 +486,6 @@ extern int _IO_new_do_write (_IO_FILE *, extern int _IO_old_do_write (_IO_FILE *, const char *, _IO_size_t); extern int _IO_wdo_write (_IO_FILE *, const wchar_t *, _IO_size_t); libc_hidden_proto (_IO_wdo_write) diff --git a/fnmatch-collating-elements.patch b/fnmatch-collating-elements.patch index 03710bd..8d5a52b 100644 --- a/fnmatch-collating-elements.patch +++ b/fnmatch-collating-elements.patch @@ -10,22 +10,22 @@ Fix fnmatch handling of collating elements (BZ #17396, BZ #16976) * posix/tst-fnmatch4.c: New file. * posix/tst-fnmatch5.c: New file. -Index: glibc-2.26/posix/Makefile +Index: glibc-2.27/posix/Makefile =================================================================== ---- glibc-2.26.orig/posix/Makefile -+++ glibc-2.26/posix/Makefile -@@ -91,6 +91,7 @@ tests := test-errno tstgetopt testfnm r +--- glibc-2.27.orig/posix/Makefile ++++ glibc-2.27/posix/Makefile +@@ -92,6 +92,7 @@ tests := test-errno tstgetopt testfnm r bug-getopt5 tst-getopt_long1 bug-regex34 bug-regex35 \ - tst-pathconf tst-getaddrinfo4 tst-rxspencer-no-utf8 \ - tst-fnmatch3 bug-regex36 tst-getaddrinfo5 \ + tst-pathconf tst-rxspencer-no-utf8 \ + tst-fnmatch3 bug-regex36 \ + tst-fnmatch4 tst-fnmatch5 \ tst-posix_spawn-fd tst-posix_spawn-setsid \ tst-posix_fadvise tst-posix_fadvise64 \ - tst-sysconf-empty-chroot tst-glob-tilde -Index: glibc-2.26/posix/fnmatch.c + tst-sysconf-empty-chroot tst-glob_symlinks tst-fexecve \ +Index: glibc-2.27/posix/fnmatch.c =================================================================== ---- glibc-2.26.orig/posix/fnmatch.c -+++ glibc-2.26/posix/fnmatch.c +--- glibc-2.27.orig/posix/fnmatch.c ++++ glibc-2.27/posix/fnmatch.c @@ -53,7 +53,6 @@ we support a correct implementation only in glibc. */ #ifdef _LIBC @@ -34,11 +34,11 @@ Index: glibc-2.26/posix/fnmatch.c # include "../locale/coll-lookup.h" # include -Index: glibc-2.26/posix/fnmatch_loop.c +Index: glibc-2.27/posix/fnmatch_loop.c =================================================================== ---- glibc-2.26.orig/posix/fnmatch_loop.c -+++ glibc-2.26/posix/fnmatch_loop.c -@@ -497,26 +497,12 @@ FCT (const CHAR *pattern, const CHAR *st +--- glibc-2.27.orig/posix/fnmatch_loop.c ++++ glibc-2.27/posix/fnmatch_loop.c +@@ -494,26 +494,12 @@ FCT (const CHAR *pattern, const CHAR *st { int32_t table_size; const int32_t *symb_table; @@ -67,7 +67,7 @@ Index: glibc-2.26/posix/fnmatch_loop.c table_size = _NL_CURRENT_WORD (LC_COLLATE, -@@ -528,71 +514,55 @@ FCT (const CHAR *pattern, const CHAR *st +@@ -525,71 +511,55 @@ FCT (const CHAR *pattern, const CHAR *st _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); @@ -180,7 +180,7 @@ Index: glibc-2.26/posix/fnmatch_loop.c } /* Get the collation sequence value. */ -@@ -600,9 +570,9 @@ FCT (const CHAR *pattern, const CHAR *st +@@ -597,9 +567,9 @@ FCT (const CHAR *pattern, const CHAR *st # if WIDE_CHAR_VERSION cold = wextra[1 + wextra[idx]]; # else @@ -192,7 +192,7 @@ Index: glibc-2.26/posix/fnmatch_loop.c cold = *((int32_t *) &extra[idx]); # endif -@@ -612,10 +582,10 @@ FCT (const CHAR *pattern, const CHAR *st +@@ -609,10 +579,10 @@ FCT (const CHAR *pattern, const CHAR *st { /* No valid character. Match it as a single byte. */ @@ -205,7 +205,7 @@ Index: glibc-2.26/posix/fnmatch_loop.c c = *p++; } else -@@ -623,7 +593,6 @@ FCT (const CHAR *pattern, const CHAR *st +@@ -620,7 +590,6 @@ FCT (const CHAR *pattern, const CHAR *st } } else @@ -213,7 +213,7 @@ Index: glibc-2.26/posix/fnmatch_loop.c #endif { c = FOLD (c); -@@ -715,25 +684,11 @@ FCT (const CHAR *pattern, const CHAR *st +@@ -712,25 +681,11 @@ FCT (const CHAR *pattern, const CHAR *st { int32_t table_size; const int32_t *symb_table; @@ -240,7 +240,7 @@ Index: glibc-2.26/posix/fnmatch_loop.c # endif table_size = -@@ -746,51 +701,44 @@ FCT (const CHAR *pattern, const CHAR *st +@@ -743,51 +698,44 @@ FCT (const CHAR *pattern, const CHAR *st _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); @@ -328,7 +328,7 @@ Index: glibc-2.26/posix/fnmatch_loop.c /* Get the collation sequence value. */ is_seqval = 1; # if WIDE_CHAR_VERSION -@@ -798,19 +746,18 @@ FCT (const CHAR *pattern, const CHAR *st +@@ -795,19 +743,18 @@ FCT (const CHAR *pattern, const CHAR *st # else /* Adjust for the alignment. */ idx += 1 + extra[idx]; @@ -351,10 +351,10 @@ Index: glibc-2.26/posix/fnmatch_loop.c } else { -Index: glibc-2.26/posix/tst-fnmatch4.c +Index: glibc-2.27/posix/tst-fnmatch4.c =================================================================== --- /dev/null -+++ glibc-2.26/posix/tst-fnmatch4.c ++++ glibc-2.27/posix/tst-fnmatch4.c @@ -0,0 +1,51 @@ +/* Test for fnmatch handling of collating elements + Copyright (C) 2015 Free Software Foundation, Inc. @@ -407,10 +407,10 @@ Index: glibc-2.26/posix/tst-fnmatch4.c + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" -Index: glibc-2.26/posix/tst-fnmatch5.c +Index: glibc-2.27/posix/tst-fnmatch5.c =================================================================== --- /dev/null -+++ glibc-2.26/posix/tst-fnmatch5.c ++++ glibc-2.27/posix/tst-fnmatch5.c @@ -0,0 +1,53 @@ +/* Test for fnmatch handling of collating elements + Copyright (C) 2015 Free Software Foundation, Inc. diff --git a/getaddrinfo-errno.patch b/getaddrinfo-errno.patch deleted file mode 100644 index 9b05528..0000000 --- a/getaddrinfo-errno.patch +++ /dev/null @@ -1,649 +0,0 @@ -2017-09-01 Florian Weimer - - [BZ #21915] - [BZ #21922] - * sysdeps/posix/getaddrinfo.c (gethosts): Look at NSS function - result to determine success or failure, not the errno value. - * nss/Makefile (tests): Add tst-nss-files-hosts-erange. - (tst-nss-files-hosts-erange): Link with -ldl. - * nss/tst-nss-files-hosts-erange.c: New file. - * nss/tst-resolv-basic.c (response): Handle nodata.example. - (do_test): Add NO_DATA tests. - * resolv/tst-resolv-basic.c (test_nodata_nxdomain): New function. - (do_test): Call it. - -2017-09-01 Florian Weimer - - [BZ #21922] - * sysdeps/posix/getaddrinfo.c (gaih_inet): Report EAI_NODATA error - coming from gethostbyname2_r. - -2017-09-01 Florian Weimer - - * sysdeps/posix/getaddrinfo.c (gaih_inet): Only use h_errno if - status indicates it is set. - -2017-09-01 Florian Weimer - - * sysdeps/posix/getaddrinfo.c (gaih_inet): Make reporting of NSS - function lookup failures more reliable. - -2017-09-01 Florian Weimer - - * sysdeps/posix/getaddrinfo.c (gethosts): Use h_errno directly. - (getcanonname): Likewise. - (gaih_inet): Likewise. - -2017-09-01 Florian Weimer - - * sysdeps/posix/getaddrinfo.c (gethosts): Use errno directly. - (getcanonname): Likewise. - (gaih_inet): Likewise. - -2017-08-08 Florian Weimer - - * sysdeps/posix/getaddrinfo.c (gaih_inet): Remove unreachable - return statement. - -Index: glibc-2.26/nss/Makefile -=================================================================== ---- glibc-2.26.orig/nss/Makefile -+++ glibc-2.26/nss/Makefile -@@ -58,6 +58,11 @@ tests = test-netdb test-digits-dots ts - tst-nss-test5 - xtests = bug-erange - -+# Tests which need libdl -+ifeq (yes,$(build-shared)) -+tests += tst-nss-files-hosts-erange -+endif -+ - # If we have a thread library then we can test cancellation against - # some routines like getpwuid_r. - ifeq (yes,$(have-thread-library)) -@@ -154,3 +159,5 @@ $(patsubst %,$(objpfx)%.out,$(tests)) : - ifeq (yes,$(have-thread-library)) - $(objpfx)tst-cancel-getpwuid_r: $(shared-thread-library) - endif -+ -+$(objpfx)tst-nss-files-hosts-erange: $(libdl) -Index: glibc-2.26/nss/tst-nss-files-hosts-erange.c -=================================================================== ---- /dev/null -+++ glibc-2.26/nss/tst-nss-files-hosts-erange.c -@@ -0,0 +1,109 @@ -+/* Parse /etc/hosts in multi mode with a trailing long line (bug 21915). -+ 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 -+#include -+#include -+ -+struct support_chroot *chroot_env; -+ -+#define X10 "XXXXXXXXXX" -+#define X100 X10 X10 X10 X10 X10 X10 X10 X10 X10 X10 -+#define X1000 X100 X100 X100 X100 X100 X100 X100 X100 X100 X100 -+ -+static void -+prepare (int argc, char **argv) -+{ -+ chroot_env = support_chroot_create -+ ((struct support_chroot_configuration) -+ { -+ .resolv_conf = "", -+ .hosts = -+ "127.0.0.1 localhost localhost.localdomain\n" -+ "::1 localhost localhost.localdomain\n" -+ "192.0.2.1 example.com\n" -+ "#" X1000 X100 "\n", -+ .host_conf = "multi on\n", -+ }); -+} -+ -+static int -+do_test (void) -+{ -+ support_become_root (); -+ if (!support_can_chroot ()) -+ return EXIT_UNSUPPORTED; -+ -+ __nss_configure_lookup ("hosts", "files"); -+ if (dlopen (LIBNSS_FILES_SO, RTLD_LAZY) == NULL) -+ FAIL_EXIT1 ("could not load " LIBNSS_DNS_SO ": %s", dlerror ()); -+ -+ xchroot (chroot_env->path_chroot); -+ -+ errno = ERANGE; -+ h_errno = NETDB_INTERNAL; -+ check_hostent ("gethostbyname example.com", -+ gethostbyname ("example.com"), -+ "name: example.com\n" -+ "address: 192.0.2.1\n"); -+ errno = ERANGE; -+ h_errno = NETDB_INTERNAL; -+ check_hostent ("gethostbyname2 AF_INET example.com", -+ gethostbyname2 ("example.com", AF_INET), -+ "name: example.com\n" -+ "address: 192.0.2.1\n"); -+ { -+ struct addrinfo hints = -+ { -+ .ai_family = AF_UNSPEC, -+ .ai_socktype = SOCK_STREAM, -+ .ai_protocol = IPPROTO_TCP, -+ }; -+ errno = ERANGE; -+ h_errno = NETDB_INTERNAL; -+ struct addrinfo *ai; -+ int ret = getaddrinfo ("example.com", "80", &hints, &ai); -+ check_addrinfo ("example.com AF_UNSPEC", ai, ret, -+ "address: STREAM/TCP 192.0.2.1 80\n"); -+ if (ret == 0) -+ freeaddrinfo (ai); -+ -+ hints.ai_family = AF_INET; -+ errno = ERANGE; -+ h_errno = NETDB_INTERNAL; -+ ret = getaddrinfo ("example.com", "80", &hints, &ai); -+ check_addrinfo ("example.com AF_INET", ai, ret, -+ "address: STREAM/TCP 192.0.2.1 80\n"); -+ if (ret == 0) -+ freeaddrinfo (ai); -+ } -+ -+ support_chroot_free (chroot_env); -+ return 0; -+} -+ -+#define PREPARE prepare -+#include -Index: glibc-2.26/resolv/tst-resolv-basic.c -=================================================================== ---- glibc-2.26.orig/resolv/tst-resolv-basic.c -+++ glibc-2.26/resolv/tst-resolv-basic.c -@@ -50,7 +50,7 @@ response (const struct resolv_response_c - qname_compare = qname + 2; - else - qname_compare = qname; -- enum {www, alias, nxdomain, long_name} requested_qname; -+ enum {www, alias, nxdomain, long_name, nodata} requested_qname; - if (strcmp (qname_compare, "www.example") == 0) - requested_qname = www; - else if (strcmp (qname_compare, "alias.example") == 0) -@@ -59,6 +59,8 @@ response (const struct resolv_response_c - requested_qname = nxdomain; - else if (strcmp (qname_compare, LONG_NAME) == 0) - requested_qname = long_name; -+ else if (strcmp (qname_compare, "nodata.example") == 0) -+ requested_qname = nodata; - else - { - support_record_failure (); -@@ -87,6 +89,8 @@ response (const struct resolv_response_c - resolv_response_close_record (b); - resolv_response_open_record (b, "www.example", qclass, qtype, 0); - break; -+ case nodata: -+ return; - case nxdomain: - FAIL_EXIT1 ("unreachable"); - } -@@ -267,6 +271,55 @@ test_bug_21295 (void) - } - } - -+/* Run tests which do not expect any data. */ -+static void -+test_nodata_nxdomain (void) -+{ -+ /* Iterate through different address families. */ -+ int families[] = { AF_UNSPEC, AF_INET, AF_INET6, -1 }; -+ for (int i = 0; families[i] >= 0; ++i) -+ /* If do_tcp, prepend "t." to the name to trigger TCP -+ fallback. */ -+ for (int do_tcp = 0; do_tcp < 2; ++do_tcp) -+ /* If do_nxdomain, trigger an NXDOMAIN error (DNS failure), -+ otherwise use a NODATA response (empty but successful -+ answer). */ -+ for (int do_nxdomain = 0; do_nxdomain < 2; ++do_nxdomain) -+ { -+ int family = families[i]; -+ char *name = xasprintf ("%s%s.example", -+ do_tcp ? "t." : "", -+ do_nxdomain ? "nxdomain" : "nodata"); -+ -+ if (family != AF_UNSPEC) -+ { -+ if (do_nxdomain) -+ check_h (name, family, "error: HOST_NOT_FOUND\n"); -+ else -+ check_h (name, family, "error: NO_ADDRESS\n"); -+ } -+ -+ const char *expected; -+ if (do_nxdomain) -+ expected = "error: Name or service not known\n"; -+ else -+ expected = "error: No address associated with hostname\n"; -+ -+ check_ai (name, "80", family, expected); -+ -+ struct addrinfo hints = -+ { -+ .ai_family = family, -+ .ai_flags = AI_V4MAPPED | AI_ALL, -+ }; -+ check_ai_hints (name, "80", hints, expected); -+ hints.ai_flags |= AI_CANONNAME; -+ check_ai_hints (name, "80", hints, expected); -+ -+ free (name); -+ } -+} -+ - static int - do_test (void) - { -@@ -439,29 +492,8 @@ do_test (void) - "address: DGRAM/UDP 2001:db8::4 80\n" - "address: RAW/IP 2001:db8::4 80\n"); - -- check_h ("nxdomain.example", AF_INET, -- "error: HOST_NOT_FOUND\n"); -- check_h ("nxdomain.example", AF_INET6, -- "error: HOST_NOT_FOUND\n"); -- check_ai ("nxdomain.example", "80", AF_UNSPEC, -- "error: Name or service not known\n"); -- check_ai ("nxdomain.example", "80", AF_INET, -- "error: Name or service not known\n"); -- check_ai ("nxdomain.example", "80", AF_INET6, -- "error: Name or service not known\n"); -- -- check_h ("t.nxdomain.example", AF_INET, -- "error: HOST_NOT_FOUND\n"); -- check_h ("t.nxdomain.example", AF_INET6, -- "error: HOST_NOT_FOUND\n"); -- check_ai ("t.nxdomain.example", "80", AF_UNSPEC, -- "error: Name or service not known\n"); -- check_ai ("t.nxdomain.example", "80", AF_INET, -- "error: Name or service not known\n"); -- check_ai ("t.nxdomain.example", "80", AF_INET6, -- "error: Name or service not known\n"); -- - test_bug_21295 (); -+ test_nodata_nxdomain (); - - resolv_test_end (aux); - -Index: glibc-2.26/support/namespace.h -=================================================================== ---- glibc-2.26.orig/support/namespace.h -+++ glibc-2.26/support/namespace.h -@@ -66,7 +66,9 @@ struct support_chroot_configuration - { - /* File contents. The files are not created if the field is - NULL. */ -- const char *resolv_conf; -+ const char *resolv_conf; /* /etc/resolv.conf. */ -+ const char *hosts; /* /etc/hosts. */ -+ const char *host_conf; /* /etc/host.conf. */ - }; - - /* The result of the creation of a chroot. */ -@@ -78,8 +80,11 @@ struct support_chroot - /* Path to the chroot directory. */ - char *path_chroot; - -- /* Path to the /etc/resolv.conf file. */ -- char *path_resolv_conf; -+ /* Paths to files in the chroot. These are absolute and outside of -+ the chroot. */ -+ char *path_resolv_conf; /* /etc/resolv.conf. */ -+ char *path_hosts; /* /etc/hosts. */ -+ char *path_host_conf; /* /etc/host.conf. */ - }; - - /* Create a chroot environment. The returned data should be freed -Index: glibc-2.26/support/support_chroot.c -=================================================================== ---- glibc-2.26.orig/support/support_chroot.c -+++ glibc-2.26/support/support_chroot.c -@@ -24,6 +24,23 @@ - #include - #include - -+/* If CONTENTS is not NULL, write it to the file at DIRECTORY/RELPATH, -+ and store the name in *ABSPATH. If CONTENTS is NULL, store NULL in -+ *ABSPATH. */ -+static void -+write_file (const char *directory, const char *relpath, const char *contents, -+ char **abspath) -+{ -+ if (contents != NULL) -+ { -+ *abspath = xasprintf ("%s/%s", directory, relpath); -+ add_temp_file (*abspath); -+ support_write_file_string (*abspath, contents); -+ } -+ else -+ *abspath = NULL; -+} -+ - struct support_chroot * - support_chroot_create (struct support_chroot_configuration conf) - { -@@ -39,15 +56,10 @@ support_chroot_create (struct support_ch - xmkdir (path_etc, 0777); - add_temp_file (path_etc); - -- if (conf.resolv_conf != NULL) -- { -- /* Create an empty resolv.conf file. */ -- chroot->path_resolv_conf = xasprintf ("%s/resolv.conf", path_etc); -- add_temp_file (chroot->path_resolv_conf); -- support_write_file_string (chroot->path_resolv_conf, conf.resolv_conf); -- } -- else -- chroot->path_resolv_conf = NULL; -+ write_file (path_etc, "resolv.conf", conf.resolv_conf, -+ &chroot->path_resolv_conf); -+ write_file (path_etc, "hosts", conf.hosts, &chroot->path_hosts); -+ write_file (path_etc, "host.conf", conf.host_conf, &chroot->path_host_conf); - - free (path_etc); - -@@ -67,5 +79,7 @@ support_chroot_free (struct support_chro - { - free (chroot->path_chroot); - free (chroot->path_resolv_conf); -+ free (chroot->path_hosts); -+ free (chroot->path_host_conf); - free (chroot); - } -Index: glibc-2.26/sysdeps/posix/getaddrinfo.c -=================================================================== ---- glibc-2.26.orig/sysdeps/posix/getaddrinfo.c -+++ glibc-2.26/sysdeps/posix/getaddrinfo.c -@@ -241,48 +241,43 @@ convert_hostent_to_gaih_addrtuple (const - - #define gethosts(_family, _type) \ - { \ -- int herrno; \ - struct hostent th; \ -- struct hostent *h; \ - char *localcanon = NULL; \ - no_data = 0; \ -- while (1) { \ -- rc = 0; \ -- status = DL_CALL_FCT (fct, (name, _family, &th, \ -- tmpbuf->data, tmpbuf->length, \ -- &rc, &herrno, NULL, &localcanon)); \ -- if (rc != ERANGE || herrno != NETDB_INTERNAL) \ -- break; \ -- if (!scratch_buffer_grow (tmpbuf)) \ -- { \ -- __resolv_context_enable_inet6 (res_ctx, res_enable_inet6); \ -- __resolv_context_put (res_ctx); \ -- result = -EAI_MEMORY; \ -- goto free_and_return; \ -- } \ -- } \ -- if (status == NSS_STATUS_SUCCESS && rc == 0) \ -- h = &th; \ -- else \ -- h = NULL; \ -- if (rc != 0) \ -+ while (1) \ - { \ -- if (herrno == NETDB_INTERNAL) \ -+ status = DL_CALL_FCT (fct, (name, _family, &th, \ -+ tmpbuf->data, tmpbuf->length, \ -+ &errno, &h_errno, NULL, &localcanon)); \ -+ if (status != NSS_STATUS_TRYAGAIN || h_errno != NETDB_INTERNAL \ -+ || errno != ERANGE) \ -+ break; \ -+ if (!scratch_buffer_grow (tmpbuf)) \ -+ { \ -+ __resolv_context_enable_inet6 (res_ctx, res_enable_inet6); \ -+ __resolv_context_put (res_ctx); \ -+ result = -EAI_MEMORY; \ -+ goto free_and_return; \ -+ } \ -+ } \ -+ if (status == NSS_STATUS_NOTFOUND \ -+ || status == NSS_STATUS_TRYAGAIN || status == NSS_STATUS_UNAVAIL) \ -+ { \ -+ if (h_errno == NETDB_INTERNAL) \ - { \ -- __set_h_errno (herrno); \ - __resolv_context_enable_inet6 (res_ctx, res_enable_inet6); \ - __resolv_context_put (res_ctx); \ - result = -EAI_SYSTEM; \ - goto free_and_return; \ - } \ -- if (herrno == TRY_AGAIN) \ -+ if (h_errno == TRY_AGAIN) \ - no_data = EAI_AGAIN; \ - else \ -- no_data = herrno == NO_DATA; \ -+ no_data = h_errno == NO_DATA; \ - } \ -- else if (h != NULL) \ -+ else if (status == NSS_STATUS_SUCCESS) \ - { \ -- if (!convert_hostent_to_gaih_addrtuple (req, _family,h, &addrmem)) \ -+ if (!convert_hostent_to_gaih_addrtuple (req, _family, &th, &addrmem)) \ - { \ - __resolv_context_enable_inet6 (res_ctx, res_enable_inet6); \ - __resolv_context_put (res_ctx); \ -@@ -334,10 +329,8 @@ getcanonname (service_user *nip, struct - if (cfct != NULL) - { - char buf[256]; -- int herrno; -- int rc; - if (DL_CALL_FCT (cfct, (at->name ?: name, buf, sizeof (buf), -- &s, &rc, &herrno)) != NSS_STATUS_SUCCESS) -+ &s, &errno, &h_errno)) != NSS_STATUS_SUCCESS) - /* If the canonical name cannot be determined, use the passed - string. */ - s = (char *) name; -@@ -353,7 +346,6 @@ gaih_inet (const char *name, const struc - const struct gaih_typeproto *tp = gaih_inet_typeproto; - struct gaih_servtuple *st = (struct gaih_servtuple *) &nullserv; - struct gaih_addrtuple *at = NULL; -- int rc; - bool got_ipv6 = false; - const char *canon = NULL; - const char *orig_name = name; -@@ -395,7 +387,8 @@ gaih_inet (const char *name, const struc - st = (struct gaih_servtuple *) - alloca_account (sizeof (struct gaih_servtuple), alloca_used); - -- if ((rc = gaih_inet_serv (service->name, tp, req, st, tmpbuf))) -+ int rc = gaih_inet_serv (service->name, tp, req, st, tmpbuf); -+ if (__glibc_unlikely (rc != 0)) - return rc; - } - else -@@ -420,13 +413,9 @@ gaih_inet (const char *name, const struc - alloca_account (sizeof (struct gaih_servtuple), - alloca_used); - -- if ((rc = gaih_inet_serv (service->name, -- tp, req, newp, tmpbuf))) -- { -- if (rc) -- continue; -- return rc; -- } -+ if (gaih_inet_serv (service->name, -+ tp, req, newp, tmpbuf) != 0) -+ continue; - - *pst = newp; - pst = &(newp->next); -@@ -499,7 +488,7 @@ gaih_inet (const char *name, const struc - idn_flags |= IDNA_USE_STD3_ASCII_RULES; - - char *p = NULL; -- rc = __idna_to_ascii_lz (name, &p, idn_flags); -+ int rc = __idna_to_ascii_lz (name, &p, idn_flags); - if (rc != IDNA_SUCCESS) - { - /* No need to jump to free_and_return here. */ -@@ -600,14 +589,13 @@ gaih_inet (const char *name, const struc - int rc; - struct hostent th; - struct hostent *h; -- int herrno; - - while (1) - { - rc = __gethostbyname2_r (name, AF_INET, &th, - tmpbuf->data, tmpbuf->length, -- &h, &herrno); -- if (rc != ERANGE || herrno != NETDB_INTERNAL) -+ &h, &h_errno); -+ if (rc != ERANGE || h_errno != NETDB_INTERNAL) - break; - if (!scratch_buffer_grow (tmpbuf)) - { -@@ -629,15 +617,20 @@ gaih_inet (const char *name, const struc - } - *pat = addrmem; - } -+ else -+ { -+ if (h_errno == NO_DATA) -+ result = -EAI_NODATA; -+ else -+ result = -EAI_NONAME; -+ goto free_and_return; -+ } - } - else - { -- if (herrno == NETDB_INTERNAL) -- { -- __set_h_errno (herrno); -- result = -EAI_SYSTEM; -- } -- else if (herrno == TRY_AGAIN) -+ if (h_errno == NETDB_INTERNAL) -+ result = -EAI_SYSTEM; -+ else if (h_errno == TRY_AGAIN) - result = -EAI_AGAIN; - else - /* We made requests but they turned out no data. -@@ -660,8 +653,7 @@ gaih_inet (const char *name, const struc - { - /* Try to use nscd. */ - struct nscd_ai_result *air = NULL; -- int herrno; -- int err = __nscd_getai (name, &air, &herrno); -+ int err = __nscd_getai (name, &air, &h_errno); - if (air != NULL) - { - /* Transform into gaih_addrtuple list. */ -@@ -752,9 +744,9 @@ gaih_inet (const char *name, const struc - goto free_and_return; - else if (__nss_not_use_nscd_hosts == 0) - { -- if (herrno == NETDB_INTERNAL && errno == ENOMEM) -+ if (h_errno == NETDB_INTERNAL && errno == ENOMEM) - result = -EAI_MEMORY; -- else if (herrno == TRY_AGAIN) -+ else if (h_errno == TRY_AGAIN) - result = -EAI_AGAIN; - else - result = -EAI_SYSTEM; -@@ -793,24 +785,21 @@ gaih_inet (const char *name, const struc - - if (fct4 != NULL) - { -- int herrno; -- - while (1) - { -- rc = 0; - status = DL_CALL_FCT (fct4, (name, pat, - tmpbuf->data, tmpbuf->length, -- &rc, &herrno, -+ &errno, &h_errno, - NULL)); - if (status == NSS_STATUS_SUCCESS) - break; - if (status != NSS_STATUS_TRYAGAIN -- || rc != ERANGE || herrno != NETDB_INTERNAL) -+ || errno != ERANGE || h_errno != NETDB_INTERNAL) - { -- if (herrno == TRY_AGAIN) -+ if (h_errno == TRY_AGAIN) - no_data = EAI_AGAIN; - else -- no_data = herrno == NO_DATA; -+ no_data = h_errno == NO_DATA; - break; - } - -@@ -940,13 +929,17 @@ gaih_inet (const char *name, const struc - } - else - { -+ /* Could not locate any of the lookup functions. -+ The NSS lookup code does not consistently set -+ errno, so we need to supply our own error -+ code here. The root cause could either be a -+ resource allocation failure, or a missing -+ service function in the DSO (so it should not -+ be listed in /etc/nsswitch.conf). Assume the -+ former, and return EBUSY. */ - status = NSS_STATUS_UNAVAIL; -- /* Could not load any of the lookup functions. Indicate -- an internal error if the failure was due to a system -- error other than the file not being found. We use the -- errno from the last failed callback. */ -- if (errno != 0 && errno != ENOENT) -- __set_h_errno (NETDB_INTERNAL); -+ __set_h_errno (NETDB_INTERNAL); -+ __set_errno (EBUSY); - } - } - -@@ -962,7 +955,10 @@ gaih_inet (const char *name, const struc - __resolv_context_enable_inet6 (res_ctx, res_enable_inet6); - __resolv_context_put (res_ctx); - -- if (h_errno == NETDB_INTERNAL) -+ /* If we have a failure which sets errno, report it using -+ EAI_SYSTEM. */ -+ if ((status == NSS_STATUS_TRYAGAIN || status == NSS_STATUS_UNAVAIL) -+ && h_errno == NETDB_INTERNAL) - { - result = -EAI_SYSTEM; - goto free_and_return; diff --git a/getcwd-absolute.patch b/getcwd-absolute.patch deleted file mode 100644 index 3c1fe2f..0000000 --- a/getcwd-absolute.patch +++ /dev/null @@ -1,34 +0,0 @@ -2018-01-12 Dmitry V. Levin - - [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. - -Index: glibc-2.26/sysdeps/unix/sysv/linux/getcwd.c -=================================================================== ---- glibc-2.26.orig/sysdeps/unix/sysv/linux/getcwd.c -+++ glibc-2.26/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) diff --git a/glibc-2.14-crypt.diff b/glibc-2.14-crypt.diff index 5afebd2..32c2a69 100644 --- a/glibc-2.14-crypt.diff +++ b/glibc-2.14-crypt.diff @@ -1,7 +1,7 @@ -Index: glibc-2.25/crypt/Makefile +Index: glibc-2.27/crypt/Makefile =================================================================== ---- glibc-2.25.orig/crypt/Makefile -+++ glibc-2.25/crypt/Makefile +--- glibc-2.27.orig/crypt/Makefile ++++ glibc-2.27/crypt/Makefile @@ -23,14 +23,18 @@ subdir := crypt include ../Makeconfig @@ -23,10 +23,10 @@ Index: glibc-2.25/crypt/Makefile ifeq ($(crypt-in-libc),yes) routines += $(libcrypt-routines) -Index: glibc-2.25/crypt/Versions +Index: glibc-2.27/crypt/Versions =================================================================== ---- glibc-2.25.orig/crypt/Versions -+++ glibc-2.25/crypt/Versions +--- glibc-2.27.orig/crypt/Versions ++++ glibc-2.27/crypt/Versions @@ -3,3 +3,8 @@ libcrypt { crypt; crypt_r; encrypt; encrypt_r; fcrypt; setkey; setkey_r; } @@ -36,10 +36,10 @@ Index: glibc-2.25/crypt/Versions + crypt_gensalt; crypt_gensalt_rn; crypt_gensalt_ra; + } +} -Index: glibc-2.25/crypt/crypt-entry.c +Index: glibc-2.27/crypt/crypt-entry.c =================================================================== ---- glibc-2.25.orig/crypt/crypt-entry.c -+++ glibc-2.25/crypt/crypt-entry.c +--- glibc-2.27.orig/crypt/crypt-entry.c ++++ glibc-2.27/crypt/crypt-entry.c @@ -71,7 +71,7 @@ extern struct crypt_data _ufc_foobar; */ @@ -62,10 +62,10 @@ Index: glibc-2.25/crypt/crypt-entry.c } #endif +#endif -Index: glibc-2.25/crypt/crypt-private.h +Index: glibc-2.27/crypt/crypt-private.h =================================================================== ---- glibc-2.25.orig/crypt/crypt-private.h -+++ glibc-2.25/crypt/crypt-private.h +--- glibc-2.27.orig/crypt/crypt-private.h ++++ glibc-2.27/crypt/crypt-private.h @@ -65,7 +65,7 @@ extern void __encrypt_r (char * __restri struct crypt_data * __restrict __data); @@ -75,11 +75,11 @@ Index: glibc-2.25/crypt/crypt-private.h struct crypt_data * __restrict __data); extern char *fcrypt (const char *key, const char *salt); -Index: glibc-2.25/shlib-versions +Index: glibc-2.27/shlib-versions =================================================================== ---- glibc-2.25.orig/shlib-versions -+++ glibc-2.25/shlib-versions -@@ -58,6 +58,7 @@ libnsl=1 +--- glibc-2.27.orig/shlib-versions ++++ glibc-2.27/shlib-versions +@@ -59,6 +59,7 @@ libnsl=1 # This defines the shared library version numbers we will install. libcrypt=1 @@ -87,10 +87,10 @@ Index: glibc-2.25/shlib-versions # The gross patch for programs assuming broken locale implementations. libBrokenLocale=1 -Index: glibc-2.25/sysdeps/unix/sysv/linux/libowcrypt.abilist +Index: glibc-2.27/sysdeps/unix/sysv/linux/libowcrypt.abilist =================================================================== --- /dev/null -+++ glibc-2.25/sysdeps/unix/sysv/linux/libowcrypt.abilist ++++ glibc-2.27/sysdeps/unix/sysv/linux/libowcrypt.abilist @@ -0,0 +1,4 @@ +OW_CRYPT_1.0 OW_CRYPT_1.0 A +OW_CRYPT_1.0 crypt_gensalt F diff --git a/glibc-2.26.tar.xz b/glibc-2.26.tar.xz deleted file mode 100644 index 3a2b030..0000000 --- a/glibc-2.26.tar.xz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e54e0a934cd2bc94429be79da5e9385898d2306b9eaf3c92d5a77af96190f6bd -size 14682748 diff --git a/glibc-2.26.tar.xz.sig b/glibc-2.26.tar.xz.sig deleted file mode 100644 index 21adc1c..0000000 --- a/glibc-2.26.tar.xz.sig +++ /dev/null @@ -1,10 +0,0 @@ ------BEGIN PGP SIGNATURE----- - -iQEcBAABAgAGBQJZgduLAAoJEHnEPfvxzyGHDesH/itf17ZUWSWNIRp2cC0RK1et -jtR7ufFMpSHfMFJQXkli162s+iFMAxuOus52rma/h3PP8BXVbEKB7M3N0dvqPbmC -AIC6YtAYU/I4M3V+6T1pi4ras19i2VgNY+iag0xw5o0ah4yZmZwB5eFR2xIz10ZD -SGffJyCD/8EFwn/SPx38JS55ENwGj5PT1m2TsEnlLeHg7sCH7ksb5Pqq/ZEwIw0v -E56a4hSliDUhurc0gUQmFxm/FhFSdTzns0vShfgou4D2tNSYaUjrf/17ebj0ehUF -XkNH5jvwHoxiKzEVnD7dS9NLbvOPAG4AlFnWejgqvX0JB/M5TknOcmJYpzZYiGE= -=XObH ------END PGP SIGNATURE----- diff --git a/glibc-2.27.tar.xz b/glibc-2.27.tar.xz new file mode 100644 index 0000000..7c85ec2 --- /dev/null +++ b/glibc-2.27.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5172de54318ec0b7f2735e5a91d908afe1c9ca291fec16b5374d9faadfc1fc72 +size 15395316 diff --git a/glibc-2.27.tar.xz.sig b/glibc-2.27.tar.xz.sig new file mode 100644 index 0000000..75b24ac --- /dev/null +++ b/glibc-2.27.tar.xz.sig @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIcBAABAgAGBQJac3pRAAoJEBZ5K06iU0D42ScP/1a2BmqiRw3vt2vtjRpZAeE+ +UcJ44FFbgRfybe2e0hSI9/Yl3aMRp3ntdUyrZrUKdDiiaBvWt6Ye7UWDHe0iraxM +1PvQsVu1HmfXGgsAyMlk9XtfqvDqBXcFWE99HbTbuybT+W+JXP+751ioN73MTgp5 +ZECrYy3o5FUPHHb2MBA1zqY4sryWR+27vY+CP2BMSvLNIUpYKVe2xOMvayi2Asxr +rTB6dlpcxwZaoErkqeOl4vgNO744WFMRj0RaMVN6/HkGfvuf1gzqcLjlsJ5AFpA/ +GliE9rJn7ogpV0cXgagcjt/+CuL/htvFOw9qTzkDrT41t0n3DBQ0HXwh60oCTN8I +3gbuudLN51+cDWk17TcNh6PDyuYFEiZbIAmU2aRha+lsGGnQaoI8fS/thHfzzGBd +P5jSvpHPfL3lp8PBwjgiuXElEi/hJlGYfjDfJZ5ta4p08362LcfHe1xNCSP49x5a +V/ZV+Ggpsf6MiRmwQBNykA55s3akYgIOtBwDs0polookDcKJ/BzczNnWYNqX0Szv +k4pvIEWsMLMsX9j3qnKbmmtlrcFTIwaQzQ75e3D1OFL3JCup7byoDf1icfRKWr8D +3Y0FWExqQ3NYpR7F7hPsbU55DGqpMlLnVMTZ0wlEn9s1TyO1vWiba1BuVMtCICDJ +fyTjM1MZXfBiFDcP1D4P +=SzqE +-----END PGP SIGNATURE----- diff --git a/glibc-2.3.2.no_archive.diff b/glibc-2.3.2.no_archive.diff index ed68c3b..64717a3 100644 --- a/glibc-2.3.2.no_archive.diff +++ b/glibc-2.3.2.no_archive.diff @@ -2,11 +2,11 @@ Wed Jun 4 14:29:07 CEST 2003 - kukuk@suse.de - Make --no-archive default for localedef -Index: glibc-2.18.90/locale/programs/localedef.c +Index: glibc-2.27/locale/programs/localedef.c =================================================================== ---- glibc-2.18.90.orig/locale/programs/localedef.c -+++ glibc-2.18.90/locale/programs/localedef.c -@@ -81,7 +81,7 @@ const char *alias_file; +--- glibc-2.27.orig/locale/programs/localedef.c ++++ glibc-2.27/locale/programs/localedef.c +@@ -71,7 +71,7 @@ const char *alias_file; static struct localedef_t *locales; /* If true don't add locale data to archive. */ @@ -15,24 +15,24 @@ Index: glibc-2.18.90/locale/programs/localedef.c /* If true add named locales to archive. */ static bool add_to_archive; -@@ -112,6 +112,7 @@ void (*argp_program_version_hook) (FILE +@@ -101,6 +101,7 @@ void (*argp_program_version_hook) (FILE #define OPT_REPLACE 307 #define OPT_DELETE_FROM_ARCHIVE 308 #define OPT_LIST_ARCHIVE 309 +#define OPT_ARCHIVE 310 #define OPT_LITTLE_ENDIAN 400 #define OPT_BIG_ENDIAN 401 + #define OPT_NO_WARN 402 +@@ -133,6 +134,8 @@ static const struct argp_option options[ + "supported warnings are: ascii, intcurrsym") }, -@@ -136,6 +137,8 @@ static const struct argp_option options[ - N_("Suppress warnings and information messages") }, - { "verbose", 'v', NULL, 0, N_("Print more messages") }, { NULL, 0, NULL, 0, N_("Archive control:") }, + { "archive", OPT_ARCHIVE, NULL, 0, + N_("Add new data to archive") }, { "no-archive", OPT_NO_ARCHIVE, NULL, 0, N_("Don't add new data to archive") }, { "add-to-archive", OPT_ADD_TO_ARCHIVE, NULL, 0, -@@ -317,6 +320,9 @@ parse_opt (int key, char *arg, struct ar +@@ -360,6 +363,9 @@ parse_opt (int key, char *arg, struct ar case OPT_PREFIX: output_prefix = arg; break; diff --git a/glibc-2.3.3-nscd-db-path.diff b/glibc-2.3.3-nscd-db-path.diff index 14242a5..64896e8 100644 --- a/glibc-2.3.3-nscd-db-path.diff +++ b/glibc-2.3.3-nscd-db-path.diff @@ -1,8 +1,8 @@ -Index: glibc-2.17.90/nscd/nscd.h +Index: glibc-2.27/nscd/nscd.h =================================================================== ---- glibc-2.17.90.orig/nscd/nscd.h -+++ glibc-2.17.90/nscd/nscd.h -@@ -112,11 +112,11 @@ struct database_dyn +--- glibc-2.27.orig/nscd/nscd.h ++++ glibc-2.27/nscd/nscd.h +@@ -161,11 +161,11 @@ struct database_dyn /* Paths of the file for the persistent storage. */ diff --git a/glibc-2.3.90-langpackdir.diff b/glibc-2.3.90-langpackdir.diff index e2da5c0..aa7e45e 100644 --- a/glibc-2.3.90-langpackdir.diff +++ b/glibc-2.3.90-langpackdir.diff @@ -1,8 +1,8 @@ -Index: glibc-2.24/intl/loadmsgcat.c +Index: glibc-2.27/intl/loadmsgcat.c =================================================================== ---- glibc-2.24.orig/intl/loadmsgcat.c -+++ glibc-2.24/intl/loadmsgcat.c -@@ -829,8 +829,47 @@ _nl_load_domain (struct loaded_l10nfile +--- glibc-2.27.orig/intl/loadmsgcat.c ++++ glibc-2.27/intl/loadmsgcat.c +@@ -796,8 +796,47 @@ _nl_load_domain (struct loaded_l10nfile if (domain_file->filename == NULL) goto out; diff --git a/glibc-2.4-china.diff b/glibc-2.4-china.diff index e6361d3..d18de37 100644 --- a/glibc-2.4-china.diff +++ b/glibc-2.4-china.diff @@ -1,17 +1,17 @@ -Index: glibc-2.17.90/localedata/locales/zh_TW +Index: glibc-2.27/localedata/locales/zh_TW =================================================================== ---- glibc-2.17.90.orig/localedata/locales/zh_TW -+++ glibc-2.17.90/localedata/locales/zh_TW -@@ -8,7 +8,7 @@ +--- glibc-2.27.orig/localedata/locales/zh_TW ++++ glibc-2.27/localedata/locales/zh_TW +@@ -8,7 +8,7 @@ escape_char / % exempt you from the conditions of the license if your use would % otherwise be governed by that license. -% Chinese language locale for Taiwan R.O.C. +% Chinese language locale for Taiwan - % charmap: BIG5-CP950 % % Original Author: -@@ -24,7 +24,7 @@ escape_char / + % Ming-Che Chuang +@@ -23,7 +23,7 @@ escape_char / % Reference: http://wwwold.dkuug.dk/JTC1/SC22/WG20/docs/n690.pdf LC_IDENTIFICATION diff --git a/glibc-2.4.90-no_NO.diff b/glibc-2.4.90-no_NO.diff index 64884ea..a71af44 100644 --- a/glibc-2.4.90-no_NO.diff +++ b/glibc-2.4.90-no_NO.diff @@ -1,8 +1,8 @@ -Index: glibc-2.18.90/intl/locale.alias +Index: glibc-2.27/intl/locale.alias =================================================================== ---- glibc-2.18.90.orig/intl/locale.alias -+++ glibc-2.18.90/intl/locale.alias -@@ -56,8 +56,6 @@ korean ko_KR.eucKR +--- glibc-2.27.orig/intl/locale.alias ++++ glibc-2.27/intl/locale.alias +@@ -65,8 +65,6 @@ korean ko_KR.eucKR korean.euc ko_KR.eucKR ko_KR ko_KR.eucKR lithuanian lt_LT.ISO-8859-13 @@ -11,11 +11,11 @@ Index: glibc-2.18.90/intl/locale.alias norwegian nb_NO.ISO-8859-1 nynorsk nn_NO.ISO-8859-1 polish pl_PL.ISO-8859-2 -Index: glibc-2.18.90/localedata/SUPPORTED +Index: glibc-2.27/localedata/SUPPORTED =================================================================== ---- glibc-2.18.90.orig/localedata/SUPPORTED -+++ glibc-2.18.90/localedata/SUPPORTED -@@ -331,6 +331,8 @@ nl_NL/ISO-8859-1 \ +--- glibc-2.27.orig/localedata/SUPPORTED ++++ glibc-2.27/localedata/SUPPORTED +@@ -355,6 +355,8 @@ nl_NL/ISO-8859-1 \ nl_NL@euro/ISO-8859-15 \ nn_NO.UTF-8/UTF-8 \ nn_NO/ISO-8859-1 \ @@ -24,10 +24,10 @@ Index: glibc-2.18.90/localedata/SUPPORTED nr_ZA/UTF-8 \ nso_ZA/UTF-8 \ oc_FR.UTF-8/UTF-8 \ -Index: glibc-2.18.90/localedata/locales/no_NO +Index: glibc-2.27/localedata/locales/no_NO =================================================================== --- /dev/null -+++ glibc-2.18.90/localedata/locales/no_NO ++++ glibc-2.27/localedata/locales/no_NO @@ -0,0 +1,69 @@ +escape_char / +comment_char % diff --git a/glibc-bindresvport-blacklist.diff b/glibc-bindresvport-blacklist.diff index 3fb3a4f..93d7252 100644 --- a/glibc-bindresvport-blacklist.diff +++ b/glibc-bindresvport-blacklist.diff @@ -1,7 +1,7 @@ -Index: glibc-2.17.90/sunrpc/bindrsvprt.c +Index: glibc-2.27/sunrpc/bindrsvprt.c =================================================================== ---- glibc-2.17.90.orig/sunrpc/bindrsvprt.c -+++ glibc-2.17.90/sunrpc/bindrsvprt.c +--- glibc-2.27.orig/sunrpc/bindrsvprt.c ++++ glibc-2.27/sunrpc/bindrsvprt.c @@ -29,6 +29,9 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ diff --git a/glibc-c-utf8-locale.patch b/glibc-c-utf8-locale.patch index 13f6318..d9924ba 100644 --- a/glibc-c-utf8-locale.patch +++ b/glibc-c-utf8-locale.patch @@ -9,10 +9,10 @@ Subject: [PATCH] Add a C.UTF-8 locale 2 files changed, 239 insertions(+) create mode 100644 localedata/locales/C -diff --git a/localedata/SUPPORTED b/localedata/SUPPORTED -index 8ca023e..2a78391 100644 ---- a/localedata/SUPPORTED -+++ b/localedata/SUPPORTED +Index: glibc-2.27/localedata/SUPPORTED +=================================================================== +--- glibc-2.27.orig/localedata/SUPPORTED ++++ glibc-2.27/localedata/SUPPORTED @@ -1,6 +1,7 @@ # This file names the currently supported and somewhat tested locales. # If you have any additions please file a glibc bug report. @@ -21,11 +21,10 @@ index 8ca023e..2a78391 100644 aa_DJ.UTF-8/UTF-8 \ aa_DJ/ISO-8859-1 \ aa_ER/UTF-8 \ -diff --git a/localedata/locales/C b/localedata/locales/C -new file mode 100644 -index 0000000..fdf460e +Index: glibc-2.27/localedata/locales/C +=================================================================== --- /dev/null -+++ b/localedata/locales/C ++++ glibc-2.27/localedata/locales/C @@ -0,0 +1,238 @@ +escape_char / +comment_char % diff --git a/glibc-disable-gettext-for-c-utf8.patch b/glibc-disable-gettext-for-c-utf8.patch index 466df5b..aab0f8a 100644 --- a/glibc-disable-gettext-for-c-utf8.patch +++ b/glibc-disable-gettext-for-c-utf8.patch @@ -1,8 +1,8 @@ -Index: glibc-2.23/intl/dcigettext.c +Index: glibc-2.27/intl/dcigettext.c =================================================================== ---- glibc-2.23.orig/intl/dcigettext.c -+++ glibc-2.23/intl/dcigettext.c -@@ -714,6 +714,7 @@ DCIGETTEXT (const char *domainname, cons +--- glibc-2.27.orig/intl/dcigettext.c ++++ glibc-2.27/intl/dcigettext.c +@@ -695,6 +695,7 @@ DCIGETTEXT (const char *domainname, cons /* If the current locale value is C (or POSIX) we don't load a domain. Return the MSGID. */ if (strcmp (single_locale, "C") == 0 diff --git a/glibc-fix-double-loopback.diff b/glibc-fix-double-loopback.diff index 8025e0c..7468112 100644 --- a/glibc-fix-double-loopback.diff +++ b/glibc-fix-double-loopback.diff @@ -7,11 +7,11 @@ Remapping ::1 to 127.0.0.1 is bogus when /etc/hosts is correct. bnc #684534, #606980 http://sources.redhat.com/bugzilla/show_bug.cgi?id=4980 -Index: glibc-2.17.90/nss/nss_files/files-hosts.c +Index: glibc-2.27/nss/nss_files/files-hosts.c =================================================================== ---- glibc-2.17.90.orig/nss/nss_files/files-hosts.c -+++ glibc-2.17.90/nss/nss_files/files-hosts.c -@@ -68,11 +68,6 @@ LINE_PARSER +--- glibc-2.27.orig/nss/nss_files/files-hosts.c ++++ glibc-2.27/nss/nss_files/files-hosts.c +@@ -70,11 +70,6 @@ LINE_PARSER { if (IN6_IS_ADDR_V4MAPPED (entdata->host_addr)) memcpy (entdata->host_addr, entdata->host_addr + 12, INADDRSZ); diff --git a/glibc-nodate.patch b/glibc-nodate.patch deleted file mode 100644 index d54f631..0000000 --- a/glibc-nodate.patch +++ /dev/null @@ -1,47 +0,0 @@ -Index: glibc-2.21/nscd/nscd_stat.c -=================================================================== ---- glibc-2.21.orig/nscd/nscd_stat.c -+++ glibc-2.21/nscd/nscd_stat.c -@@ -36,8 +36,13 @@ - #endif /* HAVE_SELINUX */ - - --/* We use this to make sure the receiver is the same. */ -+/* We use this to make sure the receiver is the same. Capture mtime -+ of this file if possible. */ -+#ifdef __TIMESTAMP__ -+static const char compilation[21]; -+#else - static const char compilation[21] = __DATE__ " " __TIME__; -+#endif - - /* Statistic data for one database. */ - struct dbstat -@@ -96,7 +101,12 @@ send_stats (int fd, struct database_dyn - - memset (&data, 0, sizeof (data)); - -+#ifdef __TIMESTAMP__ -+ /* Skip day of the week. */ -+ memcpy (data.version, __TIMESTAMP__ + 4, sizeof (compilation)); -+#else - memcpy (data.version, compilation, sizeof (compilation)); -+#endif - data.debug_level = debug_level; - data.runtime = time (NULL) - start_time; - data.client_queued = client_queued; -@@ -196,7 +206,13 @@ receive_print_stats (void) - - /* Read as much data as we expect. */ - if (TEMP_FAILURE_RETRY (read (fd, &data, sizeof (data))) != sizeof (data) -- || (memcmp (data.version, compilation, sizeof (compilation)) != 0 -+ || ( -+#ifdef __TIMESTAMP__ -+ /* Skip day of the week. */ -+ memcmp (data.version, __TIMESTAMP__ + 4, sizeof (compilation)) != 0 -+#else -+ memcmp (data.version, compilation, sizeof (compilation)) != 0 -+#endif - /* Yes, this is an assignment! */ - && (errno = EINVAL))) - { diff --git a/glibc-nscd.conf.patch b/glibc-nscd.conf.patch index 2b33892..162def6 100644 --- a/glibc-nscd.conf.patch +++ b/glibc-nscd.conf.patch @@ -1,7 +1,7 @@ -Index: glibc-2.17.90/nscd/nscd.conf +Index: glibc-2.27/nscd/nscd.conf =================================================================== ---- glibc-2.17.90.orig/nscd/nscd.conf -+++ glibc-2.17.90/nscd/nscd.conf +--- glibc-2.27.orig/nscd/nscd.conf ++++ glibc-2.27/nscd/nscd.conf @@ -61,11 +61,11 @@ auto-propagate group yes diff --git a/glibc-resolv-mdnshint.diff b/glibc-resolv-mdnshint.diff index 81c11d0..cbec05b 100644 --- a/glibc-resolv-mdnshint.diff +++ b/glibc-resolv-mdnshint.diff @@ -1,8 +1,8 @@ -Index: glibc-2.20/resolv/res_hconf.c +Index: glibc-2.27/resolv/res_hconf.c =================================================================== ---- glibc-2.20.orig/resolv/res_hconf.c -+++ glibc-2.20/resolv/res_hconf.c -@@ -240,9 +240,12 @@ parse_line (const char *fname, int line_ +--- glibc-2.27.orig/resolv/res_hconf.c ++++ glibc-2.27/resolv/res_hconf.c +@@ -215,9 +215,12 @@ parse_line (const char *fname, int line_ if (c == NULL) { char *buf; diff --git a/glibc-version.diff b/glibc-version.diff index 8381c25..b98f13d 100644 --- a/glibc-version.diff +++ b/glibc-version.diff @@ -1,18 +1,18 @@ -Index: glibc-2.17.90/csu/version.c +Index: glibc-2.27/csu/version.c =================================================================== ---- glibc-2.17.90.orig/csu/version.c -+++ glibc-2.17.90/csu/version.c +--- glibc-2.27.orig/csu/version.c ++++ glibc-2.27/csu/version.c @@ -24,11 +24,12 @@ static const char __libc_release[] = REL static const char __libc_version[] = VERSION; static const char banner[] = --"GNU C Library "PKGVERSION RELEASE" release version "VERSION", by Roland McGrath et al.\n\ -+"GNU C Library "PKGVERSION RELEASE" release version "VERSION" (git "GITID"), by Roland McGrath et al.\n\ - Copyright (C) 2017 Free Software Foundation, Inc.\n\ +-"GNU C Library "PKGVERSION RELEASE" release version "VERSION".\n\ ++"GNU C Library "PKGVERSION RELEASE" release version "VERSION" (git "GITID").\n\ + Copyright (C) 2018 Free Software Foundation, Inc.\n\ This is free software; see the source for copying conditions.\n\ There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n\ PARTICULAR PURPOSE.\n\ +Configured for "CONFHOST".\n\ Compiled by GNU CC version "__VERSION__".\n" - #include "version-info.h" #ifdef LIBC_ABIS_STRING + LIBC_ABIS_STRING diff --git a/glibc.changes b/glibc.changes index f050d53..e8262fc 100644 --- a/glibc.changes +++ b/glibc.changes @@ -1,3 +1,82 @@ +------------------------------------------------------------------- +Mon Feb 5 08:49:13 UTC 2018 - schwab@suse.de + +- Update to glibc 2.27 + * Optimized x86-64 asin, atan2, exp, expf, log, pow, atan, sin, cosf, + sinf, sincosf and tan with FMA + * Optimized x86-64 trunc and truncf for processors with SSE4.1 + * Optimized generic expf, exp2f, logf, log2f, powf, sinf, cosf and + sincosf + * In order to support faster and safer process termination the malloc API + family of functions will no longer print a failure address and stack + backtrace after detecting heap corruption + * The abort function terminates the process immediately, without flushing + stdio streams + * On platforms where long double has the IEEE binary128 format (aarch64, + alpha, mips64, riscv, s390 and sparc), the math library now implements + _Float128 interfaces for that type, as defined by ISO/IEC TS 18661-3:2015 + These are the same interfaces added in version 2.26 for some platforms where + this format is supported but is not the format of long double + * On platforms with support for _Float64x (aarch64, alpha, i386, ia64, + mips64, powerpc64le, riscv, s390, sparc and x86_64), the math library now + implements interfaces for that type, as defined by ISO/IEC TS + 18661-3:2015 + * The math library now implements interfaces for the _Float32, _Float64 and + _Float32x types, as defined by ISO/IEC TS 18661-3:2015 + * glibc now implements the memfd_create and mlock2 functions on Linux + * Support for memory protection keys was added + * The copy_file_range function was added + * The ldconfig utility now processes `include' directives using the C/POSIX + collation ordering + * Support for two grammatical forms of month names has been added + * Support for the RISC-V ISA running on Linux has been added + * Statically compiled applications attempting to load locales compiled for the + GNU C Library version 2.27 will fail and fall back to the builtin C/POSIX + locale + * Support for statically linked applications which call dlopen is deprecated + and will be removed in a future version of glibc + * Support for old programs which use internal stdio data structures and + functions is deprecated + * On GNU/Linux, the obsolete Linux constant PTRACE_SEIZE_DEVEL is no longer + defined by + * libm no longer supports SVID error handling (calling a user-provided + matherr function on error) or the _LIB_VERSION variable to control error + handling + * The libm functions pow10, pow10f and pow10l are no longer supported for + new programs + * The mcontext_t type is no longer the same as struct sigcontext + * The add-ons mechanism for building additional packages at the same time as + glibc has been removed + * The res_hnok, res_dnok, res_mailok and res_ownok functions now check that + the specified string can be parsed as a domain name + * In the malloc_info output, the element may contain another + element, "subheaps", which contains the number of sub-heaps + * In the malloc_info output, the element may contain another + element, "subheaps", which contains the number of sub-heaps + * The nonstandard header files and <_G_config.h> are deprecated + and will be removed in a future release + * CVE-2018-6485: The posix_memalign and memalign functions, when called with + an object size near the value of SIZE_MAX, would return a pointer to a + buffer which is too small, instead of NULL (bsc#1079036) +- Support for Sun RPC is no longer available, use libtirpc instead +- glibc-nodate.patch, powerpc-elision-enable-envvar.patch, + s390-elision-enable-envvar.patch, resolv-context-leak.patch, + dl-runtime-resolve-opt-avx512f.patch, libpthread-compat-wrappers.patch, + math-c++-compat.patch, remove-nss-nis-compat.patch, + eh-frame-zero-terminator.patch, ld-so-hwcap-x86-64.patch, + assert-pedantic.patch, getaddrinfo-errno.patch, resolv-conf-oom.patch, + dynarray-allocation.patch, nearbyint-inexact.patch, nss-compat.patch, + nscd-libnsl.patch, malloc-tcache-leak.patch, + falkor-memcpy-memmove.patch, aarch64-cpu-features.patch, + nss-files-large-buffers.patch. sysconf-uio-maxiov.patch, + glob-tilde-overflow.patch, dl-runtime-resolve-xsave.patch, + spawni-assert.patch, x86-64-dl-platform.patch, glob64-s390.patch, + tst-tlsopt-powerpc.patch, powerpc-hwcap-bits.patch, + malloc-tcache-check-overflow.patch, dl-init-paths-overflow.patch, + fillin-rpath-empty-tokens.patch, getcwd-absolute.patch, + ldd-system-interp.patchabort-no-flush.patch: Removed +- All patches refreshed + ------------------------------------------------------------------- Tue Jan 30 16:42:14 UTC 2018 - schwab@suse.de diff --git a/glibc.keyring b/glibc.keyring index f1e08d5..0e698c5 100644 --- a/glibc.keyring +++ b/glibc.keyring @@ -1,4 +1,3 @@ - -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v2 @@ -142,8 +141,6 @@ WtkGoi8buNcby4U= =AL6o -----END PGP PUBLIC KEY BLOCK----- - - -----BEGIN PGP PUBLIC KEY BLOCK----- Version: PGP Key Server 0.9.6 @@ -171,7 +168,6 @@ ZthBvjkZUZCOl+wjwbn3k4bpiEYEGBECAAYFAj0n9DwACgkQWDlSU/gp6efSHgCc DxXIOrZyOO3jtbtsTYR/VrsdK9sAn0lrUm/jZKWyvK6V1CCA3TwXyvLQ =dSXY -----END PGP PUBLIC KEY BLOCK----- - -----BEGIN PGP PUBLIC KEY BLOCK----- mQENBFMAZNMBCACeatEKl6YY9iEVxzS64bPbvJsA1mLE2XFWmKXyYzm58dFqPMa0 @@ -625,7 +621,6 @@ N7JGzLVNo+A= =fZUN -----END PGP PUBLIC KEY BLOCK----- - -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1.4.10 (GNU/Linux) Comment: Public key at http://people.redhat.com/eblake/eblake.gpg diff --git a/glibc.spec b/glibc.spec index d4fcca1..873b55d 100644 --- a/glibc.spec +++ b/glibc.spec @@ -56,6 +56,7 @@ Summary: Standard Shared Libraries (from the GNU C Library) License: LGPL-2.1+ AND SUSE-LGPL-2.1+-with-GCC-exception AND GPL-2.0+ Group: System/Libraries BuildRequires: audit-devel +BuildRequires: bison BuildRequires: fdupes BuildRequires: libcap-devel BuildRequires: libselinux-devel @@ -138,11 +139,14 @@ BuildArch: i686 %ifarch ia64 %define enablekernel 3.2.18 %endif +%ifarch riscv64 +%define enablekernel 4.15 +%endif -Version: 2.26 +Version: 2.27 Release: 0 %if !%{build_snapshot} -%define git_id 1c9a5c270d8b +%define git_id 3260f6ce87b7 %define libversion %version %else %define git_id %(echo %version | sed 's/.*\.g//') @@ -236,8 +240,6 @@ Patch6: glibc-2.3.3-nscd-db-path.diff Patch7: nss-db-path.patch # PATCH-FIX-OPENSUSE adjust nscd.conf Patch8: glibc-nscd.conf.patch -# PATCH-FIX-OPENSUSE do not use compile time in binaries -Patch9: glibc-nodate.patch # PATCH-FIX-OPENSUSE -- add some extra information to version output - kukuk@suse.de Patch10: glibc-version.diff # PATCH-FIX-OPENSUSE -- Make --no-archive default for localedef - kukuk@suse.de @@ -248,10 +250,6 @@ Patch14: glibc-bindresvport-blacklist.diff Patch15: glibc-2.3.90-langpackdir.diff # PATCH-FEATURE-SLE Use nscd user for nscd Patch19: nscd-server-user.patch -# PATCH-FEATURE-SLE powerpc: enable TLE only if GLIBC_ELISION_ENABLE=yes is defined -Patch21: powerpc-elision-enable-envvar.patch -# PATCH-FEATURE-SLE s390: enable TLE only if GLIBC_ELISION_ENABLE=yes is defined -Patch22: s390-elision-enable-envvar.patch ### Locale related patches # PATCH-FIX-OPENSUSE Add additional locales @@ -276,76 +274,12 @@ Patch306: glibc-fix-double-loopback.diff ### # Patches from upstream ### -# PATCH-FIX-UPSTREAM Fix leaks of resolver contexts (BZ #21885, BZ #21932) -Patch1000: resolv-context-leak.patch -# PATCH-FIX-UPSTREAM Use _dl_runtime_resolve_opt only with AVX512F (BZ #21871) -Patch1001: dl-runtime-resolve-opt-avx512f.patch -# PATCH-FIX-UPSTREAM Don't use IFUNC resolver for longjmp or system in libpthread (BZ #21041) -Patch1002: libpthread-compat-wrappers.patch -# PATCH-FIX-UPSTREAM Do not use __builtin_types_compatible_p in C++ mode (BZ #21930, BZ #22146, BZ #22235, BZ #22296) -Patch1003: math-c++-compat.patch -# PATCH-FIX-UPSTREAM Remove nis and compat from default NSS configs -Patch1004: remove-nss-nis-compat.patch -# PATCH-FIX-UPSTREAM Properly terminate .eh_frame (BZ #22051) -Patch1005: eh-frame-zero-terminator.patch -# PATCH-FIX-UPSTREAM x86: Add x86_64 to x86-64 HWCAP (BZ #22093) -Patch1006: ld-so-hwcap-x86-64.patch -# PATCH-FIX-UPSTREAM assert: Suppress pedantic warning caused by statement expression (BZ #21242, BZ #21972) -Patch1007: assert-pedantic.patch -# PATCH-FIX-UPSTREAM Fix errno and h_errno handling in getaddrinfo (BZ #21915, BZ #21922) -Patch1008: getaddrinfo-errno.patch -# PATCH-FIX-UPSTREAM Fix memory handling in OOM situation during resolv.conf parsing (BZ #22095, BZ #22096) -Patch1009: resolv-conf-oom.patch -# PATCH-FIX-UPSTREAM Fix initial size of dynarray allocation and set errno on overflow error -Patch1010: dynarray-allocation.patch -# PATCH-FIX-UPSTREAM Avoid spurious inexact in nearbyint (BZ #22225) -Patch1011: nearbyint-inexact.patch -# PATCH-FIX-UPSTREAM Move nss_compat from nis to nss subdir and install it unconditionally -Patch1012: nss-compat.patch -# PATCH-FIX-UPSTREAM Remove reference to libnsl from nscd -Patch1013: nscd-libnsl.patch -# PATCH-FIX-UPSTREAM malloc: Fix tcache leak after thread destruction (BZ #22111) -Patch1014: malloc-tcache-leak.patch -# PATCH-FIX-UPSTREAM aarch64: Optimized implementation of memcpy/memmove for Qualcomm Falkor -Patch1015: falkor-memcpy-memmove.patch -# PATCH-FIX-UPSTREAM aarch64: Fix glibc.tune.cpu tunable handling -Patch1016: aarch64-cpu-features.patch -# PATCH-FIX-UPSTREAM nss_files: Avoid large buffers with many host addresses (BZ #22078) -Patch1017: nss-files-large-buffers.patch -# PATCH-FIX-UPSTREAM sysconf: Fix missing definition of UIO_MAXIOV on Linux (BZ #22321) -Patch1018: sysconf-uio-maxiov.patch -# PATCH-FIX-UPSTREAM glob: Fix buffer overflows (CVE-2017-15670, CVE-2017-15671, CVE-2017-15804, BZ #22320, BZ #22325, BZ #22332) -Patch1019: glob-tilde-overflow.patch -# PATCH-FIX-UPSTREAM x86-64: Use fxsave/xsave/xsavec in _dl_runtime_resolve (BZ #21265) -Patch1020: dl-runtime-resolve-xsave.patch -# PATCH-FIX-UPSTREAM posix: Fix improper assert in Linux posix_spawn (BZ #22273) -Patch1021: spawni-assert.patch -# PATCH-FIX-UPSTREAM x86-64: Don't set GLRO(dl_platform) to NULL (BZ #22299) -Patch1022: x86-64-dl-platform.patch -# PATCH-FIX-UPSTREAM no compat glob64 on s390 -Patch1023: glob64-s390.patch -# PATCH-FIX-UPSTREAM tst-tlsopt-powerpc as a shared lib -Patch1024: tst-tlsopt-powerpc.patch -# PATCH-FIX-UPSTREAM Update HWCAP for powerpc -Patch1025: powerpc-hwcap-bits.patch -# PATCH-FIX-UPSTREAM Fix integer overflow in malloc when tcache is enabled (CVE-2017-17426, BZ #22375) -Patch1026: malloc-tcache-check-overflow.patch -# PATCH-FIX-UPSTREAM Count components of the expanded path in _dl_init_path (CVE-2017-1000408, CVE-2017-1000409, bsc#1071319, BZ #22607, BZ #22627) -Patch1027: dl-init-paths-overflow.patch -# PATCH-FIX-UPSTREAM Check for empty tokens before dynamic string token expansion (CVE-2017-16997, bsc#1073231, BZ #22625) -Patch1028: fillin-rpath-empty-tokens.patch -# PATCH-FIX-UPSTREAM make getcwd(3) fail if it cannot obtain an absolute path (CVE-2018-1000001, BZ #22679) -Patch1029: getcwd-absolute.patch ### # Patches awaiting upstream approval ### # PATCH-FIX-UPSTREAM Always to locking when accessing streams (BZ #15142) Patch2000: fix-locking-in-_IO_cleanup.patch -# PATCH-FIX-UPSTREAM Never try to execute the file in ldd (BZ #16750) -Patch2001: ldd-system-interp.patch -# PATCH-FIX-UPSTREAM Don't close or flush stdio streams on abort (BZ #15436) -Patch2002: abort-no-flush.patch # PATCH-FIX-UPSTREAM Fix fnmatch handling of collating elements (BZ #17396, BZ #16976) Patch2004: fnmatch-collating-elements.patch # PATCH-FIX-UPSTREAM Properly reread entry after failure in nss_files getent function (BZ #18991) @@ -534,19 +468,11 @@ mv crypt_blowfish-%crypt_bf_version/*.[chS] crypt/ %patch6 -p1 %patch7 -p1 %patch8 -p1 -# avoid changing nscd_stat.c mtime to avoid code generation -# differences on each rebuild -touch -r nscd/nscd_stat.c nscd/s-stamp -%patch9 -p1 -touch -r nscd/s-stamp nscd/nscd_stat.c -rm nscd/s-stamp %patch10 -p1 %patch13 -p1 %patch14 -p1 %patch15 -p1 %patch19 -p1 -%patch21 -p1 -%patch22 -p1 %patch100 -p1 %patch102 -p1 @@ -557,40 +483,7 @@ rm nscd/s-stamp %patch304 -p1 %patch306 -p1 -%patch1000 -p1 -%patch1001 -p1 -%patch1002 -p1 -%patch1003 -p1 -%patch1004 -p1 -%patch1005 -p1 -%patch1006 -p1 -%patch1007 -p1 -%patch1008 -p1 -%patch1009 -p1 -%patch1010 -p1 -%patch1011 -p1 -%patch1012 -p1 -%patch1013 -p1 -%patch1014 -p1 -%patch1015 -p1 -%patch1016 -p1 -%patch1017 -p1 -%patch1018 -p1 -%patch1019 -p1 -%patch1020 -p1 -%patch1021 -p1 -%patch1022 -p1 -%patch1023 -p1 -%patch1024 -p1 -%patch1025 -p1 -%patch1026 -p1 -%patch1027 -p1 -%patch1028 -p1 -%patch1029 -p1 - %patch2000 -p1 -%patch2001 -p1 -%patch2002 -p1 %patch2004 -p1 %patch2005 -p1 %patch2006 -p1 @@ -720,17 +613,13 @@ configure_and_build_glibc() { profile="--enable-profile" fi %endif - elision=--enable-lock-elision - if [ "$dirname" = "noelision" ]; then - elision=--disable-lock-elision - fi ../configure \ CFLAGS="$conf_cflags" BUILD_CFLAGS="$conf_cflags" \ CC="$BuildCC" CXX="$BuildCCplus" \ --prefix=%{_prefix} \ --libexecdir=%{_libexecdir} --infodir=%{_infodir} \ --enable-add-ons=$add_ons \ - $profile $elision \ + $profile \ "$@" \ --build=%{target} --host=%{target} \ %ifarch armv7hl ppc ppc64 ppc64le i686 x86_64 sparc sparc64 s390 s390x @@ -750,7 +639,6 @@ configure_and_build_glibc() { --enable-kernel=%{enablekernel} \ --with-bugurl=http://bugs.opensuse.org \ --enable-bind-now \ - --enable-obsolete-rpc \ --disable-timezone-tools # Should we enable --enable-systemtap? # Should we enable --enable-nss-crypt to build use freebl3 hash functions? @@ -802,12 +690,6 @@ configure_and_build_glibc() { %endif # %{build_variants} %endif # optimize_power -%if %{build_variants} -%ifarch i686 x86_64 -configure_and_build_glibc noelision "$BuildFlags" -%endif -%endif - # # Build html documentation # @@ -895,6 +777,12 @@ export STRIP_KEEP_SYMTAB=*.so* mkdir -p %{buildroot}%{_libdir}/gconv touch %{buildroot}%{_libdir}/gconv/gconv-modules.cache +%ifarch riscv64 +ln -s . %{buildroot}%{_libdir}/lp64d +mkdir -p %{buildroot}/%{_lib} +ln -s . %{buildroot}/%{_lib}/lp64d +%endif + # Install base glibc make %{?_smp_mflags} install_root=%{buildroot} install -C cc-base @@ -951,15 +839,6 @@ cc-base/elf/ldconfig -vn $destdir %endif %endif # optimize_power -%ifarch i686 x86_64 -cd cc-noelision -destdir=$RPM_BUILD_ROOT/%{_lib}/noelision -mkdir -p $destdir -install -m 755 nptl/libpthread.so $destdir/libpthread-%{libversion}.so -cd .. -cc-base/elf/ldconfig -vn $destdir -%endif - # Install locales %if %{build_locales} # XXX Do not install locales in parallel! @@ -977,11 +856,6 @@ cc-base/elf/ldconfig -vn $destdir # Create file list for glibc-locale package %{find_lang} libc -# remove nsl compat library -rm -f %{buildroot}%{_libdir}/libnsl* -# part of libnsl-devel -rm -f %{buildroot}%{_includedir}/rpcsvc/yppasswd.* - # Miscelanna: install -m 0700 glibc_post_upgrade %{buildroot}%{_sbindir} @@ -1220,6 +1094,12 @@ exit 0 /lib/ld-linux-aarch64.so.1 /%{_lib}/ld-linux-aarch64.so.1 %endif +%ifarch riscv64 +/lib/ld-linux-riscv64-lp64d.so.1 +/%{_lib}/ld-linux-riscv64-lp64d.so.1 +/%{_lib}/lp64d +%{_libdir}/lp64d +%endif %ifarch %ix86 x86_64 ppc ppc64 s390 s390x # LSB /%{_lib}/*-lsb*.so.3 @@ -1296,9 +1176,6 @@ exit 0 %{optimized_libs ppc-cell-be} %endif %endif # optimize_power -%ifarch i686 x86_64 -/%{_lib}/noelision -%endif %dir %attr(0700,root,root) /var/cache/ldconfig /sbin/ldconfig %{_bindir}/gencat @@ -1326,12 +1203,10 @@ exit 0 %files devel %defattr(-,root,root) -%doc COPYING COPYING.LIB NEWS README BUGS CONFORMANCE +%doc COPYING COPYING.LIB NEWS README %doc %{_mandir}/man1/catchsegv.1.gz -%doc %{_mandir}/man1/rpcgen.1.gz %doc %{_mandir}/man3/* %{_bindir}/catchsegv -%{_bindir}/rpcgen %{_bindir}/sprof %{_includedir}/* %{_libdir}/*.o @@ -1339,7 +1214,6 @@ exit 0 # These static libraries are needed even for shared builds %{_libdir}/libc_nonshared.a %{_libdir}/libg.a -%{_libdir}/libieee.a %ifarch ppc ppc64 ppc64le s390 s390x sparc sparcv8 sparcv9 sparcv9v # This is not built on sparc64. %{_libdir}/libnldbl_nonshared.a @@ -1349,7 +1223,6 @@ exit 0 %{_libdir}/libmvec_nonshared.a %endif %{_libdir}/libpthread_nonshared.a -%{_libdir}/librpcsvc.a %files devel-static %defattr(-,root,root) @@ -1420,7 +1293,6 @@ exit 0 %{_libdir}/libpthread_p.a %{_libdir}/libresolv_p.a %{_libdir}/librt_p.a -%{_libdir}/librpcsvc_p.a %{_libdir}/libutil_p.a %{_libdir}/libdl_p.a %endif diff --git a/glob-tilde-overflow.patch b/glob-tilde-overflow.patch deleted file mode 100644 index 5e5f7e1..0000000 --- a/glob-tilde-overflow.patch +++ /dev/null @@ -1,2244 +0,0 @@ -2017-10-22 Paul Eggert - - [BZ #22332] - * posix/glob.c (__glob): Fix buffer overflow during GLOB_TILDE - unescaping. - -2017-10-21 Florian Weimer - - * posix/Makefile (tests): Add tst-glob-tilde. - (tests-special): Add tst-glob-tilde-mem.out - (tst-glob-tilde-ENV): Set MALLOC_TRACE. - (tst-glob-tilde-mem.out): Add mtrace check. - * posix/tst-glob-tilde.c: New file. - -2017-10-20 Paul Eggert - - [BZ #22320] - CVE-2017-15670 - * posix/glob.c (__glob): Fix one-byte overflow. - -2017-09-08 Adhemerval Zanella - - [BZ #1062] - [BZ #22325] - CVE-2017-15671 - * posix/Makefile (routines): Add globfree, globfree64, and - glob_pattern_p. - * posix/flexmember.h: New file. - * posix/glob_internal.h: Likewise. - * posix/glob_pattern_p.c: Likewise. - * posix/globfree.c: Likewise. - * posix/globfree64.c: Likewise. - * sysdeps/gnu/globfree64.c: Likewise. - * sysdeps/unix/sysv/linux/alpha/globfree.c: Likewise. - * sysdeps/unix/sysv/linux/mips/mips64/n64/globfree64.c: Likewise. - * sysdeps/unix/sysv/linux/oldglob.c: Likewise. - * sysdeps/unix/sysv/linux/wordsize-64/globfree64.c: Likewise. - * sysdeps/unix/sysv/linux/x86_64/x32/globfree.c: Likewise. - * sysdeps/wordsize-64/globfree.c: Likewise. - * sysdeps/wordsize-64/globfree64.c: Likewise. - * posix/glob.c (HAVE_CONFIG_H): Use !_LIBC instead. - [NDEBUG): Remove comments. - (GLOB_ONLY_P, _AMIGA, VMS): Remove define. - (dirent_type): New type. Use uint_fast8_t not - uint8_t, as C99 does not require uint8_t. - (DT_UNKNOWN, DT_DIR, DT_LNK): New macros. - (struct readdir_result): Use dirent_type. Do not define skip_entry - unless it is needed; this saves a byte on platforms lacking d_ino. - (readdir_result_type, readdir_result_skip_entry): - New functions, replacing ... - (readdir_result_might_be_symlink, readdir_result_might_be_dir): - these functions, which were removed. This makes the callers - easier to read. All callers changed. - (D_INO_TO_RESULT): Now empty if there is no d_ino. - (size_add_wrapv, glob_use_alloca): New static functions. - (glob, glob_in_dir): Check for size_t overflow in several places, - and fix some size_t checks that were not quite right. - Remove old code using SHELL since Bash no longer - uses this. - (glob, prefix_array): Separate MS code better. - (glob_in_dir): Remove old Amiga and VMS code. - (globfree, __glob_pattern_type, __glob_pattern_p): Move to - separate files. - (glob_in_dir): Do not rely on undefined behavior in accessing - struct members beyond their bounds. Use a flexible array member - instead - (link_stat): Rename from link_exists2_p and return -1/0 instead of - 0/1. Caller changed. - (glob): Fix memory leaks. - * posix/glob64 (globfree64): Move to separate file. - * sysdeps/gnu/glob64.c (NO_GLOB_PATTERN_P): Remove define. - (globfree64): Remove hidden alias. - * sysdeps/unix/sysv/linux/Makefile (sysdeps_routines): Add - oldglob. - * sysdeps/unix/sysv/linux/alpha/glob.c (__new_globfree): Move to - separate file. - * sysdeps/unix/sysv/linux/i386/glob64.c (NO_GLOB_PATTERN_P): Remove - define. - Move compat code to separate file. - * sysdeps/wordsize-64/glob.c (globfree): Move definitions to - separate file. - -2017-08-20 H.J. Lu - - [BZ #18822] - * sysdeps/unix/sysv/linux/i386/glob64.c (__old_glob64): Add - libc_hidden_proto and libc_hidden_def. - -Index: glibc-2.26/posix/Makefile -=================================================================== ---- glibc-2.26.orig/posix/Makefile -+++ glibc-2.26/posix/Makefile -@@ -45,7 +45,7 @@ routines := \ - getpgid setpgid getpgrp bsd-getpgrp setpgrp getsid setsid \ - getresuid getresgid setresuid setresgid \ - pathconf sysconf fpathconf \ -- glob glob64 fnmatch regex \ -+ glob glob64 globfree globfree64 glob_pattern_p fnmatch regex \ - confstr \ - getopt getopt1 \ - sched_setp sched_getp sched_sets sched_gets sched_yield sched_primax \ -@@ -93,7 +93,7 @@ tests := test-errno tstgetopt testfnm r - tst-fnmatch3 bug-regex36 tst-getaddrinfo5 \ - tst-posix_spawn-fd tst-posix_spawn-setsid \ - tst-posix_fadvise tst-posix_fadvise64 \ -- tst-sysconf-empty-chroot -+ tst-sysconf-empty-chroot tst-glob-tilde - tests-internal := bug-regex5 bug-regex20 bug-regex33 \ - tst-rfc3484 tst-rfc3484-2 tst-rfc3484-3 - xtests := bug-ga2 -@@ -141,7 +141,8 @@ tests-special += $(objpfx)bug-regex2-mem - $(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 - -@@ -350,6 +351,12 @@ $(objpfx)bug-glob2-mem.out: $(objpfx)bug - $(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 ,\ -Index: glibc-2.26/posix/flexmember.h -=================================================================== ---- /dev/null -+++ glibc-2.26/posix/flexmember.h -@@ -0,0 +1,45 @@ -+/* Sizes of structs with flexible array members. -+ -+ Copyright 2016-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 -+ . -+ -+ Written by Paul Eggert. */ -+ -+#include -+ -+/* Nonzero multiple of alignment of TYPE, suitable for FLEXSIZEOF below. -+ On older platforms without _Alignof, use a pessimistic bound that is -+ safe in practice even if FLEXIBLE_ARRAY_MEMBER is 1. -+ On newer platforms, use _Alignof to get a tighter bound. */ -+ -+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112 -+# define FLEXALIGNOF(type) (sizeof (type) & ~ (sizeof (type) - 1)) -+#else -+# define FLEXALIGNOF(type) _Alignof (type) -+#endif -+ -+/* Upper bound on the size of a struct of type TYPE with a flexible -+ array member named MEMBER that is followed by N bytes of other data. -+ This is not simply sizeof (TYPE) + N, since it may require -+ alignment on unusually picky C11 platforms, and -+ FLEXIBLE_ARRAY_MEMBER may be 1 on pre-C11 platforms. -+ Yield a value less than N if and only if arithmetic overflow occurs. */ -+ -+#define FLEXSIZEOF(type, member, n) \ -+ ((offsetof (type, member) + FLEXALIGNOF (type) - 1 + (n)) \ -+ & ~ (FLEXALIGNOF (type) - 1)) -Index: glibc-2.26/posix/glob.c -=================================================================== ---- glibc-2.26.orig/posix/glob.c -+++ glibc-2.26/posix/glob.c -@@ -15,7 +15,7 @@ - License along with the GNU C Library; if not, see - . */ - --#ifdef HAVE_CONFIG_H -+#ifndef _LIBC - # include - #endif - -@@ -27,29 +27,15 @@ - #include - #include - #include -- --/* Outcomment the following line for production quality code. */ --/* #define NDEBUG 1 */ - #include -+#include - --#include /* Needed on stupid SunOS for assert. */ -- --#if !defined _LIBC || !defined GLOB_ONLY_P --#if defined HAVE_UNISTD_H || defined _LIBC --# include --# ifndef POSIX --# ifdef _POSIX_VERSION --# define POSIX --# endif --# endif -+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ -+# define WINDOWS32 - #endif - --#include -- --#if defined HAVE_STDINT_H || defined _LIBC --# include --#elif !defined UINTPTR_MAX --# define UINTPTR_MAX (~((size_t) 0)) -+#ifndef WINDOWS32 -+# include - #endif - - #include -@@ -57,24 +43,7 @@ - # define __set_errno(val) errno = (val) - #endif - --#if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__ --# include --#else --# define dirent direct --# ifdef HAVE_SYS_NDIR_H --# include --# endif --# ifdef HAVE_SYS_DIR_H --# include --# endif --# ifdef HAVE_NDIR_H --# include --# endif --# ifdef HAVE_VMSDIR_H --# include "vmsdir.h" --# endif /* HAVE_VMSDIR_H */ --#endif -- -+#include - #include - #include - #include -@@ -87,27 +56,29 @@ - # define opendir(name) __opendir (name) - # define readdir(str) __readdir64 (str) - # define getpwnam_r(name, bufp, buf, len, res) \ -- __getpwnam_r (name, bufp, buf, len, res) -+ __getpwnam_r (name, bufp, buf, len, res) - # ifndef __stat64 - # define __stat64(fname, buf) __xstat64 (_STAT_VER, fname, buf) - # endif - # define struct_stat64 struct stat64 -+# define FLEXIBLE_ARRAY_MEMBER - #else /* !_LIBC */ --# include "getlogin_r.h" --# include "mempcpy.h" --# include "stat-macros.h" --# include "strdup.h" --# define __stat64(fname, buf) stat (fname, buf) --# define struct_stat64 struct stat --# define __stat(fname, buf) stat (fname, buf) --# define __alloca alloca --# define __readdir readdir --# define __readdir64 readdir64 --# define __glob_pattern_p glob_pattern_p -+# define __getlogin_r(buf, len) getlogin_r (buf, len) -+# define __stat64(fname, buf) stat (fname, buf) -+# define __fxstatat64(_, d, f, st, flag) fstatat (d, f, st, flag) -+# define struct_stat64 struct stat -+# ifndef __MVS__ -+# define __alloca alloca -+# endif -+# define __readdir readdir -+# define COMPILE_GLOB64 - #endif /* _LIBC */ - - #include - -+#include -+#include -+ - #ifdef _SC_GETPW_R_SIZE_MAX - # define GETPW_R_SIZE_MAX() sysconf (_SC_GETPW_R_SIZE_MAX) - #else -@@ -121,61 +92,59 @@ - - static const char *next_brace_sub (const char *begin, int flags) __THROWNL; - -+typedef uint_fast8_t dirent_type; -+ -+#if !defined _LIBC && !defined HAVE_STRUCT_DIRENT_D_TYPE -+/* Any distinct values will do here. -+ Undef any existing macros out of the way. */ -+# undef DT_UNKNOWN -+# undef DT_DIR -+# undef DT_LNK -+# define DT_UNKNOWN 0 -+# define DT_DIR 1 -+# define DT_LNK 2 -+#endif -+ - /* 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 -+#if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE -+ dirent_type type; -+#endif -+#if defined _LIBC || defined D_INO_IN_DIRENT - bool skip_entry; -+#endif - }; - --# 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) -+/* Initialize and return type member of struct readdir_result. */ -+static dirent_type -+readdir_result_type (struct readdir_result d) - { -- return true; -+#if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE -+# define D_TYPE_TO_RESULT(source) (source)->d_type, -+ return d.type; -+#else -+# define D_TYPE_TO_RESULT(source) -+ return DT_UNKNOWN; -+#endif - } - -+/* Initialize and return skip_entry member of struct readdir_result. */ - static bool --readdir_result_might_be_dir (struct readdir_result d) -+readdir_result_skip_entry (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 -+#if defined _LIBC || defined D_INO_IN_DIRENT -+# define D_INO_TO_RESULT(source) (source)->d_ino == 0, -+ return d.skip_entry; -+#else -+# define D_INO_TO_RESULT(source) -+ return false; -+#endif -+} - - /* Construct an initializer for a struct readdir_result object from a - struct dirent *. No copy of the name is made. */ -@@ -186,8 +155,6 @@ readdir_result_might_be_dir (struct read - 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 -@@ -225,18 +192,55 @@ convert_dirent64 (const struct dirent64 - } - #endif - -+#ifndef _LIBC -+/* The results of opendir() in this file are not used with dirfd and fchdir, -+ and we do not leak fds to any single-threaded code that could use stdio, -+ therefore save some unnecessary recursion in fchdir.c and opendir_safer.c. -+ FIXME - if the kernel ever adds support for multi-thread safety for -+ avoiding standard fds, then we should use opendir_safer. */ -+# ifdef GNULIB_defined_opendir -+# undef opendir -+# endif -+# ifdef GNULIB_defined_closedir -+# undef closedir -+# endif - --#ifndef attribute_hidden --# define attribute_hidden -+/* Just use malloc. */ -+# define __libc_use_alloca(n) false -+# define alloca_account(len, avar) ((void) (len), (void) (avar), (void *) 0) -+# define extend_alloca_account(buf, len, newlen, avar) \ -+ ((void) (buf), (void) (len), (void) (newlen), (void) (avar), (void *) 0) - #endif - -+/* Set *R = A + B. Return true if the answer is mathematically -+ incorrect due to overflow; in this case, *R is the low order -+ bits of the correct answer. */ -+ -+static bool -+size_add_wrapv (size_t a, size_t b, size_t *r) -+{ -+#if 5 <= __GNUC__ && !defined __ICC -+ return __builtin_add_overflow (a, b, r); -+#else -+ *r = a + b; -+ return *r < a; -+#endif -+} -+ -+static bool -+glob_use_alloca (size_t alloca_used, size_t len) -+{ -+ size_t size; -+ return (!size_add_wrapv (alloca_used, len, &size) -+ && __libc_use_alloca (size)); -+} -+ - static int glob_in_dir (const char *pattern, const char *directory, - int flags, int (*errfunc) (const char *, int), - glob_t *pglob, size_t alloca_used); - extern int __glob_pattern_type (const char *pattern, int quote) - attribute_hidden; - --#if !defined _LIBC || !defined GLOB_ONLY_P - static int prefix_array (const char *prefix, char **array, size_t n) __THROWNL; - static int collated_compare (const void *, const void *) __THROWNL; - -@@ -265,16 +269,15 @@ next_brace_sub (const char *cp, int flag - return *cp != '\0' ? cp : NULL; - } - --#endif /* !defined _LIBC || !defined GLOB_ONLY_P */ - - /* Do glob searching for PATTERN, placing results in PGLOB. - The bits defined above may be set in FLAGS. - If a directory cannot be opened or read and ERRFUNC is not nil, - it is called with the pathname that caused the error, and the -- `errno' value from the failing call; if it returns non-zero -- `glob' returns GLOB_ABORTED; if it returns zero, the error is ignored. -+ 'errno' value from the failing call; if it returns non-zero -+ 'glob' returns GLOB_ABORTED; if it returns zero, the error is ignored. - If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned. -- Otherwise, `glob' returns zero. */ -+ Otherwise, 'glob' returns zero. */ - int - #ifdef GLOB_ATTRIBUTE - GLOB_ATTRIBUTE -@@ -292,9 +295,7 @@ glob (const char *pattern, int flags, in - int malloc_dirname = 0; - glob_t dirs; - int retval = 0; --#ifdef _LIBC - size_t alloca_used = 0; --#endif - - if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0) - { -@@ -308,7 +309,7 @@ glob (const char *pattern, int flags, in - flags |= GLOB_ONLYDIR; - - if (!(flags & GLOB_DOOFFS)) -- /* Have to do this so `globfree' knows where to start freeing. It -+ /* Have to do this so 'globfree' knows where to start freeing. It - also makes all the code that uses gl_offs simpler. */ - pglob->gl_offs = 0; - -@@ -372,14 +373,12 @@ glob (const char *pattern, int flags, in - size_t rest_len; - char *onealt; - size_t pattern_len = strlen (pattern) - 1; --#ifdef _LIBC -- int alloca_onealt = __libc_use_alloca (alloca_used + pattern_len); -+ int alloca_onealt = glob_use_alloca (alloca_used, pattern_len); - if (alloca_onealt) - onealt = alloca_account (pattern_len, alloca_used); - else --#endif - { -- onealt = (char *) malloc (pattern_len); -+ onealt = malloc (pattern_len); - if (onealt == NULL) - return GLOB_NOSPACE; - } -@@ -392,11 +391,9 @@ glob (const char *pattern, int flags, in - next = next_brace_sub (begin + 1, flags); - if (next == NULL) - { -- /* It is an illegal expression. */ -+ /* It is an invalid expression. */ - illegal_brace: --#ifdef _LIBC - if (__glibc_unlikely (!alloca_onealt)) --#endif - free (onealt); - flags &= ~GLOB_BRACE; - goto no_brace; -@@ -437,9 +434,7 @@ glob (const char *pattern, int flags, in - /* If we got an error, return it. */ - if (result && result != GLOB_NOMATCH) - { --#ifdef _LIBC - if (__glibc_unlikely (!alloca_onealt)) --#endif - free (onealt); - if (!(flags & GLOB_APPEND)) - { -@@ -458,9 +453,7 @@ glob (const char *pattern, int flags, in - assert (next != NULL); - } - --#ifdef _LIBC - if (__glibc_unlikely (!alloca_onealt)) --#endif - free (onealt); - - if (pglob->gl_pathc != firstc) -@@ -476,14 +469,16 @@ glob (const char *pattern, int flags, in - - /* Find the filename. */ - filename = strrchr (pattern, '/'); -+ - #if defined __MSDOS__ || defined WINDOWS32 -- /* The case of "d:pattern". Since `:' is not allowed in -+ /* The case of "d:pattern". Since ':' is not allowed in - file names, we can safely assume that wherever it - happens in pattern, it signals the filename part. This - is so we could some day support patterns like "[a-z]:foo". */ - if (filename == NULL) - filename = strchr (pattern, ':'); - #endif /* __MSDOS__ || WINDOWS32 */ -+ - dirname_modified = 0; - if (filename == NULL) - { -@@ -508,11 +503,7 @@ glob (const char *pattern, int flags, in - } - - filename = pattern; --#ifdef _AMIGA -- dirname = (char *) ""; --#else - dirname = (char *) "."; --#endif - dirlen = 0; - } - } -@@ -536,22 +527,21 @@ glob (const char *pattern, int flags, in - char *drive_spec; - - ++dirlen; -- drive_spec = (char *) __alloca (dirlen + 1); -+ drive_spec = __alloca (dirlen + 1); - *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0'; - /* For now, disallow wildcards in the drive spec, to - prevent infinite recursion in glob. */ - if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE))) - return GLOB_NOMATCH; -- /* If this is "d:pattern", we need to copy `:' to DIRNAME -+ /* If this is "d:pattern", we need to copy ':' to DIRNAME - as well. If it's "d:/pattern", don't remove the slash - from "d:/", since "d:" and "d:/" are not the same.*/ - } - #endif --#ifdef _LIBC -- if (__libc_use_alloca (alloca_used + dirlen + 1)) -+ -+ if (glob_use_alloca (alloca_used, dirlen + 1)) - newp = alloca_account (dirlen + 1, alloca_used); - else --#endif - { - newp = malloc (dirlen + 1); - if (newp == NULL) -@@ -562,14 +552,17 @@ glob (const char *pattern, int flags, in - dirname = newp; - ++filename; - -- if (filename[0] == '\0' - #if defined __MSDOS__ || defined WINDOWS32 -- && dirname[dirlen - 1] != ':' -- && (dirlen < 3 || dirname[dirlen - 2] != ':' -- || dirname[dirlen - 1] != '/') -+ bool drive_root = (dirlen > 1 -+ && (dirname[dirlen - 1] == ':' -+ || (dirlen > 2 && dirname[dirlen - 2] == ':' -+ && dirname[dirlen - 1] == '/'))); -+#else -+ bool drive_root = false; - #endif -- && dirlen > 1) -- /* "pattern/". Expand "pattern", appending slashes. */ -+ -+ if (filename[0] == '\0' && dirlen > 1 && !drive_root) -+ /* "pattern/". Expand "pattern", appending slashes. */ - { - int orig_flags = flags; - if (!(flags & GLOB_NOESCAPE) && dirname[dirlen - 1] == '\\') -@@ -602,7 +595,6 @@ glob (const char *pattern, int flags, in - } - } - --#ifndef VMS - if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~') - { - if (dirname[1] == '\0' || dirname[1] == '/' -@@ -612,100 +604,127 @@ glob (const char *pattern, int flags, in - /* Look up home directory. */ - char *home_dir = getenv ("HOME"); - int malloc_home_dir = 0; --# ifdef _AMIGA -- if (home_dir == NULL || home_dir[0] == '\0') -- home_dir = "SYS:"; --# else --# ifdef WINDOWS32 -- if (home_dir == NULL || home_dir[0] == '\0') -- home_dir = "c:/users/default"; /* poor default */ --# else - if (home_dir == NULL || home_dir[0] == '\0') - { -+#ifdef WINDOWS32 -+ /* Windows NT defines HOMEDRIVE and HOMEPATH. But give -+ preference to HOME, because the user can change HOME. */ -+ const char *home_drive = getenv ("HOMEDRIVE"); -+ const char *home_path = getenv ("HOMEPATH"); -+ -+ if (home_drive != NULL && home_path != NULL) -+ { -+ size_t home_drive_len = strlen (home_drive); -+ size_t home_path_len = strlen (home_path); -+ char *mem = alloca (home_drive_len + home_path_len + 1); -+ -+ memcpy (mem, home_drive, home_drive_len); -+ memcpy (mem + home_drive_len, home_path, home_path_len + 1); -+ home_dir = mem; -+ } -+ else -+ home_dir = "c:/users/default"; /* poor default */ -+#else - int success; - char *name; -+ int malloc_name = 0; - size_t buflen = GET_LOGIN_NAME_MAX () + 1; - - if (buflen == 0) -- /* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try -+ /* 'sysconf' does not support _SC_LOGIN_NAME_MAX. Try - a moderate value. */ - buflen = 20; -- name = alloca_account (buflen, alloca_used); -+ if (glob_use_alloca (alloca_used, buflen)) -+ name = alloca_account (buflen, alloca_used); -+ else -+ { -+ name = malloc (buflen); -+ if (name == NULL) -+ { -+ retval = GLOB_NOSPACE; -+ goto out; -+ } -+ malloc_name = 1; -+ } - - success = __getlogin_r (name, buflen) == 0; - if (success) - { - struct passwd *p; --# if defined HAVE_GETPWNAM_R || defined _LIBC -- long int pwbuflen = GETPW_R_SIZE_MAX (); -+ char *malloc_pwtmpbuf = NULL; - char *pwtmpbuf; -+# if defined HAVE_GETPWNAM_R || defined _LIBC -+ long int pwbuflenmax = GETPW_R_SIZE_MAX (); -+ size_t pwbuflen = pwbuflenmax; - struct passwd pwbuf; -- int malloc_pwtmpbuf = 0; - int save = errno; - --# ifndef _LIBC -- if (pwbuflen == -1) -- /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. -+# ifndef _LIBC -+ if (! (0 < pwbuflenmax && pwbuflenmax <= SIZE_MAX)) -+ /* 'sysconf' does not support _SC_GETPW_R_SIZE_MAX. - Try a moderate value. */ - pwbuflen = 1024; --# endif -- if (__libc_use_alloca (alloca_used + pwbuflen)) -+# endif -+ if (glob_use_alloca (alloca_used, pwbuflen)) - pwtmpbuf = alloca_account (pwbuflen, alloca_used); - else - { - pwtmpbuf = malloc (pwbuflen); - if (pwtmpbuf == NULL) - { -+ if (__glibc_unlikely (malloc_name)) -+ free (name); - retval = GLOB_NOSPACE; - goto out; - } -- malloc_pwtmpbuf = 1; -+ malloc_pwtmpbuf = pwtmpbuf; - } - - while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p) - != 0) - { -+ size_t newlen; -+ bool v; - if (errno != ERANGE) - { - p = NULL; - break; - } -- -- if (!malloc_pwtmpbuf -- && __libc_use_alloca (alloca_used -- + 2 * pwbuflen)) -+ v = size_add_wrapv (pwbuflen, pwbuflen, &newlen); -+ if (!v && malloc_pwtmpbuf == NULL -+ && glob_use_alloca (alloca_used, newlen)) - pwtmpbuf = extend_alloca_account (pwtmpbuf, pwbuflen, -- 2 * pwbuflen, -- alloca_used); -+ newlen, alloca_used); - else - { -- char *newp = realloc (malloc_pwtmpbuf -- ? pwtmpbuf : NULL, -- 2 * pwbuflen); -+ char *newp = (v ? NULL -+ : realloc (malloc_pwtmpbuf, newlen)); - if (newp == NULL) - { -- if (__glibc_unlikely (malloc_pwtmpbuf)) -- free (pwtmpbuf); -+ free (malloc_pwtmpbuf); -+ if (__glibc_unlikely (malloc_name)) -+ free (name); - retval = GLOB_NOSPACE; - goto out; - } -- pwtmpbuf = newp; -- pwbuflen = 2 * pwbuflen; -- malloc_pwtmpbuf = 1; -+ malloc_pwtmpbuf = pwtmpbuf = newp; - } -+ pwbuflen = newlen; - __set_errno (save); - } --# else -+# else - p = getpwnam (name); --# endif -+# endif -+ if (__glibc_unlikely (malloc_name)) -+ free (name); - if (p != NULL) - { -- if (!malloc_pwtmpbuf) -+ if (malloc_pwtmpbuf == NULL) - home_dir = p->pw_dir; - else - { - size_t home_dir_len = strlen (p->pw_dir) + 1; -- if (__libc_use_alloca (alloca_used + home_dir_len)) -+ if (glob_use_alloca (alloca_used, home_dir_len)) - home_dir = alloca_account (home_dir_len, - alloca_used); - else -@@ -720,26 +739,32 @@ glob (const char *pattern, int flags, in - malloc_home_dir = 1; - } - memcpy (home_dir, p->pw_dir, home_dir_len); -- -- free (pwtmpbuf); - } - } -+ free (malloc_pwtmpbuf); - } -+ else -+ { -+ if (__glibc_unlikely (malloc_name)) -+ free (name); -+ } -+#endif /* WINDOWS32 */ - } - if (home_dir == NULL || home_dir[0] == '\0') - { -+ if (__glibc_unlikely (malloc_home_dir)) -+ free (home_dir); - if (flags & GLOB_TILDE_CHECK) - { -- if (__glibc_unlikely (malloc_home_dir)) -- free (home_dir); - retval = GLOB_NOMATCH; - goto out; - } - else -- home_dir = (char *) "~"; /* No luck. */ -+ { -+ home_dir = (char *) "~"; /* No luck. */ -+ malloc_home_dir = 0; -+ } - } --# endif /* WINDOWS32 */ --# endif - /* Now construct the full directory. */ - if (dirname[1] == '\0') - { -@@ -754,8 +779,7 @@ glob (const char *pattern, int flags, in - { - char *newp; - size_t home_len = strlen (home_dir); -- int use_alloca = __libc_use_alloca (alloca_used -- + home_len + dirlen); -+ int use_alloca = glob_use_alloca (alloca_used, home_len + dirlen); - if (use_alloca) - newp = alloca_account (home_len + dirlen, alloca_used); - else -@@ -779,12 +803,15 @@ glob (const char *pattern, int flags, in - dirname = newp; - dirlen += home_len - 1; - malloc_dirname = !use_alloca; -+ -+ if (__glibc_unlikely (malloc_home_dir)) -+ free (home_dir); - } - dirname_modified = 1; - } --# if !defined _AMIGA && !defined WINDOWS32 - else - { -+#ifndef WINDOWS32 - char *end_name = strchr (dirname, '/'); - char *user_name; - int malloc_user_name = 0; -@@ -806,7 +833,7 @@ glob (const char *pattern, int flags, in - else - { - char *newp; -- if (__libc_use_alloca (alloca_used + (end_name - dirname))) -+ if (glob_use_alloca (alloca_used, end_name - dirname)) - newp = alloca_account (end_name - dirname, alloca_used); - else - { -@@ -823,11 +850,11 @@ glob (const char *pattern, int flags, in - 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 -@@ -843,7 +870,7 @@ glob (const char *pattern, int flags, in - *p = '\0'; - } - else -- *((char *) mempcpy (newp, dirname + 1, end_name - dirname)) -+ *((char *) mempcpy (newp, dirname + 1, end_name - dirname - 1)) - = '\0'; - user_name = newp; - } -@@ -851,20 +878,21 @@ glob (const char *pattern, int flags, in - /* Look up specific user's home directory. */ - { - struct passwd *p; -+ char *malloc_pwtmpbuf = NULL; - # if defined HAVE_GETPWNAM_R || defined _LIBC -- long int buflen = GETPW_R_SIZE_MAX (); -+ long int buflenmax = GETPW_R_SIZE_MAX (); -+ size_t buflen = buflenmax; - char *pwtmpbuf; -- int malloc_pwtmpbuf = 0; - struct passwd pwbuf; - int save = errno; - - # ifndef _LIBC -- if (buflen == -1) -- /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a -+ if (! (0 <= buflenmax && buflenmax <= SIZE_MAX)) -+ /* Perhaps 'sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a - moderate value. */ - buflen = 1024; - # endif -- if (__libc_use_alloca (alloca_used + buflen)) -+ if (glob_use_alloca (alloca_used, buflen)) - pwtmpbuf = alloca_account (buflen, alloca_used); - else - { -@@ -877,32 +905,32 @@ glob (const char *pattern, int flags, in - retval = GLOB_NOSPACE; - goto out; - } -- malloc_pwtmpbuf = 1; -+ malloc_pwtmpbuf = pwtmpbuf; - } - - while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0) - { -+ size_t newlen; -+ bool v; - if (errno != ERANGE) - { - p = NULL; - break; - } -- if (!malloc_pwtmpbuf -- && __libc_use_alloca (alloca_used + 2 * buflen)) -+ v = size_add_wrapv (buflen, buflen, &newlen); -+ if (!v && malloc_pwtmpbuf == NULL -+ && glob_use_alloca (alloca_used, newlen)) - pwtmpbuf = extend_alloca_account (pwtmpbuf, buflen, -- 2 * buflen, alloca_used); -+ newlen, alloca_used); - else - { -- char *newp = realloc (malloc_pwtmpbuf ? pwtmpbuf : NULL, -- 2 * buflen); -+ char *newp = v ? NULL : realloc (malloc_pwtmpbuf, newlen); - if (newp == NULL) - { -- if (__glibc_unlikely (malloc_pwtmpbuf)) -- free (pwtmpbuf); -+ free (malloc_pwtmpbuf); - goto nomem_getpw; - } -- pwtmpbuf = newp; -- malloc_pwtmpbuf = 1; -+ malloc_pwtmpbuf = pwtmpbuf = newp; - } - __set_errno (save); - } -@@ -923,7 +951,7 @@ glob (const char *pattern, int flags, in - free (dirname); - malloc_dirname = 0; - -- if (__libc_use_alloca (alloca_used + home_len + rest_len + 1)) -+ if (glob_use_alloca (alloca_used, home_len + rest_len + 1)) - dirname = alloca_account (home_len + rest_len + 1, - alloca_used); - else -@@ -931,8 +959,7 @@ glob (const char *pattern, int flags, in - dirname = malloc (home_len + rest_len + 1); - if (dirname == NULL) - { -- if (__glibc_unlikely (malloc_pwtmpbuf)) -- free (pwtmpbuf); -+ free (malloc_pwtmpbuf); - retval = GLOB_NOSPACE; - goto out; - } -@@ -944,24 +971,24 @@ glob (const char *pattern, int flags, in - dirlen = home_len + rest_len; - dirname_modified = 1; - -- if (__glibc_unlikely (malloc_pwtmpbuf)) -- free (pwtmpbuf); -+ free (malloc_pwtmpbuf); - } - else - { -- if (__glibc_unlikely (malloc_pwtmpbuf)) -- free (pwtmpbuf); -+ free (malloc_pwtmpbuf); - - if (flags & GLOB_TILDE_CHECK) -- /* We have to regard it as an error if we cannot find the -- home directory. */ -- return GLOB_NOMATCH; -+ { -+ /* We have to regard it as an error if we cannot find the -+ home directory. */ -+ retval = GLOB_NOMATCH; -+ goto out; -+ } - } - } -+#endif /* !WINDOWS32 */ - } --# endif /* Not Amiga && not WINDOWS32. */ - } --#endif /* Not VMS. */ - - /* Now test whether we looked for "~" or "~NAME". In this case we - can give the answer now. */ -@@ -980,19 +1007,18 @@ glob (const char *pattern, int flags, in - size_t newcount = pglob->gl_pathc + pglob->gl_offs; - char **new_gl_pathv; - -- if (newcount > UINTPTR_MAX - (1 + 1) -- || newcount + 1 + 1 > ~((size_t) 0) / sizeof (char *)) -+ if (newcount > SIZE_MAX / sizeof (char *) - 2) - { - nospace: - free (pglob->gl_pathv); - pglob->gl_pathv = NULL; - pglob->gl_pathc = 0; -- return GLOB_NOSPACE; -+ retval = GLOB_NOSPACE; -+ goto out; - } - -- new_gl_pathv -- = (char **) realloc (pglob->gl_pathv, -- (newcount + 1 + 1) * sizeof (char *)); -+ new_gl_pathv = realloc (pglob->gl_pathv, -+ (newcount + 2) * sizeof (char *)); - if (new_gl_pathv == NULL) - goto nospace; - pglob->gl_pathv = new_gl_pathv; -@@ -1006,12 +1032,19 @@ glob (const char *pattern, int flags, in - p = mempcpy (pglob->gl_pathv[newcount], dirname, dirlen); - p[0] = '/'; - p[1] = '\0'; -+ if (__glibc_unlikely (malloc_dirname)) -+ free (dirname); - } - else - { -- pglob->gl_pathv[newcount] = strdup (dirname); -- if (pglob->gl_pathv[newcount] == NULL) -- goto nospace; -+ if (__glibc_unlikely (malloc_dirname)) -+ pglob->gl_pathv[newcount] = dirname; -+ else -+ { -+ pglob->gl_pathv[newcount] = strdup (dirname); -+ if (pglob->gl_pathv[newcount] == NULL) -+ goto nospace; -+ } - } - pglob->gl_pathv[++newcount] = NULL; - ++pglob->gl_pathc; -@@ -1021,7 +1054,8 @@ glob (const char *pattern, int flags, in - } - - /* Not found. */ -- return GLOB_NOMATCH; -+ retval = GLOB_NOMATCH; -+ goto out; - } - - meta = __glob_pattern_type (dirname, !(flags & GLOB_NOESCAPE)); -@@ -1067,7 +1101,10 @@ glob (const char *pattern, int flags, in - if (status != 0) - { - if ((flags & GLOB_NOCHECK) == 0 || status != GLOB_NOMATCH) -- return status; -+ { -+ retval = status; -+ goto out; -+ } - goto no_matches; - } - -@@ -1078,19 +1115,6 @@ glob (const char *pattern, int flags, in - { - size_t old_pathc; - --#ifdef SHELL -- { -- /* Make globbing interruptible in the bash shell. */ -- extern int interrupt_state; -- -- if (interrupt_state) -- { -- globfree (&dirs); -- return GLOB_ABORTED; -- } -- } --#endif /* SHELL. */ -- - old_pathc = pglob->gl_pathc; - status = glob_in_dir (filename, dirs.gl_pathv[i], - ((flags | GLOB_APPEND) -@@ -1105,7 +1129,8 @@ glob (const char *pattern, int flags, in - globfree (&dirs); - globfree (pglob); - pglob->gl_pathc = 0; -- return status; -+ retval = status; -+ goto out; - } - - /* Stick the directory on the front of each name. */ -@@ -1116,13 +1141,14 @@ glob (const char *pattern, int flags, in - globfree (&dirs); - globfree (pglob); - pglob->gl_pathc = 0; -- return GLOB_NOSPACE; -+ retval = GLOB_NOSPACE; -+ goto out; - } - } - - flags |= GLOB_MAGCHAR; - -- /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls. -+ /* We have ignored the GLOB_NOCHECK flag in the 'glob_in_dir' calls. - But if we have not found any matching entry and the GLOB_NOCHECK - flag was set we must return the input pattern itself. */ - if (pglob->gl_pathc + pglob->gl_offs == oldcount) -@@ -1134,28 +1160,28 @@ glob (const char *pattern, int flags, in - size_t newcount = pglob->gl_pathc + pglob->gl_offs; - char **new_gl_pathv; - -- if (newcount > UINTPTR_MAX - 2 -- || newcount + 2 > ~((size_t) 0) / sizeof (char *)) -+ if (newcount > SIZE_MAX / sizeof (char *) - 2) - { - nospace2: - globfree (&dirs); -- return GLOB_NOSPACE; -+ retval = GLOB_NOSPACE; -+ goto out; - } - -- new_gl_pathv = (char **) realloc (pglob->gl_pathv, -- (newcount + 2) -- * sizeof (char *)); -+ new_gl_pathv = realloc (pglob->gl_pathv, -+ (newcount + 2) * sizeof (char *)); - if (new_gl_pathv == NULL) - goto nospace2; - pglob->gl_pathv = new_gl_pathv; - -- pglob->gl_pathv[newcount] = __strdup (pattern); -+ pglob->gl_pathv[newcount] = strdup (pattern); - if (pglob->gl_pathv[newcount] == NULL) - { - globfree (&dirs); - globfree (pglob); - pglob->gl_pathc = 0; -- return GLOB_NOSPACE; -+ retval = GLOB_NOSPACE; -+ goto out; - } - - ++pglob->gl_pathc; -@@ -1167,7 +1193,8 @@ glob (const char *pattern, int flags, in - else - { - globfree (&dirs); -- return GLOB_NOMATCH; -+ retval = GLOB_NOMATCH; -+ goto out; - } - } - -@@ -1213,7 +1240,8 @@ glob (const char *pattern, int flags, in - flags = orig_flags; - goto no_matches; - } -- return status; -+ retval = status; -+ goto out; - } - - if (dirlen > 0) -@@ -1225,7 +1253,8 @@ glob (const char *pattern, int flags, in - { - globfree (pglob); - pglob->gl_pathc = 0; -- return GLOB_NOSPACE; -+ retval = GLOB_NOSPACE; -+ goto out; - } - } - } -@@ -1250,7 +1279,8 @@ glob (const char *pattern, int flags, in - { - globfree (pglob); - pglob->gl_pathc = 0; -- return GLOB_NOSPACE; -+ retval = GLOB_NOSPACE; -+ goto out; - } - strcpy (&new[len - 2], "/"); - pglob->gl_pathv[i] = new; -@@ -1276,32 +1306,12 @@ libc_hidden_def (glob) - #endif - - --#if !defined _LIBC || !defined GLOB_ONLY_P -- --/* Free storage allocated in PGLOB by a previous `glob' call. */ --void --globfree (glob_t *pglob) --{ -- if (pglob->gl_pathv != NULL) -- { -- size_t i; -- for (i = 0; i < pglob->gl_pathc; ++i) -- free (pglob->gl_pathv[pglob->gl_offs + i]); -- free (pglob->gl_pathv); -- pglob->gl_pathv = NULL; -- } --} --#if defined _LIBC && !defined globfree --libc_hidden_def (globfree) --#endif -- -- - /* Do a collated comparison of A and B. */ - static int - collated_compare (const void *a, const void *b) - { -- const char *const s1 = *(const char *const * const) a; -- const char *const s2 = *(const char *const * const) b; -+ char *const *ps1 = a; char *s1 = *ps1; -+ char *const *ps2 = b; char *s2 = *ps2; - - if (s1 == s2) - return 0; -@@ -1322,28 +1332,24 @@ prefix_array (const char *dirname, char - { - size_t i; - size_t dirlen = strlen (dirname); --#if defined __MSDOS__ || defined WINDOWS32 -- int sep_char = '/'; --# define DIRSEP_CHAR sep_char --#else --# define DIRSEP_CHAR '/' --#endif -+ char dirsep_char = '/'; - - if (dirlen == 1 && dirname[0] == '/') - /* DIRNAME is just "/", so normal prepending would get us "//foo". - We want "/foo" instead, so don't prepend any chars from DIRNAME. */ - dirlen = 0; -+ - #if defined __MSDOS__ || defined WINDOWS32 -- else if (dirlen > 1) -+ if (dirlen > 1) - { - if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':') - /* DIRNAME is "d:/". Don't prepend the slash from DIRNAME. */ - --dirlen; - else if (dirname[dirlen - 1] == ':') - { -- /* DIRNAME is "d:". Use `:' instead of `/'. */ -+ /* DIRNAME is "d:". Use ':' instead of '/'. */ - --dirlen; -- sep_char = ':'; -+ dirsep_char = ':'; - } - } - #endif -@@ -1351,7 +1357,7 @@ prefix_array (const char *dirname, char - for (i = 0; i < n; ++i) - { - size_t eltlen = strlen (array[i]) + 1; -- char *new = (char *) malloc (dirlen + 1 + eltlen); -+ char *new = malloc (dirlen + 1 + eltlen); - if (new == NULL) - { - while (i > 0) -@@ -1361,7 +1367,7 @@ prefix_array (const char *dirname, char - - { - char *endp = mempcpy (new, dirname, dirlen); -- *endp++ = DIRSEP_CHAR; -+ *endp++ = dirsep_char; - mempcpy (endp, array[i], eltlen); - } - free (array[i]); -@@ -1371,103 +1377,57 @@ prefix_array (const char *dirname, char - return 0; - } - -- --/* We must not compile this function twice. */ --#if !defined _LIBC || !defined NO_GLOB_PATTERN_P --int --__glob_pattern_type (const char *pattern, int quote) --{ -- const char *p; -- int ret = 0; -- -- for (p = pattern; *p != '\0'; ++p) -- switch (*p) -- { -- case '?': -- case '*': -- return 1; -- -- case '\\': -- if (quote) -- { -- if (p[1] != '\0') -- ++p; -- ret |= 2; -- } -- break; -- -- case '[': -- ret |= 4; -- break; -- -- case ']': -- if (ret & 4) -- return 1; -- break; -- } -- -- return ret; --} -- --/* Return nonzero if PATTERN contains any metacharacters. -- Metacharacters can be quoted with backslashes if QUOTE is nonzero. */ --int --__glob_pattern_p (const char *pattern, int quote) --{ -- return __glob_pattern_type (pattern, quote) == 1; --} --# ifdef _LIBC --weak_alias (__glob_pattern_p, glob_pattern_p) --# endif --#endif -- --#endif /* !GLOB_ONLY_P */ -- -- - /* We put this in a separate function mainly to allow the memory - allocated with alloca to be recycled. */ --#if !defined _LIBC || !defined GLOB_ONLY_P - static int - __attribute_noinline__ --link_exists2_p (const char *dir, size_t dirlen, const char *fname, -- glob_t *pglob --# ifndef _LIBC -- , int flags -+link_stat (const char *dir, size_t dirlen, const char *fname, -+ glob_t *pglob -+# if !defined _LIBC && !HAVE_FSTATAT -+ , int flags - # endif -- ) -+ ) - { - size_t fnamelen = strlen (fname); -- char *fullname = (char *) __alloca (dirlen + 1 + fnamelen + 1); -+ char *fullname = __alloca (dirlen + 1 + fnamelen + 1); - struct stat st; --# ifndef _LIBC -- struct_stat64 st64; --# endif - - mempcpy (mempcpy (mempcpy (fullname, dir, dirlen), "/", 1), - fname, fnamelen + 1); - --# ifdef _LIBC -- return (*pglob->gl_stat) (fullname, &st) == 0; --# else -- return ((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0) -- ? (*pglob->gl_stat) (fullname, &st) -- : __stat64 (fullname, &st64)) == 0); -+# if !defined _LIBC && !HAVE_FSTATAT -+ if (__builtin_expect ((flags & GLOB_ALTDIRFUNC) == 0, 1)) -+ { -+ struct_stat64 st64; -+ return __stat64 (fullname, &st64); -+ } - # endif -+ return (*pglob->gl_stat) (fullname, &st); - } --# ifdef _LIBC --# define link_exists_p(dfd, dirname, dirnamelen, fname, pglob, flags) \ -- (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0) \ -- ? link_exists2_p (dirname, dirnamelen, fname, pglob) \ -- : ({ struct stat64 st64; \ -- __fxstatat64 (_STAT_VER, dfd, fname, &st64, 0) == 0; })) -+ -+/* Return true if DIR/FNAME exists. */ -+static int -+link_exists_p (int dfd, const char *dir, size_t dirlen, const char *fname, -+ glob_t *pglob, int flags) -+{ -+ int status; -+# if defined _LIBC || HAVE_FSTATAT -+ if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)) -+ status = link_stat (dir, dirlen, fname, pglob); -+ else -+ { -+ /* dfd cannot be -1 here, because dirfd never returns -1 on -+ glibc, or on hosts that have fstatat. */ -+ struct_stat64 st64; -+ status = __fxstatat64 (_STAT_VER, dfd, fname, &st64, 0); -+ } - # else --# define link_exists_p(dfd, dirname, dirnamelen, fname, pglob, flags) \ -- link_exists2_p (dirname, dirnamelen, fname, pglob, flags) -+ status = link_stat (dir, dirlen, fname, pglob, flags); - # endif --#endif -- -+ return status == 0 || errno == EOVERFLOW; -+} - --/* Like `glob', but PATTERN is a final pathname component, -+/* Like 'glob', but PATTERN is a final pathname component, - and matches are searched for in DIRECTORY. - The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done. - The GLOB_APPEND flag is assumed to be set (always appends). */ -@@ -1478,25 +1438,25 @@ glob_in_dir (const char *pattern, const - { - size_t dirlen = strlen (directory); - void *stream = NULL; -- struct globnames -- { -- struct globnames *next; -- size_t count; -- char *name[64]; -- }; --#define INITIAL_COUNT sizeof (init_names.name) / sizeof (init_names.name[0]) -- struct globnames init_names; -- struct globnames *names = &init_names; -- struct globnames *names_alloca = &init_names; -+# define GLOBNAMES_MEMBERS(nnames) \ -+ struct globnames *next; size_t count; char *name[nnames]; -+ struct globnames { GLOBNAMES_MEMBERS (FLEXIBLE_ARRAY_MEMBER) }; -+ struct { GLOBNAMES_MEMBERS (64) } init_names_buf; -+ struct globnames *init_names = (struct globnames *) &init_names_buf; -+ struct globnames *names = init_names; -+ struct globnames *names_alloca = init_names; - size_t nfound = 0; - size_t cur = 0; - int meta; - int save; -+ int result; - -- alloca_used += sizeof (init_names); -+ alloca_used += sizeof init_names_buf; - -- init_names.next = NULL; -- init_names.count = INITIAL_COUNT; -+ init_names->next = NULL; -+ init_names->count = ((sizeof init_names_buf -+ - offsetof (struct globnames, name)) -+ / sizeof init_names->name[0]); - - meta = __glob_pattern_type (pattern, !(flags & GLOB_NOESCAPE)); - if (meta == 0 && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC))) -@@ -1516,14 +1476,16 @@ glob_in_dir (const char *pattern, const - struct_stat64 st64; - } ust; - size_t patlen = strlen (pattern); -- int alloca_fullname = __libc_use_alloca (alloca_used -- + dirlen + 1 + patlen + 1); -+ size_t fullsize; -+ bool alloca_fullname -+ = (! size_add_wrapv (dirlen + 1, patlen + 1, &fullsize) -+ && glob_use_alloca (alloca_used, fullsize)); - char *fullname; - if (alloca_fullname) -- fullname = alloca_account (dirlen + 1 + patlen + 1, alloca_used); -+ fullname = alloca_account (fullsize, alloca_used); - else - { -- fullname = malloc (dirlen + 1 + patlen + 1); -+ fullname = malloc (fullsize); - if (fullname == NULL) - return GLOB_NOSPACE; - } -@@ -1531,9 +1493,11 @@ glob_in_dir (const char *pattern, const - mempcpy (mempcpy (mempcpy (fullname, directory, dirlen), - "/", 1), - pattern, patlen + 1); -- if ((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0) -+ if (((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0) - ? (*pglob->gl_stat) (fullname, &ust.st) -- : __stat64 (fullname, &ust.st64)) == 0) -+ : __stat64 (fullname, &ust.st64)) -+ == 0) -+ || errno == EOVERFLOW) - /* We found this file to be existing. Now tell the rest - of the function to copy this name into the result. */ - flags |= GLOB_NOCHECK; -@@ -1555,16 +1519,10 @@ glob_in_dir (const char *pattern, const - } - else - { --#ifdef _LIBC - int dfd = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0) - ? -1 : dirfd ((DIR *) stream)); --#endif - int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) -- | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0) --#if defined _AMIGA || defined VMS -- | FNM_CASEFOLD --#endif -- ); -+ | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)); - flags |= GLOB_MAGCHAR; - - while (1) -@@ -1584,19 +1542,24 @@ glob_in_dir (const char *pattern, const - } - if (d.name == NULL) - break; -- if (d.skip_entry) -+ if (readdir_result_skip_entry (d)) - continue; - - /* If we shall match only directories use the information - provided by the dirent call if possible. */ -- if ((flags & GLOB_ONLYDIR) && !readdir_result_might_be_dir (d)) -- continue; -+ if (flags & GLOB_ONLYDIR) -+ switch (readdir_result_type (d)) -+ { -+ case DT_DIR: case DT_LNK: case DT_UNKNOWN: break; -+ default: continue; -+ } - - 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 (!readdir_result_might_be_symlink (d) -+ dirent_type type = readdir_result_type (d); -+ if (! (type == DT_LNK || type == DT_UNKNOWN) - || link_exists_p (dfd, directory, dirlen, d.name, - pglob, flags)) - { -@@ -1604,10 +1567,13 @@ glob_in_dir (const char *pattern, const - { - struct globnames *newnames; - size_t count = names->count * 2; -- size_t size = (sizeof (struct globnames) -- + ((count - INITIAL_COUNT) -- * sizeof (char *))); -- if (__libc_use_alloca (alloca_used + size)) -+ size_t nameoff = offsetof (struct globnames, name); -+ size_t size = FLEXSIZEOF (struct globnames, name, -+ count * sizeof (char *)); -+ if ((SIZE_MAX - nameoff) / 2 / sizeof (char *) -+ < names->count) -+ goto memory_error; -+ if (glob_use_alloca (alloca_used, size)) - newnames = names_alloca - = alloca_account (size, alloca_used); - else if ((newnames = malloc (size)) -@@ -1623,6 +1589,8 @@ glob_in_dir (const char *pattern, const - goto memory_error; - ++cur; - ++nfound; -+ if (SIZE_MAX - pglob->gl_offs <= nfound) -+ goto memory_error; - } - } - } -@@ -1633,29 +1601,27 @@ glob_in_dir (const char *pattern, const - { - size_t len = strlen (pattern); - nfound = 1; -- names->name[cur] = (char *) malloc (len + 1); -+ names->name[cur] = malloc (len + 1); - if (names->name[cur] == NULL) - goto memory_error; - *((char *) mempcpy (names->name[cur++], pattern, len)) = '\0'; - } - -- int result = GLOB_NOMATCH; -+ result = GLOB_NOMATCH; - if (nfound != 0) - { -+ char **new_gl_pathv; - result = 0; - -- if (pglob->gl_pathc > UINTPTR_MAX - pglob->gl_offs -- || pglob->gl_pathc + pglob->gl_offs > UINTPTR_MAX - nfound -- || pglob->gl_pathc + pglob->gl_offs + nfound > UINTPTR_MAX - 1 -- || (pglob->gl_pathc + pglob->gl_offs + nfound + 1 -- > UINTPTR_MAX / sizeof (char *))) -+ if (SIZE_MAX / sizeof (char *) - pglob->gl_pathc -+ < pglob->gl_offs + nfound + 1) - goto memory_error; - -- char **new_gl_pathv; - new_gl_pathv -- = (char **) realloc (pglob->gl_pathv, -- (pglob->gl_pathc + pglob->gl_offs + nfound + 1) -- * sizeof (char *)); -+ = realloc (pglob->gl_pathv, -+ (pglob->gl_pathc + pglob->gl_offs + nfound + 1) -+ * sizeof (char *)); -+ - if (new_gl_pathv == NULL) - { - memory_error: -@@ -1671,7 +1637,7 @@ glob_in_dir (const char *pattern, const - and this is the block assigned to OLD here. */ - if (names == NULL) - { -- assert (old == &init_names); -+ assert (old == init_names); - break; - } - cur = names->count; -@@ -1697,7 +1663,7 @@ glob_in_dir (const char *pattern, const - and this is the block assigned to OLD here. */ - if (names == NULL) - { -- assert (old == &init_names); -+ assert (old == init_names); - break; - } - cur = names->count; -Index: glibc-2.26/posix/glob64.c -=================================================================== ---- glibc-2.26.orig/posix/glob64.c -+++ glibc-2.26/posix/glob64.c -@@ -43,10 +43,4 @@ glob64 (const char *pattern, int flags, - } - libc_hidden_def (glob64) - --void --globfree64 (glob64_t *pglob) --{ --} --libc_hidden_def (globfree64) -- - stub_warning (glob64) -Index: glibc-2.26/posix/glob_internal.h -=================================================================== ---- /dev/null -+++ glibc-2.26/posix/glob_internal.h -@@ -0,0 +1,57 @@ -+/* Shared definition for glob and glob_pattern_p. -+ 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 -+ . */ -+ -+#ifndef GLOB_INTERNAL_H -+# define GLOB_INTERNAL_H -+ -+static inline int -+__glob_pattern_type (const char *pattern, int quote) -+{ -+ const char *p; -+ int ret = 0; -+ -+ for (p = pattern; *p != '\0'; ++p) -+ switch (*p) -+ { -+ case '?': -+ case '*': -+ return 1; -+ -+ case '\\': -+ if (quote) -+ { -+ if (p[1] != '\0') -+ ++p; -+ ret |= 2; -+ } -+ break; -+ -+ case '[': -+ ret |= 4; -+ break; -+ -+ case ']': -+ if (ret & 4) -+ return 1; -+ break; -+ } -+ -+ return ret; -+} -+ -+#endif /* GLOB_INTERNAL_H */ -Index: glibc-2.26/posix/glob_pattern_p.c -=================================================================== ---- /dev/null -+++ glibc-2.26/posix/glob_pattern_p.c -@@ -0,0 +1,33 @@ -+/* Return nonzero if PATTERN contains any metacharacters. -+ 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 -+ . */ -+ -+#ifndef _LIBC -+# include -+#endif -+ -+#include -+#include "glob_internal.h" -+ -+/* Return nonzero if PATTERN contains any metacharacters. -+ Metacharacters can be quoted with backslashes if QUOTE is nonzero. */ -+int -+__glob_pattern_p (const char *pattern, int quote) -+{ -+ return __glob_pattern_type (pattern, quote) == 1; -+} -+weak_alias (__glob_pattern_p, glob_pattern_p) -Index: glibc-2.26/posix/globfree.c -=================================================================== ---- /dev/null -+++ glibc-2.26/posix/globfree.c -@@ -0,0 +1,41 @@ -+/* Frees the dynamically allocated storage from an earlier call to glob. -+ 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 -+ . */ -+ -+#ifndef _LIBC -+# include -+#endif -+ -+#include -+#include -+ -+/* Free storage allocated in PGLOB by a previous `glob' call. */ -+void -+globfree (glob_t *pglob) -+{ -+ if (pglob->gl_pathv != NULL) -+ { -+ size_t i; -+ for (i = 0; i < pglob->gl_pathc; ++i) -+ free (pglob->gl_pathv[pglob->gl_offs + i]); -+ free (pglob->gl_pathv); -+ pglob->gl_pathv = NULL; -+ } -+} -+#ifndef globfree -+libc_hidden_def (globfree) -+#endif -Index: glibc-2.26/posix/globfree64.c -=================================================================== ---- /dev/null -+++ glibc-2.26/posix/globfree64.c -@@ -0,0 +1,31 @@ -+/* Frees the dynamically allocated storage from an earlier call to glob. -+ 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 -+ . */ -+ -+#ifndef _LIBC -+# include -+#endif -+ -+#include -+#include -+ -+/* Free storage allocated in PGLOB by a previous `glob' call. */ -+void -+globfree64 (glob64_t *pglob) -+{ -+} -+libc_hidden_def (globfree64) -Index: glibc-2.26/posix/tst-glob-tilde.c -=================================================================== ---- /dev/null -+++ glibc-2.26/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 -Index: glibc-2.26/sysdeps/gnu/glob64.c -=================================================================== ---- glibc-2.26.orig/sysdeps/gnu/glob64.c -+++ glibc-2.26/sysdeps/gnu/glob64.c -@@ -15,11 +15,8 @@ - #undef __stat - #define __stat(file, buf) __xstat64 (_STAT_VER, file, buf) - --#define NO_GLOB_PATTERN_P 1 -- - #define COMPILE_GLOB64 1 - - #include - - libc_hidden_def (glob64) --libc_hidden_def (globfree64) -Index: glibc-2.26/sysdeps/gnu/globfree64.c -=================================================================== ---- /dev/null -+++ glibc-2.26/sysdeps/gnu/globfree64.c -@@ -0,0 +1,10 @@ -+#include -+#include -+#include -+ -+#define glob_t glob64_t -+#define globfree(pglob) globfree64 (pglob) -+ -+#include -+ -+libc_hidden_def (globfree64) -Index: glibc-2.26/sysdeps/unix/sysv/linux/Makefile -=================================================================== ---- glibc-2.26.orig/sysdeps/unix/sysv/linux/Makefile -+++ glibc-2.26/sysdeps/unix/sysv/linux/Makefile -@@ -166,7 +166,7 @@ endif - ifeq ($(subdir),posix) - sysdep_headers += bits/initspin.h - --sysdep_routines += sched_getcpu -+sysdep_routines += sched_getcpu oldglob - - tests += tst-affinity tst-affinity-pid - -Index: glibc-2.26/sysdeps/unix/sysv/linux/alpha/glob.c -=================================================================== ---- glibc-2.26.orig/sysdeps/unix/sysv/linux/alpha/glob.c -+++ glibc-2.26/sysdeps/unix/sysv/linux/alpha/glob.c -@@ -42,10 +42,6 @@ extern void __new_globfree (glob_t *__pg - #undef globfree64 - - versioned_symbol (libc, __new_glob, glob, GLIBC_2_1); --versioned_symbol (libc, __new_globfree, globfree, GLIBC_2_1); - libc_hidden_ver (__new_glob, glob) --libc_hidden_ver (__new_globfree, globfree) - - weak_alias (__new_glob, glob64) --weak_alias (__new_globfree, globfree64) --libc_hidden_ver (__new_globfree, globfree64) -Index: glibc-2.26/sysdeps/unix/sysv/linux/alpha/globfree.c -=================================================================== ---- /dev/null -+++ glibc-2.26/sysdeps/unix/sysv/linux/alpha/globfree.c -@@ -0,0 +1,37 @@ -+/* Compat globfree. Linux/alpha version. -+ 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 -+ . */ -+ -+#define globfree64 __no_globfree64_decl -+#include -+#include -+#include -+ -+#define globfree(pglob) \ -+ __new_globfree (pglob) -+ -+extern void __new_globfree (glob_t *__pglob); -+ -+#include -+ -+#undef globfree64 -+ -+versioned_symbol (libc, __new_globfree, globfree, GLIBC_2_1); -+libc_hidden_ver (__new_globfree, globfree) -+ -+weak_alias (__new_globfree, globfree64) -+libc_hidden_ver (__new_globfree, globfree64) -Index: glibc-2.26/sysdeps/unix/sysv/linux/i386/glob64.c -=================================================================== ---- glibc-2.26.orig/sysdeps/unix/sysv/linux/i386/glob64.c -+++ glibc-2.26/sysdeps/unix/sysv/linux/i386/glob64.c -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - - #define dirent dirent64 - #define __readdir(dirp) __readdir64 (dirp) -@@ -33,44 +34,9 @@ - #undef __stat - #define __stat(file, buf) __xstat64 (_STAT_VER, file, buf) - --#define NO_GLOB_PATTERN_P 1 -- - #define COMPILE_GLOB64 1 - - #include - --#include "shlib-compat.h" -- --libc_hidden_def (globfree64) -- - versioned_symbol (libc, __glob64, glob64, GLIBC_2_2); - libc_hidden_ver (__glob64, glob64) -- --#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2) -- --#include -- --int __old_glob64 (const char *__pattern, int __flags, -- int (*__errfunc) (const char *, int), -- glob64_t *__pglob); -- --#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 -- --#define GLOB_ONLY_P 1 -- --#include -- --compat_symbol (libc, __old_glob64, glob64, GLIBC_2_1); --#endif -Index: glibc-2.26/sysdeps/unix/sysv/linux/mips/mips64/n64/globfree64.c -=================================================================== ---- /dev/null -+++ glibc-2.26/sysdeps/unix/sysv/linux/mips/mips64/n64/globfree64.c -@@ -0,0 +1 @@ -+/* glob64 is in globfree64.c */ -Index: glibc-2.26/sysdeps/unix/sysv/linux/oldglob.c -=================================================================== ---- /dev/null -+++ glibc-2.26/sysdeps/unix/sysv/linux/oldglob.c -@@ -0,0 +1,42 @@ -+#include -+ -+#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2) -+ -+#include -+#include -+#include -+ -+#include -+ -+int __old_glob64 (const char *__pattern, int __flags, -+ int (*__errfunc) (const char *, int), -+ glob64_t *__pglob); -+libc_hidden_proto (__old_glob64); -+ -+#define dirent __old_dirent64 -+#define GL_READDIR(pglob, stream) \ -+ ((struct __old_dirent64 *) (pglob)->gl_readdir (stream)) -+#undef __readdir -+#define __readdir(dirp) __old_readdir64 (dirp) -+ -+#define glob_t glob64_t -+#define glob(pattern, flags, errfunc, pglob) \ -+ __old_glob64 (pattern, flags, errfunc, pglob) -+#define globfree(pglob) globfree64(pglob) -+ -+#define convert_dirent __old_convert_dirent -+#define glob_in_dir __old_glob_in_dir -+ -+#undef stat -+#define stat stat64 -+#undef __stat -+#define __stat(file, buf) __xstat64 (_STAT_VER, file, buf) -+ -+#define GLOB_ATTRIBUTE attribute_compat_text_section -+ -+#include -+ -+libc_hidden_def (__old_glob64); -+ -+compat_symbol (libc, __old_glob64, glob64, GLIBC_2_1); -+#endif -Index: glibc-2.26/sysdeps/unix/sysv/linux/wordsize-64/globfree64.c -=================================================================== ---- /dev/null -+++ glibc-2.26/sysdeps/unix/sysv/linux/wordsize-64/globfree64.c -@@ -0,0 +1,2 @@ -+/* This file is here so sysdeps/gnu/glob64.c doesn't take precedence. */ -+#include -Index: glibc-2.26/sysdeps/unix/sysv/linux/x86_64/x32/globfree.c -=================================================================== ---- /dev/null -+++ glibc-2.26/sysdeps/unix/sysv/linux/x86_64/x32/globfree.c -@@ -0,0 +1 @@ -+#include -Index: glibc-2.26/sysdeps/wordsize-64/glob.c -=================================================================== ---- glibc-2.26.orig/sysdeps/wordsize-64/glob.c -+++ glibc-2.26/sysdeps/wordsize-64/glob.c -@@ -4,5 +4,3 @@ - #undef glob64 - #undef globfree64 - weak_alias (glob, glob64) --weak_alias (globfree, globfree64) --libc_hidden_ver (globfree, globfree64) -Index: glibc-2.26/sysdeps/wordsize-64/globfree.c -=================================================================== ---- /dev/null -+++ glibc-2.26/sysdeps/wordsize-64/globfree.c -@@ -0,0 +1,5 @@ -+#define globfree64 __no_globfree64_decl -+#include -+#undef globfree64 -+weak_alias (globfree, globfree64) -+libc_hidden_ver (globfree, globfree64) -Index: glibc-2.26/sysdeps/wordsize-64/globfree64.c -=================================================================== ---- /dev/null -+++ glibc-2.26/sysdeps/wordsize-64/globfree64.c -@@ -0,0 +1 @@ -+/* globfree64 is in globfree.c */ diff --git a/glob64-s390.patch b/glob64-s390.patch deleted file mode 100644 index 7278589..0000000 --- a/glob64-s390.patch +++ /dev/null @@ -1,6 +0,0 @@ -Index: glibc-2.26/sysdeps/unix/sysv/linux/s390/s390-32/oldglob.c -=================================================================== ---- /dev/null -+++ glibc-2.26/sysdeps/unix/sysv/linux/s390/s390-32/oldglob.c -@@ -0,0 +1 @@ -+/* No compat glob64 on s390. */ diff --git a/iconv-reset-input-buffer.patch b/iconv-reset-input-buffer.patch index 27abf73..ef336ec 100644 --- a/iconv-reset-input-buffer.patch +++ b/iconv-reset-input-buffer.patch @@ -13,13 +13,13 @@ Fix iconv buffer handling with IGNORE error handler (bug #18830) * iconv/Makefile (tests): Add tst-iconv7. * iconv/tst-iconv7.c: New file. -Index: glibc-2.22/iconv/Makefile +Index: glibc-2.27/iconv/Makefile =================================================================== ---- glibc-2.22.orig/iconv/Makefile -+++ glibc-2.22/iconv/Makefile -@@ -42,7 +42,8 @@ CFLAGS-charmap.c = -DCHARMAP_PATH='"$(i1 - CFLAGS-linereader.c = -DNO_TRANSLITERATION - CFLAGS-simple-hash.c = -I../locale +--- glibc-2.27.orig/iconv/Makefile ++++ glibc-2.27/iconv/Makefile +@@ -43,7 +43,8 @@ CFLAGS-charmap.c += -DCHARMAP_PATH='"$(i + CFLAGS-linereader.c += -DNO_TRANSLITERATION + CFLAGS-simple-hash.c += -I../locale -tests = tst-iconv1 tst-iconv2 tst-iconv3 tst-iconv4 tst-iconv5 tst-iconv6 +tests = tst-iconv1 tst-iconv2 tst-iconv3 tst-iconv4 tst-iconv5 tst-iconv6 \ @@ -27,10 +27,10 @@ Index: glibc-2.22/iconv/Makefile others = iconv_prog iconvconfig install-others-programs = $(inst_bindir)/iconv -Index: glibc-2.22/iconv/gconv_simple.c +Index: glibc-2.27/iconv/gconv_simple.c =================================================================== ---- glibc-2.22.orig/iconv/gconv_simple.c -+++ glibc-2.22/iconv/gconv_simple.c +--- glibc-2.27.orig/iconv/gconv_simple.c ++++ glibc-2.27/iconv/gconv_simple.c @@ -76,7 +76,7 @@ __attribute ((always_inline)) internal_ucs4_loop (struct __gconv_step *step, struct __gconv_step_data *step_data, @@ -147,10 +147,10 @@ Index: glibc-2.22/iconv/gconv_simple.c size_t *irreversible) { mbstate_t *state = step_data->__statep; -Index: glibc-2.22/iconv/skeleton.c +Index: glibc-2.27/iconv/skeleton.c =================================================================== ---- glibc-2.22.orig/iconv/skeleton.c -+++ glibc-2.22/iconv/skeleton.c +--- glibc-2.27.orig/iconv/skeleton.c ++++ glibc-2.27/iconv/skeleton.c @@ -597,6 +597,10 @@ FUNCTION_NAME (struct __gconv_step *step inptr = *inptrp; /* The outbuf buffer is empty. */ @@ -224,10 +224,10 @@ Index: glibc-2.22/iconv/skeleton.c /* Change the status. */ status = result; } -Index: glibc-2.22/iconv/tst-iconv7.c +Index: glibc-2.27/iconv/tst-iconv7.c =================================================================== --- /dev/null -+++ glibc-2.22/iconv/tst-iconv7.c ++++ glibc-2.27/iconv/tst-iconv7.c @@ -0,0 +1,68 @@ +/* Test iconv buffer handling with the IGNORE error handler. + Copyright (C) 2015 Free Software Foundation, Inc. @@ -297,10 +297,10 @@ Index: glibc-2.22/iconv/tst-iconv7.c + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" -Index: glibc-2.23.90/sysdeps/s390/multiarch/gconv_simple.c +Index: glibc-2.27/sysdeps/s390/multiarch/gconv_simple.c =================================================================== ---- glibc-2.23.90.orig/sysdeps/s390/multiarch/gconv_simple.c -+++ glibc-2.23.90/sysdeps/s390/multiarch/gconv_simple.c +--- glibc-2.27.orig/sysdeps/s390/multiarch/gconv_simple.c ++++ glibc-2.27/sysdeps/s390/multiarch/gconv_simple.c @@ -403,7 +403,7 @@ ICONV_VX_NAME (internal_ucs4le_loop) (st const unsigned char **inptrp, const unsigned char *inend, diff --git a/ld-so-hwcap-x86-64.patch b/ld-so-hwcap-x86-64.patch deleted file mode 100644 index b99547a..0000000 --- a/ld-so-hwcap-x86-64.patch +++ /dev/null @@ -1,190 +0,0 @@ -2017-09-11 H.J. Lu - - [BZ #22093] - * sysdeps/x86/cpu-features.c (init_cpu_features): Initialize - GLRO(dl_hwcap) to HWCAP_X86_64 for x86-64. - * sysdeps/x86/dl-hwcap.h (HWCAP_COUNT): Updated. - (HWCAP_IMPORTANT): Likewise. - (HWCAP_X86_64): New enum. - (HWCAP_X86_AVX512_1): Updated. - * sysdeps/x86/dl-procinfo.c (_dl_x86_hwcap_flags): Add "x86_64". - * sysdeps/x86_64/Makefile (tests): Add tst-x86_64-1. - (modules-names): Add x86_64/tst-x86_64mod-1. - (LDFLAGS-tst-x86_64mod-1.so): New. - ($(objpfx)tst-x86_64-1): Likewise. - ($(objpfx)x86_64/tst-x86_64mod-1.os): Likewise. - (tst-x86_64-1-clean): Likewise. - * sysdeps/x86_64/tst-x86_64-1.c: New file. - * sysdeps/x86_64/tst-x86_64mod-1.c: Likewise. - -Index: glibc-2.26/sysdeps/x86/cpu-features.c -=================================================================== ---- glibc-2.26.orig/sysdeps/x86/cpu-features.c -+++ glibc-2.26/sysdeps/x86/cpu-features.c -@@ -336,7 +336,6 @@ no_cpuid: - - /* Reuse dl_platform, dl_hwcap and dl_hwcap_mask for x86. */ - GLRO(dl_platform) = NULL; -- GLRO(dl_hwcap) = 0; - #if !HAVE_TUNABLES && defined SHARED - /* The glibc.tune.hwcap_mask tunable is initialized already, so no need to do - this. */ -@@ -344,6 +343,7 @@ no_cpuid: - #endif - - #ifdef __x86_64__ -+ GLRO(dl_hwcap) = HWCAP_X86_64; - if (cpu_features->kind == arch_kind_intel) - { - if (CPU_FEATURES_ARCH_P (cpu_features, AVX512F_Usable) -@@ -374,6 +374,7 @@ no_cpuid: - GLRO(dl_platform) = "haswell"; - } - #else -+ GLRO(dl_hwcap) = 0; - if (CPU_FEATURES_CPU_P (cpu_features, SSE2)) - GLRO(dl_hwcap) |= HWCAP_X86_SSE2; - -Index: glibc-2.26/sysdeps/x86/dl-hwcap.h -=================================================================== ---- glibc-2.26.orig/sysdeps/x86/dl-hwcap.h -+++ glibc-2.26/sysdeps/x86/dl-hwcap.h -@@ -24,15 +24,16 @@ - # define HWCAP_PLATFORMS_START 0 - # define HWCAP_PLATFORMS_COUNT 4 - # define HWCAP_START 0 --# define HWCAP_COUNT 2 --# define HWCAP_IMPORTANT (HWCAP_X86_SSE2 | HWCAP_X86_AVX512_1) -+# define HWCAP_COUNT 3 -+# define HWCAP_IMPORTANT \ -+ (HWCAP_X86_SSE2 | HWCAP_X86_64 | HWCAP_X86_AVX512_1) - #elif defined __x86_64__ - /* For 64 bit, only cover x86-64 platforms and capabilities. */ - # define HWCAP_PLATFORMS_START 2 - # define HWCAP_PLATFORMS_COUNT 4 - # define HWCAP_START 1 --# define HWCAP_COUNT 2 --# define HWCAP_IMPORTANT (HWCAP_X86_AVX512_1) -+# define HWCAP_COUNT 3 -+# define HWCAP_IMPORTANT (HWCAP_X86_64 | HWCAP_X86_AVX512_1) - #else - /* For 32 bit, only cover i586, i686 and SSE2. */ - # define HWCAP_PLATFORMS_START 0 -@@ -45,7 +46,8 @@ - enum - { - HWCAP_X86_SSE2 = 1 << 0, -- HWCAP_X86_AVX512_1 = 1 << 1 -+ HWCAP_X86_64 = 1 << 1, -+ HWCAP_X86_AVX512_1 = 1 << 2 - }; - - static inline const char * -Index: glibc-2.26/sysdeps/x86/dl-procinfo.c -=================================================================== ---- glibc-2.26.orig/sysdeps/x86/dl-procinfo.c -+++ glibc-2.26/sysdeps/x86/dl-procinfo.c -@@ -58,11 +58,11 @@ PROCINFO_CLASS struct cpu_features _dl_x - #if !defined PROCINFO_DECL && defined SHARED - ._dl_x86_hwcap_flags - #else --PROCINFO_CLASS const char _dl_x86_hwcap_flags[2][9] -+PROCINFO_CLASS const char _dl_x86_hwcap_flags[3][9] - #endif - #ifndef PROCINFO_DECL - = { -- "sse2", "avx512_1" -+ "sse2", "x86_64", "avx512_1" - } - #endif - #if !defined SHARED || defined PROCINFO_DECL -Index: glibc-2.26/sysdeps/x86_64/Makefile -=================================================================== ---- glibc-2.26.orig/sysdeps/x86_64/Makefile -+++ glibc-2.26/sysdeps/x86_64/Makefile -@@ -52,6 +52,12 @@ $(objpfx)tst-quad2pie: $(objpfx)tst-quad - CFLAGS-tst-quad1pie.c = $(PIE-ccflag) - CFLAGS-tst-quad2pie.c = $(PIE-ccflag) - -+tests += tst-x86_64-1 -+modules-names += x86_64/tst-x86_64mod-1 -+LDFLAGS-tst-x86_64mod-1.so = -Wl,-soname,tst-x86_64mod-1.so -+ -+$(objpfx)tst-x86_64-1: $(objpfx)x86_64/tst-x86_64mod-1.so -+ - tests += tst-audit3 tst-audit4 tst-audit5 tst-audit6 tst-audit7 \ - tst-audit10 tst-sse tst-avx tst-avx512 - test-extras += tst-audit4-aux tst-audit10-aux \ -@@ -122,3 +128,14 @@ endif - ifeq ($(subdir),csu) - gen-as-const-headers += tlsdesc.sym rtld-offsets.sym - endif -+ -+$(objpfx)x86_64/tst-x86_64mod-1.os: $(objpfx)tst-x86_64mod-1.os -+ $(make-target-directory) -+ rm -f $@ -+ ln $< $@ -+ -+do-tests-clean common-mostlyclean: tst-x86_64-1-clean -+ -+.PHONY: tst-x86_64-1-clean -+tst-x86_64-1-clean: -+ -rm -rf $(objpfx)x86_64 -Index: glibc-2.26/sysdeps/x86_64/tst-x86_64-1.c -=================================================================== ---- /dev/null -+++ glibc-2.26/sysdeps/x86_64/tst-x86_64-1.c -@@ -0,0 +1,26 @@ -+/* Test searching the "x86_64" directory for shared libraries. -+ 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 -+ . */ -+ -+extern void foo (void); -+ -+int -+main (void) -+{ -+ foo (); -+ return 0; -+} -Index: glibc-2.26/sysdeps/x86_64/tst-x86_64mod-1.c -=================================================================== ---- /dev/null -+++ glibc-2.26/sysdeps/x86_64/tst-x86_64mod-1.c -@@ -0,0 +1,22 @@ -+/* Test searching the "x86_64" directory for shared libraries. -+ 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 -+ . */ -+ -+void -+foo (void) -+{ -+} diff --git a/ldd-system-interp.patch b/ldd-system-interp.patch deleted file mode 100644 index 55d84ce..0000000 --- a/ldd-system-interp.patch +++ /dev/null @@ -1,41 +0,0 @@ -Never try to execute the file in ldd - -Executing a random file is never a good idea. Treat all arguments as if -they are invoked with __libc_enable_secure, and run them through the known -good dynamic linker. - - * elf/ldd.bash.in: Always run through the dynamic linker, even if - the file has its own interpreter. - -Index: glibc-2.19/elf/ldd.bash.in -=================================================================== ---- glibc-2.19.orig/elf/ldd.bash.in -+++ glibc-2.19/elf/ldd.bash.in -@@ -164,18 +164,6 @@ warning: you do not have execution permi - fi - done - case $ret in -- 0) -- # If the program exits with exit code 5, it means the process has been -- # invoked with __libc_enable_secure. Fall back to running it through -- # the dynamic linker. -- try_trace "$file" -- rc=$? -- if [ $rc = 5 ]; then -- try_trace "$RTLD" "$file" -- rc=$? -- fi -- [ $rc = 0 ] || result=1 -- ;; - 1) - # This can be a non-ELF binary or no binary at all. - nonelf "$file" || { -@@ -183,7 +171,7 @@ warning: you do not have execution permi - result=1 - } - ;; -- 2) -+ [02]) - try_trace "$RTLD" "$file" || result=1 - ;; - *) diff --git a/libpthread-compat-wrappers.patch b/libpthread-compat-wrappers.patch deleted file mode 100644 index 7203100..0000000 --- a/libpthread-compat-wrappers.patch +++ /dev/null @@ -1,120 +0,0 @@ -2017-08-09 Andreas Schwab - - [BZ #21041] - * sysdeps/unix/sysv/linux/s390/pt-longjmp.c: Update reference to - renamed alias. - -2017-08-08 Andreas Schwab - - [BZ #21041] - * nptl/pt-longjmp.c (longjmp, siglongjmp): Don't use IFUNC resolver. - * nptl/pt-system.c (system): Likewise. - -Index: glibc-2.26/nptl/pt-longjmp.c -=================================================================== ---- glibc-2.26.orig/nptl/pt-longjmp.c -+++ glibc-2.26/nptl/pt-longjmp.c -@@ -25,21 +25,14 @@ - symbol in libpthread, but the historical ABI requires it. For static - linking, there is no need to provide anything here--the libc version - will be linked in. For shared library ABI compatibility, there must be -- longjmp and siglongjmp symbols in libpthread.so; so we define them using -- IFUNC to redirect to the libc function. */ -+ longjmp and siglongjmp symbols in libpthread.so. - --#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_22) -- --# if HAVE_IFUNC -- --# undef INIT_ARCH --# define INIT_ARCH() --# define DEFINE_LONGJMP(name) libc_ifunc (name, &__libc_longjmp) -- --extern __typeof(longjmp) longjmp_ifunc; --extern __typeof(siglongjmp) siglongjmp_ifunc; -+ With an IFUNC resolver, it would be possible to avoid the indirection, -+ but the IFUNC resolver might run before the __libc_longjmp symbol has -+ been relocated, in which case the IFUNC resolver would not be able to -+ provide the correct address. */ - --# else /* !HAVE_IFUNC */ -+#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_22) - - static void __attribute__ ((noreturn, used)) - longjmp_compat (jmp_buf env, int val) -@@ -47,14 +40,10 @@ longjmp_compat (jmp_buf env, int val) - __libc_longjmp (env, val); - } - --# define DEFINE_LONGJMP(name) strong_alias (longjmp_compat, name) -- --# endif /* HAVE_IFUNC */ -- --DEFINE_LONGJMP (longjmp_ifunc) --compat_symbol (libpthread, longjmp_ifunc, longjmp, GLIBC_2_0); -+strong_alias (longjmp_compat, longjmp_alias) -+compat_symbol (libpthread, longjmp_alias, longjmp, GLIBC_2_0); - --strong_alias (longjmp_ifunc, siglongjmp_ifunc) --compat_symbol (libpthread, siglongjmp_ifunc, siglongjmp, GLIBC_2_0); -+strong_alias (longjmp_alias, siglongjmp_alias) -+compat_symbol (libpthread, siglongjmp_alias, siglongjmp, GLIBC_2_0); - - #endif -Index: glibc-2.26/nptl/pt-system.c -=================================================================== ---- glibc-2.26.orig/nptl/pt-system.c -+++ glibc-2.26/nptl/pt-system.c -@@ -25,29 +25,21 @@ - libpthread, but the historical ABI requires it. For static linking, - there is no need to provide anything here--the libc version will be - linked in. For shared library ABI compatibility, there must be a -- 'system' symbol in libpthread.so; so we define it using IFUNC to -- redirect to the libc function. */ -+ 'system' symbol in libpthread.so. - --#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_22) -- --# if HAVE_IFUNC -- --extern __typeof(system) system_ifunc; --# undef INIT_ARCH --# define INIT_ARCH() --libc_ifunc (system_ifunc, &__libc_system) -+ With an IFUNC resolver, it would be possible to avoid the indirection, -+ but the IFUNC resolver might run before the __libc_system symbol has -+ been relocated, in which case the IFUNC resolver would not be able to -+ provide the correct address. */ - --# else /* !HAVE_IFUNC */ -+#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_22) - - static int __attribute__ ((used)) - system_compat (const char *line) - { - return __libc_system (line); - } --strong_alias (system_compat, system_ifunc) -- --# endif /* HAVE_IFUNC */ -- --compat_symbol (libpthread, system_ifunc, system, GLIBC_2_0); -+strong_alias (system_compat, system_alias) -+compat_symbol (libpthread, system_alias, system, GLIBC_2_0); - - #endif -Index: glibc-2.26/sysdeps/unix/sysv/linux/s390/pt-longjmp.c -=================================================================== ---- glibc-2.26.orig/sysdeps/unix/sysv/linux/s390/pt-longjmp.c -+++ glibc-2.26/sysdeps/unix/sysv/linux/s390/pt-longjmp.c -@@ -26,8 +26,8 @@ - /* In glibc release 2.19 new versions of longjmp-functions were introduced, - but were reverted before 2.20. Thus both versions are the same function. */ - --strong_alias (longjmp_ifunc, __v2longjmp) -+strong_alias (longjmp_alias, __v2longjmp) - compat_symbol (libpthread, __v2longjmp, longjmp, GLIBC_2_19); --strong_alias (siglongjmp_ifunc, __v2siglongjmp) -+strong_alias (siglongjmp_alias, __v2siglongjmp) - compat_symbol (libpthread, __v2siglongjmp, siglongjmp, GLIBC_2_19); - #endif /* SHLIB_COMPAT (libpthread, GLIBC_2_19, GLIBC_2_20)) */ diff --git a/malloc-tcache-check-overflow.patch b/malloc-tcache-check-overflow.patch deleted file mode 100644 index 3d6fad5..0000000 --- a/malloc-tcache-check-overflow.patch +++ /dev/null @@ -1,21 +0,0 @@ -2017-11-30 Arjun Shankar - - [BZ #22375] - CVE-2017-17426 - * malloc/malloc.c (__libc_malloc): Use checked_request2size - instead of request2size. - -Index: glibc-2.26/malloc/malloc.c -=================================================================== ---- glibc-2.26.orig/malloc/malloc.c -+++ glibc-2.26/malloc/malloc.c -@@ -3052,7 +3052,8 @@ __libc_malloc (size_t bytes) - return (*hook)(bytes, RETURN_ADDRESS (0)); - #if USE_TCACHE - /* int_free also calls request2size, be careful to not pad twice. */ -- size_t tbytes = request2size (bytes); -+ size_t tbytes; -+ checked_request2size (bytes, tbytes); - size_t tc_idx = csize2tidx (tbytes); - - MAYBE_INIT_TCACHE (); diff --git a/malloc-tcache-leak.patch b/malloc-tcache-leak.patch deleted file mode 100644 index a1e50d2..0000000 --- a/malloc-tcache-leak.patch +++ /dev/null @@ -1,179 +0,0 @@ -2017-10-06 Carlos O'Donell - - [BZ #22111] - * malloc/malloc.c (tcache_shutting_down): Use bool type. - (tcache_thread_freeres): Set tcache_shutting_down before - freeing the tcache. - * malloc/Makefile (tests): Add tst-malloc-tcache-leak. - * malloc/tst-malloc-tcache-leak.c: New file. - -Index: glibc-2.26/malloc/Makefile -=================================================================== ---- glibc-2.26.orig/malloc/Makefile -+++ glibc-2.26/malloc/Makefile -@@ -34,6 +34,7 @@ tests := mallocbug tst-malloc tst-valloc - tst-interpose-nothread \ - tst-interpose-thread \ - tst-alloc_buffer \ -+ tst-malloc-tcache-leak \ - - tests-static := \ - tst-interpose-static-nothread \ -@@ -242,3 +243,5 @@ tst-dynarray-fail-ENV = MALLOC_TRACE=$(o - $(objpfx)tst-dynarray-fail-mem.out: $(objpfx)tst-dynarray-fail.out - $(common-objpfx)malloc/mtrace $(objpfx)tst-dynarray-fail.mtrace > $@; \ - $(evaluate-test) -+ -+$(objpfx)tst-malloc-tcache-leak: $(shared-thread-library) -Index: glibc-2.26/malloc/malloc.c -=================================================================== ---- glibc-2.26.orig/malloc/malloc.c -+++ glibc-2.26/malloc/malloc.c -@@ -2940,7 +2940,7 @@ typedef struct tcache_perthread_struct - tcache_entry *entries[TCACHE_MAX_BINS]; - } tcache_perthread_struct; - --static __thread char tcache_shutting_down = 0; -+static __thread bool tcache_shutting_down = false; - static __thread tcache_perthread_struct *tcache = NULL; - - /* Caller must ensure that we know tc_idx is valid and there's room -@@ -2977,8 +2977,12 @@ tcache_thread_freeres (void) - if (!tcache) - return; - -+ /* Disable the tcache and prevent it from being reinitialized. */ - tcache = NULL; -+ tcache_shutting_down = true; - -+ /* Free all of the entries and the tcache itself back to the arena -+ heap for coalescing. */ - for (i = 0; i < TCACHE_MAX_BINS; ++i) - { - while (tcache_tmp->entries[i]) -@@ -2990,8 +2994,6 @@ tcache_thread_freeres (void) - } - - __libc_free (tcache_tmp); -- -- tcache_shutting_down = 1; - } - text_set_element (__libc_thread_subfreeres, tcache_thread_freeres); - -Index: glibc-2.26/malloc/tst-malloc-tcache-leak.c -=================================================================== ---- /dev/null -+++ glibc-2.26/malloc/tst-malloc-tcache-leak.c -@@ -0,0 +1,112 @@ -+/* Bug 22111: Test that threads do not leak their per thread cache. -+ Copyright (C) 2015-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 -+ . */ -+ -+/* The point of this test is to start and exit a large number of -+ threads, while at the same time looking to see if the used -+ memory grows with each round of threads run. If the memory -+ grows above some linear bound we declare the test failed and -+ that the malloc implementation is leaking memory with each -+ thread. This is a good indicator that the thread local cache -+ is leaking chunks. */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+void * -+worker (void *data) -+{ -+ void *ret; -+ /* Allocate an arbitrary amount of memory that is known to fit into -+ the thread local cache (tcache). If we have at least 64 bins -+ (default e.g. TCACHE_MAX_BINS) we should be able to allocate 32 -+ bytes and force malloc to fill the tcache. We are assuming tcahce -+ init happens at the first small alloc, but it might in the future -+ be deferred to some other point. Therefore to future proof this -+ test we include a full alloc/free/alloc cycle for the thread. We -+ need a compiler barrier to avoid the removal of the useless -+ alloc/free. We send some memory back to main to have the memory -+ freed after the thread dies, as just another check that the chunks -+ that were previously in the tcache are still OK to free after -+ thread death. */ -+ ret = xmalloc (32); -+ __asm__ volatile ("" ::: "memory"); -+ free (ret); -+ return (void *) xmalloc (32); -+} -+ -+static int -+do_test (void) -+{ -+ pthread_t *thread; -+ struct mallinfo info_before, info_after; -+ void *retval; -+ -+ /* This is an arbitrary choice. We choose a total of THREADS -+ threads created and joined. This gives us enough iterations to -+ show a leak. */ -+ int threads = 100000; -+ -+ /* Avoid there being 0 malloc'd data at this point by allocating the -+ pthread_t required to run the test. */ -+ thread = (pthread_t *) xcalloc (1, sizeof (pthread_t)); -+ -+ info_before = mallinfo (); -+ -+ assert (info_before.uordblks != 0); -+ -+ printf ("INFO: %d (bytes) are in use before starting threads.\n", -+ info_before.uordblks); -+ -+ for (int loop = 0; loop < threads; loop++) -+ { -+ *thread = xpthread_create (NULL, worker, NULL); -+ retval = xpthread_join (*thread); -+ free (retval); -+ } -+ -+ info_after = mallinfo (); -+ printf ("INFO: %d (bytes) are in use after all threads joined.\n", -+ info_after.uordblks); -+ -+ /* We need to compare the memory in use before and the memory in use -+ after starting and joining THREADS threads. We almost always grow -+ memory slightly, but not much. Consider that if even 1-byte leaked -+ per thread we'd have THREADS bytes of additional memory, and in -+ general the in-use at the start of main is quite low. We will -+ always leak a full malloc chunk, and never just 1-byte, therefore -+ anything above "+ threads" from the start (constant offset) is a -+ leak. Obviously this assumes no thread-related malloc'd internal -+ libc data structures persist beyond the thread death, and any that -+ did would limit the number of times you could call pthread_create, -+ which is a QoI we'd want to detect and fix. */ -+ if (info_after.uordblks > (info_before.uordblks + threads)) -+ FAIL_EXIT1 ("Memory usage after threads is too high.\n"); -+ -+ /* Did not detect excessive memory usage. */ -+ free (thread); -+ exit (0); -+} -+ -+#include diff --git a/manpages.tar.bz2 b/manpages.tar.bz2 index 87cb48b..31e2910 100644 --- a/manpages.tar.bz2 +++ b/manpages.tar.bz2 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e8715a207e621f2dea9f4d766d55514b9ac4dc91ea9652e7768cea0f950cc88b -size 10824 +oid sha256:3f6c7ae11fffac0d0f1af507f657664a703a7ae6832a72d0b161693f3fcf41f6 +size 7405 diff --git a/math-c++-compat.patch b/math-c++-compat.patch deleted file mode 100644 index bf1c089..0000000 --- a/math-c++-compat.patch +++ /dev/null @@ -1,271 +0,0 @@ -2017-10-17 Romain Naour (tiny change) - - [BZ #22296] - * math/math.h: Let signbit use the builtin in C++ mode with gcc - < 6.x - -2017-10-03 Gabriel F. T. Gomes - - [BZ #22235] - * sysdeps/ieee754/ldbl-96/bits/iscanonical.h (iscanonical): - Provide a C++ implementation based on function overloading, - rather than using __MATH_TG, which uses C-only builtins. - * sysdeps/ieee754/ldbl-128ibm/bits/iscanonical.h (iscanonical): - Likewise. - -2017-09-22 Gabriel F. T. Gomes - - [BZ #22146] - math/math.h: Let fpclassify use the builtin in C++ mode, even - when optimazing for size. - -2017-08-28 Gabriel F. T. Gomes - - [BZ #21930] - * math/math.h [defined __cplusplus && defined __SUPPORT_SNAN__] - (iszero): New C++ implementation that does not use - fpclassify/__MATH_TG/__builtin_types_compatible_p, when - signaling nans are enabled, since __builtin_types_compatible_p - is a C-only feature. - -2017-08-24 Gabriel F. T. Gomes - - * math/math.h [defined __cplusplus] (issignaling): In the long - double case, call __issignalingl only if __NO_LONG_DOUBLE_MATH - is not defined. Call __issignaling, otherwise. - -2017-08-22 Gabriel F. T. Gomes - - * math/math.h [defined __cplusplus] (issignaling): Provide a C++ - definition for issignaling that does not rely on __MATH_TG, - since __MATH_TG uses __builtin_types_compatible_p, which is only - available in C mode. - -2017-08-18 Gabriel F. T. Gomes - - [BZ #21930] - * math/math.h (isinf): Check if in C or C++ mode before using - __builtin_types_compatible_p, since this is a C mode feature. - -2017-08-18 Gabriel F. T. Gomes - - * misc/sys/cdefs.h (__HAVE_GENERIC_SELECTION): Define to 0, if - in C++ mode. - -Index: glibc-2.26/math/math.h -=================================================================== ---- glibc-2.26.orig/math/math.h -+++ glibc-2.26/math/math.h -@@ -402,7 +402,13 @@ enum - - /* Return number of classification appropriate for X. */ - # if __GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__ \ -- && !defined __OPTIMIZE_SIZE__ -+ && (!defined __OPTIMIZE_SIZE__ || defined __cplusplus) -+ /* The check for __cplusplus allows the use of the builtin, even -+ when optimization for size is on. This is provided for -+ libstdc++, only to let its configure test work when it is built -+ with -Os. No further use of this definition of fpclassify is -+ expected in C++ mode, since libstdc++ provides its own version -+ of fpclassify in cmath (which undefines fpclassify). */ - # define fpclassify(x) __builtin_fpclassify (FP_NAN, FP_INFINITE, \ - FP_NORMAL, FP_SUBNORMAL, FP_ZERO, x) - # else -@@ -412,6 +418,15 @@ enum - /* Return nonzero value if sign of X is negative. */ - # if __GNUC_PREREQ (6,0) - # define signbit(x) __builtin_signbit (x) -+# elif defined __cplusplus -+ /* In C++ mode, __MATH_TG cannot be used, because it relies on -+ __builtin_types_compatible_p, which is a C-only builtin. -+ The check for __cplusplus allows the use of the builtin instead of -+ __MATH_TG. This is provided for libstdc++, only to let its configure -+ test work. No further use of this definition of signbit is expected -+ in C++ mode, since libstdc++ provides its own version of signbit -+ in cmath (which undefines signbit). */ -+# define signbit(x) __builtin_signbitl (x) - # elif __GNUC_PREREQ (4,0) - # define signbit(x) __MATH_TG ((x), __builtin_signbit, (x)) - # else -@@ -442,8 +457,12 @@ enum - - /* Return nonzero value if X is positive or negative infinity. */ - # if __HAVE_DISTINCT_FLOAT128 && !__GNUC_PREREQ (7,0) \ -- && !defined __SUPPORT_SNAN__ -- /* __builtin_isinf_sign is broken for float128 only before GCC 7.0. */ -+ && !defined __SUPPORT_SNAN__ && !defined __cplusplus -+ /* Since __builtin_isinf_sign is broken for float128 before GCC 7.0, -+ use the helper function, __isinff128, with older compilers. This is -+ only provided for C mode, because in C++ mode, GCC has no support -+ for __builtin_types_compatible_p (and when in C++ mode, this macro is -+ not used anyway, because libstdc++ headers undefine it). */ - # define isinf(x) \ - (__builtin_types_compatible_p (__typeof (x), _Float128) \ - ? __isinff128 (x) : __builtin_isinf_sign (x)) -@@ -470,7 +489,32 @@ enum - # include - - /* Return nonzero value if X is a signaling NaN. */ --# define issignaling(x) __MATH_TG ((x), __issignaling, (x)) -+# ifndef __cplusplus -+# define issignaling(x) __MATH_TG ((x), __issignaling, (x)) -+# else -+ /* In C++ mode, __MATH_TG cannot be used, because it relies on -+ __builtin_types_compatible_p, which is a C-only builtin. On the -+ other hand, overloading provides the means to distinguish between -+ the floating-point types. The overloading resolution will match -+ the correct parameter (regardless of type qualifiers (i.e.: const -+ and volatile). */ -+extern "C++" { -+inline int issignaling (float __val) { return __issignalingf (__val); } -+inline int issignaling (double __val) { return __issignaling (__val); } -+inline int -+issignaling (long double __val) -+{ -+# ifdef __NO_LONG_DOUBLE_MATH -+ return __issignaling (__val); -+# else -+ return __issignalingl (__val); -+# endif -+} -+# if __HAVE_DISTINCT_FLOAT128 -+inline int issignaling (_Float128 __val) { return __issignalingf128 (__val); } -+# endif -+} /* extern C++ */ -+# endif - - /* Return nonzero value if X is subnormal. */ - # define issubnormal(x) (fpclassify (x) == FP_SUBNORMAL) -@@ -484,15 +528,40 @@ enum - # endif - # else /* __cplusplus */ - extern "C++" { -+# ifdef __SUPPORT_SNAN__ -+inline int -+iszero (float __val) -+{ -+ return __fpclassifyf (__val) == FP_ZERO; -+} -+inline int -+iszero (double __val) -+{ -+ return __fpclassify (__val) == FP_ZERO; -+} -+inline int -+iszero (long double __val) -+{ -+# ifdef __NO_LONG_DOUBLE_MATH -+ return __fpclassify (__val) == FP_ZERO; -+# else -+ return __fpclassifyl (__val) == FP_ZERO; -+# endif -+} -+# if __HAVE_DISTINCT_FLOAT128 -+inline int -+iszero (_Float128 __val) -+{ -+ return __fpclassifyf128 (__val) == FP_ZERO; -+} -+# endif -+# else - template inline bool - iszero (__T __val) - { --# ifdef __SUPPORT_SNAN__ -- return fpclassify (__val) == FP_ZERO; --# else - return __val == 0; --# endif - } -+# endif - } /* extern C++ */ - # endif /* __cplusplus */ - #endif /* Use IEC_60559_BFP_EXT. */ -Index: glibc-2.26/misc/sys/cdefs.h -=================================================================== ---- glibc-2.26.orig/misc/sys/cdefs.h -+++ glibc-2.26/misc/sys/cdefs.h -@@ -464,17 +464,18 @@ - # define __glibc_macro_warning(msg) - #endif - --/* Support for generic selection (ISO C11) is available in GCC since -- version 4.9. Previous versions do not provide generic selection, -- even though they might set __STDC_VERSION__ to 201112L, when in -- -std=c11 mode. Thus, we must check for !defined __GNUC__ when -- testing __STDC_VERSION__ for generic selection support. -+/* Generic selection (ISO C11) is a C-only feature, available in GCC -+ since version 4.9. Previous versions do not provide generic -+ selection, even though they might set __STDC_VERSION__ to 201112L, -+ when in -std=c11 mode. Thus, we must check for !defined __GNUC__ -+ when testing __STDC_VERSION__ for generic selection support. - On the other hand, Clang also defines __GNUC__, so a clang-specific - check is required to enable the use of generic selection. */ --#if __GNUC_PREREQ (4, 9) \ -- || __glibc_clang_has_extension (c_generic_selections) \ -- || (!defined __GNUC__ && defined __STDC_VERSION__ \ -- && __STDC_VERSION__ >= 201112L) -+#if !defined __cplusplus \ -+ && (__GNUC_PREREQ (4, 9) \ -+ || __glibc_clang_has_extension (c_generic_selections) \ -+ || (!defined __GNUC__ && defined __STDC_VERSION__ \ -+ && __STDC_VERSION__ >= 201112L)) - # define __HAVE_GENERIC_SELECTION 1 - #else - # define __HAVE_GENERIC_SELECTION 0 -Index: glibc-2.26/sysdeps/ieee754/ldbl-128ibm/bits/iscanonical.h -=================================================================== ---- glibc-2.26.orig/sysdeps/ieee754/ldbl-128ibm/bits/iscanonical.h -+++ glibc-2.26/sysdeps/ieee754/ldbl-128ibm/bits/iscanonical.h -@@ -37,5 +37,22 @@ extern int __iscanonicall (long double _ - conversion, before being discarded; in IBM long double, there are - encodings that are not consistently handled as corresponding to any - particular value of the type, and we return 0 for those. */ --# define iscanonical(x) __MATH_TG ((x), __iscanonical, (x)) --#endif -+# ifndef __cplusplus -+# define iscanonical(x) __MATH_TG ((x), __iscanonical, (x)) -+# else -+/* In C++ mode, __MATH_TG cannot be used, because it relies on -+ __builtin_types_compatible_p, which is a C-only builtin. On the -+ other hand, overloading provides the means to distinguish between -+ the floating-point types. The overloading resolution will match -+ the correct parameter (regardless of type qualifiers (i.e.: const -+ and volatile)). */ -+extern "C++" { -+inline int iscanonical (float __val) { return __iscanonicalf (__val); } -+inline int iscanonical (double __val) { return __iscanonical (__val); } -+inline int iscanonical (long double __val) { return __iscanonicall (__val); } -+# if __HAVE_DISTINCT_FLOAT128 -+inline int iscanonical (_Float128 __val) { return __iscanonicalf128 (__val); } -+# endif -+} -+# endif /* __cplusplus */ -+#endif /* __NO_LONG_DOUBLE_MATH */ -Index: glibc-2.26/sysdeps/ieee754/ldbl-96/bits/iscanonical.h -=================================================================== ---- glibc-2.26.orig/sysdeps/ieee754/ldbl-96/bits/iscanonical.h -+++ glibc-2.26/sysdeps/ieee754/ldbl-96/bits/iscanonical.h -@@ -34,4 +34,21 @@ extern int __iscanonicall (long double _ - conversion, before being discarded; in extended precision, there - are encodings that are not consistently handled as corresponding to - any particular value of the type, and we return 0 for those. */ --#define iscanonical(x) __MATH_TG ((x), __iscanonical, (x)) -+#ifndef __cplusplus -+# define iscanonical(x) __MATH_TG ((x), __iscanonical, (x)) -+#else -+/* In C++ mode, __MATH_TG cannot be used, because it relies on -+ __builtin_types_compatible_p, which is a C-only builtin. On the -+ other hand, overloading provides the means to distinguish between -+ the floating-point types. The overloading resolution will match -+ the correct parameter (regardless of type qualifiers (i.e.: const -+ and volatile)). */ -+extern "C++" { -+inline int iscanonical (float __val) { return __iscanonicalf (__val); } -+inline int iscanonical (double __val) { return __iscanonical (__val); } -+inline int iscanonical (long double __val) { return __iscanonicall (__val); } -+# if __HAVE_DISTINCT_FLOAT128 -+inline int iscanonical (_Float128 __val) { return __iscanonicalf128 (__val); } -+# endif -+} -+#endif /* __cplusplus */ diff --git a/nearbyint-inexact.patch b/nearbyint-inexact.patch deleted file mode 100644 index aba9ec2..0000000 --- a/nearbyint-inexact.patch +++ /dev/null @@ -1,107 +0,0 @@ -2017-09-28 Joseph Myers - - [BZ #22225] - * sysdeps/ieee754/dbl-64/s_nearbyint.c (__nearbyint): Use - math_opt_barrier on argument when doing arithmetic on it. - * sysdeps/ieee754/dbl-64/wordsize-64/s_nearbyint.c (__nearbyint): - Likewise. Use math_force_eval not math_opt_barrier after - arithmetic. - * sysdeps/ieee754/flt-32/s_nearbyintf.c (__nearbyintf): Use - math_opt_barrier on argument when doing arithmetic on it. - * sysdeps/ieee754/ldbl-128/s_nearbyintl.c (__nearbyintl): - Likewise. - -Index: glibc-2.26/sysdeps/ieee754/dbl-64/s_nearbyint.c -=================================================================== ---- glibc-2.26.orig/sysdeps/ieee754/dbl-64/s_nearbyint.c -+++ glibc-2.26/sysdeps/ieee754/dbl-64/s_nearbyint.c -@@ -48,7 +48,7 @@ __nearbyint (double x) - if (j0 < 0) - { - libc_feholdexcept (&env); -- w = TWO52[sx] + x; -+ w = TWO52[sx] + math_opt_barrier (x); - t = w - TWO52[sx]; - math_force_eval (t); - libc_fesetenv (&env); -@@ -65,7 +65,7 @@ __nearbyint (double x) - return x; /* x is integral */ - } - libc_feholdexcept (&env); -- w = TWO52[sx] + x; -+ w = TWO52[sx] + math_opt_barrier (x); - t = w - TWO52[sx]; - math_force_eval (t); - libc_fesetenv (&env); -Index: glibc-2.26/sysdeps/ieee754/dbl-64/wordsize-64/s_nearbyint.c -=================================================================== ---- glibc-2.26.orig/sysdeps/ieee754/dbl-64/wordsize-64/s_nearbyint.c -+++ glibc-2.26/sysdeps/ieee754/dbl-64/wordsize-64/s_nearbyint.c -@@ -42,9 +42,9 @@ __nearbyint(double x) - if(__builtin_expect(j0<52, 1)) { - if(j0<0) { - libc_feholdexcept (&env); -- double w = TWO52[sx]+x; -+ double w = TWO52[sx] + math_opt_barrier (x); - double t = w-TWO52[sx]; -- math_opt_barrier(t); -+ math_force_eval (t); - libc_fesetenv (&env); - return __copysign (t, x); - } -@@ -53,9 +53,9 @@ __nearbyint(double x) - else return x; /* x is integral */ - } - libc_feholdexcept (&env); -- double w = TWO52[sx]+x; -+ double w = TWO52[sx] + math_opt_barrier (x); - double t = w-TWO52[sx]; -- math_opt_barrier (t); -+ math_force_eval (t); - libc_fesetenv (&env); - return t; - } -Index: glibc-2.26/sysdeps/ieee754/flt-32/s_nearbyintf.c -=================================================================== ---- glibc-2.26.orig/sysdeps/ieee754/flt-32/s_nearbyintf.c -+++ glibc-2.26/sysdeps/ieee754/flt-32/s_nearbyintf.c -@@ -37,7 +37,7 @@ __nearbyintf(float x) - if(j0<23) { - if(j0<0) { - libc_feholdexceptf (&env); -- w = TWO23[sx]+x; -+ w = TWO23[sx] + math_opt_barrier (x); - t = w-TWO23[sx]; - math_force_eval (t); - libc_fesetenvf (&env); -@@ -50,7 +50,7 @@ __nearbyintf(float x) - else return x; /* x is integral */ - } - libc_feholdexceptf (&env); -- w = TWO23[sx]+x; -+ w = TWO23[sx] + math_opt_barrier (x); - t = w-TWO23[sx]; - math_force_eval (t); - libc_fesetenvf (&env); -Index: glibc-2.26/sysdeps/ieee754/ldbl-128/s_nearbyintl.c -=================================================================== ---- glibc-2.26.orig/sysdeps/ieee754/ldbl-128/s_nearbyintl.c -+++ glibc-2.26/sysdeps/ieee754/ldbl-128/s_nearbyintl.c -@@ -45,7 +45,7 @@ _Float128 __nearbyintl(_Float128 x) - if(j0<112) { - if(j0<0) { - feholdexcept (&env); -- w = TWO112[sx]+x; -+ w = TWO112[sx] + math_opt_barrier (x); - t = w-TWO112[sx]; - math_force_eval (t); - fesetenv (&env); -@@ -58,7 +58,7 @@ _Float128 __nearbyintl(_Float128 x) - else return x; /* x is integral */ - } - feholdexcept (&env); -- w = TWO112[sx]+x; -+ w = TWO112[sx] + math_opt_barrier (x); - t = w-TWO112[sx]; - math_force_eval (t); - fesetenv (&env); diff --git a/nscd-libnsl.patch b/nscd-libnsl.patch deleted file mode 100644 index c86530f..0000000 --- a/nscd-libnsl.patch +++ /dev/null @@ -1,180 +0,0 @@ -2017-10-11 Andreas Schwab - - * nis/Makefile (aux): Remove. - * nscd/Makefile (aux): Add nscd_hash. - (nscd-modules): Likewise. - ($(objpfx)nscd): Don't depend on libnsl. - * nscd/nscd_hash.c: New file. - * nscd/nscd_hash.h: Likewise. - * nscd/cache.c: Include "nscd_hash.h" instead of . - (cache_search, cache_add): Use __nscd_hash instead of __nis_hash. - * nscd/nscd_helper.c: Include and "nscd_hash.h" - instead of . - (__nscd_cache_search): Use __nscd_hash instead of __nis_hash. - -Index: glibc-2.26/nis/Makefile -=================================================================== ---- glibc-2.26.orig/nis/Makefile -+++ glibc-2.26/nis/Makefile -@@ -22,8 +22,6 @@ subdir := nis - - include ../Makeconfig - --aux := nis_hash -- - ifeq ($(build-obsolete-nsl),yes) - headers := $(wildcard rpcsvc/*.[hx]) - -Index: glibc-2.26/nscd/Makefile -=================================================================== ---- glibc-2.26.orig/nscd/Makefile -+++ glibc-2.26/nscd/Makefile -@@ -25,7 +25,7 @@ include ../Makeconfig - ifneq ($(use-nscd),no) - routines := nscd_getpw_r nscd_getgr_r nscd_gethst_r nscd_getai \ - nscd_initgroups nscd_getserv_r nscd_netgroup --aux := nscd_helper -+aux := nscd_helper nscd_hash - endif - - # To find xmalloc.c -@@ -36,7 +36,7 @@ nscd-modules := nscd connections pwdcach - getsrvbynm_r getsrvbypt_r servicescache \ - dbg_log nscd_conf nscd_stat cache mem nscd_setup_thread \ - xmalloc xstrdup aicache initgrcache gai res_hconf \ -- netgroupcache -+ netgroupcache nscd_hash - - ifeq ($(build-nscd)$(have-thread-library),yesyes) - -@@ -97,7 +97,7 @@ include $(patsubst %,$(..)libof-iterator - $(objpfx)nscd: $(nscd-modules:%=$(objpfx)%.o) - - ifeq ($(build-shared),yes) --$(objpfx)nscd: $(shared-thread-library) $(common-objpfx)nis/libnsl.so -+$(objpfx)nscd: $(shared-thread-library) - else --$(objpfx)nscd: $(static-thread-library) $(common-objpfx)nis/libnsl.a -+$(objpfx)nscd: $(static-thread-library) - endif -Index: glibc-2.26/nscd/cache.c -=================================================================== ---- glibc-2.26.orig/nscd/cache.c -+++ glibc-2.26/nscd/cache.c -@@ -25,7 +25,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -33,6 +32,7 @@ - - #include "nscd.h" - #include "dbg_log.h" -+#include "nscd_hash.h" - - - /* Wrapper functions with error checking for standard functions. */ -@@ -74,7 +74,7 @@ struct datahead * - cache_search (request_type type, const void *key, size_t len, - struct database_dyn *table, uid_t owner) - { -- unsigned long int hash = __nis_hash (key, len) % table->head->module; -+ unsigned long int hash = __nscd_hash (key, len) % table->head->module; - - unsigned long int nsearched = 0; - struct datahead *result = NULL; -@@ -153,7 +153,7 @@ cache_add (int type, const void *key, si - first ? _(" (first)") : ""); - } - -- unsigned long int hash = __nis_hash (key, len) % table->head->module; -+ unsigned long int hash = __nscd_hash (key, len) % table->head->module; - struct hashentry *newp; - - newp = mempool_alloc (table, sizeof (struct hashentry), 0); -Index: glibc-2.26/nscd/nscd_hash.c -=================================================================== ---- /dev/null -+++ glibc-2.26/nscd/nscd_hash.c -@@ -0,0 +1,19 @@ -+/* 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 -+ . */ -+ -+#define __nis_hash __nscd_hash -+#include -Index: glibc-2.26/nscd/nscd_hash.h -=================================================================== ---- /dev/null -+++ glibc-2.26/nscd/nscd_hash.h -@@ -0,0 +1,21 @@ -+/* 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 -+ -+extern uint32_t __nscd_hash (const void *__keyarg, size_t __len) -+ attribute_hidden; -Index: glibc-2.26/nscd/nscd_helper.c -=================================================================== ---- glibc-2.26.orig/nscd/nscd_helper.c -+++ glibc-2.26/nscd/nscd_helper.c -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -34,10 +35,10 @@ - #include - #include - #include --#include - #include - - #include "nscd-client.h" -+#include "nscd_hash.h" - - - /* Extra time we wait if the socket is still receiving data. This -@@ -451,7 +452,7 @@ struct datahead * - __nscd_cache_search (request_type type, const char *key, size_t keylen, - const struct mapped_database *mapped, size_t datalen) - { -- unsigned long int hash = __nis_hash (key, keylen) % mapped->head->module; -+ unsigned long int hash = __nscd_hash (key, keylen) % mapped->head->module; - size_t datasize = mapped->datasize; - - ref_t trail = mapped->head->array[hash]; diff --git a/nscd-server-user.patch b/nscd-server-user.patch index 1e66881..9b16665 100644 --- a/nscd-server-user.patch +++ b/nscd-server-user.patch @@ -1,7 +1,7 @@ -Index: glibc-2.18/nscd/nscd.conf +Index: glibc-2.27/nscd/nscd.conf =================================================================== ---- glibc-2.18.orig/nscd/nscd.conf -+++ glibc-2.18/nscd/nscd.conf +--- glibc-2.27.orig/nscd/nscd.conf ++++ glibc-2.27/nscd/nscd.conf @@ -33,7 +33,7 @@ # logfile /var/log/nscd.log # threads 4 diff --git a/nss-compat.patch b/nss-compat.patch deleted file mode 100644 index cc4819e..0000000 --- a/nss-compat.patch +++ /dev/null @@ -1,6745 +0,0 @@ -2017-10-04 Andreas Schwab - - * nis/Makefile (services): Remove compat. - (libnss_compat-routines, libnss_compat-inhibit-o): Don't define. - ($(objpfx)libnss_compat.so): Remove rule. - * nis/Versions (libnss_compat): Remove. - * nss/Makefile (services): Add compat. - (libnss_compat-routines, libnss_compat-inhibit-o): Define. - * nss/Versions (libnss_compat): Define. - * nss/nss_compat/compat-grp.c: Moved here from nis/nss_compat. - Don't include . Replace bool_t by bool. - * nss/nss_compat/compat-initgroups.c: Likewise. - * nss/nss_compat/compat-pwd.c: Likewise. Include "nisdomain.h" - instead of . - (getpwent_next_nss_netgr): Use __nss_get_default_domain instead of - yp_get_default_domain. - * nss/nss_compat/compat-pwd.c: Likewise. - (getspent_next_nss_netgr): Use __nss_get_default_domain instead of - yp_get_default_domain. - * nss/nss_compat/nisdomain.c: New file. - * nss/nss_compat/nisdomain.h: Likewise. - -Index: glibc-2.26/nis/Makefile -=================================================================== ---- glibc-2.26.orig/nis/Makefile -+++ glibc-2.26/nis/Makefile -@@ -33,7 +33,7 @@ databases = proto service hosts network - spwd netgrp alias publickey - - # Specify rules for the nss_* modules. --services := nis nisplus compat -+services := nis nisplus - endif - - extra-libs = libnsl -@@ -63,9 +63,6 @@ libnsl-routines = yp_xdr ypclnt ypupdate - nis_clone_res nss-default - - ifeq ($(build-obsolete-nsl),yes) --libnss_compat-routines := $(addprefix compat-,grp pwd spwd initgroups) --libnss_compat-inhibit-o = $(filter-out .os,$(object-suffixes)) -- - libnss_nis-routines := $(addprefix nis-,$(databases)) nis-initgroups \ - nss-nis - libnss_nis-inhibit-o = $(filter-out .os,$(object-suffixes)) -@@ -79,7 +76,6 @@ include ../Rules - - - ifeq ($(build-obsolete-nsl),yes) --$(objpfx)libnss_compat.so: $(objpfx)libnsl.so$(libnsl.so-version) - $(objpfx)libnss_nis.so: $(objpfx)libnsl.so$(libnsl.so-version) \ - $(common-objpfx)nss/libnss_files.so - $(objpfx)libnss_nisplus.so: $(objpfx)libnsl.so$(libnsl.so-version) -Index: glibc-2.26/nis/Versions -=================================================================== ---- glibc-2.26.orig/nis/Versions -+++ glibc-2.26/nis/Versions -@@ -63,17 +63,6 @@ libnsl { - } - } - --libnss_compat { -- GLIBC_PRIVATE { -- _nss_compat_endgrent; _nss_compat_endpwent; _nss_compat_endspent; -- _nss_compat_getgrent_r; _nss_compat_getgrgid_r; _nss_compat_getgrnam_r; -- _nss_compat_getpwent_r; _nss_compat_getpwnam_r; _nss_compat_getpwuid_r; -- _nss_compat_getspent_r; _nss_compat_getspnam_r; -- _nss_compat_setgrent; _nss_compat_setpwent; _nss_compat_setspent; -- _nss_compat_initgroups_dyn; -- } --} -- - libnss_nis { - GLIBC_PRIVATE { - _nss_nis_endaliasent; _nss_nis_endetherent; _nss_nis_endgrent; -Index: glibc-2.26/nis/nss_compat/compat-grp.c -=================================================================== ---- glibc-2.26.orig/nis/nss_compat/compat-grp.c -+++ /dev/null -@@ -1,683 +0,0 @@ --/* Copyright (C) 1996-2017 Free Software Foundation, Inc. -- This file is part of the GNU C Library. -- Contributed by Thorsten Kukuk , 1996. -- -- 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 --#include -- --static service_user *ni; --static enum nss_status (*nss_setgrent) (int stayopen); --static enum nss_status (*nss_getgrnam_r) (const char *name, -- struct group * grp, char *buffer, -- size_t buflen, int *errnop); --static enum nss_status (*nss_getgrgid_r) (gid_t gid, struct group * grp, -- char *buffer, size_t buflen, -- int *errnop); --static enum nss_status (*nss_getgrent_r) (struct group * grp, char *buffer, -- size_t buflen, int *errnop); --static enum nss_status (*nss_endgrent) (void); -- --/* Get the declaration of the parser function. */ --#define ENTNAME grent --#define STRUCTURE group --#define EXTERN_PARSER --#include -- --/* Structure for remembering -group members ... */ --#define BLACKLIST_INITIAL_SIZE 512 --#define BLACKLIST_INCREMENT 256 --struct blacklist_t --{ -- char *data; -- int current; -- int size; --}; -- --struct ent_t --{ -- bool_t files; -- enum nss_status setent_status; -- FILE *stream; -- struct blacklist_t blacklist; --}; --typedef struct ent_t ent_t; -- --static ent_t ext_ent = { TRUE, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0 }}; -- --/* Protect global state against multiple changers. */ --__libc_lock_define_initialized (static, lock) -- --/* Prototypes for local functions. */ --static void blacklist_store_name (const char *, ent_t *); --static int in_blacklist (const char *, int, ent_t *); -- --/* Initialize the NSS interface/functions. The calling function must -- hold the lock. */ --static void --init_nss_interface (void) --{ -- if (__nss_database_lookup ("group_compat", NULL, "nis", &ni) >= 0) -- { -- nss_setgrent = __nss_lookup_function (ni, "setgrent"); -- nss_getgrnam_r = __nss_lookup_function (ni, "getgrnam_r"); -- nss_getgrgid_r = __nss_lookup_function (ni, "getgrgid_r"); -- nss_getgrent_r = __nss_lookup_function (ni, "getgrent_r"); -- nss_endgrent = __nss_lookup_function (ni, "endgrent"); -- } --} -- --static enum nss_status --internal_setgrent (ent_t *ent, int stayopen, int needent) --{ -- enum nss_status status = NSS_STATUS_SUCCESS; -- -- ent->files = TRUE; -- -- if (ent->blacklist.data != NULL) -- { -- ent->blacklist.current = 1; -- ent->blacklist.data[0] = '|'; -- ent->blacklist.data[1] = '\0'; -- } -- else -- ent->blacklist.current = 0; -- -- if (ent->stream == NULL) -- { -- ent->stream = fopen ("/etc/group", "rme"); -- -- if (ent->stream == NULL) -- status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; -- else -- /* We take care of locking ourself. */ -- __fsetlocking (ent->stream, FSETLOCKING_BYCALLER); -- } -- else -- rewind (ent->stream); -- -- if (needent && status == NSS_STATUS_SUCCESS && nss_setgrent) -- ent->setent_status = nss_setgrent (stayopen); -- -- return status; --} -- -- --enum nss_status --_nss_compat_setgrent (int stayopen) --{ -- enum nss_status result; -- -- __libc_lock_lock (lock); -- -- if (ni == NULL) -- init_nss_interface (); -- -- result = internal_setgrent (&ext_ent, stayopen, 1); -- -- __libc_lock_unlock (lock); -- -- return result; --} -- -- --static enum nss_status --internal_endgrent (ent_t *ent) --{ -- if (ent->stream != NULL) -- { -- fclose (ent->stream); -- ent->stream = NULL; -- } -- -- if (ent->blacklist.data != NULL) -- { -- ent->blacklist.current = 1; -- ent->blacklist.data[0] = '|'; -- ent->blacklist.data[1] = '\0'; -- } -- else -- ent->blacklist.current = 0; -- -- return NSS_STATUS_SUCCESS; --} -- --enum nss_status --_nss_compat_endgrent (void) --{ -- enum nss_status result; -- -- __libc_lock_lock (lock); -- -- if (nss_endgrent) -- nss_endgrent (); -- -- result = internal_endgrent (&ext_ent); -- -- __libc_lock_unlock (lock); -- -- return result; --} -- --/* get the next group from NSS (+ entry) */ --static enum nss_status --getgrent_next_nss (struct group *result, ent_t *ent, char *buffer, -- size_t buflen, int *errnop) --{ -- if (!nss_getgrent_r) -- return NSS_STATUS_UNAVAIL; -- -- /* If the setgrent call failed, say so. */ -- if (ent->setent_status != NSS_STATUS_SUCCESS) -- return ent->setent_status; -- -- do -- { -- enum nss_status status; -- -- if ((status = nss_getgrent_r (result, buffer, buflen, errnop)) != -- NSS_STATUS_SUCCESS) -- return status; -- } -- while (in_blacklist (result->gr_name, strlen (result->gr_name), ent)); -- -- return NSS_STATUS_SUCCESS; --} -- --/* This function handle the +group entrys in /etc/group */ --static enum nss_status --getgrnam_plusgroup (const char *name, struct group *result, ent_t *ent, -- char *buffer, size_t buflen, int *errnop) --{ -- if (!nss_getgrnam_r) -- return NSS_STATUS_UNAVAIL; -- -- enum nss_status status = nss_getgrnam_r (name, result, buffer, buflen, -- errnop); -- if (status != NSS_STATUS_SUCCESS) -- return status; -- -- if (in_blacklist (result->gr_name, strlen (result->gr_name), ent)) -- return NSS_STATUS_NOTFOUND; -- -- /* We found the entry. */ -- return NSS_STATUS_SUCCESS; --} -- --static enum nss_status --getgrent_next_file (struct group *result, ent_t *ent, -- char *buffer, size_t buflen, int *errnop) --{ -- struct parser_data *data = (void *) buffer; -- while (1) -- { -- fpos_t pos; -- int parse_res = 0; -- char *p; -- -- do -- { -- /* We need at least 3 characters for one line. */ -- if (__glibc_unlikely (buflen < 3)) -- { -- erange: -- *errnop = ERANGE; -- return NSS_STATUS_TRYAGAIN; -- } -- -- fgetpos (ent->stream, &pos); -- buffer[buflen - 1] = '\xff'; -- p = fgets_unlocked (buffer, buflen, ent->stream); -- if (p == NULL && feof_unlocked (ent->stream)) -- return NSS_STATUS_NOTFOUND; -- -- if (p == NULL || __builtin_expect (buffer[buflen - 1] != '\xff', 0)) -- { -- erange_reset: -- fsetpos (ent->stream, &pos); -- goto erange; -- } -- -- /* Terminate the line for any case. */ -- buffer[buflen - 1] = '\0'; -- -- /* Skip leading blanks. */ -- while (isspace (*p)) -- ++p; -- } -- while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */ -- /* Parse the line. If it is invalid, loop to -- get the next line of the file to parse. */ -- !(parse_res = _nss_files_parse_grent (p, result, data, buflen, -- errnop))); -- -- if (__glibc_unlikely (parse_res == -1)) -- /* The parser ran out of space. */ -- goto erange_reset; -- -- if (result->gr_name[0] != '+' && result->gr_name[0] != '-') -- /* This is a real entry. */ -- break; -- -- /* -group */ -- if (result->gr_name[0] == '-' && result->gr_name[1] != '\0' -- && result->gr_name[1] != '@') -- { -- blacklist_store_name (&result->gr_name[1], ent); -- continue; -- } -- -- /* +group */ -- if (result->gr_name[0] == '+' && result->gr_name[1] != '\0' -- && result->gr_name[1] != '@') -- { -- size_t len = strlen (result->gr_name); -- char buf[len]; -- enum nss_status status; -- -- /* Store the group in the blacklist for the "+" at the end of -- /etc/group */ -- memcpy (buf, &result->gr_name[1], len); -- status = getgrnam_plusgroup (&result->gr_name[1], result, ent, -- buffer, buflen, errnop); -- blacklist_store_name (buf, ent); -- if (status == NSS_STATUS_SUCCESS) /* We found the entry. */ -- break; -- else if (status == NSS_STATUS_RETURN /* We couldn't parse the entry*/ -- || status == NSS_STATUS_NOTFOUND) /* No group in NIS */ -- continue; -- else -- { -- if (status == NSS_STATUS_TRYAGAIN) -- /* The parser ran out of space. */ -- goto erange_reset; -- -- return status; -- } -- } -- -- /* +:... */ -- if (result->gr_name[0] == '+' && result->gr_name[1] == '\0') -- { -- ent->files = FALSE; -- -- return getgrent_next_nss (result, ent, buffer, buflen, errnop); -- } -- } -- -- return NSS_STATUS_SUCCESS; --} -- -- --enum nss_status --_nss_compat_getgrent_r (struct group *grp, char *buffer, size_t buflen, -- int *errnop) --{ -- enum nss_status result = NSS_STATUS_SUCCESS; -- -- __libc_lock_lock (lock); -- -- /* Be prepared that the setgrent function was not called before. */ -- if (ni == NULL) -- init_nss_interface (); -- -- if (ext_ent.stream == NULL) -- result = internal_setgrent (&ext_ent, 1, 1); -- -- if (result == NSS_STATUS_SUCCESS) -- { -- if (ext_ent.files) -- result = getgrent_next_file (grp, &ext_ent, buffer, buflen, errnop); -- else -- result = getgrent_next_nss (grp, &ext_ent, buffer, buflen, errnop); -- } -- __libc_lock_unlock (lock); -- -- return result; --} -- --/* Searches in /etc/group and the NIS/NIS+ map for a special group */ --static enum nss_status --internal_getgrnam_r (const char *name, struct group *result, ent_t *ent, -- char *buffer, size_t buflen, int *errnop) --{ -- struct parser_data *data = (void *) buffer; -- while (1) -- { -- fpos_t pos; -- int parse_res = 0; -- char *p; -- -- do -- { -- /* We need at least 3 characters for one line. */ -- if (__glibc_unlikely (buflen < 3)) -- { -- erange: -- *errnop = ERANGE; -- return NSS_STATUS_TRYAGAIN; -- } -- -- fgetpos (ent->stream, &pos); -- buffer[buflen - 1] = '\xff'; -- p = fgets_unlocked (buffer, buflen, ent->stream); -- if (p == NULL && feof_unlocked (ent->stream)) -- return NSS_STATUS_NOTFOUND; -- -- if (p == NULL || __builtin_expect (buffer[buflen - 1] != '\xff', 0)) -- { -- erange_reset: -- fsetpos (ent->stream, &pos); -- goto erange; -- } -- -- /* Terminate the line for any case. */ -- buffer[buflen - 1] = '\0'; -- -- /* Skip leading blanks. */ -- while (isspace (*p)) -- ++p; -- } -- while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */ -- /* Parse the line. If it is invalid, loop to -- get the next line of the file to parse. */ -- !(parse_res = _nss_files_parse_grent (p, result, data, buflen, -- errnop))); -- -- if (__glibc_unlikely (parse_res == -1)) -- /* The parser ran out of space. */ -- goto erange_reset; -- -- /* This is a real entry. */ -- if (result->gr_name[0] != '+' && result->gr_name[0] != '-') -- { -- if (strcmp (result->gr_name, name) == 0) -- return NSS_STATUS_SUCCESS; -- else -- continue; -- } -- -- /* -group */ -- if (result->gr_name[0] == '-' && result->gr_name[1] != '\0') -- { -- if (strcmp (&result->gr_name[1], name) == 0) -- return NSS_STATUS_NOTFOUND; -- else -- continue; -- } -- -- /* +group */ -- if (result->gr_name[0] == '+' && result->gr_name[1] != '\0') -- { -- if (strcmp (name, &result->gr_name[1]) == 0) -- { -- enum nss_status status; -- -- status = getgrnam_plusgroup (name, result, ent, -- buffer, buflen, errnop); -- if (status == NSS_STATUS_RETURN) -- /* We couldn't parse the entry */ -- continue; -- else -- return status; -- } -- } -- /* +:... */ -- if (result->gr_name[0] == '+' && result->gr_name[1] == '\0') -- { -- enum nss_status status; -- -- status = getgrnam_plusgroup (name, result, ent, -- buffer, buflen, errnop); -- if (status == NSS_STATUS_RETURN) -- /* We couldn't parse the entry */ -- continue; -- else -- return status; -- } -- } -- -- return NSS_STATUS_SUCCESS; --} -- --enum nss_status --_nss_compat_getgrnam_r (const char *name, struct group *grp, -- char *buffer, size_t buflen, int *errnop) --{ -- ent_t ent = { TRUE, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0 }}; -- enum nss_status result; -- -- if (name[0] == '-' || name[0] == '+') -- return NSS_STATUS_NOTFOUND; -- -- __libc_lock_lock (lock); -- -- if (ni == NULL) -- init_nss_interface (); -- -- __libc_lock_unlock (lock); -- -- result = internal_setgrent (&ent, 0, 0); -- -- if (result == NSS_STATUS_SUCCESS) -- result = internal_getgrnam_r (name, grp, &ent, buffer, buflen, errnop); -- -- internal_endgrent (&ent); -- -- return result; --} -- --/* Searches in /etc/group and the NIS/NIS+ map for a special group id */ --static enum nss_status --internal_getgrgid_r (gid_t gid, struct group *result, ent_t *ent, -- char *buffer, size_t buflen, int *errnop) --{ -- struct parser_data *data = (void *) buffer; -- while (1) -- { -- fpos_t pos; -- int parse_res = 0; -- char *p; -- -- do -- { -- /* We need at least 3 characters for one line. */ -- if (__glibc_unlikely (buflen < 3)) -- { -- erange: -- *errnop = ERANGE; -- return NSS_STATUS_TRYAGAIN; -- } -- -- fgetpos (ent->stream, &pos); -- buffer[buflen - 1] = '\xff'; -- p = fgets_unlocked (buffer, buflen, ent->stream); -- if (p == NULL && feof_unlocked (ent->stream)) -- return NSS_STATUS_NOTFOUND; -- -- if (p == NULL || __builtin_expect (buffer[buflen - 1] != '\xff', 0)) -- { -- erange_reset: -- fsetpos (ent->stream, &pos); -- goto erange; -- } -- -- /* Terminate the line for any case. */ -- buffer[buflen - 1] = '\0'; -- -- /* Skip leading blanks. */ -- while (isspace (*p)) -- ++p; -- } -- while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */ -- /* Parse the line. If it is invalid, loop to -- get the next line of the file to parse. */ -- !(parse_res = _nss_files_parse_grent (p, result, data, buflen, -- errnop))); -- -- if (__glibc_unlikely (parse_res == -1)) -- /* The parser ran out of space. */ -- goto erange_reset; -- -- /* This is a real entry. */ -- if (result->gr_name[0] != '+' && result->gr_name[0] != '-') -- { -- if (result->gr_gid == gid) -- return NSS_STATUS_SUCCESS; -- else -- continue; -- } -- -- /* -group */ -- if (result->gr_name[0] == '-' && result->gr_name[1] != '\0') -- { -- blacklist_store_name (&result->gr_name[1], ent); -- continue; -- } -- -- /* +group */ -- if (result->gr_name[0] == '+' && result->gr_name[1] != '\0') -- { -- /* Yes, no +1, see the memcpy call below. */ -- size_t len = strlen (result->gr_name); -- char buf[len]; -- enum nss_status status; -- -- /* Store the group in the blacklist for the "+" at the end of -- /etc/group */ -- memcpy (buf, &result->gr_name[1], len); -- status = getgrnam_plusgroup (&result->gr_name[1], result, ent, -- buffer, buflen, errnop); -- blacklist_store_name (buf, ent); -- if (status == NSS_STATUS_SUCCESS && result->gr_gid == gid) -- break; -- else -- continue; -- } -- /* +:... */ -- if (result->gr_name[0] == '+' && result->gr_name[1] == '\0') -- { -- if (!nss_getgrgid_r) -- return NSS_STATUS_UNAVAIL; -- -- enum nss_status status = nss_getgrgid_r (gid, result, buffer, buflen, -- errnop); -- if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */ -- return NSS_STATUS_NOTFOUND; -- else -- return status; -- } -- } -- -- return NSS_STATUS_SUCCESS; --} -- --enum nss_status --_nss_compat_getgrgid_r (gid_t gid, struct group *grp, -- char *buffer, size_t buflen, int *errnop) --{ -- ent_t ent = { TRUE, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0 }}; -- enum nss_status result; -- -- __libc_lock_lock (lock); -- -- if (ni == NULL) -- init_nss_interface (); -- -- __libc_lock_unlock (lock); -- -- result = internal_setgrent (&ent, 0, 0); -- -- if (result == NSS_STATUS_SUCCESS) -- result = internal_getgrgid_r (gid, grp, &ent, buffer, buflen, errnop); -- -- internal_endgrent (&ent); -- -- return result; --} -- -- --/* Support routines for remembering -@netgroup and -user entries. -- The names are stored in a single string with `|' as separator. */ --static void --blacklist_store_name (const char *name, ent_t *ent) --{ -- int namelen = strlen (name); -- char *tmp; -- -- /* first call, setup cache */ -- if (ent->blacklist.size == 0) -- { -- ent->blacklist.size = MAX (BLACKLIST_INITIAL_SIZE, 2 * namelen); -- ent->blacklist.data = malloc (ent->blacklist.size); -- if (ent->blacklist.data == NULL) -- return; -- ent->blacklist.data[0] = '|'; -- ent->blacklist.data[1] = '\0'; -- ent->blacklist.current = 1; -- } -- else -- { -- if (in_blacklist (name, namelen, ent)) -- return; /* no duplicates */ -- -- if (ent->blacklist.current + namelen + 1 >= ent->blacklist.size) -- { -- ent->blacklist.size += MAX (BLACKLIST_INCREMENT, 2 * namelen); -- tmp = realloc (ent->blacklist.data, ent->blacklist.size); -- if (tmp == NULL) -- { -- free (ent->blacklist.data); -- ent->blacklist.size = 0; -- return; -- } -- ent->blacklist.data = tmp; -- } -- } -- -- tmp = stpcpy (ent->blacklist.data + ent->blacklist.current, name); -- *tmp++ = '|'; -- *tmp = '\0'; -- ent->blacklist.current += namelen + 1; -- -- return; --} -- --/* returns TRUE if ent->blacklist contains name, else FALSE */ --static bool_t --in_blacklist (const char *name, int namelen, ent_t *ent) --{ -- char buf[namelen + 3]; -- char *cp; -- -- if (ent->blacklist.data == NULL) -- return FALSE; -- -- buf[0] = '|'; -- cp = stpcpy (&buf[1], name); -- *cp++ = '|'; -- *cp = '\0'; -- return strstr (ent->blacklist.data, buf) != NULL; --} -Index: glibc-2.26/nis/nss_compat/compat-initgroups.c -=================================================================== ---- glibc-2.26.orig/nis/nss_compat/compat-initgroups.c -+++ /dev/null -@@ -1,576 +0,0 @@ --/* Copyright (C) 1998-2017 Free Software Foundation, Inc. -- This file is part of the GNU C Library. -- Contributed by Thorsten Kukuk , 1998. -- -- 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 --#include --#include --#include --#include -- --static service_user *ni; --/* Type of the lookup function. */ --static enum nss_status (*nss_initgroups_dyn) (const char *, gid_t, -- long int *, long int *, -- gid_t **, long int, int *); --static enum nss_status (*nss_getgrnam_r) (const char *name, -- struct group * grp, char *buffer, -- size_t buflen, int *errnop); --static enum nss_status (*nss_getgrgid_r) (gid_t gid, struct group * grp, -- char *buffer, size_t buflen, -- int *errnop); --static enum nss_status (*nss_setgrent) (int stayopen); --static enum nss_status (*nss_getgrent_r) (struct group * grp, char *buffer, -- size_t buflen, int *errnop); --static enum nss_status (*nss_endgrent) (void); -- --/* Protect global state against multiple changers. */ --__libc_lock_define_initialized (static, lock) -- -- --/* Get the declaration of the parser function. */ --#define ENTNAME grent --#define STRUCTURE group --#define EXTERN_PARSER --#include -- --/* Structure for remembering -group members ... */ --#define BLACKLIST_INITIAL_SIZE 512 --#define BLACKLIST_INCREMENT 256 --struct blacklist_t --{ -- char *data; -- int current; -- int size; --}; -- --struct ent_t --{ -- bool files; -- bool need_endgrent; -- bool skip_initgroups_dyn; -- FILE *stream; -- struct blacklist_t blacklist; --}; --typedef struct ent_t ent_t; -- --/* Prototypes for local functions. */ --static void blacklist_store_name (const char *, ent_t *); --static int in_blacklist (const char *, int, ent_t *); -- --/* Initialize the NSS interface/functions. The calling function must -- hold the lock. */ --static void --init_nss_interface (void) --{ -- __libc_lock_lock (lock); -- -- /* Retest. */ -- if (ni == NULL -- && __nss_database_lookup ("group_compat", NULL, "nis", &ni) >= 0) -- { -- nss_initgroups_dyn = __nss_lookup_function (ni, "initgroups_dyn"); -- nss_getgrnam_r = __nss_lookup_function (ni, "getgrnam_r"); -- nss_getgrgid_r = __nss_lookup_function (ni, "getgrgid_r"); -- nss_setgrent = __nss_lookup_function (ni, "setgrent"); -- nss_getgrent_r = __nss_lookup_function (ni, "getgrent_r"); -- nss_endgrent = __nss_lookup_function (ni, "endgrent"); -- } -- -- __libc_lock_unlock (lock); --} -- --static enum nss_status --internal_setgrent (ent_t *ent) --{ -- enum nss_status status = NSS_STATUS_SUCCESS; -- -- ent->files = true; -- -- if (ni == NULL) -- init_nss_interface (); -- -- if (ent->blacklist.data != NULL) -- { -- ent->blacklist.current = 1; -- ent->blacklist.data[0] = '|'; -- ent->blacklist.data[1] = '\0'; -- } -- else -- ent->blacklist.current = 0; -- -- ent->stream = fopen ("/etc/group", "rme"); -- -- if (ent->stream == NULL) -- status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; -- else -- /* We take care of locking ourself. */ -- __fsetlocking (ent->stream, FSETLOCKING_BYCALLER); -- -- return status; --} -- -- --static enum nss_status --internal_endgrent (ent_t *ent) --{ -- if (ent->stream != NULL) -- { -- fclose (ent->stream); -- ent->stream = NULL; -- } -- -- if (ent->blacklist.data != NULL) -- { -- ent->blacklist.current = 1; -- ent->blacklist.data[0] = '|'; -- ent->blacklist.data[1] = '\0'; -- } -- else -- ent->blacklist.current = 0; -- -- if (ent->need_endgrent && nss_endgrent != NULL) -- nss_endgrent (); -- -- return NSS_STATUS_SUCCESS; --} -- --/* Add new group record. */ --static void --add_group (long int *start, long int *size, gid_t **groupsp, long int limit, -- gid_t gid) --{ -- gid_t *groups = *groupsp; -- -- /* Matches user. Insert this group. */ -- if (__glibc_unlikely (*start == *size)) -- { -- /* Need a bigger buffer. */ -- gid_t *newgroups; -- long int newsize; -- -- if (limit > 0 && *size == limit) -- /* We reached the maximum. */ -- return; -- -- if (limit <= 0) -- newsize = 2 * *size; -- else -- newsize = MIN (limit, 2 * *size); -- -- newgroups = realloc (groups, newsize * sizeof (*groups)); -- if (newgroups == NULL) -- return; -- *groupsp = groups = newgroups; -- *size = newsize; -- } -- -- groups[*start] = gid; -- *start += 1; --} -- --/* This function checks, if the user is a member of this group and if -- yes, add the group id to the list. Return nonzero is we couldn't -- handle the group because the user is not in the member list. */ --static int --check_and_add_group (const char *user, gid_t group, long int *start, -- long int *size, gid_t **groupsp, long int limit, -- struct group *grp) --{ -- char **member; -- -- /* Don't add main group to list of groups. */ -- if (grp->gr_gid == group) -- return 0; -- -- for (member = grp->gr_mem; *member != NULL; ++member) -- if (strcmp (*member, user) == 0) -- { -- add_group (start, size, groupsp, limit, grp->gr_gid); -- return 0; -- } -- -- return 1; --} -- --/* Get the next group from NSS (+ entry). If the NSS module supports -- initgroups_dyn, get all entries at once. */ --static enum nss_status --getgrent_next_nss (ent_t *ent, char *buffer, size_t buflen, const char *user, -- gid_t group, long int *start, long int *size, -- gid_t **groupsp, long int limit, int *errnop) --{ -- enum nss_status status; -- struct group grpbuf; -- -- /* Try nss_initgroups_dyn if supported. We also need getgrgid_r. -- If this function is not supported, step through the whole group -- database with getgrent_r. */ -- if (! ent->skip_initgroups_dyn) -- { -- long int mystart = 0; -- long int mysize = limit <= 0 ? *size : limit; -- gid_t *mygroups = malloc (mysize * sizeof (gid_t)); -- -- if (mygroups == NULL) -- return NSS_STATUS_TRYAGAIN; -- -- /* For every gid in the list we get from the NSS module, -- get the whole group entry. We need to do this, since we -- need the group name to check if it is in the blacklist. -- In worst case, this is as twice as slow as stepping with -- getgrent_r through the whole group database. But for large -- group databases this is faster, since the user can only be -- in a limited number of groups. */ -- if (nss_initgroups_dyn (user, group, &mystart, &mysize, &mygroups, -- limit, errnop) == NSS_STATUS_SUCCESS) -- { -- status = NSS_STATUS_NOTFOUND; -- -- /* If there is no blacklist we can trust the underlying -- initgroups implementation. */ -- if (ent->blacklist.current <= 1) -- for (int i = 0; i < mystart; i++) -- add_group (start, size, groupsp, limit, mygroups[i]); -- else -- { -- /* A temporary buffer. We use the normal buffer, until we find -- an entry, for which this buffer is to small. In this case, we -- overwrite the pointer with one to a bigger buffer. */ -- char *tmpbuf = buffer; -- size_t tmplen = buflen; -- bool use_malloc = false; -- -- for (int i = 0; i < mystart; i++) -- { -- while ((status = nss_getgrgid_r (mygroups[i], &grpbuf, -- tmpbuf, tmplen, errnop)) -- == NSS_STATUS_TRYAGAIN -- && *errnop == ERANGE) -- { -- if (__libc_use_alloca (tmplen * 2)) -- { -- if (tmpbuf == buffer) -- { -- tmplen *= 2; -- tmpbuf = __alloca (tmplen); -- } -- else -- tmpbuf = extend_alloca (tmpbuf, tmplen, tmplen * 2); -- } -- else -- { -- tmplen *= 2; -- char *newbuf = realloc (use_malloc ? tmpbuf : NULL, tmplen); -- -- if (newbuf == NULL) -- { -- status = NSS_STATUS_TRYAGAIN; -- goto done; -- } -- use_malloc = true; -- tmpbuf = newbuf; -- } -- } -- -- if (__builtin_expect (status != NSS_STATUS_NOTFOUND, 1)) -- { -- if (__builtin_expect (status != NSS_STATUS_SUCCESS, 0)) -- goto done; -- -- if (!in_blacklist (grpbuf.gr_name, -- strlen (grpbuf.gr_name), ent) -- && check_and_add_group (user, group, start, size, -- groupsp, limit, &grpbuf)) -- { -- if (nss_setgrent != NULL) -- { -- nss_setgrent (1); -- ent->need_endgrent = true; -- } -- ent->skip_initgroups_dyn = true; -- -- goto iter; -- } -- } -- } -- -- status = NSS_STATUS_NOTFOUND; -- -- done: -- if (use_malloc) -- free (tmpbuf); -- } -- -- free (mygroups); -- -- return status; -- } -- -- free (mygroups); -- } -- -- /* If we come here, the NSS module does not support initgroups_dyn -- or we were confronted with a split group. In these cases we have -- to step through the whole list ourself. */ -- iter: -- do -- { -- if ((status = nss_getgrent_r (&grpbuf, buffer, buflen, errnop)) != -- NSS_STATUS_SUCCESS) -- break; -- } -- while (in_blacklist (grpbuf.gr_name, strlen (grpbuf.gr_name), ent)); -- -- if (status == NSS_STATUS_SUCCESS) -- check_and_add_group (user, group, start, size, groupsp, limit, &grpbuf); -- -- return status; --} -- --static enum nss_status --internal_getgrent_r (ent_t *ent, char *buffer, size_t buflen, const char *user, -- gid_t group, long int *start, long int *size, -- gid_t **groupsp, long int limit, int *errnop) --{ -- struct parser_data *data = (void *) buffer; -- struct group grpbuf; -- -- if (!ent->files) -- return getgrent_next_nss (ent, buffer, buflen, user, group, -- start, size, groupsp, limit, errnop); -- -- while (1) -- { -- fpos_t pos; -- int parse_res = 0; -- char *p; -- -- do -- { -- /* We need at least 3 characters for one line. */ -- if (__glibc_unlikely (buflen < 3)) -- { -- erange: -- *errnop = ERANGE; -- return NSS_STATUS_TRYAGAIN; -- } -- -- fgetpos (ent->stream, &pos); -- buffer[buflen - 1] = '\xff'; -- p = fgets_unlocked (buffer, buflen, ent->stream); -- if (p == NULL && feof_unlocked (ent->stream)) -- return NSS_STATUS_NOTFOUND; -- -- if (p == NULL || __builtin_expect (buffer[buflen - 1] != '\xff', 0)) -- { -- erange_reset: -- fsetpos (ent->stream, &pos); -- goto erange; -- } -- -- /* Terminate the line for any case. */ -- buffer[buflen - 1] = '\0'; -- -- /* Skip leading blanks. */ -- while (isspace (*p)) -- ++p; -- } -- while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */ -- /* Parse the line. If it is invalid, loop to -- get the next line of the file to parse. */ -- !(parse_res = _nss_files_parse_grent (p, &grpbuf, data, buflen, -- errnop))); -- -- if (__glibc_unlikely (parse_res == -1)) -- /* The parser ran out of space. */ -- goto erange_reset; -- -- if (grpbuf.gr_name[0] != '+' && grpbuf.gr_name[0] != '-') -- /* This is a real entry. */ -- break; -- -- /* -group */ -- if (grpbuf.gr_name[0] == '-' && grpbuf.gr_name[1] != '\0' -- && grpbuf.gr_name[1] != '@') -- { -- blacklist_store_name (&grpbuf.gr_name[1], ent); -- continue; -- } -- -- /* +group */ -- if (grpbuf.gr_name[0] == '+' && grpbuf.gr_name[1] != '\0' -- && grpbuf.gr_name[1] != '@') -- { -- if (in_blacklist (&grpbuf.gr_name[1], -- strlen (&grpbuf.gr_name[1]), ent)) -- continue; -- /* Store the group in the blacklist for the "+" at the end of -- /etc/group */ -- blacklist_store_name (&grpbuf.gr_name[1], ent); -- if (nss_getgrnam_r == NULL) -- return NSS_STATUS_UNAVAIL; -- else if (nss_getgrnam_r (&grpbuf.gr_name[1], &grpbuf, buffer, -- buflen, errnop) != NSS_STATUS_SUCCESS) -- continue; -- -- check_and_add_group (user, group, start, size, groupsp, -- limit, &grpbuf); -- -- return NSS_STATUS_SUCCESS; -- } -- -- /* +:... */ -- if (grpbuf.gr_name[0] == '+' && grpbuf.gr_name[1] == '\0') -- { -- /* If the selected module does not support getgrent_r or -- initgroups_dyn, abort. We cannot find the needed group -- entries. */ -- if (nss_initgroups_dyn == NULL || nss_getgrgid_r == NULL) -- { -- if (nss_setgrent != NULL) -- { -- nss_setgrent (1); -- ent->need_endgrent = true; -- } -- ent->skip_initgroups_dyn = true; -- -- if (nss_getgrent_r == NULL) -- return NSS_STATUS_UNAVAIL; -- } -- -- ent->files = false; -- -- return getgrent_next_nss (ent, buffer, buflen, user, group, -- start, size, groupsp, limit, errnop); -- } -- } -- -- check_and_add_group (user, group, start, size, groupsp, limit, &grpbuf); -- -- return NSS_STATUS_SUCCESS; --} -- -- --enum nss_status --_nss_compat_initgroups_dyn (const char *user, gid_t group, long int *start, -- long int *size, gid_t **groupsp, long int limit, -- int *errnop) --{ -- enum nss_status status; -- ent_t intern = { true, false, false, NULL, {NULL, 0, 0} }; -- -- status = internal_setgrent (&intern); -- if (status != NSS_STATUS_SUCCESS) -- return status; -- -- struct scratch_buffer tmpbuf; -- scratch_buffer_init (&tmpbuf); -- -- do -- { -- while ((status = internal_getgrent_r (&intern, tmpbuf.data, tmpbuf.length, -- user, group, start, size, -- groupsp, limit, errnop)) -- == NSS_STATUS_TRYAGAIN && *errnop == ERANGE) -- if (!scratch_buffer_grow (&tmpbuf)) -- goto done; -- } -- while (status == NSS_STATUS_SUCCESS); -- -- status = NSS_STATUS_SUCCESS; -- -- done: -- scratch_buffer_free (&tmpbuf); -- -- internal_endgrent (&intern); -- -- return status; --} -- -- --/* Support routines for remembering -@netgroup and -user entries. -- The names are stored in a single string with `|' as separator. */ --static void --blacklist_store_name (const char *name, ent_t *ent) --{ -- int namelen = strlen (name); -- char *tmp; -- -- /* First call, setup cache. */ -- if (ent->blacklist.size == 0) -- { -- ent->blacklist.size = MAX (BLACKLIST_INITIAL_SIZE, 2 * namelen); -- ent->blacklist.data = malloc (ent->blacklist.size); -- if (ent->blacklist.data == NULL) -- return; -- ent->blacklist.data[0] = '|'; -- ent->blacklist.data[1] = '\0'; -- ent->blacklist.current = 1; -- } -- else -- { -- if (in_blacklist (name, namelen, ent)) -- return; /* no duplicates */ -- -- if (ent->blacklist.current + namelen + 1 >= ent->blacklist.size) -- { -- ent->blacklist.size += MAX (BLACKLIST_INCREMENT, 2 * namelen); -- tmp = realloc (ent->blacklist.data, ent->blacklist.size); -- if (tmp == NULL) -- { -- free (ent->blacklist.data); -- ent->blacklist.size = 0; -- return; -- } -- ent->blacklist.data = tmp; -- } -- } -- -- tmp = stpcpy (ent->blacklist.data + ent->blacklist.current, name); -- *tmp++ = '|'; -- *tmp = '\0'; -- ent->blacklist.current += namelen + 1; -- -- return; --} -- --/* returns TRUE if ent->blacklist contains name, else FALSE */ --static bool_t --in_blacklist (const char *name, int namelen, ent_t *ent) --{ -- char buf[namelen + 3]; -- char *cp; -- -- if (ent->blacklist.data == NULL) -- return FALSE; -- -- buf[0] = '|'; -- cp = stpcpy (&buf[1], name); -- *cp++ = '|'; -- *cp = '\0'; -- return strstr (ent->blacklist.data, buf) != NULL; --} -Index: glibc-2.26/nis/nss_compat/compat-pwd.c -=================================================================== ---- glibc-2.26.orig/nis/nss_compat/compat-pwd.c -+++ /dev/null -@@ -1,1132 +0,0 @@ --/* Copyright (C) 1996-2017 Free Software Foundation, Inc. -- This file is part of the GNU C Library. -- Contributed by Thorsten Kukuk , 1996. -- -- 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 --#include --#include --#include -- --#include "netgroup.h" -- --static service_user *ni; --static enum nss_status (*nss_setpwent) (int stayopen); --static enum nss_status (*nss_getpwnam_r) (const char *name, -- struct passwd * pwd, char *buffer, -- size_t buflen, int *errnop); --static enum nss_status (*nss_getpwuid_r) (uid_t uid, struct passwd * pwd, -- char *buffer, size_t buflen, -- int *errnop); --static enum nss_status (*nss_getpwent_r) (struct passwd * pwd, char *buffer, -- size_t buflen, int *errnop); --static enum nss_status (*nss_endpwent) (void); -- --/* Get the declaration of the parser function. */ --#define ENTNAME pwent --#define STRUCTURE passwd --#define EXTERN_PARSER --#include -- --/* Structure for remembering -@netgroup and -user members ... */ --#define BLACKLIST_INITIAL_SIZE 512 --#define BLACKLIST_INCREMENT 256 --struct blacklist_t --{ -- char *data; -- int current; -- int size; --}; -- --struct ent_t --{ -- bool netgroup; -- bool first; -- bool files; -- enum nss_status setent_status; -- FILE *stream; -- struct blacklist_t blacklist; -- struct passwd pwd; -- struct __netgrent netgrdata; --}; --typedef struct ent_t ent_t; -- --static ent_t ext_ent = { false, false, true, NSS_STATUS_SUCCESS, NULL, -- { NULL, 0, 0 }, -- { NULL, NULL, 0, 0, NULL, NULL, NULL }}; -- --/* Protect global state against multiple changers. */ --__libc_lock_define_initialized (static, lock) -- --/* Prototypes for local functions. */ --static void blacklist_store_name (const char *, ent_t *); --static int in_blacklist (const char *, int, ent_t *); -- --/* Initialize the NSS interface/functions. The calling function must -- hold the lock. */ --static void --init_nss_interface (void) --{ -- if (__nss_database_lookup ("passwd_compat", NULL, "nis", &ni) >= 0) -- { -- nss_setpwent = __nss_lookup_function (ni, "setpwent"); -- nss_getpwnam_r = __nss_lookup_function (ni, "getpwnam_r"); -- nss_getpwuid_r = __nss_lookup_function (ni, "getpwuid_r"); -- nss_getpwent_r = __nss_lookup_function (ni, "getpwent_r"); -- nss_endpwent = __nss_lookup_function (ni, "endpwent"); -- } --} -- --static void --give_pwd_free (struct passwd *pwd) --{ -- free (pwd->pw_name); -- free (pwd->pw_passwd); -- free (pwd->pw_gecos); -- free (pwd->pw_dir); -- free (pwd->pw_shell); -- -- memset (pwd, '\0', sizeof (struct passwd)); --} -- --static size_t --pwd_need_buflen (struct passwd *pwd) --{ -- size_t len = 0; -- -- if (pwd->pw_passwd != NULL) -- len += strlen (pwd->pw_passwd) + 1; -- -- if (pwd->pw_gecos != NULL) -- len += strlen (pwd->pw_gecos) + 1; -- -- if (pwd->pw_dir != NULL) -- len += strlen (pwd->pw_dir) + 1; -- -- if (pwd->pw_shell != NULL) -- len += strlen (pwd->pw_shell) + 1; -- -- return len; --} -- --static void --copy_pwd_changes (struct passwd *dest, struct passwd *src, -- char *buffer, size_t buflen) --{ -- if (src->pw_passwd != NULL && strlen (src->pw_passwd)) -- { -- if (buffer == NULL) -- dest->pw_passwd = strdup (src->pw_passwd); -- else if (dest->pw_passwd && -- strlen (dest->pw_passwd) >= strlen (src->pw_passwd)) -- strcpy (dest->pw_passwd, src->pw_passwd); -- else -- { -- dest->pw_passwd = buffer; -- strcpy (dest->pw_passwd, src->pw_passwd); -- buffer += strlen (dest->pw_passwd) + 1; -- buflen = buflen - (strlen (dest->pw_passwd) + 1); -- } -- } -- -- if (src->pw_gecos != NULL && strlen (src->pw_gecos)) -- { -- if (buffer == NULL) -- dest->pw_gecos = strdup (src->pw_gecos); -- else if (dest->pw_gecos && -- strlen (dest->pw_gecos) >= strlen (src->pw_gecos)) -- strcpy (dest->pw_gecos, src->pw_gecos); -- else -- { -- dest->pw_gecos = buffer; -- strcpy (dest->pw_gecos, src->pw_gecos); -- buffer += strlen (dest->pw_gecos) + 1; -- buflen = buflen - (strlen (dest->pw_gecos) + 1); -- } -- } -- if (src->pw_dir != NULL && strlen (src->pw_dir)) -- { -- if (buffer == NULL) -- dest->pw_dir = strdup (src->pw_dir); -- else if (dest->pw_dir && strlen (dest->pw_dir) >= strlen (src->pw_dir)) -- strcpy (dest->pw_dir, src->pw_dir); -- else -- { -- dest->pw_dir = buffer; -- strcpy (dest->pw_dir, src->pw_dir); -- buffer += strlen (dest->pw_dir) + 1; -- buflen = buflen - (strlen (dest->pw_dir) + 1); -- } -- } -- -- if (src->pw_shell != NULL && strlen (src->pw_shell)) -- { -- if (buffer == NULL) -- dest->pw_shell = strdup (src->pw_shell); -- else if (dest->pw_shell && -- strlen (dest->pw_shell) >= strlen (src->pw_shell)) -- strcpy (dest->pw_shell, src->pw_shell); -- else -- { -- dest->pw_shell = buffer; -- strcpy (dest->pw_shell, src->pw_shell); -- buffer += strlen (dest->pw_shell) + 1; -- buflen = buflen - (strlen (dest->pw_shell) + 1); -- } -- } --} -- --static enum nss_status --internal_setpwent (ent_t *ent, int stayopen, int needent) --{ -- enum nss_status status = NSS_STATUS_SUCCESS; -- -- ent->first = ent->netgroup = false; -- ent->files = true; -- ent->setent_status = NSS_STATUS_SUCCESS; -- -- /* If something was left over free it. */ -- if (ent->netgroup) -- __internal_endnetgrent (&ent->netgrdata); -- -- if (ent->blacklist.data != NULL) -- { -- ent->blacklist.current = 1; -- ent->blacklist.data[0] = '|'; -- ent->blacklist.data[1] = '\0'; -- } -- else -- ent->blacklist.current = 0; -- -- if (ent->stream == NULL) -- { -- ent->stream = fopen ("/etc/passwd", "rme"); -- -- if (ent->stream == NULL) -- status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; -- else -- /* We take care of locking ourself. */ -- __fsetlocking (ent->stream, FSETLOCKING_BYCALLER); -- } -- else -- rewind (ent->stream); -- -- give_pwd_free (&ent->pwd); -- -- if (needent && status == NSS_STATUS_SUCCESS && nss_setpwent) -- ent->setent_status = nss_setpwent (stayopen); -- -- return status; --} -- -- --enum nss_status --_nss_compat_setpwent (int stayopen) --{ -- enum nss_status result; -- -- __libc_lock_lock (lock); -- -- if (ni == NULL) -- init_nss_interface (); -- -- result = internal_setpwent (&ext_ent, stayopen, 1); -- -- __libc_lock_unlock (lock); -- -- return result; --} -- -- --static enum nss_status --internal_endpwent (ent_t *ent) --{ -- if (ent->stream != NULL) -- { -- fclose (ent->stream); -- ent->stream = NULL; -- } -- -- if (ent->netgroup) -- __internal_endnetgrent (&ent->netgrdata); -- -- ent->first = ent->netgroup = false; -- -- if (ent->blacklist.data != NULL) -- { -- ent->blacklist.current = 1; -- ent->blacklist.data[0] = '|'; -- ent->blacklist.data[1] = '\0'; -- } -- else -- ent->blacklist.current = 0; -- -- give_pwd_free (&ent->pwd); -- -- return NSS_STATUS_SUCCESS; --} -- --enum nss_status --_nss_compat_endpwent (void) --{ -- enum nss_status result; -- -- __libc_lock_lock (lock); -- -- if (nss_endpwent) -- nss_endpwent (); -- -- result = internal_endpwent (&ext_ent); -- -- __libc_lock_unlock (lock); -- -- return result; --} -- -- --static enum nss_status --getpwent_next_nss_netgr (const char *name, struct passwd *result, ent_t *ent, -- char *group, char *buffer, size_t buflen, -- int *errnop) --{ -- char *curdomain = NULL, *host, *user, *domain, *p2; -- int status; -- size_t p2len; -- -- /* Leave function if NSS module does not support getpwnam_r, -- we need this function here. */ -- if (!nss_getpwnam_r) -- return NSS_STATUS_UNAVAIL; -- -- if (ent->first) -- { -- memset (&ent->netgrdata, 0, sizeof (struct __netgrent)); -- __internal_setnetgrent (group, &ent->netgrdata); -- ent->first = false; -- } -- -- while (1) -- { -- status = __internal_getnetgrent_r (&host, &user, &domain, -- &ent->netgrdata, buffer, buflen, -- errnop); -- if (status != 1) -- { -- __internal_endnetgrent (&ent->netgrdata); -- ent->netgroup = 0; -- give_pwd_free (&ent->pwd); -- return NSS_STATUS_RETURN; -- } -- -- if (user == NULL || user[0] == '-') -- continue; -- -- if (domain != NULL) -- { -- if (curdomain == NULL -- && yp_get_default_domain (&curdomain) != YPERR_SUCCESS) -- { -- __internal_endnetgrent (&ent->netgrdata); -- ent->netgroup = false; -- give_pwd_free (&ent->pwd); -- return NSS_STATUS_UNAVAIL; -- } -- if (strcmp (curdomain, domain) != 0) -- continue; -- } -- -- /* If name != NULL, we are called from getpwnam. */ -- if (name != NULL) -- if (strcmp (user, name) != 0) -- continue; -- -- p2len = pwd_need_buflen (&ent->pwd); -- if (p2len > buflen) -- { -- *errnop = ERANGE; -- return NSS_STATUS_TRYAGAIN; -- } -- p2 = buffer + (buflen - p2len); -- buflen -= p2len; -- -- if (nss_getpwnam_r (user, result, buffer, buflen, errnop) != -- NSS_STATUS_SUCCESS) -- continue; -- -- if (!in_blacklist (result->pw_name, strlen (result->pw_name), ent)) -- { -- /* Store the User in the blacklist for possible the "+" at the -- end of /etc/passwd */ -- blacklist_store_name (result->pw_name, ent); -- copy_pwd_changes (result, &ent->pwd, p2, p2len); -- break; -- } -- } -- -- return NSS_STATUS_SUCCESS; --} -- --/* get the next user from NSS (+ entry) */ --static enum nss_status --getpwent_next_nss (struct passwd *result, ent_t *ent, char *buffer, -- size_t buflen, int *errnop) --{ -- enum nss_status status; -- char *p2; -- size_t p2len; -- -- /* Return if NSS module does not support getpwent_r. */ -- if (!nss_getpwent_r) -- return NSS_STATUS_UNAVAIL; -- -- /* If the setpwent call failed, say so. */ -- if (ent->setent_status != NSS_STATUS_SUCCESS) -- return ent->setent_status; -- -- p2len = pwd_need_buflen (&ent->pwd); -- if (p2len > buflen) -- { -- *errnop = ERANGE; -- return NSS_STATUS_TRYAGAIN; -- } -- p2 = buffer + (buflen - p2len); -- buflen -= p2len; -- -- if (ent->first) -- ent->first = false; -- -- do -- { -- if ((status = nss_getpwent_r (result, buffer, buflen, errnop)) != -- NSS_STATUS_SUCCESS) -- return status; -- } -- while (in_blacklist (result->pw_name, strlen (result->pw_name), ent)); -- -- copy_pwd_changes (result, &ent->pwd, p2, p2len); -- -- return NSS_STATUS_SUCCESS; --} -- --/* This function handle the +user entrys in /etc/passwd */ --static enum nss_status --getpwnam_plususer (const char *name, struct passwd *result, ent_t *ent, -- char *buffer, size_t buflen, int *errnop) --{ -- if (!nss_getpwnam_r) -- return NSS_STATUS_UNAVAIL; -- -- struct passwd pwd; -- memset (&pwd, '\0', sizeof (struct passwd)); -- -- copy_pwd_changes (&pwd, result, NULL, 0); -- -- size_t plen = pwd_need_buflen (&pwd); -- if (plen > buflen) -- { -- *errnop = ERANGE; -- return NSS_STATUS_TRYAGAIN; -- } -- char *p = buffer + (buflen - plen); -- buflen -= plen; -- -- enum nss_status status = nss_getpwnam_r (name, result, buffer, buflen, -- errnop); -- if (status != NSS_STATUS_SUCCESS) -- return status; -- -- if (in_blacklist (result->pw_name, strlen (result->pw_name), ent)) -- return NSS_STATUS_NOTFOUND; -- -- copy_pwd_changes (result, &pwd, p, plen); -- give_pwd_free (&pwd); -- /* We found the entry. */ -- return NSS_STATUS_SUCCESS; --} -- --static enum nss_status --getpwent_next_file (struct passwd *result, ent_t *ent, -- char *buffer, size_t buflen, int *errnop) --{ -- struct parser_data *data = (void *) buffer; -- while (1) -- { -- fpos_t pos; -- char *p; -- int parse_res; -- -- do -- { -- /* We need at least 3 characters for one line. */ -- if (__glibc_unlikely (buflen < 3)) -- { -- erange: -- *errnop = ERANGE; -- return NSS_STATUS_TRYAGAIN; -- } -- -- fgetpos (ent->stream, &pos); -- buffer[buflen - 1] = '\xff'; -- p = fgets_unlocked (buffer, buflen, ent->stream); -- if (p == NULL && feof_unlocked (ent->stream)) -- return NSS_STATUS_NOTFOUND; -- -- if (p == NULL || __builtin_expect (buffer[buflen - 1] != '\xff', 0)) -- { -- erange_reset: -- fsetpos (ent->stream, &pos); -- goto erange; -- } -- -- /* Terminate the line for any case. */ -- buffer[buflen - 1] = '\0'; -- -- /* Skip leading blanks. */ -- while (isspace (*p)) -- ++p; -- } -- while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */ -- /* Parse the line. If it is invalid, loop to -- get the next line of the file to parse. */ -- !(parse_res = _nss_files_parse_pwent (p, result, data, buflen, -- errnop))); -- -- if (__glibc_unlikely (parse_res == -1)) -- /* The parser ran out of space. */ -- goto erange_reset; -- -- if (result->pw_name[0] != '+' && result->pw_name[0] != '-') -- /* This is a real entry. */ -- break; -- -- /* -@netgroup */ -- if (result->pw_name[0] == '-' && result->pw_name[1] == '@' -- && result->pw_name[2] != '\0') -- { -- /* XXX Do not use fixed length buffer. */ -- char buf2[1024]; -- char *user, *host, *domain; -- struct __netgrent netgrdata; -- -- memset (&netgrdata, 0, sizeof (struct __netgrent)); -- __internal_setnetgrent (&result->pw_name[2], &netgrdata); -- while (__internal_getnetgrent_r (&host, &user, &domain, &netgrdata, -- buf2, sizeof (buf2), errnop)) -- { -- if (user != NULL && user[0] != '-') -- blacklist_store_name (user, ent); -- } -- __internal_endnetgrent (&netgrdata); -- continue; -- } -- -- /* +@netgroup */ -- if (result->pw_name[0] == '+' && result->pw_name[1] == '@' -- && result->pw_name[2] != '\0') -- { -- enum nss_status status; -- -- ent->netgroup = true; -- ent->first = true; -- copy_pwd_changes (&ent->pwd, result, NULL, 0); -- -- status = getpwent_next_nss_netgr (NULL, result, ent, -- &result->pw_name[2], -- buffer, buflen, errnop); -- if (status == NSS_STATUS_RETURN) -- continue; -- else -- return status; -- } -- -- /* -user */ -- if (result->pw_name[0] == '-' && result->pw_name[1] != '\0' -- && result->pw_name[1] != '@') -- { -- blacklist_store_name (&result->pw_name[1], ent); -- continue; -- } -- -- /* +user */ -- if (result->pw_name[0] == '+' && result->pw_name[1] != '\0' -- && result->pw_name[1] != '@') -- { -- size_t len = strlen (result->pw_name); -- char buf[len]; -- enum nss_status status; -- -- /* Store the User in the blacklist for the "+" at the end of -- /etc/passwd */ -- memcpy (buf, &result->pw_name[1], len); -- status = getpwnam_plususer (&result->pw_name[1], result, ent, -- buffer, buflen, errnop); -- blacklist_store_name (buf, ent); -- -- if (status == NSS_STATUS_SUCCESS) /* We found the entry. */ -- break; -- else if (status == NSS_STATUS_RETURN /* We couldn't parse the entry */ -- || status == NSS_STATUS_NOTFOUND) /* entry doesn't exist */ -- continue; -- else -- { -- if (status == NSS_STATUS_TRYAGAIN) -- { -- /* The parser ran out of space */ -- fsetpos (ent->stream, &pos); -- *errnop = ERANGE; -- } -- return status; -- } -- } -- -- /* +:... */ -- if (result->pw_name[0] == '+' && result->pw_name[1] == '\0') -- { -- ent->files = false; -- ent->first = true; -- copy_pwd_changes (&ent->pwd, result, NULL, 0); -- -- return getpwent_next_nss (result, ent, buffer, buflen, errnop); -- } -- } -- -- return NSS_STATUS_SUCCESS; --} -- -- --static enum nss_status --internal_getpwent_r (struct passwd *pw, ent_t *ent, char *buffer, -- size_t buflen, int *errnop) --{ -- if (ent->netgroup) -- { -- enum nss_status status; -- -- /* We are searching members in a netgroup */ -- /* Since this is not the first call, we don't need the group name */ -- status = getpwent_next_nss_netgr (NULL, pw, ent, NULL, buffer, buflen, -- errnop); -- if (status == NSS_STATUS_RETURN) -- return getpwent_next_file (pw, ent, buffer, buflen, errnop); -- else -- return status; -- } -- else if (ent->files) -- return getpwent_next_file (pw, ent, buffer, buflen, errnop); -- else -- return getpwent_next_nss (pw, ent, buffer, buflen, errnop); -- --} -- --enum nss_status --_nss_compat_getpwent_r (struct passwd *pwd, char *buffer, size_t buflen, -- int *errnop) --{ -- enum nss_status result = NSS_STATUS_SUCCESS; -- -- __libc_lock_lock (lock); -- -- /* Be prepared that the setpwent function was not called before. */ -- if (ni == NULL) -- init_nss_interface (); -- -- if (ext_ent.stream == NULL) -- result = internal_setpwent (&ext_ent, 1, 1); -- -- if (result == NSS_STATUS_SUCCESS) -- result = internal_getpwent_r (pwd, &ext_ent, buffer, buflen, errnop); -- -- __libc_lock_unlock (lock); -- -- return result; --} -- --/* Searches in /etc/passwd and the NIS/NIS+ map for a special user */ --static enum nss_status --internal_getpwnam_r (const char *name, struct passwd *result, ent_t *ent, -- char *buffer, size_t buflen, int *errnop) --{ -- struct parser_data *data = (void *) buffer; -- -- while (1) -- { -- fpos_t pos; -- char *p; -- int parse_res; -- -- do -- { -- /* We need at least 3 characters for one line. */ -- if (__glibc_unlikely (buflen < 3)) -- { -- erange: -- *errnop = ERANGE; -- return NSS_STATUS_TRYAGAIN; -- } -- -- fgetpos (ent->stream, &pos); -- buffer[buflen - 1] = '\xff'; -- p = fgets_unlocked (buffer, buflen, ent->stream); -- if (p == NULL && feof_unlocked (ent->stream)) -- { -- return NSS_STATUS_NOTFOUND; -- } -- if (p == NULL || __builtin_expect (buffer[buflen - 1] != '\xff', 0)) -- { -- erange_reset: -- fsetpos (ent->stream, &pos); -- goto erange; -- } -- -- /* Terminate the line for any case. */ -- buffer[buflen - 1] = '\0'; -- -- /* Skip leading blanks. */ -- while (isspace (*p)) -- ++p; -- } -- while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */ -- /* Parse the line. If it is invalid, loop to -- get the next line of the file to parse. */ -- !(parse_res = _nss_files_parse_pwent (p, result, data, buflen, -- errnop))); -- -- if (__glibc_unlikely (parse_res == -1)) -- /* The parser ran out of space. */ -- goto erange_reset; -- -- /* This is a real entry. */ -- if (result->pw_name[0] != '+' && result->pw_name[0] != '-') -- { -- if (strcmp (result->pw_name, name) == 0) -- return NSS_STATUS_SUCCESS; -- else -- continue; -- } -- -- /* -@netgroup */ -- if (result->pw_name[0] == '-' && result->pw_name[1] == '@' -- && result->pw_name[2] != '\0') -- { -- if (innetgr (&result->pw_name[2], NULL, name, NULL)) -- return NSS_STATUS_NOTFOUND; -- continue; -- } -- -- /* +@netgroup */ -- if (result->pw_name[0] == '+' && result->pw_name[1] == '@' -- && result->pw_name[2] != '\0') -- { -- enum nss_status status; -- -- if (innetgr (&result->pw_name[2], NULL, name, NULL)) -- { -- status = getpwnam_plususer (name, result, ent, buffer, -- buflen, errnop); -- -- if (status == NSS_STATUS_RETURN) -- continue; -- -- return status; -- } -- continue; -- } -- -- /* -user */ -- if (result->pw_name[0] == '-' && result->pw_name[1] != '\0' -- && result->pw_name[1] != '@') -- { -- if (strcmp (&result->pw_name[1], name) == 0) -- return NSS_STATUS_NOTFOUND; -- else -- continue; -- } -- -- /* +user */ -- if (result->pw_name[0] == '+' && result->pw_name[1] != '\0' -- && result->pw_name[1] != '@') -- { -- if (strcmp (name, &result->pw_name[1]) == 0) -- { -- enum nss_status status; -- -- status = getpwnam_plususer (name, result, ent, buffer, buflen, -- errnop); -- if (status == NSS_STATUS_RETURN) -- /* We couldn't parse the entry */ -- return NSS_STATUS_NOTFOUND; -- else -- return status; -- } -- } -- -- /* +:... */ -- if (result->pw_name[0] == '+' && result->pw_name[1] == '\0') -- { -- enum nss_status status; -- -- status = getpwnam_plususer (name, result, ent, -- buffer, buflen, errnop); -- if (status == NSS_STATUS_SUCCESS) /* We found the entry. */ -- break; -- else if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */ -- return NSS_STATUS_NOTFOUND; -- else -- return status; -- } -- } -- return NSS_STATUS_SUCCESS; --} -- --enum nss_status --_nss_compat_getpwnam_r (const char *name, struct passwd *pwd, -- char *buffer, size_t buflen, int *errnop) --{ -- enum nss_status result; -- ent_t ent = { false, false, true, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0 }, -- { NULL, NULL, 0, 0, NULL, NULL, NULL }}; -- -- if (name[0] == '-' || name[0] == '+') -- return NSS_STATUS_NOTFOUND; -- -- __libc_lock_lock (lock); -- -- if (ni == NULL) -- init_nss_interface (); -- -- __libc_lock_unlock (lock); -- -- result = internal_setpwent (&ent, 0, 0); -- -- if (result == NSS_STATUS_SUCCESS) -- result = internal_getpwnam_r (name, pwd, &ent, buffer, buflen, errnop); -- -- internal_endpwent (&ent); -- -- return result; --} -- --/* This function handle the + entry in /etc/passwd for getpwuid */ --static enum nss_status --getpwuid_plususer (uid_t uid, struct passwd *result, char *buffer, -- size_t buflen, int *errnop) --{ -- struct passwd pwd; -- char *p; -- size_t plen; -- -- if (!nss_getpwuid_r) -- return NSS_STATUS_UNAVAIL; -- -- memset (&pwd, '\0', sizeof (struct passwd)); -- -- copy_pwd_changes (&pwd, result, NULL, 0); -- -- plen = pwd_need_buflen (&pwd); -- if (plen > buflen) -- { -- *errnop = ERANGE; -- return NSS_STATUS_TRYAGAIN; -- } -- p = buffer + (buflen - plen); -- buflen -= plen; -- -- if (nss_getpwuid_r (uid, result, buffer, buflen, errnop) == -- NSS_STATUS_SUCCESS) -- { -- copy_pwd_changes (result, &pwd, p, plen); -- give_pwd_free (&pwd); -- /* We found the entry. */ -- return NSS_STATUS_SUCCESS; -- } -- else -- { -- /* Give buffer the old len back */ -- buflen += plen; -- give_pwd_free (&pwd); -- } -- return NSS_STATUS_RETURN; --} -- --/* Searches in /etc/passwd and the NSS subsystem for a special user id */ --static enum nss_status --internal_getpwuid_r (uid_t uid, struct passwd *result, ent_t *ent, -- char *buffer, size_t buflen, int *errnop) --{ -- struct parser_data *data = (void *) buffer; -- -- while (1) -- { -- fpos_t pos; -- char *p; -- int parse_res; -- -- do -- { -- /* We need at least 3 characters for one line. */ -- if (__glibc_unlikely (buflen < 3)) -- { -- erange: -- *errnop = ERANGE; -- return NSS_STATUS_TRYAGAIN; -- } -- -- fgetpos (ent->stream, &pos); -- buffer[buflen - 1] = '\xff'; -- p = fgets_unlocked (buffer, buflen, ent->stream); -- if (p == NULL && feof_unlocked (ent->stream)) -- return NSS_STATUS_NOTFOUND; -- -- if (p == NULL || __builtin_expect (buffer[buflen - 1] != '\xff', 0)) -- { -- erange_reset: -- fsetpos (ent->stream, &pos); -- goto erange; -- } -- -- /* Terminate the line for any case. */ -- buffer[buflen - 1] = '\0'; -- -- /* Skip leading blanks. */ -- while (isspace (*p)) -- ++p; -- } -- while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */ -- /* Parse the line. If it is invalid, loop to -- get the next line of the file to parse. */ -- !(parse_res = _nss_files_parse_pwent (p, result, data, buflen, -- errnop))); -- -- if (__glibc_unlikely (parse_res == -1)) -- /* The parser ran out of space. */ -- goto erange_reset; -- -- /* This is a real entry. */ -- if (result->pw_name[0] != '+' && result->pw_name[0] != '-') -- { -- if (result->pw_uid == uid) -- return NSS_STATUS_SUCCESS; -- else -- continue; -- } -- -- /* -@netgroup */ -- if (result->pw_name[0] == '-' && result->pw_name[1] == '@' -- && result->pw_name[2] != '\0') -- { -- /* -1, because we remove first two character of pw_name. */ -- size_t len = strlen (result->pw_name) - 1; -- char buf[len]; -- enum nss_status status; -- -- memcpy (buf, &result->pw_name[2], len); -- -- status = getpwuid_plususer (uid, result, buffer, buflen, errnop); -- if (status == NSS_STATUS_SUCCESS && -- innetgr (buf, NULL, result->pw_name, NULL)) -- return NSS_STATUS_NOTFOUND; -- -- continue; -- } -- -- /* +@netgroup */ -- if (result->pw_name[0] == '+' && result->pw_name[1] == '@' -- && result->pw_name[2] != '\0') -- { -- /* -1, because we remove first two characters of pw_name. */ -- size_t len = strlen (result->pw_name) - 1; -- char buf[len]; -- enum nss_status status; -- -- memcpy (buf, &result->pw_name[2], len); -- -- status = getpwuid_plususer (uid, result, buffer, buflen, errnop); -- -- if (status == NSS_STATUS_RETURN) -- continue; -- -- if (status == NSS_STATUS_SUCCESS) -- { -- if (innetgr (buf, NULL, result->pw_name, NULL)) -- return NSS_STATUS_SUCCESS; -- } -- else if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */ -- return NSS_STATUS_NOTFOUND; -- else -- return status; -- -- continue; -- } -- -- /* -user */ -- if (result->pw_name[0] == '-' && result->pw_name[1] != '\0' -- && result->pw_name[1] != '@') -- { -- size_t len = strlen (result->pw_name); -- char buf[len]; -- enum nss_status status; -- -- memcpy (buf, &result->pw_name[1], len); -- -- status = getpwuid_plususer (uid, result, buffer, buflen, errnop); -- if (status == NSS_STATUS_SUCCESS && -- innetgr (buf, NULL, result->pw_name, NULL)) -- return NSS_STATUS_NOTFOUND; -- continue; -- } -- -- /* +user */ -- if (result->pw_name[0] == '+' && result->pw_name[1] != '\0' -- && result->pw_name[1] != '@') -- { -- size_t len = strlen (result->pw_name); -- char buf[len]; -- enum nss_status status; -- -- memcpy (buf, &result->pw_name[1], len); -- -- status = getpwuid_plususer (uid, result, buffer, buflen, errnop); -- -- if (status == NSS_STATUS_RETURN) -- continue; -- -- if (status == NSS_STATUS_SUCCESS) -- { -- if (strcmp (buf, result->pw_name) == 0) -- return NSS_STATUS_SUCCESS; -- } -- else if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */ -- return NSS_STATUS_NOTFOUND; -- else -- return status; -- -- continue; -- } -- -- /* +:... */ -- if (result->pw_name[0] == '+' && result->pw_name[1] == '\0') -- { -- enum nss_status status; -- -- status = getpwuid_plususer (uid, result, buffer, buflen, errnop); -- if (status == NSS_STATUS_SUCCESS) /* We found the entry. */ -- break; -- else if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */ -- return NSS_STATUS_NOTFOUND; -- else -- return status; -- } -- } -- return NSS_STATUS_SUCCESS; --} -- --enum nss_status --_nss_compat_getpwuid_r (uid_t uid, struct passwd *pwd, -- char *buffer, size_t buflen, int *errnop) --{ -- enum nss_status result; -- ent_t ent = { false, false, true, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0 }, -- { NULL, NULL, 0, 0, NULL, NULL, NULL }}; -- -- __libc_lock_lock (lock); -- -- if (ni == NULL) -- init_nss_interface (); -- -- __libc_lock_unlock (lock); -- -- result = internal_setpwent (&ent, 0, 0); -- -- if (result == NSS_STATUS_SUCCESS) -- result = internal_getpwuid_r (uid, pwd, &ent, buffer, buflen, errnop); -- -- internal_endpwent (&ent); -- -- return result; --} -- -- --/* Support routines for remembering -@netgroup and -user entries. -- The names are stored in a single string with `|' as separator. */ --static void --blacklist_store_name (const char *name, ent_t *ent) --{ -- int namelen = strlen (name); -- char *tmp; -- -- /* first call, setup cache */ -- if (ent->blacklist.size == 0) -- { -- ent->blacklist.size = MAX (BLACKLIST_INITIAL_SIZE, 2 * namelen); -- ent->blacklist.data = malloc (ent->blacklist.size); -- if (ent->blacklist.data == NULL) -- return; -- ent->blacklist.data[0] = '|'; -- ent->blacklist.data[1] = '\0'; -- ent->blacklist.current = 1; -- } -- else -- { -- if (in_blacklist (name, namelen, ent)) -- return; /* no duplicates */ -- -- if (ent->blacklist.current + namelen + 1 >= ent->blacklist.size) -- { -- ent->blacklist.size += MAX (BLACKLIST_INCREMENT, 2 * namelen); -- tmp = realloc (ent->blacklist.data, ent->blacklist.size); -- if (tmp == NULL) -- { -- free (ent->blacklist.data); -- ent->blacklist.size = 0; -- return; -- } -- ent->blacklist.data = tmp; -- } -- } -- -- tmp = stpcpy (ent->blacklist.data + ent->blacklist.current, name); -- *tmp++ = '|'; -- *tmp = '\0'; -- ent->blacklist.current += namelen + 1; -- -- return; --} -- --/* Returns TRUE if ent->blacklist contains name, else FALSE. */ --static bool_t --in_blacklist (const char *name, int namelen, ent_t *ent) --{ -- char buf[namelen + 3]; -- char *cp; -- -- if (ent->blacklist.data == NULL) -- return FALSE; -- -- buf[0] = '|'; -- cp = stpcpy (&buf[1], name); -- *cp++ = '|'; -- *cp = '\0'; -- return strstr (ent->blacklist.data, buf) != NULL; --} -Index: glibc-2.26/nis/nss_compat/compat-spwd.c -=================================================================== ---- glibc-2.26.orig/nis/nss_compat/compat-spwd.c -+++ /dev/null -@@ -1,858 +0,0 @@ --/* Copyright (C) 1996-2017 Free Software Foundation, Inc. -- This file is part of the GNU C Library. -- Contributed by Thorsten Kukuk , 1996. -- -- 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 --#include --#include --#include -- --#include "netgroup.h" -- --static service_user *ni; --static enum nss_status (*nss_setspent) (int stayopen); --static enum nss_status (*nss_getspnam_r) (const char *name, struct spwd * sp, -- char *buffer, size_t buflen, -- int *errnop); --static enum nss_status (*nss_getspent_r) (struct spwd * sp, char *buffer, -- size_t buflen, int *errnop); --static enum nss_status (*nss_endspent) (void); -- --/* Get the declaration of the parser function. */ --#define ENTNAME spent --#define STRUCTURE spwd --#define EXTERN_PARSER --#include -- --/* Structure for remembering -@netgroup and -user members ... */ --#define BLACKLIST_INITIAL_SIZE 512 --#define BLACKLIST_INCREMENT 256 --struct blacklist_t --{ -- char *data; -- int current; -- int size; --}; -- --struct ent_t --{ -- bool netgroup; -- bool files; -- bool first; -- enum nss_status setent_status; -- FILE *stream; -- struct blacklist_t blacklist; -- struct spwd pwd; -- struct __netgrent netgrdata; --}; --typedef struct ent_t ent_t; -- --static ent_t ext_ent = { false, true, false, NSS_STATUS_SUCCESS, NULL, -- { NULL, 0, 0}, -- { NULL, NULL, 0, 0, 0, 0, 0, 0, 0}}; -- --/* Protect global state against multiple changers. */ --__libc_lock_define_initialized (static, lock) -- --/* Prototypes for local functions. */ --static void blacklist_store_name (const char *, ent_t *); --static int in_blacklist (const char *, int, ent_t *); -- --/* Initialize the NSS interface/functions. The calling function must -- hold the lock. */ --static void --init_nss_interface (void) --{ -- if (__nss_database_lookup ("shadow_compat", "passwd_compat", -- "nis", &ni) >= 0) -- { -- nss_setspent = __nss_lookup_function (ni, "setspent"); -- nss_getspnam_r = __nss_lookup_function (ni, "getspnam_r"); -- nss_getspent_r = __nss_lookup_function (ni, "getspent_r"); -- nss_endspent = __nss_lookup_function (ni, "endspent"); -- } --} -- --static void --give_spwd_free (struct spwd *pwd) --{ -- free (pwd->sp_namp); -- free (pwd->sp_pwdp); -- -- memset (pwd, '\0', sizeof (struct spwd)); -- pwd->sp_warn = -1; -- pwd->sp_inact = -1; -- pwd->sp_expire = -1; -- pwd->sp_flag = ~0ul; --} -- --static int --spwd_need_buflen (struct spwd *pwd) --{ -- int len = 0; -- -- if (pwd->sp_pwdp != NULL) -- len += strlen (pwd->sp_pwdp) + 1; -- -- return len; --} -- --static void --copy_spwd_changes (struct spwd *dest, struct spwd *src, -- char *buffer, size_t buflen) --{ -- if (src->sp_pwdp != NULL && strlen (src->sp_pwdp)) -- { -- if (buffer == NULL) -- dest->sp_pwdp = strdup (src->sp_pwdp); -- else if (dest->sp_pwdp && -- strlen (dest->sp_pwdp) >= strlen (src->sp_pwdp)) -- strcpy (dest->sp_pwdp, src->sp_pwdp); -- else -- { -- dest->sp_pwdp = buffer; -- strcpy (dest->sp_pwdp, src->sp_pwdp); -- buffer += strlen (dest->sp_pwdp) + 1; -- buflen = buflen - (strlen (dest->sp_pwdp) + 1); -- } -- } -- if (src->sp_lstchg != 0) -- dest->sp_lstchg = src->sp_lstchg; -- if (src->sp_min != 0) -- dest->sp_min = src->sp_min; -- if (src->sp_max != 0) -- dest->sp_max = src->sp_max; -- if (src->sp_warn != -1) -- dest->sp_warn = src->sp_warn; -- if (src->sp_inact != -1) -- dest->sp_inact = src->sp_inact; -- if (src->sp_expire != -1) -- dest->sp_expire = src->sp_expire; -- if (src->sp_flag != ~0ul) -- dest->sp_flag = src->sp_flag; --} -- --static enum nss_status --internal_setspent (ent_t *ent, int stayopen, int needent) --{ -- enum nss_status status = NSS_STATUS_SUCCESS; -- -- ent->first = ent->netgroup = 0; -- ent->files = true; -- -- /* If something was left over free it. */ -- if (ent->netgroup) -- __internal_endnetgrent (&ent->netgrdata); -- -- if (ent->blacklist.data != NULL) -- { -- ent->blacklist.current = 1; -- ent->blacklist.data[0] = '|'; -- ent->blacklist.data[1] = '\0'; -- } -- else -- ent->blacklist.current = 0; -- -- if (ent->stream == NULL) -- { -- ent->stream = fopen ("/etc/shadow", "rme"); -- -- if (ent->stream == NULL) -- status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; -- else -- /* We take care of locking ourself. */ -- __fsetlocking (ent->stream, FSETLOCKING_BYCALLER); -- } -- else -- rewind (ent->stream); -- -- give_spwd_free (&ent->pwd); -- -- if (needent && status == NSS_STATUS_SUCCESS && nss_setspent) -- ent->setent_status = nss_setspent (stayopen); -- -- return status; --} -- -- --enum nss_status --_nss_compat_setspent (int stayopen) --{ -- enum nss_status result; -- -- __libc_lock_lock (lock); -- -- if (ni == NULL) -- init_nss_interface (); -- -- result = internal_setspent (&ext_ent, stayopen, 1); -- -- __libc_lock_unlock (lock); -- -- return result; --} -- -- --static enum nss_status --internal_endspent (ent_t *ent) --{ -- if (ent->stream != NULL) -- { -- fclose (ent->stream); -- ent->stream = NULL; -- } -- -- if (ent->netgroup) -- __internal_endnetgrent (&ent->netgrdata); -- -- ent->first = ent->netgroup = false; -- ent->files = true; -- -- if (ent->blacklist.data != NULL) -- { -- ent->blacklist.current = 1; -- ent->blacklist.data[0] = '|'; -- ent->blacklist.data[1] = '\0'; -- } -- else -- ent->blacklist.current = 0; -- -- give_spwd_free (&ent->pwd); -- -- return NSS_STATUS_SUCCESS; --} -- --enum nss_status --_nss_compat_endspent (void) --{ -- enum nss_status result; -- -- __libc_lock_lock (lock); -- -- if (nss_endspent) -- nss_endspent (); -- -- result = internal_endspent (&ext_ent); -- -- __libc_lock_unlock (lock); -- -- return result; --} -- -- --static enum nss_status --getspent_next_nss_netgr (const char *name, struct spwd *result, ent_t *ent, -- char *group, char *buffer, size_t buflen, -- int *errnop) --{ -- char *curdomain = NULL, *host, *user, *domain, *p2; -- size_t p2len; -- -- if (!nss_getspnam_r) -- return NSS_STATUS_UNAVAIL; -- -- /* If the setpwent call failed, say so. */ -- if (ent->setent_status != NSS_STATUS_SUCCESS) -- return ent->setent_status; -- -- if (ent->first) -- { -- memset (&ent->netgrdata, 0, sizeof (struct __netgrent)); -- __internal_setnetgrent (group, &ent->netgrdata); -- ent->first = false; -- } -- -- while (1) -- { -- enum nss_status status; -- -- status = __internal_getnetgrent_r (&host, &user, &domain, -- &ent->netgrdata, buffer, buflen, -- errnop); -- if (status != 1) -- { -- __internal_endnetgrent (&ent->netgrdata); -- ent->netgroup = false; -- give_spwd_free (&ent->pwd); -- return NSS_STATUS_RETURN; -- } -- -- if (user == NULL || user[0] == '-') -- continue; -- -- if (domain != NULL) -- { -- if (curdomain == NULL -- && yp_get_default_domain (&curdomain) != YPERR_SUCCESS) -- { -- __internal_endnetgrent (&ent->netgrdata); -- ent->netgroup = false; -- give_spwd_free (&ent->pwd); -- return NSS_STATUS_UNAVAIL; -- } -- if (strcmp (curdomain, domain) != 0) -- continue; -- } -- -- /* If name != NULL, we are called from getpwnam */ -- if (name != NULL) -- if (strcmp (user, name) != 0) -- continue; -- -- p2len = spwd_need_buflen (&ent->pwd); -- if (p2len > buflen) -- { -- *errnop = ERANGE; -- return NSS_STATUS_TRYAGAIN; -- } -- p2 = buffer + (buflen - p2len); -- buflen -= p2len; -- -- if (nss_getspnam_r (user, result, buffer, buflen, errnop) != -- NSS_STATUS_SUCCESS) -- continue; -- -- if (!in_blacklist (result->sp_namp, strlen (result->sp_namp), ent)) -- { -- /* Store the User in the blacklist for possible the "+" at the -- end of /etc/passwd */ -- blacklist_store_name (result->sp_namp, ent); -- copy_spwd_changes (result, &ent->pwd, p2, p2len); -- break; -- } -- } -- -- return NSS_STATUS_SUCCESS; --} -- -- --static enum nss_status --getspent_next_nss (struct spwd *result, ent_t *ent, -- char *buffer, size_t buflen, int *errnop) --{ -- enum nss_status status; -- char *p2; -- size_t p2len; -- -- if (!nss_getspent_r) -- return NSS_STATUS_UNAVAIL; -- -- p2len = spwd_need_buflen (&ent->pwd); -- if (p2len > buflen) -- { -- *errnop = ERANGE; -- return NSS_STATUS_TRYAGAIN; -- } -- p2 = buffer + (buflen - p2len); -- buflen -= p2len; -- do -- { -- if ((status = nss_getspent_r (result, buffer, buflen, errnop)) != -- NSS_STATUS_SUCCESS) -- return status; -- } -- while (in_blacklist (result->sp_namp, strlen (result->sp_namp), ent)); -- -- copy_spwd_changes (result, &ent->pwd, p2, p2len); -- -- return NSS_STATUS_SUCCESS; --} -- -- --/* This function handle the +user entrys in /etc/shadow */ --static enum nss_status --getspnam_plususer (const char *name, struct spwd *result, ent_t *ent, -- char *buffer, size_t buflen, int *errnop) --{ -- if (!nss_getspnam_r) -- return NSS_STATUS_UNAVAIL; -- -- struct spwd pwd; -- memset (&pwd, '\0', sizeof (struct spwd)); -- pwd.sp_warn = -1; -- pwd.sp_inact = -1; -- pwd.sp_expire = -1; -- pwd.sp_flag = ~0ul; -- -- copy_spwd_changes (&pwd, result, NULL, 0); -- -- size_t plen = spwd_need_buflen (&pwd); -- if (plen > buflen) -- { -- *errnop = ERANGE; -- return NSS_STATUS_TRYAGAIN; -- } -- char *p = buffer + (buflen - plen); -- buflen -= plen; -- -- enum nss_status status = nss_getspnam_r (name, result, buffer, buflen, -- errnop); -- if (status != NSS_STATUS_SUCCESS) -- return status; -- -- if (in_blacklist (result->sp_namp, strlen (result->sp_namp), ent)) -- return NSS_STATUS_NOTFOUND; -- -- copy_spwd_changes (result, &pwd, p, plen); -- give_spwd_free (&pwd); -- /* We found the entry. */ -- return NSS_STATUS_SUCCESS; --} -- -- --static enum nss_status --getspent_next_file (struct spwd *result, ent_t *ent, -- char *buffer, size_t buflen, int *errnop) --{ -- struct parser_data *data = (void *) buffer; -- while (1) -- { -- fpos_t pos; -- int parse_res = 0; -- char *p; -- -- do -- { -- /* We need at least 3 characters for one line. */ -- if (__glibc_unlikely (buflen < 3)) -- { -- erange: -- *errnop = ERANGE; -- return NSS_STATUS_TRYAGAIN; -- } -- -- fgetpos (ent->stream, &pos); -- buffer[buflen - 1] = '\xff'; -- p = fgets_unlocked (buffer, buflen, ent->stream); -- if (p == NULL && feof_unlocked (ent->stream)) -- return NSS_STATUS_NOTFOUND; -- -- if (p == NULL || __builtin_expect (buffer[buflen - 1] != '\xff', 0)) -- { -- erange_reset: -- fsetpos (ent->stream, &pos); -- goto erange; -- } -- -- /* Skip leading blanks. */ -- while (isspace (*p)) -- ++p; -- } -- while (*p == '\0' || *p == '#' /* Ignore empty and comment lines. */ -- /* Parse the line. If it is invalid, loop to -- get the next line of the file to parse. */ -- || !(parse_res = _nss_files_parse_spent (p, result, data, -- buflen, errnop))); -- -- if (__glibc_unlikely (parse_res == -1)) -- /* The parser ran out of space. */ -- goto erange_reset; -- -- if (result->sp_namp[0] != '+' && result->sp_namp[0] != '-') -- /* This is a real entry. */ -- break; -- -- /* -@netgroup */ -- if (result->sp_namp[0] == '-' && result->sp_namp[1] == '@' -- && result->sp_namp[2] != '\0') -- { -- /* XXX Do not use fixed length buffers. */ -- char buf2[1024]; -- char *user, *host, *domain; -- struct __netgrent netgrdata; -- -- memset (&netgrdata, 0, sizeof (struct __netgrent)); -- __internal_setnetgrent (&result->sp_namp[2], &netgrdata); -- while (__internal_getnetgrent_r (&host, &user, &domain, -- &netgrdata, buf2, sizeof (buf2), -- errnop)) -- { -- if (user != NULL && user[0] != '-') -- blacklist_store_name (user, ent); -- } -- __internal_endnetgrent (&netgrdata); -- continue; -- } -- -- /* +@netgroup */ -- if (result->sp_namp[0] == '+' && result->sp_namp[1] == '@' -- && result->sp_namp[2] != '\0') -- { -- int status; -- -- ent->netgroup = true; -- ent->first = true; -- copy_spwd_changes (&ent->pwd, result, NULL, 0); -- -- status = getspent_next_nss_netgr (NULL, result, ent, -- &result->sp_namp[2], -- buffer, buflen, errnop); -- if (status == NSS_STATUS_RETURN) -- continue; -- else -- return status; -- } -- -- /* -user */ -- if (result->sp_namp[0] == '-' && result->sp_namp[1] != '\0' -- && result->sp_namp[1] != '@') -- { -- blacklist_store_name (&result->sp_namp[1], ent); -- continue; -- } -- -- /* +user */ -- if (result->sp_namp[0] == '+' && result->sp_namp[1] != '\0' -- && result->sp_namp[1] != '@') -- { -- size_t len = strlen (result->sp_namp); -- char buf[len]; -- enum nss_status status; -- -- /* Store the User in the blacklist for the "+" at the end of -- /etc/passwd */ -- memcpy (buf, &result->sp_namp[1], len); -- status = getspnam_plususer (&result->sp_namp[1], result, ent, -- buffer, buflen, errnop); -- blacklist_store_name (buf, ent); -- -- if (status == NSS_STATUS_SUCCESS) /* We found the entry. */ -- break; -- /* We couldn't parse the entry */ -- else if (status == NSS_STATUS_RETURN -- /* entry doesn't exist */ -- || status == NSS_STATUS_NOTFOUND) -- continue; -- else -- { -- if (status == NSS_STATUS_TRYAGAIN) -- { -- fsetpos (ent->stream, &pos); -- *errnop = ERANGE; -- } -- return status; -- } -- } -- -- /* +:... */ -- if (result->sp_namp[0] == '+' && result->sp_namp[1] == '\0') -- { -- ent->files = false; -- ent->first = true; -- copy_spwd_changes (&ent->pwd, result, NULL, 0); -- -- return getspent_next_nss (result, ent, buffer, buflen, errnop); -- } -- } -- -- return NSS_STATUS_SUCCESS; --} -- -- --static enum nss_status --internal_getspent_r (struct spwd *pw, ent_t *ent, -- char *buffer, size_t buflen, int *errnop) --{ -- if (ent->netgroup) -- { -- enum nss_status status; -- -- /* We are searching members in a netgroup */ -- /* Since this is not the first call, we don't need the group name */ -- status = getspent_next_nss_netgr (NULL, pw, ent, NULL, buffer, -- buflen, errnop); -- -- if (status == NSS_STATUS_RETURN) -- return getspent_next_file (pw, ent, buffer, buflen, errnop); -- else -- return status; -- } -- else if (ent->files) -- return getspent_next_file (pw, ent, buffer, buflen, errnop); -- else -- return getspent_next_nss (pw, ent, buffer, buflen, errnop); --} -- -- --enum nss_status --_nss_compat_getspent_r (struct spwd *pwd, char *buffer, size_t buflen, -- int *errnop) --{ -- enum nss_status result = NSS_STATUS_SUCCESS; -- -- __libc_lock_lock (lock); -- -- /* Be prepared that the setpwent function was not called before. */ -- if (ni == NULL) -- init_nss_interface (); -- -- if (ext_ent.stream == NULL) -- result = internal_setspent (&ext_ent, 1, 1); -- -- if (result == NSS_STATUS_SUCCESS) -- result = internal_getspent_r (pwd, &ext_ent, buffer, buflen, errnop); -- -- __libc_lock_unlock (lock); -- -- return result; --} -- -- --/* Searches in /etc/passwd and the NIS/NIS+ map for a special user */ --static enum nss_status --internal_getspnam_r (const char *name, struct spwd *result, ent_t *ent, -- char *buffer, size_t buflen, int *errnop) --{ -- struct parser_data *data = (void *) buffer; -- -- while (1) -- { -- fpos_t pos; -- char *p; -- int parse_res; -- -- do -- { -- /* We need at least 3 characters for one line. */ -- if (__glibc_unlikely (buflen < 3)) -- { -- erange: -- *errnop = ERANGE; -- return NSS_STATUS_TRYAGAIN; -- } -- -- fgetpos (ent->stream, &pos); -- buffer[buflen - 1] = '\xff'; -- p = fgets_unlocked (buffer, buflen, ent->stream); -- if (p == NULL && feof_unlocked (ent->stream)) -- return NSS_STATUS_NOTFOUND; -- -- if (p == NULL || buffer[buflen - 1] != '\xff') -- { -- erange_reset: -- fsetpos (ent->stream, &pos); -- goto erange; -- } -- -- /* Terminate the line for any case. */ -- buffer[buflen - 1] = '\0'; -- -- /* Skip leading blanks. */ -- while (isspace (*p)) -- ++p; -- } -- while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */ -- /* Parse the line. If it is invalid, loop to -- get the next line of the file to parse. */ -- !(parse_res = _nss_files_parse_spent (p, result, data, buflen, -- errnop))); -- -- if (__glibc_unlikely (parse_res == -1)) -- /* The parser ran out of space. */ -- goto erange_reset; -- -- /* This is a real entry. */ -- if (result->sp_namp[0] != '+' && result->sp_namp[0] != '-') -- { -- if (strcmp (result->sp_namp, name) == 0) -- return NSS_STATUS_SUCCESS; -- else -- continue; -- } -- -- /* -@netgroup */ -- /* If the loaded NSS module does not support this service, add -- all users from a +@netgroup entry to the blacklist, too. */ -- if (result->sp_namp[0] == '-' && result->sp_namp[1] == '@' -- && result->sp_namp[2] != '\0') -- { -- if (innetgr (&result->sp_namp[2], NULL, name, NULL)) -- return NSS_STATUS_NOTFOUND; -- continue; -- } -- -- /* +@netgroup */ -- if (result->sp_namp[0] == '+' && result->sp_namp[1] == '@' -- && result->sp_namp[2] != '\0') -- { -- enum nss_status status; -- -- if (innetgr (&result->sp_namp[2], NULL, name, NULL)) -- { -- status = getspnam_plususer (name, result, ent, buffer, -- buflen, errnop); -- -- if (status == NSS_STATUS_RETURN) -- continue; -- -- return status; -- } -- continue; -- } -- -- /* -user */ -- if (result->sp_namp[0] == '-' && result->sp_namp[1] != '\0' -- && result->sp_namp[1] != '@') -- { -- if (strcmp (&result->sp_namp[1], name) == 0) -- return NSS_STATUS_NOTFOUND; -- else -- continue; -- } -- -- /* +user */ -- if (result->sp_namp[0] == '+' && result->sp_namp[1] != '\0' -- && result->sp_namp[1] != '@') -- { -- if (strcmp (name, &result->sp_namp[1]) == 0) -- { -- enum nss_status status; -- -- status = getspnam_plususer (name, result, ent, -- buffer, buflen, errnop); -- -- if (status == NSS_STATUS_RETURN) -- /* We couldn't parse the entry */ -- return NSS_STATUS_NOTFOUND; -- else -- return status; -- } -- } -- -- /* +:... */ -- if (result->sp_namp[0] == '+' && result->sp_namp[1] == '\0') -- { -- enum nss_status status; -- -- status = getspnam_plususer (name, result, ent, -- buffer, buflen, errnop); -- -- if (status == NSS_STATUS_SUCCESS) -- /* We found the entry. */ -- break; -- else if (status == NSS_STATUS_RETURN) -- /* We couldn't parse the entry */ -- return NSS_STATUS_NOTFOUND; -- else -- return status; -- } -- } -- return NSS_STATUS_SUCCESS; --} -- -- --enum nss_status --_nss_compat_getspnam_r (const char *name, struct spwd *pwd, -- char *buffer, size_t buflen, int *errnop) --{ -- enum nss_status result; -- ent_t ent = { false, true, false, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0}, -- { NULL, NULL, 0, 0, 0, 0, 0, 0, 0}}; -- -- if (name[0] == '-' || name[0] == '+') -- return NSS_STATUS_NOTFOUND; -- -- __libc_lock_lock (lock); -- -- if (ni == NULL) -- init_nss_interface (); -- -- __libc_lock_unlock (lock); -- -- result = internal_setspent (&ent, 0, 0); -- -- if (result == NSS_STATUS_SUCCESS) -- result = internal_getspnam_r (name, pwd, &ent, buffer, buflen, errnop); -- -- internal_endspent (&ent); -- -- return result; --} -- -- --/* Support routines for remembering -@netgroup and -user entries. -- The names are stored in a single string with `|' as separator. */ --static void --blacklist_store_name (const char *name, ent_t *ent) --{ -- int namelen = strlen (name); -- char *tmp; -- -- /* first call, setup cache */ -- if (ent->blacklist.size == 0) -- { -- ent->blacklist.size = MAX (BLACKLIST_INITIAL_SIZE, 2 * namelen); -- ent->blacklist.data = malloc (ent->blacklist.size); -- if (ent->blacklist.data == NULL) -- return; -- ent->blacklist.data[0] = '|'; -- ent->blacklist.data[1] = '\0'; -- ent->blacklist.current = 1; -- } -- else -- { -- if (in_blacklist (name, namelen, ent)) -- return; /* no duplicates */ -- -- if (ent->blacklist.current + namelen + 1 >= ent->blacklist.size) -- { -- ent->blacklist.size += MAX (BLACKLIST_INCREMENT, 2 * namelen); -- tmp = realloc (ent->blacklist.data, ent->blacklist.size); -- if (tmp == NULL) -- { -- free (ent->blacklist.data); -- ent->blacklist.size = 0; -- return; -- } -- ent->blacklist.data = tmp; -- } -- } -- -- tmp = stpcpy (ent->blacklist.data + ent->blacklist.current, name); -- *tmp++ = '|'; -- *tmp = '\0'; -- ent->blacklist.current += namelen + 1; -- -- return; --} -- -- --/* Returns TRUE if ent->blacklist contains name, else FALSE. */ --static bool_t --in_blacklist (const char *name, int namelen, ent_t *ent) --{ -- char buf[namelen + 3]; -- char *cp; -- -- if (ent->blacklist.data == NULL) -- return false; -- -- buf[0] = '|'; -- cp = stpcpy (&buf[1], name); -- *cp++ = '|'; -- *cp = '\0'; -- return strstr (ent->blacklist.data, buf) != NULL; --} -Index: glibc-2.26/nss/Makefile -=================================================================== ---- glibc-2.26.orig/nss/Makefile -+++ glibc-2.26/nss/Makefile -@@ -70,7 +70,7 @@ tests += tst-cancel-getpwuid_r - endif - - # Specify rules for the nss_* modules. We have some services. --services := files db -+services := files db compat - - extra-libs = $(services:%=libnss_%) - # These libraries will be built in the `others' pass rather than -@@ -93,11 +93,15 @@ libnss_db-routines := $(libnss_db-dbs) d - generated += $(filter-out db-alias.c db-netgrp.c, \ - $(addsuffix .c,$(libnss_db-dbs))) - -+libnss_compat-routines := $(addprefix compat-,grp pwd spwd initgroups) \ -+ nisdomain -+ - install-others += $(inst_vardbdir)/Makefile - - # Build static module into libc if requested - libnss_files-inhibit-o = $(filter-out .os,$(object-suffixes)) - libnss_db-inhibit-o = $(filter-out .os,$(object-suffixes)) -+libnss_compat-inhibit-o = $(filter-out .os,$(object-suffixes)) - ifeq ($(build-static-nss),yes) - routines += $(libnss_files-routines) - static-only-routines += $(libnss_files-routines) -Index: glibc-2.26/nss/Versions -=================================================================== ---- glibc-2.26.orig/nss/Versions -+++ glibc-2.26/nss/Versions -@@ -160,3 +160,14 @@ libnss_db { - _nss_db_init; - } - } -+ -+libnss_compat { -+ GLIBC_PRIVATE { -+ _nss_compat_endgrent; _nss_compat_endpwent; _nss_compat_endspent; -+ _nss_compat_getgrent_r; _nss_compat_getgrgid_r; _nss_compat_getgrnam_r; -+ _nss_compat_getpwent_r; _nss_compat_getpwnam_r; _nss_compat_getpwuid_r; -+ _nss_compat_getspent_r; _nss_compat_getspnam_r; -+ _nss_compat_setgrent; _nss_compat_setpwent; _nss_compat_setspent; -+ _nss_compat_initgroups_dyn; -+ } -+} -Index: glibc-2.26/nss/nss_compat/compat-grp.c -=================================================================== ---- /dev/null -+++ glibc-2.26/nss/nss_compat/compat-grp.c -@@ -0,0 +1,682 @@ -+/* Copyright (C) 1996-2017 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Thorsten Kukuk , 1996. -+ -+ 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 service_user *ni; -+static enum nss_status (*nss_setgrent) (int stayopen); -+static enum nss_status (*nss_getgrnam_r) (const char *name, -+ struct group * grp, char *buffer, -+ size_t buflen, int *errnop); -+static enum nss_status (*nss_getgrgid_r) (gid_t gid, struct group * grp, -+ char *buffer, size_t buflen, -+ int *errnop); -+static enum nss_status (*nss_getgrent_r) (struct group * grp, char *buffer, -+ size_t buflen, int *errnop); -+static enum nss_status (*nss_endgrent) (void); -+ -+/* Get the declaration of the parser function. */ -+#define ENTNAME grent -+#define STRUCTURE group -+#define EXTERN_PARSER -+#include -+ -+/* Structure for remembering -group members ... */ -+#define BLACKLIST_INITIAL_SIZE 512 -+#define BLACKLIST_INCREMENT 256 -+struct blacklist_t -+{ -+ char *data; -+ int current; -+ int size; -+}; -+ -+struct ent_t -+{ -+ bool files; -+ enum nss_status setent_status; -+ FILE *stream; -+ struct blacklist_t blacklist; -+}; -+typedef struct ent_t ent_t; -+ -+static ent_t ext_ent = { true, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0 }}; -+ -+/* Protect global state against multiple changers. */ -+__libc_lock_define_initialized (static, lock) -+ -+/* Prototypes for local functions. */ -+static void blacklist_store_name (const char *, ent_t *); -+static bool in_blacklist (const char *, int, ent_t *); -+ -+/* Initialize the NSS interface/functions. The calling function must -+ hold the lock. */ -+static void -+init_nss_interface (void) -+{ -+ if (__nss_database_lookup ("group_compat", NULL, "nis", &ni) >= 0) -+ { -+ nss_setgrent = __nss_lookup_function (ni, "setgrent"); -+ nss_getgrnam_r = __nss_lookup_function (ni, "getgrnam_r"); -+ nss_getgrgid_r = __nss_lookup_function (ni, "getgrgid_r"); -+ nss_getgrent_r = __nss_lookup_function (ni, "getgrent_r"); -+ nss_endgrent = __nss_lookup_function (ni, "endgrent"); -+ } -+} -+ -+static enum nss_status -+internal_setgrent (ent_t *ent, int stayopen, int needent) -+{ -+ enum nss_status status = NSS_STATUS_SUCCESS; -+ -+ ent->files = true; -+ -+ if (ent->blacklist.data != NULL) -+ { -+ ent->blacklist.current = 1; -+ ent->blacklist.data[0] = '|'; -+ ent->blacklist.data[1] = '\0'; -+ } -+ else -+ ent->blacklist.current = 0; -+ -+ if (ent->stream == NULL) -+ { -+ ent->stream = fopen ("/etc/group", "rme"); -+ -+ if (ent->stream == NULL) -+ status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; -+ else -+ /* We take care of locking ourself. */ -+ __fsetlocking (ent->stream, FSETLOCKING_BYCALLER); -+ } -+ else -+ rewind (ent->stream); -+ -+ if (needent && status == NSS_STATUS_SUCCESS && nss_setgrent) -+ ent->setent_status = nss_setgrent (stayopen); -+ -+ return status; -+} -+ -+ -+enum nss_status -+_nss_compat_setgrent (int stayopen) -+{ -+ enum nss_status result; -+ -+ __libc_lock_lock (lock); -+ -+ if (ni == NULL) -+ init_nss_interface (); -+ -+ result = internal_setgrent (&ext_ent, stayopen, 1); -+ -+ __libc_lock_unlock (lock); -+ -+ return result; -+} -+ -+ -+static enum nss_status -+internal_endgrent (ent_t *ent) -+{ -+ if (ent->stream != NULL) -+ { -+ fclose (ent->stream); -+ ent->stream = NULL; -+ } -+ -+ if (ent->blacklist.data != NULL) -+ { -+ ent->blacklist.current = 1; -+ ent->blacklist.data[0] = '|'; -+ ent->blacklist.data[1] = '\0'; -+ } -+ else -+ ent->blacklist.current = 0; -+ -+ return NSS_STATUS_SUCCESS; -+} -+ -+enum nss_status -+_nss_compat_endgrent (void) -+{ -+ enum nss_status result; -+ -+ __libc_lock_lock (lock); -+ -+ if (nss_endgrent) -+ nss_endgrent (); -+ -+ result = internal_endgrent (&ext_ent); -+ -+ __libc_lock_unlock (lock); -+ -+ return result; -+} -+ -+/* get the next group from NSS (+ entry) */ -+static enum nss_status -+getgrent_next_nss (struct group *result, ent_t *ent, char *buffer, -+ size_t buflen, int *errnop) -+{ -+ if (!nss_getgrent_r) -+ return NSS_STATUS_UNAVAIL; -+ -+ /* If the setgrent call failed, say so. */ -+ if (ent->setent_status != NSS_STATUS_SUCCESS) -+ return ent->setent_status; -+ -+ do -+ { -+ enum nss_status status; -+ -+ if ((status = nss_getgrent_r (result, buffer, buflen, errnop)) != -+ NSS_STATUS_SUCCESS) -+ return status; -+ } -+ while (in_blacklist (result->gr_name, strlen (result->gr_name), ent)); -+ -+ return NSS_STATUS_SUCCESS; -+} -+ -+/* This function handle the +group entrys in /etc/group */ -+static enum nss_status -+getgrnam_plusgroup (const char *name, struct group *result, ent_t *ent, -+ char *buffer, size_t buflen, int *errnop) -+{ -+ if (!nss_getgrnam_r) -+ return NSS_STATUS_UNAVAIL; -+ -+ enum nss_status status = nss_getgrnam_r (name, result, buffer, buflen, -+ errnop); -+ if (status != NSS_STATUS_SUCCESS) -+ return status; -+ -+ if (in_blacklist (result->gr_name, strlen (result->gr_name), ent)) -+ return NSS_STATUS_NOTFOUND; -+ -+ /* We found the entry. */ -+ return NSS_STATUS_SUCCESS; -+} -+ -+static enum nss_status -+getgrent_next_file (struct group *result, ent_t *ent, -+ char *buffer, size_t buflen, int *errnop) -+{ -+ struct parser_data *data = (void *) buffer; -+ while (1) -+ { -+ fpos_t pos; -+ int parse_res = 0; -+ char *p; -+ -+ do -+ { -+ /* We need at least 3 characters for one line. */ -+ if (__glibc_unlikely (buflen < 3)) -+ { -+ erange: -+ *errnop = ERANGE; -+ return NSS_STATUS_TRYAGAIN; -+ } -+ -+ fgetpos (ent->stream, &pos); -+ buffer[buflen - 1] = '\xff'; -+ p = fgets_unlocked (buffer, buflen, ent->stream); -+ if (p == NULL && feof_unlocked (ent->stream)) -+ return NSS_STATUS_NOTFOUND; -+ -+ if (p == NULL || __builtin_expect (buffer[buflen - 1] != '\xff', 0)) -+ { -+ erange_reset: -+ fsetpos (ent->stream, &pos); -+ goto erange; -+ } -+ -+ /* Terminate the line for any case. */ -+ buffer[buflen - 1] = '\0'; -+ -+ /* Skip leading blanks. */ -+ while (isspace (*p)) -+ ++p; -+ } -+ while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */ -+ /* Parse the line. If it is invalid, loop to -+ get the next line of the file to parse. */ -+ !(parse_res = _nss_files_parse_grent (p, result, data, buflen, -+ errnop))); -+ -+ if (__glibc_unlikely (parse_res == -1)) -+ /* The parser ran out of space. */ -+ goto erange_reset; -+ -+ if (result->gr_name[0] != '+' && result->gr_name[0] != '-') -+ /* This is a real entry. */ -+ break; -+ -+ /* -group */ -+ if (result->gr_name[0] == '-' && result->gr_name[1] != '\0' -+ && result->gr_name[1] != '@') -+ { -+ blacklist_store_name (&result->gr_name[1], ent); -+ continue; -+ } -+ -+ /* +group */ -+ if (result->gr_name[0] == '+' && result->gr_name[1] != '\0' -+ && result->gr_name[1] != '@') -+ { -+ size_t len = strlen (result->gr_name); -+ char buf[len]; -+ enum nss_status status; -+ -+ /* Store the group in the blacklist for the "+" at the end of -+ /etc/group */ -+ memcpy (buf, &result->gr_name[1], len); -+ status = getgrnam_plusgroup (&result->gr_name[1], result, ent, -+ buffer, buflen, errnop); -+ blacklist_store_name (buf, ent); -+ if (status == NSS_STATUS_SUCCESS) /* We found the entry. */ -+ break; -+ else if (status == NSS_STATUS_RETURN /* We couldn't parse the entry*/ -+ || status == NSS_STATUS_NOTFOUND) /* No group in NIS */ -+ continue; -+ else -+ { -+ if (status == NSS_STATUS_TRYAGAIN) -+ /* The parser ran out of space. */ -+ goto erange_reset; -+ -+ return status; -+ } -+ } -+ -+ /* +:... */ -+ if (result->gr_name[0] == '+' && result->gr_name[1] == '\0') -+ { -+ ent->files = false; -+ -+ return getgrent_next_nss (result, ent, buffer, buflen, errnop); -+ } -+ } -+ -+ return NSS_STATUS_SUCCESS; -+} -+ -+ -+enum nss_status -+_nss_compat_getgrent_r (struct group *grp, char *buffer, size_t buflen, -+ int *errnop) -+{ -+ enum nss_status result = NSS_STATUS_SUCCESS; -+ -+ __libc_lock_lock (lock); -+ -+ /* Be prepared that the setgrent function was not called before. */ -+ if (ni == NULL) -+ init_nss_interface (); -+ -+ if (ext_ent.stream == NULL) -+ result = internal_setgrent (&ext_ent, 1, 1); -+ -+ if (result == NSS_STATUS_SUCCESS) -+ { -+ if (ext_ent.files) -+ result = getgrent_next_file (grp, &ext_ent, buffer, buflen, errnop); -+ else -+ result = getgrent_next_nss (grp, &ext_ent, buffer, buflen, errnop); -+ } -+ __libc_lock_unlock (lock); -+ -+ return result; -+} -+ -+/* Searches in /etc/group and the NIS/NIS+ map for a special group */ -+static enum nss_status -+internal_getgrnam_r (const char *name, struct group *result, ent_t *ent, -+ char *buffer, size_t buflen, int *errnop) -+{ -+ struct parser_data *data = (void *) buffer; -+ while (1) -+ { -+ fpos_t pos; -+ int parse_res = 0; -+ char *p; -+ -+ do -+ { -+ /* We need at least 3 characters for one line. */ -+ if (__glibc_unlikely (buflen < 3)) -+ { -+ erange: -+ *errnop = ERANGE; -+ return NSS_STATUS_TRYAGAIN; -+ } -+ -+ fgetpos (ent->stream, &pos); -+ buffer[buflen - 1] = '\xff'; -+ p = fgets_unlocked (buffer, buflen, ent->stream); -+ if (p == NULL && feof_unlocked (ent->stream)) -+ return NSS_STATUS_NOTFOUND; -+ -+ if (p == NULL || __builtin_expect (buffer[buflen - 1] != '\xff', 0)) -+ { -+ erange_reset: -+ fsetpos (ent->stream, &pos); -+ goto erange; -+ } -+ -+ /* Terminate the line for any case. */ -+ buffer[buflen - 1] = '\0'; -+ -+ /* Skip leading blanks. */ -+ while (isspace (*p)) -+ ++p; -+ } -+ while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */ -+ /* Parse the line. If it is invalid, loop to -+ get the next line of the file to parse. */ -+ !(parse_res = _nss_files_parse_grent (p, result, data, buflen, -+ errnop))); -+ -+ if (__glibc_unlikely (parse_res == -1)) -+ /* The parser ran out of space. */ -+ goto erange_reset; -+ -+ /* This is a real entry. */ -+ if (result->gr_name[0] != '+' && result->gr_name[0] != '-') -+ { -+ if (strcmp (result->gr_name, name) == 0) -+ return NSS_STATUS_SUCCESS; -+ else -+ continue; -+ } -+ -+ /* -group */ -+ if (result->gr_name[0] == '-' && result->gr_name[1] != '\0') -+ { -+ if (strcmp (&result->gr_name[1], name) == 0) -+ return NSS_STATUS_NOTFOUND; -+ else -+ continue; -+ } -+ -+ /* +group */ -+ if (result->gr_name[0] == '+' && result->gr_name[1] != '\0') -+ { -+ if (strcmp (name, &result->gr_name[1]) == 0) -+ { -+ enum nss_status status; -+ -+ status = getgrnam_plusgroup (name, result, ent, -+ buffer, buflen, errnop); -+ if (status == NSS_STATUS_RETURN) -+ /* We couldn't parse the entry */ -+ continue; -+ else -+ return status; -+ } -+ } -+ /* +:... */ -+ if (result->gr_name[0] == '+' && result->gr_name[1] == '\0') -+ { -+ enum nss_status status; -+ -+ status = getgrnam_plusgroup (name, result, ent, -+ buffer, buflen, errnop); -+ if (status == NSS_STATUS_RETURN) -+ /* We couldn't parse the entry */ -+ continue; -+ else -+ return status; -+ } -+ } -+ -+ return NSS_STATUS_SUCCESS; -+} -+ -+enum nss_status -+_nss_compat_getgrnam_r (const char *name, struct group *grp, -+ char *buffer, size_t buflen, int *errnop) -+{ -+ ent_t ent = { true, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0 }}; -+ enum nss_status result; -+ -+ if (name[0] == '-' || name[0] == '+') -+ return NSS_STATUS_NOTFOUND; -+ -+ __libc_lock_lock (lock); -+ -+ if (ni == NULL) -+ init_nss_interface (); -+ -+ __libc_lock_unlock (lock); -+ -+ result = internal_setgrent (&ent, 0, 0); -+ -+ if (result == NSS_STATUS_SUCCESS) -+ result = internal_getgrnam_r (name, grp, &ent, buffer, buflen, errnop); -+ -+ internal_endgrent (&ent); -+ -+ return result; -+} -+ -+/* Searches in /etc/group and the NIS/NIS+ map for a special group id */ -+static enum nss_status -+internal_getgrgid_r (gid_t gid, struct group *result, ent_t *ent, -+ char *buffer, size_t buflen, int *errnop) -+{ -+ struct parser_data *data = (void *) buffer; -+ while (1) -+ { -+ fpos_t pos; -+ int parse_res = 0; -+ char *p; -+ -+ do -+ { -+ /* We need at least 3 characters for one line. */ -+ if (__glibc_unlikely (buflen < 3)) -+ { -+ erange: -+ *errnop = ERANGE; -+ return NSS_STATUS_TRYAGAIN; -+ } -+ -+ fgetpos (ent->stream, &pos); -+ buffer[buflen - 1] = '\xff'; -+ p = fgets_unlocked (buffer, buflen, ent->stream); -+ if (p == NULL && feof_unlocked (ent->stream)) -+ return NSS_STATUS_NOTFOUND; -+ -+ if (p == NULL || __builtin_expect (buffer[buflen - 1] != '\xff', 0)) -+ { -+ erange_reset: -+ fsetpos (ent->stream, &pos); -+ goto erange; -+ } -+ -+ /* Terminate the line for any case. */ -+ buffer[buflen - 1] = '\0'; -+ -+ /* Skip leading blanks. */ -+ while (isspace (*p)) -+ ++p; -+ } -+ while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */ -+ /* Parse the line. If it is invalid, loop to -+ get the next line of the file to parse. */ -+ !(parse_res = _nss_files_parse_grent (p, result, data, buflen, -+ errnop))); -+ -+ if (__glibc_unlikely (parse_res == -1)) -+ /* The parser ran out of space. */ -+ goto erange_reset; -+ -+ /* This is a real entry. */ -+ if (result->gr_name[0] != '+' && result->gr_name[0] != '-') -+ { -+ if (result->gr_gid == gid) -+ return NSS_STATUS_SUCCESS; -+ else -+ continue; -+ } -+ -+ /* -group */ -+ if (result->gr_name[0] == '-' && result->gr_name[1] != '\0') -+ { -+ blacklist_store_name (&result->gr_name[1], ent); -+ continue; -+ } -+ -+ /* +group */ -+ if (result->gr_name[0] == '+' && result->gr_name[1] != '\0') -+ { -+ /* Yes, no +1, see the memcpy call below. */ -+ size_t len = strlen (result->gr_name); -+ char buf[len]; -+ enum nss_status status; -+ -+ /* Store the group in the blacklist for the "+" at the end of -+ /etc/group */ -+ memcpy (buf, &result->gr_name[1], len); -+ status = getgrnam_plusgroup (&result->gr_name[1], result, ent, -+ buffer, buflen, errnop); -+ blacklist_store_name (buf, ent); -+ if (status == NSS_STATUS_SUCCESS && result->gr_gid == gid) -+ break; -+ else -+ continue; -+ } -+ /* +:... */ -+ if (result->gr_name[0] == '+' && result->gr_name[1] == '\0') -+ { -+ if (!nss_getgrgid_r) -+ return NSS_STATUS_UNAVAIL; -+ -+ enum nss_status status = nss_getgrgid_r (gid, result, buffer, buflen, -+ errnop); -+ if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */ -+ return NSS_STATUS_NOTFOUND; -+ else -+ return status; -+ } -+ } -+ -+ return NSS_STATUS_SUCCESS; -+} -+ -+enum nss_status -+_nss_compat_getgrgid_r (gid_t gid, struct group *grp, -+ char *buffer, size_t buflen, int *errnop) -+{ -+ ent_t ent = { true, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0 }}; -+ enum nss_status result; -+ -+ __libc_lock_lock (lock); -+ -+ if (ni == NULL) -+ init_nss_interface (); -+ -+ __libc_lock_unlock (lock); -+ -+ result = internal_setgrent (&ent, 0, 0); -+ -+ if (result == NSS_STATUS_SUCCESS) -+ result = internal_getgrgid_r (gid, grp, &ent, buffer, buflen, errnop); -+ -+ internal_endgrent (&ent); -+ -+ return result; -+} -+ -+ -+/* Support routines for remembering -@netgroup and -user entries. -+ The names are stored in a single string with `|' as separator. */ -+static void -+blacklist_store_name (const char *name, ent_t *ent) -+{ -+ int namelen = strlen (name); -+ char *tmp; -+ -+ /* first call, setup cache */ -+ if (ent->blacklist.size == 0) -+ { -+ ent->blacklist.size = MAX (BLACKLIST_INITIAL_SIZE, 2 * namelen); -+ ent->blacklist.data = malloc (ent->blacklist.size); -+ if (ent->blacklist.data == NULL) -+ return; -+ ent->blacklist.data[0] = '|'; -+ ent->blacklist.data[1] = '\0'; -+ ent->blacklist.current = 1; -+ } -+ else -+ { -+ if (in_blacklist (name, namelen, ent)) -+ return; /* no duplicates */ -+ -+ if (ent->blacklist.current + namelen + 1 >= ent->blacklist.size) -+ { -+ ent->blacklist.size += MAX (BLACKLIST_INCREMENT, 2 * namelen); -+ tmp = realloc (ent->blacklist.data, ent->blacklist.size); -+ if (tmp == NULL) -+ { -+ free (ent->blacklist.data); -+ ent->blacklist.size = 0; -+ return; -+ } -+ ent->blacklist.data = tmp; -+ } -+ } -+ -+ tmp = stpcpy (ent->blacklist.data + ent->blacklist.current, name); -+ *tmp++ = '|'; -+ *tmp = '\0'; -+ ent->blacklist.current += namelen + 1; -+ -+ return; -+} -+ -+/* Return whether ent->blacklist contains name. */ -+static bool -+in_blacklist (const char *name, int namelen, ent_t *ent) -+{ -+ char buf[namelen + 3]; -+ char *cp; -+ -+ if (ent->blacklist.data == NULL) -+ return false; -+ -+ buf[0] = '|'; -+ cp = stpcpy (&buf[1], name); -+ *cp++ = '|'; -+ *cp = '\0'; -+ return strstr (ent->blacklist.data, buf) != NULL; -+} -Index: glibc-2.26/nss/nss_compat/compat-initgroups.c -=================================================================== ---- /dev/null -+++ glibc-2.26/nss/nss_compat/compat-initgroups.c -@@ -0,0 +1,575 @@ -+/* Copyright (C) 1998-2017 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Thorsten Kukuk , 1998. -+ -+ 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 -+#include -+#include -+#include -+ -+static service_user *ni; -+/* Type of the lookup function. */ -+static enum nss_status (*nss_initgroups_dyn) (const char *, gid_t, -+ long int *, long int *, -+ gid_t **, long int, int *); -+static enum nss_status (*nss_getgrnam_r) (const char *name, -+ struct group * grp, char *buffer, -+ size_t buflen, int *errnop); -+static enum nss_status (*nss_getgrgid_r) (gid_t gid, struct group * grp, -+ char *buffer, size_t buflen, -+ int *errnop); -+static enum nss_status (*nss_setgrent) (int stayopen); -+static enum nss_status (*nss_getgrent_r) (struct group * grp, char *buffer, -+ size_t buflen, int *errnop); -+static enum nss_status (*nss_endgrent) (void); -+ -+/* Protect global state against multiple changers. */ -+__libc_lock_define_initialized (static, lock) -+ -+ -+/* Get the declaration of the parser function. */ -+#define ENTNAME grent -+#define STRUCTURE group -+#define EXTERN_PARSER -+#include -+ -+/* Structure for remembering -group members ... */ -+#define BLACKLIST_INITIAL_SIZE 512 -+#define BLACKLIST_INCREMENT 256 -+struct blacklist_t -+{ -+ char *data; -+ int current; -+ int size; -+}; -+ -+struct ent_t -+{ -+ bool files; -+ bool need_endgrent; -+ bool skip_initgroups_dyn; -+ FILE *stream; -+ struct blacklist_t blacklist; -+}; -+typedef struct ent_t ent_t; -+ -+/* Prototypes for local functions. */ -+static void blacklist_store_name (const char *, ent_t *); -+static bool in_blacklist (const char *, int, ent_t *); -+ -+/* Initialize the NSS interface/functions. The calling function must -+ hold the lock. */ -+static void -+init_nss_interface (void) -+{ -+ __libc_lock_lock (lock); -+ -+ /* Retest. */ -+ if (ni == NULL -+ && __nss_database_lookup ("group_compat", NULL, "nis", &ni) >= 0) -+ { -+ nss_initgroups_dyn = __nss_lookup_function (ni, "initgroups_dyn"); -+ nss_getgrnam_r = __nss_lookup_function (ni, "getgrnam_r"); -+ nss_getgrgid_r = __nss_lookup_function (ni, "getgrgid_r"); -+ nss_setgrent = __nss_lookup_function (ni, "setgrent"); -+ nss_getgrent_r = __nss_lookup_function (ni, "getgrent_r"); -+ nss_endgrent = __nss_lookup_function (ni, "endgrent"); -+ } -+ -+ __libc_lock_unlock (lock); -+} -+ -+static enum nss_status -+internal_setgrent (ent_t *ent) -+{ -+ enum nss_status status = NSS_STATUS_SUCCESS; -+ -+ ent->files = true; -+ -+ if (ni == NULL) -+ init_nss_interface (); -+ -+ if (ent->blacklist.data != NULL) -+ { -+ ent->blacklist.current = 1; -+ ent->blacklist.data[0] = '|'; -+ ent->blacklist.data[1] = '\0'; -+ } -+ else -+ ent->blacklist.current = 0; -+ -+ ent->stream = fopen ("/etc/group", "rme"); -+ -+ if (ent->stream == NULL) -+ status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; -+ else -+ /* We take care of locking ourself. */ -+ __fsetlocking (ent->stream, FSETLOCKING_BYCALLER); -+ -+ return status; -+} -+ -+ -+static enum nss_status -+internal_endgrent (ent_t *ent) -+{ -+ if (ent->stream != NULL) -+ { -+ fclose (ent->stream); -+ ent->stream = NULL; -+ } -+ -+ if (ent->blacklist.data != NULL) -+ { -+ ent->blacklist.current = 1; -+ ent->blacklist.data[0] = '|'; -+ ent->blacklist.data[1] = '\0'; -+ } -+ else -+ ent->blacklist.current = 0; -+ -+ if (ent->need_endgrent && nss_endgrent != NULL) -+ nss_endgrent (); -+ -+ return NSS_STATUS_SUCCESS; -+} -+ -+/* Add new group record. */ -+static void -+add_group (long int *start, long int *size, gid_t **groupsp, long int limit, -+ gid_t gid) -+{ -+ gid_t *groups = *groupsp; -+ -+ /* Matches user. Insert this group. */ -+ if (__glibc_unlikely (*start == *size)) -+ { -+ /* Need a bigger buffer. */ -+ gid_t *newgroups; -+ long int newsize; -+ -+ if (limit > 0 && *size == limit) -+ /* We reached the maximum. */ -+ return; -+ -+ if (limit <= 0) -+ newsize = 2 * *size; -+ else -+ newsize = MIN (limit, 2 * *size); -+ -+ newgroups = realloc (groups, newsize * sizeof (*groups)); -+ if (newgroups == NULL) -+ return; -+ *groupsp = groups = newgroups; -+ *size = newsize; -+ } -+ -+ groups[*start] = gid; -+ *start += 1; -+} -+ -+/* This function checks, if the user is a member of this group and if -+ yes, add the group id to the list. Return nonzero is we couldn't -+ handle the group because the user is not in the member list. */ -+static int -+check_and_add_group (const char *user, gid_t group, long int *start, -+ long int *size, gid_t **groupsp, long int limit, -+ struct group *grp) -+{ -+ char **member; -+ -+ /* Don't add main group to list of groups. */ -+ if (grp->gr_gid == group) -+ return 0; -+ -+ for (member = grp->gr_mem; *member != NULL; ++member) -+ if (strcmp (*member, user) == 0) -+ { -+ add_group (start, size, groupsp, limit, grp->gr_gid); -+ return 0; -+ } -+ -+ return 1; -+} -+ -+/* Get the next group from NSS (+ entry). If the NSS module supports -+ initgroups_dyn, get all entries at once. */ -+static enum nss_status -+getgrent_next_nss (ent_t *ent, char *buffer, size_t buflen, const char *user, -+ gid_t group, long int *start, long int *size, -+ gid_t **groupsp, long int limit, int *errnop) -+{ -+ enum nss_status status; -+ struct group grpbuf; -+ -+ /* Try nss_initgroups_dyn if supported. We also need getgrgid_r. -+ If this function is not supported, step through the whole group -+ database with getgrent_r. */ -+ if (! ent->skip_initgroups_dyn) -+ { -+ long int mystart = 0; -+ long int mysize = limit <= 0 ? *size : limit; -+ gid_t *mygroups = malloc (mysize * sizeof (gid_t)); -+ -+ if (mygroups == NULL) -+ return NSS_STATUS_TRYAGAIN; -+ -+ /* For every gid in the list we get from the NSS module, -+ get the whole group entry. We need to do this, since we -+ need the group name to check if it is in the blacklist. -+ In worst case, this is as twice as slow as stepping with -+ getgrent_r through the whole group database. But for large -+ group databases this is faster, since the user can only be -+ in a limited number of groups. */ -+ if (nss_initgroups_dyn (user, group, &mystart, &mysize, &mygroups, -+ limit, errnop) == NSS_STATUS_SUCCESS) -+ { -+ status = NSS_STATUS_NOTFOUND; -+ -+ /* If there is no blacklist we can trust the underlying -+ initgroups implementation. */ -+ if (ent->blacklist.current <= 1) -+ for (int i = 0; i < mystart; i++) -+ add_group (start, size, groupsp, limit, mygroups[i]); -+ else -+ { -+ /* A temporary buffer. We use the normal buffer, until we find -+ an entry, for which this buffer is to small. In this case, we -+ overwrite the pointer with one to a bigger buffer. */ -+ char *tmpbuf = buffer; -+ size_t tmplen = buflen; -+ bool use_malloc = false; -+ -+ for (int i = 0; i < mystart; i++) -+ { -+ while ((status = nss_getgrgid_r (mygroups[i], &grpbuf, -+ tmpbuf, tmplen, errnop)) -+ == NSS_STATUS_TRYAGAIN -+ && *errnop == ERANGE) -+ { -+ if (__libc_use_alloca (tmplen * 2)) -+ { -+ if (tmpbuf == buffer) -+ { -+ tmplen *= 2; -+ tmpbuf = __alloca (tmplen); -+ } -+ else -+ tmpbuf = extend_alloca (tmpbuf, tmplen, tmplen * 2); -+ } -+ else -+ { -+ tmplen *= 2; -+ char *newbuf = realloc (use_malloc ? tmpbuf : NULL, tmplen); -+ -+ if (newbuf == NULL) -+ { -+ status = NSS_STATUS_TRYAGAIN; -+ goto done; -+ } -+ use_malloc = true; -+ tmpbuf = newbuf; -+ } -+ } -+ -+ if (__builtin_expect (status != NSS_STATUS_NOTFOUND, 1)) -+ { -+ if (__builtin_expect (status != NSS_STATUS_SUCCESS, 0)) -+ goto done; -+ -+ if (!in_blacklist (grpbuf.gr_name, -+ strlen (grpbuf.gr_name), ent) -+ && check_and_add_group (user, group, start, size, -+ groupsp, limit, &grpbuf)) -+ { -+ if (nss_setgrent != NULL) -+ { -+ nss_setgrent (1); -+ ent->need_endgrent = true; -+ } -+ ent->skip_initgroups_dyn = true; -+ -+ goto iter; -+ } -+ } -+ } -+ -+ status = NSS_STATUS_NOTFOUND; -+ -+ done: -+ if (use_malloc) -+ free (tmpbuf); -+ } -+ -+ free (mygroups); -+ -+ return status; -+ } -+ -+ free (mygroups); -+ } -+ -+ /* If we come here, the NSS module does not support initgroups_dyn -+ or we were confronted with a split group. In these cases we have -+ to step through the whole list ourself. */ -+ iter: -+ do -+ { -+ if ((status = nss_getgrent_r (&grpbuf, buffer, buflen, errnop)) != -+ NSS_STATUS_SUCCESS) -+ break; -+ } -+ while (in_blacklist (grpbuf.gr_name, strlen (grpbuf.gr_name), ent)); -+ -+ if (status == NSS_STATUS_SUCCESS) -+ check_and_add_group (user, group, start, size, groupsp, limit, &grpbuf); -+ -+ return status; -+} -+ -+static enum nss_status -+internal_getgrent_r (ent_t *ent, char *buffer, size_t buflen, const char *user, -+ gid_t group, long int *start, long int *size, -+ gid_t **groupsp, long int limit, int *errnop) -+{ -+ struct parser_data *data = (void *) buffer; -+ struct group grpbuf; -+ -+ if (!ent->files) -+ return getgrent_next_nss (ent, buffer, buflen, user, group, -+ start, size, groupsp, limit, errnop); -+ -+ while (1) -+ { -+ fpos_t pos; -+ int parse_res = 0; -+ char *p; -+ -+ do -+ { -+ /* We need at least 3 characters for one line. */ -+ if (__glibc_unlikely (buflen < 3)) -+ { -+ erange: -+ *errnop = ERANGE; -+ return NSS_STATUS_TRYAGAIN; -+ } -+ -+ fgetpos (ent->stream, &pos); -+ buffer[buflen - 1] = '\xff'; -+ p = fgets_unlocked (buffer, buflen, ent->stream); -+ if (p == NULL && feof_unlocked (ent->stream)) -+ return NSS_STATUS_NOTFOUND; -+ -+ if (p == NULL || __builtin_expect (buffer[buflen - 1] != '\xff', 0)) -+ { -+ erange_reset: -+ fsetpos (ent->stream, &pos); -+ goto erange; -+ } -+ -+ /* Terminate the line for any case. */ -+ buffer[buflen - 1] = '\0'; -+ -+ /* Skip leading blanks. */ -+ while (isspace (*p)) -+ ++p; -+ } -+ while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */ -+ /* Parse the line. If it is invalid, loop to -+ get the next line of the file to parse. */ -+ !(parse_res = _nss_files_parse_grent (p, &grpbuf, data, buflen, -+ errnop))); -+ -+ if (__glibc_unlikely (parse_res == -1)) -+ /* The parser ran out of space. */ -+ goto erange_reset; -+ -+ if (grpbuf.gr_name[0] != '+' && grpbuf.gr_name[0] != '-') -+ /* This is a real entry. */ -+ break; -+ -+ /* -group */ -+ if (grpbuf.gr_name[0] == '-' && grpbuf.gr_name[1] != '\0' -+ && grpbuf.gr_name[1] != '@') -+ { -+ blacklist_store_name (&grpbuf.gr_name[1], ent); -+ continue; -+ } -+ -+ /* +group */ -+ if (grpbuf.gr_name[0] == '+' && grpbuf.gr_name[1] != '\0' -+ && grpbuf.gr_name[1] != '@') -+ { -+ if (in_blacklist (&grpbuf.gr_name[1], -+ strlen (&grpbuf.gr_name[1]), ent)) -+ continue; -+ /* Store the group in the blacklist for the "+" at the end of -+ /etc/group */ -+ blacklist_store_name (&grpbuf.gr_name[1], ent); -+ if (nss_getgrnam_r == NULL) -+ return NSS_STATUS_UNAVAIL; -+ else if (nss_getgrnam_r (&grpbuf.gr_name[1], &grpbuf, buffer, -+ buflen, errnop) != NSS_STATUS_SUCCESS) -+ continue; -+ -+ check_and_add_group (user, group, start, size, groupsp, -+ limit, &grpbuf); -+ -+ return NSS_STATUS_SUCCESS; -+ } -+ -+ /* +:... */ -+ if (grpbuf.gr_name[0] == '+' && grpbuf.gr_name[1] == '\0') -+ { -+ /* If the selected module does not support getgrent_r or -+ initgroups_dyn, abort. We cannot find the needed group -+ entries. */ -+ if (nss_initgroups_dyn == NULL || nss_getgrgid_r == NULL) -+ { -+ if (nss_setgrent != NULL) -+ { -+ nss_setgrent (1); -+ ent->need_endgrent = true; -+ } -+ ent->skip_initgroups_dyn = true; -+ -+ if (nss_getgrent_r == NULL) -+ return NSS_STATUS_UNAVAIL; -+ } -+ -+ ent->files = false; -+ -+ return getgrent_next_nss (ent, buffer, buflen, user, group, -+ start, size, groupsp, limit, errnop); -+ } -+ } -+ -+ check_and_add_group (user, group, start, size, groupsp, limit, &grpbuf); -+ -+ return NSS_STATUS_SUCCESS; -+} -+ -+ -+enum nss_status -+_nss_compat_initgroups_dyn (const char *user, gid_t group, long int *start, -+ long int *size, gid_t **groupsp, long int limit, -+ int *errnop) -+{ -+ enum nss_status status; -+ ent_t intern = { true, false, false, NULL, {NULL, 0, 0} }; -+ -+ status = internal_setgrent (&intern); -+ if (status != NSS_STATUS_SUCCESS) -+ return status; -+ -+ struct scratch_buffer tmpbuf; -+ scratch_buffer_init (&tmpbuf); -+ -+ do -+ { -+ while ((status = internal_getgrent_r (&intern, tmpbuf.data, tmpbuf.length, -+ user, group, start, size, -+ groupsp, limit, errnop)) -+ == NSS_STATUS_TRYAGAIN && *errnop == ERANGE) -+ if (!scratch_buffer_grow (&tmpbuf)) -+ goto done; -+ } -+ while (status == NSS_STATUS_SUCCESS); -+ -+ status = NSS_STATUS_SUCCESS; -+ -+ done: -+ scratch_buffer_free (&tmpbuf); -+ -+ internal_endgrent (&intern); -+ -+ return status; -+} -+ -+ -+/* Support routines for remembering -@netgroup and -user entries. -+ The names are stored in a single string with `|' as separator. */ -+static void -+blacklist_store_name (const char *name, ent_t *ent) -+{ -+ int namelen = strlen (name); -+ char *tmp; -+ -+ /* First call, setup cache. */ -+ if (ent->blacklist.size == 0) -+ { -+ ent->blacklist.size = MAX (BLACKLIST_INITIAL_SIZE, 2 * namelen); -+ ent->blacklist.data = malloc (ent->blacklist.size); -+ if (ent->blacklist.data == NULL) -+ return; -+ ent->blacklist.data[0] = '|'; -+ ent->blacklist.data[1] = '\0'; -+ ent->blacklist.current = 1; -+ } -+ else -+ { -+ if (in_blacklist (name, namelen, ent)) -+ return; /* no duplicates */ -+ -+ if (ent->blacklist.current + namelen + 1 >= ent->blacklist.size) -+ { -+ ent->blacklist.size += MAX (BLACKLIST_INCREMENT, 2 * namelen); -+ tmp = realloc (ent->blacklist.data, ent->blacklist.size); -+ if (tmp == NULL) -+ { -+ free (ent->blacklist.data); -+ ent->blacklist.size = 0; -+ return; -+ } -+ ent->blacklist.data = tmp; -+ } -+ } -+ -+ tmp = stpcpy (ent->blacklist.data + ent->blacklist.current, name); -+ *tmp++ = '|'; -+ *tmp = '\0'; -+ ent->blacklist.current += namelen + 1; -+ -+ return; -+} -+ -+/* Return whether ent->blacklist contains name. */ -+static bool -+in_blacklist (const char *name, int namelen, ent_t *ent) -+{ -+ char buf[namelen + 3]; -+ char *cp; -+ -+ if (ent->blacklist.data == NULL) -+ return false; -+ -+ buf[0] = '|'; -+ cp = stpcpy (&buf[1], name); -+ *cp++ = '|'; -+ *cp = '\0'; -+ return strstr (ent->blacklist.data, buf) != NULL; -+} -Index: glibc-2.26/nss/nss_compat/compat-pwd.c -=================================================================== ---- /dev/null -+++ glibc-2.26/nss/nss_compat/compat-pwd.c -@@ -0,0 +1,1131 @@ -+/* Copyright (C) 1996-2017 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Thorsten Kukuk , 1996. -+ -+ 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 -+#include -+ -+#include "netgroup.h" -+#include "nisdomain.h" -+ -+static service_user *ni; -+static enum nss_status (*nss_setpwent) (int stayopen); -+static enum nss_status (*nss_getpwnam_r) (const char *name, -+ struct passwd * pwd, char *buffer, -+ size_t buflen, int *errnop); -+static enum nss_status (*nss_getpwuid_r) (uid_t uid, struct passwd * pwd, -+ char *buffer, size_t buflen, -+ int *errnop); -+static enum nss_status (*nss_getpwent_r) (struct passwd * pwd, char *buffer, -+ size_t buflen, int *errnop); -+static enum nss_status (*nss_endpwent) (void); -+ -+/* Get the declaration of the parser function. */ -+#define ENTNAME pwent -+#define STRUCTURE passwd -+#define EXTERN_PARSER -+#include -+ -+/* Structure for remembering -@netgroup and -user members ... */ -+#define BLACKLIST_INITIAL_SIZE 512 -+#define BLACKLIST_INCREMENT 256 -+struct blacklist_t -+{ -+ char *data; -+ int current; -+ int size; -+}; -+ -+struct ent_t -+{ -+ bool netgroup; -+ bool first; -+ bool files; -+ enum nss_status setent_status; -+ FILE *stream; -+ struct blacklist_t blacklist; -+ struct passwd pwd; -+ struct __netgrent netgrdata; -+}; -+typedef struct ent_t ent_t; -+ -+static ent_t ext_ent = { false, false, true, NSS_STATUS_SUCCESS, NULL, -+ { NULL, 0, 0 }, -+ { NULL, NULL, 0, 0, NULL, NULL, NULL }}; -+ -+/* Protect global state against multiple changers. */ -+__libc_lock_define_initialized (static, lock) -+ -+/* Prototypes for local functions. */ -+static void blacklist_store_name (const char *, ent_t *); -+static bool in_blacklist (const char *, int, ent_t *); -+ -+/* Initialize the NSS interface/functions. The calling function must -+ hold the lock. */ -+static void -+init_nss_interface (void) -+{ -+ if (__nss_database_lookup ("passwd_compat", NULL, "nis", &ni) >= 0) -+ { -+ nss_setpwent = __nss_lookup_function (ni, "setpwent"); -+ nss_getpwnam_r = __nss_lookup_function (ni, "getpwnam_r"); -+ nss_getpwuid_r = __nss_lookup_function (ni, "getpwuid_r"); -+ nss_getpwent_r = __nss_lookup_function (ni, "getpwent_r"); -+ nss_endpwent = __nss_lookup_function (ni, "endpwent"); -+ } -+} -+ -+static void -+give_pwd_free (struct passwd *pwd) -+{ -+ free (pwd->pw_name); -+ free (pwd->pw_passwd); -+ free (pwd->pw_gecos); -+ free (pwd->pw_dir); -+ free (pwd->pw_shell); -+ -+ memset (pwd, '\0', sizeof (struct passwd)); -+} -+ -+static size_t -+pwd_need_buflen (struct passwd *pwd) -+{ -+ size_t len = 0; -+ -+ if (pwd->pw_passwd != NULL) -+ len += strlen (pwd->pw_passwd) + 1; -+ -+ if (pwd->pw_gecos != NULL) -+ len += strlen (pwd->pw_gecos) + 1; -+ -+ if (pwd->pw_dir != NULL) -+ len += strlen (pwd->pw_dir) + 1; -+ -+ if (pwd->pw_shell != NULL) -+ len += strlen (pwd->pw_shell) + 1; -+ -+ return len; -+} -+ -+static void -+copy_pwd_changes (struct passwd *dest, struct passwd *src, -+ char *buffer, size_t buflen) -+{ -+ if (src->pw_passwd != NULL && strlen (src->pw_passwd)) -+ { -+ if (buffer == NULL) -+ dest->pw_passwd = strdup (src->pw_passwd); -+ else if (dest->pw_passwd && -+ strlen (dest->pw_passwd) >= strlen (src->pw_passwd)) -+ strcpy (dest->pw_passwd, src->pw_passwd); -+ else -+ { -+ dest->pw_passwd = buffer; -+ strcpy (dest->pw_passwd, src->pw_passwd); -+ buffer += strlen (dest->pw_passwd) + 1; -+ buflen = buflen - (strlen (dest->pw_passwd) + 1); -+ } -+ } -+ -+ if (src->pw_gecos != NULL && strlen (src->pw_gecos)) -+ { -+ if (buffer == NULL) -+ dest->pw_gecos = strdup (src->pw_gecos); -+ else if (dest->pw_gecos && -+ strlen (dest->pw_gecos) >= strlen (src->pw_gecos)) -+ strcpy (dest->pw_gecos, src->pw_gecos); -+ else -+ { -+ dest->pw_gecos = buffer; -+ strcpy (dest->pw_gecos, src->pw_gecos); -+ buffer += strlen (dest->pw_gecos) + 1; -+ buflen = buflen - (strlen (dest->pw_gecos) + 1); -+ } -+ } -+ if (src->pw_dir != NULL && strlen (src->pw_dir)) -+ { -+ if (buffer == NULL) -+ dest->pw_dir = strdup (src->pw_dir); -+ else if (dest->pw_dir && strlen (dest->pw_dir) >= strlen (src->pw_dir)) -+ strcpy (dest->pw_dir, src->pw_dir); -+ else -+ { -+ dest->pw_dir = buffer; -+ strcpy (dest->pw_dir, src->pw_dir); -+ buffer += strlen (dest->pw_dir) + 1; -+ buflen = buflen - (strlen (dest->pw_dir) + 1); -+ } -+ } -+ -+ if (src->pw_shell != NULL && strlen (src->pw_shell)) -+ { -+ if (buffer == NULL) -+ dest->pw_shell = strdup (src->pw_shell); -+ else if (dest->pw_shell && -+ strlen (dest->pw_shell) >= strlen (src->pw_shell)) -+ strcpy (dest->pw_shell, src->pw_shell); -+ else -+ { -+ dest->pw_shell = buffer; -+ strcpy (dest->pw_shell, src->pw_shell); -+ buffer += strlen (dest->pw_shell) + 1; -+ buflen = buflen - (strlen (dest->pw_shell) + 1); -+ } -+ } -+} -+ -+static enum nss_status -+internal_setpwent (ent_t *ent, int stayopen, int needent) -+{ -+ enum nss_status status = NSS_STATUS_SUCCESS; -+ -+ ent->first = ent->netgroup = false; -+ ent->files = true; -+ ent->setent_status = NSS_STATUS_SUCCESS; -+ -+ /* If something was left over free it. */ -+ if (ent->netgroup) -+ __internal_endnetgrent (&ent->netgrdata); -+ -+ if (ent->blacklist.data != NULL) -+ { -+ ent->blacklist.current = 1; -+ ent->blacklist.data[0] = '|'; -+ ent->blacklist.data[1] = '\0'; -+ } -+ else -+ ent->blacklist.current = 0; -+ -+ if (ent->stream == NULL) -+ { -+ ent->stream = fopen ("/etc/passwd", "rme"); -+ -+ if (ent->stream == NULL) -+ status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; -+ else -+ /* We take care of locking ourself. */ -+ __fsetlocking (ent->stream, FSETLOCKING_BYCALLER); -+ } -+ else -+ rewind (ent->stream); -+ -+ give_pwd_free (&ent->pwd); -+ -+ if (needent && status == NSS_STATUS_SUCCESS && nss_setpwent) -+ ent->setent_status = nss_setpwent (stayopen); -+ -+ return status; -+} -+ -+ -+enum nss_status -+_nss_compat_setpwent (int stayopen) -+{ -+ enum nss_status result; -+ -+ __libc_lock_lock (lock); -+ -+ if (ni == NULL) -+ init_nss_interface (); -+ -+ result = internal_setpwent (&ext_ent, stayopen, 1); -+ -+ __libc_lock_unlock (lock); -+ -+ return result; -+} -+ -+ -+static enum nss_status -+internal_endpwent (ent_t *ent) -+{ -+ if (ent->stream != NULL) -+ { -+ fclose (ent->stream); -+ ent->stream = NULL; -+ } -+ -+ if (ent->netgroup) -+ __internal_endnetgrent (&ent->netgrdata); -+ -+ ent->first = ent->netgroup = false; -+ -+ if (ent->blacklist.data != NULL) -+ { -+ ent->blacklist.current = 1; -+ ent->blacklist.data[0] = '|'; -+ ent->blacklist.data[1] = '\0'; -+ } -+ else -+ ent->blacklist.current = 0; -+ -+ give_pwd_free (&ent->pwd); -+ -+ return NSS_STATUS_SUCCESS; -+} -+ -+enum nss_status -+_nss_compat_endpwent (void) -+{ -+ enum nss_status result; -+ -+ __libc_lock_lock (lock); -+ -+ if (nss_endpwent) -+ nss_endpwent (); -+ -+ result = internal_endpwent (&ext_ent); -+ -+ __libc_lock_unlock (lock); -+ -+ return result; -+} -+ -+ -+static enum nss_status -+getpwent_next_nss_netgr (const char *name, struct passwd *result, ent_t *ent, -+ char *group, char *buffer, size_t buflen, -+ int *errnop) -+{ -+ char *curdomain = NULL, *host, *user, *domain, *p2; -+ int status; -+ size_t p2len; -+ -+ /* Leave function if NSS module does not support getpwnam_r, -+ we need this function here. */ -+ if (!nss_getpwnam_r) -+ return NSS_STATUS_UNAVAIL; -+ -+ if (ent->first) -+ { -+ memset (&ent->netgrdata, 0, sizeof (struct __netgrent)); -+ __internal_setnetgrent (group, &ent->netgrdata); -+ ent->first = false; -+ } -+ -+ while (1) -+ { -+ status = __internal_getnetgrent_r (&host, &user, &domain, -+ &ent->netgrdata, buffer, buflen, -+ errnop); -+ if (status != 1) -+ { -+ __internal_endnetgrent (&ent->netgrdata); -+ ent->netgroup = 0; -+ give_pwd_free (&ent->pwd); -+ return NSS_STATUS_RETURN; -+ } -+ -+ if (user == NULL || user[0] == '-') -+ continue; -+ -+ if (domain != NULL) -+ { -+ if (curdomain == NULL -+ && __nss_get_default_domain (&curdomain) != 0) -+ { -+ __internal_endnetgrent (&ent->netgrdata); -+ ent->netgroup = false; -+ give_pwd_free (&ent->pwd); -+ return NSS_STATUS_UNAVAIL; -+ } -+ if (strcmp (curdomain, domain) != 0) -+ continue; -+ } -+ -+ /* If name != NULL, we are called from getpwnam. */ -+ if (name != NULL) -+ if (strcmp (user, name) != 0) -+ continue; -+ -+ p2len = pwd_need_buflen (&ent->pwd); -+ if (p2len > buflen) -+ { -+ *errnop = ERANGE; -+ return NSS_STATUS_TRYAGAIN; -+ } -+ p2 = buffer + (buflen - p2len); -+ buflen -= p2len; -+ -+ if (nss_getpwnam_r (user, result, buffer, buflen, errnop) != -+ NSS_STATUS_SUCCESS) -+ continue; -+ -+ if (!in_blacklist (result->pw_name, strlen (result->pw_name), ent)) -+ { -+ /* Store the User in the blacklist for possible the "+" at the -+ end of /etc/passwd */ -+ blacklist_store_name (result->pw_name, ent); -+ copy_pwd_changes (result, &ent->pwd, p2, p2len); -+ break; -+ } -+ } -+ -+ return NSS_STATUS_SUCCESS; -+} -+ -+/* get the next user from NSS (+ entry) */ -+static enum nss_status -+getpwent_next_nss (struct passwd *result, ent_t *ent, char *buffer, -+ size_t buflen, int *errnop) -+{ -+ enum nss_status status; -+ char *p2; -+ size_t p2len; -+ -+ /* Return if NSS module does not support getpwent_r. */ -+ if (!nss_getpwent_r) -+ return NSS_STATUS_UNAVAIL; -+ -+ /* If the setpwent call failed, say so. */ -+ if (ent->setent_status != NSS_STATUS_SUCCESS) -+ return ent->setent_status; -+ -+ p2len = pwd_need_buflen (&ent->pwd); -+ if (p2len > buflen) -+ { -+ *errnop = ERANGE; -+ return NSS_STATUS_TRYAGAIN; -+ } -+ p2 = buffer + (buflen - p2len); -+ buflen -= p2len; -+ -+ if (ent->first) -+ ent->first = false; -+ -+ do -+ { -+ if ((status = nss_getpwent_r (result, buffer, buflen, errnop)) != -+ NSS_STATUS_SUCCESS) -+ return status; -+ } -+ while (in_blacklist (result->pw_name, strlen (result->pw_name), ent)); -+ -+ copy_pwd_changes (result, &ent->pwd, p2, p2len); -+ -+ return NSS_STATUS_SUCCESS; -+} -+ -+/* This function handle the +user entrys in /etc/passwd */ -+static enum nss_status -+getpwnam_plususer (const char *name, struct passwd *result, ent_t *ent, -+ char *buffer, size_t buflen, int *errnop) -+{ -+ if (!nss_getpwnam_r) -+ return NSS_STATUS_UNAVAIL; -+ -+ struct passwd pwd; -+ memset (&pwd, '\0', sizeof (struct passwd)); -+ -+ copy_pwd_changes (&pwd, result, NULL, 0); -+ -+ size_t plen = pwd_need_buflen (&pwd); -+ if (plen > buflen) -+ { -+ *errnop = ERANGE; -+ return NSS_STATUS_TRYAGAIN; -+ } -+ char *p = buffer + (buflen - plen); -+ buflen -= plen; -+ -+ enum nss_status status = nss_getpwnam_r (name, result, buffer, buflen, -+ errnop); -+ if (status != NSS_STATUS_SUCCESS) -+ return status; -+ -+ if (in_blacklist (result->pw_name, strlen (result->pw_name), ent)) -+ return NSS_STATUS_NOTFOUND; -+ -+ copy_pwd_changes (result, &pwd, p, plen); -+ give_pwd_free (&pwd); -+ /* We found the entry. */ -+ return NSS_STATUS_SUCCESS; -+} -+ -+static enum nss_status -+getpwent_next_file (struct passwd *result, ent_t *ent, -+ char *buffer, size_t buflen, int *errnop) -+{ -+ struct parser_data *data = (void *) buffer; -+ while (1) -+ { -+ fpos_t pos; -+ char *p; -+ int parse_res; -+ -+ do -+ { -+ /* We need at least 3 characters for one line. */ -+ if (__glibc_unlikely (buflen < 3)) -+ { -+ erange: -+ *errnop = ERANGE; -+ return NSS_STATUS_TRYAGAIN; -+ } -+ -+ fgetpos (ent->stream, &pos); -+ buffer[buflen - 1] = '\xff'; -+ p = fgets_unlocked (buffer, buflen, ent->stream); -+ if (p == NULL && feof_unlocked (ent->stream)) -+ return NSS_STATUS_NOTFOUND; -+ -+ if (p == NULL || __builtin_expect (buffer[buflen - 1] != '\xff', 0)) -+ { -+ erange_reset: -+ fsetpos (ent->stream, &pos); -+ goto erange; -+ } -+ -+ /* Terminate the line for any case. */ -+ buffer[buflen - 1] = '\0'; -+ -+ /* Skip leading blanks. */ -+ while (isspace (*p)) -+ ++p; -+ } -+ while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */ -+ /* Parse the line. If it is invalid, loop to -+ get the next line of the file to parse. */ -+ !(parse_res = _nss_files_parse_pwent (p, result, data, buflen, -+ errnop))); -+ -+ if (__glibc_unlikely (parse_res == -1)) -+ /* The parser ran out of space. */ -+ goto erange_reset; -+ -+ if (result->pw_name[0] != '+' && result->pw_name[0] != '-') -+ /* This is a real entry. */ -+ break; -+ -+ /* -@netgroup */ -+ if (result->pw_name[0] == '-' && result->pw_name[1] == '@' -+ && result->pw_name[2] != '\0') -+ { -+ /* XXX Do not use fixed length buffer. */ -+ char buf2[1024]; -+ char *user, *host, *domain; -+ struct __netgrent netgrdata; -+ -+ memset (&netgrdata, 0, sizeof (struct __netgrent)); -+ __internal_setnetgrent (&result->pw_name[2], &netgrdata); -+ while (__internal_getnetgrent_r (&host, &user, &domain, &netgrdata, -+ buf2, sizeof (buf2), errnop)) -+ { -+ if (user != NULL && user[0] != '-') -+ blacklist_store_name (user, ent); -+ } -+ __internal_endnetgrent (&netgrdata); -+ continue; -+ } -+ -+ /* +@netgroup */ -+ if (result->pw_name[0] == '+' && result->pw_name[1] == '@' -+ && result->pw_name[2] != '\0') -+ { -+ enum nss_status status; -+ -+ ent->netgroup = true; -+ ent->first = true; -+ copy_pwd_changes (&ent->pwd, result, NULL, 0); -+ -+ status = getpwent_next_nss_netgr (NULL, result, ent, -+ &result->pw_name[2], -+ buffer, buflen, errnop); -+ if (status == NSS_STATUS_RETURN) -+ continue; -+ else -+ return status; -+ } -+ -+ /* -user */ -+ if (result->pw_name[0] == '-' && result->pw_name[1] != '\0' -+ && result->pw_name[1] != '@') -+ { -+ blacklist_store_name (&result->pw_name[1], ent); -+ continue; -+ } -+ -+ /* +user */ -+ if (result->pw_name[0] == '+' && result->pw_name[1] != '\0' -+ && result->pw_name[1] != '@') -+ { -+ size_t len = strlen (result->pw_name); -+ char buf[len]; -+ enum nss_status status; -+ -+ /* Store the User in the blacklist for the "+" at the end of -+ /etc/passwd */ -+ memcpy (buf, &result->pw_name[1], len); -+ status = getpwnam_plususer (&result->pw_name[1], result, ent, -+ buffer, buflen, errnop); -+ blacklist_store_name (buf, ent); -+ -+ if (status == NSS_STATUS_SUCCESS) /* We found the entry. */ -+ break; -+ else if (status == NSS_STATUS_RETURN /* We couldn't parse the entry */ -+ || status == NSS_STATUS_NOTFOUND) /* entry doesn't exist */ -+ continue; -+ else -+ { -+ if (status == NSS_STATUS_TRYAGAIN) -+ { -+ /* The parser ran out of space */ -+ fsetpos (ent->stream, &pos); -+ *errnop = ERANGE; -+ } -+ return status; -+ } -+ } -+ -+ /* +:... */ -+ if (result->pw_name[0] == '+' && result->pw_name[1] == '\0') -+ { -+ ent->files = false; -+ ent->first = true; -+ copy_pwd_changes (&ent->pwd, result, NULL, 0); -+ -+ return getpwent_next_nss (result, ent, buffer, buflen, errnop); -+ } -+ } -+ -+ return NSS_STATUS_SUCCESS; -+} -+ -+ -+static enum nss_status -+internal_getpwent_r (struct passwd *pw, ent_t *ent, char *buffer, -+ size_t buflen, int *errnop) -+{ -+ if (ent->netgroup) -+ { -+ enum nss_status status; -+ -+ /* We are searching members in a netgroup */ -+ /* Since this is not the first call, we don't need the group name */ -+ status = getpwent_next_nss_netgr (NULL, pw, ent, NULL, buffer, buflen, -+ errnop); -+ if (status == NSS_STATUS_RETURN) -+ return getpwent_next_file (pw, ent, buffer, buflen, errnop); -+ else -+ return status; -+ } -+ else if (ent->files) -+ return getpwent_next_file (pw, ent, buffer, buflen, errnop); -+ else -+ return getpwent_next_nss (pw, ent, buffer, buflen, errnop); -+ -+} -+ -+enum nss_status -+_nss_compat_getpwent_r (struct passwd *pwd, char *buffer, size_t buflen, -+ int *errnop) -+{ -+ enum nss_status result = NSS_STATUS_SUCCESS; -+ -+ __libc_lock_lock (lock); -+ -+ /* Be prepared that the setpwent function was not called before. */ -+ if (ni == NULL) -+ init_nss_interface (); -+ -+ if (ext_ent.stream == NULL) -+ result = internal_setpwent (&ext_ent, 1, 1); -+ -+ if (result == NSS_STATUS_SUCCESS) -+ result = internal_getpwent_r (pwd, &ext_ent, buffer, buflen, errnop); -+ -+ __libc_lock_unlock (lock); -+ -+ return result; -+} -+ -+/* Searches in /etc/passwd and the NIS/NIS+ map for a special user */ -+static enum nss_status -+internal_getpwnam_r (const char *name, struct passwd *result, ent_t *ent, -+ char *buffer, size_t buflen, int *errnop) -+{ -+ struct parser_data *data = (void *) buffer; -+ -+ while (1) -+ { -+ fpos_t pos; -+ char *p; -+ int parse_res; -+ -+ do -+ { -+ /* We need at least 3 characters for one line. */ -+ if (__glibc_unlikely (buflen < 3)) -+ { -+ erange: -+ *errnop = ERANGE; -+ return NSS_STATUS_TRYAGAIN; -+ } -+ -+ fgetpos (ent->stream, &pos); -+ buffer[buflen - 1] = '\xff'; -+ p = fgets_unlocked (buffer, buflen, ent->stream); -+ if (p == NULL && feof_unlocked (ent->stream)) -+ { -+ return NSS_STATUS_NOTFOUND; -+ } -+ if (p == NULL || __builtin_expect (buffer[buflen - 1] != '\xff', 0)) -+ { -+ erange_reset: -+ fsetpos (ent->stream, &pos); -+ goto erange; -+ } -+ -+ /* Terminate the line for any case. */ -+ buffer[buflen - 1] = '\0'; -+ -+ /* Skip leading blanks. */ -+ while (isspace (*p)) -+ ++p; -+ } -+ while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */ -+ /* Parse the line. If it is invalid, loop to -+ get the next line of the file to parse. */ -+ !(parse_res = _nss_files_parse_pwent (p, result, data, buflen, -+ errnop))); -+ -+ if (__glibc_unlikely (parse_res == -1)) -+ /* The parser ran out of space. */ -+ goto erange_reset; -+ -+ /* This is a real entry. */ -+ if (result->pw_name[0] != '+' && result->pw_name[0] != '-') -+ { -+ if (strcmp (result->pw_name, name) == 0) -+ return NSS_STATUS_SUCCESS; -+ else -+ continue; -+ } -+ -+ /* -@netgroup */ -+ if (result->pw_name[0] == '-' && result->pw_name[1] == '@' -+ && result->pw_name[2] != '\0') -+ { -+ if (innetgr (&result->pw_name[2], NULL, name, NULL)) -+ return NSS_STATUS_NOTFOUND; -+ continue; -+ } -+ -+ /* +@netgroup */ -+ if (result->pw_name[0] == '+' && result->pw_name[1] == '@' -+ && result->pw_name[2] != '\0') -+ { -+ enum nss_status status; -+ -+ if (innetgr (&result->pw_name[2], NULL, name, NULL)) -+ { -+ status = getpwnam_plususer (name, result, ent, buffer, -+ buflen, errnop); -+ -+ if (status == NSS_STATUS_RETURN) -+ continue; -+ -+ return status; -+ } -+ continue; -+ } -+ -+ /* -user */ -+ if (result->pw_name[0] == '-' && result->pw_name[1] != '\0' -+ && result->pw_name[1] != '@') -+ { -+ if (strcmp (&result->pw_name[1], name) == 0) -+ return NSS_STATUS_NOTFOUND; -+ else -+ continue; -+ } -+ -+ /* +user */ -+ if (result->pw_name[0] == '+' && result->pw_name[1] != '\0' -+ && result->pw_name[1] != '@') -+ { -+ if (strcmp (name, &result->pw_name[1]) == 0) -+ { -+ enum nss_status status; -+ -+ status = getpwnam_plususer (name, result, ent, buffer, buflen, -+ errnop); -+ if (status == NSS_STATUS_RETURN) -+ /* We couldn't parse the entry */ -+ return NSS_STATUS_NOTFOUND; -+ else -+ return status; -+ } -+ } -+ -+ /* +:... */ -+ if (result->pw_name[0] == '+' && result->pw_name[1] == '\0') -+ { -+ enum nss_status status; -+ -+ status = getpwnam_plususer (name, result, ent, -+ buffer, buflen, errnop); -+ if (status == NSS_STATUS_SUCCESS) /* We found the entry. */ -+ break; -+ else if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */ -+ return NSS_STATUS_NOTFOUND; -+ else -+ return status; -+ } -+ } -+ return NSS_STATUS_SUCCESS; -+} -+ -+enum nss_status -+_nss_compat_getpwnam_r (const char *name, struct passwd *pwd, -+ char *buffer, size_t buflen, int *errnop) -+{ -+ enum nss_status result; -+ ent_t ent = { false, false, true, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0 }, -+ { NULL, NULL, 0, 0, NULL, NULL, NULL }}; -+ -+ if (name[0] == '-' || name[0] == '+') -+ return NSS_STATUS_NOTFOUND; -+ -+ __libc_lock_lock (lock); -+ -+ if (ni == NULL) -+ init_nss_interface (); -+ -+ __libc_lock_unlock (lock); -+ -+ result = internal_setpwent (&ent, 0, 0); -+ -+ if (result == NSS_STATUS_SUCCESS) -+ result = internal_getpwnam_r (name, pwd, &ent, buffer, buflen, errnop); -+ -+ internal_endpwent (&ent); -+ -+ return result; -+} -+ -+/* This function handle the + entry in /etc/passwd for getpwuid */ -+static enum nss_status -+getpwuid_plususer (uid_t uid, struct passwd *result, char *buffer, -+ size_t buflen, int *errnop) -+{ -+ struct passwd pwd; -+ char *p; -+ size_t plen; -+ -+ if (!nss_getpwuid_r) -+ return NSS_STATUS_UNAVAIL; -+ -+ memset (&pwd, '\0', sizeof (struct passwd)); -+ -+ copy_pwd_changes (&pwd, result, NULL, 0); -+ -+ plen = pwd_need_buflen (&pwd); -+ if (plen > buflen) -+ { -+ *errnop = ERANGE; -+ return NSS_STATUS_TRYAGAIN; -+ } -+ p = buffer + (buflen - plen); -+ buflen -= plen; -+ -+ if (nss_getpwuid_r (uid, result, buffer, buflen, errnop) == -+ NSS_STATUS_SUCCESS) -+ { -+ copy_pwd_changes (result, &pwd, p, plen); -+ give_pwd_free (&pwd); -+ /* We found the entry. */ -+ return NSS_STATUS_SUCCESS; -+ } -+ else -+ { -+ /* Give buffer the old len back */ -+ buflen += plen; -+ give_pwd_free (&pwd); -+ } -+ return NSS_STATUS_RETURN; -+} -+ -+/* Searches in /etc/passwd and the NSS subsystem for a special user id */ -+static enum nss_status -+internal_getpwuid_r (uid_t uid, struct passwd *result, ent_t *ent, -+ char *buffer, size_t buflen, int *errnop) -+{ -+ struct parser_data *data = (void *) buffer; -+ -+ while (1) -+ { -+ fpos_t pos; -+ char *p; -+ int parse_res; -+ -+ do -+ { -+ /* We need at least 3 characters for one line. */ -+ if (__glibc_unlikely (buflen < 3)) -+ { -+ erange: -+ *errnop = ERANGE; -+ return NSS_STATUS_TRYAGAIN; -+ } -+ -+ fgetpos (ent->stream, &pos); -+ buffer[buflen - 1] = '\xff'; -+ p = fgets_unlocked (buffer, buflen, ent->stream); -+ if (p == NULL && feof_unlocked (ent->stream)) -+ return NSS_STATUS_NOTFOUND; -+ -+ if (p == NULL || __builtin_expect (buffer[buflen - 1] != '\xff', 0)) -+ { -+ erange_reset: -+ fsetpos (ent->stream, &pos); -+ goto erange; -+ } -+ -+ /* Terminate the line for any case. */ -+ buffer[buflen - 1] = '\0'; -+ -+ /* Skip leading blanks. */ -+ while (isspace (*p)) -+ ++p; -+ } -+ while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */ -+ /* Parse the line. If it is invalid, loop to -+ get the next line of the file to parse. */ -+ !(parse_res = _nss_files_parse_pwent (p, result, data, buflen, -+ errnop))); -+ -+ if (__glibc_unlikely (parse_res == -1)) -+ /* The parser ran out of space. */ -+ goto erange_reset; -+ -+ /* This is a real entry. */ -+ if (result->pw_name[0] != '+' && result->pw_name[0] != '-') -+ { -+ if (result->pw_uid == uid) -+ return NSS_STATUS_SUCCESS; -+ else -+ continue; -+ } -+ -+ /* -@netgroup */ -+ if (result->pw_name[0] == '-' && result->pw_name[1] == '@' -+ && result->pw_name[2] != '\0') -+ { -+ /* -1, because we remove first two character of pw_name. */ -+ size_t len = strlen (result->pw_name) - 1; -+ char buf[len]; -+ enum nss_status status; -+ -+ memcpy (buf, &result->pw_name[2], len); -+ -+ status = getpwuid_plususer (uid, result, buffer, buflen, errnop); -+ if (status == NSS_STATUS_SUCCESS && -+ innetgr (buf, NULL, result->pw_name, NULL)) -+ return NSS_STATUS_NOTFOUND; -+ -+ continue; -+ } -+ -+ /* +@netgroup */ -+ if (result->pw_name[0] == '+' && result->pw_name[1] == '@' -+ && result->pw_name[2] != '\0') -+ { -+ /* -1, because we remove first two characters of pw_name. */ -+ size_t len = strlen (result->pw_name) - 1; -+ char buf[len]; -+ enum nss_status status; -+ -+ memcpy (buf, &result->pw_name[2], len); -+ -+ status = getpwuid_plususer (uid, result, buffer, buflen, errnop); -+ -+ if (status == NSS_STATUS_RETURN) -+ continue; -+ -+ if (status == NSS_STATUS_SUCCESS) -+ { -+ if (innetgr (buf, NULL, result->pw_name, NULL)) -+ return NSS_STATUS_SUCCESS; -+ } -+ else if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */ -+ return NSS_STATUS_NOTFOUND; -+ else -+ return status; -+ -+ continue; -+ } -+ -+ /* -user */ -+ if (result->pw_name[0] == '-' && result->pw_name[1] != '\0' -+ && result->pw_name[1] != '@') -+ { -+ size_t len = strlen (result->pw_name); -+ char buf[len]; -+ enum nss_status status; -+ -+ memcpy (buf, &result->pw_name[1], len); -+ -+ status = getpwuid_plususer (uid, result, buffer, buflen, errnop); -+ if (status == NSS_STATUS_SUCCESS && -+ innetgr (buf, NULL, result->pw_name, NULL)) -+ return NSS_STATUS_NOTFOUND; -+ continue; -+ } -+ -+ /* +user */ -+ if (result->pw_name[0] == '+' && result->pw_name[1] != '\0' -+ && result->pw_name[1] != '@') -+ { -+ size_t len = strlen (result->pw_name); -+ char buf[len]; -+ enum nss_status status; -+ -+ memcpy (buf, &result->pw_name[1], len); -+ -+ status = getpwuid_plususer (uid, result, buffer, buflen, errnop); -+ -+ if (status == NSS_STATUS_RETURN) -+ continue; -+ -+ if (status == NSS_STATUS_SUCCESS) -+ { -+ if (strcmp (buf, result->pw_name) == 0) -+ return NSS_STATUS_SUCCESS; -+ } -+ else if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */ -+ return NSS_STATUS_NOTFOUND; -+ else -+ return status; -+ -+ continue; -+ } -+ -+ /* +:... */ -+ if (result->pw_name[0] == '+' && result->pw_name[1] == '\0') -+ { -+ enum nss_status status; -+ -+ status = getpwuid_plususer (uid, result, buffer, buflen, errnop); -+ if (status == NSS_STATUS_SUCCESS) /* We found the entry. */ -+ break; -+ else if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */ -+ return NSS_STATUS_NOTFOUND; -+ else -+ return status; -+ } -+ } -+ return NSS_STATUS_SUCCESS; -+} -+ -+enum nss_status -+_nss_compat_getpwuid_r (uid_t uid, struct passwd *pwd, -+ char *buffer, size_t buflen, int *errnop) -+{ -+ enum nss_status result; -+ ent_t ent = { false, false, true, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0 }, -+ { NULL, NULL, 0, 0, NULL, NULL, NULL }}; -+ -+ __libc_lock_lock (lock); -+ -+ if (ni == NULL) -+ init_nss_interface (); -+ -+ __libc_lock_unlock (lock); -+ -+ result = internal_setpwent (&ent, 0, 0); -+ -+ if (result == NSS_STATUS_SUCCESS) -+ result = internal_getpwuid_r (uid, pwd, &ent, buffer, buflen, errnop); -+ -+ internal_endpwent (&ent); -+ -+ return result; -+} -+ -+ -+/* Support routines for remembering -@netgroup and -user entries. -+ The names are stored in a single string with `|' as separator. */ -+static void -+blacklist_store_name (const char *name, ent_t *ent) -+{ -+ int namelen = strlen (name); -+ char *tmp; -+ -+ /* first call, setup cache */ -+ if (ent->blacklist.size == 0) -+ { -+ ent->blacklist.size = MAX (BLACKLIST_INITIAL_SIZE, 2 * namelen); -+ ent->blacklist.data = malloc (ent->blacklist.size); -+ if (ent->blacklist.data == NULL) -+ return; -+ ent->blacklist.data[0] = '|'; -+ ent->blacklist.data[1] = '\0'; -+ ent->blacklist.current = 1; -+ } -+ else -+ { -+ if (in_blacklist (name, namelen, ent)) -+ return; /* no duplicates */ -+ -+ if (ent->blacklist.current + namelen + 1 >= ent->blacklist.size) -+ { -+ ent->blacklist.size += MAX (BLACKLIST_INCREMENT, 2 * namelen); -+ tmp = realloc (ent->blacklist.data, ent->blacklist.size); -+ if (tmp == NULL) -+ { -+ free (ent->blacklist.data); -+ ent->blacklist.size = 0; -+ return; -+ } -+ ent->blacklist.data = tmp; -+ } -+ } -+ -+ tmp = stpcpy (ent->blacklist.data + ent->blacklist.current, name); -+ *tmp++ = '|'; -+ *tmp = '\0'; -+ ent->blacklist.current += namelen + 1; -+ -+ return; -+} -+ -+/* Returns whether ent->blacklist contains name. */ -+static bool -+in_blacklist (const char *name, int namelen, ent_t *ent) -+{ -+ char buf[namelen + 3]; -+ char *cp; -+ -+ if (ent->blacklist.data == NULL) -+ return false; -+ -+ buf[0] = '|'; -+ cp = stpcpy (&buf[1], name); -+ *cp++ = '|'; -+ *cp = '\0'; -+ return strstr (ent->blacklist.data, buf) != NULL; -+} -Index: glibc-2.26/nss/nss_compat/compat-spwd.c -=================================================================== ---- /dev/null -+++ glibc-2.26/nss/nss_compat/compat-spwd.c -@@ -0,0 +1,857 @@ -+/* Copyright (C) 1996-2017 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Thorsten Kukuk , 1996. -+ -+ 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 -+#include -+ -+#include "netgroup.h" -+#include "nisdomain.h" -+ -+static service_user *ni; -+static enum nss_status (*nss_setspent) (int stayopen); -+static enum nss_status (*nss_getspnam_r) (const char *name, struct spwd * sp, -+ char *buffer, size_t buflen, -+ int *errnop); -+static enum nss_status (*nss_getspent_r) (struct spwd * sp, char *buffer, -+ size_t buflen, int *errnop); -+static enum nss_status (*nss_endspent) (void); -+ -+/* Get the declaration of the parser function. */ -+#define ENTNAME spent -+#define STRUCTURE spwd -+#define EXTERN_PARSER -+#include -+ -+/* Structure for remembering -@netgroup and -user members ... */ -+#define BLACKLIST_INITIAL_SIZE 512 -+#define BLACKLIST_INCREMENT 256 -+struct blacklist_t -+{ -+ char *data; -+ int current; -+ int size; -+}; -+ -+struct ent_t -+{ -+ bool netgroup; -+ bool files; -+ bool first; -+ enum nss_status setent_status; -+ FILE *stream; -+ struct blacklist_t blacklist; -+ struct spwd pwd; -+ struct __netgrent netgrdata; -+}; -+typedef struct ent_t ent_t; -+ -+static ent_t ext_ent = { false, true, false, NSS_STATUS_SUCCESS, NULL, -+ { NULL, 0, 0}, -+ { NULL, NULL, 0, 0, 0, 0, 0, 0, 0}}; -+ -+/* Protect global state against multiple changers. */ -+__libc_lock_define_initialized (static, lock) -+ -+/* Prototypes for local functions. */ -+static void blacklist_store_name (const char *, ent_t *); -+static bool in_blacklist (const char *, int, ent_t *); -+ -+/* Initialize the NSS interface/functions. The calling function must -+ hold the lock. */ -+static void -+init_nss_interface (void) -+{ -+ if (__nss_database_lookup ("shadow_compat", "passwd_compat", -+ "nis", &ni) >= 0) -+ { -+ nss_setspent = __nss_lookup_function (ni, "setspent"); -+ nss_getspnam_r = __nss_lookup_function (ni, "getspnam_r"); -+ nss_getspent_r = __nss_lookup_function (ni, "getspent_r"); -+ nss_endspent = __nss_lookup_function (ni, "endspent"); -+ } -+} -+ -+static void -+give_spwd_free (struct spwd *pwd) -+{ -+ free (pwd->sp_namp); -+ free (pwd->sp_pwdp); -+ -+ memset (pwd, '\0', sizeof (struct spwd)); -+ pwd->sp_warn = -1; -+ pwd->sp_inact = -1; -+ pwd->sp_expire = -1; -+ pwd->sp_flag = ~0ul; -+} -+ -+static int -+spwd_need_buflen (struct spwd *pwd) -+{ -+ int len = 0; -+ -+ if (pwd->sp_pwdp != NULL) -+ len += strlen (pwd->sp_pwdp) + 1; -+ -+ return len; -+} -+ -+static void -+copy_spwd_changes (struct spwd *dest, struct spwd *src, -+ char *buffer, size_t buflen) -+{ -+ if (src->sp_pwdp != NULL && strlen (src->sp_pwdp)) -+ { -+ if (buffer == NULL) -+ dest->sp_pwdp = strdup (src->sp_pwdp); -+ else if (dest->sp_pwdp && -+ strlen (dest->sp_pwdp) >= strlen (src->sp_pwdp)) -+ strcpy (dest->sp_pwdp, src->sp_pwdp); -+ else -+ { -+ dest->sp_pwdp = buffer; -+ strcpy (dest->sp_pwdp, src->sp_pwdp); -+ buffer += strlen (dest->sp_pwdp) + 1; -+ buflen = buflen - (strlen (dest->sp_pwdp) + 1); -+ } -+ } -+ if (src->sp_lstchg != 0) -+ dest->sp_lstchg = src->sp_lstchg; -+ if (src->sp_min != 0) -+ dest->sp_min = src->sp_min; -+ if (src->sp_max != 0) -+ dest->sp_max = src->sp_max; -+ if (src->sp_warn != -1) -+ dest->sp_warn = src->sp_warn; -+ if (src->sp_inact != -1) -+ dest->sp_inact = src->sp_inact; -+ if (src->sp_expire != -1) -+ dest->sp_expire = src->sp_expire; -+ if (src->sp_flag != ~0ul) -+ dest->sp_flag = src->sp_flag; -+} -+ -+static enum nss_status -+internal_setspent (ent_t *ent, int stayopen, int needent) -+{ -+ enum nss_status status = NSS_STATUS_SUCCESS; -+ -+ ent->first = ent->netgroup = 0; -+ ent->files = true; -+ -+ /* If something was left over free it. */ -+ if (ent->netgroup) -+ __internal_endnetgrent (&ent->netgrdata); -+ -+ if (ent->blacklist.data != NULL) -+ { -+ ent->blacklist.current = 1; -+ ent->blacklist.data[0] = '|'; -+ ent->blacklist.data[1] = '\0'; -+ } -+ else -+ ent->blacklist.current = 0; -+ -+ if (ent->stream == NULL) -+ { -+ ent->stream = fopen ("/etc/shadow", "rme"); -+ -+ if (ent->stream == NULL) -+ status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; -+ else -+ /* We take care of locking ourself. */ -+ __fsetlocking (ent->stream, FSETLOCKING_BYCALLER); -+ } -+ else -+ rewind (ent->stream); -+ -+ give_spwd_free (&ent->pwd); -+ -+ if (needent && status == NSS_STATUS_SUCCESS && nss_setspent) -+ ent->setent_status = nss_setspent (stayopen); -+ -+ return status; -+} -+ -+ -+enum nss_status -+_nss_compat_setspent (int stayopen) -+{ -+ enum nss_status result; -+ -+ __libc_lock_lock (lock); -+ -+ if (ni == NULL) -+ init_nss_interface (); -+ -+ result = internal_setspent (&ext_ent, stayopen, 1); -+ -+ __libc_lock_unlock (lock); -+ -+ return result; -+} -+ -+ -+static enum nss_status -+internal_endspent (ent_t *ent) -+{ -+ if (ent->stream != NULL) -+ { -+ fclose (ent->stream); -+ ent->stream = NULL; -+ } -+ -+ if (ent->netgroup) -+ __internal_endnetgrent (&ent->netgrdata); -+ -+ ent->first = ent->netgroup = false; -+ ent->files = true; -+ -+ if (ent->blacklist.data != NULL) -+ { -+ ent->blacklist.current = 1; -+ ent->blacklist.data[0] = '|'; -+ ent->blacklist.data[1] = '\0'; -+ } -+ else -+ ent->blacklist.current = 0; -+ -+ give_spwd_free (&ent->pwd); -+ -+ return NSS_STATUS_SUCCESS; -+} -+ -+enum nss_status -+_nss_compat_endspent (void) -+{ -+ enum nss_status result; -+ -+ __libc_lock_lock (lock); -+ -+ if (nss_endspent) -+ nss_endspent (); -+ -+ result = internal_endspent (&ext_ent); -+ -+ __libc_lock_unlock (lock); -+ -+ return result; -+} -+ -+ -+static enum nss_status -+getspent_next_nss_netgr (const char *name, struct spwd *result, ent_t *ent, -+ char *group, char *buffer, size_t buflen, -+ int *errnop) -+{ -+ char *curdomain = NULL, *host, *user, *domain, *p2; -+ size_t p2len; -+ -+ if (!nss_getspnam_r) -+ return NSS_STATUS_UNAVAIL; -+ -+ /* If the setpwent call failed, say so. */ -+ if (ent->setent_status != NSS_STATUS_SUCCESS) -+ return ent->setent_status; -+ -+ if (ent->first) -+ { -+ memset (&ent->netgrdata, 0, sizeof (struct __netgrent)); -+ __internal_setnetgrent (group, &ent->netgrdata); -+ ent->first = false; -+ } -+ -+ while (1) -+ { -+ enum nss_status status; -+ -+ status = __internal_getnetgrent_r (&host, &user, &domain, -+ &ent->netgrdata, buffer, buflen, -+ errnop); -+ if (status != 1) -+ { -+ __internal_endnetgrent (&ent->netgrdata); -+ ent->netgroup = false; -+ give_spwd_free (&ent->pwd); -+ return NSS_STATUS_RETURN; -+ } -+ -+ if (user == NULL || user[0] == '-') -+ continue; -+ -+ if (domain != NULL) -+ { -+ if (curdomain == NULL -+ && __nss_get_default_domain (&curdomain) != 0) -+ { -+ __internal_endnetgrent (&ent->netgrdata); -+ ent->netgroup = false; -+ give_spwd_free (&ent->pwd); -+ return NSS_STATUS_UNAVAIL; -+ } -+ if (strcmp (curdomain, domain) != 0) -+ continue; -+ } -+ -+ /* If name != NULL, we are called from getpwnam */ -+ if (name != NULL) -+ if (strcmp (user, name) != 0) -+ continue; -+ -+ p2len = spwd_need_buflen (&ent->pwd); -+ if (p2len > buflen) -+ { -+ *errnop = ERANGE; -+ return NSS_STATUS_TRYAGAIN; -+ } -+ p2 = buffer + (buflen - p2len); -+ buflen -= p2len; -+ -+ if (nss_getspnam_r (user, result, buffer, buflen, errnop) != -+ NSS_STATUS_SUCCESS) -+ continue; -+ -+ if (!in_blacklist (result->sp_namp, strlen (result->sp_namp), ent)) -+ { -+ /* Store the User in the blacklist for possible the "+" at the -+ end of /etc/passwd */ -+ blacklist_store_name (result->sp_namp, ent); -+ copy_spwd_changes (result, &ent->pwd, p2, p2len); -+ break; -+ } -+ } -+ -+ return NSS_STATUS_SUCCESS; -+} -+ -+ -+static enum nss_status -+getspent_next_nss (struct spwd *result, ent_t *ent, -+ char *buffer, size_t buflen, int *errnop) -+{ -+ enum nss_status status; -+ char *p2; -+ size_t p2len; -+ -+ if (!nss_getspent_r) -+ return NSS_STATUS_UNAVAIL; -+ -+ p2len = spwd_need_buflen (&ent->pwd); -+ if (p2len > buflen) -+ { -+ *errnop = ERANGE; -+ return NSS_STATUS_TRYAGAIN; -+ } -+ p2 = buffer + (buflen - p2len); -+ buflen -= p2len; -+ do -+ { -+ if ((status = nss_getspent_r (result, buffer, buflen, errnop)) != -+ NSS_STATUS_SUCCESS) -+ return status; -+ } -+ while (in_blacklist (result->sp_namp, strlen (result->sp_namp), ent)); -+ -+ copy_spwd_changes (result, &ent->pwd, p2, p2len); -+ -+ return NSS_STATUS_SUCCESS; -+} -+ -+ -+/* This function handle the +user entrys in /etc/shadow */ -+static enum nss_status -+getspnam_plususer (const char *name, struct spwd *result, ent_t *ent, -+ char *buffer, size_t buflen, int *errnop) -+{ -+ if (!nss_getspnam_r) -+ return NSS_STATUS_UNAVAIL; -+ -+ struct spwd pwd; -+ memset (&pwd, '\0', sizeof (struct spwd)); -+ pwd.sp_warn = -1; -+ pwd.sp_inact = -1; -+ pwd.sp_expire = -1; -+ pwd.sp_flag = ~0ul; -+ -+ copy_spwd_changes (&pwd, result, NULL, 0); -+ -+ size_t plen = spwd_need_buflen (&pwd); -+ if (plen > buflen) -+ { -+ *errnop = ERANGE; -+ return NSS_STATUS_TRYAGAIN; -+ } -+ char *p = buffer + (buflen - plen); -+ buflen -= plen; -+ -+ enum nss_status status = nss_getspnam_r (name, result, buffer, buflen, -+ errnop); -+ if (status != NSS_STATUS_SUCCESS) -+ return status; -+ -+ if (in_blacklist (result->sp_namp, strlen (result->sp_namp), ent)) -+ return NSS_STATUS_NOTFOUND; -+ -+ copy_spwd_changes (result, &pwd, p, plen); -+ give_spwd_free (&pwd); -+ /* We found the entry. */ -+ return NSS_STATUS_SUCCESS; -+} -+ -+ -+static enum nss_status -+getspent_next_file (struct spwd *result, ent_t *ent, -+ char *buffer, size_t buflen, int *errnop) -+{ -+ struct parser_data *data = (void *) buffer; -+ while (1) -+ { -+ fpos_t pos; -+ int parse_res = 0; -+ char *p; -+ -+ do -+ { -+ /* We need at least 3 characters for one line. */ -+ if (__glibc_unlikely (buflen < 3)) -+ { -+ erange: -+ *errnop = ERANGE; -+ return NSS_STATUS_TRYAGAIN; -+ } -+ -+ fgetpos (ent->stream, &pos); -+ buffer[buflen - 1] = '\xff'; -+ p = fgets_unlocked (buffer, buflen, ent->stream); -+ if (p == NULL && feof_unlocked (ent->stream)) -+ return NSS_STATUS_NOTFOUND; -+ -+ if (p == NULL || __builtin_expect (buffer[buflen - 1] != '\xff', 0)) -+ { -+ erange_reset: -+ fsetpos (ent->stream, &pos); -+ goto erange; -+ } -+ -+ /* Skip leading blanks. */ -+ while (isspace (*p)) -+ ++p; -+ } -+ while (*p == '\0' || *p == '#' /* Ignore empty and comment lines. */ -+ /* Parse the line. If it is invalid, loop to -+ get the next line of the file to parse. */ -+ || !(parse_res = _nss_files_parse_spent (p, result, data, -+ buflen, errnop))); -+ -+ if (__glibc_unlikely (parse_res == -1)) -+ /* The parser ran out of space. */ -+ goto erange_reset; -+ -+ if (result->sp_namp[0] != '+' && result->sp_namp[0] != '-') -+ /* This is a real entry. */ -+ break; -+ -+ /* -@netgroup */ -+ if (result->sp_namp[0] == '-' && result->sp_namp[1] == '@' -+ && result->sp_namp[2] != '\0') -+ { -+ /* XXX Do not use fixed length buffers. */ -+ char buf2[1024]; -+ char *user, *host, *domain; -+ struct __netgrent netgrdata; -+ -+ memset (&netgrdata, 0, sizeof (struct __netgrent)); -+ __internal_setnetgrent (&result->sp_namp[2], &netgrdata); -+ while (__internal_getnetgrent_r (&host, &user, &domain, -+ &netgrdata, buf2, sizeof (buf2), -+ errnop)) -+ { -+ if (user != NULL && user[0] != '-') -+ blacklist_store_name (user, ent); -+ } -+ __internal_endnetgrent (&netgrdata); -+ continue; -+ } -+ -+ /* +@netgroup */ -+ if (result->sp_namp[0] == '+' && result->sp_namp[1] == '@' -+ && result->sp_namp[2] != '\0') -+ { -+ int status; -+ -+ ent->netgroup = true; -+ ent->first = true; -+ copy_spwd_changes (&ent->pwd, result, NULL, 0); -+ -+ status = getspent_next_nss_netgr (NULL, result, ent, -+ &result->sp_namp[2], -+ buffer, buflen, errnop); -+ if (status == NSS_STATUS_RETURN) -+ continue; -+ else -+ return status; -+ } -+ -+ /* -user */ -+ if (result->sp_namp[0] == '-' && result->sp_namp[1] != '\0' -+ && result->sp_namp[1] != '@') -+ { -+ blacklist_store_name (&result->sp_namp[1], ent); -+ continue; -+ } -+ -+ /* +user */ -+ if (result->sp_namp[0] == '+' && result->sp_namp[1] != '\0' -+ && result->sp_namp[1] != '@') -+ { -+ size_t len = strlen (result->sp_namp); -+ char buf[len]; -+ enum nss_status status; -+ -+ /* Store the User in the blacklist for the "+" at the end of -+ /etc/passwd */ -+ memcpy (buf, &result->sp_namp[1], len); -+ status = getspnam_plususer (&result->sp_namp[1], result, ent, -+ buffer, buflen, errnop); -+ blacklist_store_name (buf, ent); -+ -+ if (status == NSS_STATUS_SUCCESS) /* We found the entry. */ -+ break; -+ /* We couldn't parse the entry */ -+ else if (status == NSS_STATUS_RETURN -+ /* entry doesn't exist */ -+ || status == NSS_STATUS_NOTFOUND) -+ continue; -+ else -+ { -+ if (status == NSS_STATUS_TRYAGAIN) -+ { -+ fsetpos (ent->stream, &pos); -+ *errnop = ERANGE; -+ } -+ return status; -+ } -+ } -+ -+ /* +:... */ -+ if (result->sp_namp[0] == '+' && result->sp_namp[1] == '\0') -+ { -+ ent->files = false; -+ ent->first = true; -+ copy_spwd_changes (&ent->pwd, result, NULL, 0); -+ -+ return getspent_next_nss (result, ent, buffer, buflen, errnop); -+ } -+ } -+ -+ return NSS_STATUS_SUCCESS; -+} -+ -+ -+static enum nss_status -+internal_getspent_r (struct spwd *pw, ent_t *ent, -+ char *buffer, size_t buflen, int *errnop) -+{ -+ if (ent->netgroup) -+ { -+ enum nss_status status; -+ -+ /* We are searching members in a netgroup */ -+ /* Since this is not the first call, we don't need the group name */ -+ status = getspent_next_nss_netgr (NULL, pw, ent, NULL, buffer, -+ buflen, errnop); -+ -+ if (status == NSS_STATUS_RETURN) -+ return getspent_next_file (pw, ent, buffer, buflen, errnop); -+ else -+ return status; -+ } -+ else if (ent->files) -+ return getspent_next_file (pw, ent, buffer, buflen, errnop); -+ else -+ return getspent_next_nss (pw, ent, buffer, buflen, errnop); -+} -+ -+ -+enum nss_status -+_nss_compat_getspent_r (struct spwd *pwd, char *buffer, size_t buflen, -+ int *errnop) -+{ -+ enum nss_status result = NSS_STATUS_SUCCESS; -+ -+ __libc_lock_lock (lock); -+ -+ /* Be prepared that the setpwent function was not called before. */ -+ if (ni == NULL) -+ init_nss_interface (); -+ -+ if (ext_ent.stream == NULL) -+ result = internal_setspent (&ext_ent, 1, 1); -+ -+ if (result == NSS_STATUS_SUCCESS) -+ result = internal_getspent_r (pwd, &ext_ent, buffer, buflen, errnop); -+ -+ __libc_lock_unlock (lock); -+ -+ return result; -+} -+ -+ -+/* Searches in /etc/passwd and the NIS/NIS+ map for a special user */ -+static enum nss_status -+internal_getspnam_r (const char *name, struct spwd *result, ent_t *ent, -+ char *buffer, size_t buflen, int *errnop) -+{ -+ struct parser_data *data = (void *) buffer; -+ -+ while (1) -+ { -+ fpos_t pos; -+ char *p; -+ int parse_res; -+ -+ do -+ { -+ /* We need at least 3 characters for one line. */ -+ if (__glibc_unlikely (buflen < 3)) -+ { -+ erange: -+ *errnop = ERANGE; -+ return NSS_STATUS_TRYAGAIN; -+ } -+ -+ fgetpos (ent->stream, &pos); -+ buffer[buflen - 1] = '\xff'; -+ p = fgets_unlocked (buffer, buflen, ent->stream); -+ if (p == NULL && feof_unlocked (ent->stream)) -+ return NSS_STATUS_NOTFOUND; -+ -+ if (p == NULL || buffer[buflen - 1] != '\xff') -+ { -+ erange_reset: -+ fsetpos (ent->stream, &pos); -+ goto erange; -+ } -+ -+ /* Terminate the line for any case. */ -+ buffer[buflen - 1] = '\0'; -+ -+ /* Skip leading blanks. */ -+ while (isspace (*p)) -+ ++p; -+ } -+ while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */ -+ /* Parse the line. If it is invalid, loop to -+ get the next line of the file to parse. */ -+ !(parse_res = _nss_files_parse_spent (p, result, data, buflen, -+ errnop))); -+ -+ if (__glibc_unlikely (parse_res == -1)) -+ /* The parser ran out of space. */ -+ goto erange_reset; -+ -+ /* This is a real entry. */ -+ if (result->sp_namp[0] != '+' && result->sp_namp[0] != '-') -+ { -+ if (strcmp (result->sp_namp, name) == 0) -+ return NSS_STATUS_SUCCESS; -+ else -+ continue; -+ } -+ -+ /* -@netgroup */ -+ /* If the loaded NSS module does not support this service, add -+ all users from a +@netgroup entry to the blacklist, too. */ -+ if (result->sp_namp[0] == '-' && result->sp_namp[1] == '@' -+ && result->sp_namp[2] != '\0') -+ { -+ if (innetgr (&result->sp_namp[2], NULL, name, NULL)) -+ return NSS_STATUS_NOTFOUND; -+ continue; -+ } -+ -+ /* +@netgroup */ -+ if (result->sp_namp[0] == '+' && result->sp_namp[1] == '@' -+ && result->sp_namp[2] != '\0') -+ { -+ enum nss_status status; -+ -+ if (innetgr (&result->sp_namp[2], NULL, name, NULL)) -+ { -+ status = getspnam_plususer (name, result, ent, buffer, -+ buflen, errnop); -+ -+ if (status == NSS_STATUS_RETURN) -+ continue; -+ -+ return status; -+ } -+ continue; -+ } -+ -+ /* -user */ -+ if (result->sp_namp[0] == '-' && result->sp_namp[1] != '\0' -+ && result->sp_namp[1] != '@') -+ { -+ if (strcmp (&result->sp_namp[1], name) == 0) -+ return NSS_STATUS_NOTFOUND; -+ else -+ continue; -+ } -+ -+ /* +user */ -+ if (result->sp_namp[0] == '+' && result->sp_namp[1] != '\0' -+ && result->sp_namp[1] != '@') -+ { -+ if (strcmp (name, &result->sp_namp[1]) == 0) -+ { -+ enum nss_status status; -+ -+ status = getspnam_plususer (name, result, ent, -+ buffer, buflen, errnop); -+ -+ if (status == NSS_STATUS_RETURN) -+ /* We couldn't parse the entry */ -+ return NSS_STATUS_NOTFOUND; -+ else -+ return status; -+ } -+ } -+ -+ /* +:... */ -+ if (result->sp_namp[0] == '+' && result->sp_namp[1] == '\0') -+ { -+ enum nss_status status; -+ -+ status = getspnam_plususer (name, result, ent, -+ buffer, buflen, errnop); -+ -+ if (status == NSS_STATUS_SUCCESS) -+ /* We found the entry. */ -+ break; -+ else if (status == NSS_STATUS_RETURN) -+ /* We couldn't parse the entry */ -+ return NSS_STATUS_NOTFOUND; -+ else -+ return status; -+ } -+ } -+ return NSS_STATUS_SUCCESS; -+} -+ -+ -+enum nss_status -+_nss_compat_getspnam_r (const char *name, struct spwd *pwd, -+ char *buffer, size_t buflen, int *errnop) -+{ -+ enum nss_status result; -+ ent_t ent = { false, true, false, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0}, -+ { NULL, NULL, 0, 0, 0, 0, 0, 0, 0}}; -+ -+ if (name[0] == '-' || name[0] == '+') -+ return NSS_STATUS_NOTFOUND; -+ -+ __libc_lock_lock (lock); -+ -+ if (ni == NULL) -+ init_nss_interface (); -+ -+ __libc_lock_unlock (lock); -+ -+ result = internal_setspent (&ent, 0, 0); -+ -+ if (result == NSS_STATUS_SUCCESS) -+ result = internal_getspnam_r (name, pwd, &ent, buffer, buflen, errnop); -+ -+ internal_endspent (&ent); -+ -+ return result; -+} -+ -+ -+/* Support routines for remembering -@netgroup and -user entries. -+ The names are stored in a single string with `|' as separator. */ -+static void -+blacklist_store_name (const char *name, ent_t *ent) -+{ -+ int namelen = strlen (name); -+ char *tmp; -+ -+ /* first call, setup cache */ -+ if (ent->blacklist.size == 0) -+ { -+ ent->blacklist.size = MAX (BLACKLIST_INITIAL_SIZE, 2 * namelen); -+ ent->blacklist.data = malloc (ent->blacklist.size); -+ if (ent->blacklist.data == NULL) -+ return; -+ ent->blacklist.data[0] = '|'; -+ ent->blacklist.data[1] = '\0'; -+ ent->blacklist.current = 1; -+ } -+ else -+ { -+ if (in_blacklist (name, namelen, ent)) -+ return; /* no duplicates */ -+ -+ if (ent->blacklist.current + namelen + 1 >= ent->blacklist.size) -+ { -+ ent->blacklist.size += MAX (BLACKLIST_INCREMENT, 2 * namelen); -+ tmp = realloc (ent->blacklist.data, ent->blacklist.size); -+ if (tmp == NULL) -+ { -+ free (ent->blacklist.data); -+ ent->blacklist.size = 0; -+ return; -+ } -+ ent->blacklist.data = tmp; -+ } -+ } -+ -+ tmp = stpcpy (ent->blacklist.data + ent->blacklist.current, name); -+ *tmp++ = '|'; -+ *tmp = '\0'; -+ ent->blacklist.current += namelen + 1; -+ -+ return; -+} -+ -+ -+/* Returns whether ent->blacklist contains name. */ -+static bool -+in_blacklist (const char *name, int namelen, ent_t *ent) -+{ -+ char buf[namelen + 3]; -+ char *cp; -+ -+ if (ent->blacklist.data == NULL) -+ return false; -+ -+ buf[0] = '|'; -+ cp = stpcpy (&buf[1], name); -+ *cp++ = '|'; -+ *cp = '\0'; -+ return strstr (ent->blacklist.data, buf) != NULL; -+} -Index: glibc-2.26/nss/nss_compat/nisdomain.c -=================================================================== ---- /dev/null -+++ glibc-2.26/nss/nss_compat/nisdomain.c -@@ -0,0 +1,58 @@ -+/* 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 "nisdomain.h" -+ -+#define MAXDOMAINNAMELEN 1024 -+ -+static char domainname[MAXDOMAINNAMELEN]; -+ -+__libc_lock_define_initialized (static, domainname_lock) -+ -+int -+__nss_get_default_domain (char **outdomain) -+{ -+ int result = 0; -+ *outdomain = NULL; -+ -+ __libc_lock_lock (domainname_lock); -+ -+ if (domainname[0] != '\0') -+ { -+ if (getdomainname (domainname, MAXDOMAINNAMELEN) < 0) -+ result = errno; -+ else if (strcmp (domainname, "(none)") == 0) -+ { -+ /* If domainname is not set, some systems will return "(none)" */ -+ domainname[0] = '\0'; -+ result = ENOENT; -+ } -+ else -+ *outdomain = domainname; -+ } -+ else -+ *outdomain = domainname; -+ -+ __libc_lock_unlock (domainname_lock); -+ -+ return result; -+} -Index: glibc-2.26/nss/nss_compat/nisdomain.h -=================================================================== ---- /dev/null -+++ glibc-2.26/nss/nss_compat/nisdomain.h -@@ -0,0 +1,20 @@ -+/* 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 -+ . */ -+ -+/* Set OUTDOMAIN to a pointer to the current NIS domain name, or NULL if -+ not set. Return zero on success, an error number on failure. */ -+extern int __nss_get_default_domain (char **outdomain); diff --git a/nss-db-path.patch b/nss-db-path.patch index f485008..302fcf7 100644 --- a/nss-db-path.patch +++ b/nss-db-path.patch @@ -1,10 +1,10 @@ Use /var/db for nss_db -Index: glibc-2.17.90/Makeconfig +Index: glibc-2.27/Makeconfig =================================================================== ---- glibc-2.17.90.orig/Makeconfig -+++ glibc-2.17.90/Makeconfig -@@ -259,7 +259,7 @@ inst_sysconfdir = $(install_root)$(sysco +--- glibc-2.27.orig/Makeconfig ++++ glibc-2.27/Makeconfig +@@ -245,7 +245,7 @@ inst_sysconfdir = $(install_root)$(sysco # Directory for the database files and Makefile for nss_db. ifndef vardbdir @@ -13,10 +13,10 @@ Index: glibc-2.17.90/Makeconfig endif inst_vardbdir = $(install_root)$(vardbdir) -Index: glibc-2.17.90/nss/db-Makefile +Index: glibc-2.27/nss/db-Makefile =================================================================== ---- glibc-2.17.90.orig/nss/db-Makefile -+++ glibc-2.17.90/nss/db-Makefile +--- glibc-2.27.orig/nss/db-Makefile ++++ glibc-2.27/nss/db-Makefile @@ -22,7 +22,7 @@ DATABASES = $(wildcard /etc/passwd /etc/ /etc/rpc /etc/services /etc/shadow /etc/gshadow \ /etc/netgroup) @@ -26,10 +26,10 @@ Index: glibc-2.17.90/nss/db-Makefile AWK = awk MAKEDB = makedb --quiet -Index: glibc-2.17.90/sysdeps/unix/sysv/linux/paths.h +Index: glibc-2.27/sysdeps/unix/sysv/linux/paths.h =================================================================== ---- glibc-2.17.90.orig/sysdeps/unix/sysv/linux/paths.h -+++ glibc-2.17.90/sysdeps/unix/sysv/linux/paths.h +--- glibc-2.27.orig/sysdeps/unix/sysv/linux/paths.h ++++ glibc-2.27/sysdeps/unix/sysv/linux/paths.h @@ -68,7 +68,7 @@ /* Provide trailing slash, since mostly used for building pathnames. */ #define _PATH_DEV "/dev/" diff --git a/nss-files-large-buffers.patch b/nss-files-large-buffers.patch deleted file mode 100644 index 6419e3f..0000000 --- a/nss-files-large-buffers.patch +++ /dev/null @@ -1,831 +0,0 @@ -2017-10-11 Florian Weimer - - [BZ #22078] - Avoid large NSS buffers with many addresses, aliases. - * nss/nss_files/files-hosts.c (gethostbyname3_multi): Rewrite - using dynarrays and struct alloc_buffer. - * nss/Makefile (tests): Add tst-nss-files-hosts-multi. - (tst-nss-files-hosts-multi): Link with -ldl. - * nss/tst-nss-files-hosts-multi.c: New file. - -2017-10-11 Florian Weimer - - [BZ #18023] - * nss/nss_files/files-hosts.c (gethostbyname3_multi): Use struct - scratch_buffer. Eliminate gotos. - -2017-10-10 Florian Weimer - - * nss/nss_files/files-hosts.c (gethostbyname3_multi): New - function. - (_nss_files_gethostbyname3_r): Call it. - -Index: glibc-2.26/nss/Makefile -=================================================================== ---- glibc-2.26.orig/nss/Makefile -+++ glibc-2.26/nss/Makefile -@@ -61,6 +61,7 @@ xtests = bug-erange - # Tests which need libdl - ifeq (yes,$(build-shared)) - tests += tst-nss-files-hosts-erange -+tests += tst-nss-files-hosts-multi - endif - - # If we have a thread library then we can test cancellation against -@@ -165,3 +166,4 @@ $(objpfx)tst-cancel-getpwuid_r: $(shared - endif - - $(objpfx)tst-nss-files-hosts-erange: $(libdl) -+$(objpfx)tst-nss-files-hosts-multi: $(libdl) -Index: glibc-2.26/nss/nss_files/files-hosts.c -=================================================================== ---- glibc-2.26.orig/nss/nss_files/files-hosts.c -+++ glibc-2.26/nss/nss_files/files-hosts.c -@@ -22,6 +22,8 @@ - #include - #include - #include -+#include -+#include - - - /* Get implementation for some internal functions. */ -@@ -110,228 +112,250 @@ DB_LOOKUP (hostbyaddr, ,,, - }, const void *addr, socklen_t len, int af) - #undef EXTRA_ARGS_VALUE - --enum nss_status --_nss_files_gethostbyname3_r (const char *name, int af, struct hostent *result, -- char *buffer, size_t buflen, int *errnop, -- int *herrnop, int32_t *ttlp, char **canonp) -+/* Type of the address and alias arrays. */ -+#define DYNARRAY_STRUCT array -+#define DYNARRAY_ELEMENT char * -+#define DYNARRAY_PREFIX array_ -+#include -+ -+static enum nss_status -+gethostbyname3_multi (FILE * stream, const char *name, int af, -+ struct hostent *result, char *buffer, size_t buflen, -+ int *errnop, int *herrnop, int flags) - { -- FILE *stream = NULL; -- uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct hostent_data); -- buffer += pad; -- buflen = buflen > pad ? buflen - pad : 0; -+ assert (af == AF_INET || af == AF_INET6); - -- /* Open file. */ -- enum nss_status status = internal_setent (&stream); -+ /* We have to get all host entries from the file. */ -+ struct scratch_buffer tmp_buffer; -+ scratch_buffer_init (&tmp_buffer); -+ struct hostent tmp_result_buf; -+ struct array addresses; -+ array_init (&addresses); -+ struct array aliases; -+ array_init (&aliases); -+ enum nss_status status; -+ -+ /* Preserve the addresses and aliases encountered so far. */ -+ for (size_t i = 0; result->h_addr_list[i] != NULL; ++i) -+ array_add (&addresses, result->h_addr_list[i]); -+ for (size_t i = 0; result->h_aliases[i] != NULL; ++i) -+ array_add (&aliases, result->h_aliases[i]); -+ -+ /* The output buffer re-uses now-unused space at the end of the -+ buffer, starting with the aliases array. It comes last in the -+ data produced by internal_getent. (The alias names themselves -+ are still located in the line read in internal_getent, which is -+ stored at the beginning of the buffer.) */ -+ struct alloc_buffer outbuf; -+ { -+ char *bufferend = (char *) result->h_aliases; -+ outbuf = alloc_buffer_create (bufferend, buffer + buflen - bufferend); -+ } - -- if (status == NSS_STATUS_SUCCESS) -+ while (true) - { -- /* XXX Is using _res to determine whether we want to convert IPv4 -- addresses to IPv6 addresses really the right thing to do? */ -- int flags = (res_use_inet6 () ? AI_V4MAPPED : 0); -- -- while ((status = internal_getent (stream, result, buffer, buflen, errnop, -- herrnop, af, flags)) -- == NSS_STATUS_SUCCESS) -+ status = internal_getent (stream, &tmp_result_buf, tmp_buffer.data, -+ tmp_buffer.length, errnop, herrnop, af, -+ flags); -+ /* Enlarge the buffer if necessary. */ -+ if (status == NSS_STATUS_TRYAGAIN && *herrnop == NETDB_INTERNAL -+ && *errnop == ERANGE) - { -- LOOKUP_NAME_CASE (h_name, h_aliases) -+ if (!scratch_buffer_grow (&tmp_buffer)) -+ { -+ *errnop = ENOMEM; -+ /* *herrnop and status already have the right value. */ -+ break; -+ } -+ /* Loop around and retry with a larger buffer. */ - } -- -- if (status == NSS_STATUS_SUCCESS -- && _res_hconf.flags & HCONF_FLAG_MULTI) -+ else if (status == NSS_STATUS_SUCCESS) - { -- /* We have to get all host entries from the file. */ -- size_t tmp_buflen = MIN (buflen, 4096); -- char tmp_buffer_stack[tmp_buflen] -- __attribute__ ((__aligned__ (__alignof__ (struct hostent_data)))); -- char *tmp_buffer = tmp_buffer_stack; -- struct hostent tmp_result_buf; -- int naddrs = 1; -- int naliases = 0; -- char *bufferend; -- bool tmp_buffer_malloced = false; -- -- while (result->h_aliases[naliases] != NULL) -- ++naliases; -- -- bufferend = (char *) &result->h_aliases[naliases + 1]; -- -- again: -- while ((status = internal_getent (stream, &tmp_result_buf, tmp_buffer, -- tmp_buflen, errnop, herrnop, af, -- flags)) -- == NSS_STATUS_SUCCESS) -+ /* A line was read. Check that it matches the search -+ criteria. */ -+ -+ int matches = 1; -+ struct hostent *old_result = result; -+ result = &tmp_result_buf; -+ /* The following piece is a bit clumsy but we want to use -+ the `LOOKUP_NAME_CASE' value. The optimizer should do -+ its job. */ -+ do - { -- int matches = 1; -- struct hostent *old_result = result; -- result = &tmp_result_buf; -- /* The following piece is a bit clumsy but we want to use the -- `LOOKUP_NAME_CASE' value. The optimizer should do its -- job. */ -- do -- { -- LOOKUP_NAME_CASE (h_name, h_aliases) -- result = old_result; -- } -- while ((matches = 0)); -+ LOOKUP_NAME_CASE (h_name, h_aliases) -+ result = old_result; -+ } -+ while ((matches = 0)); - -- if (matches) -+ /* If the line matches, we need to copy the addresses and -+ aliases, so that we can reuse tmp_buffer for the next -+ line. */ -+ if (matches) -+ { -+ /* Record the addresses. */ -+ for (size_t i = 0; tmp_result_buf.h_addr_list[i] != NULL; ++i) - { -- /* We could be very clever and try to recycle a few bytes -- in the buffer instead of generating new arrays. But -- we are not doing this here since it's more work than -- it's worth. Simply let the user provide a bit bigger -- buffer. */ -- char **new_h_addr_list; -- char **new_h_aliases; -- int newaliases = 0; -- size_t newstrlen = 0; -- int cnt; -- -- /* Count the new aliases and the length of the strings. */ -- while (tmp_result_buf.h_aliases[newaliases] != NULL) -+ /* Allocate the target space in the output buffer, -+ depending on the address family. */ -+ void *target; -+ if (af == AF_INET) - { -- char *cp = tmp_result_buf.h_aliases[newaliases]; -- ++newaliases; -- newstrlen += strlen (cp) + 1; -+ assert (tmp_result_buf.h_length == 4); -+ target = alloc_buffer_alloc (&outbuf, struct in_addr); - } -- /* If the real name is different add it also to the -- aliases. This means that there is a duplication -- in the alias list but this is really the user's -- problem. */ -- if (strcmp (old_result->h_name, -- tmp_result_buf.h_name) != 0) -+ else if (af == AF_INET6) - { -- ++newaliases; -- newstrlen += strlen (tmp_result_buf.h_name) + 1; -+ assert (tmp_result_buf.h_length == 16); -+ target = alloc_buffer_alloc (&outbuf, struct in6_addr); - } -+ else -+ __builtin_unreachable (); - -- /* Make sure bufferend is aligned. */ -- assert ((bufferend - (char *) 0) % sizeof (char *) == 0); -- -- /* Now we can check whether the buffer is large enough. -- 16 is the maximal size of the IP address. */ -- if (bufferend + 16 + (naddrs + 2) * sizeof (char *) -- + roundup (newstrlen, sizeof (char *)) -- + (naliases + newaliases + 1) * sizeof (char *) -- >= buffer + buflen) -+ if (target == NULL) - { -+ /* Request a larger output buffer. */ - *errnop = ERANGE; - *herrnop = NETDB_INTERNAL; - status = NSS_STATUS_TRYAGAIN; -- goto out; -- } -- -- new_h_addr_list = -- (char **) (bufferend -- + roundup (newstrlen, sizeof (char *)) -- + 16); -- new_h_aliases = -- (char **) ((char *) new_h_addr_list -- + (naddrs + 2) * sizeof (char *)); -- -- /* Copy the old data in the new arrays. */ -- for (cnt = 0; cnt < naddrs; ++cnt) -- new_h_addr_list[cnt] = old_result->h_addr_list[cnt]; -- -- for (cnt = 0; cnt < naliases; ++cnt) -- new_h_aliases[cnt] = old_result->h_aliases[cnt]; -- -- /* Store the new strings. */ -- cnt = 0; -- while (tmp_result_buf.h_aliases[cnt] != NULL) -- { -- new_h_aliases[naliases++] = bufferend; -- bufferend = (__stpcpy (bufferend, -- tmp_result_buf.h_aliases[cnt]) -- + 1); -- ++cnt; -+ break; - } -- -- if (cnt < newaliases) -- { -- new_h_aliases[naliases++] = bufferend; -- bufferend = __stpcpy (bufferend, -- tmp_result_buf.h_name) + 1; -- } -- -- /* Final NULL pointer. */ -- new_h_aliases[naliases] = NULL; -- -- /* Round up the buffer end address. */ -- bufferend += (sizeof (char *) -- - ((bufferend - (char *) 0) -- % sizeof (char *))) % sizeof (char *); -- -- /* Now the new address. */ -- new_h_addr_list[naddrs++] = -- memcpy (bufferend, tmp_result_buf.h_addr, -- tmp_result_buf.h_length); -- -- /* Also here a final NULL pointer. */ -- new_h_addr_list[naddrs] = NULL; -- -- /* Store the new array pointers. */ -- old_result->h_aliases = new_h_aliases; -- old_result->h_addr_list = new_h_addr_list; -- -- /* Compute the new buffer end. */ -- bufferend = (char *) &new_h_aliases[naliases + 1]; -- assert (bufferend <= buffer + buflen); -- -- result = old_result; -+ memcpy (target, tmp_result_buf.h_addr_list[i], -+ tmp_result_buf.h_length); -+ array_add (&addresses, target); - } -- } - -- if (status == NSS_STATUS_TRYAGAIN) -- { -- size_t newsize = 2 * tmp_buflen; -- if (tmp_buffer_malloced) -+ /* Record the aliases. */ -+ for (size_t i = 0; tmp_result_buf.h_aliases[i] != NULL; ++i) - { -- char *newp = realloc (tmp_buffer, newsize); -- if (newp != NULL) -- { -- assert ((((uintptr_t) newp) -- & (__alignof__ (struct hostent_data) - 1)) -- == 0); -- tmp_buffer = newp; -- tmp_buflen = newsize; -- goto again; -- } -+ char *alias = tmp_result_buf.h_aliases[i]; -+ array_add (&aliases, -+ alloc_buffer_copy_string (&outbuf, alias)); - } -- else if (!__libc_use_alloca (buflen + newsize)) -+ -+ /* If the real name is different add, it also to the -+ aliases. This means that there is a duplication in -+ the alias list but this is really the user's -+ problem. */ -+ { -+ char *new_name = tmp_result_buf.h_name; -+ if (strcmp (old_result->h_name, new_name) != 0) -+ array_add (&aliases, -+ alloc_buffer_copy_string (&outbuf, new_name)); -+ } -+ -+ /* Report memory allocation failures during the -+ expansion of the temporary arrays. */ -+ if (array_has_failed (&addresses) || array_has_failed (&aliases)) - { -- tmp_buffer = malloc (newsize); -- if (tmp_buffer != NULL) -- { -- assert ((((uintptr_t) tmp_buffer) -- & (__alignof__ (struct hostent_data) - 1)) -- == 0); -- tmp_buffer_malloced = true; -- tmp_buflen = newsize; -- goto again; -- } -+ *errnop = ENOMEM; -+ *herrnop = NETDB_INTERNAL; -+ status = NSS_STATUS_UNAVAIL; -+ break; - } -- else -+ -+ /* Request a larger output buffer if we ran out of room. */ -+ if (alloc_buffer_has_failed (&outbuf)) - { -- tmp_buffer -- = extend_alloca (tmp_buffer, tmp_buflen, -- newsize -- + __alignof__ (struct hostent_data)); -- tmp_buffer = (char *) (((uintptr_t) tmp_buffer -- + __alignof__ (struct hostent_data) -- - 1) -- & ~(__alignof__ (struct hostent_data) -- - 1)); -- goto again; -+ *errnop = ERANGE; -+ *herrnop = NETDB_INTERNAL; -+ status = NSS_STATUS_TRYAGAIN; -+ break; - } -- } -- else -- status = NSS_STATUS_SUCCESS; -- out: -- if (tmp_buffer_malloced) -- free (tmp_buffer); -+ -+ result = old_result; -+ } /* If match was found. */ -+ -+ /* If no match is found, loop around and fetch another -+ line. */ -+ -+ } /* status == NSS_STATUS_SUCCESS. */ -+ else -+ /* internal_getent returned an error. */ -+ break; -+ } /* while (true) */ -+ -+ /* Propagate the NSS_STATUS_TRYAGAIN error to the caller. It means -+ that we may not have loaded the complete result. -+ NSS_STATUS_NOTFOUND, however, means that we reached the end of -+ the file successfully. */ -+ if (status != NSS_STATUS_TRYAGAIN) -+ status = NSS_STATUS_SUCCESS; -+ -+ if (status == NSS_STATUS_SUCCESS) -+ { -+ /* Copy the address and alias arrays into the output buffer and -+ add NULL terminators. The pointed-to elements were directly -+ written into the output buffer above and do not need to be -+ copied again. */ -+ size_t addresses_count = array_size (&addresses); -+ size_t aliases_count = array_size (&aliases); -+ char **out_addresses = alloc_buffer_alloc_array -+ (&outbuf, char *, addresses_count + 1); -+ char **out_aliases = alloc_buffer_alloc_array -+ (&outbuf, char *, aliases_count + 1); -+ if (out_addresses == NULL || out_aliases == NULL) -+ { -+ /* The output buffer is not large enough. */ -+ *errnop = ERANGE; -+ *herrnop = NETDB_INTERNAL; -+ status = NSS_STATUS_TRYAGAIN; -+ /* Fall through to function exit. */ -+ } -+ else -+ { -+ /* Everything is allocated in place. Make the copies and -+ adjust the array pointers. */ -+ memcpy (out_addresses, array_begin (&addresses), -+ addresses_count * sizeof (char *)); -+ out_addresses[addresses_count] = NULL; -+ memcpy (out_aliases, array_begin (&aliases), -+ aliases_count * sizeof (char *)); -+ out_aliases[aliases_count] = NULL; -+ -+ result->h_addr_list = out_addresses; -+ result->h_aliases = out_aliases; -+ -+ status = NSS_STATUS_SUCCESS; -+ } -+ } -+ -+ scratch_buffer_free (&tmp_buffer); -+ array_free (&addresses); -+ array_free (&aliases); -+ return status; -+} -+ -+enum nss_status -+_nss_files_gethostbyname3_r (const char *name, int af, struct hostent *result, -+ char *buffer, size_t buflen, int *errnop, -+ int *herrnop, int32_t *ttlp, char **canonp) -+{ -+ FILE *stream = NULL; -+ uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct hostent_data); -+ buffer += pad; -+ buflen = buflen > pad ? buflen - pad : 0; -+ -+ /* Open file. */ -+ enum nss_status status = internal_setent (&stream); -+ -+ if (status == NSS_STATUS_SUCCESS) -+ { -+ /* XXX Is using _res to determine whether we want to convert IPv4 -+ addresses to IPv6 addresses really the right thing to do? */ -+ int flags = (res_use_inet6 () ? AI_V4MAPPED : 0); -+ -+ while ((status = internal_getent (stream, result, buffer, buflen, errnop, -+ herrnop, af, flags)) -+ == NSS_STATUS_SUCCESS) -+ { -+ LOOKUP_NAME_CASE (h_name, h_aliases) - } - -+ if (status == NSS_STATUS_SUCCESS -+ && _res_hconf.flags & HCONF_FLAG_MULTI) -+ status = gethostbyname3_multi -+ (stream, name, af, result, buffer, buflen, errnop, herrnop, flags); -+ - internal_endent (&stream); - } - -Index: glibc-2.26/nss/tst-nss-files-hosts-multi.c -=================================================================== ---- /dev/null -+++ glibc-2.26/nss/tst-nss-files-hosts-multi.c -@@ -0,0 +1,331 @@ -+/* Parse /etc/hosts in multi mode with many addresses/aliases. -+ 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct support_chroot *chroot_env; -+ -+static void -+prepare (int argc, char **argv) -+{ -+ chroot_env = support_chroot_create -+ ((struct support_chroot_configuration) -+ { -+ .resolv_conf = "", -+ .hosts = "", /* See write_hosts below. */ -+ .host_conf = "multi on\n", -+ }); -+} -+ -+/* Create the /etc/hosts file from outside the chroot. */ -+static void -+write_hosts (int count) -+{ -+ TEST_VERIFY (count > 0 && count <= 65535); -+ FILE *fp = xfopen (chroot_env->path_hosts, "w"); -+ fputs ("127.0.0.1 localhost localhost.localdomain\n" -+ "::1 localhost localhost.localdomain\n", -+ fp); -+ for (int i = 0; i < count; ++i) -+ { -+ fprintf (fp, "10.4.%d.%d www4.example.com\n", -+ (i / 256) & 0xff, i & 0xff); -+ fprintf (fp, "10.46.%d.%d www.example.com\n", -+ (i / 256) & 0xff, i & 0xff); -+ fprintf (fp, "192.0.2.1 alias.example.com v4-%d.example.com\n", i); -+ fprintf (fp, "2001:db8::6:%x www6.example.com\n", i); -+ fprintf (fp, "2001:db8::46:%x www.example.com\n", i); -+ fprintf (fp, "2001:db8::1 alias.example.com v6-%d.example.com\n", i); -+ } -+ xfclose (fp); -+} -+ -+/* Parameters of a single test. */ -+struct test_params -+{ -+ const char *name; /* Name to query. */ -+ const char *marker; /* Address marker for the name. */ -+ int count; /* Number of addresses/aliases. */ -+ int family; /* AF_INET, AF_INET_6 or AF_UNSPEC. */ -+ bool canonname; /* True if AI_CANONNAME should be enabled. */ -+}; -+ -+/* Expected result of gethostbyname/gethostbyname2. */ -+static char * -+expected_ghbn (const struct test_params *params) -+{ -+ TEST_VERIFY (params->family == AF_INET || params->family == AF_INET6); -+ -+ struct xmemstream expected; -+ xopen_memstream (&expected); -+ if (strcmp (params->name, "alias.example.com") == 0) -+ { -+ fprintf (expected.out, "name: %s\n", params->name); -+ char af; -+ if (params->family == AF_INET) -+ af = '4'; -+ else -+ af = '6'; -+ for (int i = 0; i < params->count; ++i) -+ fprintf (expected.out, "alias: v%c-%d.example.com\n", af, i); -+ -+ for (int i = 0; i < params->count; ++i) -+ if (params->family == AF_INET) -+ fputs ("address: 192.0.2.1\n", expected.out); -+ else -+ fputs ("address: 2001:db8::1\n", expected.out); -+ } -+ else /* www/www4/www6 name. */ -+ { -+ bool do_ipv4 = params->family == AF_INET -+ && strncmp (params->name, "www6", 4) != 0; -+ bool do_ipv6 = params->family == AF_INET6 -+ && strncmp (params->name, "www4", 4) != 0; -+ if (do_ipv4 || do_ipv6) -+ { -+ fprintf (expected.out, "name: %s\n", params->name); -+ if (do_ipv4) -+ for (int i = 0; i < params->count; ++i) -+ fprintf (expected.out, "address: 10.%s.%d.%d\n", -+ params->marker, i / 256, i % 256); -+ if (do_ipv6) -+ for (int i = 0; i < params->count; ++i) -+ fprintf (expected.out, "address: 2001:db8::%s:%x\n", -+ params->marker, i); -+ } -+ else -+ fputs ("error: HOST_NOT_FOUND\n", expected.out); -+ } -+ xfclose_memstream (&expected); -+ return expected.buffer; -+} -+ -+/* Expected result of getaddrinfo. */ -+static char * -+expected_gai (const struct test_params *params) -+{ -+ bool do_ipv4 = false; -+ bool do_ipv6 = false; -+ if (params->family == AF_UNSPEC) -+ do_ipv4 = do_ipv6 = true; -+ else if (params->family == AF_INET) -+ do_ipv4 = true; -+ else if (params->family == AF_INET6) -+ do_ipv6 = true; -+ -+ struct xmemstream expected; -+ xopen_memstream (&expected); -+ if (strcmp (params->name, "alias.example.com") == 0) -+ { -+ if (params->canonname) -+ fprintf (expected.out, -+ "flags: AI_CANONNAME\n" -+ "canonname: %s\n", -+ params->name); -+ -+ if (do_ipv4) -+ for (int i = 0; i < params->count; ++i) -+ fputs ("address: STREAM/TCP 192.0.2.1 80\n", expected.out); -+ if (do_ipv6) -+ for (int i = 0; i < params->count; ++i) -+ fputs ("address: STREAM/TCP 2001:db8::1 80\n", expected.out); -+ } -+ else /* www/www4/www6 name. */ -+ { -+ if (strncmp (params->name, "www4", 4) == 0) -+ do_ipv6 = false; -+ else if (strncmp (params->name, "www6", 4) == 0) -+ do_ipv4 = false; -+ /* Otherwise, we have www as the name, so we do both. */ -+ -+ if (do_ipv4 || do_ipv6) -+ { -+ if (params->canonname) -+ fprintf (expected.out, -+ "flags: AI_CANONNAME\n" -+ "canonname: %s\n", -+ params->name); -+ -+ if (do_ipv4) -+ for (int i = 0; i < params->count; ++i) -+ fprintf (expected.out, "address: STREAM/TCP 10.%s.%d.%d 80\n", -+ params->marker, i / 256, i % 256); -+ if (do_ipv6) -+ for (int i = 0; i < params->count; ++i) -+ fprintf (expected.out, -+ "address: STREAM/TCP 2001:db8::%s:%x 80\n", -+ params->marker, i); -+ } -+ else -+ fputs ("error: Name or service not known\n", expected.out); -+ } -+ xfclose_memstream (&expected); -+ return expected.buffer; -+} -+ -+static void -+run_gbhn_gai (struct test_params *params) -+{ -+ char *ctx = xasprintf ("name=%s marker=%s count=%d family=%d", -+ params->name, params->marker, params->count, -+ params->family); -+ if (test_verbose > 0) -+ printf ("info: %s\n", ctx); -+ -+ /* Check gethostbyname, gethostbyname2. */ -+ if (params->family == AF_INET) -+ { -+ char *expected = expected_ghbn (params); -+ check_hostent (ctx, gethostbyname (params->name), expected); -+ free (expected); -+ } -+ if (params->family != AF_UNSPEC) -+ { -+ char *expected = expected_ghbn (params); -+ check_hostent (ctx, gethostbyname2 (params->name, params->family), -+ expected); -+ free (expected); -+ } -+ -+ /* Check getaddrinfo. */ -+ for (int do_canonical = 0; do_canonical < 2; ++do_canonical) -+ { -+ params->canonname = do_canonical; -+ char *expected = expected_gai (params); -+ struct addrinfo hints = -+ { -+ .ai_family = params->family, -+ .ai_socktype = SOCK_STREAM, -+ .ai_protocol = IPPROTO_TCP, -+ }; -+ if (do_canonical) -+ hints.ai_flags |= AI_CANONNAME; -+ struct addrinfo *ai; -+ int ret = getaddrinfo (params->name, "80", &hints, &ai); -+ check_addrinfo (ctx, ai, ret, expected); -+ if (ret == 0) -+ freeaddrinfo (ai); -+ free (expected); -+ } -+ -+ free (ctx); -+} -+ -+/* Callback for the subprocess which runs the test in a chroot. */ -+static void -+subprocess (void *closure) -+{ -+ struct test_params *params = closure; -+ -+ xchroot (chroot_env->path_chroot); -+ -+ static const int families[] = { AF_INET, AF_INET6, AF_UNSPEC, -1 }; -+ static const char *const names[] = -+ { -+ "www.example.com", "www4.example.com", "www6.example.com", -+ "alias.example.com", -+ NULL -+ }; -+ static const char *const names_marker[] = { "46", "4", "6", "" }; -+ -+ for (int family_idx = 0; families[family_idx] >= 0; ++family_idx) -+ { -+ params->family = families[family_idx]; -+ for (int names_idx = 0; names[names_idx] != NULL; ++names_idx) -+ { -+ params->name = names[names_idx]; -+ params->marker = names_marker[names_idx]; -+ run_gbhn_gai (params); -+ } -+ } -+} -+ -+/* Run the test for a specific number of addresses/aliases. */ -+static void -+run_test (int count) -+{ -+ write_hosts (count); -+ -+ struct test_params params = -+ { -+ .count = count, -+ }; -+ -+ support_isolate_in_subprocess (subprocess, ¶ms); -+} -+ -+static int -+do_test (void) -+{ -+ support_become_root (); -+ if (!support_can_chroot ()) -+ return EXIT_UNSUPPORTED; -+ -+ /* This test should not use gigabytes of memory. */ -+ { -+ struct rlimit limit; -+ if (getrlimit (RLIMIT_AS, &limit) != 0) -+ { -+ printf ("getrlimit (RLIMIT_AS) failed: %m\n"); -+ return 1; -+ } -+ long target = 200 * 1024 * 1024; -+ if (limit.rlim_cur == RLIM_INFINITY || limit.rlim_cur > target) -+ { -+ limit.rlim_cur = target; -+ if (setrlimit (RLIMIT_AS, &limit) != 0) -+ { -+ printf ("setrlimit (RLIMIT_AS) failed: %m\n"); -+ return 1; -+ } -+ } -+ } -+ -+ __nss_configure_lookup ("hosts", "files"); -+ if (dlopen (LIBNSS_FILES_SO, RTLD_LAZY) == NULL) -+ FAIL_EXIT1 ("could not load " LIBNSS_DNS_SO ": %s", dlerror ()); -+ -+ /* Run the tests with a few different address/alias counts. */ -+ for (int count = 1; count <= 111; ++count) -+ run_test (count); -+ run_test (1111); -+ run_test (22222); -+ -+ support_chroot_free (chroot_env); -+ return 0; -+} -+ -+#define PREPARE prepare -+#include diff --git a/nss-files-long-lines-2.patch b/nss-files-long-lines-2.patch index ec41f8a..2e46d0c 100644 --- a/nss-files-long-lines-2.patch +++ b/nss-files-long-lines-2.patch @@ -11,10 +11,10 @@ Properly reread entry after failure in nss_files getent function (bug 18991) (_nss_files_getaliasent_r): Likewise. Reposition stream if last call was uncessful. -Index: glibc-2.19/nss/nss_files/files-XXX.c +Index: glibc-2.27/nss/nss_files/files-XXX.c =================================================================== ---- glibc-2.19.orig/nss/nss_files/files-XXX.c -+++ glibc-2.19/nss/nss_files/files-XXX.c +--- glibc-2.27.orig/nss/nss_files/files-XXX.c ++++ glibc-2.27/nss/nss_files/files-XXX.c @@ -65,6 +65,10 @@ __libc_lock_define_initialized (static, getXXbyYY operations all use their own stream. */ @@ -26,7 +26,7 @@ Index: glibc-2.19/nss/nss_files/files-XXX.c /* Open database file if not already opened. */ static enum nss_status -@@ -131,6 +135,15 @@ CONCAT(_nss_files_set,ENTNAME) (int stay +@@ -96,6 +100,15 @@ CONCAT(_nss_files_set,ENTNAME) (int stay status = internal_setent (&stream); @@ -42,7 +42,7 @@ Index: glibc-2.19/nss/nss_files/files-XXX.c __libc_lock_unlock (lock); return status; -@@ -286,11 +299,42 @@ CONCAT(_nss_files_get,ENTNAME_r) (struct +@@ -251,11 +264,42 @@ CONCAT(_nss_files_get,ENTNAME_r) (struct status = internal_setent (&stream); __set_errno (save_errno); @@ -54,11 +54,9 @@ Index: glibc-2.19/nss/nss_files/files-XXX.c + status = NSS_STATUS_UNAVAIL; + } + need_reread = false; - } - - if (status == NSS_STATUS_SUCCESS) -- status = internal_getent (stream, result, buffer, buflen, errnop -- H_ERRNO_ARG EXTRA_ARGS_VALUE); ++ } ++ ++ if (status == NSS_STATUS_SUCCESS) + { + /* Reposition the stream if the last call was unsucessful. */ + if (need_reread) @@ -68,9 +66,11 @@ Index: glibc-2.19/nss/nss_files/files-XXX.c + else + need_reread = false; + } -+ } -+ -+ if (status == NSS_STATUS_SUCCESS) + } + + if (status == NSS_STATUS_SUCCESS) +- status = internal_getent (stream, result, buffer, buflen, errnop +- H_ERRNO_ARG EXTRA_ARGS_VALUE); + { + status = internal_getent (stream, result, buffer, buflen, errnop + H_ERRNO_ARG EXTRA_ARGS_VALUE); @@ -87,10 +87,10 @@ Index: glibc-2.19/nss/nss_files/files-XXX.c __libc_lock_unlock (lock); -Index: glibc-2.19/nss/nss_files/files-alias.c +Index: glibc-2.27/nss/nss_files/files-alias.c =================================================================== ---- glibc-2.19.orig/nss/nss_files/files-alias.c -+++ glibc-2.19/nss/nss_files/files-alias.c +--- glibc-2.27.orig/nss/nss_files/files-alias.c ++++ glibc-2.27/nss/nss_files/files-alias.c @@ -38,6 +38,10 @@ __libc_lock_define_initialized (static, getXXbyYY operations all use their own stream. */ @@ -102,7 +102,7 @@ Index: glibc-2.19/nss/nss_files/files-alias.c static enum nss_status -@@ -104,6 +108,15 @@ _nss_files_setaliasent (void) +@@ -69,6 +73,15 @@ _nss_files_setaliasent (void) status = internal_setent (&stream); @@ -118,7 +118,7 @@ Index: glibc-2.19/nss/nss_files/files-alias.c __libc_lock_unlock (lock); return status; -@@ -388,7 +401,29 @@ _nss_files_getaliasent_r (struct aliasen +@@ -353,7 +366,29 @@ _nss_files_getaliasent_r (struct aliasen /* Be prepared that the set*ent function was not called before. */ if (stream == NULL) @@ -149,7 +149,7 @@ Index: glibc-2.19/nss/nss_files/files-alias.c if (status == NSS_STATUS_SUCCESS) { -@@ -398,6 +433,12 @@ _nss_files_getaliasent_r (struct aliasen +@@ -363,6 +398,12 @@ _nss_files_getaliasent_r (struct aliasen do status = get_next_alias (stream, NULL, result, buffer, buflen, errnop); while (status == NSS_STATUS_RETURN); diff --git a/powerpc-elision-enable-envvar.patch b/powerpc-elision-enable-envvar.patch deleted file mode 100644 index 6e7bbb1..0000000 --- a/powerpc-elision-enable-envvar.patch +++ /dev/null @@ -1,41 +0,0 @@ -2016-02-11 Paul E. Murphy - - * sysdeps/unix/sysv/linux/powerpc/elision-conf.c - (elision_init): Further restrict enablement based - on whether GLIBC_ELISION_ENABLE=yes is in the env. ---- - sysdeps/unix/sysv/linux/powerpc/elision-conf.c | 14 +++++++++++++- - 1 file changed, 13 insertions(+), 1 deletion(-) - -Index: glibc-2.22/sysdeps/unix/sysv/linux/powerpc/elision-conf.c -=================================================================== ---- glibc-2.22.orig/sysdeps/unix/sysv/linux/powerpc/elision-conf.c -+++ glibc-2.22/sysdeps/unix/sysv/linux/powerpc/elision-conf.c -@@ -21,6 +21,7 @@ - #include - #include - #include -+#include - - /* Reasonable initial tuning values, may be revised in the future. - This is a conservative initial value. */ -@@ -61,7 +62,18 @@ elision_init (int argc __attribute__ ((u - { - #ifdef ENABLE_LOCK_ELISION - int elision_available = (GLRO (dl_hwcap2) & PPC_FEATURE2_HAS_HTM) ? 1 : 0; -- __pthread_force_elision = __libc_enable_secure ? 0 : elision_available; -+ -+ /* Scan the environment and conditionally enable TLE. */ -+ if (elision_available != 0 && __libc_enable_secure == 0) -+ { -+ for ( ; *environ != NULL; environ++) -+ if (**environ == 'G' && -+ strcmp (*environ,"GLIBC_ELISION_ENABLE=yes") == 0) -+ { -+ __pthread_force_elision = elision_available; -+ break; -+ } -+ } - #endif - if (!__pthread_force_elision) - /* Disable elision on rwlocks. */ diff --git a/powerpc-hwcap-bits.patch b/powerpc-hwcap-bits.patch deleted file mode 100644 index 4a7cbd6..0000000 --- a/powerpc-hwcap-bits.patch +++ /dev/null @@ -1,15 +0,0 @@ -2017-11-17 Tulio Magno Quites Machado Filho - - * sysdeps/powerpc/bits/hwcap.h (PPC_FEATURE2_HTM_NO_SUSPEND): New - macro. - -Index: glibc-2.26/sysdeps/powerpc/bits/hwcap.h -=================================================================== ---- glibc-2.26.orig/sysdeps/powerpc/bits/hwcap.h -+++ glibc-2.26/sysdeps/powerpc/bits/hwcap.h -@@ -72,3 +72,5 @@ - 128-bit */ - #define PPC_FEATURE2_DARN 0x00200000 /* darn instruction. */ - #define PPC_FEATURE2_SCV 0x00100000 /* scv syscall. */ -+#define PPC_FEATURE2_HTM_NO_SUSPEND 0x00080000 /* TM without suspended -+ state. */ diff --git a/remove-nss-nis-compat.patch b/remove-nss-nis-compat.patch deleted file mode 100644 index 4a78c5c..0000000 --- a/remove-nss-nis-compat.patch +++ /dev/null @@ -1,207 +0,0 @@ -2017-08-29 Steve Ellcey - - * grp/initgroups.c: Include config.h. - (DEFAULT_CONFIG): New macro. - (internal_getgrouplist): Use DEFAULT_CONFIG. - * nscd/initgrcache.c (addinitgroupsX): Likewise. - * nss/nsswitch.c (__nss_disable_nscd): Likewise. - (DEFAULT_DEFCONFIG): New macro. - (__nss_database_lookup): Use DEFAULT_DEFCONFIG. - * nss/grp-lookup.c: Include config.h - (DEFAULT_CONFIG): Set definition based on LINK_OBSOLETE_NSL. - * nss/pwd-lookup.c (DEFAULT_CONFIG): Likewise. - * nss/spwd-lookup.c (DEFAULT_CONFIG): Likewise. - * manual/nss.texi: Update default values section. - - -Index: glibc-2.26/grp/initgroups.c -=================================================================== ---- glibc-2.26.orig/grp/initgroups.c -+++ glibc-2.26/grp/initgroups.c -@@ -26,10 +26,16 @@ - #include - #include - #include -+#include - - #include "../nscd/nscd-client.h" - #include "../nscd/nscd_proto.h" - -+#ifdef LINK_OBSOLETE_NSL -+# define DEFAULT_CONFIG "compat [NOTFOUND=return] files" -+#else -+# define DEFAULT_CONFIG "files" -+#endif - - /* Type of the lookup function. */ - typedef enum nss_status (*initgroups_dyn_function) (const char *, gid_t, -@@ -84,7 +90,7 @@ internal_getgrouplist (const char *user, - &__nss_initgroups_database) < 0) - { - if (__nss_group_database == NULL) -- no_more = __nss_database_lookup ("group", NULL, "compat files", -+ no_more = __nss_database_lookup ("group", NULL, DEFAULT_CONFIG, - &__nss_group_database); - - __nss_initgroups_database = __nss_group_database; -Index: glibc-2.26/manual/nss.texi -=================================================================== ---- glibc-2.26.orig/manual/nss.texi -+++ glibc-2.26/manual/nss.texi -@@ -318,13 +318,17 @@ The @code{passwd}, @code{group}, and @co - traditionally handled in a special way. The appropriate files in the - @file{/etc} directory are read but if an entry with a name starting - with a @code{+} character is found NIS is used. This kind of lookup --remains possible by using the special lookup service @code{compat} --and the default value for the three databases above is --@code{compat [NOTFOUND=return] files}. -+remains possible if @theglibc{} was configured with the -+@code{--enable-obsolete-nsl} option and the special lookup service -+@code{compat} is used. If @theglibc{} was configured with the -+@code{--enable-obsolete-nsl} option the default value for the three -+databases above is @code{compat [NOTFOUND=return] files}. If the -+@code{--enable-obsolete-nsl} option was not used the default value -+for the services is @code{files}. - --For all other databases the default value is --@code{nis [NOTFOUND=return] files}. This solution gives the best --chance to be correct since NIS and file based lookups are used. -+For all other databases the default value is @code{files} unless -+@theglibc{} was configured with @code{--enable-obsolete-rpc} option, in -+which case it the default value is @code{nis [NOTFOUND=return] files}. - - @cindex optimizing NSS - A second point is that the user should try to optimize the lookup -Index: glibc-2.26/nscd/initgrcache.c -=================================================================== ---- glibc-2.26.orig/nscd/initgrcache.c -+++ glibc-2.26/nscd/initgrcache.c -@@ -25,6 +25,7 @@ - #include - #include - #include -+#include - - #include "dbg_log.h" - #include "nscd.h" -@@ -34,6 +35,11 @@ - - #include "../nss/nsswitch.h" - -+#ifdef LINK_OBSOLETE_NSL -+# define DEFAULT_CONFIG "compat [NOTFOUND=return] files" -+#else -+# define DEFAULT_CONFIG "files" -+#endif - - /* Type of the lookup function. */ - typedef enum nss_status (*initgroups_dyn_function) (const char *, gid_t, -@@ -85,8 +91,7 @@ addinitgroupsX (struct database_dyn *db, - int no_more; - - if (group_database == NULL) -- no_more = __nss_database_lookup ("group", NULL, -- "compat [NOTFOUND=return] files", -+ no_more = __nss_database_lookup ("group", NULL, DEFAULT_CONFIG, - &group_database); - else - no_more = 0; -Index: glibc-2.26/nss/grp-lookup.c -=================================================================== ---- glibc-2.26.orig/nss/grp-lookup.c -+++ glibc-2.26/nss/grp-lookup.c -@@ -16,7 +16,13 @@ - License along with the GNU C Library; if not, see - . */ - -+#include -+ - #define DATABASE_NAME group --#define DEFAULT_CONFIG "compat [NOTFOUND=return] files" -+#ifdef LINK_OBSOLETE_NSL -+# define DEFAULT_CONFIG "compat [NOTFOUND=return] files" -+#else -+# define DEFAULT_CONFIG "files" -+#endif - - #include "XXX-lookup.c" -Index: glibc-2.26/nss/nsswitch.c -=================================================================== ---- glibc-2.26.orig/nss/nsswitch.c -+++ glibc-2.26/nss/nsswitch.c -@@ -40,6 +40,15 @@ - #include "nsswitch.h" - #include "../nscd/nscd_proto.h" - #include -+#include -+ -+#ifdef LINK_OBSOLETE_NSL -+# define DEFAULT_CONFIG "compat [NOTFOUND=return] files" -+# define DEFAULT_DEFCONFIG "nis [NOTFOUND=return] files" -+#else -+# define DEFAULT_CONFIG "files" -+# define DEFAULT_DEFCONFIG "files" -+#endif - - /* Prototypes for the local functions. */ - static name_database *nss_parse_file (const char *fname) internal_function; -@@ -151,8 +160,7 @@ __nss_database_lookup (const char *datab - or null to use the most common default. */ - if (*ni == NULL) - { -- *ni = nss_parse_service_list (defconfig -- ?: "nis [NOTFOUND=return] files"); -+ *ni = nss_parse_service_list (defconfig ?: DEFAULT_DEFCONFIG); - if (*ni != NULL) - { - /* Record the memory we've just allocated in defconfig_entries list, -@@ -848,8 +856,8 @@ __nss_disable_nscd (void (*cb) (size_t, - is_nscd = true; - - /* Find all the relevant modules so that the init functions are called. */ -- nss_load_all_libraries ("passwd", "compat [NOTFOUND=return] files"); -- nss_load_all_libraries ("group", "compat [NOTFOUND=return] files"); -+ nss_load_all_libraries ("passwd", DEFAULT_CONFIG); -+ nss_load_all_libraries ("group", DEFAULT_CONFIG); - nss_load_all_libraries ("hosts", "dns [!UNAVAIL=return] files"); - nss_load_all_libraries ("services", NULL); - -Index: glibc-2.26/nss/pwd-lookup.c -=================================================================== ---- glibc-2.26.orig/nss/pwd-lookup.c -+++ glibc-2.26/nss/pwd-lookup.c -@@ -16,7 +16,13 @@ - License along with the GNU C Library; if not, see - . */ - -+#include -+ - #define DATABASE_NAME passwd --#define DEFAULT_CONFIG "compat [NOTFOUND=return] files" -+#ifdef LINK_OBSOLETE_NSL -+# define DEFAULT_CONFIG "compat [NOTFOUND=return] files" -+#else -+# define DEFAULT_CONFIG "files" -+#endif - - #include "XXX-lookup.c" -Index: glibc-2.26/nss/spwd-lookup.c -=================================================================== ---- glibc-2.26.orig/nss/spwd-lookup.c -+++ glibc-2.26/nss/spwd-lookup.c -@@ -16,8 +16,14 @@ - License along with the GNU C Library; if not, see - . */ - -+#include -+ - #define DATABASE_NAME shadow - #define ALTERNATE_NAME passwd --#define DEFAULT_CONFIG "compat [NOTFOUND=return] files" -+#ifdef LINK_OBSOLETE_NSL -+# define DEFAULT_CONFIG "compat [NOTFOUND=return] files" -+#else -+# define DEFAULT_CONFIG "files" -+#endif - - #include "XXX-lookup.c" diff --git a/resolv-conf-oom.patch b/resolv-conf-oom.patch deleted file mode 100644 index 129aa7a..0000000 --- a/resolv-conf-oom.patch +++ /dev/null @@ -1,44 +0,0 @@ -2017-09-06 Florian Weimer - - [BZ #22096] - * resolv/resolv_conf.c (__resolv_conf_attach): Do not free conf in - case of failure to obtain the global conf object. - -2017-09-06 Florian Weimer - - [BZ #22095] - * resolv/res_init.c (res_vinit_1): Avoid memory leak in case of - dynarray allocation failure. - -Index: glibc-2.26/resolv/res_init.c -=================================================================== ---- glibc-2.26.orig/resolv/res_init.c -+++ glibc-2.26/resolv/res_init.c -@@ -446,6 +446,11 @@ res_vinit_1 (FILE *fp, struct resolv_con - (&parser->nameserver_list); - if (p != NULL) - *p = sa; -+ else -+ { -+ free (sa); -+ return false; -+ } - } - continue; - } -Index: glibc-2.26/resolv/resolv_conf.c -=================================================================== ---- glibc-2.26.orig/resolv/resolv_conf.c -+++ glibc-2.26/resolv/resolv_conf.c -@@ -600,10 +600,7 @@ __resolv_conf_attach (struct __res_state - - struct resolv_conf_global *global_copy = get_locked_global (); - if (global_copy == NULL) -- { -- free (conf); -- return false; -- } -+ return false; - - /* Try to find an unused index in the array. */ - size_t index; diff --git a/resolv-context-leak.patch b/resolv-context-leak.patch deleted file mode 100644 index 352e7c8..0000000 --- a/resolv-context-leak.patch +++ /dev/null @@ -1,53 +0,0 @@ -2017-08-09 Florian Weimer - - [BZ #21932] - * nss/getXXbyYY_r.c (REENTRANT_NAME): Call __resolv_context_put - before early return. - -2017-08-03 Florian Weimer - - [BZ #21885] - * sysdeps/posix/getaddrinfo.c (gethosts): Release resolver context - on memory allocation failure. - -Index: glibc-2.26/nss/getXXbyYY_r.c -=================================================================== ---- glibc-2.26.orig/nss/getXXbyYY_r.c -+++ glibc-2.26/nss/getXXbyYY_r.c -@@ -234,6 +234,9 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, L - H_ERRNO_VAR_P)) - { - case -1: -+# ifdef NEED__RES -+ __resolv_context_put (res_ctx); -+# endif - return errno; - case 1: - #ifdef NEED_H_ERRNO -@@ -253,7 +256,12 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, L - nscd_status = NSCD_NAME (ADD_VARIABLES, resbuf, buffer, buflen, result - H_ERRNO_VAR); - if (nscd_status >= 0) -- return nscd_status; -+ { -+# ifdef NEED__RES -+ __resolv_context_put (res_ctx); -+# endif -+ return nscd_status; -+ } - } - #endif - -Index: glibc-2.26/sysdeps/posix/getaddrinfo.c -=================================================================== ---- glibc-2.26.orig/sysdeps/posix/getaddrinfo.c -+++ glibc-2.26/sysdeps/posix/getaddrinfo.c -@@ -255,6 +255,8 @@ convert_hostent_to_gaih_addrtuple (const - break; \ - if (!scratch_buffer_grow (tmpbuf)) \ - { \ -+ __resolv_context_enable_inet6 (res_ctx, res_enable_inet6); \ -+ __resolv_context_put (res_ctx); \ - result = -EAI_MEMORY; \ - goto free_and_return; \ - } \ diff --git a/s390-elision-enable-envvar.patch b/s390-elision-enable-envvar.patch deleted file mode 100644 index e83b280..0000000 --- a/s390-elision-enable-envvar.patch +++ /dev/null @@ -1,31 +0,0 @@ -Index: glibc-2.25/sysdeps/unix/sysv/linux/s390/elision-conf.c -=================================================================== ---- glibc-2.25.orig/sysdeps/unix/sysv/linux/s390/elision-conf.c -+++ glibc-2.25/sysdeps/unix/sysv/linux/s390/elision-conf.c -@@ -21,6 +21,7 @@ - #include - #include - #include -+#include - - /* Reasonable initial tuning values, may be revised in the future. - This is a conservative initial value. */ -@@ -64,7 +65,17 @@ elision_init (int argc __attribute__ ((u - When false elision is never attempted. */ - int elision_available = (GLRO (dl_hwcap) & HWCAP_S390_TE) ? 1 : 0; - -- __pthread_force_elision = __libc_enable_secure ? 0 : elision_available; -+ /* Scan the environment and conditionally enable TLE. */ -+ if (elision_available != 0 && __libc_enable_secure == 0) -+ { -+ for ( ; *environ != NULL; environ++) -+ if (**environ == 'G' -+ && strcmp (*environ, "GLIBC_ELISION_ENABLE=yes") == 0) -+ { -+ __pthread_force_elision = elision_available; -+ break; -+ } -+ } - } - - #ifdef SHARED diff --git a/spawni-assert.patch b/spawni-assert.patch deleted file mode 100644 index 429c5cf..0000000 --- a/spawni-assert.patch +++ /dev/null @@ -1,71 +0,0 @@ -2017-10-23 Adhemerval Zanella - - * sysdeps/unix/sysv/linux/spawni.c (__spawnix): Use 0 instead of - WNOHANG in waitpid call. - -2017-10-20 Adhemerval Zanella - - [BZ #22273] - * sysdeps/unix/sysv/linux/spawni.c (__spawnix): Handle the case where - the auxiliary process is terminated by a signal before calling _exit - or execve. - -Index: glibc-2.26/sysdeps/unix/sysv/linux/spawni.c -=================================================================== ---- glibc-2.26.orig/sysdeps/unix/sysv/linux/spawni.c -+++ glibc-2.26/sysdeps/unix/sysv/linux/spawni.c -@@ -17,7 +17,6 @@ - . */ - - #include --#include - #include - #include - #include -@@ -268,7 +267,6 @@ __spawni_child (void *arguments) - __sigprocmask (SIG_SETMASK, (attr->__flags & POSIX_SPAWN_SETSIGMASK) - ? &attr->__ss : &args->oldmask, 0); - -- args->err = 0; - args->exec (args->file, args->argv, args->envp); - - /* This is compatibility function required to enable posix_spawn run -@@ -339,7 +337,7 @@ __spawnix (pid_t * pid, const char *file - - /* Child must set args.err to something non-negative - we rely on - the parent and child sharing VM. */ -- args.err = -1; -+ args.err = 0; - args.file = file; - args.exec = exec; - args.fa = file_actions; -@@ -362,12 +360,26 @@ __spawnix (pid_t * pid, const char *file - new_pid = CLONE (__spawni_child, STACK (stack, stack_size), stack_size, - CLONE_VM | CLONE_VFORK | SIGCHLD, &args); - -+ /* It needs to collect the case where the auxiliary process was created -+ but failed to execute the file (due either any preparation step or -+ for execve itself). */ - if (new_pid > 0) - { -+ /* Also, it handles the unlikely case where the auxiliary process was -+ terminated before calling execve as if it was successfully. The -+ args.err is set to 0 as default and changed to a positive value -+ only in case of failure, so in case of premature termination -+ due a signal args.err will remain zeroed and it will be up to -+ caller to actually collect it. */ - ec = args.err; -- assert (ec >= 0); -- if (ec != 0) -- __waitpid (new_pid, NULL, 0); -+ if (ec > 0) -+ /* There still an unlikely case where the child is cancelled after -+ setting args.err, due to a positive error value. Also there is -+ possible pid reuse race (where the kernel allocated the same pid -+ to an unrelated process). Unfortunately due synchronization -+ issues where the kernel might not have the process collected -+ the waitpid below can not use WNOHANG. */ -+ __waitpid (new_pid, NULL, 0); - } - else - ec = -new_pid; diff --git a/sysconf-uio-maxiov.patch b/sysconf-uio-maxiov.patch deleted file mode 100644 index 9359e06..0000000 --- a/sysconf-uio-maxiov.patch +++ /dev/null @@ -1,125 +0,0 @@ -2017-10-20 Florian Weimer - - [BZ #22321] - sysconf: Fix missing definition of UIO_MAXIOV on Linux. - * sysdeps/posix/sysconf.c: Include . - * sysdeps/unix/sysv/linux/Makefile (tests): Add tst-sysconf-iov_max. - (tst-sysconf-iov_max): Link with tst-sysconf-iov_max-uapi.o. - * sysdeps/unix/sysv/linux/tst-sysconf-iov_max.c: New file. - * sysdeps/unix/sysv/linux/tst-sysconf-iov_max-uapi.c: Likewise. - -Index: glibc-2.26/sysdeps/posix/sysconf.c -=================================================================== ---- glibc-2.26.orig/sysdeps/posix/sysconf.c -+++ glibc-2.26/sysdeps/posix/sysconf.c -@@ -29,6 +29,7 @@ - #include - #include - #include -+#include - #include - - #define NEED_SPEC_ARRAY 0 -Index: glibc-2.26/sysdeps/unix/sysv/linux/Makefile -=================================================================== ---- glibc-2.26.orig/sysdeps/unix/sysv/linux/Makefile -+++ glibc-2.26/sysdeps/unix/sysv/linux/Makefile -@@ -50,7 +50,7 @@ sysdep_headers += sys/mount.h sys/acct.h - bits/siginfo-arch.h bits/siginfo-consts-arch.h - - tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \ -- tst-quota tst-sync_file_range test-errno-linux -+ tst-quota tst-sync_file_range test-errno-linux tst-sysconf-iov_max - - # Generate the list of SYS_* macros for the system calls (__NR_* macros). - -@@ -120,7 +120,11 @@ ifndef no_deps - -include $(objpfx)bits/syscall.d - endif - generated += bits/syscall.h bits/syscall.d --endif -+ -+# Separate object file for access to the constant from the UAPI header. -+$(objpfx)tst-sysconf-iov_max: $(objpfx)tst-sysconf-iov_max-uapi.o -+ -+endif # $(subdir) == misc - - ifeq ($(subdir),time) - sysdep_headers += sys/timex.h bits/timex.h -Index: glibc-2.26/sysdeps/unix/sysv/linux/tst-sysconf-iov_max-uapi.c -=================================================================== ---- /dev/null -+++ glibc-2.26/sysdeps/unix/sysv/linux/tst-sysconf-iov_max-uapi.c -@@ -0,0 +1,27 @@ -+/* Check IOV_MAX definition: Helper function to capture UAPI header value. -+ 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 -+ . */ -+ -+/* Use a separate function to avoid header compatibility issues. */ -+ -+#include -+ -+long -+uio_maxiov_value (void) -+{ -+ return UIO_MAXIOV; -+} -Index: glibc-2.26/sysdeps/unix/sysv/linux/tst-sysconf-iov_max.c -=================================================================== ---- /dev/null -+++ glibc-2.26/sysdeps/unix/sysv/linux/tst-sysconf-iov_max.c -@@ -0,0 +1,40 @@ -+/* Check IOV_MAX definition for consistency (bug 22321). -+ 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 -+ . */ -+ -+/* Defined in tst-sysconf-iov_max-uapi.c. */ -+long uio_maxiov_value (void); -+ -+ -+#include -+#include -+#include -+#include -+ -+static int -+do_test (void) -+{ -+ TEST_VERIFY (_XOPEN_IOV_MAX == 16); /* Value required by POSIX. */ -+ TEST_VERIFY (uio_maxiov_value () >= _XOPEN_IOV_MAX); -+ TEST_VERIFY (IOV_MAX == uio_maxiov_value ()); -+ TEST_VERIFY (UIO_MAXIOV == uio_maxiov_value ()); -+ TEST_VERIFY (sysconf (_SC_UIO_MAXIOV) == uio_maxiov_value ()); -+ TEST_VERIFY (sysconf (_SC_IOV_MAX) == uio_maxiov_value ()); -+ return 0; -+} -+ -+#include diff --git a/tst-tlsopt-powerpc.patch b/tst-tlsopt-powerpc.patch deleted file mode 100644 index e722d41..0000000 --- a/tst-tlsopt-powerpc.patch +++ /dev/null @@ -1,171 +0,0 @@ -2017-08-03 Alan Modra - - * sysdeps/powerpc/mod-tlsopt-powerpc.c: Extract from - tst-tlsopt-powerpc.c with function name change and no test harness. - * sysdeps/powerpc/tst-tlsopt-powerpc.c: Remove body of test. - Call tls_get_addr_opt_test. - * sysdeps/powerpc/Makefile (LDFLAGS-tst-tlsopt-powerpc): Don't define. - (modules-names): Add mod-tlsopt-powerpc. - (mod-tlsopt-powerpc.so-no-z-defs): Define. - (tst-tlsopt-powerpc): Depend on .so. - * sysdeps/powerpc/powerpc64/tls-macros.h (__TLS_GET_ADDR): Don't - define. Expand use in TLS_GD and TLS_LD. - -Index: glibc-2.26/sysdeps/powerpc/Makefile -=================================================================== ---- glibc-2.26.orig/sysdeps/powerpc/Makefile -+++ glibc-2.26/sysdeps/powerpc/Makefile -@@ -8,9 +8,11 @@ sysdep-dl-routines += dl-machine hwcapin - sysdep_routines += dl-machine hwcapinfo - # extra shared linker files to link only into dl-allobjs.so - sysdep-rtld-routines += dl-machine hwcapinfo --# Don't optimize GD tls sequence to LE. --LDFLAGS-tst-tlsopt-powerpc += -Wl,--no-tls-optimize -+ -+modules-names += mod-tlsopt-powerpc -+mod-tlsopt-powerpc.so-no-z-defs = yes - tests += tst-tlsopt-powerpc -+$(objpfx)tst-tlsopt-powerpc: $(objpfx)mod-tlsopt-powerpc.so - - ifneq (no,$(multi-arch)) - tests-static += tst-tlsifunc-static -Index: glibc-2.26/sysdeps/powerpc/mod-tlsopt-powerpc.c -=================================================================== ---- /dev/null -+++ glibc-2.26/sysdeps/powerpc/mod-tlsopt-powerpc.c -@@ -0,0 +1,49 @@ -+/* shared library to test for __tls_get_addr optimization. */ -+#include -+ -+#include "../../elf/tls-macros.h" -+#include "dl-tls.h" -+ -+/* common 'int' variable in TLS. */ -+COMMON_INT_DEF(foo); -+ -+ -+int -+tls_get_addr_opt_test (void) -+{ -+ int result = 0; -+ -+ /* Get variable using general dynamic model. */ -+ int *ap = TLS_GD (foo); -+ if (*ap != 0) -+ { -+ printf ("foo = %d\n", *ap); -+ result = 1; -+ } -+ -+ tls_index *tls_arg; -+#ifdef __powerpc64__ -+ register unsigned long thread_pointer __asm__ ("r13"); -+ asm ("addi %0,2,foo@got@tlsgd" : "=r" (tls_arg)); -+#else -+ register unsigned long thread_pointer __asm__ ("r2"); -+ asm ("bcl 20,31,1f\n1:\t" -+ "mflr %0\n\t" -+ "addis %0,%0,_GLOBAL_OFFSET_TABLE_-1b@ha\n\t" -+ "addi %0,%0,_GLOBAL_OFFSET_TABLE_-1b@l\n\t" -+ "addi %0,%0,foo@got@tlsgd" : "=b" (tls_arg)); -+#endif -+ -+ if (tls_arg->ti_module != 0) -+ { -+ printf ("tls_index not optimized, binutils too old?\n"); -+ result = 1; -+ } -+ else if (tls_arg->ti_offset + thread_pointer != (unsigned long) ap) -+ { -+ printf ("tls_index->ti_offset wrong value\n"); -+ result = 1; -+ } -+ -+ return result; -+} -Index: glibc-2.26/sysdeps/powerpc/powerpc64/tls-macros.h -=================================================================== ---- glibc-2.26.orig/sysdeps/powerpc/powerpc64/tls-macros.h -+++ glibc-2.26/sysdeps/powerpc/powerpc64/tls-macros.h -@@ -18,13 +18,11 @@ - __result; \ - }) - --#define __TLS_GET_ADDR "__tls_get_addr" -- - /* PowerPC64 Local Dynamic TLS access. */ - #define TLS_LD(x) \ - ({ int * __result; \ - asm ("addi 3,2," #x "@got@tlsld\n\t" \ -- "bl " __TLS_GET_ADDR "\n\t" \ -+ "bl __tls_get_addr\n\t" \ - "nop \n\t" \ - "addis %0,3," #x "@dtprel@ha\n\t" \ - "addi %0,%0," #x "@dtprel@l" \ -@@ -36,7 +34,7 @@ - #define TLS_GD(x) \ - ({ register int *__result __asm__ ("r3"); \ - asm ("addi 3,2," #x "@got@tlsgd\n\t" \ -- "bl " __TLS_GET_ADDR "\n\t" \ -+ "bl __tls_get_addr\n\t" \ - "nop " \ - : "=r" (__result) : \ - : __TLS_CALL_CLOBBERS); \ -Index: glibc-2.26/sysdeps/powerpc/tst-tlsopt-powerpc.c -=================================================================== ---- glibc-2.26.orig/sysdeps/powerpc/tst-tlsopt-powerpc.c -+++ glibc-2.26/sysdeps/powerpc/tst-tlsopt-powerpc.c -@@ -1,51 +1,11 @@ - /* glibc test for __tls_get_addr optimization. */ --#include -- --#include "../../elf/tls-macros.h" --#include "dl-tls.h" -- --/* common 'int' variable in TLS. */ --COMMON_INT_DEF(foo); -- - - static int - do_test (void) - { -- int result = 0; -- -- /* Get variable using general dynamic model. */ -- int *ap = TLS_GD (foo); -- if (*ap != 0) -- { -- printf ("foo = %d\n", *ap); -- result = 1; -- } -- -- tls_index *tls_arg; --#ifdef __powerpc64__ -- register unsigned long thread_pointer __asm__ ("r13"); -- asm ("addi %0,2,foo@got@tlsgd" : "=r" (tls_arg)); --#else -- register unsigned long thread_pointer __asm__ ("r2"); -- asm ("bcl 20,31,1f\n1:\t" -- "mflr %0\n\t" -- "addis %0,%0,_GLOBAL_OFFSET_TABLE_-1b@ha\n\t" -- "addi %0,%0,_GLOBAL_OFFSET_TABLE_-1b@l\n\t" -- "addi %0,%0,foo@got@tlsgd" : "=b" (tls_arg)); --#endif -- -- if (tls_arg->ti_module != 0) -- { -- printf ("tls_index not optimized, binutils too old?\n"); -- result = 1; -- } -- else if (tls_arg->ti_offset + thread_pointer != (unsigned long) ap) -- { -- printf ("tls_index->ti_offset wrong value\n"); -- result = 1; -- } -+ extern int tls_get_addr_opt_test (void); - -- return result; -+ return tls_get_addr_opt_test (); - } - - #include diff --git a/x86-64-dl-platform.patch b/x86-64-dl-platform.patch deleted file mode 100644 index 70ba272..0000000 --- a/x86-64-dl-platform.patch +++ /dev/null @@ -1,196 +0,0 @@ -2017-10-26 Valery Reznic - H.J. Lu - - [BZ #22299] - * sysdeps/x86/cpu-features.c (init_cpu_features): Don't set - GLRO(dl_platform) to NULL. - * sysdeps/x86_64/Makefile (tests): Add tst-platform-1. - (modules-names): Add tst-platformmod-1 and - x86_64/tst-platformmod-2. - (CFLAGS-tst-platform-1.c): New. - (CFLAGS-tst-platformmod-1.c): Likewise. - (CFLAGS-tst-platformmod-2.c): Likewise. - (LDFLAGS-tst-platformmod-2.so): Likewise. - ($(objpfx)tst-platform-1): Likewise. - ($(objpfx)tst-platform-1.out): Likewise. - (tst-platform-1-ENV): Likewise. - ($(objpfx)x86_64/tst-platformmod-2.os): Likewise. - * sysdeps/x86_64/tst-platform-1.c: New file. - * sysdeps/x86_64/tst-platformmod-1.c: Likewise. - * sysdeps/x86_64/tst-platformmod-2.c: Likewise. - -Index: glibc-2.26/sysdeps/x86/cpu-features.c -=================================================================== ---- glibc-2.26.orig/sysdeps/x86/cpu-features.c -+++ glibc-2.26/sysdeps/x86/cpu-features.c -@@ -389,7 +389,6 @@ no_cpuid: - #endif - - /* Reuse dl_platform, dl_hwcap and dl_hwcap_mask for x86. */ -- GLRO(dl_platform) = NULL; - #if !HAVE_TUNABLES && defined SHARED - /* The glibc.tune.hwcap_mask tunable is initialized already, so no need to do - this. */ -@@ -400,13 +399,15 @@ no_cpuid: - GLRO(dl_hwcap) = HWCAP_X86_64; - if (cpu_features->kind == arch_kind_intel) - { -+ const char *platform = NULL; -+ - if (CPU_FEATURES_ARCH_P (cpu_features, AVX512F_Usable) - && CPU_FEATURES_CPU_P (cpu_features, AVX512CD)) - { - if (CPU_FEATURES_CPU_P (cpu_features, AVX512ER)) - { - if (CPU_FEATURES_CPU_P (cpu_features, AVX512PF)) -- GLRO(dl_platform) = "xeon_phi"; -+ platform = "xeon_phi"; - } - else - { -@@ -417,7 +418,7 @@ no_cpuid: - } - } - -- if (GLRO(dl_platform) == NULL -+ if (platform == NULL - && CPU_FEATURES_ARCH_P (cpu_features, AVX2_Usable) - && CPU_FEATURES_ARCH_P (cpu_features, FMA_Usable) - && CPU_FEATURES_CPU_P (cpu_features, BMI1) -@@ -425,7 +426,10 @@ no_cpuid: - && CPU_FEATURES_CPU_P (cpu_features, LZCNT) - && CPU_FEATURES_CPU_P (cpu_features, MOVBE) - && CPU_FEATURES_CPU_P (cpu_features, POPCNT)) -- GLRO(dl_platform) = "haswell"; -+ platform = "haswell"; -+ -+ if (platform != NULL) -+ GLRO(dl_platform) = platform; - } - #else - GLRO(dl_hwcap) = 0; -Index: glibc-2.26/sysdeps/x86_64/Makefile -=================================================================== ---- glibc-2.26.orig/sysdeps/x86_64/Makefile -+++ glibc-2.26/sysdeps/x86_64/Makefile -@@ -62,6 +62,21 @@ endif - - $(objpfx)tst-x86_64-1: $(objpfx)x86_64/tst-x86_64mod-1.so - -+ifneq (no,$(have-tunables)) -+tests += tst-platform-1 -+modules-names += tst-platformmod-1 x86_64/tst-platformmod-2 -+CFLAGS-tst-platform-1.c = -mno-avx -+CFLAGS-tst-platformmod-1.c = -mno-avx -+CFLAGS-tst-platformmod-2.c = -mno-avx -+LDFLAGS-tst-platformmod-2.so = -Wl,-soname,tst-platformmod-2.so -+$(objpfx)tst-platform-1: $(objpfx)tst-platformmod-1.so -+$(objpfx)tst-platform-1.out: $(objpfx)x86_64/tst-platformmod-2.so -+# Turn off AVX512F_Usable and AVX2_Usable so that GLRO(dl_platform) is -+# always set to x86_64. -+tst-platform-1-ENV = LD_PRELOAD=$(objpfx)\$$PLATFORM/tst-platformmod-2.so \ -+ GLIBC_TUNABLES=glibc.tune.hwcaps=-AVX512F_Usable,-AVX2_Usable -+endif -+ - tests += tst-audit3 tst-audit4 tst-audit5 tst-audit6 tst-audit7 \ - tst-audit10 tst-sse tst-avx tst-avx512 - test-extras += tst-audit4-aux tst-audit10-aux \ -@@ -143,3 +158,8 @@ do-tests-clean common-mostlyclean: tst-x - .PHONY: tst-x86_64-1-clean - tst-x86_64-1-clean: - -rm -rf $(objpfx)x86_64 -+ -+$(objpfx)x86_64/tst-platformmod-2.os: $(objpfx)tst-platformmod-2.os -+ $(make-target-directory) -+ rm -f $@ -+ ln $< $@ -Index: glibc-2.26/sysdeps/x86_64/tst-platform-1.c -=================================================================== ---- /dev/null -+++ glibc-2.26/sysdeps/x86_64/tst-platform-1.c -@@ -0,0 +1,29 @@ -+/* Test PRELOAD with $PLATFORM. -+ 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 -+ -+extern int preload (void); -+ -+static int -+do_test (void) -+{ -+ return preload () == 0x1234 ? EXIT_SUCCESS : EXIT_FAILURE; -+} -+ -+#include -Index: glibc-2.26/sysdeps/x86_64/tst-platformmod-1.c -=================================================================== ---- /dev/null -+++ glibc-2.26/sysdeps/x86_64/tst-platformmod-1.c -@@ -0,0 +1,23 @@ -+/* Test PRELOAD with $PLATFORM. -+ 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 -+ . */ -+ -+int -+preload (void) -+{ -+ return 0; -+} -Index: glibc-2.26/sysdeps/x86_64/tst-platformmod-2.c -=================================================================== ---- /dev/null -+++ glibc-2.26/sysdeps/x86_64/tst-platformmod-2.c -@@ -0,0 +1,23 @@ -+/* Test PRELOAD with $PLATFORM. -+ 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 -+ . */ -+ -+int -+preload (void) -+{ -+ return 0x1234; -+}