diff --git a/SOURCES/glibc-armhfp-ELF_MACHINE_NO_REL-undefined.patch b/SOURCES/glibc-armhfp-ELF_MACHINE_NO_REL-undefined.patch deleted file mode 100644 index 78d7c4b..0000000 --- a/SOURCES/glibc-armhfp-ELF_MACHINE_NO_REL-undefined.patch +++ /dev/null @@ -1,36 +0,0 @@ -From patchwork Thu Jul 3 13:26:40 2014 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -Subject: ARM: Define ELF_MACHINE_NO_REL -X-Patchwork-Submitter: Will Newton <will.newton@linaro.org> -X-Patchwork-Id: 366862 -Message-Id: <1404394000-13429-1-git-send-email-will.newton@linaro.org> -To: libc-alpha@sourceware.org -Date: Thu, 3 Jul 2014 14:26:40 +0100 -From: Will Newton <will.newton@linaro.org> -List-Id: <libc-alpha.sourceware.org> - -Fix a -Wundef warning on ARM. - -ChangeLog: - -2014-07-03 Will Newton <will.newton@linaro.org> - - * sysdeps/arm/dl-machine.h (ELF_MACHINE_NO_REL): Define. ---- - sysdeps/arm/dl-machine.h | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/sysdeps/arm/dl-machine.h b/sysdeps/arm/dl-machine.h -index c5ffc93..d6b0c52 100644 ---- a/sysdeps/arm/dl-machine.h -+++ b/sysdeps/arm/dl-machine.h -@@ -296,6 +296,7 @@ elf_machine_plt_value (struct link_map *map, const Elf32_Rel *reloc, - /* ARM never uses Elf32_Rela relocations for the dynamic linker. - Prelinked libraries may use Elf32_Rela though. */ - #define ELF_MACHINE_NO_RELA defined RTLD_BOOTSTRAP -+#define ELF_MACHINE_NO_REL 0 - - /* Names of the architecture-specific auditing callback functions. */ - #define ARCH_LA_PLTENTER arm_gnu_pltenter diff --git a/SOURCES/glibc-rh1039304-1.patch b/SOURCES/glibc-rh1039304-1.patch new file mode 100644 index 0000000..f2bbe6e --- /dev/null +++ b/SOURCES/glibc-rh1039304-1.patch @@ -0,0 +1,185 @@ +commit 5c1a69238fcb87ff7f916a5ce7960b2864afb3a1 +Author: Florian Weimer <fweimer@redhat.com> +Date: Sat Nov 11 11:23:40 2017 +0100 + + resolv: Add tst-res_hnok + +diff --git a/resolv/Makefile b/resolv/Makefile +index 988871086a70b291..b1fd2e2db8736f9b 100644 +--- a/resolv/Makefile ++++ b/resolv/Makefile +@@ -50,6 +50,7 @@ tests += \ + tst-ns_name \ + tst-ns_name_compress \ + tst-res_hconf_reorder \ ++ tst-res_hnok \ + tst-res_use_inet6 \ + tst-resolv-basic \ + tst-resolv-edns \ +@@ -182,6 +183,7 @@ $(objpfx)tst-resolv-canonname: \ + $(objpfx)tst-ns_name: $(objpfx)libresolv.so + $(objpfx)tst-ns_name.out: tst-ns_name.data + $(objpfx)tst-ns_name_compress: $(objpfx)libresolv.so ++$(objpfx)tst-res_hnok: $(objpfx)libresolv.so + + + # This test case uses the deprecated RES_USE_INET6 resolver option. +diff --git a/resolv/tst-res_hnok.c b/resolv/tst-res_hnok.c +new file mode 100644 +index 0000000000000000..9c923038218e965c +--- /dev/null ++++ b/resolv/tst-res_hnok.c +@@ -0,0 +1,153 @@ ++/* Tests for res_hnok and related functions. ++ 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 ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <array_length.h> ++#include <resolv.h> ++#include <string.h> ++#include <support/check.h> ++#include <support/test-driver.h> ++ ++/* Bits which indicate which functions are supposed to report ++ success. */ ++enum ++ { ++ hnok = 1, ++ dnok = 2, ++ mailok = 4, ++ ownok = 8, ++ allnomailok = hnok | dnok | ownok, ++ allok = hnok | dnok | mailok | ownok ++ }; ++ ++/* A string of 60 characters. */ ++#define STRING60 "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" ++ ++/* A string of 63 characters (maximum label length). */ ++#define STRING63 STRING60 "zzz" ++ ++/* Combines a test name with the expected results. */ ++struct test_case ++{ ++ const char *dn; ++ unsigned int result; /* Combination of the *ok flags. */ ++}; ++ ++static const struct test_case tests[] = ++ { ++ { "", allok }, ++ { ".", allok }, ++ { "www", allnomailok }, ++ { "example", allnomailok }, ++ { "example.com", allok }, ++ { "www.example.com", allok }, ++ { "www.example.com.", allok }, ++ { "*.example.com", dnok | mailok | ownok }, ++ { "-v", dnok }, ++ { "-v.example.com", mailok | dnok }, ++ { "**.example.com", dnok | mailok }, ++ { STRING63, allnomailok }, ++ { STRING63 ".example.com", allok }, ++ { STRING63 "." STRING63 "." STRING63 "." STRING60 "z", allok }, ++ { "hostmaster@mail.example.com", dnok | mailok }, ++ { "with whitespace", 0 }, ++ { "with\twhitespace", 0 }, ++ { "with\nwhitespace", 0 }, ++ { "with.whitespace ", 0 }, ++ { "with.whitespace\t", 0 }, ++ { "with.whitespace\n", 0 }, ++ { "with\\ whitespace", 0 }, ++ { "with\\\twhitespace", 0 }, ++ { "with\\\nwhitespace", 0 }, ++ { "with.whitespace\\ ", 0 }, ++ { "with.whitespace\\\t", 0 }, ++ { "with.whitespace\\\n", 0 }, ++ }; ++ ++/* Run test case *TEST with FUNC (named FUNCNAME) and report an error ++ if the result does not match the result flag at BIT. */ ++static void ++one_test (const struct test_case *test, const char *funcname, ++ int (*func) (const char *), unsigned int bit) ++{ ++ int expected = (test->result & bit) != 0; ++ int actual = func (test->dn); ++ if (actual != expected) ++ { ++ support_record_failure (); ++ printf ("error: %s (\"%s\"): expected=%d, actual=%d\n", ++ funcname, test->dn, expected, actual); ++ } ++} ++ ++/* Run 255 tests using all the bytes from 1 to 255, surround the byte ++ with the strings PREFIX and SUFFIX, and check that FUNC (named ++ FUNCNAME) accepts only those bytes listed in ACCEPTED. */ ++static void ++one_char (const char *prefix, const char *accepted, const char *suffix, ++ const char *funcname, int (*func) (const char *)) ++{ ++ for (int ch = 1; ch <= 255; ++ch) ++ { ++ char dn[1024]; ++ snprintf (dn, sizeof (dn), "%s%c%s", prefix, ch, suffix); ++ int expected = strchr (accepted, ch) != NULL; ++ int actual = func (dn); ++ if (actual != expected) ++ { ++ support_record_failure (); ++ printf ("error: %s (\"%s\"): expected=%d, actual=%d\n", ++ funcname, dn, expected, actual); ++ } ++ } ++} ++ ++static int ++do_test (void) ++{ ++ for (const struct test_case *test = tests; test < array_end (tests); ++test) ++ { ++ if (test_verbose) ++ printf ("info: testing domain name [[[%s]]] (0x%x)\n", ++ test->dn, test->result); ++ one_test (test, "res_hnok", res_hnok, hnok); ++ one_test (test, "res_dnok", res_dnok, dnok); ++ one_test (test, "res_mailok", res_mailok, mailok); ++ one_test (test, "res_ownok", res_ownok, ownok); ++ } ++ ++ one_char ++ ("", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.", ++ "", "res_hnok", res_hnok); ++ one_char ++ ("middle", ++ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.-_", ++ "suffix", "res_hnok", res_hnok); ++ one_char ++ ("middle", ++ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.-_" ++ "!\"#$%&'()*+,/:;<=>?@[\\]^`{|}~", ++ "suffix.example", "res_mailok", res_mailok); ++ one_char ++ ("mailbox.middle", ++ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.-_", ++ "suffix.example", "res_mailok", res_mailok); ++ ++ return 0; ++} ++ ++#include <support/test-driver.c> diff --git a/SOURCES/glibc-rh1039304-2.patch b/SOURCES/glibc-rh1039304-2.patch new file mode 100644 index 0000000..7bea4a3 --- /dev/null +++ b/SOURCES/glibc-rh1039304-2.patch @@ -0,0 +1,235 @@ +commit e2a9fca8101443076235a8dbcfceaa2d96bf4801 +Author: Florian Weimer <fweimer@redhat.com> +Date: Sat Nov 11 11:33:32 2017 +0100 + + resolv: Add tst-ns_name_pton + +diff --git a/resolv/Makefile b/resolv/Makefile +index b1fd2e2db8736f9b..0130a09db2d69451 100644 +--- a/resolv/Makefile ++++ b/resolv/Makefile +@@ -49,6 +49,7 @@ tests += \ + tst-bug18665-tcp \ + tst-ns_name \ + tst-ns_name_compress \ ++ tst-ns_name_pton \ + tst-res_hconf_reorder \ + tst-res_hnok \ + tst-res_use_inet6 \ +@@ -183,6 +184,7 @@ $(objpfx)tst-resolv-canonname: \ + $(objpfx)tst-ns_name: $(objpfx)libresolv.so + $(objpfx)tst-ns_name.out: tst-ns_name.data + $(objpfx)tst-ns_name_compress: $(objpfx)libresolv.so ++$(objpfx)tst-ns_name_pton: $(objpfx)libresolv.so + $(objpfx)tst-res_hnok: $(objpfx)libresolv.so + + +diff --git a/resolv/tst-ns_name_pton.c b/resolv/tst-ns_name_pton.c +new file mode 100644 +index 0000000000000000..879d97c9d3816210 +--- /dev/null ++++ b/resolv/tst-ns_name_pton.c +@@ -0,0 +1,203 @@ ++/* Tests for ns_name_pton. ++ 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 ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <arpa/nameser.h> ++#include <array_length.h> ++#include <stdbool.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <support/check.h> ++#include <support/support.h> ++#include <support/test-driver.h> ++ ++/* Bits which indicate which functions are supposed to report ++ success. */ ++enum ++ { ++ hnok = 1, ++ dnok = 2, ++ mailok = 4, ++ ownok = 8, ++ allnomailok = hnok | dnok | ownok, ++ allok = hnok | dnok | mailok | ownok ++ }; ++ ++/* A string of 60 characters. */ ++#define STRING60 "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" ++ ++/* A string of 63 characters (maximum label length). */ ++#define STRING63 STRING60 "zzz" ++ ++/* A string of 60 bytes (non-ASCII). */ ++#define STRING60OCT \ ++ "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ ++ "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ ++ "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ ++ "\377\377\377\377\377\377\377\377\377" ++ ++/* A string of 63 bytes (non-ASCII). */ ++#define STRING63OCT STRING60OCT "\377\377\377" ++ ++/* A string of 60 bytes (non-ASCII, quoted decimal). */ ++#define STRING60DEC \ ++ "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \ ++ "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \ ++ "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \ ++ "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \ ++ "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \ ++ "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" ++ ++/* A string of 63 bytes (non-ASCII, quoted decimal). */ ++#define STRING63DEC STRING60DEC "\\255\\255\\255" ++ ++/* Combines a test name with the expected results. */ ++struct test_case ++{ ++ const char *dn; ++ const char *back; /* Expected test result converted using ns_name_ntop. */ ++ bool fully_qualified; /* True if the domain name has a trailing dot. */ ++}; ++ ++static const struct test_case tests[] = ++ { ++ { "", ".", false }, ++ { ".", ".", true }, ++ { "..", NULL, }, ++ { "www", "www", false }, ++ { "www.", "www", true }, ++ { "www\\.", "www\\.", false }, ++ { ".www", NULL, }, ++ { ".www\\.", NULL, }, ++ { "example.com", "example.com", false }, ++ { "example.com.", "example.com", true }, ++ { ".example.com", NULL, }, ++ { ".example.com.", NULL, }, ++ { "example\\.com", "example\\.com", false }, ++ { "example\\.com.", "example\\.com", true }, ++ { "example..", NULL, }, ++ { "example..com", NULL, }, ++ { "example..com", NULL, }, ++ { "\\0", NULL, }, ++ { "\\00", NULL, }, ++ { "\\000", "\\000", false }, ++ { "\\1", NULL, }, ++ { "\\01", NULL, }, ++ { "\\001", "\\001", false }, ++ { "\\1x", NULL, }, ++ { "\\01x", NULL, }, ++ { "\\001x", "\\001x", false }, ++ { "\\256", NULL, }, ++ { "\\0641", "\\@1", false }, ++ { "\\0011", "\\0011", false }, ++ { STRING63, STRING63, false }, ++ { STRING63 ".", STRING63, true }, ++ { STRING63 "z", NULL, }, ++ { STRING63 "\\.", NULL, }, ++ { STRING60 "zz\\.", STRING60 "zz\\.", false }, ++ { STRING60 "zz\\..", STRING60 "zz\\.", true }, ++ { STRING63 "." STRING63 "." STRING63 "." STRING60 "z", ++ STRING63 "." STRING63 "." STRING63 "." STRING60 "z", false }, ++ { STRING63 "." STRING63 "." STRING63 "." STRING60 "z.", ++ STRING63 "." STRING63 "." STRING63 "." STRING60 "z", true }, ++ { STRING63 "." STRING63 "." STRING63 "." STRING60 "zz", NULL, }, ++ { STRING63 "." STRING63 "." STRING63 "." STRING60 "zzz", NULL, }, ++ { STRING63OCT "." STRING63OCT "." STRING63OCT "." STRING60OCT "\377", ++ STRING63DEC "." STRING63DEC "." STRING63DEC "." STRING60DEC "\\255", ++ false }, ++ { STRING63OCT "." STRING63OCT "." STRING63OCT "." STRING60OCT "\377.", ++ STRING63DEC "." STRING63DEC "." STRING63DEC "." STRING60DEC "\\255", ++ true }, ++ { STRING63OCT "." STRING63OCT "." STRING63OCT "." STRING60OCT ++ "\377\377", NULL, }, ++ { STRING63OCT "." STRING63OCT "." STRING63OCT "." STRING60OCT ++ "\377\377\377", NULL, }, ++ }; ++ ++static int ++do_test (void) ++{ ++ unsigned char *wire = xmalloc (NS_MAXCDNAME); ++ char *text = xmalloc (NS_MAXDNAME); ++ for (const struct test_case *test = tests; test < array_end (tests); ++test) ++ { ++ if (test_verbose) ++ printf ("info: testing domain name [[[%s]]]\n", test->dn); ++ int ret = ns_name_pton (test->dn, wire, NS_MAXCDNAME); ++ if (ret == -1) ++ { ++ if (test->back != NULL) ++ { ++ support_record_failure (); ++ printf ("error: unexpected decoding failure for [[%s]]\n", ++ test->dn); ++ } ++ /* Otherwise, we have an expected decoding failure. */ ++ continue; ++ } ++ ++ if (ret < -1 || ret > 1) ++ { ++ support_record_failure (); ++ printf ("error: invalid return value %d for [[%s]]\n", ++ ret, test->dn); ++ continue; ++ } ++ ++ int ret2 = ns_name_ntop (wire, text, NS_MAXDNAME); ++ ++ if (ret2 < 0) ++ { ++ support_record_failure (); ++ printf ("error: failure to convert back [[%s]]\n", test->dn); ++ } ++ ++ if (test->back == NULL) ++ { ++ support_record_failure (); ++ printf ("error: unexpected success converting [[%s]]\n", test->dn); ++ if (ret2 >= 1) ++ printf ("error: result converts back to [[%s]]\n", test->dn); ++ continue; ++ } ++ ++ if (strcmp (text, test->back) != 0) ++ { ++ support_record_failure (); ++ printf ("error: back-conversion of [[%s]] did not match\n", ++ test->dn); ++ printf ("error: expected: [[%s]]\n", test->back); ++ printf ("error: actual: [[%s]]\n", text); ++ } ++ ++ if (ret != test->fully_qualified) ++ { ++ support_record_failure (); ++ printf ("error: invalid fully-qualified status for [[%s]]\n", ++ test->dn); ++ printf ("error: expected: %d\n", (int) test->fully_qualified); ++ printf ("error: actual: %d\n", ret); ++ } ++ } ++ ++ free (text); ++ free (wire); ++ return 0; ++} ++ ++#include <support/test-driver.c> diff --git a/SOURCES/glibc-rh1039304-3.patch b/SOURCES/glibc-rh1039304-3.patch new file mode 100644 index 0000000..d39d4d2 --- /dev/null +++ b/SOURCES/glibc-rh1039304-3.patch @@ -0,0 +1,40 @@ +commit 9e0ad3049dbae88d615bfb038e53bf365a39a634 +Author: Florian Weimer <fweimer@redhat.com> +Date: Sat Nov 11 11:41:45 2017 +0100 + + resolv: ns_name_pton should report trailing \ as error [BZ #22413] + +diff --git a/resolv/ns_name.c b/resolv/ns_name.c +index 08a75e2fe0b4edd6..73213fee2dca530b 100644 +--- a/resolv/ns_name.c ++++ b/resolv/ns_name.c +@@ -222,6 +222,11 @@ ns_name_pton(const char *src, u_char *dst, size_t dstsiz) + } + *bp++ = (u_char)c; + } ++ if (escaped) { ++ /* Trailing backslash. */ ++ __set_errno (EMSGSIZE); ++ return -1; ++ } + c = (bp - label - 1); + if ((c & NS_CMPRSFLGS) != 0) { /*%< Label too big. */ + __set_errno (EMSGSIZE); +diff --git a/resolv/tst-ns_name_pton.c b/resolv/tst-ns_name_pton.c +index 879d97c9d3816210..73bdb05e08e405dc 100644 +--- a/resolv/tst-ns_name_pton.c ++++ b/resolv/tst-ns_name_pton.c +@@ -127,6 +127,13 @@ static const struct test_case tests[] = + "\377\377", NULL, }, + { STRING63OCT "." STRING63OCT "." STRING63OCT "." STRING60OCT + "\377\377\377", NULL, }, ++ { "\\", NULL, }, ++ { "\\\\", "\\\\", false }, ++ { "\\\\.", "\\\\", true }, ++ { "\\\\\\", NULL, }, ++ { "a\\", NULL, }, ++ { "a.\\", NULL, }, ++ { "a.b\\", NULL, }, + }; + + static int diff --git a/SOURCES/glibc-rh1039304-4.patch b/SOURCES/glibc-rh1039304-4.patch new file mode 100644 index 0000000..e67eab1 --- /dev/null +++ b/SOURCES/glibc-rh1039304-4.patch @@ -0,0 +1,322 @@ +commit c0a25aa92b612786f4e45292c4aee1d7d47123f8 +Author: Florian Weimer <fweimer@redhat.com> +Date: Sat Nov 11 11:51:08 2017 +0100 + + resolv: More precise checks in res_hnok, res_dnok [BZ #22409] [BZ #22412] + + res_hnok rejected some host names used on the Internet, such as + www-.example.com. res_hnok and res_dnok failed to perform basic syntax + checking on DNS domain names. + + Also fix res_mailok, res_ownok. + +diff --git a/resolv/res_comp.c b/resolv/res_comp.c +index ffb2ed59147d3680..79760e891f607daa 100644 +--- a/resolv/res_comp.c ++++ b/resolv/res_comp.c +@@ -1,3 +1,21 @@ ++/* Domain name processing functions. ++ Copyright (C) 1995-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 ++ <http://www.gnu.org/licenses/>. */ ++ + /* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. +@@ -121,110 +139,118 @@ dn_skipname(const u_char *ptr, const u_char *eom) { + } + libresolv_hidden_def (dn_skipname) + +-/* +- * Verify that a domain name uses an acceptable character set. +- */ ++/* Return true if the string consists of printable ASCII characters ++ only. */ ++static bool ++printable_string (const char *dn) ++{ ++ while (true) ++ { ++ char ch = *dn; ++ if (ch == '\0') ++ return true; ++ if (ch <= ' ' || ch > '~') ++ return false; ++ ++dn; ++ } ++} + +-/* +- * Note the conspicuous absence of ctype macros in these definitions. On +- * non-ASCII hosts, we can't depend on string literals or ctype macros to +- * tell us anything about network-format data. The rest of the BIND system +- * is not careful about this, but for some reason, we're doing it right here. +- */ +-#define PERIOD 0x2e +-#define hyphenchar(c) ((c) == 0x2d) +-#define underscorechar(c) ((c) == 0x5f) +-#define bslashchar(c) ((c) == 0x5c) +-#define periodchar(c) ((c) == PERIOD) +-#define asterchar(c) ((c) == 0x2a) +-#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \ +- || ((c) >= 0x61 && (c) <= 0x7a)) +-#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39) +- +-#define borderchar(c) (alphachar(c) || digitchar(c)) +-#define middlechar(c) (borderchar(c) || hyphenchar(c) || underscorechar(c)) +-#define domainchar(c) ((c) > 0x20 && (c) < 0x7f) ++/* Return true if DN points to a name consisting only of [0-9a-zA-Z_-] ++ characters. DN must be in DNS wire format, without ++ compression. */ ++static bool ++binary_hnok (const unsigned char *dn) ++{ ++ while (true) ++ { ++ size_t label_length = *dn; ++ if (label_length == 0) ++ break; ++ ++dn; ++ const unsigned char *label_end = dn + label_length; ++ do ++ { ++ unsigned char ch = *dn; ++ if (!(('0' <= ch && ch <= '9') ++ || ('A' <= ch && ch <= 'Z') ++ || ('a' <= ch && ch <= 'z') ++ || ch == '-' || ch == '_')) ++ return false; ++ ++dn; ++ } ++ while (dn < label_end); ++ } ++ return true; ++} ++ ++/* Return true if the binary domain name has a first labels which ++ starts with '-'. */ ++static inline bool ++binary_leading_dash (const unsigned char *dn) ++{ ++ return dn[0] > 0 && dn[1] == '-'; ++} + ++/* Return 1 if res_hnok is a valid host name. Labels must only ++ contain [0-9a-zA-Z_-] characters, and the name must not start with ++ a '-'. The latter is to avoid confusion with program options. */ + int +-res_hnok(const char *dn) { +- int pch = PERIOD, ch = *dn++; +- +- while (ch != '\0') { +- int nch = *dn++; +- +- if (periodchar(ch)) { +- (void)NULL; +- } else if (periodchar(pch)) { +- if (!borderchar(ch)) +- return (0); +- } else if (periodchar(nch) || nch == '\0') { +- if (!borderchar(ch)) +- return (0); +- } else { +- if (!middlechar(ch)) +- return (0); +- } +- pch = ch, ch = nch; +- } +- return (1); ++res_hnok (const char *dn) ++{ ++ unsigned char buf[NS_MAXCDNAME]; ++ if (!printable_string (dn) ++ || ns_name_pton (dn, buf, sizeof (buf)) < 0 ++ || binary_leading_dash (buf)) ++ return 0; ++ return binary_hnok (buf); + } + libresolv_hidden_def (res_hnok) + +-/* +- * hostname-like (A, MX, WKS) owners can have "*" as their first label +- * but must otherwise be as a host name. +- */ ++/* Hostname-like (A, MX, WKS) owners can have "*" as their first label ++ but must otherwise be as a host name. */ + int +-res_ownok(const char *dn) { +- if (asterchar(dn[0])) { +- if (periodchar(dn[1])) +- return (res_hnok(dn+2)); +- if (dn[1] == '\0') +- return (1); +- } +- return (res_hnok(dn)); ++res_ownok (const char *dn) ++{ ++ unsigned char buf[NS_MAXCDNAME]; ++ if (!printable_string (dn) ++ || ns_name_pton (dn, buf, sizeof (buf)) < 0 ++ || binary_leading_dash (buf)) ++ return 0; ++ if (buf[0] == 1 && buf [1] == '*') ++ /* Skip over the leading "*." part. */ ++ return binary_hnok (buf + 2); ++ else ++ return binary_hnok (buf); + } + +-/* +- * SOA RNAMEs and RP RNAMEs can have any printable character in their first +- * label, but the rest of the name has to look like a host name. +- */ ++/* SOA RNAMEs and RP RNAMEs can have any byte in their first label, ++ but the rest of the name has to look like a host name. */ + int +-res_mailok(const char *dn) { +- int ch, escaped = 0; +- +- /* "." is a valid missing representation */ +- if (*dn == '\0') +- return (1); +- +- /* otherwise <label>.<hostname> */ +- while ((ch = *dn++) != '\0') { +- if (!domainchar(ch)) +- return (0); +- if (!escaped && periodchar(ch)) +- break; +- if (escaped) +- escaped = 0; +- else if (bslashchar(ch)) +- escaped = 1; +- } +- if (periodchar(ch)) +- return (res_hnok(dn)); +- return (0); ++res_mailok (const char *dn) ++{ ++ unsigned char buf[NS_MAXCDNAME]; ++ if (!printable_string (dn) ++ || ns_name_pton (dn, buf, sizeof (buf)) < 0) ++ return 0; ++ unsigned char label_length = buf[0]; ++ /* "." is a valid missing representation */ ++ if (label_length == 0) ++ return 1; ++ /* Skip over the first label. */ ++ unsigned char *tail = buf + 1 + label_length; ++ if (*tail == 0) ++ /* More than one label is required (except for "."). */ ++ return 0; ++ return binary_hnok (tail); + } + +-/* +- * This function is quite liberal, since RFC 1034's character sets are only +- * recommendations. +- */ ++/* Return 1 if DN is a syntactically valid domain name. Empty names ++ are accepted. */ + int +-res_dnok(const char *dn) { +- int ch; +- +- while ((ch = *dn++) != '\0') +- if (!domainchar(ch)) +- return (0); +- return (1); ++res_dnok (const char *dn) ++{ ++ unsigned char buf[NS_MAXCDNAME]; ++ return printable_string (dn) && ns_name_pton (dn, buf, sizeof (buf)) >= 0; + } + libresolv_hidden_def (res_dnok) + +diff --git a/resolv/tst-res_hnok.c b/resolv/tst-res_hnok.c +index 9c923038218e965c..314477a2ce2661c0 100644 +--- a/resolv/tst-res_hnok.c ++++ b/resolv/tst-res_hnok.c +@@ -51,19 +51,31 @@ static const struct test_case tests[] = + { + { "", allok }, + { ".", allok }, ++ { "..", 0 }, + { "www", allnomailok }, ++ { "www.", allnomailok }, + { "example", allnomailok }, + { "example.com", allok }, + { "www.example.com", allok }, + { "www.example.com.", allok }, ++ { "www-.example.com.", allok }, ++ { "www.-example.com.", allok }, + { "*.example.com", dnok | mailok | ownok }, + { "-v", dnok }, + { "-v.example.com", mailok | dnok }, + { "**.example.com", dnok | mailok }, ++ { "www.example.com\\", 0 }, + { STRING63, allnomailok }, ++ { STRING63 ".", allnomailok }, ++ { STRING63 "\\.", 0 }, ++ { STRING63 "z", 0 }, + { STRING63 ".example.com", allok }, + { STRING63 "." STRING63 "." STRING63 "." STRING60 "z", allok }, ++ { STRING63 "." STRING63 "." STRING63 "." STRING60 "z.", allok }, ++ { STRING63 "." STRING63 "." STRING63 "." STRING60 "zz", 0 }, ++ { STRING63 "." STRING63 "." STRING63 "." STRING60 "zzz", 0 }, + { "hostmaster@mail.example.com", dnok | mailok }, ++ { "hostmaster\\@mail.example.com", dnok | mailok }, + { "with whitespace", 0 }, + { "with\twhitespace", 0 }, + { "with\nwhitespace", 0 }, +@@ -116,6 +128,12 @@ one_char (const char *prefix, const char *accepted, const char *suffix, + } + } + ++#define LETTERSDIGITS \ ++ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" ++ ++#define PRINTABLE \ ++ "!\"#$%&'()*+,/:;<=>?@[\\]^`{|}~" ++ + static int + do_test (void) + { +@@ -131,20 +149,18 @@ do_test (void) + } + + one_char +- ("", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.", +- "", "res_hnok", res_hnok); ++ ("", LETTERSDIGITS "._", "", "res_hnok", res_hnok); + one_char + ("middle", +- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.-_", ++ LETTERSDIGITS ".-_\\", /* "middle\\suffix" == "middlesuffix", so good. */ + "suffix", "res_hnok", res_hnok); + one_char + ("middle", +- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.-_" +- "!\"#$%&'()*+,/:;<=>?@[\\]^`{|}~", ++ LETTERSDIGITS ".-_" PRINTABLE, + "suffix.example", "res_mailok", res_mailok); + one_char + ("mailbox.middle", +- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.-_", ++ LETTERSDIGITS ".-_\\", + "suffix.example", "res_mailok", res_mailok); + + return 0; diff --git a/SOURCES/glibc-rh1163509-1.patch b/SOURCES/glibc-rh1163509-1.patch new file mode 100644 index 0000000..c8cd366 --- /dev/null +++ b/SOURCES/glibc-rh1163509-1.patch @@ -0,0 +1,834 @@ +Note: The __pthread_once definition in the new unified implementation in +this patch has been edited. The original version of the patch had an old +style declaration that was causing a -Werror=old-style-definition failure. + +commit 36875b06e0ed7f137190b9228bef553adfc338ba +Author: Torvald Riegel <triegel@redhat.com> +Date: Wed May 8 16:35:10 2013 +0200 + + Fixed and unified pthread_once. + + [BZ #15215] This unifies various pthread_once architecture-specific + implementations which were using the same algorithm with slightly different + implementations. It also adds missing memory barriers that are required for + correctness. + +diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_once.c b/nptl/sysdeps/unix/sysv/linux/pthread_once.c +new file mode 100644 +index 0000000000000000..2684b660958361d4 +--- /dev/null ++++ b/nptl/sysdeps/unix/sysv/linux/pthread_once.c +@@ -0,0 +1,129 @@ ++/* Copyright (C) 2003-2014 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. ++ ++ 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 ++ <http://www.gnu.org/licenses/>. */ ++ ++#include "pthreadP.h" ++#include <lowlevellock.h> ++#include <atomic.h> ++ ++ ++unsigned long int __fork_generation attribute_hidden; ++ ++ ++static void ++clear_once_control (void *arg) ++{ ++ pthread_once_t *once_control = (pthread_once_t *) arg; ++ ++ /* Reset to the uninitialized state here. We don't need a stronger memory ++ order because we do not need to make any other of our writes visible to ++ other threads that see this value: This function will be called if we ++ get interrupted (see __pthread_once), so all we need to relay to other ++ threads is the state being reset again. */ ++ *once_control = 0; ++ lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); ++} ++ ++ ++/* This is similar to a lock implementation, but we distinguish between three ++ states: not yet initialized (0), initialization finished (2), and ++ initialization in progress (__fork_generation | 1). If in the first state, ++ threads will try to run the initialization by moving to the second state; ++ the first thread to do so via a CAS on once_control runs init_routine, ++ other threads block. ++ When forking the process, some threads can be interrupted during the second ++ state; they won't be present in the forked child, so we need to restart ++ initialization in the child. To distinguish an in-progress initialization ++ from an interrupted initialization (in which case we need to reclaim the ++ lock), we look at the fork generation that's part of the second state: We ++ can reclaim iff it differs from the current fork generation. ++ XXX: This algorithm has an ABA issue on the fork generation: If an ++ initialization is interrupted, we then fork 2^30 times (30 bits of ++ once_control are used for the fork generation), and try to initialize ++ again, we can deadlock because we can't distinguish the in-progress and ++ interrupted cases anymore. */ ++int ++__pthread_once (pthread_once_t *once_control, void (*init_routine) (void)) ++{ ++ while (1) ++ { ++ int oldval, val, newval; ++ ++ /* We need acquire memory order for this load because if the value ++ signals that initialization has finished, we need to be see any ++ data modifications done during initialization. */ ++ val = *once_control; ++ atomic_read_barrier(); ++ do ++ { ++ /* Check if the initialization has already been done. */ ++ if (__glibc_likely ((val & 2) != 0)) ++ return 0; ++ ++ oldval = val; ++ /* We try to set the state to in-progress and having the current ++ fork generation. We don't need atomic accesses for the fork ++ generation because it's immutable in a particular process, and ++ forked child processes start with a single thread that modified ++ the generation. */ ++ newval = __fork_generation | 1; ++ /* We need acquire memory order here for the same reason as for the ++ load from once_control above. */ ++ val = atomic_compare_and_exchange_val_acq (once_control, newval, ++ oldval); ++ } ++ while (__glibc_unlikely (val != oldval)); ++ ++ /* Check if another thread already runs the initializer. */ ++ if ((oldval & 1) != 0) ++ { ++ /* Check whether the initializer execution was interrupted by a ++ fork. We know that for both values, bit 0 is set and bit 1 is ++ not. */ ++ if (oldval == newval) ++ { ++ /* Same generation, some other thread was faster. Wait. */ ++ lll_futex_wait (once_control, newval, LLL_PRIVATE); ++ continue; ++ } ++ } ++ ++ /* This thread is the first here. Do the initialization. ++ Register a cleanup handler so that in case the thread gets ++ interrupted the initialization can be restarted. */ ++ pthread_cleanup_push (clear_once_control, once_control); ++ ++ init_routine (); ++ ++ pthread_cleanup_pop (0); ++ ++ ++ /* Mark *once_control as having finished the initialization. We need ++ release memory order here because we need to synchronize with other ++ threads that want to use the initialized data. */ ++ atomic_write_barrier(); ++ *once_control = 2; ++ ++ /* Wake up all other threads. */ ++ lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); ++ break; ++ } ++ ++ return 0; ++} ++weak_alias (__pthread_once, pthread_once) ++hidden_def (__pthread_once) +diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/pthread_once.c b/nptl/sysdeps/unix/sysv/linux/sparc/pthread_once.c +deleted file mode 100644 +index a2111756374174f2..0000000000000000 +--- a/nptl/sysdeps/unix/sysv/linux/sparc/pthread_once.c ++++ /dev/null +@@ -1,93 +0,0 @@ +-/* Copyright (C) 2003-2012 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. +- +- 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 +- <http://www.gnu.org/licenses/>. */ +- +-#include "pthreadP.h" +-#include <lowlevellock.h> +- +- +-unsigned long int __fork_generation attribute_hidden; +- +- +-static void +-clear_once_control (void *arg) +-{ +- pthread_once_t *once_control = (pthread_once_t *) arg; +- +- *once_control = 0; +- lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +-} +- +- +-int +-__pthread_once (once_control, init_routine) +- pthread_once_t *once_control; +- void (*init_routine) (void); +-{ +- while (1) +- { +- int oldval, val, newval; +- +- val = *once_control; +- do +- { +- /* Check if the initialized has already been done. */ +- if ((val & 2) != 0) +- return 0; +- +- oldval = val; +- newval = (oldval & 3) | __fork_generation | 1; +- val = atomic_compare_and_exchange_val_acq (once_control, newval, +- oldval); +- } +- while (__builtin_expect (val != oldval, 0)); +- +- /* Check if another thread already runs the initializer. */ +- if ((oldval & 1) != 0) +- { +- /* Check whether the initializer execution was interrupted +- by a fork. */ +- if (((oldval ^ newval) & -4) == 0) +- { +- /* Same generation, some other thread was faster. Wait. */ +- lll_futex_wait (once_control, newval, LLL_PRIVATE); +- continue; +- } +- } +- +- /* This thread is the first here. Do the initialization. +- Register a cleanup handler so that in case the thread gets +- interrupted the initialization can be restarted. */ +- pthread_cleanup_push (clear_once_control, once_control); +- +- init_routine (); +- +- pthread_cleanup_pop (0); +- +- +- /* Add one to *once_control. */ +- atomic_increment (once_control); +- +- /* Wake up all other threads. */ +- lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +- break; +- } +- +- return 0; +-} +-weak_alias (__pthread_once, pthread_once) +-hidden_def (__pthread_once) +diff --git a/sysdeps/unix/sysv/linux/aarch64/nptl/pthread_once.c b/sysdeps/unix/sysv/linux/aarch64/nptl/pthread_once.c +deleted file mode 100644 +index 0897e1e004ef3278..0000000000000000 +--- a/sysdeps/unix/sysv/linux/aarch64/nptl/pthread_once.c ++++ /dev/null +@@ -1,90 +0,0 @@ +-/* Copyright (C) 2004-2012 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 +- <http://www.gnu.org/licenses/>. */ +- +-#include "pthreadP.h" +-#include <lowlevellock.h> +- +-unsigned long int __fork_generation attribute_hidden; +- +-static void +-clear_once_control (void *arg) +-{ +- pthread_once_t *once_control = (pthread_once_t *) arg; +- +- *once_control = 0; +- lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +-} +- +-int +-__pthread_once (pthread_once_t *once_control, void (*init_routine) (void)) +-{ +- for (;;) +- { +- int oldval; +- int newval; +- +- /* Pseudo code: +- newval = __fork_generation | 1; +- oldval = *once_control; +- if ((oldval & 2) == 0) +- *once_control = newval; +- Do this atomically. +- */ +- do +- { +- newval = __fork_generation | 1; +- oldval = *once_control; +- if (oldval & 2) +- break; +- } while (atomic_compare_and_exchange_val_acq (once_control, newval, oldval) != oldval); +- +- /* Check if the initializer has already been done. */ +- if ((oldval & 2) != 0) +- return 0; +- +- /* Check if another thread already runs the initializer. */ +- if ((oldval & 1) == 0) +- break; +- +- /* Check whether the initializer execution was interrupted by a fork. */ +- if (oldval != newval) +- break; +- +- /* Same generation, some other thread was faster. Wait. */ +- lll_futex_wait (once_control, oldval, LLL_PRIVATE); +- } +- +- /* This thread is the first here. Do the initialization. +- Register a cleanup handler so that in case the thread gets +- interrupted the initialization can be restarted. */ +- pthread_cleanup_push (clear_once_control, once_control); +- +- init_routine (); +- +- pthread_cleanup_pop (0); +- +- /* Say that the initialisation is done. */ +- *once_control = __fork_generation | 2; +- +- /* Wake up all other threads. */ +- lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +- +- return 0; +-} +-weak_alias (__pthread_once, pthread_once) +-hidden_def (__pthread_once) +diff --git a/sysdeps/unix/sysv/linux/arm/nptl/pthread_once.c b/sysdeps/unix/sysv/linux/arm/nptl/pthread_once.c +deleted file mode 100644 +index 0c03f1c816a2fad5..0000000000000000 +--- a/sysdeps/unix/sysv/linux/arm/nptl/pthread_once.c ++++ /dev/null +@@ -1,89 +0,0 @@ +-/* Copyright (C) 2004-2012 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 +- <http://www.gnu.org/licenses/>. */ +- +-#include "pthreadP.h" +-#include <lowlevellock.h> +- +-unsigned long int __fork_generation attribute_hidden; +- +-static void +-clear_once_control (void *arg) +-{ +- pthread_once_t *once_control = (pthread_once_t *) arg; +- +- *once_control = 0; +- lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +-} +- +-int +-__pthread_once (pthread_once_t *once_control, void (*init_routine) (void)) +-{ +- for (;;) +- { +- int oldval; +- int newval; +- +- /* Pseudo code: +- newval = __fork_generation | 1; +- oldval = *once_control; +- if ((oldval & 2) == 0) +- *once_control = newval; +- Do this atomically. +- */ +- do +- { +- newval = __fork_generation | 1; +- oldval = *once_control; +- if (oldval & 2) +- break; +- } while (atomic_compare_and_exchange_val_acq (once_control, newval, oldval) != oldval); +- +- /* Check if the initializer has already been done. */ +- if ((oldval & 2) != 0) +- return 0; +- +- /* Check if another thread already runs the initializer. */ +- if ((oldval & 1) == 0) +- break; +- +- /* Check whether the initializer execution was interrupted by a fork. */ +- if (oldval != newval) +- break; +- +- /* Same generation, some other thread was faster. Wait. */ +- lll_futex_wait (once_control, oldval, LLL_PRIVATE); +- } +- +- /* This thread is the first here. Do the initialization. +- Register a cleanup handler so that in case the thread gets +- interrupted the initialization can be restarted. */ +- pthread_cleanup_push (clear_once_control, once_control); +- +- init_routine (); +- +- pthread_cleanup_pop (0); +- +- /* Say that the initialisation is done. */ +- *once_control = __fork_generation | 2; +- +- /* Wake up all other threads. */ +- lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +- +- return 0; +-} +-weak_alias (__pthread_once, pthread_once) +-hidden_def (__pthread_once) +diff --git a/sysdeps/unix/sysv/linux/ia64/nptl/pthread_once.c b/sysdeps/unix/sysv/linux/ia64/nptl/pthread_once.c +deleted file mode 100644 +index 7730935dfec85ae6..0000000000000000 +--- a/sysdeps/unix/sysv/linux/ia64/nptl/pthread_once.c ++++ /dev/null +@@ -1,93 +0,0 @@ +-/* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. +- +- 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 +- <http://www.gnu.org/licenses/>. */ +- +-#include "pthreadP.h" +-#include <lowlevellock.h> +- +- +-unsigned long int __fork_generation attribute_hidden; +- +- +-static void +-clear_once_control (void *arg) +-{ +- pthread_once_t *once_control = (pthread_once_t *) arg; +- +- *once_control = 0; +- lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +-} +- +- +-int +-__pthread_once (once_control, init_routine) +- pthread_once_t *once_control; +- void (*init_routine) (void); +-{ +- while (1) +- { +- int oldval, val, newval; +- +- val = *once_control; +- do +- { +- /* Check if the initialized has already been done. */ +- if ((val & 2) != 0) +- return 0; +- +- oldval = val; +- newval = (oldval & 3) | __fork_generation | 1; +- val = atomic_compare_and_exchange_val_acq (once_control, newval, +- oldval); +- } +- while (__builtin_expect (val != oldval, 0)); +- +- /* Check if another thread already runs the initializer. */ +- if ((oldval & 1) != 0) +- { +- /* Check whether the initializer execution was interrupted +- by a fork. */ +- if (((oldval ^ newval) & -4) == 0) +- { +- /* Same generation, some other thread was faster. Wait. */ +- lll_futex_wait (once_control, newval, LLL_PRIVATE); +- continue; +- } +- } +- +- /* This thread is the first here. Do the initialization. +- Register a cleanup handler so that in case the thread gets +- interrupted the initialization can be restarted. */ +- pthread_cleanup_push (clear_once_control, once_control); +- +- init_routine (); +- +- pthread_cleanup_pop (0); +- +- +- /* Add one to *once_control. */ +- atomic_increment (once_control); +- +- /* Wake up all other threads. */ +- lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +- break; +- } +- +- return 0; +-} +-weak_alias (__pthread_once, pthread_once) +-hidden_def (__pthread_once) +diff --git a/sysdeps/unix/sysv/linux/m68k/nptl/pthread_once.c b/sysdeps/unix/sysv/linux/m68k/nptl/pthread_once.c +deleted file mode 100644 +index 8d81db602eee601f..0000000000000000 +--- a/sysdeps/unix/sysv/linux/m68k/nptl/pthread_once.c ++++ /dev/null +@@ -1,90 +0,0 @@ +-/* Copyright (C) 2010-2012 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010. +- +- 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 +- <http://www.gnu.org/licenses/>. */ +- +-#include "pthreadP.h" +-#include <lowlevellock.h> +- +-unsigned long int __fork_generation attribute_hidden; +- +-static void +-clear_once_control (void *arg) +-{ +- pthread_once_t *once_control = (pthread_once_t *) arg; +- +- *once_control = 0; +- lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +-} +- +-int +-__pthread_once (pthread_once_t *once_control, void (*init_routine) (void)) +-{ +- for (;;) +- { +- int oldval; +- int newval; +- +- /* Pseudo code: +- newval = __fork_generation | 1; +- oldval = *once_control; +- if ((oldval & 2) == 0) +- *once_control = newval; +- Do this atomically. +- */ +- do +- { +- newval = __fork_generation | 1; +- oldval = *once_control; +- if (oldval & 2) +- break; +- } while (atomic_compare_and_exchange_val_acq (once_control, newval, oldval) != oldval); +- +- /* Check if the initializer has already been done. */ +- if ((oldval & 2) != 0) +- return 0; +- +- /* Check if another thread already runs the initializer. */ +- if ((oldval & 1) == 0) +- break; +- +- /* Check whether the initializer execution was interrupted by a fork. */ +- if (oldval != newval) +- break; +- +- /* Same generation, some other thread was faster. Wait. */ +- lll_futex_wait (once_control, oldval, LLL_PRIVATE); +- } +- +- /* This thread is the first here. Do the initialization. +- Register a cleanup handler so that in case the thread gets +- interrupted the initialization can be restarted. */ +- pthread_cleanup_push (clear_once_control, once_control); +- +- init_routine (); +- +- pthread_cleanup_pop (0); +- +- /* Say that the initialisation is done. */ +- *once_control = __fork_generation | 2; +- +- /* Wake up all other threads. */ +- lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +- +- return 0; +-} +-weak_alias (__pthread_once, pthread_once) +-hidden_def (__pthread_once) +diff --git a/sysdeps/unix/sysv/linux/mips/nptl/pthread_once.c b/sysdeps/unix/sysv/linux/mips/nptl/pthread_once.c +deleted file mode 100644 +index 308da8bbce0c3800..0000000000000000 +--- a/sysdeps/unix/sysv/linux/mips/nptl/pthread_once.c ++++ /dev/null +@@ -1,93 +0,0 @@ +-/* Copyright (C) 2003-2012 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. +- +- 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 +- <http://www.gnu.org/licenses/>. */ +- +-#include "pthreadP.h" +-#include <lowlevellock.h> +- +- +-unsigned long int __fork_generation attribute_hidden; +- +- +-static void +-clear_once_control (void *arg) +-{ +- pthread_once_t *once_control = (pthread_once_t *) arg; +- +- *once_control = 0; +- lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +-} +- +- +-int +-__pthread_once (once_control, init_routine) +- pthread_once_t *once_control; +- void (*init_routine) (void); +-{ +- while (1) +- { +- int oldval, val, newval; +- +- val = *once_control; +- do +- { +- /* Check if the initialized has already been done. */ +- if ((val & 2) != 0) +- return 0; +- +- oldval = val; +- newval = (oldval & 3) | __fork_generation | 1; +- val = atomic_compare_and_exchange_val_acq (once_control, newval, +- oldval); +- } +- while (__builtin_expect (val != oldval, 0)); +- +- /* Check if another thread already runs the initializer. */ +- if ((oldval & 1) != 0) +- { +- /* Check whether the initializer execution was interrupted +- by a fork. */ +- if (((oldval ^ newval) & -4) == 0) +- { +- /* Same generation, some other thread was faster. Wait. */ +- lll_futex_wait (once_control, newval, LLL_PRIVATE); +- continue; +- } +- } +- +- /* This thread is the first here. Do the initialization. +- Register a cleanup handler so that in case the thread gets +- interrupted the initialization can be restarted. */ +- pthread_cleanup_push (clear_once_control, once_control); +- +- init_routine (); +- +- pthread_cleanup_pop (0); +- +- +- /* Add one to *once_control. */ +- atomic_increment (once_control); +- +- /* Wake up all other threads. */ +- lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +- break; +- } +- +- return 0; +-} +-weak_alias (__pthread_once, pthread_once) +-hidden_def (__pthread_once) +diff --git a/sysdeps/unix/sysv/linux/tile/nptl/pthread_once.c b/sysdeps/unix/sysv/linux/tile/nptl/pthread_once.c +deleted file mode 100644 +index 93ac29b24c440b2c..0000000000000000 +--- a/sysdeps/unix/sysv/linux/tile/nptl/pthread_once.c ++++ /dev/null +@@ -1,94 +0,0 @@ +-/* Copyright (C) 2011-2012 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011. +- Based on work contributed by Jakub Jelinek <jakub@redhat.com>, 2003. +- +- 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 +- <http://www.gnu.org/licenses/>. */ +- +-#include <nptl/pthreadP.h> +-#include <lowlevellock.h> +- +- +-unsigned long int __fork_generation attribute_hidden; +- +- +-static void +-clear_once_control (void *arg) +-{ +- pthread_once_t *once_control = (pthread_once_t *) arg; +- +- *once_control = 0; +- lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +-} +- +- +-int +-__pthread_once (once_control, init_routine) +- pthread_once_t *once_control; +- void (*init_routine) (void); +-{ +- while (1) +- { +- int oldval, val, newval; +- +- val = *once_control; +- do +- { +- /* Check if the initialized has already been done. */ +- if ((val & 2) != 0) +- return 0; +- +- oldval = val; +- newval = (oldval & 3) | __fork_generation | 1; +- val = atomic_compare_and_exchange_val_acq (once_control, newval, +- oldval); +- } +- while (__builtin_expect (val != oldval, 0)); +- +- /* Check if another thread already runs the initializer. */ +- if ((oldval & 1) != 0) +- { +- /* Check whether the initializer execution was interrupted +- by a fork. */ +- if (((oldval ^ newval) & -4) == 0) +- { +- /* Same generation, some other thread was faster. Wait. */ +- lll_futex_wait (once_control, newval, LLL_PRIVATE); +- continue; +- } +- } +- +- /* This thread is the first here. Do the initialization. +- Register a cleanup handler so that in case the thread gets +- interrupted the initialization can be restarted. */ +- pthread_cleanup_push (clear_once_control, once_control); +- +- init_routine (); +- +- pthread_cleanup_pop (0); +- +- +- /* Add one to *once_control. */ +- atomic_increment (once_control); +- +- /* Wake up all other threads. */ +- lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +- break; +- } +- +- return 0; +-} +-weak_alias (__pthread_once, pthread_once) +-hidden_def (__pthread_once) diff --git a/SOURCES/glibc-rh1163509-2.patch b/SOURCES/glibc-rh1163509-2.patch new file mode 100644 index 0000000..78284d0 --- /dev/null +++ b/SOURCES/glibc-rh1163509-2.patch @@ -0,0 +1,294 @@ +This patch is based on the below upstream commit. +It only includes relevant pthread_once bits. + +commit 08192659bbeae149e7cb1f4c43547257f7099bb0 +Author: Roland McGrath <roland@hack.frob.com> +Date: Mon Jul 7 09:28:38 2014 -0700 + + Get rid of nptl/sysdeps/ entirely! + +diff --git a/nptl/pthread_once.c b/nptl/pthread_once.c +index ed1ea3498c397e5c..10c01d6023508e3c 100644 +--- a/nptl/pthread_once.c ++++ b/nptl/pthread_once.c +@@ -1,6 +1,6 @@ +-/* Copyright (C) 2002-2012 Free Software Foundation, Inc. ++/* Copyright (C) 2003-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. +- Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. ++ Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public +@@ -9,7 +9,7 @@ + + 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 ++ 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 +@@ -18,37 +18,114 @@ + + #include "pthreadP.h" + #include <lowlevellock.h> ++#include <atomic.h> + + ++unsigned long int __fork_generation attribute_hidden; + +-static int once_lock = LLL_LOCK_INITIALIZER; + ++static void ++clear_once_control (void *arg) ++{ ++ pthread_once_t *once_control = (pthread_once_t *) arg; ++ ++ /* Reset to the uninitialized state here. We don't need a stronger memory ++ order because we do not need to make any other of our writes visible to ++ other threads that see this value: This function will be called if we ++ get interrupted (see __pthread_once), so all we need to relay to other ++ threads is the state being reset again. */ ++ *once_control = 0; ++ lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); ++} + ++ ++/* This is similar to a lock implementation, but we distinguish between three ++ states: not yet initialized (0), initialization finished (2), and ++ initialization in progress (__fork_generation | 1). If in the first state, ++ threads will try to run the initialization by moving to the second state; ++ the first thread to do so via a CAS on once_control runs init_routine, ++ other threads block. ++ When forking the process, some threads can be interrupted during the second ++ state; they won't be present in the forked child, so we need to restart ++ initialization in the child. To distinguish an in-progress initialization ++ from an interrupted initialization (in which case we need to reclaim the ++ lock), we look at the fork generation that's part of the second state: We ++ can reclaim iff it differs from the current fork generation. ++ XXX: This algorithm has an ABA issue on the fork generation: If an ++ initialization is interrupted, we then fork 2^30 times (30 bits of ++ once_control are used for the fork generation), and try to initialize ++ again, we can deadlock because we can't distinguish the in-progress and ++ interrupted cases anymore. */ + int + __pthread_once (once_control, init_routine) + pthread_once_t *once_control; + void (*init_routine) (void); + { +- /* XXX Depending on whether the LOCK_IN_ONCE_T is defined use a +- global lock variable or one which is part of the pthread_once_t +- object. */ +- if (*once_control == PTHREAD_ONCE_INIT) ++ while (1) + { +- lll_lock (once_lock, LLL_PRIVATE); ++ int oldval, val, newval; + +- /* XXX This implementation is not complete. It doesn't take +- cancelation and fork into account. */ +- if (*once_control == PTHREAD_ONCE_INIT) ++ /* We need acquire memory order for this load because if the value ++ signals that initialization has finished, we need to be see any ++ data modifications done during initialization. */ ++ val = *once_control; ++ atomic_read_barrier(); ++ do + { +- init_routine (); ++ /* Check if the initialization has already been done. */ ++ if (__glibc_likely ((val & 2) != 0)) ++ return 0; ++ ++ oldval = val; ++ /* We try to set the state to in-progress and having the current ++ fork generation. We don't need atomic accesses for the fork ++ generation because it's immutable in a particular process, and ++ forked child processes start with a single thread that modified ++ the generation. */ ++ newval = __fork_generation | 1; ++ /* We need acquire memory order here for the same reason as for the ++ load from once_control above. */ ++ val = atomic_compare_and_exchange_val_acq (once_control, newval, ++ oldval); ++ } ++ while (__glibc_unlikely (val != oldval)); + +- *once_control = !PTHREAD_ONCE_INIT; ++ /* Check if another thread already runs the initializer. */ ++ if ((oldval & 1) != 0) ++ { ++ /* Check whether the initializer execution was interrupted by a ++ fork. We know that for both values, bit 0 is set and bit 1 is ++ not. */ ++ if (oldval == newval) ++ { ++ /* Same generation, some other thread was faster. Wait. */ ++ lll_futex_wait (once_control, newval, LLL_PRIVATE); ++ continue; ++ } + } + +- lll_unlock (once_lock, LLL_PRIVATE); ++ /* This thread is the first here. Do the initialization. ++ Register a cleanup handler so that in case the thread gets ++ interrupted the initialization can be restarted. */ ++ pthread_cleanup_push (clear_once_control, once_control); ++ ++ init_routine (); ++ ++ pthread_cleanup_pop (0); ++ ++ ++ /* Mark *once_control as having finished the initialization. We need ++ release memory order here because we need to synchronize with other ++ threads that want to use the initialized data. */ ++ atomic_write_barrier(); ++ *once_control = 2; ++ ++ /* Wake up all other threads. */ ++ lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); ++ break; + } + + return 0; + } +-strong_alias (__pthread_once, pthread_once) ++weak_alias (__pthread_once, pthread_once) + hidden_def (__pthread_once) +diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_once.c b/nptl/sysdeps/unix/sysv/linux/pthread_once.c +deleted file mode 100644 +index 2684b660958361d4..0000000000000000 +--- a/nptl/sysdeps/unix/sysv/linux/pthread_once.c ++++ /dev/null +@@ -1,129 +0,0 @@ +-/* Copyright (C) 2003-2014 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. +- +- 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 +- <http://www.gnu.org/licenses/>. */ +- +-#include "pthreadP.h" +-#include <lowlevellock.h> +-#include <atomic.h> +- +- +-unsigned long int __fork_generation attribute_hidden; +- +- +-static void +-clear_once_control (void *arg) +-{ +- pthread_once_t *once_control = (pthread_once_t *) arg; +- +- /* Reset to the uninitialized state here. We don't need a stronger memory +- order because we do not need to make any other of our writes visible to +- other threads that see this value: This function will be called if we +- get interrupted (see __pthread_once), so all we need to relay to other +- threads is the state being reset again. */ +- *once_control = 0; +- lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +-} +- +- +-/* This is similar to a lock implementation, but we distinguish between three +- states: not yet initialized (0), initialization finished (2), and +- initialization in progress (__fork_generation | 1). If in the first state, +- threads will try to run the initialization by moving to the second state; +- the first thread to do so via a CAS on once_control runs init_routine, +- other threads block. +- When forking the process, some threads can be interrupted during the second +- state; they won't be present in the forked child, so we need to restart +- initialization in the child. To distinguish an in-progress initialization +- from an interrupted initialization (in which case we need to reclaim the +- lock), we look at the fork generation that's part of the second state: We +- can reclaim iff it differs from the current fork generation. +- XXX: This algorithm has an ABA issue on the fork generation: If an +- initialization is interrupted, we then fork 2^30 times (30 bits of +- once_control are used for the fork generation), and try to initialize +- again, we can deadlock because we can't distinguish the in-progress and +- interrupted cases anymore. */ +-int +-__pthread_once (pthread_once_t *once_control, void (*init_routine) (void)) +-{ +- while (1) +- { +- int oldval, val, newval; +- +- /* We need acquire memory order for this load because if the value +- signals that initialization has finished, we need to be see any +- data modifications done during initialization. */ +- val = *once_control; +- atomic_read_barrier(); +- do +- { +- /* Check if the initialization has already been done. */ +- if (__glibc_likely ((val & 2) != 0)) +- return 0; +- +- oldval = val; +- /* We try to set the state to in-progress and having the current +- fork generation. We don't need atomic accesses for the fork +- generation because it's immutable in a particular process, and +- forked child processes start with a single thread that modified +- the generation. */ +- newval = __fork_generation | 1; +- /* We need acquire memory order here for the same reason as for the +- load from once_control above. */ +- val = atomic_compare_and_exchange_val_acq (once_control, newval, +- oldval); +- } +- while (__glibc_unlikely (val != oldval)); +- +- /* Check if another thread already runs the initializer. */ +- if ((oldval & 1) != 0) +- { +- /* Check whether the initializer execution was interrupted by a +- fork. We know that for both values, bit 0 is set and bit 1 is +- not. */ +- if (oldval == newval) +- { +- /* Same generation, some other thread was faster. Wait. */ +- lll_futex_wait (once_control, newval, LLL_PRIVATE); +- continue; +- } +- } +- +- /* This thread is the first here. Do the initialization. +- Register a cleanup handler so that in case the thread gets +- interrupted the initialization can be restarted. */ +- pthread_cleanup_push (clear_once_control, once_control); +- +- init_routine (); +- +- pthread_cleanup_pop (0); +- +- +- /* Mark *once_control as having finished the initialization. We need +- release memory order here because we need to synchronize with other +- threads that want to use the initialized data. */ +- atomic_write_barrier(); +- *once_control = 2; +- +- /* Wake up all other threads. */ +- lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +- break; +- } +- +- return 0; +-} +-weak_alias (__pthread_once, pthread_once) +-hidden_def (__pthread_once) diff --git a/SOURCES/glibc-rh1163509-3.patch b/SOURCES/glibc-rh1163509-3.patch new file mode 100644 index 0000000..17b2c93 --- /dev/null +++ b/SOURCES/glibc-rh1163509-3.patch @@ -0,0 +1,108 @@ +commit 63668b7084ac26865136e59fdf17781f9f49bd99 +Author: Torvald Riegel <triegel@redhat.com> +Date: Fri Oct 11 18:58:04 2013 +0300 + + pthread_once: Clean up constants. + + [BZ #15215] This just gives a name to the integer constants being used. + +diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h +index dda1032d5aa95234..1a842e06bff82479 100644 +--- a/nptl/pthreadP.h ++++ b/nptl/pthreadP.h +@@ -159,6 +159,12 @@ enum + #define FUTEX_TID_MASK 0x3fffffff + + ++/* pthread_once definitions. See __pthread_once for how these are used. */ ++#define __PTHREAD_ONCE_INPROGRESS 1 ++#define __PTHREAD_ONCE_DONE 2 ++#define __PTHREAD_ONCE_FORK_GEN_INCR 4 ++ ++ + /* Internal variables. */ + + +diff --git a/nptl/pthread_once.c b/nptl/pthread_once.c +index 10c01d6023508e3c..595bd7e298003e00 100644 +--- a/nptl/pthread_once.c ++++ b/nptl/pthread_once.c +@@ -40,8 +40,11 @@ clear_once_control (void *arg) + + + /* This is similar to a lock implementation, but we distinguish between three +- states: not yet initialized (0), initialization finished (2), and +- initialization in progress (__fork_generation | 1). If in the first state, ++ states: not yet initialized (0), initialization in progress ++ (__fork_generation | __PTHREAD_ONCE_INPROGRESS), and initialization ++ finished (__PTHREAD_ONCE_DONE); __fork_generation does not use the bits ++ that are used for __PTHREAD_ONCE_INPROGRESS and __PTHREAD_ONCE_DONE (which ++ is what __PTHREAD_ONCE_FORK_GEN_INCR is used for). If in the first state, + threads will try to run the initialization by moving to the second state; + the first thread to do so via a CAS on once_control runs init_routine, + other threads block. +@@ -66,14 +69,14 @@ __pthread_once (once_control, init_routine) + int oldval, val, newval; + + /* We need acquire memory order for this load because if the value +- signals that initialization has finished, we need to be see any ++ signals that initialization has finished, we need to see any + data modifications done during initialization. */ + val = *once_control; + atomic_read_barrier(); + do + { + /* Check if the initialization has already been done. */ +- if (__glibc_likely ((val & 2) != 0)) ++ if (__glibc_likely ((val & __PTHREAD_ONCE_DONE) != 0)) + return 0; + + oldval = val; +@@ -82,7 +85,7 @@ __pthread_once (once_control, init_routine) + generation because it's immutable in a particular process, and + forked child processes start with a single thread that modified + the generation. */ +- newval = __fork_generation | 1; ++ newval = __fork_generation | __PTHREAD_ONCE_INPROGRESS; + /* We need acquire memory order here for the same reason as for the + load from once_control above. */ + val = atomic_compare_and_exchange_val_acq (once_control, newval, +@@ -91,11 +94,11 @@ __pthread_once (once_control, init_routine) + while (__glibc_unlikely (val != oldval)); + + /* Check if another thread already runs the initializer. */ +- if ((oldval & 1) != 0) ++ if ((oldval & __PTHREAD_ONCE_INPROGRESS) != 0) + { + /* Check whether the initializer execution was interrupted by a +- fork. We know that for both values, bit 0 is set and bit 1 is +- not. */ ++ fork. We know that for both values, __PTHREAD_ONCE_INPROGRESS ++ is set and __PTHREAD_ONCE_DONE is not. */ + if (oldval == newval) + { + /* Same generation, some other thread was faster. Wait. */ +@@ -118,7 +121,7 @@ __pthread_once (once_control, init_routine) + release memory order here because we need to synchronize with other + threads that want to use the initialized data. */ + atomic_write_barrier(); +- *once_control = 2; ++ *once_control = __PTHREAD_ONCE_DONE; + + /* Wake up all other threads. */ + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +diff --git a/nptl/sysdeps/unix/sysv/linux/fork.c b/nptl/sysdeps/unix/sysv/linux/fork.c +index 0635bfdb6cdf0aa8..8c197cb8e4347959 100644 +--- a/nptl/sysdeps/unix/sysv/linux/fork.c ++++ b/nptl/sysdeps/unix/sysv/linux/fork.c +@@ -146,8 +146,9 @@ __libc_fork (void) + + assert (THREAD_GETMEM (self, tid) != ppid); + ++ /* See __pthread_once. */ + if (__fork_generation_pointer != NULL) +- *__fork_generation_pointer += 4; ++ *__fork_generation_pointer += __PTHREAD_ONCE_FORK_GEN_INCR; + + /* Adjust the PID field for the new process. */ + THREAD_SETMEM (self, pid, THREAD_GETMEM (self, tid)); diff --git a/SOURCES/glibc-rh1163509-4.patch b/SOURCES/glibc-rh1163509-4.patch new file mode 100644 index 0000000..641face --- /dev/null +++ b/SOURCES/glibc-rh1163509-4.patch @@ -0,0 +1,443 @@ +This patch is based on the below upstream commit. +File deletions were altered to reflect file renames. + +commit f50277c19df0937ea9691ab7e7c642ecd3ed3d94 +Author: Torvald Riegel <triegel@redhat.com> +Date: Sun Oct 19 21:59:26 2014 +0200 + + pthread_once: Add fast path and remove x86 variants. + +diff --git a/nptl/pthread_once.c b/nptl/pthread_once.c +index 595bd7e298003e00..2afb79c01fe0a61e 100644 +--- a/nptl/pthread_once.c ++++ b/nptl/pthread_once.c +@@ -58,11 +58,13 @@ clear_once_control (void *arg) + initialization is interrupted, we then fork 2^30 times (30 bits of + once_control are used for the fork generation), and try to initialize + again, we can deadlock because we can't distinguish the in-progress and +- interrupted cases anymore. */ +-int +-__pthread_once (once_control, init_routine) +- pthread_once_t *once_control; +- void (*init_routine) (void); ++ interrupted cases anymore. ++ XXX: We split out this slow path because current compilers do not generate ++ as efficient code when the fast path in __pthread_once below is not in a ++ separate function. */ ++static int ++__attribute__ ((noinline)) ++__pthread_once_slow (pthread_once_t *once_control, void (*init_routine) (void)) + { + while (1) + { +@@ -72,7 +74,7 @@ __pthread_once (once_control, init_routine) + signals that initialization has finished, we need to see any + data modifications done during initialization. */ + val = *once_control; +- atomic_read_barrier(); ++ atomic_read_barrier (); + do + { + /* Check if the initialization has already been done. */ +@@ -130,5 +132,18 @@ __pthread_once (once_control, init_routine) + + return 0; + } ++ ++int ++__pthread_once (pthread_once_t *once_control, void (*init_routine) (void)) ++{ ++ /* Fast path. See __pthread_once_slow. */ ++ int val; ++ val = *once_control; ++ atomic_read_barrier (); ++ if (__glibc_likely ((val & __PTHREAD_ONCE_DONE) != 0)) ++ return 0; ++ else ++ return __pthread_once_slow (once_control, init_routine); ++} + weak_alias (__pthread_once, pthread_once) + hidden_def (__pthread_once) +diff --git a/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S b/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S +deleted file mode 100644 +index ca3b860a7f6f95ae..0000000000000000 +--- a/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S ++++ /dev/null +@@ -1,178 +0,0 @@ +-/* Copyright (C) 2002-2012 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. +- +- 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 +- <http://www.gnu.org/licenses/>. */ +- +-#include <unwindbuf.h> +-#include <sysdep.h> +-#include <kernel-features.h> +-#include <lowlevellock.h> +- +- +- .comm __fork_generation, 4, 4 +- +- .text +- +- +- .globl __pthread_once +- .type __pthread_once,@function +- .align 16 +- cfi_startproc +-__pthread_once: +- movl 4(%esp), %ecx +- testl $2, (%ecx) +- jz 1f +- xorl %eax, %eax +- ret +- +-1: pushl %ebx +- cfi_adjust_cfa_offset (4) +- cfi_rel_offset (3, 0) +- pushl %esi +- cfi_adjust_cfa_offset (4) +- cfi_rel_offset (6, 0) +- movl %ecx, %ebx +- xorl %esi, %esi +- +- /* Not yet initialized or initialization in progress. +- Get the fork generation counter now. */ +-6: movl (%ebx), %eax +-#ifdef PIC +- LOAD_PIC_REG(cx) +-#endif +- +-5: movl %eax, %edx +- +- testl $2, %eax +- jnz 4f +- +- andl $3, %edx +-#ifdef PIC +- orl __fork_generation@GOTOFF(%ecx), %edx +-#else +- orl __fork_generation, %edx +-#endif +- orl $1, %edx +- +- LOCK +- cmpxchgl %edx, (%ebx) +- jnz 5b +- +- /* Check whether another thread already runs the initializer. */ +- testl $1, %eax +- jz 3f /* No -> do it. */ +- +- /* Check whether the initializer execution was interrupted +- by a fork. */ +- xorl %edx, %eax +- testl $0xfffffffc, %eax +- jnz 3f /* Different for generation -> run initializer. */ +- +- /* Somebody else got here first. Wait. */ +-#ifdef __ASSUME_PRIVATE_FUTEX +- movl $FUTEX_WAIT|FUTEX_PRIVATE_FLAG, %ecx +-#else +-# if FUTEX_WAIT == 0 +- movl %gs:PRIVATE_FUTEX, %ecx +-# else +- movl $FUTEX_WAIT, %ecx +- orl %gs:PRIVATE_FUTEX, %ecx +-# endif +-#endif +- movl $SYS_futex, %eax +- ENTER_KERNEL +- jmp 6b +- +-3: /* Call the initializer function after setting up the +- cancellation handler. Note that it is not possible here +- to use the unwind-based cleanup handling. This would require +- that the user-provided function and all the code it calls +- is compiled with exceptions. Unfortunately this cannot be +- guaranteed. */ +- subl $UNWINDBUFSIZE+8, %esp +- cfi_adjust_cfa_offset (UNWINDBUFSIZE+8) +- movl %ecx, %ebx /* PIC register value. */ +- +- leal 8+UWJMPBUF(%esp), %eax +- movl $0, 4(%esp) +- movl %eax, (%esp) +- call __sigsetjmp@PLT +- testl %eax, %eax +- jne 7f +- +- leal 8(%esp), %eax +- call HIDDEN_JUMPTARGET(__pthread_register_cancel) +- +- /* Call the user-provided initialization function. */ +- call *24+UNWINDBUFSIZE(%esp) +- +- /* Pop the cleanup handler. */ +- leal 8(%esp), %eax +- call HIDDEN_JUMPTARGET(__pthread_unregister_cancel) +- addl $UNWINDBUFSIZE+8, %esp +- cfi_adjust_cfa_offset (-UNWINDBUFSIZE-8) +- +- /* Sucessful run of the initializer. Signal that we are done. */ +- movl 12(%esp), %ebx +- LOCK +- addl $1, (%ebx) +- +- /* Wake up all other threads. */ +- movl $0x7fffffff, %edx +-#ifdef __ASSUME_PRIVATE_FUTEX +- movl $FUTEX_WAKE|FUTEX_PRIVATE_FLAG, %ecx +-#else +- movl $FUTEX_WAKE, %ecx +- orl %gs:PRIVATE_FUTEX, %ecx +-#endif +- movl $SYS_futex, %eax +- ENTER_KERNEL +- +-4: popl %esi +- cfi_adjust_cfa_offset (-4) +- cfi_restore (6) +- popl %ebx +- cfi_adjust_cfa_offset (-4) +- cfi_restore (3) +- xorl %eax, %eax +- ret +- +-7: /* __sigsetjmp returned for the second time. */ +- movl 20+UNWINDBUFSIZE(%esp), %ebx +- cfi_adjust_cfa_offset (UNWINDBUFSIZE+16) +- cfi_offset (3, -8) +- cfi_offset (6, -12) +- movl $0, (%ebx) +- +- movl $0x7fffffff, %edx +-#ifdef __ASSUME_PRIVATE_FUTEX +- movl $FUTEX_WAKE|FUTEX_PRIVATE_FLAG, %ecx +-#else +- movl $FUTEX_WAKE, %ecx +- orl %gs:PRIVATE_FUTEX, %ecx +-#endif +- movl $SYS_futex, %eax +- ENTER_KERNEL +- +- leal 8(%esp), %eax +- call HIDDEN_JUMPTARGET (__pthread_unwind_next) +- /* NOTREACHED */ +- hlt +- cfi_endproc +- .size __pthread_once,.-__pthread_once +- +-hidden_def (__pthread_once) +-strong_alias (__pthread_once, pthread_once) +diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S +deleted file mode 100644 +index 7f5c0810fa16b987..0000000000000000 +--- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S ++++ /dev/null +@@ -1,193 +0,0 @@ +-/* Copyright (C) 2002-2012 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. +- +- 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 +- <http://www.gnu.org/licenses/>. */ +- +-#include <sysdep.h> +-#include <kernel-features.h> +-#include <tcb-offsets.h> +-#include <lowlevellock.h> +- +- +- .comm __fork_generation, 4, 4 +- +- .text +- +- +- .globl __pthread_once +- .type __pthread_once,@function +- .align 16 +-__pthread_once: +-.LSTARTCODE: +- cfi_startproc +-#ifdef SHARED +- cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect, +- DW.ref.__gcc_personality_v0) +- cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART) +-#else +- cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0) +- cfi_lsda(DW_EH_PE_udata4, .LexceptSTART) +-#endif +- testl $2, (%rdi) +- jz 1f +- xorl %eax, %eax +- retq +- +- /* Preserve the function pointer. */ +-1: pushq %rsi +- cfi_adjust_cfa_offset(8) +- xorq %r10, %r10 +- +- /* Not yet initialized or initialization in progress. +- Get the fork generation counter now. */ +-6: movl (%rdi), %eax +- +-5: movl %eax, %edx +- +- testl $2, %eax +- jnz 4f +- +- andl $3, %edx +- orl __fork_generation(%rip), %edx +- orl $1, %edx +- +- LOCK +- cmpxchgl %edx, (%rdi) +- jnz 5b +- +- /* Check whether another thread already runs the initializer. */ +- testl $1, %eax +- jz 3f /* No -> do it. */ +- +- /* Check whether the initializer execution was interrupted +- by a fork. */ +- xorl %edx, %eax +- testl $0xfffffffc, %eax +- jnz 3f /* Different for generation -> run initializer. */ +- +- /* Somebody else got here first. Wait. */ +-#ifdef __ASSUME_PRIVATE_FUTEX +- movl $FUTEX_WAIT|FUTEX_PRIVATE_FLAG, %esi +-#else +-# if FUTEX_WAIT == 0 +- movl %fs:PRIVATE_FUTEX, %esi +-# else +- movl $FUTEX_WAIT, %esi +- orl %fs:PRIVATE_FUTEX, %esi +-# endif +-#endif +- movl $SYS_futex, %eax +- syscall +- jmp 6b +- +- /* Preserve the pointer to the control variable. */ +-3: pushq %rdi +- cfi_adjust_cfa_offset(8) +- pushq %rdi +- cfi_adjust_cfa_offset(8) +- +-.LcleanupSTART: +- callq *16(%rsp) +-.LcleanupEND: +- +- /* Get the control variable address back. */ +- popq %rdi +- cfi_adjust_cfa_offset(-8) +- +- /* Sucessful run of the initializer. Signal that we are done. */ +- LOCK +- incl (%rdi) +- +- addq $8, %rsp +- cfi_adjust_cfa_offset(-8) +- +- /* Wake up all other threads. */ +- movl $0x7fffffff, %edx +-#ifdef __ASSUME_PRIVATE_FUTEX +- movl $FUTEX_WAKE|FUTEX_PRIVATE_FLAG, %esi +-#else +- movl $FUTEX_WAKE, %esi +- orl %fs:PRIVATE_FUTEX, %esi +-#endif +- movl $SYS_futex, %eax +- syscall +- +-4: addq $8, %rsp +- cfi_adjust_cfa_offset(-8) +- xorl %eax, %eax +- retq +- .size __pthread_once,.-__pthread_once +- +- +-hidden_def (__pthread_once) +-strong_alias (__pthread_once, pthread_once) +- +- +- .type clear_once_control,@function +- .align 16 +-clear_once_control: +- cfi_adjust_cfa_offset(3 * 8) +- movq (%rsp), %rdi +- movq %rax, %r8 +- movl $0, (%rdi) +- +- movl $0x7fffffff, %edx +-#ifdef __ASSUME_PRIVATE_FUTEX +- movl $FUTEX_WAKE|FUTEX_PRIVATE_FLAG, %esi +-#else +- movl $FUTEX_WAKE, %esi +- orl %fs:PRIVATE_FUTEX, %esi +-#endif +- movl $SYS_futex, %eax +- syscall +- +- movq %r8, %rdi +-.LcallUR: +- call _Unwind_Resume@PLT +- hlt +-.LENDCODE: +- cfi_endproc +- .size clear_once_control,.-clear_once_control +- +- +- .section .gcc_except_table,"a",@progbits +-.LexceptSTART: +- .byte DW_EH_PE_omit # @LPStart format +- .byte DW_EH_PE_omit # @TType format +- .byte DW_EH_PE_uleb128 # call-site format +- .uleb128 .Lcstend-.Lcstbegin +-.Lcstbegin: +- .uleb128 .LcleanupSTART-.LSTARTCODE +- .uleb128 .LcleanupEND-.LcleanupSTART +- .uleb128 clear_once_control-.LSTARTCODE +- .uleb128 0 +- .uleb128 .LcallUR-.LSTARTCODE +- .uleb128 .LENDCODE-.LcallUR +- .uleb128 0 +- .uleb128 0 +-.Lcstend: +- +- +-#ifdef SHARED +- .hidden DW.ref.__gcc_personality_v0 +- .weak DW.ref.__gcc_personality_v0 +- .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits +- .align LP_SIZE +- .type DW.ref.__gcc_personality_v0, @object +- .size DW.ref.__gcc_personality_v0, LP_SIZE +-DW.ref.__gcc_personality_v0: +- ASM_ADDR __gcc_personality_v0 +-#endif diff --git a/SOURCES/glibc-rh1163509-5.patch b/SOURCES/glibc-rh1163509-5.patch new file mode 100644 index 0000000..cc314ec --- /dev/null +++ b/SOURCES/glibc-rh1163509-5.patch @@ -0,0 +1,720 @@ +This patch removes the following remaining architecture specific +pthread_once implementations: + +- alpha, hppa, sh: Not used in RHEL. + +- s390: Was first moved, then renamed upstream by the following commits: + + commit 52ae23b4bfa09fa1f42e3f659aaa057d1176d06b + Author: Roland McGrath <roland@hack.frob.com> + Date: Thu Jun 26 09:31:11 2014 -0700 + + Move remaining S390 code out of nptl/. + + commit bc89c0fc70ba952f78fc27fc261ec209be0a6732 + Author: Torvald Riegel <triegel@redhat.com> + Date: Mon Dec 8 18:32:14 2014 +0100 + + Remove custom pthread_once implementation on s390. + +- powerpc: Was removed upstream by the following commit: + + commit 75ffb047f6ee2a545da8cf69dba9a979ca6271ce + Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com> + Date: Sun Apr 13 18:13:42 2014 -0500 + + PowerPC: Sync pthread_once with default implementation + +diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c b/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c +deleted file mode 100644 +index 52ab53f0a912d107..0000000000000000 +--- a/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c ++++ /dev/null +@@ -1,110 +0,0 @@ +-/* Copyright (C) 2003-2012 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003. +- +- 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 +- <http://www.gnu.org/licenses/>. */ +- +-#include "pthreadP.h" +-#include <lowlevellock.h> +- +- +-unsigned long int __fork_generation attribute_hidden; +- +- +-static void +-clear_once_control (void *arg) +-{ +- pthread_once_t *once_control = (pthread_once_t *) arg; +- +- __asm __volatile (__lll_rel_instr); +- *once_control = 0; +- lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +-} +- +- +-int +-__pthread_once (pthread_once_t *once_control, void (*init_routine) (void)) +-{ +- for (;;) +- { +- int oldval; +- int newval; +- int tmp; +- +- /* Pseudo code: +- newval = __fork_generation | 1; +- oldval = *once_control; +- if ((oldval & 2) == 0) +- *once_control = newval; +- Do this atomically with an acquire barrier. +- */ +- newval = __fork_generation | 1; +- __asm __volatile ("1: lwarx %0,0,%3" MUTEX_HINT_ACQ "\n" +- " andi. %1,%0,2\n" +- " bne 2f\n" +- " stwcx. %4,0,%3\n" +- " bne 1b\n" +- "2: " __lll_acq_instr +- : "=&r" (oldval), "=&r" (tmp), "=m" (*once_control) +- : "r" (once_control), "r" (newval), "m" (*once_control) +- : "cr0"); +- +- /* Check if the initializer has already been done. */ +- if ((oldval & 2) != 0) +- return 0; +- +- /* Check if another thread already runs the initializer. */ +- if ((oldval & 1) == 0) +- break; +- +- /* Check whether the initializer execution was interrupted by a fork. */ +- if (oldval != newval) +- break; +- +- /* Same generation, some other thread was faster. Wait. */ +- lll_futex_wait (once_control, oldval, LLL_PRIVATE); +- } +- +- +- /* This thread is the first here. Do the initialization. +- Register a cleanup handler so that in case the thread gets +- interrupted the initialization can be restarted. */ +- pthread_cleanup_push (clear_once_control, once_control); +- +- init_routine (); +- +- pthread_cleanup_pop (0); +- +- +- /* Add one to *once_control to take the bottom 2 bits from 01 to 10. +- A release barrier is needed to ensure memory written by init_routine +- is seen in other threads before *once_control changes. */ +- int tmp; +- __asm __volatile (__lll_rel_instr "\n" +- "1: lwarx %0,0,%2" MUTEX_HINT_REL "\n" +- " addi %0,%0,1\n" +- " stwcx. %0,0,%2\n" +- " bne- 1b" +- : "=&b" (tmp), "=m" (*once_control) +- : "r" (once_control), "m" (*once_control) +- : "cr0"); +- +- /* Wake up all other threads. */ +- lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +- +- return 0; +-} +-weak_alias (__pthread_once, pthread_once) +-hidden_def (__pthread_once) +diff --git a/nptl/sysdeps/unix/sysv/linux/s390/pthread_once.c b/nptl/sysdeps/unix/sysv/linux/s390/pthread_once.c +deleted file mode 100644 +index 4bce7fec13ea3bb2..0000000000000000 +--- a/nptl/sysdeps/unix/sysv/linux/s390/pthread_once.c ++++ /dev/null +@@ -1,108 +0,0 @@ +-/* Copyright (C) 2003-2012 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003. +- +- 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 +- <http://www.gnu.org/licenses/>. */ +- +-#include "pthreadP.h" +-#include <lowlevellock.h> +- +- +-unsigned long int __fork_generation attribute_hidden; +- +- +-static void +-clear_once_control (void *arg) +-{ +- pthread_once_t *once_control = (pthread_once_t *) arg; +- +- *once_control = 0; +- lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +-} +- +- +-int +-__pthread_once (pthread_once_t *once_control, void (*init_routine) (void)) +-{ +- while (1) +- { +- int oldval; +- int newval; +- +- /* Pseudo code: +- oldval = *once_control; +- if ((oldval & 2) == 0) +- { +- newval = (oldval & 3) | __fork_generation | 1; +- *once_control = newval; +- } +- Do this atomically. */ +- __asm __volatile (" l %1,%0\n" +- "0: lhi %2,2\n" +- " tml %1,2\n" +- " jnz 1f\n" +- " nr %2,%1\n" +- " ahi %2,1\n" +- " o %2,%3\n" +- " cs %1,%2,%0\n" +- " jl 0b\n" +- "1:" +- : "=Q" (*once_control), "=&d" (oldval), "=&d" (newval) +- : "m" (__fork_generation), "m" (*once_control) +- : "cc" ); +- /* Check if the initialized has already been done. */ +- if ((oldval & 2) != 0) +- break; +- /* Check if another thread already runs the initializer. */ +- if ((oldval & 1) != 0) +- { +- /* Check whether the initializer execution was interrupted +- by a fork. */ +- if (((oldval ^ newval) & -4) == 0) +- { +- /* Same generation, some other thread was faster. Wait. */ +- lll_futex_wait (once_control, newval, LLL_PRIVATE); +- continue; +- } +- } +- +- /* This thread is the first here. Do the initialization. +- Register a cleanup handler so that in case the thread gets +- interrupted the initialization can be restarted. */ +- pthread_cleanup_push (clear_once_control, once_control); +- +- init_routine (); +- +- pthread_cleanup_pop (0); +- +- +- /* Add one to *once_control. */ +- __asm __volatile (" l %1,%0\n" +- "0: lr %2,%1\n" +- " ahi %2,1\n" +- " cs %1,%2,%0\n" +- " jl 0b\n" +- : "=Q" (*once_control), "=&d" (oldval), "=&d" (newval) +- : "m" (*once_control) : "cc" ); +- +- /* Wake up all other threads. */ +- lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +- break; +- } +- +- return 0; +-} +-weak_alias (__pthread_once, pthread_once) +-hidden_def (__pthread_once) +diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S +deleted file mode 100644 +index 62b92d8b103ded65..0000000000000000 +--- a/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S ++++ /dev/null +@@ -1,257 +0,0 @@ +-/* Copyright (C) 2003-2012 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 +- <http://www.gnu.org/licenses/>. */ +- +-#include <unwindbuf.h> +-#include <sysdep.h> +-#include <kernel-features.h> +-#include <lowlevellock.h> +-#include "lowlevel-atomic.h" +- +- +- .comm __fork_generation, 4, 4 +- +- .text +- .globl __pthread_once +- .type __pthread_once,@function +- .align 5 +- cfi_startproc +-__pthread_once: +- mov.l @r4, r0 +- tst #2, r0 +- bt 1f +- rts +- mov #0, r0 +- +-1: +- mov.l r12, @-r15 +- cfi_adjust_cfa_offset (4) +- cfi_rel_offset (r12, 0) +- mov.l r9, @-r15 +- cfi_adjust_cfa_offset (4) +- cfi_rel_offset (r9, 0) +- mov.l r8, @-r15 +- cfi_adjust_cfa_offset (4) +- cfi_rel_offset (r8, 0) +- sts.l pr, @-r15 +- cfi_adjust_cfa_offset (4) +- cfi_rel_offset (pr, 0) +- mov r5, r8 +- mov r4, r9 +- +- /* Not yet initialized or initialization in progress. +- Get the fork generation counter now. */ +-6: +- mov.l @r4, r1 +- mova .Lgot, r0 +- mov.l .Lgot, r12 +- add r0, r12 +- +-5: +- mov r1, r0 +- +- tst #2, r0 +- bf 4f +- +- and #3, r0 +- mov.l .Lfgen, r2 +-#ifdef PIC +- add r12, r2 +-#endif +- mov.l @r2, r3 +- or r3, r0 +- or #1, r0 +- mov r0, r3 +- mov r1, r5 +- +- CMPXCHG (r5, @r4, r3, r2) +- bf 5b +- +- /* Check whether another thread already runs the initializer. */ +- mov r2, r0 +- tst #1, r0 +- bt 3f /* No -> do it. */ +- +- /* Check whether the initializer execution was interrupted +- by a fork. */ +- xor r3, r0 +- mov #-4, r1 /* -4 = 0xfffffffc */ +- tst r1, r0 +- bf 3f /* Different for generation -> run initializer. */ +- +- /* Somebody else got here first. Wait. */ +-#ifdef __ASSUME_PRIVATE_FUTEX +- mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAIT), r5 +- extu.b r5, r5 +-#else +- stc gbr, r1 +- mov.w .Lpfoff, r2 +- add r2, r1 +- mov.l @r1, r5 +-# if FUTEX_WAIT != 0 +- mov #FUTEX_WAIT, r0 +- or r0, r5 +-# endif +-#endif +- mov r3, r6 +- mov #0, r7 +- mov #SYS_futex, r3 +- extu.b r3, r3 +- trapa #0x14 +- SYSCALL_INST_PAD +- bra 6b +- nop +- +- .align 2 +-.Lgot: +- .long _GLOBAL_OFFSET_TABLE_ +-#ifdef PIC +-.Lfgen: +- .long __fork_generation@GOTOFF +-#else +-.Lfgen: +- .long __fork_generation +-#endif +- +-3: +- /* Call the initializer function after setting up the +- cancellation handler. Note that it is not possible here +- to use the unwind-based cleanup handling. This would require +- that the user-provided function and all the code it calls +- is compiled with exceptions. Unfortunately this cannot be +- guaranteed. */ +- add #-UNWINDBUFSIZE, r15 +- cfi_adjust_cfa_offset (UNWINDBUFSIZE) +- +- mov.l .Lsigsetjmp, r1 +- mov #UWJMPBUF, r4 +- add r15, r4 +- bsrf r1 +- mov #0, r5 +-.Lsigsetjmp0: +- tst r0, r0 +- bf 7f +- +- mov.l .Lcpush, r1 +- bsrf r1 +- mov r15, r4 +-.Lcpush0: +- +- /* Call the user-provided initialization function. */ +- jsr @r8 +- nop +- +- /* Pop the cleanup handler. */ +- mov.l .Lcpop, r1 +- bsrf r1 +- mov r15, r4 +-.Lcpop0: +- +- add #UNWINDBUFSIZE, r15 +- cfi_adjust_cfa_offset (-UNWINDBUFSIZE) +- +- /* Sucessful run of the initializer. Signal that we are done. */ +- INC (@r9, r2) +- /* Wake up all other threads. */ +- mov r9, r4 +-#ifdef __ASSUME_PRIVATE_FUTEX +- mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAKE), r5 +- extu.b r5, r5 +-#else +- stc gbr, r1 +- mov.w .Lpfoff, r2 +- add r2, r1 +- mov.l @r1, r5 +- mov #FUTEX_WAKE, r0 +- or r0, r5 +-#endif +- mov #-1, r6 +- shlr r6 /* r6 = 0x7fffffff */ +- mov #0, r7 +- mov #SYS_futex, r3 +- extu.b r3, r3 +- trapa #0x14 +- SYSCALL_INST_PAD +- +-4: +- lds.l @r15+, pr +- cfi_adjust_cfa_offset (-4) +- cfi_restore (pr) +- mov.l @r15+, r8 +- cfi_adjust_cfa_offset (-4) +- cfi_restore (r8) +- mov.l @r15+, r9 +- cfi_adjust_cfa_offset (-4) +- cfi_restore (r9) +- mov.l @r15+, r12 +- cfi_adjust_cfa_offset (-4) +- cfi_restore (r12) +- rts +- mov #0, r0 +- +-7: +- /* __sigsetjmp returned for the second time. */ +- cfi_adjust_cfa_offset (UNWINDBUFSIZE+16) +- cfi_offset (r12, -4) +- cfi_offset (r9, -8) +- cfi_offset (r8, -12) +- cfi_offset (pr, -16) +- mov #0, r7 +- mov.l r7, @r9 +- mov r9, r4 +-#ifdef __ASSUME_PRIVATE_FUTEX +- mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAKE), r5 +-#else +- stc gbr, r1 +- mov.w .Lpfoff, r2 +- add r2, r1 +- mov.l @r1, r5 +- mov #FUTEX_WAKE, r0 +- or r0, r5 +-#endif +- extu.b r5, r5 +- mov #-1, r6 +- shlr r6 /* r6 = 0x7fffffff */ +- mov #SYS_futex, r3 +- extu.b r3, r3 +- trapa #0x14 +- SYSCALL_INST_PAD +- +- mov.l .Lunext, r1 +- bsrf r1 +- mov r15, r4 +-.Lunext0: +- /* NOTREACHED */ +- sleep +- cfi_endproc +- +-#ifndef __ASSUME_PRIVATE_FUTEX +-.Lpfoff: +- .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +-#endif +- .align 2 +-.Lsigsetjmp: +- .long __sigsetjmp@PLT-(.Lsigsetjmp0-.) +-.Lcpush: +- .long HIDDEN_JUMPTARGET(__pthread_register_cancel)-.Lcpush0 +-.Lcpop: +- .long HIDDEN_JUMPTARGET(__pthread_unregister_cancel)-.Lcpop0 +-.Lunext: +- .long HIDDEN_JUMPTARGET(__pthread_unwind_next)-.Lunext0 +- .size __pthread_once,.-__pthread_once +- +-hidden_def (__pthread_once) +-strong_alias (__pthread_once, pthread_once) +diff --git a/sysdeps/unix/sysv/linux/alpha/nptl/pthread_once.c b/sysdeps/unix/sysv/linux/alpha/nptl/pthread_once.c +deleted file mode 100644 +index c342e0a7a0965086..0000000000000000 +--- a/sysdeps/unix/sysv/linux/alpha/nptl/pthread_once.c ++++ /dev/null +@@ -1,95 +0,0 @@ +-/* Copyright (C) 2003-2012 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 +- <http://www.gnu.org/licenses/>. */ +- +-#include "pthreadP.h" +-#include <lowlevellock.h> +- +- +-unsigned long int __fork_generation attribute_hidden; +- +-static void +-clear_once_control (void *arg) +-{ +- pthread_once_t *once_control = (pthread_once_t *) arg; +- +- *once_control = 0; +- lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +-} +- +-int +-__pthread_once (pthread_once_t *once_control, void (*init_routine) (void)) +-{ +- for (;;) +- { +- int oldval; +- int newval; +- int tmp; +- +- /* Pseudo code: +- newval = __fork_generation | 1; +- oldval = *once_control; +- if ((oldval & 2) == 0) +- *once_control = newval; +- Do this atomically. +- */ +- newval = __fork_generation | 1; +- __asm __volatile ( +- "1: ldl_l %0, %2\n" +- " and %0, 2, %1\n" +- " bne %1, 2f\n" +- " mov %3, %1\n" +- " stl_c %1, %2\n" +- " beq %1, 1b\n" +- "2: mb" +- : "=&r" (oldval), "=&r" (tmp), "=m" (*once_control) +- : "r" (newval), "m" (*once_control)); +- +- /* Check if the initializer has already been done. */ +- if ((oldval & 2) != 0) +- return 0; +- +- /* Check if another thread already runs the initializer. */ +- if ((oldval & 1) == 0) +- break; +- +- /* Check whether the initializer execution was interrupted by a fork. */ +- if (oldval != newval) +- break; +- +- /* Same generation, some other thread was faster. Wait. */ +- lll_futex_wait (once_control, oldval, LLL_PRIVATE); +- } +- +- /* This thread is the first here. Do the initialization. +- Register a cleanup handler so that in case the thread gets +- interrupted the initialization can be restarted. */ +- pthread_cleanup_push (clear_once_control, once_control); +- +- init_routine (); +- +- pthread_cleanup_pop (0); +- +- /* Add one to *once_control to take the bottom 2 bits from 01 to 10. */ +- atomic_increment (once_control); +- +- /* Wake up all other threads. */ +- lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +- +- return 0; +-} +-weak_alias (__pthread_once, pthread_once) +-hidden_def (__pthread_once) +diff --git a/sysdeps/unix/sysv/linux/hppa/nptl/pthread_once.c b/sysdeps/unix/sysv/linux/hppa/nptl/pthread_once.c +deleted file mode 100644 +index b920ebb22c10a569..0000000000000000 +--- a/sysdeps/unix/sysv/linux/hppa/nptl/pthread_once.c ++++ /dev/null +@@ -1,93 +0,0 @@ +-/* Copyright (C) 2003-2012 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. +- +- 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 +- <http://www.gnu.org/licenses/>. */ +- +-#include "pthreadP.h" +-#include <lowlevellock.h> +- +- +-unsigned long int __fork_generation attribute_hidden; +- +- +-static void +-clear_once_control (void *arg) +-{ +- pthread_once_t *once_control = (pthread_once_t *) arg; +- +- *once_control = 0; +- lll_private_futex_wake (once_control, INT_MAX); +-} +- +- +-int +-__pthread_once (once_control, init_routine) +- pthread_once_t *once_control; +- void (*init_routine) (void); +-{ +- while (1) +- { +- int oldval, val, newval; +- +- val = *once_control; +- do +- { +- /* Check if the initialized has already been done. */ +- if ((val & 2) != 0) +- return 0; +- +- oldval = val; +- newval = (oldval & 3) | __fork_generation | 1; +- val = atomic_compare_and_exchange_val_acq (once_control, newval, +- oldval); +- } +- while (__builtin_expect (val != oldval, 0)); +- +- /* Check if another thread already runs the initializer. */ +- if ((oldval & 1) != 0) +- { +- /* Check whether the initializer execution was interrupted +- by a fork. */ +- if (((oldval ^ newval) & -4) == 0) +- { +- /* Same generation, some other thread was faster. Wait. */ +- lll_private_futex_wait (once_control, newval); +- continue; +- } +- } +- +- /* This thread is the first here. Do the initialization. +- Register a cleanup handler so that in case the thread gets +- interrupted the initialization can be restarted. */ +- pthread_cleanup_push (clear_once_control, once_control); +- +- init_routine (); +- +- pthread_cleanup_pop (0); +- +- +- /* Add one to *once_control. */ +- atomic_increment (once_control); +- +- /* Wake up all other threads. */ +- lll_private_futex_wake (once_control, INT_MAX); +- break; +- } +- +- return 0; +-} +-weak_alias (__pthread_once, pthread_once) +-hidden_def (__pthread_once) diff --git a/SOURCES/glibc-rh1256317-armhfp-build-issue.patch b/SOURCES/glibc-rh1256317-armhfp-build-issue.patch deleted file mode 100644 index aa6e7fe..0000000 --- a/SOURCES/glibc-rh1256317-armhfp-build-issue.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/sysdeps/unix/arm/sysdep.S 2016-11-05 11:44:45.561945344 +0100 -+++ b/sysdeps/unix/arm/sysdep.S 2016-11-05 11:44:19.542069815 +0100 -@@ -37,7 +37,7 @@ - moveq r0, $EAGAIN /* Yes; translate it to EAGAIN. */ - #endif - --#ifndef IS_IN_rtld -+#if !IS_IN (rtld) - mov ip, lr - cfi_register (lr, ip) - mov r1, r0 diff --git a/SOURCES/glibc-rh1418978-1.patch b/SOURCES/glibc-rh1418978-1.patch index c57c652..466a62e 100644 --- a/SOURCES/glibc-rh1418978-1.patch +++ b/SOURCES/glibc-rh1418978-1.patch @@ -1,19 +1,25 @@ This patch creates the contents of the support/ directory up to this upstream commit on the master branch: -commit 401311cfba71b61d93d23aa17e5c9ac5fb047d48 -Author: Florian Weimer <fweimer@redhat.com> -Date: Mon Jan 8 14:33:17 2018 +0100 +commit 00c86a37d1b63044e3169d1f2ebec23447c73f79 +Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> +Date: Wed Nov 7 11:09:02 2018 -0200 - resolv: Support binary labels in test framework + support: Fix printf format for TEST_COMPARE_STRING - The old implementation based on hsearch_r used an ad-hoc C string - encoding and produced an incorrect format on the wire for domain - names which contained bytes which needed escaping when printed. + Fix the following on 32 bits targets: - This commit switches to ns_name_pton for the wire format conversion - (now that we have separate tests for it) and uses a tsearch tree - with a suitable comparison function to locate compression targets. + support_test_compare_string.c: In function ‘support_test_compare_string’: + support_test_compare_string.c:80:37: error: format ‘%lu’ expects argument of + type ‘long unsigned int’, but argument 2 has type ‘size_t’ {aka ‘unsigned int’} + [-Werror=format=] + printf (" string length: %lu bytes\n", left_length); + ~~^ ~~~~~~~~~~~ + %u + Checked on arm-linux-gnueabihf. + + * support/support_test_compare_string.c + (support_test_compare_string): Fix printf format. diff --git a/scripts/backport-support.sh b/scripts/backport-support.sh new file mode 100644 @@ -133,10 +139,10 @@ index 0000000000..4057e42d3c +command_$command diff --git a/support/Makefile b/support/Makefile new file mode 100644 -index 0000000000..1bda81e55e +index 0000000000..2b663fbbfa --- /dev/null +++ b/support/Makefile -@@ -0,0 +1,171 @@ +@@ -0,0 +1,219 @@ +# Makefile for support library, used only at build and test time +# Copyright (C) 2016-2018 Free Software Foundation, Inc. +# This file is part of the GNU C Library. @@ -164,6 +170,7 @@ index 0000000000..1bda81e55e +extra-libs-noinstall := $(extra-libs) + +libsupport-routines = \ ++ blob_repeat \ + check \ + check_addrinfo \ + check_dns_packet \ @@ -182,6 +189,8 @@ index 0000000000..1bda81e55e + support_capture_subprocess \ + support_capture_subprocess_check \ + support_chroot \ ++ support_copy_file_range \ ++ support_descriptor_supports_holes \ + support_enter_mount_namespace \ + support_enter_network_namespace \ + support_format_address_family \ @@ -191,10 +200,15 @@ index 0000000000..1bda81e55e + support_format_hostent \ + support_format_netent \ + support_isolate_in_subprocess \ ++ support_openpty \ ++ support_paths \ ++ support_quote_blob \ + support_record_failure \ + support_run_diff \ + support_shared_allocate \ ++ support_test_compare_blob \ + support_test_compare_failure \ ++ support_test_compare_string \ + support_write_file_string \ + support_test_main \ + support_test_verify_impl \ @@ -208,6 +222,7 @@ index 0000000000..1bda81e55e + xchroot \ + xclose \ + xconnect \ ++ xcopy_file_range \ + xdlfcn \ + xdup2 \ + xfclose \ @@ -220,6 +235,7 @@ index 0000000000..1bda81e55e + xmalloc \ + xmemstream \ + xmkdir \ ++ xmkdirp \ + xmmap \ + xmprotect \ + xmunmap \ @@ -234,6 +250,9 @@ index 0000000000..1bda81e55e + xpthread_barrier_destroy \ + xpthread_barrier_init \ + xpthread_barrier_wait \ ++ xpthread_barrierattr_destroy \ ++ xpthread_barrierattr_init \ ++ xpthread_barrierattr_setpshared \ + xpthread_cancel \ + xpthread_check_return \ + xpthread_cond_wait \ @@ -272,6 +291,7 @@ index 0000000000..1bda81e55e + xsocket \ + xstrdup \ + xstrndup \ ++ xsymlink \ + xsysconf \ + xunlink \ + xwaitpid \ @@ -284,13 +304,47 @@ index 0000000000..1bda81e55e +libsupport-inhibit-o += .o +endif + ++CFLAGS-support_paths.c = \ ++ -DSRCDIR_PATH=\"`cd .. ; pwd`\" \ ++ -DOBJDIR_PATH=\"`cd $(objpfx)/..; pwd`\" \ ++ -DOBJDIR_ELF_LDSO_PATH=\"`cd $(objpfx)/..; pwd`/elf/$(rtld-installed-name)\" \ ++ -DINSTDIR_PATH=\"$(prefix)\" \ ++ -DLIBDIR_PATH=\"$(libdir)\" ++ ++ifeq (,$(CXX)) ++LINKS_DSO_PROGRAM = links-dso-program-c ++else ++LINKS_DSO_PROGRAM = links-dso-program ++LDLIBS-links-dso-program = -lstdc++ -lgcc -lgcc_s $(libunwind) ++endif ++ ++LDLIBS-test-container = $(libsupport) ++ ++others += test-container ++others-noinstall += test-container ++ ++others += shell-container echo-container true-container ++others-noinstall += shell-container echo-container true-container ++ ++others += $(LINKS_DSO_PROGRAM) ++others-noinstall += $(LINKS_DSO_PROGRAM) ++ ++$(objpfx)test-container : $(libsupport) ++$(objpfx)shell-container : $(libsupport) ++$(objpfx)echo-container : $(libsupport) ++$(objpfx)true-container : $(libsupport) ++ +tests = \ + README-testing \ + tst-support-namespace \ ++ tst-support_blob_repeat \ + tst-support_capture_subprocess \ + tst-support_format_dns_packet \ ++ tst-support_quote_blob \ + tst-support_record_failure \ + tst-test_compare \ ++ tst-test_compare_blob \ ++ tst-test_compare_string \ + tst-xreadlink \ + +ifeq ($(run-built-tests),yes) @@ -368,6 +422,344 @@ index 0000000000..9d289c3020 +/* This file references do_test above and contains the definition of + the main function. */ +#include <support/test-driver.c> +diff --git a/support/blob_repeat.c b/support/blob_repeat.c +new file mode 100644 +index 0000000000..16c1e448b9 +--- /dev/null ++++ b/support/blob_repeat.c +@@ -0,0 +1,282 @@ ++/* Repeating a memory blob, with alias mapping optimization. ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <errno.h> ++#include <fcntl.h> ++#include <stdbool.h> ++#include <stdlib.h> ++#include <string.h> ++#include <support/blob_repeat.h> ++#include <support/check.h> ++#include <support/test-driver.h> ++#include <support/support.h> ++#include <support/xunistd.h> ++#include <sys/mman.h> ++#include <unistd.h> ++#include <wchar.h> ++ ++/* Small allocations should use malloc directly instead of the mmap ++ optimization because mappings carry a lot of overhead. */ ++static const size_t maximum_small_size = 4 * 1024 * 1024; ++ ++/* Internal helper for fill. */ ++static void ++fill0 (char *target, const char *element, size_t element_size, ++ size_t count) ++{ ++ while (count > 0) ++ { ++ memcpy (target, element, element_size); ++ target += element_size; ++ --count; ++ } ++} ++ ++/* Fill the buffer at TARGET with COUNT copies of the ELEMENT_SIZE ++ bytes starting at ELEMENT. */ ++static void ++fill (char *target, const char *element, size_t element_size, ++ size_t count) ++{ ++ if (element_size == 0 || count == 0) ++ return; ++ else if (element_size == 1) ++ memset (target, element[0], count); ++ else if (element_size == sizeof (wchar_t)) ++ { ++ wchar_t wc; ++ memcpy (&wc, element, sizeof (wc)); ++ wmemset ((wchar_t *) target, wc, count); ++ } ++ else if (element_size < 1024 && count > 4096) ++ { ++ /* Use larger copies for really small element sizes. */ ++ char buffer[8192]; ++ size_t buffer_count = sizeof (buffer) / element_size; ++ fill0 (buffer, element, element_size, buffer_count); ++ while (count > 0) ++ { ++ size_t copy_count = buffer_count; ++ if (copy_count > count) ++ copy_count = count; ++ size_t copy_bytes = copy_count * element_size; ++ memcpy (target, buffer, copy_bytes); ++ target += copy_bytes; ++ count -= copy_count; ++ } ++ } ++ else ++ fill0 (target, element, element_size, count); ++} ++ ++/* Use malloc instead of mmap for small allocations and unusual size ++ combinations. */ ++static struct support_blob_repeat ++allocate_malloc (size_t total_size, const void *element, size_t element_size, ++ size_t count) ++{ ++ void *buffer = malloc (total_size); ++ if (buffer == NULL) ++ return (struct support_blob_repeat) { 0 }; ++ fill (buffer, element, element_size, count); ++ return (struct support_blob_repeat) ++ { ++ .start = buffer, ++ .size = total_size, ++ .use_malloc = true ++ }; ++} ++ ++/* Return the least common multiple of PAGE_SIZE and ELEMENT_SIZE, ++ avoiding overflow. This assumes that PAGE_SIZE is a power of ++ two. */ ++static size_t ++minimum_stride_size (size_t page_size, size_t element_size) ++{ ++ TEST_VERIFY_EXIT (page_size > 0); ++ TEST_VERIFY_EXIT (element_size > 0); ++ ++ /* Compute the number of trailing zeros common to both sizes. */ ++ unsigned int common_zeros = __builtin_ctzll (page_size | element_size); ++ ++ /* In the product, this power of two appears twice, but in the least ++ common multiple, it appears only once. Therefore, shift one ++ factor. */ ++ size_t multiple; ++ if (__builtin_mul_overflow (page_size >> common_zeros, element_size, ++ &multiple)) ++ return 0; ++ return multiple; ++} ++ ++/* Allocations larger than maximum_small_size potentially use mmap ++ with alias mappings. */ ++static struct support_blob_repeat ++allocate_big (size_t total_size, const void *element, size_t element_size, ++ size_t count) ++{ ++ unsigned long page_size = xsysconf (_SC_PAGESIZE); ++ size_t stride_size = minimum_stride_size (page_size, element_size); ++ if (stride_size == 0) ++ { ++ errno = EOVERFLOW; ++ return (struct support_blob_repeat) { 0 }; ++ } ++ ++ /* Ensure that the stride size is at least maximum_small_size. This ++ is necessary to reduce the number of distinct mappings. */ ++ if (stride_size < maximum_small_size) ++ stride_size ++ = ((maximum_small_size + stride_size - 1) / stride_size) * stride_size; ++ ++ if (stride_size > total_size) ++ /* The mmap optimization would not save anything. */ ++ return allocate_malloc (total_size, element, element_size, count); ++ ++ /* Reserve the memory region. If we cannot create the mapping, ++ there is no reason to set up the backing file. */ ++ void *target = mmap (NULL, total_size, PROT_NONE, ++ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); ++ if (target == MAP_FAILED) ++ return (struct support_blob_repeat) { 0 }; ++ ++ /* Create the backing file for the repeated mapping. Call mkstemp ++ directly to remove the resources backing the temporary file ++ immediately, once support_blob_repeat_free is called. Using ++ create_temp_file would result in a warning during post-test ++ cleanup. */ ++ int fd; ++ { ++ char *temppath = xasprintf ("%s/support_blob_repeat-XXXXXX", test_dir); ++ fd = mkstemp (temppath); ++ if (fd < 0) ++ FAIL_EXIT1 ("mkstemp (\"%s\"): %m", temppath); ++ xunlink (temppath); ++ free (temppath); ++ } ++ ++ /* Make sure that there is backing storage, so that the fill ++ operation will not fault. */ ++ if (posix_fallocate (fd, 0, stride_size) != 0) ++ FAIL_EXIT1 ("posix_fallocate (%zu): %m", stride_size); ++ ++ /* The stride size must still be a multiple of the page size and ++ element size. */ ++ TEST_VERIFY_EXIT ((stride_size % page_size) == 0); ++ TEST_VERIFY_EXIT ((stride_size % element_size) == 0); ++ ++ /* Fill the backing store. */ ++ { ++ void *ptr = mmap (target, stride_size, PROT_READ | PROT_WRITE, ++ MAP_FIXED | MAP_FILE | MAP_SHARED, fd, 0); ++ if (ptr == MAP_FAILED) ++ { ++ int saved_errno = errno; ++ xmunmap (target, total_size); ++ xclose (fd); ++ errno = saved_errno; ++ return (struct support_blob_repeat) { 0 }; ++ } ++ if (ptr != target) ++ FAIL_EXIT1 ("mapping of %zu bytes moved from %p to %p", ++ stride_size, target, ptr); ++ ++ /* Write the repeating data. */ ++ fill (target, element, element_size, stride_size / element_size); ++ ++ /* Return to a PROT_NONE mapping, just to be on the safe side. */ ++ ptr = mmap (target, stride_size, PROT_NONE, ++ MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); ++ if (ptr == MAP_FAILED) ++ FAIL_EXIT1 ("Failed to reinstate PROT_NONE mapping: %m"); ++ if (ptr != target) ++ FAIL_EXIT1 ("PROT_NONE mapping of %zu bytes moved from %p to %p", ++ stride_size, target, ptr); ++ } ++ ++ /* Create the alias mappings. */ ++ { ++ size_t remaining_size = total_size; ++ char *current = target; ++ int flags = MAP_FIXED | MAP_FILE | MAP_PRIVATE; ++#ifdef MAP_NORESERVE ++ flags |= MAP_NORESERVE; ++#endif ++ while (remaining_size > 0) ++ { ++ size_t to_map = stride_size; ++ if (to_map > remaining_size) ++ to_map = remaining_size; ++ void *ptr = mmap (current, to_map, PROT_READ | PROT_WRITE, ++ flags, fd, 0); ++ if (ptr == MAP_FAILED) ++ { ++ int saved_errno = errno; ++ xmunmap (target, total_size); ++ xclose (fd); ++ errno = saved_errno; ++ return (struct support_blob_repeat) { 0 }; ++ } ++ if (ptr != current) ++ FAIL_EXIT1 ("MAP_PRIVATE mapping of %zu bytes moved from %p to %p", ++ to_map, target, ptr); ++ remaining_size -= to_map; ++ current += to_map; ++ } ++ } ++ ++ xclose (fd); ++ ++ return (struct support_blob_repeat) ++ { ++ .start = target, ++ .size = total_size, ++ .use_malloc = false ++ }; ++} ++ ++struct support_blob_repeat ++support_blob_repeat_allocate (const void *element, size_t element_size, ++ size_t count) ++{ ++ size_t total_size; ++ if (__builtin_mul_overflow (element_size, count, &total_size)) ++ { ++ errno = EOVERFLOW; ++ return (struct support_blob_repeat) { 0 }; ++ } ++ if (total_size <= maximum_small_size) ++ return allocate_malloc (total_size, element, element_size, count); ++ else ++ return allocate_big (total_size, element, element_size, count); ++} ++ ++void ++support_blob_repeat_free (struct support_blob_repeat *blob) ++{ ++ if (blob->size > 0) ++ { ++ int saved_errno = errno; ++ if (blob->use_malloc) ++ free (blob->start); ++ else ++ xmunmap (blob->start, blob->size); ++ errno = saved_errno; ++ } ++ *blob = (struct support_blob_repeat) { 0 }; ++} +diff --git a/support/blob_repeat.h b/support/blob_repeat.h +new file mode 100644 +index 0000000000..8e9d7ff5f1 +--- /dev/null ++++ b/support/blob_repeat.h +@@ -0,0 +1,44 @@ ++/* Repeating a memory blob, with alias mapping optimization. ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#ifndef SUPPORT_BLOB_REPEAT_H ++#define SUPPORT_BLOB_REPEAT_H ++ ++#include <stdbool.h> ++#include <stddef.h> ++ ++struct support_blob_repeat ++{ ++ void *start; ++ size_t size; ++ bool use_malloc; ++}; ++ ++/* Return an allocation of COUNT elements, each of ELEMENT_SIZE bytes, ++ initialized with the bytes starting at ELEMENT. The memory is ++ writable (and thus counts towards the commit charge). In case of ++ on error, all members of the return struct are zero-initialized, ++ and errno is set accordingly. */ ++struct support_blob_repeat support_blob_repeat_allocate (const void *element, ++ size_t element_size, ++ size_t count); ++ ++/* Deallocate the blob created by support_blob_repeat_allocate. */ ++void support_blob_repeat_free (struct support_blob_repeat *); ++ ++#endif /* SUPPORT_BLOB_REPEAT_H */ diff --git a/support/capture_subprocess.h b/support/capture_subprocess.h new file mode 100644 index 0000000000..b0886ba1d1 @@ -437,10 +829,10 @@ index 0000000000..b0886ba1d1 +#endif /* SUPPORT_CAPTURE_SUBPROCESS_H */ diff --git a/support/check.c b/support/check.c new file mode 100644 -index 0000000000..688ed569ac +index 0000000000..78f2b3cde1 --- /dev/null +++ b/support/check.c -@@ -0,0 +1,57 @@ +@@ -0,0 +1,60 @@ +/* Support code for reporting test results. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. @@ -461,6 +853,7 @@ index 0000000000..688ed569ac + +#include <support/check.h> + ++#include <errno.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> @@ -469,9 +862,11 @@ index 0000000000..688ed569ac +static void +print_failure (const char *file, int line, const char *format, va_list ap) +{ ++ int saved_errno = errno; + printf ("error: %s:%d: ", file, line); + vprintf (format, ap); + puts (""); ++ errno = saved_errno; +} + +int @@ -500,10 +895,10 @@ index 0000000000..688ed569ac +} diff --git a/support/check.h b/support/check.h new file mode 100644 -index 0000000000..2192f38941 +index 0000000000..e6765289f2 --- /dev/null +++ b/support/check.h -@@ -0,0 +1,153 @@ +@@ -0,0 +1,188 @@ +/* Functionality for reporting test results. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. @@ -570,6 +965,8 @@ index 0000000000..2192f38941 + (1, __FILE__, __LINE__, #expr); \ + }) + ++ ++ +int support_print_failure_impl (const char *file, int line, + const char *format, ...) + __attribute__ ((nonnull (1), format (printf, 3, 4))); @@ -647,6 +1044,39 @@ index 0000000000..2192f38941 + int right_size); + + ++/* Compare [LEFT, LEFT + LEFT_LENGTH) with [RIGHT, RIGHT + ++ RIGHT_LENGTH) and report a test failure if the arrays are ++ different. LEFT_LENGTH and RIGHT_LENGTH are measured in bytes. If ++ the length is null, the corresponding pointer is ignored (i.e., it ++ can be NULL). The blobs should be reasonably short because on ++ mismatch, both are printed. */ ++#define TEST_COMPARE_BLOB(left, left_length, right, right_length) \ ++ (support_test_compare_blob (left, left_length, right, right_length, \ ++ __FILE__, __LINE__, \ ++ #left, #left_length, #right, #right_length)) ++ ++void support_test_compare_blob (const void *left, ++ unsigned long int left_length, ++ const void *right, ++ unsigned long int right_length, ++ const char *file, int line, ++ const char *left_exp, const char *left_len_exp, ++ const char *right_exp, ++ const char *right_len_exp); ++ ++/* Compare the strings LEFT and RIGHT and report a test failure if ++ they are different. Also report failure if one of the arguments is ++ a null pointer and the other is not. The strings should be ++ reasonably short because on mismatch, both are printed. */ ++#define TEST_COMPARE_STRING(left, right) \ ++ (support_test_compare_string (left, right, __FILE__, __LINE__, \ ++ #left, #right)) ++ ++void support_test_compare_string (const char *left, const char *right, ++ const char *file, int line, ++ const char *left_expr, ++ const char *right_expr); ++ +/* Internal function called by the test driver. */ +int support_report_failure (int status) + __attribute__ ((weak, warn_unused_result)); @@ -962,6 +1392,46 @@ index 0000000000..2780d9a6fe + /* Restore the original signal mask. */ + xpthread_sigmask (SIG_SETMASK, &old_set, NULL); +} +diff --git a/support/echo-container.c b/support/echo-container.c +new file mode 100644 +index 0000000000..e4d48df957 +--- /dev/null ++++ b/support/echo-container.c +@@ -0,0 +1,34 @@ ++/* Minimal /bin/echo for in-container use. ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <stdio.h> ++ ++int ++main (int argc, const char **argv) ++{ ++ int i; ++ ++ for (i = 1; i < argc; i++) ++ { ++ if (i > 1) ++ putchar (' '); ++ fputs (argv[i], stdout); ++ } ++ putchar ('\n'); ++ return 0; ++} diff --git a/support/format_nss.h b/support/format_nss.h new file mode 100644 index 0000000000..e55354e788 @@ -1053,6 +1523,38 @@ index 0000000000..450333ad38 + } + setenv ("LIBC_FATAL_STDERR_", "1", 1); +} +diff --git a/support/links-dso-program-c.c b/support/links-dso-program-c.c +new file mode 100644 +index 0000000000..d28a28a0d0 +--- /dev/null ++++ b/support/links-dso-program-c.c +@@ -0,0 +1,9 @@ ++#include <stdio.h> ++ ++int ++main (int argc, char **argv) ++{ ++ /* Complexity to keep gcc from optimizing this away. */ ++ printf ("This is a test %s.\n", argc > 1 ? argv[1] : "null"); ++ return 0; ++} +diff --git a/support/links-dso-program.cc b/support/links-dso-program.cc +new file mode 100644 +index 0000000000..dba6976c06 +--- /dev/null ++++ b/support/links-dso-program.cc +@@ -0,0 +1,11 @@ ++#include <iostream> ++ ++using namespace std; ++ ++int ++main (int argc, char **argv) ++{ ++ /* Complexity to keep gcc from optimizing this away. */ ++ cout << (argc > 1 ? argv[1] : "null"); ++ return 0; ++} diff --git a/support/namespace.h b/support/namespace.h new file mode 100644 index 0000000000..3c3842a49b @@ -2855,14 +3357,14 @@ index 0000000000..c2dacbb179 + sigaction (SIGABRT, &sa, NULL); + ignore_stderr (); +} -diff --git a/support/support-xfstat.c b/support/support-xfstat.c +diff --git a/support/shell-container.c b/support/shell-container.c new file mode 100644 -index 0000000000..f69253af09 +index 0000000000..9bd90d3f60 --- /dev/null -+++ b/support/support-xfstat.c -@@ -0,0 +1,28 @@ -+/* fstat64 with error checking. -+ Copyright (C) 2017-2018 Free Software Foundation, Inc. ++++ b/support/shell-container.c +@@ -0,0 +1,395 @@ ++/* Minimal /bin/sh for in-container use. ++ Copyright (C) 2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or @@ -2879,58 +3381,459 @@ index 0000000000..f69253af09 + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + -+#include <support/check.h> -+#include <support/xunistd.h> ++#define _FILE_OFFSET_BITS 64 ++ ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <sched.h> ++#include <sys/syscall.h> ++#include <unistd.h> ++#include <sys/types.h> ++#include <dirent.h> ++#include <string.h> +#include <sys/stat.h> ++#include <sys/fcntl.h> ++#include <sys/file.h> ++#include <sys/wait.h> ++#include <stdarg.h> ++#include <sys/sysmacros.h> ++#include <ctype.h> ++#include <utime.h> ++#include <errno.h> ++#include <error.h> + -+void -+xfstat (int fd, struct stat64 *result) -+{ -+ if (fstat64 (fd, result) != 0) -+ FAIL_EXIT1 ("fstat64 (%d): %m", fd); -+} -diff --git a/support/support-xstat.c b/support/support-xstat.c -new file mode 100644 -index 0000000000..fc10c6dcb7 ---- /dev/null -+++ b/support/support-xstat.c -@@ -0,0 +1,30 @@ -+/* stat64 with error checking. -+ Copyright (C) 2017-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. ++#include <support/support.h> + -+ 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. ++/* Design considerations + -+ 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. ++ General rule: optimize for developer time, not run time. + -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ <http://www.gnu.org/licenses/>. */ ++ Specifically: + -+/* NB: Non-standard file name to avoid sysdeps override for xstat. */ ++ * Don't worry about slow algorithms ++ * Don't worry about free'ing memory ++ * Don't implement anything the testsuite doesn't need. ++ * Line and argument counts are limited, see below. + -+#include <support/check.h> -+#include <support/xunistd.h> -+#include <sys/stat.h> ++*/ + -+void -+xstat (const char *path, struct stat64 *result) ++#define MAX_ARG_COUNT 100 ++#define MAX_LINE_LENGTH 1000 ++ ++/* Debugging is enabled via --debug, which must be the first argument. */ ++static int debug_mode = 0; ++#define dprintf if (debug_mode) fprintf ++ ++/* Emulate the "/bin/true" command. Arguments are ignored. */ ++static int ++true_func (char **argv) +{ -+ if (stat64 (path, result) != 0) -+ FAIL_EXIT1 ("stat64 (\"%s\"): %m", path); ++ return 0; ++} ++ ++/* Emulate the "/bin/echo" command. Options are ignored, arguments ++ are printed to stdout. */ ++static int ++echo_func (char **argv) ++{ ++ int i; ++ ++ for (i = 0; argv[i]; i++) ++ { ++ if (i > 0) ++ putchar (' '); ++ fputs (argv[i], stdout); ++ } ++ putchar ('\n'); ++ ++ return 0; ++} ++ ++/* Emulate the "/bin/cp" command. Options are ignored. Only copies ++ one source file to one destination file. Directory destinations ++ are not supported. */ ++static int ++copy_func (char **argv) ++{ ++ char *sname = argv[0]; ++ char *dname = argv[1]; ++ int sfd, dfd; ++ struct stat st; ++ ++ sfd = open (sname, O_RDONLY); ++ if (sfd < 0) ++ { ++ fprintf (stderr, "cp: unable to open %s for reading: %s\n", ++ sname, strerror (errno)); ++ return 1; ++ } ++ ++ if (fstat (sfd, &st) < 0) ++ { ++ fprintf (stderr, "cp: unable to fstat %s: %s\n", ++ sname, strerror (errno)); ++ return 1; ++ } ++ ++ dfd = open (dname, O_WRONLY | O_TRUNC | O_CREAT, 0600); ++ if (dfd < 0) ++ { ++ fprintf (stderr, "cp: unable to open %s for writing: %s\n", ++ dname, strerror (errno)); ++ return 1; ++ } ++ ++ if (support_copy_file_range (sfd, 0, dfd, 0, st.st_size, 0) != st.st_size) ++ { ++ fprintf (stderr, "cp: cannot copy file %s to %s: %s\n", ++ sname, dname, strerror (errno)); ++ return 1; ++ } ++ ++ close (sfd); ++ close (dfd); ++ ++ chmod (dname, st.st_mode & 0777); ++ ++ return 0; ++ ++} ++ ++/* This is a list of all the built-in commands we understand. */ ++static struct { ++ const char *name; ++ int (*func) (char **argv); ++} builtin_funcs[] = { ++ { "true", true_func }, ++ { "echo", echo_func }, ++ { "cp", copy_func }, ++ { NULL, NULL } ++}; ++ ++/* Run one tokenized command. argv[0] is the command. argv is ++ NULL-terminated. */ ++static void ++run_command_array (char **argv) ++{ ++ int i, j; ++ pid_t pid; ++ int status; ++ int (*builtin_func) (char **args); ++ ++ if (argv[0] == NULL) ++ return; ++ ++ builtin_func = NULL; ++ ++ int new_stdin = 0; ++ int new_stdout = 1; ++ int new_stderr = 2; ++ ++ dprintf (stderr, "run_command_array starting\n"); ++ for (i = 0; argv[i]; i++) ++ dprintf (stderr, " argv [%d] `%s'\n", i, argv[i]); ++ ++ for (j = i = 0; argv[i]; i++) ++ { ++ if (strcmp (argv[i], "<") == 0 && argv[i + 1]) ++ { ++ new_stdin = open (argv[i + 1], O_WRONLY|O_CREAT|O_TRUNC, 0777); ++ ++i; ++ continue; ++ } ++ if (strcmp (argv[i], ">") == 0 && argv[i + 1]) ++ { ++ new_stdout = open (argv[i + 1], O_WRONLY|O_CREAT|O_TRUNC, 0777); ++ ++i; ++ continue; ++ } ++ if (strcmp (argv[i], ">>") == 0 && argv[i + 1]) ++ { ++ new_stdout = open (argv[i + 1], O_WRONLY|O_CREAT|O_APPEND, 0777); ++ ++i; ++ continue; ++ } ++ if (strcmp (argv[i], "2>") == 0 && argv[i + 1]) ++ { ++ new_stderr = open (argv[i + 1], O_WRONLY|O_CREAT|O_TRUNC, 0777); ++ ++i; ++ continue; ++ } ++ argv[j++] = argv[i]; ++ } ++ argv[j] = NULL; ++ ++ ++ for (i = 0; builtin_funcs[i].name != NULL; i++) ++ if (strcmp (argv[0], builtin_funcs[i].name) == 0) ++ builtin_func = builtin_funcs[i].func; ++ ++ dprintf (stderr, "builtin %p argv0 `%s'\n", builtin_func, argv[0]); ++ ++ pid = fork (); ++ if (pid < 0) ++ { ++ fprintf (stderr, "sh: fork failed\n"); ++ exit (1); ++ } ++ ++ if (pid == 0) ++ { ++ if (new_stdin != 0) ++ { ++ dup2 (new_stdin, 0); ++ close (new_stdin); ++ } ++ if (new_stdout != 1) ++ { ++ dup2 (new_stdout, 1); ++ close (new_stdout); ++ } ++ if (new_stderr != 2) ++ { ++ dup2 (new_stderr, 2); ++ close (new_stdout); ++ } ++ ++ if (builtin_func != NULL) ++ exit (builtin_func (argv + 1)); ++ ++ execvp (argv[0], argv); ++ ++ fprintf (stderr, "sh: execing %s failed: %s", ++ argv[0], strerror (errno)); ++ exit (1); ++ } ++ ++ waitpid (pid, &status, 0); ++ ++ dprintf (stderr, "exiting run_command_array\n"); ++ ++ if (WIFEXITED (status)) ++ { ++ int rv = WEXITSTATUS (status); ++ if (rv) ++ exit (rv); ++ } ++ else ++ exit (1); ++} ++ ++/* Run one command-as-a-string, by tokenizing it. Limited to ++ MAX_ARG_COUNT arguments. Simple substitution is done of $1 to $9 ++ (as whole separate tokens) from iargs[]. Quoted strings work if ++ the quotes wrap whole tokens; i.e. "foo bar" but not foo" bar". */ ++static void ++run_command_string (const char *cmdline, const char **iargs) ++{ ++ char *args[MAX_ARG_COUNT+1]; ++ int ap = 0; ++ const char *start, *end; ++ int nargs; ++ ++ for (nargs = 0; iargs[nargs] != NULL; ++nargs) ++ ; ++ ++ dprintf (stderr, "run_command_string starting: '%s'\n", cmdline); ++ ++ while (ap < MAX_ARG_COUNT) ++ { ++ /* If the argument is quoted, this is the quote character, else NUL. */ ++ int in_quote = 0; ++ ++ /* Skip whitespace up to the next token. */ ++ while (*cmdline && isspace (*cmdline)) ++ cmdline ++; ++ if (*cmdline == 0) ++ break; ++ ++ start = cmdline; ++ /* Check for quoted argument. */ ++ in_quote = (*cmdline == '\'' || *cmdline == '"') ? *cmdline : 0; ++ ++ /* Skip to end of token; either by whitespace or matching quote. */ ++ dprintf (stderr, "in_quote %d\n", in_quote); ++ while (*cmdline ++ && (!isspace (*cmdline) || in_quote)) ++ { ++ if (*cmdline == in_quote ++ && cmdline != start) ++ in_quote = 0; ++ dprintf (stderr, "[%c]%d ", *cmdline, in_quote); ++ cmdline ++; ++ } ++ dprintf (stderr, "\n"); ++ ++ /* Allocate space for this token and store it in args[]. */ ++ end = cmdline; ++ dprintf (stderr, "start<%s> end<%s>\n", start, end); ++ args[ap] = (char *) xmalloc (end - start + 1); ++ memcpy (args[ap], start, end - start); ++ args[ap][end - start] = 0; ++ ++ /* Strip off quotes, if found. */ ++ dprintf (stderr, "args[%d] = <%s>\n", ap, args[ap]); ++ if (args[ap][0] == '\'' ++ && args[ap][strlen (args[ap])-1] == '\'') ++ { ++ args[ap][strlen (args[ap])-1] = 0; ++ args[ap] ++; ++ } ++ ++ else if (args[ap][0] == '"' ++ && args[ap][strlen (args[ap])-1] == '"') ++ { ++ args[ap][strlen (args[ap])-1] = 0; ++ args[ap] ++; ++ } ++ ++ /* Replace positional parameters like $4. */ ++ else if (args[ap][0] == '$' ++ && isdigit (args[ap][1]) ++ && args[ap][2] == 0) ++ { ++ int a = args[ap][1] - '1'; ++ if (0 <= a && a < nargs) ++ args[ap] = strdup (iargs[a]); ++ } ++ ++ ap ++; ++ ++ if (*cmdline == 0) ++ break; ++ } ++ ++ /* Lastly, NULL terminate the array and run it. */ ++ args[ap] = NULL; ++ run_command_array (args); ++} ++ ++/* Run a script by reading lines and passing them to the above ++ function. */ ++static void ++run_script (const char *filename, const char **args) ++{ ++ char line[MAX_LINE_LENGTH + 1]; ++ dprintf (stderr, "run_script starting: '%s'\n", filename); ++ FILE *f = fopen (filename, "r"); ++ if (f == NULL) ++ { ++ fprintf (stderr, "sh: %s: %s\n", filename, strerror (errno)); ++ exit (1); ++ } ++ while (fgets (line, sizeof (line), f) != NULL) ++ { ++ if (line[0] == '#') ++ { ++ dprintf (stderr, "comment: %s\n", line); ++ continue; ++ } ++ run_command_string (line, args); ++ } ++ fclose (f); ++} ++ ++int ++main (int argc, const char **argv) ++{ ++ int i; ++ ++ if (strcmp (argv[1], "--debug") == 0) ++ { ++ debug_mode = 1; ++ --argc; ++ ++argv; ++ } ++ ++ dprintf (stderr, "container-sh starting:\n"); ++ for (i = 0; i < argc; i++) ++ dprintf (stderr, " argv[%d] is `%s'\n", i, argv[i]); ++ ++ if (strcmp (argv[1], "-c") == 0) ++ run_command_string (argv[2], argv+3); ++ else ++ run_script (argv[1], argv+2); ++ ++ dprintf (stderr, "normal exit 0\n"); ++ return 0; ++} +diff --git a/support/support-xfstat.c b/support/support-xfstat.c +new file mode 100644 +index 0000000000..f69253af09 +--- /dev/null ++++ b/support/support-xfstat.c +@@ -0,0 +1,28 @@ ++/* fstat64 with error checking. ++ Copyright (C) 2017-2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <support/check.h> ++#include <support/xunistd.h> ++#include <sys/stat.h> ++ ++void ++xfstat (int fd, struct stat64 *result) ++{ ++ if (fstat64 (fd, result) != 0) ++ FAIL_EXIT1 ("fstat64 (%d): %m", fd); ++} +diff --git a/support/support-xstat.c b/support/support-xstat.c +new file mode 100644 +index 0000000000..fc10c6dcb7 +--- /dev/null ++++ b/support/support-xstat.c +@@ -0,0 +1,30 @@ ++/* stat64 with error checking. ++ Copyright (C) 2017-2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++/* NB: Non-standard file name to avoid sysdeps override for xstat. */ ++ ++#include <support/check.h> ++#include <support/xunistd.h> ++#include <sys/stat.h> ++ ++void ++xstat (const char *path, struct stat64 *result) ++{ ++ if (stat64 (path, result) != 0) ++ FAIL_EXIT1 ("stat64 (\"%s\"): %m", path); +} diff --git a/support/support.h b/support/support.h new file mode 100644 -index 0000000000..bc5827ed87 +index 0000000000..9418cd11ef --- /dev/null +++ b/support/support.h -@@ -0,0 +1,75 @@ +@@ -0,0 +1,108 @@ +/* Common extra functions. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. @@ -2958,6 +3861,10 @@ index 0000000000..bc5827ed87 + +#include <stddef.h> +#include <sys/cdefs.h> ++/* For mode_t. */ ++#include <sys/stat.h> ++/* For ssize_t and off64_t. */ ++#include <sys/types.h> + +__BEGIN_DECLS + @@ -2992,6 +3899,18 @@ index 0000000000..bc5827ed87 + process on error. */ +void support_write_file_string (const char *path, const char *contents); + ++/* Quote the contents of the byte array starting at BLOB, of LENGTH ++ bytes, in such a way that the result string can be included in a C ++ literal (in single/double quotes, without putting the quotes into ++ the result). */ ++char *support_quote_blob (const void *blob, size_t length); ++ ++/* Returns non-zero if the file descriptor is a regular file on a file ++ system which supports holes (that is, seeking and writing does not ++ allocate storage for the range of zeros). FD must refer to a ++ regular file open for writing, and initially empty. */ ++int support_descriptor_supports_holes (int fd); ++ +/* Error-checking wrapper functions which terminate the process on + error. */ + @@ -3003,6 +3922,23 @@ index 0000000000..bc5827ed87 +char *xstrdup (const char *); +char *xstrndup (const char *, size_t); + ++/* These point to the TOP of the source/build tree, not your (or ++ support's) subdirectory. */ ++extern const char support_srcdir_root[]; ++extern const char support_objdir_root[]; ++ ++/* Corresponds to the path to the runtime linker used by the testsuite, ++ e.g. OBJDIR_PATH/elf/ld-linux-x86-64.so.2 */ ++extern const char support_objdir_elf_ldso[]; ++ ++/* Corresponds to the --prefix= passed to configure. */ ++extern const char support_install_prefix[]; ++/* Corresponds to the install's lib/ or lib64/ directory. */ ++extern const char support_libdir_prefix[]; ++ ++extern ssize_t support_copy_file_range (int, off64_t *, int, off64_t *, ++ size_t, unsigned int); ++ +__END_DECLS + +#endif /* SUPPORT_H */ @@ -3459,14 +4395,14 @@ index 0000000000..6356b1af6c + free (chroot->path_host_conf); + free (chroot); +} -diff --git a/support/support_enter_mount_namespace.c b/support/support_enter_mount_namespace.c +diff --git a/support/support_copy_file_range.c b/support/support_copy_file_range.c new file mode 100644 -index 0000000000..ba68e990f2 +index 0000000000..9a1e39773e --- /dev/null -+++ b/support/support_enter_mount_namespace.c -@@ -0,0 +1,47 @@ -+/* Enter a mount namespace. -+ Copyright (C) 2017-2018 Free Software Foundation, Inc. ++++ b/support/support_copy_file_range.c +@@ -0,0 +1,143 @@ ++/* Simplified copy_file_range with cross-device copy. ++ Copyright (C) 2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or @@ -3483,39 +4419,281 @@ index 0000000000..ba68e990f2 + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + -+#include <support/namespace.h> -+ -+#include <sched.h> -+#include <stdio.h> -+#ifdef CLONE_NEWNS -+# include <sys/mount.h> -+#endif /* CLONE_NEWNS */ ++#include <errno.h> ++#include <fcntl.h> ++#include <inttypes.h> ++#include <limits.h> ++#include <sys/stat.h> ++#include <sys/types.h> ++#include <unistd.h> ++#include <support/support.h> + -+bool -+support_enter_mount_namespace (void) ++ssize_t ++support_copy_file_range (int infd, __off64_t *pinoff, ++ int outfd, __off64_t *poutoff, ++ size_t length, unsigned int flags) +{ -+#ifdef CLONE_NEWNS -+ if (unshare (CLONE_NEWNS) == 0) ++ if (flags != 0) + { -+ /* On some systems, / is marked as MS_SHARED, which means that -+ mounts within the namespace leak to the rest of the system, -+ which is not what we want. */ -+ if (mount ("none", "/", NULL, MS_REC | MS_PRIVATE, NULL) != 0) -+ { -+ printf ("warning: making the mount namespace private failed: %m\n"); -+ return false; -+ } -+ return true; ++ errno = EINVAL; ++ return -1; + } -+ else -+ printf ("warning: unshare (CLONE_NEWNS) failed: %m\n"); -+#endif /* CLONE_NEWNS */ -+ return false; -+} -diff --git a/support/support_enter_network_namespace.c b/support/support_enter_network_namespace.c -new file mode 100644 -index 0000000000..1d874df885 ---- /dev/null ++ ++ struct stat64 instat; ++ struct stat64 outstat; ++ if (fstat64 (infd, &instat) != 0 || fstat64 (outfd, &outstat) != 0) ++ return -1; ++ if (S_ISDIR (instat.st_mode) || S_ISDIR (outstat.st_mode)) ++ { ++ errno = EISDIR; ++ return -1; ++ } ++ if (!S_ISREG (instat.st_mode) || !S_ISREG (outstat.st_mode)) ++ { ++ /* We need a regular input file so that the we can seek ++ backwards in case of a write failure. */ ++ errno = EINVAL; ++ return -1; ++ } ++ ++ /* The output descriptor must not have O_APPEND set. */ ++ if (fcntl (outfd, F_GETFL) & O_APPEND) ++ { ++ errno = EBADF; ++ return -1; ++ } ++ ++ /* Avoid an overflow in the result. */ ++ if (length > SSIZE_MAX) ++ length = SSIZE_MAX; ++ ++ /* Main copying loop. The buffer size is arbitrary and is a ++ trade-off between stack size consumption, cache usage, and ++ amortization of system call overhead. */ ++ size_t copied = 0; ++ char buf[8192]; ++ while (length > 0) ++ { ++ size_t to_read = length; ++ if (to_read > sizeof (buf)) ++ to_read = sizeof (buf); ++ ++ /* Fill the buffer. */ ++ ssize_t read_count; ++ if (pinoff == NULL) ++ read_count = read (infd, buf, to_read); ++ else ++ read_count = pread64 (infd, buf, to_read, *pinoff); ++ if (read_count == 0) ++ /* End of file reached prematurely. */ ++ return copied; ++ if (read_count < 0) ++ { ++ if (copied > 0) ++ /* Report the number of bytes copied so far. */ ++ return copied; ++ return -1; ++ } ++ if (pinoff != NULL) ++ *pinoff += read_count; ++ ++ /* Write the buffer part which was read to the destination. */ ++ char *end = buf + read_count; ++ for (char *p = buf; p < end; ) ++ { ++ ssize_t write_count; ++ if (poutoff == NULL) ++ write_count = write (outfd, p, end - p); ++ else ++ write_count = pwrite64 (outfd, p, end - p, *poutoff); ++ if (write_count < 0) ++ { ++ /* Adjust the input read position to match what we have ++ written, so that the caller can pick up after the ++ error. */ ++ size_t written = p - buf; ++ /* NB: This needs to be signed so that we can form the ++ negative value below. */ ++ ssize_t overread = read_count - written; ++ if (pinoff == NULL) ++ { ++ if (overread > 0) ++ { ++ /* We are on an error recovery path, so we ++ cannot deal with failure here. */ ++ int save_errno = errno; ++ (void) lseek64 (infd, -overread, SEEK_CUR); ++ errno = save_errno; ++ } ++ } ++ else /* pinoff != NULL */ ++ *pinoff -= overread; ++ ++ if (copied + written > 0) ++ /* Report the number of bytes copied so far. */ ++ return copied + written; ++ return -1; ++ } ++ p += write_count; ++ if (poutoff != NULL) ++ *poutoff += write_count; ++ } /* Write loop. */ ++ ++ copied += read_count; ++ length -= read_count; ++ } ++ return copied; ++} +diff --git a/support/support_descriptor_supports_holes.c b/support/support_descriptor_supports_holes.c +new file mode 100644 +index 0000000000..c7099ca67c +--- /dev/null ++++ b/support/support_descriptor_supports_holes.c +@@ -0,0 +1,87 @@ ++/* Test for file system hole support. ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <stdbool.h> ++#include <support.h> ++#include <support/check.h> ++#include <sys/stat.h> ++#include <xunistd.h> ++ ++int ++support_descriptor_supports_holes (int fd) ++{ ++ enum ++ { ++ /* Write offset for the enlarged file. This value is arbitrary ++ and hopefully large enough to trigger the creation of holes. ++ We cannot use the file system block size as a reference here ++ because it is incorrect for network file systems. */ ++ write_offset = 16 * 1024 * 1024, ++ ++ /* Our write may add this number of additional blocks (see ++ block_limit below). */ ++ block_headroom = 8, ++ }; ++ ++ struct stat64 st; ++ xfstat (fd, &st); ++ if (!S_ISREG (st.st_mode)) ++ FAIL_EXIT1 ("descriptor %d does not refer to a regular file", fd); ++ if (st.st_size != 0) ++ FAIL_EXIT1 ("descriptor %d does not refer to an empty file", fd); ++ if (st.st_blocks > block_headroom) ++ FAIL_EXIT1 ("descriptor %d refers to a pre-allocated file (%lld blocks)", ++ fd, (long long int) st.st_blocks); ++ ++ /* Write a single byte at the start of the file to compute the block ++ usage for a single byte. */ ++ xlseek (fd, 0, SEEK_SET); ++ char b = '@'; ++ xwrite (fd, &b, 1); ++ /* Attempt to bypass delayed allocation. */ ++ TEST_COMPARE (fsync (fd), 0); ++ xfstat (fd, &st); ++ ++ /* This limit is arbitrary. The file system needs to store ++ somewhere that data exists at the write offset, and this may ++ moderately increase the number of blocks used by the file, in ++ proportion to the initial block count, but not in proportion to ++ the write offset. */ ++ unsigned long long int block_limit = 2 * st.st_blocks + block_headroom; ++ ++ /* Write a single byte at 16 megabytes. */ ++ xlseek (fd, write_offset, SEEK_SET); ++ xwrite (fd, &b, 1); ++ /* Attempt to bypass delayed allocation. */ ++ TEST_COMPARE (fsync (fd), 0); ++ xfstat (fd, &st); ++ bool supports_holes = st.st_blocks <= block_limit; ++ ++ /* Also check that extending the file does not fill up holes. */ ++ xftruncate (fd, 2 * write_offset); ++ /* Attempt to bypass delayed allocation. */ ++ TEST_COMPARE (fsync (fd), 0); ++ xfstat (fd, &st); ++ supports_holes = supports_holes && st.st_blocks <= block_limit; ++ ++ /* Return to a zero-length file. */ ++ xftruncate (fd, 0); ++ xlseek (fd, 0, SEEK_SET); ++ ++ return supports_holes; ++} +diff --git a/support/support_enter_mount_namespace.c b/support/support_enter_mount_namespace.c +new file mode 100644 +index 0000000000..ba68e990f2 +--- /dev/null ++++ b/support/support_enter_mount_namespace.c +@@ -0,0 +1,47 @@ ++/* Enter a mount namespace. ++ Copyright (C) 2017-2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <support/namespace.h> ++ ++#include <sched.h> ++#include <stdio.h> ++#ifdef CLONE_NEWNS ++# include <sys/mount.h> ++#endif /* CLONE_NEWNS */ ++ ++bool ++support_enter_mount_namespace (void) ++{ ++#ifdef CLONE_NEWNS ++ if (unshare (CLONE_NEWNS) == 0) ++ { ++ /* On some systems, / is marked as MS_SHARED, which means that ++ mounts within the namespace leak to the rest of the system, ++ which is not what we want. */ ++ if (mount ("none", "/", NULL, MS_REC | MS_PRIVATE, NULL) != 0) ++ { ++ printf ("warning: making the mount namespace private failed: %m\n"); ++ return false; ++ } ++ return true; ++ } ++ else ++ printf ("warning: unshare (CLONE_NEWNS) failed: %m\n"); ++#endif /* CLONE_NEWNS */ ++ return false; ++} +diff --git a/support/support_enter_network_namespace.c b/support/support_enter_network_namespace.c +new file mode 100644 +index 0000000000..1d874df885 +--- /dev/null +++ b/support/support_enter_network_namespace.c @@ -0,0 +1,75 @@ +/* Enter a network namespace. @@ -3636,10 +4814,10 @@ index 0000000000..2acb9afffd +} diff --git a/support/support_format_addrinfo.c b/support/support_format_addrinfo.c new file mode 100644 -index 0000000000..c5e00e516a +index 0000000000..60d2cc40f6 --- /dev/null +++ b/support/support_format_addrinfo.c -@@ -0,0 +1,240 @@ +@@ -0,0 +1,242 @@ +/* Convert struct addrinfo values to a string. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. @@ -3709,8 +4887,6 @@ index 0000000000..c5e00e516a + FLAG (AI_ADDRCONFIG); + FLAG (AI_IDN); + FLAG (AI_CANONIDN); -+ FLAG (AI_IDN_ALLOW_UNASSIGNED); -+ FLAG (AI_IDN_USE_STD3_ASCII_RULES); + FLAG (AI_NUMERICSERV); +#undef FLAG + int remaining = ai->ai_flags & ~flags_printed; @@ -3862,7 +5038,11 @@ index 0000000000..c5e00e516a + xopen_memstream (&mem); + if (ret != 0) + { -+ fprintf (mem.out, "error: %s\n", gai_strerror (ret)); ++ const char *errmsg = gai_strerror (ret); ++ if (strcmp (errmsg, "Unknown error") == 0) ++ fprintf (mem.out, "error: Unknown error %d\n", ret); ++ else ++ fprintf (mem.out, "error: %s\n", errmsg); + if (ret == EAI_SYSTEM) + { + errno = errno_copy; @@ -4351,6 +5531,275 @@ index 0000000000..25edc00385 + if (status != 0) + FAIL_EXIT1 ("child process exited with status %d", status); +} +diff --git a/support/support_openpty.c b/support/support_openpty.c +new file mode 100644 +index 0000000000..ac779ab91e +--- /dev/null ++++ b/support/support_openpty.c +@@ -0,0 +1,109 @@ ++/* Open a pseudoterminal. ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <support/tty.h> ++#include <support/check.h> ++#include <support/support.h> ++ ++#include <errno.h> ++#include <stdlib.h> ++#include <string.h> ++ ++#include <fcntl.h> ++#include <termios.h> ++#include <sys/ioctl.h> ++#include <unistd.h> ++ ++/* As ptsname, but allocates space for an appropriately-sized string ++ using malloc. */ ++static char * ++xptsname (int fd) ++{ ++ int rv; ++ size_t buf_len = 128; ++ char *buf = xmalloc (buf_len); ++ for (;;) ++ { ++ rv = ptsname_r (fd, buf, buf_len); ++ if (rv) ++ FAIL_EXIT1 ("ptsname_r: %s", strerror (errno)); ++ ++ if (memchr (buf, '\0', buf_len)) ++ return buf; /* ptsname succeeded and the buffer was not truncated */ ++ ++ buf_len *= 2; ++ buf = xrealloc (buf, buf_len); ++ } ++} ++ ++void ++support_openpty (int *a_outer, int *a_inner, char **a_name, ++ const struct termios *termp, ++ const struct winsize *winp) ++{ ++ int outer = -1, inner = -1; ++ char *namebuf = 0; ++ ++ outer = posix_openpt (O_RDWR | O_NOCTTY); ++ if (outer == -1) ++ FAIL_EXIT1 ("posix_openpt: %s", strerror (errno)); ++ ++ if (grantpt (outer)) ++ FAIL_EXIT1 ("grantpt: %s", strerror (errno)); ++ ++ if (unlockpt (outer)) ++ FAIL_EXIT1 ("unlockpt: %s", strerror (errno)); ++ ++ ++#ifdef TIOCGPTPEER ++ inner = ioctl (outer, TIOCGPTPEER, O_RDWR | O_NOCTTY); ++#endif ++ if (inner == -1) ++ { ++ /* The kernel might not support TIOCGPTPEER, fall back to open ++ by name. */ ++ namebuf = xptsname (outer); ++ inner = open (namebuf, O_RDWR | O_NOCTTY); ++ if (inner == -1) ++ FAIL_EXIT1 ("%s: %s", namebuf, strerror (errno)); ++ } ++ ++ if (termp) ++ { ++ if (tcsetattr (inner, TCSAFLUSH, termp)) ++ FAIL_EXIT1 ("tcsetattr: %s", strerror (errno)); ++ } ++#ifdef TIOCSWINSZ ++ if (winp) ++ { ++ if (ioctl (inner, TIOCSWINSZ, winp)) ++ FAIL_EXIT1 ("TIOCSWINSZ: %s", strerror (errno)); ++ } ++#endif ++ ++ if (a_name) ++ { ++ if (!namebuf) ++ namebuf = xptsname (outer); ++ *a_name = namebuf; ++ } ++ else ++ free (namebuf); ++ *a_outer = outer; ++ *a_inner = inner; ++} +diff --git a/support/support_paths.c b/support/support_paths.c +new file mode 100644 +index 0000000000..6d0beb102c +--- /dev/null ++++ b/support/support_paths.c +@@ -0,0 +1,59 @@ ++/* Various paths that might be needed. ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <support/support.h> ++#include <support/check.h> ++ ++/* The idea here is to make various makefile-level paths available to ++ support programs, as canonicalized absolute paths. */ ++ ++/* These point to the TOP of the source/build tree, not your (or ++ support's) subdirectory. */ ++#ifdef SRCDIR_PATH ++const char support_srcdir_root[] = SRCDIR_PATH; ++#else ++# error please -DSRCDIR_PATH=something in the Makefile ++#endif ++ ++#ifdef OBJDIR_PATH ++const char support_objdir_root[] = OBJDIR_PATH; ++#else ++# error please -DOBJDIR_PATH=something in the Makefile ++#endif ++ ++#ifdef OBJDIR_ELF_LDSO_PATH ++/* Corresponds to the path to the runtime linker used by the testsuite, ++ e.g. OBJDIR_PATH/elf/ld-linux-x86-64.so.2 */ ++const char support_objdir_elf_ldso[] = OBJDIR_ELF_LDSO_PATH; ++#else ++# error please -DOBJDIR_ELF_LDSO_PATH=something in the Makefile ++#endif ++ ++#ifdef INSTDIR_PATH ++/* Corresponds to the --prefix= passed to configure. */ ++const char support_install_prefix[] = INSTDIR_PATH; ++#else ++# error please -DINSTDIR_PATH=something in the Makefile ++#endif ++ ++#ifdef LIBDIR_PATH ++/* Corresponds to the install's lib/ or lib64/ directory. */ ++const char support_libdir_prefix[] = LIBDIR_PATH; ++#else ++# error please -DLIBDIR_PATH=something in the Makefile ++#endif +diff --git a/support/support_quote_blob.c b/support/support_quote_blob.c +new file mode 100644 +index 0000000000..d6a678d8d6 +--- /dev/null ++++ b/support/support_quote_blob.c +@@ -0,0 +1,83 @@ ++/* Quote a blob so that it can be used in C literals. ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <support/support.h> ++#include <support/xmemstream.h> ++ ++char * ++support_quote_blob (const void *blob, size_t length) ++{ ++ struct xmemstream out; ++ xopen_memstream (&out); ++ ++ const unsigned char *p = blob; ++ for (size_t i = 0; i < length; ++i) ++ { ++ unsigned char ch = p[i]; ++ ++ /* Use C backslash escapes for those control characters for ++ which they are defined. */ ++ switch (ch) ++ { ++ case '\a': ++ putc_unlocked ('\\', out.out); ++ putc_unlocked ('a', out.out); ++ break; ++ case '\b': ++ putc_unlocked ('\\', out.out); ++ putc_unlocked ('b', out.out); ++ break; ++ case '\f': ++ putc_unlocked ('\\', out.out); ++ putc_unlocked ('f', out.out); ++ break; ++ case '\n': ++ putc_unlocked ('\\', out.out); ++ putc_unlocked ('n', out.out); ++ break; ++ case '\r': ++ putc_unlocked ('\\', out.out); ++ putc_unlocked ('r', out.out); ++ break; ++ case '\t': ++ putc_unlocked ('\\', out.out); ++ putc_unlocked ('t', out.out); ++ break; ++ case '\v': ++ putc_unlocked ('\\', out.out); ++ putc_unlocked ('v', out.out); ++ break; ++ case '\\': ++ case '\'': ++ case '\"': ++ putc_unlocked ('\\', out.out); ++ putc_unlocked (ch, out.out); ++ break; ++ default: ++ if (ch < ' ' || ch > '~') ++ /* Use octal sequences because they are fixed width, ++ unlike hexadecimal sequences. */ ++ fprintf (out.out, "\\%03o", ch); ++ else ++ putc_unlocked (ch, out.out); ++ } ++ } ++ ++ xfclose_memstream (&out); ++ return out.buffer; ++} diff --git a/support/support_record_failure.c b/support/support_record_failure.c new file mode 100644 index 0000000000..356798f556 @@ -4608,14 +6057,14 @@ index 0000000000..8ab43c4b38 + struct header *header = data - offsetof (struct header, data); + xmunmap (header, header->total_size); +} -diff --git a/support/support_test_compare_failure.c b/support/support_test_compare_failure.c +diff --git a/support/support_test_compare_blob.c b/support/support_test_compare_blob.c new file mode 100644 -index 0000000000..e5596fd121 +index 0000000000..c5e63d1b93 --- /dev/null -+++ b/support/support_test_compare_failure.c -@@ -0,0 +1,55 @@ -+/* Reporting a numeric comparison failure. -+ Copyright (C) 2017-2018 Free Software Foundation, Inc. ++++ b/support/support_test_compare_blob.c +@@ -0,0 +1,76 @@ ++/* Check two binary blobs for equality. ++ Copyright (C) 2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or @@ -4633,18 +6082,101 @@ index 0000000000..e5596fd121 + <http://www.gnu.org/licenses/>. */ + +#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> +#include <support/check.h> ++#include <support/support.h> ++#include <support/xmemstream.h> + +static void -+report (const char *which, const char *expr, long long value, int positive, -+ int size) ++report_length (const char *what, unsigned long int length, const char *expr) +{ -+ printf (" %s: ", which); -+ if (positive) -+ printf ("%llu", (unsigned long long) value); -+ else -+ printf ("%lld", value); -+ unsigned long long mask ++ printf (" %s %lu bytes (from %s)\n", what, length, expr); ++} ++ ++static void ++report_blob (const char *what, const unsigned char *blob, ++ unsigned long int length, const char *expr) ++{ ++ if (length > 0) ++ { ++ printf (" %s (evaluated from %s):\n", what, expr); ++ char *quoted = support_quote_blob (blob, length); ++ printf (" \"%s\"\n", quoted); ++ free (quoted); ++ ++ fputs (" ", stdout); ++ for (unsigned long i = 0; i < length; ++i) ++ printf (" %02X", blob[i]); ++ putc ('\n', stdout); ++ } ++} ++ ++void ++support_test_compare_blob (const void *left, unsigned long int left_length, ++ const void *right, unsigned long int right_length, ++ const char *file, int line, ++ const char *left_expr, const char *left_len_expr, ++ const char *right_expr, const char *right_len_expr) ++{ ++ /* No differences are possible if both lengths are null. */ ++ if (left_length == 0 && right_length == 0) ++ return; ++ ++ if (left_length != right_length || left == NULL || right == NULL ++ || memcmp (left, right, left_length) != 0) ++ { ++ support_record_failure (); ++ printf ("%s:%d: error: blob comparison failed\n", file, line); ++ if (left_length == right_length) ++ printf (" blob length: %lu bytes\n", left_length); ++ else ++ { ++ report_length ("left length: ", left_length, left_len_expr); ++ report_length ("right length:", right_length, right_len_expr); ++ } ++ report_blob ("left", left, left_length, left_expr); ++ report_blob ("right", right, right_length, right_expr); ++ } ++} +diff --git a/support/support_test_compare_failure.c b/support/support_test_compare_failure.c +new file mode 100644 +index 0000000000..8eb51c439d +--- /dev/null ++++ b/support/support_test_compare_failure.c +@@ -0,0 +1,58 @@ ++/* Reporting a numeric comparison failure. ++ Copyright (C) 2017-2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <errno.h> ++#include <stdio.h> ++#include <support/check.h> ++ ++static void ++report (const char *which, const char *expr, long long value, int positive, ++ int size) ++{ ++ printf (" %s: ", which); ++ if (positive) ++ printf ("%llu", (unsigned long long) value); ++ else ++ printf ("%lld", value); ++ unsigned long long mask + = (~0ULL) >> (8 * (sizeof (unsigned long long) - size)); + printf (" (0x%llx); from: %s\n", (unsigned long long) value & mask, expr); +} @@ -4660,6 +6192,7 @@ index 0000000000..e5596fd121 + int right_positive, + int right_size) +{ ++ int saved_errno = errno; + support_record_failure (); + if (left_size != right_size) + printf ("%s:%d: numeric comparison failure (widths %d and %d)\n", @@ -4668,13 +6201,111 @@ index 0000000000..e5596fd121 + printf ("%s:%d: numeric comparison failure\n", file, line); + report (" left", left_expr, left_value, left_positive, left_size); + report ("right", right_expr, right_value, right_positive, right_size); ++ errno = saved_errno; ++} +diff --git a/support/support_test_compare_string.c b/support/support_test_compare_string.c +new file mode 100644 +index 0000000000..a76ba8eda7 +--- /dev/null ++++ b/support/support_test_compare_string.c +@@ -0,0 +1,91 @@ ++/* Check two strings for equality. ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <support/check.h> ++#include <support/support.h> ++#include <support/xmemstream.h> ++ ++static void ++report_length (const char *what, const char *str, size_t length) ++{ ++ if (str == NULL) ++ printf (" %s string: NULL\n", what); ++ else ++ printf (" %s string: %zu bytes\n", what, length); ++} ++ ++static void ++report_string (const char *what, const unsigned char *blob, ++ size_t length, const char *expr) ++{ ++ if (length > 0) ++ { ++ printf (" %s (evaluated from %s):\n", what, expr); ++ char *quoted = support_quote_blob (blob, length); ++ printf (" \"%s\"\n", quoted); ++ free (quoted); ++ ++ fputs (" ", stdout); ++ for (size_t i = 0; i < length; ++i) ++ printf (" %02X", blob[i]); ++ putc ('\n', stdout); ++ } ++} ++ ++static size_t ++string_length_or_zero (const char *str) ++{ ++ if (str == NULL) ++ return 0; ++ else ++ return strlen (str); ++} ++ ++void ++support_test_compare_string (const char *left, const char *right, ++ const char *file, int line, ++ const char *left_expr, const char *right_expr) ++{ ++ /* Two null pointers are accepted. */ ++ if (left == NULL && right == NULL) ++ return; ++ ++ size_t left_length = string_length_or_zero (left); ++ size_t right_length = string_length_or_zero (right); ++ ++ if (left_length != right_length || left == NULL || right == NULL ++ || memcmp (left, right, left_length) != 0) ++ { ++ support_record_failure (); ++ printf ("%s:%d: error: blob comparison failed\n", file, line); ++ if (left_length == right_length && right != NULL && left != NULL) ++ printf (" string length: %zu bytes\n", left_length); ++ else ++ { ++ report_length ("left", left, left_length); ++ report_length ("right", right, right_length); ++ } ++ report_string ("left", (const unsigned char *) left, ++ left_length, left_expr); ++ report_string ("right", (const unsigned char *) right, ++ right_length, right_expr); ++ } +} diff --git a/support/support_test_main.c b/support/support_test_main.c new file mode 100644 -index 0000000000..396385729b +index 0000000000..23429779ac --- /dev/null +++ b/support/support_test_main.c -@@ -0,0 +1,424 @@ +@@ -0,0 +1,425 @@ +/* Main worker function for the test driver. + Copyright (C) 1998-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. @@ -4947,7 +6578,8 @@ index 0000000000..396385729b + timeout = DEFAULT_TIMEOUT; + + /* Make sure we see all message, even those on stdout. */ -+ setvbuf (stdout, NULL, _IONBF, 0); ++ if (!config->no_setvbuf) ++ setvbuf (stdout, NULL, _IONBF, 0); + + /* Make sure temporary files are deleted. */ + if (support_delete_temp_files != NULL) @@ -5101,10 +6733,10 @@ index 0000000000..396385729b +} diff --git a/support/support_test_verify_impl.c b/support/support_test_verify_impl.c new file mode 100644 -index 0000000000..80311a8265 +index 0000000000..5ff5555a6a --- /dev/null +++ b/support/support_test_verify_impl.c -@@ -0,0 +1,37 @@ +@@ -0,0 +1,40 @@ +/* Implementation of the TEST_VERIFY and TEST_VERIFY_EXIT macros. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. @@ -5125,14 +6757,17 @@ index 0000000000..80311a8265 + +#include <support/check.h> + ++#include <errno.h> +#include <stdio.h> +#include <stdlib.h> + +void +support_test_verify_impl (const char *file, int line, const char *expr) +{ ++ int saved_errno = errno; + support_record_failure (); + printf ("error: %s:%d: not true: %s\n", file, line, expr); ++ errno = saved_errno; +} + +void @@ -5406,29 +7041,1023 @@ index 0000000000..c7795cc577 + +__BEGIN_DECLS + -+/* Schedule a temporary file for deletion on exit. */ -+void add_temp_file (const char *name); ++/* Schedule a temporary file for deletion on exit. */ ++void add_temp_file (const char *name); ++ ++/* Create a temporary file. Return the opened file descriptor on ++ success, or -1 on failure. Write the file name to *FILENAME if ++ FILENAME is not NULL. In this case, the caller is expected to free ++ *FILENAME. */ ++int create_temp_file (const char *base, char **filename); ++ ++/* Create a temporary directory and schedule it for deletion. BASE is ++ used as a prefix for the unique directory name, which the function ++ returns. The caller should free this string. */ ++char *support_create_temp_directory (const char *base); ++ ++__END_DECLS ++ ++#endif /* SUPPORT_TEMP_FILE_H */ +diff --git a/support/test-container.c b/support/test-container.c +new file mode 100644 +index 0000000000..b58f0f7b3d +--- /dev/null ++++ b/support/test-container.c +@@ -0,0 +1,988 @@ ++/* Run a test case in an isolated namespace. ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#define _FILE_OFFSET_BITS 64 ++ ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <sched.h> ++#include <sys/syscall.h> ++#include <unistd.h> ++#include <sys/types.h> ++#include <dirent.h> ++#include <string.h> ++#include <sys/stat.h> ++#include <sys/fcntl.h> ++#include <sys/file.h> ++#include <sys/wait.h> ++#include <stdarg.h> ++#include <sys/sysmacros.h> ++#include <ctype.h> ++#include <utime.h> ++#include <errno.h> ++#include <error.h> ++#include <libc-pointer-arith.h> ++ ++#ifdef __linux__ ++#include <sys/mount.h> ++#endif ++ ++#include <support/support.h> ++#include <support/xunistd.h> ++#include "check.h" ++#include "test-driver.h" ++ ++#ifndef __linux__ ++#define mount(s,t,fs,f,d) no_mount() ++int no_mount (void) ++{ ++ FAIL_UNSUPPORTED("mount not supported; port needed"); ++} ++#endif ++ ++int verbose = 0; ++ ++/* Running a test in a container is tricky. There are two main ++ categories of things to do: ++ ++ 1. "Once" actions, like setting up the container and doing an ++ install into it. ++ ++ 2. "Per-test" actions, like copying in support files and ++ configuring the container. ++ ++ ++ "Once" actions: ++ ++ * mkdir $buildroot/testroot.pristine/ ++ * install into it ++ * rsync to $buildroot/testroot.root/ ++ ++ "Per-test" actions: ++ * maybe rsync to $buildroot/testroot.root/ ++ * copy support files and test binary ++ * chroot/unshare ++ * set up any mounts (like /proc) ++ ++ Magic files: ++ ++ For test $srcdir/foo/mytest.c we look for $srcdir/foo/mytest.root ++ and, if found... ++ ++ * mytest.root/ is rsync'd into container ++ * mytest.root/preclean.req causes fresh rsync (with delete) before ++ test if present ++ * mytest.root/mytset.script has a list of "commands" to run: ++ syntax: ++ # comment ++ mv FILE FILE ++ cp FILE FILE ++ rm FILE ++ FILE must start with $B/, $S/, $I/, $L/, or / ++ (expands to build dir, source dir, install dir, library dir ++ (in container), or container's root) ++ * mytest.root/postclean.req causes fresh rsync (with delete) after ++ test if present ++ ++ Note that $srcdir/foo/mytest.script may be used instead of a ++ $srcdir/foo/mytest.root/mytest.script in the sysroot template, if ++ there is no other reason for a sysroot. ++ ++ Design goals: ++ ++ * independent of other packages which may not be installed (like ++ rsync or Docker, or even "cp") ++ ++ * Simple, easy to review code (i.e. prefer simple naive code over ++ complex efficient code) ++ ++ * The current implementation ist parallel-make-safe, but only in ++ that it uses a lock to prevent parallel access to the testroot. */ ++ ++ ++/* Utility Functions */ ++ ++/* Like xunlink, but it's OK if the file already doesn't exist. */ ++void ++maybe_xunlink (const char *path) ++{ ++ int rv = unlink (path); ++ if (rv < 0 && errno != ENOENT) ++ FAIL_EXIT1 ("unlink (\"%s\"): %m", path); ++} ++ ++/* Like xmkdir, but it's OK if the directory already exists. */ ++void ++maybe_xmkdir (const char *path, mode_t mode) ++{ ++ struct stat st; ++ ++ if (stat (path, &st) == 0 ++ && S_ISDIR (st.st_mode)) ++ return; ++ xmkdir (path, mode); ++} ++ ++/* Temporarily concatenate multiple strings into one. Allows up to 10 ++ temporary results; use strdup () if you need them to be ++ permanent. */ ++static char * ++concat (const char *str, ...) ++{ ++ /* Assume initialized to NULL/zero. */ ++ static char *bufs[10]; ++ static size_t buflens[10]; ++ static int bufn = 0; ++ int n; ++ size_t len; ++ va_list ap, ap2; ++ char *cp; ++ char *next; ++ ++ va_start (ap, str); ++ va_copy (ap2, ap); ++ ++ n = bufn; ++ bufn = (bufn + 1) % 10; ++ len = strlen (str); ++ ++ while ((next = va_arg (ap, char *)) != NULL) ++ len = len + strlen (next); ++ ++ va_end (ap); ++ ++ if (bufs[n] == NULL) ++ { ++ bufs[n] = xmalloc (len + 1); /* NUL */ ++ buflens[n] = len + 1; ++ } ++ else if (buflens[n] < len + 1) ++ { ++ bufs[n] = xrealloc (bufs[n], len + 1); /* NUL */ ++ buflens[n] = len + 1; ++ } ++ ++ strcpy (bufs[n], str); ++ cp = strchr (bufs[n], '\0'); ++ while ((next = va_arg (ap2, char *)) != NULL) ++ { ++ strcpy (cp, next); ++ cp = strchr (cp, '\0'); ++ } ++ *cp = 0; ++ va_end (ap2); ++ ++ return bufs[n]; ++} ++ ++/* Try to mount SRC onto DEST. */ ++static void ++trymount (const char *src, const char *dest) ++{ ++ if (mount (src, dest, "", MS_BIND, NULL) < 0) ++ FAIL_EXIT1 ("can't mount %s onto %s\n", src, dest); ++} ++ ++/* Special case of above for devices like /dev/zero where we have to ++ mount a device over a device, not a directory over a directory. */ ++static void ++devmount (const char *new_root_path, const char *which) ++{ ++ int fd; ++ fd = open (concat (new_root_path, "/dev/", which, NULL), ++ O_CREAT | O_TRUNC | O_RDWR, 0777); ++ xclose (fd); ++ ++ trymount (concat ("/dev/", which, NULL), ++ concat (new_root_path, "/dev/", which, NULL)); ++} ++ ++/* Returns true if the string "looks like" an environement variable ++ being set. */ ++static int ++is_env_setting (const char *a) ++{ ++ int count_name = 0; ++ ++ while (*a) ++ { ++ if (isalnum (*a) || *a == '_') ++ ++count_name; ++ else if (*a == '=' && count_name > 0) ++ return 1; ++ else ++ return 0; ++ ++a; ++ } ++ return 0; ++} ++ ++/* Break the_line into words and store in the_words. Max nwords, ++ returns actual count. */ ++static int ++tokenize (char *the_line, char **the_words, int nwords) ++{ ++ int rv = 0; ++ ++ while (nwords > 0) ++ { ++ /* Skip leading whitespace, if any. */ ++ while (*the_line && isspace (*the_line)) ++ ++the_line; ++ ++ /* End of line? */ ++ if (*the_line == 0) ++ return rv; ++ ++ /* THE_LINE points to a non-whitespace character, so we have a ++ word. */ ++ *the_words = the_line; ++ ++the_words; ++ nwords--; ++ ++rv; ++ ++ /* Skip leading whitespace, if any. */ ++ while (*the_line && ! isspace (*the_line)) ++ ++the_line; ++ ++ /* We now point at the trailing NUL *or* some whitespace. */ ++ if (*the_line == 0) ++ return rv; ++ ++ /* It was whitespace, skip and keep tokenizing. */ ++ *the_line++ = 0; ++ } ++ ++ /* We get here if we filled the words buffer. */ ++ return rv; ++} ++ ++ ++/* Mini-RSYNC implementation. Optimize later. */ ++ ++/* A few routines for an "rsync buffer" which stores the paths we're ++ working on. We continuously grow and shrink the paths in each ++ buffer so there's lot of re-use. */ ++ ++/* We rely on "initialized to zero" to set these up. */ ++typedef struct ++{ ++ char *buf; ++ size_t len; ++ size_t size; ++} path_buf; ++ ++static path_buf spath, dpath; ++ ++static void ++r_setup (char *path, path_buf * pb) ++{ ++ size_t len = strlen (path); ++ if (pb->buf == NULL || pb->size < len + 1) ++ { ++ /* Round up. This is an arbitrary number, just to keep from ++ reallocing too often. */ ++ size_t sz = ALIGN_UP (len + 1, 512); ++ if (pb->buf == NULL) ++ pb->buf = (char *) xmalloc (sz); ++ else ++ pb->buf = (char *) xrealloc (pb->buf, sz); ++ if (pb->buf == NULL) ++ FAIL_EXIT1 ("Out of memory while rsyncing\n"); ++ ++ pb->size = sz; ++ } ++ strcpy (pb->buf, path); ++ pb->len = len; ++} ++ ++static void ++r_append (const char *path, path_buf * pb) ++{ ++ size_t len = strlen (path) + pb->len; ++ if (pb->size < len + 1) ++ { ++ /* Round up */ ++ size_t sz = ALIGN_UP (len + 1, 512); ++ pb->buf = (char *) xrealloc (pb->buf, sz); ++ if (pb->buf == NULL) ++ FAIL_EXIT1 ("Out of memory while rsyncing\n"); ++ ++ pb->size = sz; ++ } ++ strcpy (pb->buf + pb->len, path); ++ pb->len = len; ++} ++ ++static int ++file_exists (char *path) ++{ ++ struct stat st; ++ if (lstat (path, &st) == 0) ++ return 1; ++ return 0; ++} ++ ++static void ++recursive_remove (char *path) ++{ ++ pid_t child; ++ int status; ++ ++ child = fork (); ++ ++ switch (child) { ++ case -1: ++ FAIL_EXIT1 ("Unable to fork"); ++ case 0: ++ /* Child. */ ++ execlp ("rm", "rm", "-rf", path, NULL); ++ default: ++ /* Parent. */ ++ waitpid (child, &status, 0); ++ /* "rm" would have already printed a suitable error message. */ ++ if (! WIFEXITED (status) ++ || WEXITSTATUS (status) != 0) ++ exit (1); ++ ++ break; ++ } ++} ++ ++/* Used for both rsync and the mytest.script "cp" command. */ ++static void ++copy_one_file (const char *sname, const char *dname) ++{ ++ int sfd, dfd; ++ struct stat st; ++ struct utimbuf times; ++ ++ sfd = open (sname, O_RDONLY); ++ if (sfd < 0) ++ FAIL_EXIT1 ("unable to open %s for reading\n", sname); ++ ++ if (fstat (sfd, &st) < 0) ++ FAIL_EXIT1 ("unable to fstat %s\n", sname); ++ ++ dfd = open (dname, O_WRONLY | O_TRUNC | O_CREAT, 0600); ++ if (dfd < 0) ++ FAIL_EXIT1 ("unable to open %s for writing\n", dname); ++ ++ xcopy_file_range (sfd, 0, dfd, 0, st.st_size, 0); ++ ++ xclose (sfd); ++ xclose (dfd); ++ ++ if (chmod (dname, st.st_mode & 0777) < 0) ++ FAIL_EXIT1 ("chmod %s: %s\n", dname, strerror (errno)); ++ ++ times.actime = st.st_atime; ++ times.modtime = st.st_mtime; ++ if (utime (dname, ×) < 0) ++ FAIL_EXIT1 ("utime %s: %s\n", dname, strerror (errno)); ++} ++ ++/* We don't check *everything* about the two files to see if a copy is ++ needed, just the minimum to make sure we get the latest copy. */ ++static int ++need_sync (char *ap, char *bp, struct stat *a, struct stat *b) ++{ ++ if ((a->st_mode & S_IFMT) != (b->st_mode & S_IFMT)) ++ return 1; ++ ++ if (S_ISLNK (a->st_mode)) ++ { ++ int rv; ++ char *al, *bl; ++ ++ if (a->st_size != b->st_size) ++ return 1; ++ ++ al = xreadlink (ap); ++ bl = xreadlink (bp); ++ rv = strcmp (al, bl); ++ free (al); ++ free (bl); ++ if (rv == 0) ++ return 0; /* links are same */ ++ return 1; /* links differ */ ++ } ++ ++ if (verbose) ++ { ++ if (a->st_size != b->st_size) ++ printf ("SIZE\n"); ++ if ((a->st_mode & 0777) != (b->st_mode & 0777)) ++ printf ("MODE\n"); ++ if (a->st_mtime != b->st_mtime) ++ printf ("TIME\n"); ++ } ++ ++ if (a->st_size == b->st_size ++ && ((a->st_mode & 0777) == (b->st_mode & 0777)) ++ && a->st_mtime == b->st_mtime) ++ return 0; ++ ++ return 1; ++} ++ ++static void ++rsync_1 (path_buf * src, path_buf * dest, int and_delete) ++{ ++ DIR *dir; ++ struct dirent *de; ++ struct stat s, d; ++ ++ r_append ("/", src); ++ r_append ("/", dest); ++ ++ if (verbose) ++ printf ("sync %s to %s %s\n", src->buf, dest->buf, ++ and_delete ? "and delete" : ""); ++ ++ size_t staillen = src->len; ++ ++ size_t dtaillen = dest->len; ++ ++ dir = opendir (src->buf); ++ ++ while ((de = readdir (dir)) != NULL) ++ { ++ if (strcmp (de->d_name, ".") == 0 ++ || strcmp (de->d_name, "..") == 0) ++ continue; ++ ++ src->len = staillen; ++ r_append (de->d_name, src); ++ dest->len = dtaillen; ++ r_append (de->d_name, dest); ++ ++ s.st_mode = ~0; ++ d.st_mode = ~0; ++ ++ if (lstat (src->buf, &s) != 0) ++ FAIL_EXIT1 ("%s obtained by readdir, but stat failed.\n", src->buf); ++ ++ /* It's OK if this one fails, since we know the file might be ++ missing. */ ++ lstat (dest->buf, &d); ++ ++ if (! need_sync (src->buf, dest->buf, &s, &d)) ++ { ++ if (S_ISDIR (s.st_mode)) ++ rsync_1 (src, dest, and_delete); ++ continue; ++ } ++ ++ if (d.st_mode != ~0) ++ switch (d.st_mode & S_IFMT) ++ { ++ case S_IFDIR: ++ if (!S_ISDIR (s.st_mode)) ++ { ++ if (verbose) ++ printf ("-D %s\n", dest->buf); ++ recursive_remove (dest->buf); ++ } ++ break; ++ ++ default: ++ if (verbose) ++ printf ("-F %s\n", dest->buf); ++ maybe_xunlink (dest->buf); ++ break; ++ } ++ ++ switch (s.st_mode & S_IFMT) ++ { ++ case S_IFREG: ++ if (verbose) ++ printf ("+F %s\n", dest->buf); ++ copy_one_file (src->buf, dest->buf); ++ break; ++ ++ case S_IFDIR: ++ if (verbose) ++ printf ("+D %s\n", dest->buf); ++ maybe_xmkdir (dest->buf, (s.st_mode & 0777) | 0700); ++ rsync_1 (src, dest, and_delete); ++ break; ++ ++ case S_IFLNK: ++ { ++ char *lp; ++ if (verbose) ++ printf ("+L %s\n", dest->buf); ++ lp = xreadlink (src->buf); ++ xsymlink (lp, dest->buf); ++ free (lp); ++ break; ++ } ++ ++ default: ++ break; ++ } ++ } ++ ++ closedir (dir); ++ src->len = staillen; ++ src->buf[staillen] = 0; ++ dest->len = dtaillen; ++ dest->buf[dtaillen] = 0; ++ ++ if (!and_delete) ++ return; ++ ++ /* The rest of this function removes any files/directories in DEST ++ that do not exist in SRC. This is triggered as part of a ++ preclean or postsclean step. */ ++ ++ dir = opendir (dest->buf); ++ ++ while ((de = readdir (dir)) != NULL) ++ { ++ if (strcmp (de->d_name, ".") == 0 ++ || strcmp (de->d_name, "..") == 0) ++ continue; ++ ++ src->len = staillen; ++ r_append (de->d_name, src); ++ dest->len = dtaillen; ++ r_append (de->d_name, dest); ++ ++ s.st_mode = ~0; ++ d.st_mode = ~0; ++ ++ lstat (src->buf, &s); ++ ++ if (lstat (dest->buf, &d) != 0) ++ FAIL_EXIT1 ("%s obtained by readdir, but stat failed.\n", dest->buf); ++ ++ if (s.st_mode == ~0) ++ { ++ /* dest exists and src doesn't, clean it. */ ++ switch (d.st_mode & S_IFMT) ++ { ++ case S_IFDIR: ++ if (!S_ISDIR (s.st_mode)) ++ { ++ if (verbose) ++ printf ("-D %s\n", dest->buf); ++ recursive_remove (dest->buf); ++ } ++ break; ++ ++ default: ++ if (verbose) ++ printf ("-F %s\n", dest->buf); ++ maybe_xunlink (dest->buf); ++ break; ++ } ++ } ++ } ++ ++ closedir (dir); ++} ++ ++static void ++rsync (char *src, char *dest, int and_delete) ++{ ++ r_setup (src, &spath); ++ r_setup (dest, &dpath); ++ ++ rsync_1 (&spath, &dpath, and_delete); ++} ++ ++ ++int ++main (int argc, char **argv) ++{ ++ pid_t child; ++ char *pristine_root_path; ++ char *new_root_path; ++ char *new_cwd_path; ++ char *new_objdir_path; ++ char *new_srcdir_path; ++ char **new_child_proc; ++ char *command_root; ++ char *command_base; ++ char *command_basename; ++ char *so_base; ++ int do_postclean = 0; ++ ++ uid_t original_uid; ++ gid_t original_gid; ++ int UMAP; ++ int GMAP; ++ /* Used for "%lld %lld 1" so need not be large. */ ++ char tmp[100]; ++ struct stat st; ++ int lock_fd; ++ ++ setbuf (stdout, NULL); ++ ++ /* The command line we're expecting looks like this: ++ env <set some vars> ld.so <library path> test-binary ++ ++ We need to peel off any "env" or "ld.so" portion of the command ++ line, and keep track of which env vars we should preserve and ++ which we drop. */ ++ ++ if (argc < 2) ++ { ++ fprintf (stderr, "Usage: containerize <program to run> <args...>\n"); ++ exit (1); ++ } ++ ++ if (strcmp (argv[1], "-v") == 0) ++ { ++ verbose = 1; ++ ++argv; ++ --argc; ++ } ++ ++ if (strcmp (argv[1], "env") == 0) ++ { ++ ++argv; ++ --argc; ++ while (is_env_setting (argv[1])) ++ { ++ /* If there are variables we do NOT want to propogate, this ++ is where the test for them goes. */ ++ { ++ /* Need to keep these. Note that putenv stores a ++ pointer to our argv. */ ++ putenv (argv[1]); ++ } ++ ++argv; ++ --argc; ++ } ++ } ++ ++ if (strcmp (argv[1], support_objdir_elf_ldso) == 0) ++ { ++ ++argv; ++ --argc; ++ while (argv[1][0] == '-') ++ { ++ if (strcmp (argv[1], "--library-path") == 0) ++ { ++ ++argv; ++ --argc; ++ } ++ ++argv; ++ --argc; ++ } ++ } ++ ++ pristine_root_path = strdup (concat (support_objdir_root, ++ "/testroot.pristine", NULL)); ++ new_root_path = strdup (concat (support_objdir_root, ++ "/testroot.root", NULL)); ++ new_cwd_path = get_current_dir_name (); ++ new_child_proc = argv + 1; ++ ++ lock_fd = open (concat (pristine_root_path, "/lock.fd", NULL), ++ O_CREAT | O_TRUNC | O_RDWR, 0666); ++ if (lock_fd < 0) ++ FAIL_EXIT1 ("Cannot create testroot lock.\n"); ++ ++ while (flock (lock_fd, LOCK_EX) != 0) ++ { ++ if (errno != EINTR) ++ FAIL_EXIT1 ("Cannot lock testroot.\n"); ++ } ++ ++ xmkdirp (new_root_path, 0755); ++ ++ /* We look for extra setup info in a subdir in the same spot as the ++ test, with the same name but a ".root" extension. This is that ++ directory. We try to look in the source tree if the path we're ++ given refers to the build tree, but we rely on the path to be ++ absolute. This is what the glibc makefiles do. */ ++ command_root = concat (argv[1], ".root", NULL); ++ if (strncmp (command_root, support_objdir_root, ++ strlen (support_objdir_root)) == 0 ++ && command_root[strlen (support_objdir_root)] == '/') ++ command_root = concat (support_srcdir_root, ++ argv[1] + strlen (support_objdir_root), ++ ".root", NULL); ++ command_root = strdup (command_root); ++ ++ /* This cuts off the ".root" we appended above. */ ++ command_base = strdup (command_root); ++ command_base[strlen (command_base) - 5] = 0; ++ ++ /* This is the basename of the test we're running. */ ++ command_basename = strrchr (command_base, '/'); ++ if (command_basename == NULL) ++ command_basename = command_base; ++ else ++ ++command_basename; ++ ++ /* Shared object base directory. */ ++ so_base = strdup (argv[1]); ++ if (strrchr (so_base, '/') != NULL) ++ strrchr (so_base, '/')[1] = 0; ++ ++ if (file_exists (concat (command_root, "/postclean.req", NULL))) ++ do_postclean = 1; ++ ++ rsync (pristine_root_path, new_root_path, ++ file_exists (concat (command_root, "/preclean.req", NULL))); ++ ++ if (stat (command_root, &st) >= 0 ++ && S_ISDIR (st.st_mode)) ++ rsync (command_root, new_root_path, 0); ++ ++ new_objdir_path = strdup (concat (new_root_path, ++ support_objdir_root, NULL)); ++ new_srcdir_path = strdup (concat (new_root_path, ++ support_srcdir_root, NULL)); ++ ++ /* new_cwd_path starts with '/' so no "/" needed between the two. */ ++ xmkdirp (concat (new_root_path, new_cwd_path, NULL), 0755); ++ xmkdirp (new_srcdir_path, 0755); ++ xmkdirp (new_objdir_path, 0755); ++ ++ original_uid = getuid (); ++ original_gid = getgid (); ++ ++ /* Handle the cp/mv/rm "script" here. */ ++ { ++ char *the_line = NULL; ++ size_t line_len = 0; ++ char *fname = concat (command_root, "/", ++ command_basename, ".script", NULL); ++ char *the_words[3]; ++ FILE *f = fopen (fname, "r"); ++ ++ if (verbose && f) ++ fprintf (stderr, "running %s\n", fname); ++ ++ if (f == NULL) ++ { ++ /* Try foo.script instead of foo.root/foo.script, as a shortcut. */ ++ fname = concat (command_base, ".script", NULL); ++ f = fopen (fname, "r"); ++ if (verbose && f) ++ fprintf (stderr, "running %s\n", fname); ++ } ++ ++ /* Note that we do NOT look for a Makefile-generated foo.script in ++ the build directory. If that is ever needed, this is the place ++ to add it. */ ++ ++ /* This is where we "interpret" the mini-script which is <test>.script. */ ++ if (f != NULL) ++ { ++ while (getline (&the_line, &line_len, f) > 0) ++ { ++ int nt = tokenize (the_line, the_words, 3); ++ int i; ++ ++ for (i = 1; i < nt; ++i) ++ { ++ if (memcmp (the_words[i], "$B/", 3) == 0) ++ the_words[i] = concat (support_objdir_root, ++ the_words[i] + 2, NULL); ++ else if (memcmp (the_words[i], "$S/", 3) == 0) ++ the_words[i] = concat (support_srcdir_root, ++ the_words[i] + 2, NULL); ++ else if (memcmp (the_words[i], "$I/", 3) == 0) ++ the_words[i] = concat (new_root_path, ++ support_install_prefix, ++ the_words[i] + 2, NULL); ++ else if (memcmp (the_words[i], "$L/", 3) == 0) ++ the_words[i] = concat (new_root_path, ++ support_libdir_prefix, ++ the_words[i] + 2, NULL); ++ else if (the_words[i][0] == '/') ++ the_words[i] = concat (new_root_path, ++ the_words[i], NULL); ++ } ++ ++ if (nt == 3 && the_words[2][strlen (the_words[2]) - 1] == '/') ++ { ++ char *r = strrchr (the_words[1], '/'); ++ if (r) ++ the_words[2] = concat (the_words[2], r + 1, NULL); ++ else ++ the_words[2] = concat (the_words[2], the_words[1], NULL); ++ } ++ ++ if (nt == 2 && strcmp (the_words[0], "so") == 0) ++ { ++ the_words[2] = concat (new_root_path, support_libdir_prefix, ++ "/", the_words[1], NULL); ++ the_words[1] = concat (so_base, the_words[1], NULL); ++ copy_one_file (the_words[1], the_words[2]); ++ } ++ else if (nt == 3 && strcmp (the_words[0], "cp") == 0) ++ { ++ copy_one_file (the_words[1], the_words[2]); ++ } ++ else if (nt == 3 && strcmp (the_words[0], "mv") == 0) ++ { ++ if (rename (the_words[1], the_words[2]) < 0) ++ FAIL_EXIT1 ("rename %s -> %s: %s", the_words[1], ++ the_words[2], strerror (errno)); ++ } ++ else if (nt == 3 && strcmp (the_words[0], "chmod") == 0) ++ { ++ long int m; ++ m = strtol (the_words[1], NULL, 0); ++ if (chmod (the_words[2], m) < 0) ++ FAIL_EXIT1 ("chmod %s: %s\n", ++ the_words[2], strerror (errno)); ++ ++ } ++ else if (nt == 2 && strcmp (the_words[0], "rm") == 0) ++ { ++ maybe_xunlink (the_words[1]); ++ } ++ else if (nt > 0 && the_words[0][0] != '#') ++ { ++ printf ("\033[31minvalid [%s]\033[0m\n", the_words[0]); ++ } ++ } ++ fclose (f); ++ } ++ } ++ ++#ifdef CLONE_NEWNS ++ /* The unshare here gives us our own spaces and capabilities. */ ++ if (unshare (CLONE_NEWUSER | CLONE_NEWPID | CLONE_NEWNS) < 0) ++ { ++ /* Older kernels may not support all the options, or security ++ policy may block this call. */ ++ if (errno == EINVAL || errno == EPERM) ++ FAIL_UNSUPPORTED ("unable to unshare user/fs: %s", strerror (errno)); ++ else ++ FAIL_EXIT1 ("unable to unshare user/fs: %s", strerror (errno)); ++ } ++#else ++ /* Some targets may not support unshare at all. */ ++ FAIL_UNSUPPORTED ("unshare support missing"); ++#endif ++ ++ /* Some systems, by default, all mounts leak out of the namespace. */ ++ if (mount ("none", "/", NULL, MS_REC | MS_PRIVATE, NULL) != 0) ++ FAIL_EXIT1 ("could not create a private mount namespace\n"); ++ ++ trymount (support_srcdir_root, new_srcdir_path); ++ trymount (support_objdir_root, new_objdir_path); ++ ++ xmkdirp (concat (new_root_path, "/dev", NULL), 0755); ++ devmount (new_root_path, "null"); ++ devmount (new_root_path, "zero"); ++ devmount (new_root_path, "urandom"); ++ ++ /* We're done with the "old" root, switch to the new one. */ ++ if (chroot (new_root_path) < 0) ++ FAIL_EXIT1 ("Can't chroot to %s - ", new_root_path); ++ ++ if (chdir (new_cwd_path) < 0) ++ FAIL_EXIT1 ("Can't cd to new %s - ", new_cwd_path); ++ ++ /* To complete the containerization, we need to fork () at least ++ once. We can't exec, nor can we somehow link the new child to ++ our parent. So we run the child and propogate it's exit status ++ up. */ ++ child = fork (); ++ if (child < 0) ++ FAIL_EXIT1 ("Unable to fork"); ++ else if (child > 0) ++ { ++ /* Parent. */ ++ int status; ++ waitpid (child, &status, 0); ++ ++ /* There's a bit of magic here, since the buildroot is mounted ++ in our space, the paths are still valid, and since the mounts ++ aren't recursive, it sees *only* the built root, not anything ++ we would normally se if we rsync'd to "/" like mounted /dev ++ files. */ ++ if (do_postclean) ++ rsync (pristine_root_path, new_root_path, 1); ++ ++ if (WIFEXITED (status)) ++ exit (WEXITSTATUS (status)); ++ ++ if (WIFSIGNALED (status)) ++ { ++ printf ("%%SIGNALLED%%\n"); ++ exit (77); ++ } ++ ++ printf ("%%EXITERROR%%\n"); ++ exit (78); ++ } ++ ++ /* The rest is the child process, which is now PID 1 and "in" the ++ new root. */ ++ ++ maybe_xmkdir ("/tmp", 0755); ++ ++ /* Now that we're pid 1 (effectively "root") we can mount /proc */ ++ maybe_xmkdir ("/proc", 0777); ++ if (mount ("proc", "/proc", "proc", 0, NULL) < 0) ++ FAIL_EXIT1 ("Unable to mount /proc: "); ++ ++ /* We map our original UID to the same UID in the container so we ++ can own our own files normally. */ ++ UMAP = open ("/proc/self/uid_map", O_WRONLY); ++ if (UMAP < 0) ++ FAIL_EXIT1 ("can't write to /proc/self/uid_map\n"); ++ ++ sprintf (tmp, "%lld %lld 1\n", ++ (long long) original_uid, (long long) original_uid); ++ write (UMAP, tmp, strlen (tmp)); ++ xclose (UMAP); ++ ++ /* We must disable setgroups () before we can map our groups, else we ++ get EPERM. */ ++ GMAP = open ("/proc/self/setgroups", O_WRONLY); ++ if (GMAP >= 0) ++ { ++ /* We support kernels old enough to not have this. */ ++ write (GMAP, "deny\n", 5); ++ xclose (GMAP); ++ } ++ ++ /* We map our original GID to the same GID in the container so we ++ can own our own files normally. */ ++ GMAP = open ("/proc/self/gid_map", O_WRONLY); ++ if (GMAP < 0) ++ FAIL_EXIT1 ("can't write to /proc/self/gid_map\n"); + -+/* Create a temporary file. Return the opened file descriptor on -+ success, or -1 on failure. Write the file name to *FILENAME if -+ FILENAME is not NULL. In this case, the caller is expected to free -+ *FILENAME. */ -+int create_temp_file (const char *base, char **filename); ++ sprintf (tmp, "%lld %lld 1\n", ++ (long long) original_gid, (long long) original_gid); ++ write (GMAP, tmp, strlen (tmp)); ++ xclose (GMAP); + -+/* Create a temporary directory and schedule it for deletion. BASE is -+ used as a prefix for the unique directory name, which the function -+ returns. The caller should free this string. */ -+char *support_create_temp_directory (const char *base); ++ /* Now run the child. */ ++ execvp (new_child_proc[0], new_child_proc); + -+__END_DECLS ++ /* Or don't run the child? */ ++ FAIL_EXIT1 ("Unable to exec %s\n", new_child_proc[0]); + -+#endif /* SUPPORT_TEMP_FILE_H */ ++ /* Because gcc won't know error () never returns... */ ++ exit (EXIT_UNSUPPORTED); ++} diff --git a/support/test-driver.c b/support/test-driver.c new file mode 100644 -index 0000000000..09c8783e4f +index 0000000000..9798f16227 --- /dev/null +++ b/support/test-driver.c -@@ -0,0 +1,165 @@ +@@ -0,0 +1,169 @@ +/* Main function for test programs. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. @@ -5571,6 +8200,10 @@ index 0000000000..09c8783e4f + test_config.no_mallopt = 1; +#endif + ++#ifdef TEST_NO_SETVBUF ++ test_config.no_setvbuf = 1; ++#endif ++ +#ifdef TIMEOUT + test_config.timeout = TIMEOUT; +#endif @@ -5596,10 +8229,10 @@ index 0000000000..09c8783e4f +} diff --git a/support/test-driver.h b/support/test-driver.h new file mode 100644 -index 0000000000..1708d68d60 +index 0000000000..549179b254 --- /dev/null +++ b/support/test-driver.h -@@ -0,0 +1,75 @@ +@@ -0,0 +1,76 @@ +/* Interfaces for the test driver. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. @@ -5637,6 +8270,7 @@ index 0000000000..1708d68d60 + int expected_status; /* Expected exit status. */ + int expected_signal; /* If non-zero, expect termination by signal. */ + char no_mallopt; /* Boolean flag to disable mallopt. */ ++ char no_setvbuf; /* Boolean flag to disable setvbuf. */ + const char *optstring; /* Short command line options. */ +}; + @@ -5675,6 +8309,38 @@ index 0000000000..1708d68d60 +__END_DECLS + +#endif /* SUPPORT_TEST_DRIVER_H */ +diff --git a/support/true-container.c b/support/true-container.c +new file mode 100644 +index 0000000000..57dc57e252 +--- /dev/null ++++ b/support/true-container.c +@@ -0,0 +1,26 @@ ++/* Minimal /bin/true for in-container use. ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++/* Implements the in-container /bin/true, which always returns true ++ (0). */ ++ ++int ++main (void) ++{ ++ return 0; ++} diff --git a/support/tst-support-namespace.c b/support/tst-support-namespace.c new file mode 100644 index 0000000000..e20423c4a3 @@ -5795,6 +8461,97 @@ index 0000000000..e20423c4a3 +} + +#include <support/test-driver.c> +diff --git a/support/tst-support_blob_repeat.c b/support/tst-support_blob_repeat.c +new file mode 100644 +index 0000000000..1978c14488 +--- /dev/null ++++ b/support/tst-support_blob_repeat.c +@@ -0,0 +1,85 @@ ++/* Tests for <support/blob_repeat.h> ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <stdio.h> ++#include <support/blob_repeat.h> ++#include <support/check.h> ++ ++static int ++do_test (void) ++{ ++ struct support_blob_repeat repeat ++ = support_blob_repeat_allocate ("5", 1, 5); ++ TEST_COMPARE_BLOB (repeat.start, repeat.size, "55555", 5); ++ support_blob_repeat_free (&repeat); ++ ++ repeat = support_blob_repeat_allocate ("ABC", 3, 3); ++ TEST_COMPARE_BLOB (repeat.start, repeat.size, "ABCABCABC", 9); ++ support_blob_repeat_free (&repeat); ++ ++ repeat = support_blob_repeat_allocate ("abc", 4, 3); ++ TEST_COMPARE_BLOB (repeat.start, repeat.size, "abc\0abc\0abc", 12); ++ support_blob_repeat_free (&repeat); ++ ++ size_t gigabyte = 1U << 30; ++ repeat = support_blob_repeat_allocate ("X", 1, gigabyte + 1); ++ if (repeat.start == NULL) ++ puts ("warning: not enough memory for 1 GiB mapping"); ++ else ++ { ++ TEST_COMPARE (repeat.size, gigabyte + 1); ++ { ++ unsigned char *p = repeat.start; ++ for (size_t i = 0; i < gigabyte + 1; ++i) ++ if (p[i] != 'X') ++ FAIL_EXIT1 ("invalid byte 0x%02x at %zu", p[i], i); ++ ++ /* Check that there is no sharing across the mapping. */ ++ p[0] = 'Y'; ++ p[1U << 24] = 'Z'; ++ for (size_t i = 0; i < gigabyte + 1; ++i) ++ if (i == 0) ++ TEST_COMPARE (p[i], 'Y'); ++ else if (i == 1U << 24) ++ TEST_COMPARE (p[i], 'Z'); ++ else if (p[i] != 'X') ++ FAIL_EXIT1 ("invalid byte 0x%02x at %zu", p[i], i); ++ } ++ } ++ support_blob_repeat_free (&repeat); ++ ++ repeat = support_blob_repeat_allocate ("012345678", 9, 10 * 1000 * 1000); ++ if (repeat.start == NULL) ++ puts ("warning: not enough memory for large mapping"); ++ else ++ { ++ unsigned char *p = repeat.start; ++ for (int i = 0; i < 10 * 1000 * 1000; ++i) ++ for (int j = 0; j <= 8; ++j) ++ if (p[i * 9 + j] != '0' + j) ++ { ++ printf ("error: element %d index %d\n", i, j); ++ TEST_COMPARE (p[i * 9 + j], '0' + j); ++ } ++ } ++ support_blob_repeat_free (&repeat); ++ ++ return 0; ++} ++ ++#include <support/test-driver.c> diff --git a/support/tst-support_capture_subprocess.c b/support/tst-support_capture_subprocess.c new file mode 100644 index 0000000000..a685256091 @@ -6096,6 +8853,73 @@ index 0000000000..b1135eebc6 +} + +#include <support/test-driver.c> +diff --git a/support/tst-support_quote_blob.c b/support/tst-support_quote_blob.c +new file mode 100644 +index 0000000000..5467a190a6 +--- /dev/null ++++ b/support/tst-support_quote_blob.c +@@ -0,0 +1,61 @@ ++/* Test the support_quote_blob function. ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <support/check.h> ++#include <support/support.h> ++#include <string.h> ++#include <stdlib.h> ++ ++static int ++do_test (void) ++{ ++ /* Check handling of the empty blob, both with and without trailing ++ NUL byte. */ ++ char *p = support_quote_blob ("", 0); ++ TEST_COMPARE (strlen (p), 0); ++ free (p); ++ p = support_quote_blob ("X", 0); ++ TEST_COMPARE (strlen (p), 0); ++ free (p); ++ ++ /* Check escaping of backslash-escaped characters, and lack of ++ escaping for other shell meta-characters. */ ++ p = support_quote_blob ("$()*?`@[]{}~\'\"X", 14); ++ TEST_COMPARE (strcmp (p, "$()*?`@[]{}~\\'\\\""), 0); ++ free (p); ++ ++ /* Check lack of escaping for letters and digits. */ ++#define LETTERS_AND_DIGTS \ ++ "abcdefghijklmnopqrstuvwxyz" \ ++ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ ++ "0123456789" ++ p = support_quote_blob (LETTERS_AND_DIGTS "@", 2 * 26 + 10); ++ TEST_COMPARE (strcmp (p, LETTERS_AND_DIGTS), 0); ++ free (p); ++ ++ /* Check escaping of control characters and other non-printable ++ characters. */ ++ p = support_quote_blob ("\r\n\t\a\b\f\v\1\177\200\377\0@", 14); ++ TEST_COMPARE (strcmp (p, "\\r\\n\\t\\a\\b\\f\\v\\001" ++ "\\177\\200\\377\\000@\\000"), 0); ++ free (p); ++ ++ return 0; ++} ++ ++#include <support/test-driver.c> diff --git a/support/tst-support_record_failure-2.sh b/support/tst-support_record_failure-2.sh new file mode 100644 index 0000000000..09cd96290a @@ -6380,47 +9204,264 @@ index 0000000000..123ba1bc3c + unsigned long long int u63 : 63; +}; + -+/* Functions which return signed sizes are common, so test that these -+ results can readily checked using TEST_COMPARE. */ ++/* Functions which return signed sizes are common, so test that these ++ results can readily checked using TEST_COMPARE. */ ++ ++static int ++return_ssize_t (void) ++{ ++ return 4; ++} ++ ++static int ++return_int (void) ++{ ++ return 4; ++} ++ ++ ++static int ++do_test (void) ++{ ++ /* This should succeed. */ ++ TEST_COMPARE (1, 1); ++ TEST_COMPARE (2LL, 2U); ++ { ++ char i8 = 3; ++ unsigned short u16 = 3; ++ TEST_COMPARE (i8, u16); ++ } ++ TEST_COMPARE (return_ssize_t (), sizeof (char[4])); ++ TEST_COMPARE (return_int (), sizeof (char[4])); ++ ++ struct bitfield bitfield = { 0 }; ++ TEST_COMPARE (bitfield.i2, bitfield.i3); ++ TEST_COMPARE (bitfield.u2, bitfield.u3); ++ TEST_COMPARE (bitfield.u2, bitfield.i3); ++ TEST_COMPARE (bitfield.u3, bitfield.i3); ++ TEST_COMPARE (bitfield.i2, bitfield.u3); ++ TEST_COMPARE (bitfield.i3, bitfield.u2); ++ TEST_COMPARE (bitfield.i63, bitfield.i63); ++ TEST_COMPARE (bitfield.u63, bitfield.u63); ++ TEST_COMPARE (bitfield.i31, bitfield.i63); ++ TEST_COMPARE (bitfield.i63, bitfield.i31); ++ ++ struct support_capture_subprocess proc = support_capture_subprocess ++ (&subprocess, NULL); ++ ++ /* Discard the reported error. */ ++ support_record_failure_reset (); ++ ++ puts ("info: *** subprocess output starts ***"); ++ fputs (proc.out.buffer, stdout); ++ puts ("info: *** subprocess output ends ***"); ++ ++ TEST_VERIFY ++ (strcmp (proc.out.buffer, ++ "tst-test_compare.c:28: numeric comparison failure\n" ++ " left: 1 (0x1); from: ch\n" ++ " right: -1 (0xffffffff); from: -1\n" ++ "tst-test_compare.c:29: numeric comparison failure\n" ++ " left: 2 (0x2); from: 2LL\n" ++ " right: -2 (0xfffffffffffffffe); from: -2LL\n" ++ "tst-test_compare.c:30: numeric comparison failure" ++ " (widths 64 and 32)\n" ++ " left: 3 (0x3); from: 3LL\n" ++ " right: -3 (0xfffffffd); from: (short) -3\n") == 0); ++ ++ /* Check that there is no output on standard error. */ ++ support_capture_subprocess_check (&proc, "TEST_COMPARE", 0, sc_allow_stdout); ++ ++ return 0; ++} ++ ++#include <support/test-driver.c> +diff --git a/support/tst-test_compare_blob.c b/support/tst-test_compare_blob.c +new file mode 100644 +index 0000000000..aa8643e182 +--- /dev/null ++++ b/support/tst-test_compare_blob.c +@@ -0,0 +1,125 @@ ++/* Basic test for the TEST_COMPARE_BLOB macro. ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <string.h> ++#include <support/check.h> ++#include <support/capture_subprocess.h> ++ ++static void ++subprocess (void *closure) ++{ ++ /* These tests should fail. They were chosen to cover differences ++ in length (with the same contents), single-bit mismatches, and ++ mismatching null pointers. */ ++ TEST_COMPARE_BLOB ("", 0, "", 1); /* Line 29. */ ++ TEST_COMPARE_BLOB ("X", 1, "", 1); /* Line 30. */ ++ TEST_COMPARE_BLOB ("abcd", 3, "abcd", 4); /* Line 31. */ ++ TEST_COMPARE_BLOB ("abcd", 4, "abcD", 4); /* Line 32. */ ++ TEST_COMPARE_BLOB ("abcd", 4, NULL, 0); /* Line 33. */ ++ TEST_COMPARE_BLOB (NULL, 0, "abcd", 4); /* Line 34. */ ++} ++ ++/* Same contents, different addresses. */ ++char buffer_abc_1[] = "abc"; ++char buffer_abc_2[] = "abc"; ++ ++static int ++do_test (void) ++{ ++ /* This should succeed. Even if the pointers and array contents are ++ different, zero-length inputs are not different. */ ++ TEST_COMPARE_BLOB ("", 0, "", 0); ++ TEST_COMPARE_BLOB ("", 0, buffer_abc_1, 0); ++ TEST_COMPARE_BLOB (buffer_abc_1, 0, "", 0); ++ TEST_COMPARE_BLOB (NULL, 0, "", 0); ++ TEST_COMPARE_BLOB ("", 0, NULL, 0); ++ TEST_COMPARE_BLOB (NULL, 0, NULL, 0); ++ ++ /* Check equality of blobs containing a single NUL byte. */ ++ TEST_COMPARE_BLOB ("", 1, "", 1); ++ TEST_COMPARE_BLOB ("", 1, &buffer_abc_1[3], 1); ++ ++ /* Check equality of blobs of varying lengths. */ ++ for (size_t i = 0; i <= sizeof (buffer_abc_1); ++i) ++ TEST_COMPARE_BLOB (buffer_abc_1, i, buffer_abc_2, i); ++ ++ struct support_capture_subprocess proc = support_capture_subprocess ++ (&subprocess, NULL); ++ ++ /* Discard the reported error. */ ++ support_record_failure_reset (); ++ ++ puts ("info: *** subprocess output starts ***"); ++ fputs (proc.out.buffer, stdout); ++ puts ("info: *** subprocess output ends ***"); ++ ++ TEST_VERIFY ++ (strcmp (proc.out.buffer, ++"tst-test_compare_blob.c:29: error: blob comparison failed\n" ++" left length: 0 bytes (from 0)\n" ++" right length: 1 bytes (from 1)\n" ++" right (evaluated from \"\"):\n" ++" \"\\000\"\n" ++" 00\n" ++"tst-test_compare_blob.c:30: error: blob comparison failed\n" ++" blob length: 1 bytes\n" ++" left (evaluated from \"X\"):\n" ++" \"X\"\n" ++" 58\n" ++" right (evaluated from \"\"):\n" ++" \"\\000\"\n" ++" 00\n" ++"tst-test_compare_blob.c:31: error: blob comparison failed\n" ++" left length: 3 bytes (from 3)\n" ++" right length: 4 bytes (from 4)\n" ++" left (evaluated from \"abcd\"):\n" ++" \"abc\"\n" ++" 61 62 63\n" ++" right (evaluated from \"abcd\"):\n" ++" \"abcd\"\n" ++" 61 62 63 64\n" ++"tst-test_compare_blob.c:32: error: blob comparison failed\n" ++" blob length: 4 bytes\n" ++" left (evaluated from \"abcd\"):\n" ++" \"abcd\"\n" ++" 61 62 63 64\n" ++" right (evaluated from \"abcD\"):\n" ++" \"abcD\"\n" ++" 61 62 63 44\n" ++"tst-test_compare_blob.c:33: error: blob comparison failed\n" ++" left length: 4 bytes (from 4)\n" ++" right length: 0 bytes (from 0)\n" ++" left (evaluated from \"abcd\"):\n" ++" \"abcd\"\n" ++" 61 62 63 64\n" ++"tst-test_compare_blob.c:34: error: blob comparison failed\n" ++" left length: 0 bytes (from 0)\n" ++" right length: 4 bytes (from 4)\n" ++" right (evaluated from \"abcd\"):\n" ++" \"abcd\"\n" ++" 61 62 63 64\n" ++ ) == 0); ++ ++ /* Check that there is no output on standard error. */ ++ support_capture_subprocess_check (&proc, "TEST_COMPARE_BLOB", ++ 0, sc_allow_stdout); ++ ++ return 0; ++} ++ ++#include <support/test-driver.c> +diff --git a/support/tst-test_compare_string.c b/support/tst-test_compare_string.c +new file mode 100644 +index 0000000000..2a4b258587 +--- /dev/null ++++ b/support/tst-test_compare_string.c +@@ -0,0 +1,107 @@ ++/* Basic test for the TEST_COMPARE_STRING macro. ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ + -+static int -+return_ssize_t (void) -+{ -+ return 4; -+} ++#include <string.h> ++#include <support/check.h> ++#include <support/capture_subprocess.h> + -+static int -+return_int (void) ++static void ++subprocess (void *closure) +{ -+ return 4; ++ /* These tests should fail. They were chosen to cover differences ++ in length (with the same contents), single-bit mismatches, and ++ mismatching null pointers. */ ++ TEST_COMPARE_STRING ("", NULL); /* Line 29. */ ++ TEST_COMPARE_STRING ("X", ""); /* Line 30. */ ++ TEST_COMPARE_STRING (NULL, "X"); /* Line 31. */ ++ TEST_COMPARE_STRING ("abcd", "abcD"); /* Line 32. */ ++ TEST_COMPARE_STRING ("abcd", NULL); /* Line 33. */ ++ TEST_COMPARE_STRING (NULL, "abcd"); /* Line 34. */ +} + ++/* Same contents, different addresses. */ ++char buffer_abc_1[] = "abc"; ++char buffer_abc_2[] = "abc"; + +static int +do_test (void) +{ -+ /* This should succeed. */ -+ TEST_COMPARE (1, 1); -+ TEST_COMPARE (2LL, 2U); -+ { -+ char i8 = 3; -+ unsigned short u16 = 3; -+ TEST_COMPARE (i8, u16); -+ } -+ TEST_COMPARE (return_ssize_t (), sizeof (char[4])); -+ TEST_COMPARE (return_int (), sizeof (char[4])); -+ -+ struct bitfield bitfield = { 0 }; -+ TEST_COMPARE (bitfield.i2, bitfield.i3); -+ TEST_COMPARE (bitfield.u2, bitfield.u3); -+ TEST_COMPARE (bitfield.u2, bitfield.i3); -+ TEST_COMPARE (bitfield.u3, bitfield.i3); -+ TEST_COMPARE (bitfield.i2, bitfield.u3); -+ TEST_COMPARE (bitfield.i3, bitfield.u2); -+ TEST_COMPARE (bitfield.i63, bitfield.i63); -+ TEST_COMPARE (bitfield.u63, bitfield.u63); -+ TEST_COMPARE (bitfield.i31, bitfield.i63); -+ TEST_COMPARE (bitfield.i63, bitfield.i31); ++ /* This should succeed. Even if the pointers and array contents are ++ different, zero-length inputs are not different. */ ++ TEST_COMPARE_STRING (NULL, NULL); ++ TEST_COMPARE_STRING ("", ""); ++ TEST_COMPARE_STRING (buffer_abc_1, buffer_abc_2); ++ TEST_COMPARE_STRING (buffer_abc_1, "abc"); + + struct support_capture_subprocess proc = support_capture_subprocess + (&subprocess, NULL); @@ -6434,19 +9475,46 @@ index 0000000000..123ba1bc3c + + TEST_VERIFY + (strcmp (proc.out.buffer, -+ "tst-test_compare.c:28: numeric comparison failure\n" -+ " left: 1 (0x1); from: ch\n" -+ " right: -1 (0xffffffff); from: -1\n" -+ "tst-test_compare.c:29: numeric comparison failure\n" -+ " left: 2 (0x2); from: 2LL\n" -+ " right: -2 (0xfffffffffffffffe); from: -2LL\n" -+ "tst-test_compare.c:30: numeric comparison failure" -+ " (widths 64 and 32)\n" -+ " left: 3 (0x3); from: 3LL\n" -+ " right: -3 (0xfffffffd); from: (short) -3\n") == 0); ++"tst-test_compare_string.c:29: error: blob comparison failed\n" ++" left string: 0 bytes\n" ++" right string: NULL\n" ++"tst-test_compare_string.c:30: error: blob comparison failed\n" ++" left string: 1 bytes\n" ++" right string: 0 bytes\n" ++" left (evaluated from \"X\"):\n" ++" \"X\"\n" ++" 58\n" ++"tst-test_compare_string.c:31: error: blob comparison failed\n" ++" left string: NULL\n" ++" right string: 1 bytes\n" ++" right (evaluated from \"X\"):\n" ++" \"X\"\n" ++" 58\n" ++"tst-test_compare_string.c:32: error: blob comparison failed\n" ++" string length: 4 bytes\n" ++" left (evaluated from \"abcd\"):\n" ++" \"abcd\"\n" ++" 61 62 63 64\n" ++" right (evaluated from \"abcD\"):\n" ++" \"abcD\"\n" ++" 61 62 63 44\n" ++"tst-test_compare_string.c:33: error: blob comparison failed\n" ++" left string: 4 bytes\n" ++" right string: NULL\n" ++" left (evaluated from \"abcd\"):\n" ++" \"abcd\"\n" ++" 61 62 63 64\n" ++"tst-test_compare_string.c:34: error: blob comparison failed\n" ++" left string: NULL\n" ++" right string: 4 bytes\n" ++" right (evaluated from \"abcd\"):\n" ++" \"abcd\"\n" ++" 61 62 63 64\n" ++ ) == 0); + + /* Check that there is no output on standard error. */ -+ support_capture_subprocess_check (&proc, "TEST_COMPARE", 0, sc_allow_stdout); ++ support_capture_subprocess_check (&proc, "TEST_COMPARE_STRING", ++ 0, sc_allow_stdout); + + return 0; +} @@ -6530,12 +9598,63 @@ index 0000000000..b142207228 +} + +#include <support/test-driver.c> +diff --git a/support/tty.h b/support/tty.h +new file mode 100644 +index 0000000000..1d37c42279 +--- /dev/null ++++ b/support/tty.h +@@ -0,0 +1,45 @@ ++/* Support functions related to (pseudo)terminals. ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#ifndef _SUPPORT_TTY_H ++#define _SUPPORT_TTY_H 1 ++ ++struct termios; ++struct winsize; ++ ++/** Open a pseudoterminal pair. The outer fd is written to the address ++ A_OUTER and the inner fd to A_INNER. ++ ++ If A_NAME is not NULL, it will be set to point to a string naming ++ the /dev/pts/NNN device corresponding to the inner fd; space for ++ this string is allocated with malloc and should be freed by the ++ caller when no longer needed. (This is different from the libutil ++ function 'openpty'.) ++ ++ If TERMP is not NULL, the terminal parameters will be initialized ++ according to the termios structure it points to. ++ ++ If WINP is not NULL, the terminal window size will be set ++ accordingly. ++ ++ Terminates the process on failure (like xmalloc). */ ++extern void support_openpty (int *a_outer, int *a_inner, char **a_name, ++ const struct termios *termp, ++ const struct winsize *winp); ++ ++#endif diff --git a/support/write_message.c b/support/write_message.c new file mode 100644 -index 0000000000..9d0f267a2f +index 0000000000..a3e2f90535 --- /dev/null +++ b/support/write_message.c -@@ -0,0 +1,29 @@ +@@ -0,0 +1,32 @@ +/* Write a message to standard output. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. @@ -6556,14 +9675,17 @@ index 0000000000..9d0f267a2f + +#include <support/support.h> + ++#include <errno.h> +#include <string.h> +#include <unistd.h> + +void +write_message (const char *message) +{ ++ int saved_errno = errno; + ssize_t unused __attribute__ ((unused)); + unused = write (STDOUT_FILENO, message, strlen (message)); ++ errno = saved_errno; +} diff --git a/support/xaccept.c b/support/xaccept.c new file mode 100644 @@ -6863,6 +9985,44 @@ index 0000000000..341805d80d + if (connect (fd, sa, sa_len) != 0) + FAIL_EXIT1 ("connect (%d), family %d: %m", fd, sa->sa_family); +} +diff --git a/support/xcopy_file_range.c b/support/xcopy_file_range.c +new file mode 100644 +index 0000000000..b3501a4d5e +--- /dev/null ++++ b/support/xcopy_file_range.c +@@ -0,0 +1,32 @@ ++/* copy_file_range with error checking. ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <support/support.h> ++#include <support/xunistd.h> ++#include <support/check.h> ++ ++ssize_t ++xcopy_file_range (int infd, off64_t *pinoff, int outfd, off64_t *poutoff, ++ size_t length, unsigned int flags) ++{ ++ ssize_t status = support_copy_file_range (infd, pinoff, outfd, ++ poutoff, length, flags); ++ if (status == -1) ++ FAIL_EXIT1 ("cannot copy file: %m\n"); ++ return status; ++} diff --git a/support/xdlfcn.c b/support/xdlfcn.c new file mode 100644 index 0000000000..f34bb059c0 @@ -7433,6 +10593,78 @@ index 0000000000..7e67f783de + if (mkdir (path, mode) != 0) + FAIL_EXIT1 ("mkdir (\"%s\", 0%o): %m", path, mode); +} +diff --git a/support/xmkdirp.c b/support/xmkdirp.c +new file mode 100644 +index 0000000000..fada0452ea +--- /dev/null ++++ b/support/xmkdirp.c +@@ -0,0 +1,66 @@ ++/* Error-checking replacement for "mkdir -p". ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <support/support.h> ++#include <support/check.h> ++#include <support/xunistd.h> ++ ++#include <stdlib.h> ++#include <string.h> ++#include <errno.h> ++ ++/* Equivalent of "mkdir -p". Any failures cause FAIL_EXIT1 so no ++ return code is needed. */ ++ ++void ++xmkdirp (const char *path, mode_t mode) ++{ ++ struct stat s; ++ const char *slash_p; ++ int rv; ++ ++ if (path[0] == 0) ++ return; ++ ++ if (stat (path, &s) == 0) ++ { ++ if (S_ISDIR (s.st_mode)) ++ return; ++ errno = EEXIST; ++ FAIL_EXIT1 ("mkdir_p (\"%s\", 0%o): %m", path, mode); ++ } ++ ++ slash_p = strrchr (path, '/'); ++ if (slash_p != NULL) ++ { ++ while (slash_p > path && slash_p[-1] == '/') ++ --slash_p; ++ if (slash_p > path) ++ { ++ char *parent = xstrndup (path, slash_p - path); ++ xmkdirp (parent, mode); ++ free (parent); ++ } ++ } ++ ++ rv = mkdir (path, mode); ++ if (rv != 0) ++ FAIL_EXIT1 ("mkdir_p (\"%s\", 0%o): %m", path, mode); ++ ++ return; ++} diff --git a/support/xmmap.c b/support/xmmap.c new file mode 100644 index 0000000000..d580c07013 @@ -7905,6 +11137,102 @@ index 0000000000..61690c5e7c + xpthread_check_return ("pthread_barrier_wait", ret); + return ret == PTHREAD_BARRIER_SERIAL_THREAD; +} +diff --git a/support/xpthread_barrierattr_destroy.c b/support/xpthread_barrierattr_destroy.c +new file mode 100644 +index 0000000000..3e471f9a81 +--- /dev/null ++++ b/support/xpthread_barrierattr_destroy.c +@@ -0,0 +1,26 @@ ++/* pthread_barrierattr_destroy with error checking. ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <support/xthread.h> ++ ++void ++xpthread_barrierattr_destroy (pthread_barrierattr_t *attr) ++{ ++ xpthread_check_return ("pthread_barrierattr_destroy", ++ pthread_barrierattr_destroy (attr)); ++} +diff --git a/support/xpthread_barrierattr_init.c b/support/xpthread_barrierattr_init.c +new file mode 100644 +index 0000000000..4ee14e78f3 +--- /dev/null ++++ b/support/xpthread_barrierattr_init.c +@@ -0,0 +1,26 @@ ++/* pthread_barrierattr_init with error checking. ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <support/xthread.h> ++ ++void ++xpthread_barrierattr_init (pthread_barrierattr_t *attr) ++{ ++ xpthread_check_return ("pthread_barrierattr_init", ++ pthread_barrierattr_init (attr)); ++} +diff --git a/support/xpthread_barrierattr_setpshared.c b/support/xpthread_barrierattr_setpshared.c +new file mode 100644 +index 0000000000..90b2c5bec6 +--- /dev/null ++++ b/support/xpthread_barrierattr_setpshared.c +@@ -0,0 +1,26 @@ ++/* pthread_barrierattr_setpshared with error checking. ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <support/xthread.h> ++ ++void ++xpthread_barrierattr_setpshared (pthread_barrierattr_t *attr, int pshared) ++{ ++ xpthread_check_return ("pthread_barrierattr_setpshared", ++ pthread_barrierattr_setpshared (attr, pshared)); ++} diff --git a/support/xpthread_cancel.c b/support/xpthread_cancel.c new file mode 100644 index 0000000000..26e864ea3e @@ -9330,6 +12658,41 @@ index 0000000000..e85fddd439 + oom_error ("strndup", length); + return p; +} +diff --git a/support/xsymlink.c b/support/xsymlink.c +new file mode 100644 +index 0000000000..0f3edf640a +--- /dev/null ++++ b/support/xsymlink.c +@@ -0,0 +1,29 @@ ++/* Error-checking replacement for "symlink". ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <support/support.h> ++#include <support/check.h> ++ ++#include <unistd.h> ++ ++void ++xsymlink (const char *target, const char *linkpath) ++{ ++ if (symlink (target, linkpath) < 0) ++ FAIL_EXIT1 ("symlink (\"%s\", \"%s\")", target, linkpath); ++} diff --git a/support/xsysconf.c b/support/xsysconf.c new file mode 100644 index 0000000000..afefc2d098 @@ -9374,10 +12737,10 @@ index 0000000000..afefc2d098 +} diff --git a/support/xthread.h b/support/xthread.h new file mode 100644 -index 0000000000..79358e7c99 +index 0000000000..623f5ad0ac --- /dev/null +++ b/support/xthread.h -@@ -0,0 +1,87 @@ +@@ -0,0 +1,90 @@ +/* Support functionality for using threads. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. @@ -9421,6 +12784,9 @@ index 0000000000..79358e7c99 +void xpthread_barrier_init (pthread_barrier_t *barrier, + pthread_barrierattr_t *attr, unsigned int count); +void xpthread_barrier_destroy (pthread_barrier_t *barrier); ++void xpthread_barrierattr_destroy (pthread_barrierattr_t *); ++void xpthread_barrierattr_init (pthread_barrierattr_t *); ++void xpthread_barrierattr_setpshared (pthread_barrierattr_t *, int pshared); +void xpthread_mutexattr_destroy (pthread_mutexattr_t *); +void xpthread_mutexattr_init (pthread_mutexattr_t *); +void xpthread_mutexattr_setprotocol (pthread_mutexattr_t *, int); @@ -9467,10 +12833,10 @@ index 0000000000..79358e7c99 +#endif /* SUPPORT_THREAD_H */ diff --git a/support/xunistd.h b/support/xunistd.h new file mode 100644 -index 0000000000..5fe5dae818 +index 0000000000..f99f362cb4 --- /dev/null +++ b/support/xunistd.h -@@ -0,0 +1,65 @@ +@@ -0,0 +1,72 @@ +/* POSIX-specific extra functions. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. @@ -9516,6 +12882,10 @@ index 0000000000..5fe5dae818 +long xsysconf (int name); +long long xlseek (int fd, long long offset, int whence); +void xftruncate (int fd, long long length); ++void xsymlink (const char *target, const char *linkpath); ++ ++/* Equivalent of "mkdir -p". */ ++void xmkdirp (const char *, mode_t); + +/* Read the link at PATH. The caller should free the returned string + with free. */ @@ -9533,6 +12903,9 @@ index 0000000000..5fe5dae818 +void xmprotect (void *addr, size_t length, int prot); +void xmunmap (void *addr, size_t length); + ++ssize_t xcopy_file_range(int fd_in, loff_t *off_in, int fd_out, ++ loff_t *off_out, size_t len, unsigned int flags); ++ +__END_DECLS + +#endif /* SUPPORT_XUNISTD_H */ diff --git a/SOURCES/glibc-rh1418978-1a.patch b/SOURCES/glibc-rh1418978-1a.patch new file mode 100644 index 0000000..6d41e32 --- /dev/null +++ b/SOURCES/glibc-rh1418978-1a.patch @@ -0,0 +1,54 @@ +Backporting changes to the support/ subdirectory. + +This is kept separate from glibc-rh1418978-1.patch to simplify rebases +of the support/ subdirectory. Changes here should be restricted to +things that absolutely cannot be upstreamed at this point (such as +support for older compilers). + +diff --git a/support/blob_repeat.c b/support/blob_repeat.c +index 16c1e448b990e386..a2d5e0cbd736f998 100644 +--- a/support/blob_repeat.c ++++ b/support/blob_repeat.c +@@ -30,6 +30,9 @@ + #include <unistd.h> + #include <wchar.h> + ++/* For check_mul_overflow_size_t. */ ++#include <malloc/malloc-internal.h> ++ + /* Small allocations should use malloc directly instead of the mmap + optimization because mappings carry a lot of overhead. */ + static const size_t maximum_small_size = 4 * 1024 * 1024; +@@ -118,8 +121,8 @@ minimum_stride_size (size_t page_size, size_t element_size) + common multiple, it appears only once. Therefore, shift one + factor. */ + size_t multiple; +- if (__builtin_mul_overflow (page_size >> common_zeros, element_size, +- &multiple)) ++ if (check_mul_overflow_size_t (page_size >> common_zeros, element_size, ++ &multiple)) + return 0; + return multiple; + } +@@ -255,7 +258,7 @@ support_blob_repeat_allocate (const void *element, size_t element_size, + size_t count) + { + size_t total_size; +- if (__builtin_mul_overflow (element_size, count, &total_size)) ++ if (check_mul_overflow_size_t (element_size, count, &total_size)) + { + errno = EOVERFLOW; + return (struct support_blob_repeat) { 0 }; +diff --git a/support/links-dso-program.cc b/support/links-dso-program.cc +index dba6976c0609a332..8ff3155dd7fcd757 100644 +--- a/support/links-dso-program.cc ++++ b/support/links-dso-program.cc +@@ -1,3 +1,8 @@ ++/* Change for backporting: The build system does not define _ISOMAC ++ for us because the tests-internal changes have not been ++ backported. */ ++#define _ISOMAC 1 ++ + #include <iostream> + + using namespace std; diff --git a/SOURCES/glibc-rh1427734-1.patch b/SOURCES/glibc-rh1427734-1.patch new file mode 100644 index 0000000..c9e569f --- /dev/null +++ b/SOURCES/glibc-rh1427734-1.patch @@ -0,0 +1,318 @@ +The commit included in this patch only incidentally fixes the problem +reported in bug 1427734: In each of the IBM9xx character sets referenced in +this patch, the removal of the "break" statement means that the subsequent +increment of "inptr" is executed instead of being skipped. This allows +conversion to progress instead of hanging. + +commit 692de4b3960dc90bdcfb871513ee4d81d314cf69 +Author: Martin Sebor <msebor@redhat.com> +Date: Fri Jan 15 11:25:13 2016 -0700 + + Have iconv accept redundant escape sequences in IBM900, IBM903, IBM905, + IBM907, and IBM909. + + Patch for bug #17197 changes the encoder to avoid generating redundant + shift sequences. However, those sequences may already be present in + data encododed by prior versions of the encoder. This change modifies + the decoder to also avoid rejecting redundant shift sequences. + + [BZ #19432] + * iconvdata/Makefile: Add bug-iconv11. + * iconvdata/bug-iconv11.c: New test. + * iconvdata/ibm930.c: Do not reject redundant shift sequences. + * iconvdata/ibm933.c: Same. + * iconvdata/ibm935.c: Same. + * iconvdata/ibm937.c: Same. + * iconvdata/ibm939.c: Same. + +# Conflicts: +# iconvdata/Makefile + +diff --git a/iconvdata/Makefile b/iconvdata/Makefile +index 0ec67554ca4c29ea..c4e6c510d7abc055 100644 +--- a/iconvdata/Makefile ++++ b/iconvdata/Makefile +@@ -68,7 +68,7 @@ include ../Makeconfig + ifeq (yes,$(build-shared)) + tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \ + tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \ +- bug-iconv10 bug-iconv12 ++ bug-iconv10 bug-iconv11 bug-iconv12 + ifeq ($(have-thread-library),yes) + tests += bug-iconv3 + endif +diff --git a/iconvdata/bug-iconv11.c b/iconvdata/bug-iconv11.c +new file mode 100644 +index 0000000000000000..6cdc07d79883454d +--- /dev/null ++++ b/iconvdata/bug-iconv11.c +@@ -0,0 +1,114 @@ ++/* bug 19432: iconv rejects redundant escape sequences in IBM903, ++ IBM905, IBM907, and IBM909 ++ ++ Copyright (C) 2016 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <iconv.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <errno.h> ++ ++// The longest test input sequence. ++#define MAXINBYTES 8 ++#define MAXOUTBYTES (MAXINBYTES * MB_LEN_MAX) ++ ++/* Verify that a conversion of the INPUT sequence consisting of ++ INBYTESLEFT bytes in the encoding specified by the codeset ++ named by FROM_SET is successful. ++ Return 0 on success, non-zero on iconv() failure. */ ++ ++static int ++test_ibm93x (const char *from_set, const char *input, size_t inbytesleft) ++{ ++ const char to_set[] = "UTF-8"; ++ iconv_t cd = iconv_open (to_set, from_set); ++ if (cd == (iconv_t) -1) ++ { ++ printf ("iconv_open(\"%s\", \"%s\"): %s\n", ++ from_set, to_set, strerror (errno)); ++ return 1; ++ } ++ ++ char output [MAXOUTBYTES]; ++ size_t outbytesleft = sizeof output; ++ ++ char *inbuf = (char*)input; ++ char *outbuf = output; ++ ++ printf ("iconv(cd, %p, %zu, %p, %zu)\n", ++ inbuf, inbytesleft, outbuf, outbytesleft); ++ ++ errno = 0; ++ size_t ret = iconv (cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft); ++ printf (" ==> %td: %s\n" ++ " inbuf%+td, inbytesleft=%zu, outbuf%+td, outbytesleft=%zu\n", ++ ret, strerror (errno), ++ inbuf - input, inbytesleft, outbuf - output, outbytesleft); ++ ++ // Return 0 on success, non-zero on iconv() failure. ++ return ret == (size_t)-1 || errno; ++} ++ ++static int ++do_test (void) ++{ ++ // State-dependent encodings to exercise. ++ static const char* const to_code[] = { ++ "IBM930", "IBM933", "IBM935", "IBM937", "IBM939" ++ }; ++ ++ static const size_t ncodesets = sizeof to_code / sizeof *to_code; ++ ++ static const struct { ++ char txt[MAXINBYTES]; ++ size_t len; ++ } input[] = { ++#define DATA(s) { s, sizeof s - 1 } ++ /* <SI>: denotes the shift-in 1-byte escape sequence, changing ++ the encoder from a sigle-byte encoding to multibyte ++ <SO>: denotes the shift-out 1-byte escape sequence, switching ++ the encoder from a multibyte to a single-byte state */ ++ ++ DATA ("\x0e"), // <SI> (not redundant) ++ DATA ("\x0f"), // <S0> (redundant with initial state) ++ DATA ("\x0e\x0e"), // <SI><SI> ++ DATA ("\x0e\x0f\x0f"), // <SI><SO><SO> ++ DATA ("\x0f\x0f"), // <SO><SO> ++ DATA ("\x0f\x0e\x0e"), // <SO><SI><SI> ++ DATA ("\x0e\x0f\xc7\x0f"), // <SI><SO><G><SO> ++ DATA ("\xc7\x0f") // <G><SO> (redundant with initial state) ++ }; ++ ++ static const size_t ninputs = sizeof input / sizeof *input; ++ ++ int ret = 0; ++ ++ size_t i, j; ++ ++ /* Iterate over the IBM93x codesets above and exercise each with ++ the input sequences above. */ ++ for (i = 0; i != ncodesets; ++i) ++ for (j = 0; j != ninputs; ++j) ++ ret += test_ibm93x (to_code [i], input [i].txt, input [i].len); ++ ++ return ret; ++} ++ ++#define TEST_FUNCTION do_test () ++#include "../test-skeleton.c" +diff --git a/iconvdata/ibm930.c b/iconvdata/ibm930.c +index 636141114f506985..88413ccfbabfdc35 100644 +--- a/iconvdata/ibm930.c ++++ b/iconvdata/ibm930.c +@@ -105,24 +105,14 @@ enum + \ + if (__builtin_expect (ch, 0) == SO) \ + { \ +- /* Shift OUT, change to DBCS converter. */ \ +- if (curcs == db) \ +- { \ +- result = __GCONV_ILLEGAL_INPUT; \ +- break; \ +- } \ ++ /* Shift OUT, change to DBCS converter (redundant escape okay). */ \ + curcs = db; \ + ++inptr; \ + continue; \ + } \ + else if (__builtin_expect (ch, 0) == SI) \ + { \ +- /* Shift IN, change to SBCS converter */ \ +- if (curcs == sb) \ +- { \ +- result = __GCONV_ILLEGAL_INPUT; \ +- break; \ +- } \ ++ /* Shift IN, change to SBCS converter (redundant escape okay). */ \ + curcs = sb; \ + ++inptr; \ + continue; \ +diff --git a/iconvdata/ibm933.c b/iconvdata/ibm933.c +index 8b9e5780a36a454a..335d385551fee86e 100644 +--- a/iconvdata/ibm933.c ++++ b/iconvdata/ibm933.c +@@ -104,24 +104,14 @@ enum + \ + if (__builtin_expect (ch, 0) == SO) \ + { \ +- /* Shift OUT, change to DBCS converter. */ \ +- if (curcs == db) \ +- { \ +- result = __GCONV_ILLEGAL_INPUT; \ +- break; \ +- } \ ++ /* Shift OUT, change to DBCS converter (redundant escape okay). */ \ + curcs = db; \ + ++inptr; \ + continue; \ + } \ + else if (__builtin_expect (ch, 0) == SI) \ + { \ +- /* Shift IN, change to SBCS converter. */ \ +- if (curcs == sb) \ +- { \ +- result = __GCONV_ILLEGAL_INPUT; \ +- break; \ +- } \ ++ /* Shift IN, change to SBCS converter (redundant escape okay). */ \ + curcs = sb; \ + ++inptr; \ + continue; \ +diff --git a/iconvdata/ibm935.c b/iconvdata/ibm935.c +index 4e2d99ab56d7f0d2..520d28a4e9a690fc 100644 +--- a/iconvdata/ibm935.c ++++ b/iconvdata/ibm935.c +@@ -104,24 +104,14 @@ enum + \ + if (__builtin_expect(ch, 0) == SO) \ + { \ +- /* Shift OUT, change to DBCS converter. */ \ +- if (curcs == db) \ +- { \ +- result = __GCONV_ILLEGAL_INPUT; \ +- break; \ +- } \ ++ /* Shift OUT, change to DBCS converter (redundant escape okay). */ \ + curcs = db; \ + ++inptr; \ + continue; \ + } \ + else if (__builtin_expect (ch, 0) == SI) \ + { \ +- /* Shift IN, change to SBCS converter. */ \ +- if (curcs == sb) \ +- { \ +- result = __GCONV_ILLEGAL_INPUT; \ +- break; \ +- } \ ++ /* Shift IN, change to SBCS converter (redundant escape okay). */ \ + curcs = sb; \ + ++inptr; \ + continue; \ +diff --git a/iconvdata/ibm937.c b/iconvdata/ibm937.c +index 1e468871b783e78d..64563bb8bf0441ff 100644 +--- a/iconvdata/ibm937.c ++++ b/iconvdata/ibm937.c +@@ -104,24 +104,14 @@ enum + \ + if (__builtin_expect (ch, 0) == SO) \ + { \ +- /* Shift OUT, change to DBCS converter. */ \ +- if (curcs == db) \ +- { \ +- result = __GCONV_ILLEGAL_INPUT; \ +- break; \ +- } \ ++ /* Shift OUT, change to DBCS converter (redundant escape okay). */ \ + curcs = db; \ + ++inptr; \ + continue; \ + } \ + else if (__builtin_expect (ch, 0) == SI) \ + { \ +- /* Shift IN, change to SBCS converter. */ \ +- if (curcs == sb) \ +- { \ +- result = __GCONV_ILLEGAL_INPUT; \ +- break; \ +- } \ ++ /* Shift IN, change to SBCS converter (redundant escape okay). */ \ + curcs = sb; \ + ++inptr; \ + continue; \ +diff --git a/iconvdata/ibm939.c b/iconvdata/ibm939.c +index 2060b0c329df0c86..4f73e2e55c94972d 100644 +--- a/iconvdata/ibm939.c ++++ b/iconvdata/ibm939.c +@@ -104,24 +104,14 @@ enum + \ + if (__builtin_expect (ch, 0) == SO) \ + { \ +- /* Shift OUT, change to DBCS converter. */ \ +- if (curcs == db) \ +- { \ +- result = __GCONV_ILLEGAL_INPUT; \ +- break; \ +- } \ ++ /* Shift OUT, change to DBCS converter (redundant escape okay). */ \ + curcs = db; \ + ++inptr; \ + continue; \ + } \ + else if (__builtin_expect (ch, 0) == SI) \ + { \ +- /* Shift IN, change to SBCS converter. */ \ +- if (curcs == sb) \ +- { \ +- result = __GCONV_ILLEGAL_INPUT; \ +- break; \ +- } \ ++ /* Shift IN, change to SBCS converter (redundant escape okay). */ \ + curcs = sb; \ + ++inptr; \ + continue; \ diff --git a/SOURCES/glibc-rh1427734-2.patch b/SOURCES/glibc-rh1427734-2.patch new file mode 100644 index 0000000..eaa39ad --- /dev/null +++ b/SOURCES/glibc-rh1427734-2.patch @@ -0,0 +1,34 @@ +commit ab9f6255ab4e7aa353ec1b61b4f332bf00cea4d0 +Author: Stefan Liebler <stli@linux.vnet.ibm.com> +Date: Wed Jan 20 08:32:37 2016 +0100 + + S390: Fix build error in iconvdata/bug-iconv11.c. + + This fixes the following build error on S390 31bit while building the test + iconvdata/bug-iconv11.c with gcc 5.3: + bug-iconv11.c: In function ‘test_ibm93x’: + bug-iconv11.c:59:11: error: format ‘%td’ expects argument of type ‘ptrdiff_t’, but argument 2 has type ‘size_t {aka long unsigned int}’ [-Werror=format=] + printf (" ==> %td: %s\n" + ^ + cc1: all warnings being treated as errors + + This patch uses %zu format specifier for argument size_t ret instead of %td. + + ChangeLog: + + * iconvdata/bug-iconv11.c (test_ibm93x): + Use %zu printf format specifier for size_t argument. + +diff --git a/iconvdata/bug-iconv11.c b/iconvdata/bug-iconv11.c +index 6cdc07d79883454d..5b9d9a36af0b4bcf 100644 +--- a/iconvdata/bug-iconv11.c ++++ b/iconvdata/bug-iconv11.c +@@ -56,7 +56,7 @@ test_ibm93x (const char *from_set, const char *input, size_t inbytesleft) + + errno = 0; + size_t ret = iconv (cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft); +- printf (" ==> %td: %s\n" ++ printf (" ==> %zu: %s\n" + " inbuf%+td, inbytesleft=%zu, outbuf%+td, outbytesleft=%zu\n", + ret, strerror (errno), + inbuf - input, inbytesleft, outbuf - output, outbytesleft); diff --git a/SOURCES/glibc-rh1439165-syscall-names.patch b/SOURCES/glibc-rh1439165-syscall-names.patch index 247e3f2..6bc2372 100644 --- a/SOURCES/glibc-rh1439165-syscall-names.patch +++ b/SOURCES/glibc-rh1439165-syscall-names.patch @@ -1,5 +1,6 @@ This patch contains the sysdeps/unix/sysv/linux/syscall-names.list file -from upstream and is continuously updated for new kernel versions. +from upstream for Linux 4.13, and forms the baseline, subsequent changes +are cherry picked from upstream. diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list new file mode 100644 diff --git a/SOURCES/glibc-rh1439165.patch b/SOURCES/glibc-rh1439165.patch index bb2ee65..624d448 100644 --- a/SOURCES/glibc-rh1439165.patch +++ b/SOURCES/glibc-rh1439165.patch @@ -3,8 +3,8 @@ Posted upstream at: https://sourceware.org/ml/libc-alpha/2017-04/msg00082.html sysdeps/unix/sysv/linux/syscall-names.list is stored as a separate patch -(glibc-rh1439165-syscall-names.patch) in the source RPM for easier -updates. +(glibc-rh1439165-syscall-names.patch) in the source RPM, and is the +baseline for subsequent changes. Author: Florian Weimer <fweimer@redhat.com> diff --git a/SOURCES/glibc-rh1443872-2.patch b/SOURCES/glibc-rh1443872-2.patch new file mode 100644 index 0000000..c7717f7 --- /dev/null +++ b/SOURCES/glibc-rh1443872-2.patch @@ -0,0 +1,40 @@ +Add missing newlines to __libc_fatal error messages. This was +implemented upstream in commits a6e8926f8d49a213a9abb1a61f6af964f612ab7f +("[BZ #20271] Add newlines in __libc_fatal calls.") and +36f30c104fe3addd4d864e276202c6b934f825b7 +("__netlink_assert_response: Add more __libc_fatal newlines [BZ #20271]"). + +diff --git a/sysdeps/unix/sysv/linux/netlink_assert_response.c b/sysdeps/unix/sysv/linux/netlink_assert_response.c +index b570e93db840fec1..434b50d20b67d130 100644 +--- a/sysdeps/unix/sysv/linux/netlink_assert_response.c ++++ b/sysdeps/unix/sysv/linux/netlink_assert_response.c +@@ -73,12 +73,12 @@ __netlink_assert_response (int fd, ssize_t result) + char message[200]; + if (family < 0) + __snprintf (message, sizeof (message), +- "Unexpected error %d on netlink descriptor %d", ++ "Unexpected error %d on netlink descriptor %d\n", + error_code, fd); + else + __snprintf (message, sizeof (message), + "Unexpected error %d on netlink descriptor %d" +- " (address family %d)", ++ " (address family %d)\n", + error_code, fd, family); + __libc_fatal (message); + } +@@ -93,12 +93,12 @@ __netlink_assert_response (int fd, ssize_t result) + if (family < 0) + __snprintf (message, sizeof (message), + "Unexpected netlink response of size %zd" +- " on descriptor %d", ++ " on descriptor %d\n", + result, fd); + else + __snprintf (message, sizeof (message), + "Unexpected netlink response of size %zd" +- " on descriptor %d (address family %d)", ++ " on descriptor %d (address family %d)\n", + result, fd, family); + __libc_fatal (message); + } diff --git a/SOURCES/glibc-rh1443872.patch b/SOURCES/glibc-rh1443872.patch new file mode 100644 index 0000000..6027304 --- /dev/null +++ b/SOURCES/glibc-rh1443872.patch @@ -0,0 +1,250 @@ +commit 2eecc8afd02d8c65cf098cbae4de87f332dc21bd +Author: Florian Weimer <fweimer@redhat.com> +Date: Mon Nov 9 12:48:41 2015 +0100 + + Terminate process on invalid netlink response from kernel [BZ #12926] + + The recvmsg system calls for netlink sockets have been particularly + prone to picking up unrelated data after a file descriptor race + (where the descriptor is closed and reopened concurrently in a + multi-threaded process, as the result of a file descriptor + management issue elsewhere). This commit adds additional error + checking and aborts the process if a datagram of unexpected length + (without the netlink header) is received, or an error code which + cannot happen due to the way the netlink socket is used. + + [BZ #12926] + Terminate process on invalid netlink response. + * sysdeps/unix/sysv/linux/netlinkaccess.h + (__netlink_assert_response): Declare. + * sysdeps/unix/sysv/linux/netlink_assert_response.c: New file. + * sysdeps/unix/sysv/linux/Makefile [$(subdir) == inet] + (sysdep_routines): Add netlink_assert_response. + * sysdeps/unix/sysv/linux/check_native.c (__check_native): Call + __netlink_assert_response. + * sysdeps/unix/sysv/linux/check_pf.c (make_request): Likewise. + * sysdeps/unix/sysv/linux/ifaddrs.c (__netlink_request): Likewise. + * sysdeps/unix/sysv/linux/Versions (GLIBC_PRIVATE): Add + __netlink_assert_response. + +Conflicts: + sysdeps/unix/sysv/linux/check_pf.c + Upstream commit fda389c8f0311dd5786be91a7b54b9f935fcafa1 + ("Fix infinite loop in check_pf (BZ #12926)") was not backported + before and is superseded by the upstream commit backported here. + sysdeps/unix/sysv/linux/netlinkaccess.h + Missing backport of e054f494306530720114b321b3d97ca2f397cbbb + ("Add #include <stdint.h> for uint[32|64]_t usage (except + installed headers)"). + +diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile +index 95cff0ef651e74a9..bb69b985e6df7fb1 100644 +--- a/sysdeps/unix/sysv/linux/Makefile ++++ b/sysdeps/unix/sysv/linux/Makefile +@@ -114,6 +114,7 @@ sysdep_headers += netinet/if_fddi.h netinet/if_tr.h \ + netipx/ipx.h netash/ash.h netax25/ax25.h netatalk/at.h \ + netrom/netrom.h netpacket/packet.h netrose/rose.h \ + neteconet/ec.h netiucv/iucv.h ++sysdep_routines += netlink_assert_response + endif + + # Don't compile the ctype glue code, since there is no old non-GNU C library. +diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions +index 16bb28159099c5fa..202ffccc2908ddcc 100644 +--- a/sysdeps/unix/sysv/linux/Versions ++++ b/sysdeps/unix/sysv/linux/Versions +@@ -169,5 +169,7 @@ libc { + GLIBC_PRIVATE { + # functions used in other libraries + __syscall_rt_sigqueueinfo; ++ # functions used by nscd ++ __netlink_assert_response; + } + } +diff --git a/sysdeps/unix/sysv/linux/check_native.c b/sysdeps/unix/sysv/linux/check_native.c +index 4968a07a0f8c7932..319b46762aeaf3b6 100644 +--- a/sysdeps/unix/sysv/linux/check_native.c ++++ b/sysdeps/unix/sysv/linux/check_native.c +@@ -35,6 +35,7 @@ + + #include <not-cancel.h> + ++#include "netlinkaccess.h" + + void + __check_native (uint32_t a1_index, int *a1_native, +@@ -117,6 +118,7 @@ __check_native (uint32_t a1_index, int *a1_native, + }; + + ssize_t read_len = TEMP_FAILURE_RETRY (__recvmsg (fd, &msg, 0)); ++ __netlink_assert_response (fd, read_len); + if (read_len < 0) + goto out_fail; + +diff --git a/sysdeps/unix/sysv/linux/check_pf.c b/sysdeps/unix/sysv/linux/check_pf.c +index d33e1b497d8ba9c7..6b28a735a14f1498 100644 +--- a/sysdeps/unix/sysv/linux/check_pf.c ++++ b/sysdeps/unix/sysv/linux/check_pf.c +@@ -36,6 +36,7 @@ + #include <atomic.h> + #include <nscd/nscd-client.h> + ++#include "netlinkaccess.h" + + #ifndef IFA_F_HOMEADDRESS + # define IFA_F_HOMEADDRESS 0 +@@ -178,6 +179,7 @@ make_request (int fd, pid_t pid) + }; + + ssize_t read_len = TEMP_FAILURE_RETRY (__recvmsg (fd, &msg, 0)); ++ __netlink_assert_response (fd, read_len); + if (read_len < 0) + goto out_fail; + +diff --git a/sysdeps/unix/sysv/linux/ifaddrs.c b/sysdeps/unix/sysv/linux/ifaddrs.c +index 179653103e057b79..c87e594e30a314fe 100644 +--- a/sysdeps/unix/sysv/linux/ifaddrs.c ++++ b/sysdeps/unix/sysv/linux/ifaddrs.c +@@ -169,6 +169,7 @@ __netlink_request (struct netlink_handle *h, int type) + }; + + read_len = TEMP_FAILURE_RETRY (__recvmsg (h->fd, &msg, 0)); ++ __netlink_assert_response (h->fd, read_len); + if (read_len < 0) + goto out_fail; + +diff --git a/sysdeps/unix/sysv/linux/netlink_assert_response.c b/sysdeps/unix/sysv/linux/netlink_assert_response.c +new file mode 100644 +index 0000000000000000..b570e93db840fec1 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/netlink_assert_response.c +@@ -0,0 +1,106 @@ ++/* Check recvmsg results for netlink sockets. ++ Copyright (C) 2015 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <errno.h> ++#include <fcntl.h> ++#include <stdio.h> ++#include <sys/socket.h> ++ ++#include "netlinkaccess.h" ++ ++static int ++get_address_family (int fd) ++{ ++ struct sockaddr_storage sa; ++ socklen_t sa_len = sizeof (sa); ++ if (__getsockname (fd, (struct sockaddr *) &sa, &sa_len) < 0) ++ return -1; ++ /* Check that the socket family number is preserved despite in-band ++ signaling. */ ++ _Static_assert (sizeof (sa.ss_family) < sizeof (int), "address family size"); ++ _Static_assert (0 < (__typeof__ (sa.ss_family)) -1, ++ "address family unsigned"); ++ return sa.ss_family; ++} ++ ++void ++internal_function ++__netlink_assert_response (int fd, ssize_t result) ++{ ++ if (result < 0) ++ { ++ /* Check if the error is unexpected. */ ++ bool terminate = false; ++ int error_code = errno; ++ int family = get_address_family (fd); ++ if (family != AF_NETLINK) ++ /* If the address family does not match (or getsockname ++ failed), report the original error. */ ++ terminate = true; ++ else if (error_code == EBADF ++ || error_code == ENOTCONN ++ || error_code == ENOTSOCK ++ || error_code == ECONNREFUSED) ++ /* These errors indicate that the descriptor is not a ++ connected socket. */ ++ terminate = true; ++ else if (error_code == EAGAIN || error_code == EWOULDBLOCK) ++ { ++ /* The kernel might return EAGAIN for other reasons than a ++ non-blocking socket. But if the socket is not blocking, ++ it is not ours, so report the error. */ ++ int mode = __fcntl (fd, F_GETFL, 0); ++ if (mode < 0 || (mode & O_NONBLOCK) != 0) ++ terminate = true; ++ } ++ if (terminate) ++ { ++ char message[200]; ++ if (family < 0) ++ __snprintf (message, sizeof (message), ++ "Unexpected error %d on netlink descriptor %d", ++ error_code, fd); ++ else ++ __snprintf (message, sizeof (message), ++ "Unexpected error %d on netlink descriptor %d" ++ " (address family %d)", ++ error_code, fd, family); ++ __libc_fatal (message); ++ } ++ else ++ /* Restore orignal errno value. */ ++ __set_errno (error_code); ++ } ++ else if (result < sizeof (struct nlmsghdr)) ++ { ++ char message[200]; ++ int family = get_address_family (fd); ++ if (family < 0) ++ __snprintf (message, sizeof (message), ++ "Unexpected netlink response of size %zd" ++ " on descriptor %d", ++ result, fd); ++ else ++ __snprintf (message, sizeof (message), ++ "Unexpected netlink response of size %zd" ++ " on descriptor %d (address family %d)", ++ result, fd, family); ++ __libc_fatal (message); ++ } ++} ++libc_hidden_def (__netlink_assert_response) +diff --git a/sysdeps/unix/sysv/linux/netlinkaccess.h b/sysdeps/unix/sysv/linux/netlinkaccess.h +index 6cd8a882640d2486..33dc4e12cd464681 100644 +--- a/sysdeps/unix/sysv/linux/netlinkaccess.h ++++ b/sysdeps/unix/sysv/linux/netlinkaccess.h +@@ -18,6 +18,7 @@ + #ifndef _NETLINKACCESS_H + #define _NETLINKACCESS_H 1 + ++#include <sys/types.h> + #include <asm/types.h> + #include <linux/netlink.h> + #include <linux/rtnetlink.h> +@@ -49,5 +50,10 @@ extern void __netlink_close (struct netlink_handle *h); + extern void __netlink_free_handle (struct netlink_handle *h); + extern int __netlink_request (struct netlink_handle *h, int type); + ++/* Terminate the process if RESULT is an invalid recvmsg result for ++ the netlink socket FD. */ ++void __netlink_assert_response (int fd, ssize_t result) ++ internal_function; ++libc_hidden_proto (__netlink_assert_response) + + #endif /* netlinkaccess.h */ diff --git a/SOURCES/glibc-rh1457479-3.patch b/SOURCES/glibc-rh1457479-3.patch index bb86e24..e8710fd 100644 --- a/SOURCES/glibc-rh1457479-3.patch +++ b/SOURCES/glibc-rh1457479-3.patch @@ -1,3 +1,7 @@ +Note; the test is known to fail on the RHEL 7.7 kernel - the patch +fixes PT_GETREGS (which we want) but adds PTRACE_SINGLEBLOCK (which we +don't support yet). So, the test case was not included. - DJ + commit b08a6a0dea63742313ed3d9577c1e2d83436b196 Author: Stefan Liebler <stli@linux.vnet.ibm.com> Date: Mon Jun 19 16:27:25 2017 +0200 diff --git a/SOURCES/glibc-rh1472832.patch b/SOURCES/glibc-rh1472832.patch new file mode 100644 index 0000000..3d9e01e --- /dev/null +++ b/SOURCES/glibc-rh1472832.patch @@ -0,0 +1,38 @@ +commit c1f86a33ca32e26a9d6e29fc961e5ecb5e2e5eb4 +Author: Daniel Alvarez <dalvarez@redhat.com> +Date: Fri Jun 29 09:44:55 2018 +0200 + + getifaddrs: Don't return ifa entries with NULL names [BZ #21812] + + A lookup operation in map_newlink could turn into an insert because of + holes in the interface part of the map. This leads to incorrectly set + the name of the interface to NULL when the interface is not present + for the address being processed (most likely because the interface was + added between the RTM_GETLINK and RTM_GETADDR calls to the kernel). + When such changes are detected by the kernel, it'll mark the dump as + "inconsistent" by setting NLM_F_DUMP_INTR flag on the next netlink + message. + + This patch checks this condition and retries the whole operation. + Hopes are that next time the interface corresponding to the address + entry is present in the list and correct name is returned. + +diff --git a/sysdeps/unix/sysv/linux/ifaddrs.c b/sysdeps/unix/sysv/linux/ifaddrs.c +index c87e594e30a314fe..b1329dc4d4c63529 100644 +--- a/sysdeps/unix/sysv/linux/ifaddrs.c ++++ b/sysdeps/unix/sysv/linux/ifaddrs.c +@@ -369,6 +369,14 @@ getifaddrs_internal (struct ifaddrs **ifap) + if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq) + continue; + ++ /* If the dump got interrupted, we can't rely on the results ++ so try again. */ ++ if (nlh->nlmsg_flags & NLM_F_DUMP_INTR) ++ { ++ result = -EAGAIN; ++ goto exit_free; ++ } ++ + if (nlh->nlmsg_type == NLMSG_DONE) + break; /* ok */ + diff --git a/SOURCES/glibc-rh1488370.patch b/SOURCES/glibc-rh1488370.patch new file mode 100644 index 0000000..4ecebda --- /dev/null +++ b/SOURCES/glibc-rh1488370.patch @@ -0,0 +1,61 @@ +Partial backport of the following Fedora Rawhide patches: + +commit a747c093bbee95a3bdf1d7ef052bd248c95fadc5 +Author: Florian Weimer <fweimer@redhat.com> +Date: Fri Jun 1 12:05:26 2018 +0200 + + Modernise nsswitch.conf defaults (#1581809) + +(backported the line which adds sss description). + +commit 82a97343d6405772541d754aeb4bab79612bd839 +Author: Carlos O'Donell <carlos@redhat.com> +Date: Thu Feb 7 17:15:12 2019 -0500 + + Add warnings and notes to /etc/nsswitch.conf and /etc/nscd.conf. + +(backported fully with adjustments for releng/nsswitch.conf). + +diff --git a/nscd/nscd.conf b/nscd/nscd.conf +index 3730835c50a349c4..d7c0ee590466b0d4 100644 +--- a/nscd/nscd.conf ++++ b/nscd/nscd.conf +@@ -3,6 +3,9 @@ + # + # An example Name Service Cache config file. This file is needed by nscd. + # ++# WARNING: Running nscd with a secondary caching service like sssd may lead to ++# unexpected behaviour, especially with how long entries are cached. ++# + # Legal entries are: + # + # logfile <file> +@@ -22,7 +25,12 @@ + # suggested-size <service> <prime number> + # check-files <service> <yes|no> + # persistent <service> <yes|no> ++# + # shared <service> <yes|no> ++# NOTE: Setting 'shared' to a value of 'yes' will accelerate the lookup ++# with the help of the client, but these lookups will not be ++# counted as cache hits i.e. 'nscd -g' may show '0%'. ++# + # max-db-size <service> <number bytes> + # auto-propagate <service> <yes|no> + # +diff --git a/releng/nsswitch.conf b/releng/nsswitch.conf +index 0a02e5717d906387..4b120bf9e6f94e5f 100644 +--- a/releng/nsswitch.conf ++++ b/releng/nsswitch.conf +@@ -19,8 +19,11 @@ + # db Use the local database (.db) files + # compat Use NIS on compat mode + # hesiod Use Hesiod for user lookups ++# sss Use sssd (System Security Services Daemon) + # [NOTFOUND=return] Stop searching if not found so far + # ++# WARNING: Running nscd with a secondary caching service like sssd may lead to ++# unexpected behaviour, especially with how long entries are cached. + + # To use db, put the "db" in front of "files" for entries you want to be + # looked up first in the databases diff --git a/SOURCES/glibc-rh1555189-1.patch b/SOURCES/glibc-rh1555189-1.patch new file mode 100644 index 0000000..772b293 --- /dev/null +++ b/SOURCES/glibc-rh1555189-1.patch @@ -0,0 +1,35 @@ +This patch replaces the era block in ja_JP with the non-escaped +version. It is a partial backport of commit +a259f5d388d6195da958b2d147d17c2e2d16b857 ("Replaced unicode sequences +in the ASCII printable range"), containing only the changes to this +part of the localedata/locales/ja_JP file. + +diff --git a/localedata/locales/ja_JP b/localedata/locales/ja_JP +index 54e55b1b52e90f29..594df82f05a23719 100644 +--- a/localedata/locales/ja_JP ++++ b/localedata/locales/ja_JP +@@ -14942,15 +14942,15 @@ am_pm "<U5348><U524D>";"<U5348><U5F8C>" + + t_fmt_ampm "<U0025><U0070><U0025><U0049><U6642><U0025><U004D><U5206><U0025><U0053><U79D2>" + +-era "<U002B><U003A><U0032><U003A><U0031><U0039><U0039><U0030><U002F><U0030><U0031><U002F><U0030><U0031><U003A><U002B><U002A><U003A><U5E73><U6210><U003A><U0025><U0045><U0043><U0025><U0045><U0079><U5E74>";/ +- "<U002B><U003A><U0031><U003A><U0031><U0039><U0038><U0039><U002F><U0030><U0031><U002F><U0030><U0038><U003A><U0031><U0039><U0038><U0039><U002F><U0031><U0032><U002F><U0033><U0031><U003A><U5E73><U6210><U003A><U0025><U0045><U0043><U5143><U5E74>";/ +- "<U002B><U003A><U0032><U003A><U0031><U0039><U0032><U0037><U002F><U0030><U0031><U002F><U0030><U0031><U003A><U0031><U0039><U0038><U0039><U002F><U0030><U0031><U002F><U0030><U0037><U003A><U662D><U548C><U003A><U0025><U0045><U0043><U0025><U0045><U0079><U5E74>";/ +- "<U002B><U003A><U0031><U003A><U0031><U0039><U0032><U0036><U002F><U0031><U0032><U002F><U0032><U0035><U003A><U0031><U0039><U0032><U0036><U002F><U0031><U0032><U002F><U0033><U0031><U003A><U662D><U548C><U003A><U0025><U0045><U0043><U5143><U5E74>";/ +- "<U002B><U003A><U0032><U003A><U0031><U0039><U0031><U0033><U002F><U0030><U0031><U002F><U0030><U0031><U003A><U0031><U0039><U0032><U0036><U002F><U0031><U0032><U002F><U0032><U0034><U003A><U5927><U6B63><U003A><U0025><U0045><U0043><U0025><U0045><U0079><U5E74>";/ +- "<U002B><U003A><U0032><U003A><U0031><U0039><U0031><U0032><U002F><U0030><U0037><U002F><U0033><U0030><U003A><U0031><U0039><U0031><U0032><U002F><U0031><U0032><U002F><U0033><U0031><U003A><U5927><U6B63><U003A><U0025><U0045><U0043><U5143><U5E74>";/ +- "<U002B><U003A><U0036><U003A><U0031><U0038><U0037><U0033><U002F><U0030><U0031><U002F><U0030><U0031><U003A><U0031><U0039><U0031><U0032><U002F><U0030><U0037><U002F><U0032><U0039><U003A><U660E><U6CBB><U003A><U0025><U0045><U0043><U0025><U0045><U0079><U5E74>";/ +- "<U002B><U003A><U0031><U003A><U0030><U0030><U0030><U0031><U002F><U0030><U0031><U002F><U0030><U0031><U003A><U0031><U0038><U0037><U0032><U002F><U0031><U0032><U002F><U0033><U0031><U003A><U897F><U66A6><U003A><U0025><U0045><U0043><U0025><U0045><U0079><U5E74>";/ +- "<U002B><U003A><U0031><U003A><U002D><U0030><U0030><U0030><U0031><U002F><U0031><U0032><U002F><U0033><U0031><U003A><U002D><U002A><U003A><U7D00><U5143><U524D><U003A><U0025><U0045><U0043><U0025><U0045><U0079><U5E74>" ++era "+:2:1990//01//01:+*:<U5E73><U6210>:%EC%Ey<U5E74>";/ ++ "+:1:1989//01//08:1989//12//31:<U5E73><U6210>:%EC<U5143><U5E74>";/ ++ "+:2:1927//01//01:1989//01//07:<U662D><U548C>:%EC%Ey<U5E74>";/ ++ "+:1:1926//12//25:1926//12//31:<U662D><U548C>:%EC<U5143><U5E74>";/ ++ "+:2:1913//01//01:1926//12//24:<U5927><U6B63>:%EC%Ey<U5E74>";/ ++ "+:2:1912//07//30:1912//12//31:<U5927><U6B63>:%EC<U5143><U5E74>";/ ++ "+:6:1873//01//01:1912//07//29:<U660E><U6CBB>:%EC%Ey<U5E74>";/ ++ "+:1:0001//01//01:1872//12//31:<U897F><U66A6>:%EC%Ey<U5E74>";/ ++ "+:1:-0001//12//31:-*:<U7D00><U5143><U524D>:%EC%Ey<U5E74>" + + era_d_fmt "<U0025><U0045><U0059><U0025><U006d><U6708><U0025><U0064><U65E5>" + diff --git a/SOURCES/glibc-rh1555189-2.patch b/SOURCES/glibc-rh1555189-2.patch new file mode 100644 index 0000000..f9cbc16 --- /dev/null +++ b/SOURCES/glibc-rh1555189-2.patch @@ -0,0 +1,24 @@ +Patch by Hanataka Shinya <hanataka.shinya@gmail.com> from +<https://sourceware.org/bugzilla/show_bug.cgi?id=24405>. Confirmed by TAMUKI +Shoichi's patch in +<https://sourceware.org/ml/libc-alpha/2019-04/msg00005.html>. + +The official announcement by the Japanese Prime Minister in +<https://www.kantei.go.jp/jp/tyoukanpress/201904/1_a.html> uses U+4EE4 U+548C +as well. + +diff --git a/localedata/locales/ja_JP b/localedata/locales/ja_JP +index 594df82f05a23719..40cb5795fea730a5 100644 +--- a/localedata/locales/ja_JP ++++ b/localedata/locales/ja_JP +@@ -14942,7 +14942,9 @@ am_pm "<U5348><U524D>";"<U5348><U5F8C>" + + t_fmt_ampm "<U0025><U0070><U0025><U0049><U6642><U0025><U004D><U5206><U0025><U0053><U79D2>" + +-era "+:2:1990//01//01:+*:<U5E73><U6210>:%EC%Ey<U5E74>";/ ++era "+:2:2020//01//01:+*:<U4EE4><U548C>:%EC%Ey<U5E74>";/ ++ "+:1:2019//05//01:2019//12//31:<U4EE4><U548C>:%EC<U5143><U5E74>";/ ++ "+:2:1990//01//01:2019//04//30:<U5E73><U6210>:%EC%Ey<U5E74>";/ + "+:1:1989//01//08:1989//12//31:<U5E73><U6210>:%EC<U5143><U5E74>";/ + "+:2:1927//01//01:1989//01//07:<U662D><U548C>:%EC%Ey<U5E74>";/ + "+:1:1926//12//25:1926//12//31:<U662D><U548C>:%EC<U5143><U5E74>";/ diff --git a/SOURCES/glibc-rh1579354.patch b/SOURCES/glibc-rh1579354.patch new file mode 100644 index 0000000..e0182ce --- /dev/null +++ b/SOURCES/glibc-rh1579354.patch @@ -0,0 +1,57 @@ +commit 583a27d525ae189bdfaa6784021b92a9a1dae12e +Author: Florian Weimer <fweimer@redhat.com> +Date: Mon Apr 9 10:08:07 2018 +0200 + + resolv: Fully initialize struct mmsghdr in send_dg [BZ #23037] + +diff --git a/resolv/res_send.c b/resolv/res_send.c +index 478d542419566574..05c7ba511b0383c1 100644 +--- a/resolv/res_send.c ++++ b/resolv/res_send.c +@@ -1154,25 +1154,27 @@ send_dg(res_state statp, + if (have_sendmmsg >= 0 && nwritten == 0 && buf2 != NULL + && !single_request) + { +- struct iovec iov[2]; +- struct mmsghdr reqs[2]; +- reqs[0].msg_hdr.msg_name = NULL; +- reqs[0].msg_hdr.msg_namelen = 0; +- reqs[0].msg_hdr.msg_iov = &iov[0]; +- reqs[0].msg_hdr.msg_iovlen = 1; +- iov[0].iov_base = (void *) buf; +- iov[0].iov_len = buflen; +- reqs[0].msg_hdr.msg_control = NULL; +- reqs[0].msg_hdr.msg_controllen = 0; +- +- reqs[1].msg_hdr.msg_name = NULL; +- reqs[1].msg_hdr.msg_namelen = 0; +- reqs[1].msg_hdr.msg_iov = &iov[1]; +- reqs[1].msg_hdr.msg_iovlen = 1; +- iov[1].iov_base = (void *) buf2; +- iov[1].iov_len = buflen2; +- reqs[1].msg_hdr.msg_control = NULL; +- reqs[1].msg_hdr.msg_controllen = 0; ++ struct iovec iov = ++ { .iov_base = (void *) buf, .iov_len = buflen }; ++ struct iovec iov2 = ++ { .iov_base = (void *) buf2, .iov_len = buflen2 }; ++ struct mmsghdr reqs[2] = ++ { ++ { ++ .msg_hdr = ++ { ++ .msg_iov = &iov, ++ .msg_iovlen = 1, ++ }, ++ }, ++ { ++ .msg_hdr = ++ { ++ .msg_iov = &iov2, ++ .msg_iovlen = 1, ++ } ++ }, ++ }; + + int ndg = __sendmmsg (pfd[0].fd, reqs, 2, MSG_NOSIGNAL); + if (__glibc_likely (ndg == 2)) diff --git a/SOURCES/glibc-rh1579730-1.patch b/SOURCES/glibc-rh1579730-1.patch new file mode 100644 index 0000000..16a13ce --- /dev/null +++ b/SOURCES/glibc-rh1579730-1.patch @@ -0,0 +1,308 @@ +commit 68448be208ee06e76665918b37b0a57e3e00c8b4 +Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> +Date: Fri Nov 17 16:04:29 2017 -0200 + + i386: Fix i386 sigaction sa_restorer initialization (BZ#21269) + + This patch fixes the i386 sa_restorer field initialization for sigaction + syscall for kernel with vDSO. As described in bug report, i386 Linux + (and compat on x86_64) interprets SA_RESTORER clear with nonzero + sa_restorer as a request for stack switching if the SS segment is 'funny'. + This means that anything that tries to mix glibc's signal handling with + segmentation (for instance through modify_ldt syscall) is randomly broken + depending on what values lands in sa_restorer. + + The testcase added is based on Linux test tools/testing/selftests/x86/ldt_gdt.c, + more specifically in do_multicpu_tests function. The main changes are: + + - C11 atomics instead of plain access. + + - Remove x86_64 support which simplifies the syscall handling and fallbacks. + + - Replicate only the test required to trigger the issue. + + Checked on i686-linux-gnu. + + [BZ #21269] + * sysdeps/unix/sysv/linux/i386/Makefile (tests): Add tst-bz21269. + * sysdeps/unix/sysv/linux/i386/sigaction.c (SET_SA_RESTORER): Clear + sa_restorer for vDSO case. + * sysdeps/unix/sysv/linux/i386/tst-bz21269.c: New file. + +(Adjusted for conflicted in sysdeps/unix/sysv/linux/i386/Makefile due +different context around the addition of the new test.) + +diff --git a/sysdeps/unix/sysv/linux/i386/Makefile b/sysdeps/unix/sysv/linux/i386/Makefile +index acc30219e8dc965f..78e2101682d8d996 100644 +--- a/sysdeps/unix/sysv/linux/i386/Makefile ++++ b/sysdeps/unix/sysv/linux/i386/Makefile +@@ -3,6 +3,9 @@ default-abi := 32 + + ifeq ($(subdir),misc) + sysdep_routines += ioperm iopl vm86 call_pselect6 call_fallocate ++ ++tests += tst-bz21269 ++$(objpfx)tst-bz21269: $(shared-thread-library) + endif + + ifeq ($(subdir),elf) +diff --git a/sysdeps/unix/sysv/linux/i386/sigaction.c b/sysdeps/unix/sysv/linux/i386/sigaction.c +index 414ef759a97363c4..f10e1363865c3d18 100644 +--- a/sysdeps/unix/sysv/linux/i386/sigaction.c ++++ b/sysdeps/unix/sysv/linux/i386/sigaction.c +@@ -44,7 +44,6 @@ extern void restore_rt (void) asm ("__restore_rt") attribute_hidden; + #endif + extern void restore (void) asm ("__restore") attribute_hidden; + +- + /* If ACT is not NULL, change the action for SIG to *ACT. + If OACT is not NULL, put the old action for SIG in *OACT. */ + int +@@ -67,6 +66,8 @@ __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact) + kact.sa_restorer = ((act->sa_flags & SA_SIGINFO) + ? &restore_rt : &restore); + } ++ else ++ kact.sa_restorer = NULL; + } + + /* XXX The size argument hopefully will have to be changed to the +diff --git a/sysdeps/unix/sysv/linux/i386/tst-bz21269.c b/sysdeps/unix/sysv/linux/i386/tst-bz21269.c +new file mode 100644 +index 0000000000000000..353e36507dce92ea +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/i386/tst-bz21269.c +@@ -0,0 +1,233 @@ ++/* Test for i386 sigaction sa_restorer handling (BZ#21269) ++ 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 ++ <http://www.gnu.org/licenses/>. */ ++ ++/* This is based on Linux test tools/testing/selftests/x86/ldt_gdt.c, ++ more specifically in do_multicpu_tests function. The main changes ++ are: ++ ++ - C11 atomics instead of plain access. ++ - Remove x86_64 support which simplifies the syscall handling ++ and fallbacks. ++ - Replicate only the test required to trigger the issue for the ++ BZ#21269. */ ++ ++#include <stdatomic.h> ++ ++#include <asm/ldt.h> ++#include <linux/futex.h> ++ ++#include <setjmp.h> ++#include <signal.h> ++#include <errno.h> ++#include <sys/syscall.h> ++#include <sys/mman.h> ++ ++#include <support/xunistd.h> ++#include <support/check.h> ++#include <support/xthread.h> ++ ++static int ++xset_thread_area (struct user_desc *u_info) ++{ ++ long ret = syscall (SYS_set_thread_area, u_info); ++ TEST_VERIFY_EXIT (ret == 0); ++ return ret; ++} ++ ++static void ++xmodify_ldt (int func, const void *ptr, unsigned long bytecount) ++{ ++ TEST_VERIFY_EXIT (syscall (SYS_modify_ldt, 1, ptr, bytecount) == 0); ++} ++ ++static int ++futex (int *uaddr, int futex_op, int val, void *timeout, int *uaddr2, ++ int val3) ++{ ++ return syscall (SYS_futex, uaddr, futex_op, val, timeout, uaddr2, val3); ++} ++ ++static void ++xsethandler (int sig, void (*handler)(int, siginfo_t *, void *), int flags) ++{ ++ struct sigaction sa = { 0 }; ++ sa.sa_sigaction = handler; ++ sa.sa_flags = SA_SIGINFO | flags; ++ TEST_VERIFY_EXIT (sigemptyset (&sa.sa_mask) == 0); ++ TEST_VERIFY_EXIT (sigaction (sig, &sa, 0) == 0); ++} ++ ++static jmp_buf jmpbuf; ++ ++static void ++sigsegv_handler (int sig, siginfo_t *info, void *ctx_void) ++{ ++ siglongjmp (jmpbuf, 1); ++} ++ ++/* Points to an array of 1024 ints, each holding its own index. */ ++static const unsigned int *counter_page; ++static struct user_desc *low_user_desc; ++static struct user_desc *low_user_desc_clear; /* Used to delete GDT entry. */ ++static int gdt_entry_num; ++ ++static void ++setup_counter_page (void) ++{ ++ long page_size = sysconf (_SC_PAGE_SIZE); ++ TEST_VERIFY_EXIT (page_size > 0); ++ unsigned int *page = xmmap (NULL, page_size, PROT_READ | PROT_WRITE, ++ MAP_ANONYMOUS | MAP_PRIVATE | MAP_32BIT, -1); ++ for (int i = 0; i < (page_size / sizeof (unsigned int)); i++) ++ page[i] = i; ++ counter_page = page; ++} ++ ++static void ++setup_low_user_desc (void) ++{ ++ low_user_desc = xmmap (NULL, 2 * sizeof (struct user_desc), ++ PROT_READ | PROT_WRITE, ++ MAP_ANONYMOUS | MAP_PRIVATE | MAP_32BIT, -1); ++ ++ low_user_desc->entry_number = -1; ++ low_user_desc->base_addr = (unsigned long) &counter_page[1]; ++ low_user_desc->limit = 0xffff; ++ low_user_desc->seg_32bit = 1; ++ low_user_desc->contents = 0; ++ low_user_desc->read_exec_only = 0; ++ low_user_desc->limit_in_pages = 1; ++ low_user_desc->seg_not_present = 0; ++ low_user_desc->useable = 0; ++ ++ xset_thread_area (low_user_desc); ++ ++ low_user_desc_clear = low_user_desc + 1; ++ low_user_desc_clear->entry_number = gdt_entry_num; ++ low_user_desc_clear->read_exec_only = 1; ++ low_user_desc_clear->seg_not_present = 1; ++} ++ ++/* Possible values of futex: ++ 0: thread is idle. ++ 1: thread armed. ++ 2: thread should clear LDT entry 0. ++ 3: thread should exit. */ ++static atomic_uint ftx; ++ ++static void * ++threadproc (void *ctx) ++{ ++ while (1) ++ { ++ futex ((int *) &ftx, FUTEX_WAIT, 1, NULL, NULL, 0); ++ while (atomic_load (&ftx) != 2) ++ { ++ if (atomic_load (&ftx) >= 3) ++ return NULL; ++ } ++ ++ /* clear LDT entry 0. */ ++ const struct user_desc desc = { 0 }; ++ xmodify_ldt (1, &desc, sizeof (desc)); ++ ++ /* If ftx == 2, set it to zero, If ftx == 100, quit. */ ++ if (atomic_fetch_add (&ftx, -2) != 2) ++ return NULL; ++ } ++} ++ ++ ++/* As described in testcase, for historical reasons x86_32 Linux (and compat ++ on x86_64) interprets SA_RESTORER clear with nonzero sa_restorer as a ++ request for stack switching if the SS segment is 'funny' (this is default ++ scenario for vDSO system). This means that anything that tries to mix ++ signal handling with segmentation should explicit clear the sa_restorer. ++ ++ This testcase check if sigaction in fact does it by changing the local ++ descriptor table (LDT) through the modify_ldt syscall and triggering ++ a synchronous segfault on iret fault by trying to install an invalid ++ segment. With a correct zeroed sa_restorer it should not trigger an ++ 'real' SEGSEGV and allows the siglongjmp in signal handler. */ ++ ++static int ++do_test (void) ++{ ++ setup_counter_page (); ++ setup_low_user_desc (); ++ ++ pthread_t thread; ++ unsigned short orig_ss; ++ ++ xsethandler (SIGSEGV, sigsegv_handler, 0); ++ /* 32-bit kernels send SIGILL instead of SIGSEGV on IRET faults. */ ++ xsethandler (SIGILL, sigsegv_handler, 0); ++ ++ thread = xpthread_create (0, threadproc, 0); ++ ++ asm volatile ("mov %%ss, %0" : "=rm" (orig_ss)); ++ ++ for (int i = 0; i < 5; i++) ++ { ++ if (sigsetjmp (jmpbuf, 1) != 0) ++ continue; ++ ++ /* Make sure the thread is ready after the last test. */ ++ while (atomic_load (&ftx) != 0) ++ ; ++ ++ struct user_desc desc = { ++ .entry_number = 0, ++ .base_addr = 0, ++ .limit = 0xffff, ++ .seg_32bit = 1, ++ .contents = 0, ++ .read_exec_only = 0, ++ .limit_in_pages = 1, ++ .seg_not_present = 0, ++ .useable = 0 ++ }; ++ ++ xmodify_ldt (0x11, &desc, sizeof (desc)); ++ ++ /* Arm the thread. */ ++ ftx = 1; ++ futex ((int*) &ftx, FUTEX_WAKE, 0, NULL, NULL, 0); ++ ++ asm volatile ("mov %0, %%ss" : : "r" (0x7)); ++ ++ /* Fire up thread modify_ldt call. */ ++ atomic_store (&ftx, 2); ++ ++ while (atomic_load (&ftx) != 0) ++ ; ++ ++ /* On success, modify_ldt will segfault us synchronously and we will ++ escape via siglongjmp. */ ++ support_record_failure (); ++ } ++ ++ atomic_store (&ftx, 100); ++ futex ((int*) &ftx, FUTEX_WAKE, 0, NULL, NULL, 0); ++ ++ xpthread_join (thread); ++ ++ return 0; ++} ++ ++#include <support/test-driver.c> diff --git a/SOURCES/glibc-rh1579730-2.patch b/SOURCES/glibc-rh1579730-2.patch new file mode 100644 index 0000000..fbf93f8 --- /dev/null +++ b/SOURCES/glibc-rh1579730-2.patch @@ -0,0 +1,22 @@ +commit 4d76d3e59d31aa690f148fc0c95cc0c581aed3e8 +Author: Florian Weimer <fweimer@redhat.com> +Date: Thu Mar 29 11:42:24 2018 +0200 + + Linux i386: tst-bz21269 triggers SIGBUS on some kernels + + In addition to SIGSEGV and SIGILL, SIGBUS is also a possible signal + generated by the kernel. + +diff --git a/sysdeps/unix/sysv/linux/i386/tst-bz21269.c b/sysdeps/unix/sysv/linux/i386/tst-bz21269.c +index 353e36507dce92ea..6ee3fc62be0d3312 100644 +--- a/sysdeps/unix/sysv/linux/i386/tst-bz21269.c ++++ b/sysdeps/unix/sysv/linux/i386/tst-bz21269.c +@@ -177,6 +177,8 @@ do_test (void) + xsethandler (SIGSEGV, sigsegv_handler, 0); + /* 32-bit kernels send SIGILL instead of SIGSEGV on IRET faults. */ + xsethandler (SIGILL, sigsegv_handler, 0); ++ /* Some kernels send SIGBUS instead. */ ++ xsethandler (SIGBUS, sigsegv_handler, 0); + + thread = xpthread_create (0, threadproc, 0); + diff --git a/SOURCES/glibc-rh1579730-3.patch b/SOURCES/glibc-rh1579730-3.patch new file mode 100644 index 0000000..e051406 --- /dev/null +++ b/SOURCES/glibc-rh1579730-3.patch @@ -0,0 +1,131 @@ +Port sysdeps/unix/sysv/linux/i386/tst-bz21269.c to __atomic builtins + +The upstream test uses <stdatomic.h>, which is not supported in the +Red Hat Enterprise Linux 7 system compiler. + +The port uses __ATOMIC_SEQ_CST for consistency with the upstream test; +such as trong memory ordering is not actually required here. + +Furthermore, it is necessary to change the SYS_ system call constants +to __NR_ constants. Downstream builts the test with internal headers, +and those only have the __NR_ constants from the kernel. + +The initializer of sa in xsethandler was replaced with a memset, to +avoid a warning about missing braces in an initializer (something that +later GCC versions do not warn about). + +diff --git a/sysdeps/unix/sysv/linux/i386/tst-bz21269.c b/sysdeps/unix/sysv/linux/i386/tst-bz21269.c +index 6ee3fc62be0d3312..f58395cedc6972c4 100644 +--- a/sysdeps/unix/sysv/linux/i386/tst-bz21269.c ++++ b/sysdeps/unix/sysv/linux/i386/tst-bz21269.c +@@ -26,8 +26,6 @@ + - Replicate only the test required to trigger the issue for the + BZ#21269. */ + +-#include <stdatomic.h> +- + #include <asm/ldt.h> + #include <linux/futex.h> + +@@ -36,6 +34,7 @@ + #include <errno.h> + #include <sys/syscall.h> + #include <sys/mman.h> ++#include <string.h> + + #include <support/xunistd.h> + #include <support/check.h> +@@ -44,7 +43,7 @@ + static int + xset_thread_area (struct user_desc *u_info) + { +- long ret = syscall (SYS_set_thread_area, u_info); ++ long ret = syscall (__NR_set_thread_area, u_info); + TEST_VERIFY_EXIT (ret == 0); + return ret; + } +@@ -52,20 +51,21 @@ xset_thread_area (struct user_desc *u_info) + static void + xmodify_ldt (int func, const void *ptr, unsigned long bytecount) + { +- TEST_VERIFY_EXIT (syscall (SYS_modify_ldt, 1, ptr, bytecount) == 0); ++ TEST_VERIFY_EXIT (syscall (__NR_modify_ldt, 1, ptr, bytecount) == 0); + } + + static int + futex (int *uaddr, int futex_op, int val, void *timeout, int *uaddr2, + int val3) + { +- return syscall (SYS_futex, uaddr, futex_op, val, timeout, uaddr2, val3); ++ return syscall (__NR_futex, uaddr, futex_op, val, timeout, uaddr2, val3); + } + + static void + xsethandler (int sig, void (*handler)(int, siginfo_t *, void *), int flags) + { +- struct sigaction sa = { 0 }; ++ struct sigaction sa; ++ memset (&sa, 0, sizeof (sa)); + sa.sa_sigaction = handler; + sa.sa_flags = SA_SIGINFO | flags; + TEST_VERIFY_EXIT (sigemptyset (&sa.sa_mask) == 0); +@@ -128,7 +128,7 @@ setup_low_user_desc (void) + 1: thread armed. + 2: thread should clear LDT entry 0. + 3: thread should exit. */ +-static atomic_uint ftx; ++static unsigned int ftx; + + static void * + threadproc (void *ctx) +@@ -136,9 +136,9 @@ threadproc (void *ctx) + while (1) + { + futex ((int *) &ftx, FUTEX_WAIT, 1, NULL, NULL, 0); +- while (atomic_load (&ftx) != 2) ++ while (__atomic_load_n (&ftx, __ATOMIC_SEQ_CST) != 2) + { +- if (atomic_load (&ftx) >= 3) ++ if (__atomic_load_n (&ftx, __ATOMIC_SEQ_CST) >= 3) + return NULL; + } + +@@ -147,7 +147,7 @@ threadproc (void *ctx) + xmodify_ldt (1, &desc, sizeof (desc)); + + /* If ftx == 2, set it to zero, If ftx == 100, quit. */ +- if (atomic_fetch_add (&ftx, -2) != 2) ++ if (__atomic_fetch_add (&ftx, -2, __ATOMIC_SEQ_CST) != 2) + return NULL; + } + } +@@ -190,7 +190,7 @@ do_test (void) + continue; + + /* Make sure the thread is ready after the last test. */ +- while (atomic_load (&ftx) != 0) ++ while (__atomic_load_n (&ftx, __ATOMIC_SEQ_CST) != 0) + ; + + struct user_desc desc = { +@@ -214,9 +214,9 @@ do_test (void) + asm volatile ("mov %0, %%ss" : : "r" (0x7)); + + /* Fire up thread modify_ldt call. */ +- atomic_store (&ftx, 2); ++ __atomic_store_n (&ftx, 2, __ATOMIC_SEQ_CST); + +- while (atomic_load (&ftx) != 0) ++ while (__atomic_load_n (&ftx, __ATOMIC_SEQ_CST) != 0) + ; + + /* On success, modify_ldt will segfault us synchronously and we will +@@ -224,7 +224,7 @@ do_test (void) + support_record_failure (); + } + +- atomic_store (&ftx, 100); ++ __atomic_store_n (&ftx, 100, __ATOMIC_SEQ_CST); + futex ((int*) &ftx, FUTEX_WAKE, 0, NULL, NULL, 0); + + xpthread_join (thread); diff --git a/SOURCES/glibc-rh1579739-2.patch b/SOURCES/glibc-rh1579739-2.patch new file mode 100644 index 0000000..72ea53e --- /dev/null +++ b/SOURCES/glibc-rh1579739-2.patch @@ -0,0 +1,66 @@ +commit c259196b5005812aa3294dbf4eeca29b266a4522 +Author: Florian Weimer <fweimer@redhat.com> +Date: Fri Mar 1 18:53:03 2019 +0100 + + elf/tst-big-note: Improve accuracy of test [BZ #20419] + + It is possible that the link editor injects an allocated ABI tag note + before the artificial, allocated large note in the test. Note parsing + in open_verify stops when the first ABI tag note is encountered, so if + the ABI tag note comes first, the problematic code is not actually + exercised. + + Also tweak the artificial note so that it is a syntactically valid + 4-byte aligned note, in case the link editor tries to parse notes and + process them. + + Improves the testing part of commit 0065aaaaae51cd60210ec3a7e13. + + Reviewed-by: Carlos O'Donell <carlos@redhat.com> + +(Minor adjustment for Makefile conflict.) + +diff --git a/elf/Makefile b/elf/Makefile +index b46b3a0e3542a06f..2b2662d5cf96c437 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -244,8 +244,8 @@ extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) + # We need this variable to be sure the test modules get the right CPPFLAGS. + test-extras += $(modules-names) + +-# filtmod1.so has a special rule +-modules-names-nobuild := filtmod1 ++# filtmod1.so, tst-big-note-lib.so have special rules. ++modules-names-nobuild := filtmod1 tst-big-note-lib + + ifneq (no,$(multi-arch)) + tests-static += ifuncmain1static ifuncmain1picstatic \ +@@ -1239,3 +1239,8 @@ $(objpfx)tst-audit12mod1.so: $(objpfx)tst-audit12mod2.so + LDFLAGS-tst-audit12mod2.so = -Wl,--version-script=tst-audit12mod2.map + + $(objpfx)tst-big-note: $(objpfx)tst-big-note-lib.so ++# Avoid creating an ABI tag note, which may come before the ++# artificial, large note in tst-big-note-lib.o and invalidate the ++# test. ++$(objpfx)tst-big-note-lib.so: $(objpfx)tst-big-note-lib.o ++ $(LINK.o) -shared -o $@ $(LDFLAGS.so) $< +diff --git a/elf/tst-big-note-lib.S b/elf/tst-big-note-lib.S +index 6b514a03cc686141..c97590ccb05e9b2e 100644 +--- a/elf/tst-big-note-lib.S ++++ b/elf/tst-big-note-lib.S +@@ -20,7 +20,13 @@ + On a typical Linux system with 8MiB "ulimit -s", that was enough + to trigger stack overflow in open_verify. */ + ++#define NOTE_SIZE 8*1024*1024 ++ + .pushsection .note.big,"a" +-.balign 4 +-.fill 8*1024*1024, 1, 0 ++ .balign 4 ++ .long 5 /* n_namesz. Length of "GLIBC". */ ++ .long NOTE_SIZE /* n_descsz. */ ++ .long 0 /* n_type. */ ++ .ascii "GLIBC\0\0\0" /* Name and alignment to four bytes. */ ++ .fill NOTE_SIZE, 1, 0 + .popsection diff --git a/SOURCES/glibc-rh1579739.patch b/SOURCES/glibc-rh1579739.patch new file mode 100644 index 0000000..f6811d5 --- /dev/null +++ b/SOURCES/glibc-rh1579739.patch @@ -0,0 +1,162 @@ +commit 0065aaaaae51cd60210ec3a7e13dddd8e01ffe2c +Author: Paul Pluzhnikov <ppluzhnikov@google.com> +Date: Sat May 5 18:08:27 2018 -0700 + + Fix BZ 20419. A PT_NOTE in a binary could be arbitratily large, so using + alloca for it may cause stack overflow. If the note is larger than + __MAX_ALLOCA_CUTOFF, use dynamically allocated memory to read it in. + + 2018-05-05 Paul Pluzhnikov <ppluzhnikov@google.com> + + [BZ #20419] + * elf/dl-load.c (open_verify): Fix stack overflow. + * elf/Makefile (tst-big-note): New test. + * elf/tst-big-note-lib.S: New. + * elf/tst-big-note.c: New. + +Minor textual conflicts and elf/Makefile due to continued upstream +development. + +diff --git a/elf/Makefile b/elf/Makefile +index dea66ca1c12e5c29..b46b3a0e3542a06f 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -151,7 +151,8 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \ + tst-audit1 tst-audit2 tst-audit8 tst-audit9 \ + tst-stackguard1 tst-addr1 tst-thrlock \ + tst-unique1 tst-unique2 tst-unique3 tst-unique4 \ +- tst-initorder tst-initorder2 tst-relsort1 tst-ptrguard1 ++ tst-initorder tst-initorder2 tst-relsort1 tst-ptrguard1 \ ++ tst-big-note + # reldep9 + test-srcs = tst-pathopt + selinux-enabled := $(shell cat /selinux/enforce 2> /dev/null) +@@ -223,7 +224,9 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ + tst-relsort1mod1 tst-relsort1mod2 tst-array2dep \ + tst-array5dep \ + tst-audit11mod1 tst-audit11mod2 tst-auditmod11 \ +- tst-audit12mod1 tst-audit12mod2 tst-audit12mod3 tst-auditmod12 ++ tst-audit12mod1 tst-audit12mod2 tst-audit12mod3 tst-auditmod12 \ ++ tst-big-note-lib ++ + ifeq (yesyes,$(have-fpie)$(build-shared)) + modules-names += tst-piemod1 + tests += tst-pie1 +@@ -1234,3 +1237,5 @@ $(objpfx)tst-audit12: $(libdl) + tst-audit12-ENV = LD_AUDIT=$(objpfx)tst-auditmod12.so + $(objpfx)tst-audit12mod1.so: $(objpfx)tst-audit12mod2.so + LDFLAGS-tst-audit12mod2.so = -Wl,--version-script=tst-audit12mod2.map ++ ++$(objpfx)tst-big-note: $(objpfx)tst-big-note-lib.so +diff --git a/elf/dl-load.c b/elf/dl-load.c +index 7466b686244e55b2..013efdb3814700d3 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -1744,6 +1744,7 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader, + ElfW(Ehdr) *ehdr; + ElfW(Phdr) *phdr, *ph; + ElfW(Word) *abi_note; ++ ElfW(Word) *abi_note_malloced = NULL; + unsigned int osversion; + size_t maplength; + +@@ -1889,10 +1890,25 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader, + abi_note = (void *) (fbp->buf + ph->p_offset); + else + { +- abi_note = alloca (size); ++ /* Note: __libc_use_alloca is not usable here, because ++ thread info may not have been set up yet. */ ++ if (size < __MAX_ALLOCA_CUTOFF) ++ abi_note = alloca (size); ++ else ++ { ++ /* There could be multiple PT_NOTEs. */ ++ abi_note_malloced = realloc (abi_note_malloced, size); ++ if (abi_note_malloced == NULL) ++ goto read_error; ++ ++ abi_note = abi_note_malloced; ++ } + __lseek (fd, ph->p_offset, SEEK_SET); + if (__libc_read (fd, (void *) abi_note, size) != size) +- goto read_error; ++ { ++ free (abi_note_malloced); ++ goto read_error; ++ } + } + + while (memcmp (abi_note, &expected_note, sizeof (expected_note))) +@@ -1928,6 +1944,7 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader, + + break; + } ++ free (abi_note_malloced); + } + + return fd; +diff --git a/elf/tst-big-note-lib.S b/elf/tst-big-note-lib.S +new file mode 100644 +index 0000000000000000..6b514a03cc686141 +--- /dev/null ++++ b/elf/tst-big-note-lib.S +@@ -0,0 +1,26 @@ ++/* Bug 20419: test for stack overflow in elf/dl-load.c open_verify() ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++/* This creates a .so with 8MiB PT_NOTE segment. ++ On a typical Linux system with 8MiB "ulimit -s", that was enough ++ to trigger stack overflow in open_verify. */ ++ ++.pushsection .note.big,"a" ++.balign 4 ++.fill 8*1024*1024, 1, 0 ++.popsection +diff --git a/elf/tst-big-note.c b/elf/tst-big-note.c +new file mode 100644 +index 0000000000000000..fcd2b0ed82cc1667 +--- /dev/null ++++ b/elf/tst-big-note.c +@@ -0,0 +1,26 @@ ++/* Bug 20419: test for stack overflow in elf/dl-load.c open_verify() ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++/* This file must be run from within a directory called "elf". */ ++ ++int main (int argc, char *argv[]) ++{ ++ /* Nothing to do here: merely linking against tst-big-note-lib.so triggers ++ the bug. */ ++ return 0; ++} diff --git a/SOURCES/glibc-rh1591268.patch b/SOURCES/glibc-rh1591268.patch new file mode 100644 index 0000000..3dc8bd6 --- /dev/null +++ b/SOURCES/glibc-rh1591268.patch @@ -0,0 +1,38 @@ +From 14beef7575099f6373f9a45b4656f1e3675f7372 Mon Sep 17 00:00:00 2001 +From: Florian Weimer <fweimer@redhat.com> +Date: Thu, 14 Jun 2018 22:34:09 +0200 +Subject: [PATCH] localedata: Make IBM273 compatible with ISO-8859-1 [BZ + #23290] + +Reviewed-by: Carlos O'Donell <carlos@redhat.com> +--- + ChangeLog | 8 ++++++++ + iconvdata/ibm273.c | 2 +- + localedata/charmaps/IBM273 | 2 +- + 3 files changed, 10 insertions(+), 2 deletions(-) + +Index: b/iconvdata/ibm273.c +=================================================================== +--- a/iconvdata/ibm273.c ++++ b/iconvdata/ibm273.c +@@ -23,6 +23,6 @@ + #define TABLES <ibm273.h> + + #define CHARSET_NAME "IBM273//" +-#define HAS_HOLES 1 /* Not all 256 character are defined. */ ++#define HAS_HOLES 0 + + #include <8bit-gap.c> +Index: b/localedata/charmaps/IBM273 +=================================================================== +--- a/localedata/charmaps/IBM273 ++++ b/localedata/charmaps/IBM273 +@@ -194,7 +194,7 @@ CHARMAP + <U00BE> /xb9 VULGAR FRACTION THREE QUARTERS + <U00AC> /xba NOT SIGN + <U007C> /xbb VERTICAL LINE +-<U203E> /xbc OVERLINE ++<U00AF> /xbc MACRON + <U00A8> /xbd DIAERESIS + <U00B4> /xbe ACUTE ACCENT + <U00D7> /xbf MULTIPLICATION SIGN diff --git a/SOURCES/glibc-rh1592475-1.patch b/SOURCES/glibc-rh1592475-1.patch new file mode 100644 index 0000000..e1785dc --- /dev/null +++ b/SOURCES/glibc-rh1592475-1.patch @@ -0,0 +1,194 @@ +From f2857da7cdb65bfad75ee30981f5b2fde5bbb1dc Mon Sep 17 00:00:00 2001 +From: Joseph Myers <joseph@codesourcery.com> +Date: Mon, 18 Jun 2018 13:37:57 +0000 +Subject: [PATCH] Add SHM_STAT_ANY from Linux 4.17 to bits/shm.h. + +Linux 4.17 adds a SHM_STAT_ANY constant (ipcs command). This patch +adds it to the relevant bits/shm.h headers. + +Tested for x86_64. + + * sysdeps/unix/sysv/linux/alpha/bits/shm.h [__USE_MISC] + (SHM_STAT_ANY): New macro. + * sysdeps/unix/sysv/linux/arm/bits/shm.h [__USE_MISC] + (SHM_STAT_ANY): Likewise. + * sysdeps/unix/sysv/linux/bits/shm.h [__USE_MISC] + (SHM_STAT_ANY): Likewise. + * sysdeps/unix/sysv/linux/generic/bits/shm.h [__USE_MISC] + (SHM_STAT_ANY): Likewise. + * sysdeps/unix/sysv/linux/hppa/bits/shm.h [__USE_MISC] + (SHM_STAT_ANY): Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/shm.h [__USE_MISC] + (SHM_STAT_ANY): Likewise. + * sysdeps/unix/sysv/linux/mips/bits/shm.h [__USE_MISC] + (SHM_STAT_ANY): Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/shm.h [__USE_MISC] + (SHM_STAT_ANY): Likewise. + * sysdeps/unix/sysv/linux/s390/bits/shm.h [__USE_MISC] + (SHM_STAT_ANY): Likewise. + * sysdeps/unix/sysv/linux/sh/bits/shm.h [__USE_MISC] + (SHM_STAT_ANY): Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/shm.h [__USE_MISC] + (SHM_STAT_ANY): Likewise. + * sysdeps/unix/sysv/linux/x86/bits/shm.h [__USE_MISC] + (SHM_STAT_ANY): Likewise. +--- + ChangeLog | 25 ++++++++++++++++++++++ + sysdeps/unix/sysv/linux/alpha/bits/shm.h | 1 + + sysdeps/unix/sysv/linux/arm/bits/shm.h | 1 + + sysdeps/unix/sysv/linux/bits/shm.h | 1 + + sysdeps/unix/sysv/linux/generic/bits/shm.h | 1 + + sysdeps/unix/sysv/linux/hppa/bits/shm.h | 1 + + sysdeps/unix/sysv/linux/ia64/bits/shm.h | 1 + + sysdeps/unix/sysv/linux/mips/bits/shm.h | 1 + + sysdeps/unix/sysv/linux/powerpc/bits/shm.h | 1 + + sysdeps/unix/sysv/linux/s390/bits/shm.h | 1 + + sysdeps/unix/sysv/linux/sh/bits/shm.h | 1 + + sysdeps/unix/sysv/linux/sparc/bits/shm.h | 1 + + sysdeps/unix/sysv/linux/x86/bits/shm.h | 1 + + 13 files changed, 37 insertions(+) + +Index: b/sysdeps/unix/sysv/linux/alpha/bits/shm.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/alpha/bits/shm.h ++++ b/sysdeps/unix/sysv/linux/alpha/bits/shm.h +@@ -65,6 +65,7 @@ struct shmid_ds + /* ipcs ctl commands */ + # define SHM_STAT 13 + # define SHM_INFO 14 ++# define SHM_STAT_ANY 15 + + /* shm_mode upper byte flags */ + # define SHM_DEST 01000 /* segment will be destroyed on last detach */ +Index: b/sysdeps/unix/sysv/linux/arm/bits/shm.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/arm/bits/shm.h ++++ b/sysdeps/unix/sysv/linux/arm/bits/shm.h +@@ -69,6 +69,7 @@ struct shmid_ds + /* ipcs ctl commands */ + # define SHM_STAT 13 + # define SHM_INFO 14 ++# define SHM_STAT_ANY 15 + + /* shm_mode upper byte flags */ + # define SHM_DEST 01000 /* segment will be destroyed on last detach */ +Index: b/sysdeps/unix/sysv/linux/bits/shm.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/bits/shm.h ++++ b/sysdeps/unix/sysv/linux/bits/shm.h +@@ -68,6 +68,7 @@ struct shmid_ds + /* ipcs ctl commands */ + # define SHM_STAT 13 + # define SHM_INFO 14 ++# define SHM_STAT_ANY 15 + + /* shm_mode upper byte flags */ + # define SHM_DEST 01000 /* segment will be destroyed on last detach */ +Index: b/sysdeps/unix/sysv/linux/generic/bits/shm.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/generic/bits/shm.h ++++ b/sysdeps/unix/sysv/linux/generic/bits/shm.h +@@ -76,6 +76,7 @@ struct shmid_ds + /* ipcs ctl commands */ + # define SHM_STAT 13 + # define SHM_INFO 14 ++# define SHM_STAT_ANY 15 + + /* shm_mode upper byte flags */ + # define SHM_DEST 01000 /* segment will be destroyed on last detach */ +Index: b/sysdeps/unix/sysv/linux/hppa/bits/shm.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/hppa/bits/shm.h ++++ b/sysdeps/unix/sysv/linux/hppa/bits/shm.h +@@ -73,6 +73,7 @@ struct shmid_ds + /* ipcs ctl commands */ + # define SHM_STAT 13 + # define SHM_INFO 14 ++# define SHM_STAT_ANY 15 + + /* shm_mode upper byte flags */ + # define SHM_DEST 01000 /* segment will be destroyed on last detach */ +Index: b/sysdeps/unix/sysv/linux/ia64/bits/shm.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/ia64/bits/shm.h ++++ b/sysdeps/unix/sysv/linux/ia64/bits/shm.h +@@ -61,6 +61,7 @@ struct shmid_ds + /* ipcs ctl commands */ + # define SHM_STAT 13 + # define SHM_INFO 14 ++# define SHM_STAT_ANY 15 + + /* shm_mode upper byte flags */ + # define SHM_DEST 01000 /* segment will be destroyed on last detach */ +Index: b/sysdeps/unix/sysv/linux/mips/bits/shm.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/mips/bits/shm.h ++++ b/sysdeps/unix/sysv/linux/mips/bits/shm.h +@@ -62,6 +62,7 @@ struct shmid_ds + /* ipcs ctl commands */ + # define SHM_STAT 13 + # define SHM_INFO 14 ++# define SHM_STAT_ANY 15 + + /* shm_mode upper byte flags */ + # define SHM_DEST 01000 /* segment will be destroyed on last detach */ +Index: b/sysdeps/unix/sysv/linux/powerpc/bits/shm.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/powerpc/bits/shm.h ++++ b/sysdeps/unix/sysv/linux/powerpc/bits/shm.h +@@ -78,6 +78,7 @@ struct shmid_ds + /* ipcs ctl commands */ + # define SHM_STAT 13 + # define SHM_INFO 14 ++# define SHM_STAT_ANY 15 + + /* shm_mode upper byte flags */ + # define SHM_DEST 01000 /* segment will be destroyed on last detach */ +Index: b/sysdeps/unix/sysv/linux/s390/bits/shm.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/s390/bits/shm.h ++++ b/sysdeps/unix/sysv/linux/s390/bits/shm.h +@@ -75,6 +75,7 @@ struct shmid_ds + /* ipcs ctl commands */ + # define SHM_STAT 13 + # define SHM_INFO 14 ++# define SHM_STAT_ANY 15 + + /* shm_mode upper byte flags */ + # define SHM_DEST 01000 /* segment will be destroyed on last detach */ +Index: b/sysdeps/unix/sysv/linux/sh/bits/shm.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/sh/bits/shm.h ++++ b/sysdeps/unix/sysv/linux/sh/bits/shm.h +@@ -66,6 +66,7 @@ struct shmid_ds + /* ipcs ctl commands */ + # define SHM_STAT 13 + # define SHM_INFO 14 ++# define SHM_STAT_ANY 15 + + /* shm_mode upper byte flags */ + # define SHM_DEST 01000 /* segment will be destroyed on last detach */ +Index: b/sysdeps/unix/sysv/linux/sparc/bits/shm.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/sparc/bits/shm.h ++++ b/sysdeps/unix/sysv/linux/sparc/bits/shm.h +@@ -76,6 +76,7 @@ struct shmid_ds + /* ipcs ctl commands */ + # define SHM_STAT 13 + # define SHM_INFO 14 ++# define SHM_STAT_ANY 15 + + /* shm_mode upper byte flags */ + # define SHM_DEST 01000 /* segment will be destroyed on last detach */ +Index: b/sysdeps/unix/sysv/linux/x86/bits/shm.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/x86/bits/shm.h ++++ b/sysdeps/unix/sysv/linux/x86/bits/shm.h +@@ -74,6 +74,7 @@ struct shmid_ds + /* ipcs ctl commands */ + # define SHM_STAT 13 + # define SHM_INFO 14 ++# define SHM_STAT_ANY 15 + + /* shm_mode upper byte flags */ + # define SHM_DEST 01000 /* segment will be destroyed on last detach */ diff --git a/SOURCES/glibc-rh1592475-2.patch b/SOURCES/glibc-rh1592475-2.patch new file mode 100644 index 0000000..7b6fc50 --- /dev/null +++ b/SOURCES/glibc-rh1592475-2.patch @@ -0,0 +1,164 @@ +From 176c7fee517c11f628aed4ef4b9457e47fa976a1 Mon Sep 17 00:00:00 2001 +From: Joseph Myers <joseph@codesourcery.com> +Date: Mon, 18 Jun 2018 13:36:41 +0000 +Subject: [PATCH] Add SEM_STAT_ANY from Linux 4.17 to bits/sem.h. + +Linux 4.17 adds a SEM_STAT_ANY constant (ipcs command). This patch +adds it to the relevant bits/sem.h headers. + +Tested for x86_64. + + * sysdeps/unix/sysv/linux/alpha/bits/sem.h [__USE_MISC] + (SEM_STAT_ANY): New macro. + * sysdeps/unix/sysv/linux/bits/sem.h [__USE_MISC] + (SEM_STAT_ANY): Likewise. + * sysdeps/unix/sysv/linux/generic/bits/sem.h [__USE_MISC] + (SEM_STAT_ANY): Likewise. + * sysdeps/unix/sysv/linux/hppa/bits/sem.h [__USE_MISC] + (SEM_STAT_ANY): Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/sem.h [__USE_MISC] + (SEM_STAT_ANY): Likewise. + * sysdeps/unix/sysv/linux/mips/bits/sem.h [__USE_MISC] + (SEM_STAT_ANY): Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/sem.h [__USE_MISC] + (SEM_STAT_ANY): Likewise. + * sysdeps/unix/sysv/linux/s390/bits/sem.h [__USE_MISC] + (SEM_STAT_ANY): Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/sem.h [__USE_MISC] + (SEM_STAT_ANY): Likewise. + * sysdeps/unix/sysv/linux/x86/bits/sem.h [__USE_MISC] + (SEM_STAT_ANY): Likewise. +--- + ChangeLog | 21 +++++++++++++++++++++ + sysdeps/unix/sysv/linux/alpha/bits/sem.h | 1 + + sysdeps/unix/sysv/linux/bits/sem.h | 1 + + sysdeps/unix/sysv/linux/generic/bits/sem.h | 1 + + sysdeps/unix/sysv/linux/hppa/bits/sem.h | 1 + + sysdeps/unix/sysv/linux/ia64/bits/sem.h | 1 + + sysdeps/unix/sysv/linux/mips/bits/sem.h | 1 + + sysdeps/unix/sysv/linux/powerpc/bits/sem.h | 1 + + sysdeps/unix/sysv/linux/s390/bits/sem.h | 1 + + sysdeps/unix/sysv/linux/sparc/bits/sem.h | 1 + + sysdeps/unix/sysv/linux/x86/bits/sem.h | 1 + + 11 files changed, 31 insertions(+) + +Index: b/sysdeps/unix/sysv/linux/alpha/bits/sem.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/alpha/bits/sem.h ++++ b/sysdeps/unix/sysv/linux/alpha/bits/sem.h +@@ -66,6 +66,7 @@ struct semid_ds + /* ipcs ctl cmds */ + # define SEM_STAT 18 + # define SEM_INFO 19 ++# define SEM_STAT_ANY 20 + + struct seminfo + { +Index: b/sysdeps/unix/sysv/linux/bits/sem.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/bits/sem.h ++++ b/sysdeps/unix/sysv/linux/bits/sem.h +@@ -68,6 +68,7 @@ struct semid_ds + /* ipcs ctl cmds */ + # define SEM_STAT 18 + # define SEM_INFO 19 ++# define SEM_STAT_ANY 20 + + struct seminfo + { +Index: b/sysdeps/unix/sysv/linux/generic/bits/sem.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/generic/bits/sem.h ++++ b/sysdeps/unix/sysv/linux/generic/bits/sem.h +@@ -74,6 +74,7 @@ struct semid_ds + /* ipcs ctl cmds */ + # define SEM_STAT 18 + # define SEM_INFO 19 ++# define SEM_STAT_ANY 20 + + struct seminfo + { +Index: b/sysdeps/unix/sysv/linux/hppa/bits/sem.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/hppa/bits/sem.h ++++ b/sysdeps/unix/sysv/linux/hppa/bits/sem.h +@@ -73,6 +73,7 @@ struct semid_ds + /* ipcs ctl cmds */ + # define SEM_STAT 18 + # define SEM_INFO 19 ++# define SEM_STAT_ANY 20 + + struct seminfo + { +Index: b/sysdeps/unix/sysv/linux/ia64/bits/sem.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/ia64/bits/sem.h ++++ b/sysdeps/unix/sysv/linux/ia64/bits/sem.h +@@ -68,6 +68,7 @@ struct semid_ds + /* ipcs ctl cmds */ + # define SEM_STAT 18 + # define SEM_INFO 19 ++# define SEM_STAT_ANY 20 + + struct seminfo + { +Index: b/sysdeps/unix/sysv/linux/mips/bits/sem.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/mips/bits/sem.h ++++ b/sysdeps/unix/sysv/linux/mips/bits/sem.h +@@ -66,6 +66,7 @@ struct semid_ds + /* ipcs ctl cmds */ + # define SEM_STAT 18 + # define SEM_INFO 19 ++# define SEM_STAT_ANY 20 + + struct seminfo + { +Index: b/sysdeps/unix/sysv/linux/powerpc/bits/sem.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/powerpc/bits/sem.h ++++ b/sysdeps/unix/sysv/linux/powerpc/bits/sem.h +@@ -73,6 +73,7 @@ struct semid_ds + /* ipcs ctl cmds */ + # define SEM_STAT 18 + # define SEM_INFO 19 ++# define SEM_STAT_ANY 20 + + struct seminfo + { +Index: b/sysdeps/unix/sysv/linux/s390/bits/sem.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/s390/bits/sem.h ++++ b/sysdeps/unix/sysv/linux/s390/bits/sem.h +@@ -73,6 +73,7 @@ struct semid_ds + /* ipcs ctl cmds */ + # define SEM_STAT 18 + # define SEM_INFO 19 ++# define SEM_STAT_ANY 20 + + struct seminfo + { +Index: b/sysdeps/unix/sysv/linux/sparc/bits/sem.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/sparc/bits/sem.h ++++ b/sysdeps/unix/sysv/linux/sparc/bits/sem.h +@@ -73,6 +73,7 @@ struct semid_ds + /* ipcs ctl cmds */ + # define SEM_STAT 18 + # define SEM_INFO 19 ++# define SEM_STAT_ANY 20 + + struct seminfo + { +Index: b/sysdeps/unix/sysv/linux/x86/bits/sem.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/x86/bits/sem.h ++++ b/sysdeps/unix/sysv/linux/x86/bits/sem.h +@@ -68,6 +68,7 @@ struct semid_ds + /* ipcs ctl cmds */ + # define SEM_STAT 18 + # define SEM_INFO 19 ++# define SEM_STAT_ANY 20 + + struct seminfo + { diff --git a/SOURCES/glibc-rh1592475-3.patch b/SOURCES/glibc-rh1592475-3.patch new file mode 100644 index 0000000..4a7fab5 --- /dev/null +++ b/SOURCES/glibc-rh1592475-3.patch @@ -0,0 +1,164 @@ +From 86bf0019ed9c0d1e19916448454c3f7df0479ac6 Mon Sep 17 00:00:00 2001 +From: Joseph Myers <joseph@codesourcery.com> +Date: Mon, 18 Jun 2018 13:34:52 +0000 +Subject: [PATCH] Add MSG_STAT_ANY from Linux 4.17 to bits/msq.h. + +Linux 4.17 adds a MSG_STAT_ANY constant (ipcs command). This patch +adds it to the relevant bits/msq.h headers. + +Tested for x86_64. + + * sysdeps/unix/sysv/linux/alpha/bits/msq.h [__USE_MISC] + (MSG_STAT_ANY): New macro. + * sysdeps/unix/sysv/linux/bits/msq.h [__USE_MISC] + (MSG_STAT_ANY): Likewise. + * sysdeps/unix/sysv/linux/generic/bits/msq.h [__USE_MISC] + (MSG_STAT_ANY): Likewise. + * sysdeps/unix/sysv/linux/hppa/bits/msq.h [__USE_MISC] + (MSG_STAT_ANY): Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/msq.h [__USE_MISC] + (MSG_STAT_ANY): Likewise. + * sysdeps/unix/sysv/linux/mips/bits/msq.h [__USE_MISC] + (MSG_STAT_ANY): Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/msq.h [__USE_MISC] + (MSG_STAT_ANY): Likewise. + * sysdeps/unix/sysv/linux/s390/bits/msq.h [__USE_MISC] + (MSG_STAT_ANY): Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/msq.h [__USE_MISC] + (MSG_STAT_ANY): Likewise. + * sysdeps/unix/sysv/linux/x86/bits/msq.h [__USE_MISC] + (MSG_STAT_ANY): Likewise. +--- + ChangeLog | 21 +++++++++++++++++++++ + sysdeps/unix/sysv/linux/alpha/bits/msq.h | 1 + + sysdeps/unix/sysv/linux/bits/msq.h | 1 + + sysdeps/unix/sysv/linux/generic/bits/msq.h | 1 + + sysdeps/unix/sysv/linux/hppa/bits/msq.h | 1 + + sysdeps/unix/sysv/linux/ia64/bits/msq.h | 1 + + sysdeps/unix/sysv/linux/mips/bits/msq.h | 1 + + sysdeps/unix/sysv/linux/powerpc/bits/msq.h | 1 + + sysdeps/unix/sysv/linux/s390/bits/msq.h | 1 + + sysdeps/unix/sysv/linux/sparc/bits/msq.h | 1 + + sysdeps/unix/sysv/linux/x86/bits/msq.h | 1 + + 11 files changed, 31 insertions(+) + +Index: b/sysdeps/unix/sysv/linux/alpha/bits/msq.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/alpha/bits/msq.h ++++ b/sysdeps/unix/sysv/linux/alpha/bits/msq.h +@@ -56,6 +56,7 @@ struct msqid_ds + /* ipcs ctl commands */ + # define MSG_STAT 11 + # define MSG_INFO 12 ++# define MSG_STAT_ANY 13 + + /* buffer for msgctl calls IPC_INFO, MSG_INFO */ + struct msginfo +Index: b/sysdeps/unix/sysv/linux/bits/msq.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/bits/msq.h ++++ b/sysdeps/unix/sysv/linux/bits/msq.h +@@ -59,6 +59,7 @@ struct msqid_ds + /* ipcs ctl commands */ + # define MSG_STAT 11 + # define MSG_INFO 12 ++# define MSG_STAT_ANY 13 + + /* buffer for msgctl calls IPC_INFO, MSG_INFO */ + struct msginfo +Index: b/sysdeps/unix/sysv/linux/generic/bits/msq.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/generic/bits/msq.h ++++ b/sysdeps/unix/sysv/linux/generic/bits/msq.h +@@ -66,6 +66,7 @@ struct msqid_ds + /* ipcs ctl commands */ + # define MSG_STAT 11 + # define MSG_INFO 12 ++# define MSG_STAT_ANY 13 + + /* buffer for msgctl calls IPC_INFO, MSG_INFO */ + struct msginfo +Index: b/sysdeps/unix/sysv/linux/hppa/bits/msq.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/hppa/bits/msq.h ++++ b/sysdeps/unix/sysv/linux/hppa/bits/msq.h +@@ -66,6 +66,7 @@ struct msqid_ds + /* ipcs ctl commands */ + # define MSG_STAT 11 + # define MSG_INFO 12 ++# define MSG_STAT_ANY 13 + + /* buffer for msgctl calls IPC_INFO, MSG_INFO */ + struct msginfo +Index: b/sysdeps/unix/sysv/linux/ia64/bits/msq.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/ia64/bits/msq.h ++++ b/sysdeps/unix/sysv/linux/ia64/bits/msq.h +@@ -51,6 +51,7 @@ struct msqid_ds + /* ipcs ctl commands */ + # define MSG_STAT 11 + # define MSG_INFO 12 ++# define MSG_STAT_ANY 13 + + /* buffer for msgctl calls IPC_INFO, MSG_INFO */ + struct msginfo +Index: b/sysdeps/unix/sysv/linux/mips/bits/msq.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/mips/bits/msq.h ++++ b/sysdeps/unix/sysv/linux/mips/bits/msq.h +@@ -74,6 +74,7 @@ struct msqid_ds + /* ipcs ctl commands */ + # define MSG_STAT 11 + # define MSG_INFO 12 ++# define MSG_STAT_ANY 13 + + /* buffer for msgctl calls IPC_INFO, MSG_INFO */ + struct msginfo +Index: b/sysdeps/unix/sysv/linux/powerpc/bits/msq.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/powerpc/bits/msq.h ++++ b/sysdeps/unix/sysv/linux/powerpc/bits/msq.h +@@ -65,6 +65,7 @@ struct msqid_ds + /* ipcs ctl commands */ + # define MSG_STAT 11 + # define MSG_INFO 12 ++# define MSG_STAT_ANY 13 + + /* buffer for msgctl calls IPC_INFO, MSG_INFO */ + struct msginfo +Index: b/sysdeps/unix/sysv/linux/s390/bits/msq.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/s390/bits/msq.h ++++ b/sysdeps/unix/sysv/linux/s390/bits/msq.h +@@ -66,6 +66,7 @@ struct msqid_ds + /* ipcs ctl commands */ + # define MSG_STAT 11 + # define MSG_INFO 12 ++# define MSG_STAT_ANY 13 + + /* buffer for msgctl calls IPC_INFO, MSG_INFO */ + struct msginfo +Index: b/sysdeps/unix/sysv/linux/sparc/bits/msq.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/sparc/bits/msq.h ++++ b/sysdeps/unix/sysv/linux/sparc/bits/msq.h +@@ -66,6 +66,7 @@ struct msqid_ds + /* ipcs ctl commands */ + # define MSG_STAT 11 + # define MSG_INFO 12 ++# define MSG_STAT_ANY 13 + + /* buffer for msgctl calls IPC_INFO, MSG_INFO */ + struct msginfo +Index: b/sysdeps/unix/sysv/linux/x86/bits/msq.h +=================================================================== +--- a/sysdeps/unix/sysv/linux/x86/bits/msq.h ++++ b/sysdeps/unix/sysv/linux/x86/bits/msq.h +@@ -64,6 +64,7 @@ struct msqid_ds + /* ipcs ctl commands */ + # define MSG_STAT 11 + # define MSG_INFO 12 ++# define MSG_STAT_ANY 13 + + /* buffer for msgctl calls IPC_INFO, MSG_INFO */ + struct msginfo diff --git a/SOURCES/glibc-rh1595191-1.patch b/SOURCES/glibc-rh1595191-1.patch new file mode 100644 index 0000000..62a85d7 --- /dev/null +++ b/SOURCES/glibc-rh1595191-1.patch @@ -0,0 +1,230 @@ +commit 0262507918cfad7223bf81b8f162b7adc7a2af01 +Author: Florian Weimer <fweimer@redhat.com> +Date: Fri Jun 1 10:43:06 2018 +0200 + + libio: Avoid _allocate_buffer, _free_buffer function pointers [BZ #23236] + + These unmangled function pointers reside on the heap and could + be targeted by exploit writers, effectively bypassing libio vtable + validation. Instead, we ignore these pointers and always call + malloc or free. + + In theory, this is a backwards-incompatible change, but using the + global heap instead of the user-supplied callback functions should + have little application impact. (The old libstdc++ implementation + exposed this functionality via a public, undocumented constructor + in its strstreambuf class.) + + (cherry picked from commit 4e8a6346cd3da2d88bbad745a1769260d36f2783) + +Backported from the upstream release/2.26/master branch. + +diff --git a/debug/vasprintf_chk.c b/debug/vasprintf_chk.c +index a8ca32bad57b4d13..113354749ccf8d9a 100644 +--- a/debug/vasprintf_chk.c ++++ b/debug/vasprintf_chk.c +@@ -55,8 +55,8 @@ __vasprintf_chk (char **result_ptr, int flags, const char *format, + _IO_JUMPS (&sf._sbf) = &_IO_str_jumps; + _IO_str_init_static_internal (&sf, string, init_string_size, string); + sf._sbf._f._flags &= ~_IO_USER_BUF; +- sf._s._allocate_buffer = (_IO_alloc_type) malloc; +- sf._s._free_buffer = (_IO_free_type) free; ++ sf._s._allocate_buffer_unused = (_IO_alloc_type) malloc; ++ sf._s._free_buffer_unused = (_IO_free_type) free; + + /* For flags > 0 (i.e. __USE_FORTIFY_LEVEL > 1) request that %n + can only come from read-only format strings. */ +diff --git a/libio/memstream.c b/libio/memstream.c +index e18a7756b297c9f4..9a51331e525c3468 100644 +--- a/libio/memstream.c ++++ b/libio/memstream.c +@@ -87,8 +87,8 @@ open_memstream (char **bufloc, _IO_size_t *sizeloc) + _IO_JUMPS ((struct _IO_FILE_plus *) &new_f->fp._sf._sbf) = &_IO_mem_jumps; + _IO_str_init_static_internal (&new_f->fp._sf, buf, _IO_BUFSIZ, buf); + new_f->fp._sf._sbf._f._flags &= ~_IO_USER_BUF; +- new_f->fp._sf._s._allocate_buffer = (_IO_alloc_type) malloc; +- new_f->fp._sf._s._free_buffer = (_IO_free_type) free; ++ new_f->fp._sf._s._allocate_buffer_unused = (_IO_alloc_type) malloc; ++ new_f->fp._sf._s._free_buffer_unused = (_IO_free_type) free; + + new_f->fp.bufloc = bufloc; + new_f->fp.sizeloc = sizeloc; +diff --git a/libio/strfile.h b/libio/strfile.h +index 4ea7548f9fa92638..9cd8e7c466616b52 100644 +--- a/libio/strfile.h ++++ b/libio/strfile.h +@@ -34,8 +34,11 @@ typedef void (*_IO_free_type) (void*); + + struct _IO_str_fields + { +- _IO_alloc_type _allocate_buffer; +- _IO_free_type _free_buffer; ++ /* These members are preserved for ABI compatibility. The glibc ++ implementation always calls malloc/free for user buffers if ++ _IO_USER_BUF or _IO_FLAGS2_USER_WBUF are not set. */ ++ _IO_alloc_type _allocate_buffer_unused; ++ _IO_free_type _free_buffer_unused; + }; + + /* This is needed for the Irix6 N32 ABI, which has a 64 bit off_t type, +@@ -55,10 +58,6 @@ typedef struct _IO_strfile_ + struct _IO_str_fields _s; + } _IO_strfile; + +-/* dynamic: set when the array object is allocated (or reallocated) as +- necessary to hold a character sequence that can change in length. */ +-#define _IO_STR_DYNAMIC(FP) ((FP)->_s._allocate_buffer != (_IO_alloc_type)0) +- + /* frozen: set when the program has requested that the array object not + be altered, reallocated, or freed. */ + #define _IO_STR_FROZEN(FP) ((FP)->_f._IO_file_flags & _IO_USER_BUF) +diff --git a/libio/strops.c b/libio/strops.c +index fdd113a60811e593..129a0f6aeca818fd 100644 +--- a/libio/strops.c ++++ b/libio/strops.c +@@ -61,7 +61,7 @@ _IO_str_init_static_internal (_IO_strfile *sf, char *ptr, _IO_size_t size, + fp->_IO_read_end = end; + } + /* A null _allocate_buffer function flags the strfile as being static. */ +- sf->_s._allocate_buffer = (_IO_alloc_type) 0; ++ sf->_s._allocate_buffer_unused = (_IO_alloc_type) 0; + } + + void +@@ -103,8 +103,7 @@ _IO_str_overflow (_IO_FILE *fp, int c) + _IO_size_t new_size = 2 * old_blen + 100; + if (new_size < old_blen) + return EOF; +- new_buf +- = (char *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size); ++ new_buf = malloc (new_size); + if (new_buf == NULL) + { + /* __ferror(fp) = 1; */ +@@ -113,7 +112,7 @@ _IO_str_overflow (_IO_FILE *fp, int c) + if (old_buf) + { + memcpy (new_buf, old_buf, old_blen); +- (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf); ++ free (old_buf); + /* Make sure _IO_setb won't try to delete _IO_buf_base. */ + fp->_IO_buf_base = NULL; + } +@@ -182,15 +181,14 @@ enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading) + + _IO_size_t newsize = offset + 100; + char *oldbuf = fp->_IO_buf_base; +- char *newbuf +- = (char *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (newsize); ++ char *newbuf = malloc (newsize); + if (newbuf == NULL) + return 1; + + if (oldbuf != NULL) + { + memcpy (newbuf, oldbuf, _IO_blen (fp)); +- (*((_IO_strfile *) fp)->_s._free_buffer) (oldbuf); ++ free (oldbuf); + /* Make sure _IO_setb won't try to delete + _IO_buf_base. */ + fp->_IO_buf_base = NULL; +@@ -317,7 +315,7 @@ void + _IO_str_finish (_IO_FILE *fp, int dummy) + { + if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF)) +- (((_IO_strfile *) fp)->_s._free_buffer) (fp->_IO_buf_base); ++ free (fp->_IO_buf_base); + fp->_IO_buf_base = NULL; + + _IO_default_finish (fp, 0); +diff --git a/libio/vasprintf.c b/libio/vasprintf.c +index 282c86fff0a7ae0e..867ef4fe4ca4ec56 100644 +--- a/libio/vasprintf.c ++++ b/libio/vasprintf.c +@@ -54,8 +54,8 @@ _IO_vasprintf (char **result_ptr, const char *format, _IO_va_list args) + _IO_JUMPS (&sf._sbf) = &_IO_str_jumps; + _IO_str_init_static_internal (&sf, string, init_string_size, string); + sf._sbf._f._flags &= ~_IO_USER_BUF; +- sf._s._allocate_buffer = (_IO_alloc_type) malloc; +- sf._s._free_buffer = (_IO_free_type) free; ++ sf._s._allocate_buffer_unused = (_IO_alloc_type) malloc; ++ sf._s._free_buffer_unused = (_IO_free_type) free; + ret = _IO_vfprintf (&sf._sbf._f, format, args); + if (ret < 0) + { +diff --git a/libio/wmemstream.c b/libio/wmemstream.c +index bd6d1798b1685fe9..3a9a681c80a321a7 100644 +--- a/libio/wmemstream.c ++++ b/libio/wmemstream.c +@@ -90,8 +90,8 @@ open_wmemstream (wchar_t **bufloc, _IO_size_t *sizeloc) + _IO_wstr_init_static (&new_f->fp._sf._sbf._f, buf, + _IO_BUFSIZ / sizeof (wchar_t), buf); + new_f->fp._sf._sbf._f._flags2 &= ~_IO_FLAGS2_USER_WBUF; +- new_f->fp._sf._s._allocate_buffer = (_IO_alloc_type) malloc; +- new_f->fp._sf._s._free_buffer = (_IO_free_type) free; ++ new_f->fp._sf._s._allocate_buffer_unused = (_IO_alloc_type) malloc; ++ new_f->fp._sf._s._free_buffer_unused = (_IO_free_type) free; + + new_f->fp.bufloc = bufloc; + new_f->fp.sizeloc = sizeloc; +diff --git a/libio/wstrops.c b/libio/wstrops.c +index 7a9a33ab8763b8ff..a31d0e23341b2aad 100644 +--- a/libio/wstrops.c ++++ b/libio/wstrops.c +@@ -63,7 +63,7 @@ _IO_wstr_init_static (_IO_FILE *fp, wchar_t *ptr, _IO_size_t size, + fp->_wide_data->_IO_read_end = end; + } + /* A null _allocate_buffer function flags the strfile as being static. */ +- (((_IO_strfile *) fp)->_s._allocate_buffer) = (_IO_alloc_type)0; ++ (((_IO_strfile *) fp)->_s._allocate_buffer_unused) = (_IO_alloc_type)0; + } + + _IO_wint_t +@@ -95,9 +95,7 @@ _IO_wstr_overflow (_IO_FILE *fp, _IO_wint_t c) + || __glibc_unlikely (new_size > SIZE_MAX / sizeof (wchar_t))) + return EOF; + +- new_buf +- = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size +- * sizeof (wchar_t)); ++ new_buf = malloc (new_size * sizeof (wchar_t)); + if (new_buf == NULL) + { + /* __ferror(fp) = 1; */ +@@ -106,7 +104,7 @@ _IO_wstr_overflow (_IO_FILE *fp, _IO_wint_t c) + if (old_buf) + { + __wmemcpy (new_buf, old_buf, old_wblen); +- (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf); ++ free (old_buf); + /* Make sure _IO_setb won't try to delete _IO_buf_base. */ + fp->_wide_data->_IO_buf_base = NULL; + } +@@ -186,16 +184,14 @@ enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading) + return 1; + + wchar_t *oldbuf = wd->_IO_buf_base; +- wchar_t *newbuf +- = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (newsize +- * sizeof (wchar_t)); ++ wchar_t *newbuf = malloc (newsize * sizeof (wchar_t)); + if (newbuf == NULL) + return 1; + + if (oldbuf != NULL) + { + __wmemcpy (newbuf, oldbuf, _IO_wblen (fp)); +- (*((_IO_strfile *) fp)->_s._free_buffer) (oldbuf); ++ free (oldbuf); + /* Make sure _IO_setb won't try to delete + _IO_buf_base. */ + wd->_IO_buf_base = NULL; +@@ -326,7 +322,7 @@ void + _IO_wstr_finish (_IO_FILE *fp, int dummy) + { + if (fp->_wide_data->_IO_buf_base && !(fp->_flags2 & _IO_FLAGS2_USER_WBUF)) +- (((_IO_strfile *) fp)->_s._free_buffer) (fp->_wide_data->_IO_buf_base); ++ free (fp->_wide_data->_IO_buf_base); + fp->_wide_data->_IO_buf_base = NULL; + + _IO_wdefault_finish (fp, 0); diff --git a/SOURCES/glibc-rh1595191-2.patch b/SOURCES/glibc-rh1595191-2.patch new file mode 100644 index 0000000..17b6030 --- /dev/null +++ b/SOURCES/glibc-rh1595191-2.patch @@ -0,0 +1,34 @@ +commit 3bb748257405e94e13de76573a4e9da1cfd961d0 +Author: Florian Weimer <fweimer@redhat.com> +Date: Tue Jul 3 15:54:49 2018 +0200 + + libio: Disable vtable validation in case of interposition [BZ #23313] + + (cherry picked from commit c402355dfa7807b8e0adb27c009135a7e2b9f1b0) + +Backported from the upstream release/2.26/master branch. + +diff --git a/libio/vtables.c b/libio/vtables.c +index e364ea03edbfa75b..d6478e4bab9050ce 100644 +--- a/libio/vtables.c ++++ b/libio/vtables.c +@@ -68,3 +68,19 @@ _IO_vtable_check (void) + + __libc_fatal ("Fatal error: glibc detected an invalid stdio handle\n"); + } ++ ++/* Some variants of libstdc++ interpose _IO_2_1_stdin_ etc. and ++ install their own vtables directly, without calling _IO_init or ++ other functions. Detect this by looking at the vtables values ++ during startup, and disable vtable validation in this case. */ ++#ifdef SHARED ++__attribute__ ((constructor)) ++static void ++check_stdfiles_vtables (void) ++{ ++ if (_IO_2_1_stdin_.vtable != &_IO_file_jumps ++ || _IO_2_1_stdout_.vtable != &_IO_file_jumps ++ || _IO_2_1_stderr_.vtable != &_IO_file_jumps) ++ IO_set_accept_foreign_vtables (&_IO_vtable_check); ++} ++#endif diff --git a/SOURCES/glibc-rh1595191-3.patch b/SOURCES/glibc-rh1595191-3.patch new file mode 100644 index 0000000..ab88533 --- /dev/null +++ b/SOURCES/glibc-rh1595191-3.patch @@ -0,0 +1,624 @@ +commit 44927211651adde42bbd431ef5ebe568186125e5 +Author: Florian Weimer <fweimer@redhat.com> +Date: Tue Jul 3 17:57:14 2018 +0200 + + libio: Add tst-vtables, tst-vtables-interposed + + (cherry picked from commit 29055464a03c72762969a2e8734d0d05d4d70e58) + + Some adjustments were needed for a tricky multi-inclusion issue related + to libioP.h. + +Backported from the upsteam release/2.26/master branch, adjusted for +lack of tests-internal support downstream. + +diff --git a/libio/Makefile b/libio/Makefile +index 0cef96141209fe99..1e923da42e45c492 100644 +--- a/libio/Makefile ++++ b/libio/Makefile +@@ -61,7 +61,9 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \ + bug-memstream1 bug-wmemstream1 \ + tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos tst-fseek \ + tst-fwrite-error tst-ftell-active-handler \ +- tst-ftell-append ++ tst-ftell-append \ ++ tst-vtables tst-vtables-interposed ++ + ifeq (yes,$(build-shared)) + # Add test-fopenloc only if shared library is enabled since it depends on + # shared localedata objects. +diff --git a/libio/tst-vtables-common.c b/libio/tst-vtables-common.c +new file mode 100644 +index 0000000000000000..dc8d89c195b95b8d +--- /dev/null ++++ b/libio/tst-vtables-common.c +@@ -0,0 +1,511 @@ ++/* Test for libio vtables and their validation. Common code. ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++/* This test provides some coverage for how various stdio functions ++ use the vtables in FILE * objects. The focus is mostly on which ++ functions call which methods, not so much on validating data ++ processing. An initial series of tests check that custom vtables ++ do not work without activation through _IO_init. ++ ++ Note: libio vtables are deprecated feature. Do not use this test ++ as a documentation source for writing custom vtables. See ++ fopencookie for a different way of creating custom stdio ++ streams. */ ++ ++#include <stdbool.h> ++#include <string.h> ++#include <support/capture_subprocess.h> ++#include <support/check.h> ++#include <support/namespace.h> ++#include <support/support.h> ++#include <support/test-driver.h> ++#include <support/xunistd.h> ++ ++/* Data shared between the test subprocess and the test driver in the ++ parent. Note that *shared is reset at the start of the check_call ++ function. */ ++struct shared ++{ ++ /* Expected file pointer for method calls. */ ++ FILE *fp; ++ ++ /* If true, assume that a call to _IO_init is needed to enable ++ custom vtables. */ ++ bool initially_disabled; ++ ++ /* Requested return value for the methods which have one. */ ++ int return_value; ++ ++ /* A value (usually a character) recorded by some of the methods ++ below. */ ++ int value; ++ ++ /* Likewise, for some data. */ ++ char buffer[16]; ++ size_t buffer_length; ++ ++ /* Total number of method calls. */ ++ unsigned int calls; ++ ++ /* Individual method call counts. */ ++ unsigned int calls_finish; ++ unsigned int calls_overflow; ++ unsigned int calls_underflow; ++ unsigned int calls_uflow; ++ unsigned int calls_pbackfail; ++ unsigned int calls_xsputn; ++ unsigned int calls_xsgetn; ++ unsigned int calls_seekoff; ++ unsigned int calls_seekpos; ++ unsigned int calls_setbuf; ++ unsigned int calls_sync; ++ unsigned int calls_doallocate; ++ unsigned int calls_read; ++ unsigned int calls_write; ++ unsigned int calls_seek; ++ unsigned int calls_close; ++ unsigned int calls_stat; ++ unsigned int calls_showmanyc; ++ unsigned int calls_imbue; ++} *shared; ++ ++/* Method implementations which increment the counters in *shared. */ ++ ++static void ++log_method (FILE *fp, const char *name) ++{ ++ if (test_verbose > 0) ++ printf ("info: %s (%p) called\n", name, fp); ++} ++ ++static void ++method_finish (FILE *fp, int dummy) ++{ ++ log_method (fp, __func__); ++ TEST_VERIFY (fp == shared->fp); ++ ++shared->calls; ++ ++shared->calls_finish; ++} ++ ++static int ++method_overflow (FILE *fp, int ch) ++{ ++ log_method (fp, __func__); ++ TEST_VERIFY (fp == shared->fp); ++ ++shared->calls; ++ ++shared->calls_overflow; ++ shared->value = ch; ++ return shared->return_value; ++} ++ ++static int ++method_underflow (FILE *fp) ++{ ++ log_method (fp, __func__); ++ TEST_VERIFY (fp == shared->fp); ++ ++shared->calls; ++ ++shared->calls_underflow; ++ return shared->return_value; ++} ++ ++static int ++method_uflow (FILE *fp) ++{ ++ log_method (fp, __func__); ++ TEST_VERIFY (fp == shared->fp); ++ ++shared->calls; ++ ++shared->calls_uflow; ++ return shared->return_value; ++} ++ ++static int ++method_pbackfail (FILE *fp, int ch) ++{ ++ log_method (fp, __func__); ++ TEST_VERIFY (fp == shared->fp); ++ ++shared->calls; ++ ++shared->calls_pbackfail; ++ shared->value = ch; ++ return shared->return_value; ++} ++ ++static size_t ++method_xsputn (FILE *fp, const void *data, size_t n) ++{ ++ log_method (fp, __func__); ++ TEST_VERIFY (fp == shared->fp); ++ ++shared->calls; ++ ++shared->calls_xsputn; ++ ++ size_t to_copy = n; ++ if (n > sizeof (shared->buffer)) ++ to_copy = sizeof (shared->buffer); ++ memcpy (shared->buffer, data, to_copy); ++ shared->buffer_length = to_copy; ++ return to_copy; ++} ++ ++static size_t ++method_xsgetn (FILE *fp, void *data, size_t n) ++{ ++ log_method (fp, __func__); ++ TEST_VERIFY (fp == shared->fp); ++ ++shared->calls; ++ ++shared->calls_xsgetn; ++ return 0; ++} ++ ++static off64_t ++method_seekoff (FILE *fp, off64_t offset, int dir, int mode) ++{ ++ log_method (fp, __func__); ++ TEST_VERIFY (fp == shared->fp); ++ ++shared->calls; ++ ++shared->calls_seekoff; ++ return shared->return_value; ++} ++ ++static off64_t ++method_seekpos (FILE *fp, off64_t offset, int mode) ++{ ++ log_method (fp, __func__); ++ TEST_VERIFY (fp == shared->fp); ++ ++shared->calls; ++ ++shared->calls_seekpos; ++ return shared->return_value; ++} ++ ++static FILE * ++method_setbuf (FILE *fp, char *buffer, ssize_t length) ++{ ++ log_method (fp, __func__); ++ TEST_VERIFY (fp == shared->fp); ++ ++shared->calls; ++ ++shared->calls_setbuf; ++ return fp; ++} ++ ++static int ++method_sync (FILE *fp) ++{ ++ log_method (fp, __func__); ++ TEST_VERIFY (fp == shared->fp); ++ ++shared->calls; ++ ++shared->calls_sync; ++ return shared->return_value; ++} ++ ++static int ++method_doallocate (FILE *fp) ++{ ++ log_method (fp, __func__); ++ TEST_VERIFY (fp == shared->fp); ++ ++shared->calls; ++ ++shared->calls_doallocate; ++ return shared->return_value; ++} ++ ++static ssize_t ++method_read (FILE *fp, void *data, ssize_t length) ++{ ++ log_method (fp, __func__); ++ TEST_VERIFY (fp == shared->fp); ++ ++shared->calls; ++ ++shared->calls_read; ++ return shared->return_value; ++} ++ ++static ssize_t ++method_write (FILE *fp, const void *data, ssize_t length) ++{ ++ log_method (fp, __func__); ++ TEST_VERIFY (fp == shared->fp); ++ ++shared->calls; ++ ++shared->calls_write; ++ return shared->return_value; ++} ++ ++static off64_t ++method_seek (FILE *fp, off64_t offset, int mode) ++{ ++ log_method (fp, __func__); ++ TEST_VERIFY (fp == shared->fp); ++ ++shared->calls; ++ ++shared->calls_seek; ++ return shared->return_value; ++} ++ ++static int ++method_close (FILE *fp) ++{ ++ log_method (fp, __func__); ++ TEST_VERIFY (fp == shared->fp); ++ ++shared->calls; ++ ++shared->calls_close; ++ return shared->return_value; ++} ++ ++static int ++method_stat (FILE *fp, void *buffer) ++{ ++ log_method (fp, __func__); ++ TEST_VERIFY (fp == shared->fp); ++ ++shared->calls; ++ ++shared->calls_stat; ++ return shared->return_value; ++} ++ ++static int ++method_showmanyc (FILE *fp) ++{ ++ log_method (fp, __func__); ++ TEST_VERIFY (fp == shared->fp); ++ ++shared->calls; ++ ++shared->calls_showmanyc; ++ return shared->return_value; ++} ++ ++static void ++method_imbue (FILE *fp, void *locale) ++{ ++ log_method (fp, __func__); ++ TEST_VERIFY (fp == shared->fp); ++ ++shared->calls; ++ ++shared->calls_imbue; ++} ++ ++/* Our custom vtable. */ ++ ++static const struct _IO_jump_t jumps = ++{ ++ JUMP_INIT_DUMMY, ++ JUMP_INIT (finish, method_finish), ++ JUMP_INIT (overflow, method_overflow), ++ JUMP_INIT (underflow, method_underflow), ++ JUMP_INIT (uflow, method_uflow), ++ JUMP_INIT (pbackfail, method_pbackfail), ++ JUMP_INIT (xsputn, method_xsputn), ++ JUMP_INIT (xsgetn, method_xsgetn), ++ JUMP_INIT (seekoff, method_seekoff), ++ JUMP_INIT (seekpos, method_seekpos), ++ JUMP_INIT (setbuf, method_setbuf), ++ JUMP_INIT (sync, method_sync), ++ JUMP_INIT (doallocate, method_doallocate), ++ JUMP_INIT (read, method_read), ++ JUMP_INIT (write, method_write), ++ JUMP_INIT (seek, method_seek), ++ JUMP_INIT (close, method_close), ++ JUMP_INIT (stat, method_stat), ++ JUMP_INIT (showmanyc, method_showmanyc), ++ JUMP_INIT (imbue, method_imbue) ++}; ++ ++/* Our file implementation. */ ++ ++struct my_file ++{ ++ FILE f; ++ const struct _IO_jump_t *vtable; ++}; ++ ++struct my_file ++my_file_create (void) ++{ ++ return (struct my_file) ++ { ++ /* Disable locking, so that we do not have to set up a lock ++ pointer. */ ++ .f._flags = _IO_USER_LOCK, ++ ++ /* Copy the offset from the an initialized handle, instead of ++ figuring it out from scratch. */ ++ .f._vtable_offset = stdin->_vtable_offset, ++ ++ .vtable = &jumps, ++ }; ++} ++ ++/* Initial tests which do not enable vtable compatibility. */ ++ ++/* Inhibit GCC optimization of fprintf. */ ++typedef int (*fprintf_type) (FILE *, const char *, ...); ++static const volatile fprintf_type fprintf_ptr = &fprintf; ++ ++static void ++without_compatibility_fprintf (void *closure) ++{ ++ /* This call should abort. */ ++ fprintf_ptr (shared->fp, " "); ++ _exit (1); ++} ++ ++static void ++without_compatibility_fputc (void *closure) ++{ ++ /* This call should abort. */ ++ fputc (' ', shared->fp); ++ _exit (1); ++} ++ ++static void ++without_compatibility_fgetc (void *closure) ++{ ++ /* This call should abort. */ ++ fgetc (shared->fp); ++ _exit (1); ++} ++ ++static void ++without_compatibility_fflush (void *closure) ++{ ++ /* This call should abort. */ ++ fflush (shared->fp); ++ _exit (1); ++} ++ ++/* Exit status after abnormal termination. */ ++static int termination_status; ++ ++static void ++init_termination_status (void) ++{ ++ pid_t pid = xfork (); ++ if (pid == 0) ++ abort (); ++ xwaitpid (pid, &termination_status, 0); ++ ++ TEST_VERIFY (WIFSIGNALED (termination_status)); ++ TEST_COMPARE (WTERMSIG (termination_status), SIGABRT); ++} ++ ++static void ++check_for_termination (const char *name, void (*callback) (void *)) ++{ ++ struct my_file file = my_file_create (); ++ shared->fp = &file.f; ++ shared->return_value = -1; ++ shared->calls = 0; ++ struct support_capture_subprocess proc ++ = support_capture_subprocess (callback, NULL); ++ support_capture_subprocess_check (&proc, name, termination_status, ++ sc_allow_stderr); ++ const char *message ++ = "Fatal error: glibc detected an invalid stdio handle\n"; ++ TEST_COMPARE_BLOB (proc.err.buffer, proc.err.length, ++ message, strlen (message)); ++ TEST_COMPARE (shared->calls, 0); ++ support_capture_subprocess_free (&proc); ++} ++ ++/* The test with vtable validation disabled. */ ++ ++/* This function does not have a prototype in libioP.h to prevent ++ accidental use from within the library (which would disable vtable ++ verification). */ ++void _IO_init (FILE *fp, int flags); ++ ++static void ++with_compatibility_fprintf (void *closure) ++{ ++ TEST_COMPARE (fprintf_ptr (shared->fp, "A%sCD", "B"), 4); ++ TEST_COMPARE (shared->calls, 3); ++ TEST_COMPARE (shared->calls_xsputn, 3); ++ TEST_COMPARE_BLOB (shared->buffer, shared->buffer_length, ++ "CD", 2); ++} ++ ++static void ++with_compatibility_fputc (void *closure) ++{ ++ shared->return_value = '@'; ++ TEST_COMPARE (fputc ('@', shared->fp), '@'); ++ TEST_COMPARE (shared->calls, 1); ++ TEST_COMPARE (shared->calls_overflow, 1); ++ TEST_COMPARE (shared->value, '@'); ++} ++ ++static void ++with_compatibility_fgetc (void *closure) ++{ ++ shared->return_value = 'X'; ++ TEST_COMPARE (fgetc (shared->fp), 'X'); ++ TEST_COMPARE (shared->calls, 1); ++ TEST_COMPARE (shared->calls_uflow, 1); ++} ++ ++static void ++with_compatibility_fflush (void *closure) ++{ ++ TEST_COMPARE (fflush (shared->fp), 0); ++ TEST_COMPARE (shared->calls, 1); ++ TEST_COMPARE (shared->calls_sync, 1); ++} ++ ++/* Call CALLBACK in a subprocess, after setting up a custom file ++ object and updating shared->fp. */ ++static void ++check_call (const char *name, void (*callback) (void *), ++ bool initially_disabled) ++{ ++ *shared = (struct shared) ++ { ++ .initially_disabled = initially_disabled, ++ }; ++ ++ /* Set up a custom file object. */ ++ struct my_file file = my_file_create (); ++ shared->fp = &file.f; ++ if (shared->initially_disabled) ++ _IO_init (shared->fp, file.f._flags); ++ ++ if (test_verbose > 0) ++ printf ("info: calling test %s\n", name); ++ support_isolate_in_subprocess (callback, NULL); ++} ++ ++/* Run the tests. INITIALLY_DISABLED indicates whether custom vtables ++ are disabled when the test starts. */ ++static int ++run_tests (bool initially_disabled) ++{ ++ /* The test relies on fatal error messages being printed to standard ++ error. */ ++ setenv ("LIBC_FATAL_STDERR_", "1", 1); ++ ++ shared = support_shared_allocate (sizeof (*shared)); ++ shared->initially_disabled = initially_disabled; ++ init_termination_status (); ++ ++ if (initially_disabled) ++ { ++ check_for_termination ("fprintf", without_compatibility_fprintf); ++ check_for_termination ("fputc", without_compatibility_fputc); ++ check_for_termination ("fgetc", without_compatibility_fgetc); ++ check_for_termination ("fflush", without_compatibility_fflush); ++ } ++ ++ check_call ("fprintf", with_compatibility_fprintf, initially_disabled); ++ check_call ("fputc", with_compatibility_fputc, initially_disabled); ++ check_call ("fgetc", with_compatibility_fgetc, initially_disabled); ++ check_call ("fflush", with_compatibility_fflush, initially_disabled); ++ ++ support_shared_free (shared); ++ shared = NULL; ++ ++ return 0; ++} +diff --git a/libio/tst-vtables-interposed.c b/libio/tst-vtables-interposed.c +new file mode 100644 +index 0000000000000000..c8f4e8c7c386af39 +--- /dev/null ++++ b/libio/tst-vtables-interposed.c +@@ -0,0 +1,37 @@ ++/* Test for libio vtables and their validation. Enabled through interposition. ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++/* Provide an interposed definition of the standard file handles with ++ our own vtable. stdout/stdin/stderr will not work as a result, but ++ a succesful test does not print anything, so this is fine. */ ++static const struct _IO_jump_t jumps; ++#define _IO_file_jumps jumps ++#include "stdfiles.c" ++ ++#include "tst-vtables-common.c" ++ ++static int ++do_test (void) ++{ ++ return run_tests (false); ++} ++ ++/* Calling setvbuf in the test driver is not supported with our ++ interposed file handles. */ ++#define TEST_NO_SETVBUF ++#include <support/test-driver.c> +diff --git a/libio/tst-vtables.c b/libio/tst-vtables.c +new file mode 100644 +index 0000000000000000..f16acf5d23b0fff6 +--- /dev/null ++++ b/libio/tst-vtables.c +@@ -0,0 +1,29 @@ ++/* Test for libio vtables and their validation. Initially disabled case. ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include "libioP.h" ++ ++#include "tst-vtables-common.c" ++ ++static int ++do_test (void) ++{ ++ return run_tests (true); ++} ++ ++#include <support/test-driver.c> diff --git a/SOURCES/glibc-rh1595191-4.patch b/SOURCES/glibc-rh1595191-4.patch new file mode 100644 index 0000000..9e9d95b --- /dev/null +++ b/SOURCES/glibc-rh1595191-4.patch @@ -0,0 +1,24 @@ +commit 2d1c89a5d7c872a1109768f50e2508cf9a4b0348 +Author: Florian Weimer <fweimer@redhat.com> +Date: Wed Jun 20 09:45:19 2018 +0200 + + libio: Avoid ptrdiff_t overflow in IO_validate_vtable + + If the candidate pointer is sufficiently far away from + __start___libc_IO_vtables, the result might not fit into ptrdiff_t. + +diff --git a/libio/libioP.h b/libio/libioP.h +index b60244ac5fc3d908..f1576381500ffc85 100644 +--- a/libio/libioP.h ++++ b/libio/libioP.h +@@ -957,8 +957,8 @@ IO_validate_vtable (const struct _IO_jump_t *vtable) + /* Fast path: The vtable pointer is within the __libc_IO_vtables + section. */ + uintptr_t section_length = __stop___libc_IO_vtables - __start___libc_IO_vtables; +- const char *ptr = (const char *) vtable; +- uintptr_t offset = ptr - __start___libc_IO_vtables; ++ uintptr_t ptr = (uintptr_t) vtable; ++ uintptr_t offset = ptr - (uintptr_t) __start___libc_IO_vtables; + if (__glibc_unlikely (offset >= section_length)) + /* The vtable pointer is not in the expected section. Use the + slow path, which will terminate the process if necessary. */ diff --git a/SOURCES/glibc-rh1609067.patch b/SOURCES/glibc-rh1609067.patch new file mode 100644 index 0000000..e10b503 --- /dev/null +++ b/SOURCES/glibc-rh1609067.patch @@ -0,0 +1,65 @@ +commit b04acb2651e0aaf615de50e9138cddfd5c24021f +Author: Andreas Schwab <schwab@suse.de> +Date: Tue Jul 30 11:58:45 2013 +0200 + + Fix race conditions in pldd that may leave the process stopped after detaching + + Fixes bug 15804 + +diff --git a/elf/pldd.c b/elf/pldd.c +index 684aff4..75f7812 100644 +--- a/elf/pldd.c ++++ b/elf/pldd.c +@@ -34,6 +34,7 @@ + #include <unistd.h> + #include <sys/ptrace.h> + #include <sys/stat.h> ++#include <sys/wait.h> + + #include <ldsodefs.h> + #include <version.h> +@@ -82,6 +83,7 @@ static char *exe; + + /* Local functions. */ + static int get_process_info (int dfd, long int pid); ++static void wait_for_ptrace_stop (long int pid); + + + int +@@ -170,6 +172,8 @@ main (int argc, char *argv[]) + tid); + } + ++ wait_for_ptrace_stop (tid); ++ + struct thread_list *newp = alloca (sizeof (*newp)); + newp->tid = tid; + newp->next = thread_list; +@@ -194,6 +198,27 @@ main (int argc, char *argv[]) + } + + ++/* Wait for PID to enter ptrace-stop state after being attached. */ ++static void ++wait_for_ptrace_stop (long int pid) ++{ ++ int status; ++ ++ /* While waiting for SIGSTOP being delivered to the tracee we have to ++ reinject any other pending signal. Ignore all other errors. */ ++ while (waitpid (pid, &status, __WALL) == pid && WIFSTOPPED (status)) ++ { ++ /* The STOP signal should not be delivered to the tracee. */ ++ if (WSTOPSIG (status) == SIGSTOP) ++ return; ++ if (ptrace (PTRACE_CONT, pid, NULL, ++ (void *) (uintptr_t) WSTOPSIG (status))) ++ /* The only possible error is that the process died. */ ++ return; ++ } ++} ++ ++ + /* Handle program arguments. */ + static error_t + parse_opt (int key, char *arg, struct argp_state *state) diff --git a/SOURCES/glibc-rh1630440-1.patch b/SOURCES/glibc-rh1630440-1.patch new file mode 100644 index 0000000..971c251 --- /dev/null +++ b/SOURCES/glibc-rh1630440-1.patch @@ -0,0 +1,486 @@ +commit e5d262effe3a87164308a3f37e61b32d0348692a +Author: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> +Date: Fri Nov 30 18:05:32 2018 -0200 + + Fix _dl_profile_fixup data-dependency issue (Bug 23690) + + There is a data-dependency between the fields of struct l_reloc_result + and the field used as the initialization guard. Users of the guard + expect writes to the structure to be observable when they also observe + the guard initialized. The solution for this problem is to use an acquire + and release load and store to ensure previous writes to the structure are + observable if the guard is initialized. + + The previous implementation used DL_FIXUP_VALUE_ADDR (l_reloc_result->addr) + as the initialization guard, making it impossible for some architectures + to load and store it atomically, i.e. hppa and ia64, due to its larger size. + + This commit adds an unsigned int to l_reloc_result to be used as the new + initialization guard of the struct, making it possible to load and store + it atomically in all architectures. The fix ensures that the values + observed in l_reloc_result are consistent and do not lead to crashes. + The algorithm is documented in the code in elf/dl-runtime.c + (_dl_profile_fixup). Not all data races have been eliminated. + + Tested with build-many-glibcs and on powerpc, powerpc64, and powerpc64le. + + [BZ #23690] + * elf/dl-runtime.c (_dl_profile_fixup): Guarantee memory + modification order when accessing reloc_result->addr. + * include/link.h (reloc_result): Add field init. + * nptl/Makefile (tests): Add tst-audit-threads. + (modules-names): Add tst-audit-threads-mod1 and + tst-audit-threads-mod2. + Add rules to build tst-audit-threads. + * nptl/tst-audit-threads-mod1.c: New file. + * nptl/tst-audit-threads-mod2.c: Likewise. + * nptl/tst-audit-threads.c: Likewise. + * nptl/tst-audit-threads.h: Likewise. + + Signed-off-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> + Reviewed-by: Carlos O'Donell <carlos@redhat.com> + +(elf/dl-runtime.c adjusted here for lack of __builtin_expect cleanup, +nptl/Makefile for the usual test-related conflicts.) + +diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c +index a42e3c4924e067ba..3678a98c98d726f3 100644 +--- a/elf/dl-runtime.c ++++ b/elf/dl-runtime.c +@@ -183,10 +183,36 @@ _dl_profile_fixup ( + /* This is the address in the array where we store the result of previous + relocations. */ + struct reloc_result *reloc_result = &l->l_reloc_result[reloc_index]; +- DL_FIXUP_VALUE_TYPE *resultp = &reloc_result->addr; + +- DL_FIXUP_VALUE_TYPE value = *resultp; +- if (DL_FIXUP_VALUE_CODE_ADDR (value) == 0) ++ /* CONCURRENCY NOTES: ++ ++ Multiple threads may be calling the same PLT sequence and with ++ LD_AUDIT enabled they will be calling into _dl_profile_fixup to ++ update the reloc_result with the result of the lazy resolution. ++ The reloc_result guard variable is reloc_init, and we use ++ acquire/release loads and store to it to ensure that the results of ++ the structure are consistent with the loaded value of the guard. ++ This does not fix all of the data races that occur when two or more ++ threads read reloc_result->reloc_init with a value of zero and read ++ and write to that reloc_result concurrently. The expectation is ++ generally that while this is a data race it works because the ++ threads write the same values. Until the data races are fixed ++ there is a potential for problems to arise from these data races. ++ The reloc result updates should happen in parallel but there should ++ be an atomic RMW which does the final update to the real result ++ entry (see bug 23790). ++ ++ The following code uses reloc_result->init set to 0 to indicate if it is ++ the first time this object is being relocated, otherwise 1 which ++ indicates the object has already been relocated. ++ ++ Reading/Writing from/to reloc_result->reloc_init must not happen ++ before previous writes to reloc_result complete as they could ++ end-up with an incomplete struct. */ ++ DL_FIXUP_VALUE_TYPE value; ++ unsigned int init = atomic_load_acquire (&reloc_result->init); ++ ++ if (init == 0) + { + /* This is the first time we have to relocate this object. */ + const ElfW(Sym) *const symtab +@@ -347,20 +373,32 @@ _dl_profile_fixup ( + #endif + + /* Store the result for later runs. */ +- if (__builtin_expect (! GLRO(dl_bind_not), 1)) +- *resultp = value; ++ if (__glibc_likely (! GLRO(dl_bind_not))) ++ { ++ reloc_result->addr = value; ++ /* Guarantee all previous writes complete before ++ init is updated. See CONCURRENCY NOTES earlier */ ++ atomic_store_release (&reloc_result->init, 1); ++ } ++ init = 1; + } ++ else ++ value = reloc_result->addr; + + /* By default we do not call the pltexit function. */ + long int framesize = -1; + ++ + #ifdef SHARED + /* Auditing checkpoint: report the PLT entering and allow the + auditors to change the value. */ +- if (DL_FIXUP_VALUE_CODE_ADDR (value) != 0 && GLRO(dl_naudit) > 0 ++ if (GLRO(dl_naudit) > 0 + /* Don't do anything if no auditor wants to intercept this call. */ + && (reloc_result->enterexit & LA_SYMB_NOPLTENTER) == 0) + { ++ /* Sanity check: DL_FIXUP_VALUE_CODE_ADDR (value) should have been ++ initialized earlier in this function or in another thread. */ ++ assert (DL_FIXUP_VALUE_CODE_ADDR (value) != 0); + ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound, + l_info[DT_SYMTAB]) + + reloc_result->boundndx); +diff --git a/include/link.h b/include/link.h +index d7590640aa9285e5..22d020d833ae3a7c 100644 +--- a/include/link.h ++++ b/include/link.h +@@ -206,6 +206,10 @@ struct link_map + unsigned int boundndx; + uint32_t enterexit; + unsigned int flags; ++ /* CONCURRENCY NOTE: This is used to guard the concurrent initialization ++ of the relocation result across multiple threads. See the more ++ detailed notes in elf/dl-runtime.c. */ ++ unsigned int init; + } *l_reloc_result; + + /* Pointer to the version information if available. */ +diff --git a/nptl/Makefile b/nptl/Makefile +index cf47a6f097916766..1b9639f3566a63fd 100644 +--- a/nptl/Makefile ++++ b/nptl/Makefile +@@ -298,7 +298,7 @@ tests += tst-cancelx2 tst-cancelx3 tst-cancelx4 tst-cancelx5 \ + endif + ifeq ($(build-shared),yes) + tests += tst-atfork2 tst-tls3 tst-tls4 tst-tls5 tst-_res1 tst-fini1 \ +- tst-stackguard1 ++ tst-stackguard1 tst-audit-threads + tests-nolibpthread += tst-fini1 + ifeq ($(have-z-execstack),yes) + tests += tst-execstack +@@ -309,7 +309,7 @@ modules-names = tst-atfork2mod tst-tls3mod tst-tls4moda tst-tls4modb \ + tst-tls5mod tst-tls5moda tst-tls5modb tst-tls5modc \ + tst-tls5modd tst-tls5mode tst-tls5modf tst-stack4mod \ + tst-_res1mod1 tst-_res1mod2 tst-execstack-mod tst-fini1mod \ +- tst-join7mod ++ tst-join7mod tst-audit-threads-mod1 tst-audit-threads-mod2 + extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) tst-cleanup4aux.o + test-extras += $(modules-names) tst-cleanup4aux + test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names))) +@@ -627,6 +627,14 @@ $(objpfx)tst-oddstacklimit.out: $(objpfx)tst-oddstacklimit $(objpfx)tst-basic1 + $(run-program-prefix) $< --command '$(host-built-program-cmd)' > $@ + endif + ++# Protect against a build using -Wl,-z,now. ++LDFLAGS-tst-audit-threads-mod1.so = -Wl,-z,lazy ++LDFLAGS-tst-audit-threads-mod2.so = -Wl,-z,lazy ++LDFLAGS-tst-audit-threads = -Wl,-z,lazy ++$(objpfx)tst-audit-threads: $(objpfx)tst-audit-threads-mod2.so ++$(objpfx)tst-audit-threads.out: $(objpfx)tst-audit-threads-mod1.so ++tst-audit-threads-ENV = LD_AUDIT=$(objpfx)tst-audit-threads-mod1.so ++ + # The tests here better do not run in parallel + ifneq ($(filter %tests,$(MAKECMDGOALS)),) + .NOTPARALLEL: +diff --git a/nptl/tst-audit-threads-mod1.c b/nptl/tst-audit-threads-mod1.c +new file mode 100644 +index 0000000000000000..615d5ee5121962df +--- /dev/null ++++ b/nptl/tst-audit-threads-mod1.c +@@ -0,0 +1,74 @@ ++/* Dummy audit library for test-audit-threads. ++ ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <elf.h> ++#include <link.h> ++#include <stdio.h> ++#include <assert.h> ++#include <string.h> ++ ++/* We must use a dummy LD_AUDIT module to force the dynamic loader to ++ *not* update the real PLT, and instead use a cached value for the ++ lazy resolution result. It is the update of that cached value that ++ we are testing for correctness by doing this. */ ++ ++/* Library to be audited. */ ++#define LIB "tst-audit-threads-mod2.so" ++/* CALLNUM is the number of retNum functions. */ ++#define CALLNUM 7999 ++ ++#define CONCATX(a, b) __CONCAT (a, b) ++ ++static int previous = 0; ++ ++unsigned int ++la_version (unsigned int ver) ++{ ++ return 1; ++} ++ ++unsigned int ++la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie) ++{ ++ return LA_FLG_BINDTO | LA_FLG_BINDFROM; ++} ++ ++uintptr_t ++CONCATX(la_symbind, __ELF_NATIVE_CLASS) (ElfW(Sym) *sym, ++ unsigned int ndx, ++ uintptr_t *refcook, ++ uintptr_t *defcook, ++ unsigned int *flags, ++ const char *symname) ++{ ++ const char * retnum = "retNum"; ++ char * num = strstr (symname, retnum); ++ int n; ++ /* Validate if the symbols are getting called in the correct order. ++ This code is here to verify binutils does not optimize out the PLT ++ entries that require the symbol binding. */ ++ if (num != NULL) ++ { ++ n = atoi (num); ++ assert (n >= previous); ++ assert (n <= CALLNUM); ++ previous = n; ++ } ++ return sym->st_value; ++} +diff --git a/nptl/tst-audit-threads-mod2.c b/nptl/tst-audit-threads-mod2.c +new file mode 100644 +index 0000000000000000..f9817dd3dc7f4910 +--- /dev/null ++++ b/nptl/tst-audit-threads-mod2.c +@@ -0,0 +1,22 @@ ++/* Shared object with a huge number of functions for test-audit-threads. ++ ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++/* Define all the retNumN functions in a library. */ ++#define definenum ++#include "tst-audit-threads.h" +diff --git a/nptl/tst-audit-threads.c b/nptl/tst-audit-threads.c +new file mode 100644 +index 0000000000000000..e4bf433bd85f3715 +--- /dev/null ++++ b/nptl/tst-audit-threads.c +@@ -0,0 +1,97 @@ ++/* Test multi-threading using LD_AUDIT. ++ ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++/* This test uses a dummy LD_AUDIT library (test-audit-threads-mod1) and a ++ library with a huge number of functions in order to validate lazy symbol ++ binding with an audit library. We use one thread per CPU to test that ++ concurrent lazy resolution does not have any defects which would cause ++ the process to fail. We use an LD_AUDIT library to force the testing of ++ the relocation resolution caching code in the dynamic loader i.e. ++ _dl_runtime_profile and _dl_profile_fixup. */ ++ ++#include <support/xthread.h> ++#include <strings.h> ++#include <stdlib.h> ++#include <sys/sysinfo.h> ++ ++static int do_test (void); ++ ++/* This test usually takes less than 3s to run. However, there are cases that ++ take up to 30s. */ ++#define TIMEOUT 60 ++#define TEST_FUNCTION do_test () ++#include "../test-skeleton.c" ++ ++/* Declare the functions we are going to call. */ ++#define externnum ++#include "tst-audit-threads.h" ++#undef externnum ++ ++int num_threads; ++pthread_barrier_t barrier; ++ ++void ++sync_all (int num) ++{ ++ pthread_barrier_wait (&barrier); ++} ++ ++void ++call_all_ret_nums (void) ++{ ++ /* Call each function one at a time from all threads. */ ++#define callnum ++#include "tst-audit-threads.h" ++#undef callnum ++} ++ ++void * ++thread_main (void *unused) ++{ ++ call_all_ret_nums (); ++ return NULL; ++} ++ ++#define STR2(X) #X ++#define STR(X) STR2(X) ++ ++static int ++do_test (void) ++{ ++ int i; ++ pthread_t *threads; ++ ++ num_threads = get_nprocs (); ++ if (num_threads <= 1) ++ num_threads = 2; ++ ++ /* Used to synchronize all the threads after calling each retNumN. */ ++ xpthread_barrier_init (&barrier, NULL, num_threads); ++ ++ threads = (pthread_t *) xcalloc (num_threads, sizeof(pthread_t)); ++ for (i = 0; i < num_threads; i++) ++ threads[i] = xpthread_create(NULL, thread_main, NULL); ++ ++ for (i = 0; i < num_threads; i++) ++ xpthread_join(threads[i]); ++ ++ free (threads); ++ ++ return 0; ++} +diff --git a/nptl/tst-audit-threads.h b/nptl/tst-audit-threads.h +new file mode 100644 +index 0000000000000000..1c9ecc08dfcd3e65 +--- /dev/null ++++ b/nptl/tst-audit-threads.h +@@ -0,0 +1,92 @@ ++/* Helper header for test-audit-threads. ++ ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++/* We use this helper to create a large number of functions, all of ++ which will be resolved lazily and thus have their PLT updated. ++ This is done to provide enough functions that we can statistically ++ observe a thread vs. PLT resolution failure if one exists. */ ++ ++#define CONCAT(a, b) a ## b ++#define NUM(x, y) CONCAT (x, y) ++ ++#define FUNC10(x) \ ++ FUNC (NUM (x, 0)); \ ++ FUNC (NUM (x, 1)); \ ++ FUNC (NUM (x, 2)); \ ++ FUNC (NUM (x, 3)); \ ++ FUNC (NUM (x, 4)); \ ++ FUNC (NUM (x, 5)); \ ++ FUNC (NUM (x, 6)); \ ++ FUNC (NUM (x, 7)); \ ++ FUNC (NUM (x, 8)); \ ++ FUNC (NUM (x, 9)) ++ ++#define FUNC100(x) \ ++ FUNC10 (NUM (x, 0)); \ ++ FUNC10 (NUM (x, 1)); \ ++ FUNC10 (NUM (x, 2)); \ ++ FUNC10 (NUM (x, 3)); \ ++ FUNC10 (NUM (x, 4)); \ ++ FUNC10 (NUM (x, 5)); \ ++ FUNC10 (NUM (x, 6)); \ ++ FUNC10 (NUM (x, 7)); \ ++ FUNC10 (NUM (x, 8)); \ ++ FUNC10 (NUM (x, 9)) ++ ++#define FUNC1000(x) \ ++ FUNC100 (NUM (x, 0)); \ ++ FUNC100 (NUM (x, 1)); \ ++ FUNC100 (NUM (x, 2)); \ ++ FUNC100 (NUM (x, 3)); \ ++ FUNC100 (NUM (x, 4)); \ ++ FUNC100 (NUM (x, 5)); \ ++ FUNC100 (NUM (x, 6)); \ ++ FUNC100 (NUM (x, 7)); \ ++ FUNC100 (NUM (x, 8)); \ ++ FUNC100 (NUM (x, 9)) ++ ++#define FUNC7000() \ ++ FUNC1000 (1); \ ++ FUNC1000 (2); \ ++ FUNC1000 (3); \ ++ FUNC1000 (4); \ ++ FUNC1000 (5); \ ++ FUNC1000 (6); \ ++ FUNC1000 (7); ++ ++#ifdef FUNC ++# undef FUNC ++#endif ++ ++#ifdef externnum ++# define FUNC(x) extern int CONCAT (retNum, x) (void) ++#endif ++ ++#ifdef definenum ++# define FUNC(x) int CONCAT (retNum, x) (void) { return x; } ++#endif ++ ++#ifdef callnum ++# define FUNC(x) CONCAT (retNum, x) (); sync_all (x) ++#endif ++ ++/* A value of 7000 functions is chosen as an arbitrarily large ++ number of functions that will allow us enough attempts to ++ verify lazy resolution operation. */ ++FUNC7000 (); diff --git a/SOURCES/glibc-rh1630440-2.patch b/SOURCES/glibc-rh1630440-2.patch new file mode 100644 index 0000000..e2bf37b --- /dev/null +++ b/SOURCES/glibc-rh1630440-2.patch @@ -0,0 +1,48 @@ +nptl/tst-audit-threads: Switch to <support/test-driver.c> + +The downstream version of test-skeleton.c does not include +<support/support.h> for backwards compatibility reasons, leading to a +compilation failure: + +tst-audit-threads.c: In function 'do_test': +tst-audit-threads.c:87:3: error: implicit declaration of function 'xcalloc' [-Werror=implicit-function-declaration] + threads = (pthread_t *) xcalloc (num_threads, sizeof(pthread_t)); + ^ +tst-audit-threads.c:87:13: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] + threads = (pthread_t *) xcalloc (num_threads, sizeof(pthread_t)); + ^ + +diff --git a/nptl/tst-audit-threads.c b/nptl/tst-audit-threads.c +index e4bf433bd85f3715..42742d51e4bc06a3 100644 +--- a/nptl/tst-audit-threads.c ++++ b/nptl/tst-audit-threads.c +@@ -25,19 +25,12 @@ + the relocation resolution caching code in the dynamic loader i.e. + _dl_runtime_profile and _dl_profile_fixup. */ + ++#include <support/support.h> + #include <support/xthread.h> + #include <strings.h> + #include <stdlib.h> + #include <sys/sysinfo.h> + +-static int do_test (void); +- +-/* This test usually takes less than 3s to run. However, there are cases that +- take up to 30s. */ +-#define TIMEOUT 60 +-#define TEST_FUNCTION do_test () +-#include "../test-skeleton.c" +- + /* Declare the functions we are going to call. */ + #define externnum + #include "tst-audit-threads.h" +@@ -95,3 +88,8 @@ do_test (void) + + return 0; + } ++ ++/* This test usually takes less than 3s to run. However, there are cases that ++ take up to 30s. */ ++#define TIMEOUT 60 ++#include <support/test-driver.c> diff --git a/SOURCES/glibc-rh1639524.patch b/SOURCES/glibc-rh1639524.patch new file mode 100644 index 0000000..9302219 --- /dev/null +++ b/SOURCES/glibc-rh1639524.patch @@ -0,0 +1,74 @@ +Note: the context of this patch differs from upstream slightly, +to accomodate the lack of ILP32 in RHEL. + +commit b7cf203b5c17dd6d9878537d41e0c7cc3d270a67 +Author: Szabolcs Nagy <szabolcs.nagy@arm.com> +Date: Wed Sep 27 16:55:14 2017 +0100 + + aarch64: Disable lazy symbol binding of TLSDESC + + Always do TLS descriptor initialization at load time during relocation + processing to avoid barriers at every TLS access. In non-dlopened shared + libraries the overhead of tls access vs static global access is > 3x + bigger when lazy initialization is used (_dl_tlsdesc_return_lazy) + compared to bind-now (_dl_tlsdesc_return) so the barriers dominate tls + access performance. + + TLSDESC relocs are in DT_JMPREL which are processed at load time using + elf_machine_lazy_rel which is only supposed to do lightweight + initialization using the DT_TLSDESC_PLT trampoline (the trampoline code + jumps to the entry point in DT_TLSDESC_GOT which does the lazy tlsdesc + initialization at runtime). This patch changes elf_machine_lazy_rel + in aarch64 to do the symbol binding and initialization as if DF_BIND_NOW + was set, so the non-lazy code path of elf/do-rel.h was replicated. + + The static linker could be changed to emit TLSDESC relocs in DT_REL*, + which are processed non-lazily, but the goal of this patch is to always + guarantee bind-now semantics, even if the binary was produced with an + old linker, so the barriers can be dropped in tls descriptor functions. + + After this change the synchronizing ldar instructions can be dropped + as well as the lazy initialization machinery including the DT_TLSDESC_GOT + setup. + + I believe this should be done on all targets, including ones where no + barrier is needed for lazy initialization. There is very little gain in + optimizing for large number of symbolic tlsdesc relocations which is an + extremely uncommon case. And currently the tlsdesc entries are only + readonly protected with -z now and some hardennings against writable + JUMPSLOT relocs don't work for TLSDESC so they are a security hazard. + (But to fix that the static linker has to be changed.) + + * sysdeps/aarch64/dl-machine.h (elf_machine_lazy_rel): Do symbol + binding and initialization non-lazily for R_AARCH64_TLSDESC. + +diff -rup a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h +--- a/sysdeps/aarch64/dl-machine.h 2018-10-16 12:07:31.588149003 -0400 ++++ b/sysdeps/aarch64/dl-machine.h 2018-10-16 12:18:46.214078837 -0400 +@@ -376,12 +376,21 @@ elf_machine_lazy_rel (struct link_map *m + } + else if (__builtin_expect (r_type == R_AARCH64_TLSDESC, 1)) + { +- struct tlsdesc volatile *td = +- (struct tlsdesc volatile *)reloc_addr; ++ const Elf_Symndx symndx = ELFW (R_SYM) (reloc->r_info); ++ const ElfW (Sym) *symtab = (const void *)D_PTR (map, l_info[DT_SYMTAB]); ++ const ElfW (Sym) *sym = &symtab[symndx]; ++ const struct r_found_version *version = NULL; + +- td->arg = (void*)reloc; +- td->entry = (void*)(D_PTR (map, l_info[ADDRIDX (DT_TLSDESC_PLT)]) +- + map->l_addr); ++ if (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL) ++ { ++ const ElfW (Half) *vernum = ++ (const void *)D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]); ++ version = &map->l_versions[vernum[symndx] & 0x7fff]; ++ } ++ ++ /* Always initialize TLS descriptors completely, because lazy ++ initialization requires synchronization at every TLS access. */ ++ elf_machine_rela (map, reloc, sym, version, reloc_addr, skip_ifunc); + } + else if (__glibc_unlikely (r_type == R_AARCH64_IRELATIVE)) + { diff --git a/SOURCES/glibc-rh1641981.patch b/SOURCES/glibc-rh1641981.patch new file mode 100644 index 0000000..48cea45 --- /dev/null +++ b/SOURCES/glibc-rh1641981.patch @@ -0,0 +1,41 @@ +commit c3d8dc45c9df199b8334599a6cbd98c9950dba62 +Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> +Date: Thu Oct 11 15:18:40 2018 -0300 + + x86: Fix Haswell strong flags (BZ#23709) + + Th commit 'Disable TSX on some Haswell processors.' (2702856bf4) changed the + default flags for Haswell models. Previously, new models were handled by the + default switch path, which assumed a Core i3/i5/i7 if AVX is available. After + the patch, Haswell models (0x3f, 0x3c, 0x45, 0x46) do not set the flags + Fast_Rep_String, Fast_Unaligned_Load, Fast_Unaligned_Copy, and + Prefer_PMINUB_for_stringop (only the TSX one). + + This patch fixes it by disentangle the TSX flag handling from the memory + optimization ones. The strstr case cited on patch now selects the + __strstr_sse2_unaligned as expected for the Haswell cpu. + + Checked on x86_64-linux-gnu. + + [BZ #23709] + * sysdeps/x86/cpu-features.c (init_cpu_features): Set TSX bits + independently of other flags. + +diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c +index 0667e486959a8a91..d134ef3a92cbc83d 100644 +--- a/sysdeps/x86/cpu-features.c ++++ b/sysdeps/x86/cpu-features.c +@@ -133,7 +133,13 @@ init_cpu_features (struct cpu_features *cpu_features) + | bit_Fast_Unaligned_Load + | bit_Prefer_PMINUB_for_stringop); + break; ++ } + ++ /* Disable TSX on some Haswell processors to avoid TSX on kernels that ++ weren't updated with the latest microcode package (which disables ++ broken feature by default). */ ++ switch (model) ++ { + case 0x3f: + /* Xeon E7 v3 with stepping >= 4 has working TSX. */ + if (stepping >= 4) diff --git a/SOURCES/glibc-rh1646373.patch b/SOURCES/glibc-rh1646373.patch new file mode 100644 index 0000000..a6c6c7b --- /dev/null +++ b/SOURCES/glibc-rh1646373.patch @@ -0,0 +1,32 @@ +commit bd3b0fbae33a9a4cc5e2daf049443d5cf03d4251 +Author: Andreas Schwab <schwab@suse.de> +Date: Mon Nov 5 12:47:30 2018 +0100 + + libanl: properly cleanup if first helper thread creation failed (bug 22927) + +2018-11-05 Andreas Schwab <schwab@suse.de> + + [BZ #22927] + * resolv/gai_misc.c (__gai_enqueue_request): Don't crash if + creating the first helper thread failed. + +[Note from DJ - hard to test; must force second calloc() call in +getaddrinfo_a() to return NULL/ENOMEM] + +diff -rup a/resolv/gai_misc.c b/resolv/gai_misc.c +--- a/resolv/gai_misc.c 2012-12-24 22:02:13.000000000 -0500 ++++ b/resolv/gai_misc.c 2019-01-22 16:19:30.514199534 -0500 +@@ -264,8 +264,11 @@ __gai_enqueue_request (struct gaicb *gai + /* We cannot create a thread in the moment and there is + also no thread running. This is a problem. `errno' is + set to EAGAIN if this is only a temporary problem. */ +- assert (lastp->next == newp); +- lastp->next = NULL; ++ assert (requests == newp || lastp->next == newp); ++ if (lastp != NULL) ++ lastp->next = NULL; ++ else ++ requests = NULL; + requests_tail = lastp; + + newp->next = freelist; diff --git a/SOURCES/glibc-rh1647490-1.patch b/SOURCES/glibc-rh1647490-1.patch new file mode 100644 index 0000000..cf3ade5 --- /dev/null +++ b/SOURCES/glibc-rh1647490-1.patch @@ -0,0 +1,80 @@ +commit 6c3a8a9d868a8deddf0d6dcc785b6d120de90523 +Author: Paul Pluzhnikov <ppluzhnikov@kazbek.mtv.corp.google.com> +Date: Fri Aug 24 18:08:51 2018 -0700 + + Fix BZ#23400 (creating temporary files in source tree), and undefined behavior in test. + +diff --git a/stdlib/test-bz22786.c b/stdlib/test-bz22786.c +index e7837f98c19fc4bf..d1aa69106ccf6ac5 100644 +--- a/stdlib/test-bz22786.c ++++ b/stdlib/test-bz22786.c +@@ -26,28 +26,20 @@ + #include <unistd.h> + #include <sys/stat.h> + #include <sys/types.h> ++#include <support/check.h> ++#include <support/support.h> ++#include <support/temp_file.h> + #include <support/test-driver.h> + #include <libc-diag.h> + + static int + do_test (void) + { +- const char dir[] = "bz22786"; +- const char lnk[] = "bz22786/symlink"; ++ const char *dir = support_create_temp_directory ("bz22786."); ++ const char *lnk = xasprintf ("%s/symlink", dir); ++ const size_t path_len = (size_t) INT_MAX + strlen (lnk) + 1; + +- rmdir (dir); +- if (mkdir (dir, 0755) != 0 && errno != EEXIST) +- { +- printf ("mkdir %s: %m\n", dir); +- return EXIT_FAILURE; +- } +- if (symlink (".", lnk) != 0 && errno != EEXIST) +- { +- printf ("symlink (%s, %s): %m\n", dir, lnk); +- return EXIT_FAILURE; +- } +- +- const size_t path_len = (size_t) INT_MAX + 1; ++ TEST_VERIFY_EXIT (symlink (".", lnk) == 0); + + DIAG_PUSH_NEEDS_COMMENT; + #if __GNUC_PREREQ (7, 0) +@@ -55,20 +47,14 @@ do_test (void) + allocation to succeed for the test to work. */ + DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than="); + #endif +- char *path = malloc (path_len); ++ char *path = xmalloc (path_len); + DIAG_POP_NEEDS_COMMENT; + +- if (path == NULL) +- { +- printf ("malloc (%zu): %m\n", path_len); +- return EXIT_UNSUPPORTED; +- } +- +- /* Construct very long path = "bz22786/symlink/aaaa....." */ +- char *p = mempcpy (path, lnk, sizeof (lnk) - 1); ++ /* Construct very long path = "/tmp/bz22786.XXXX/symlink/aaaa....." */ ++ char *p = mempcpy (path, lnk, strlen (lnk)); + *(p++) = '/'; +- memset (p, 'a', path_len - (path - p) - 2); +- p[path_len - (path - p) - 1] = '\0'; ++ memset (p, 'a', path_len - (p - path) - 2); ++ p[path_len - (p - path) - 1] = '\0'; + + /* This call crashes before the fix for bz22786 on 32-bit platforms. */ + p = realpath (path, NULL); +@@ -81,7 +67,6 @@ do_test (void) + + /* Cleanup. */ + unlink (lnk); +- rmdir (dir); + + return 0; + } diff --git a/SOURCES/glibc-rh1647490-2.patch b/SOURCES/glibc-rh1647490-2.patch new file mode 100644 index 0000000..8ad2241 --- /dev/null +++ b/SOURCES/glibc-rh1647490-2.patch @@ -0,0 +1,55 @@ +commit 3bad2358d67d371497079bba4f8eca9c0096f4e2 +Author: Stefan Liebler <stli@linux.ibm.com> +Date: Thu Aug 30 08:44:32 2018 +0200 + + Test stdlib/test-bz22786 exits now with unsupported if malloc fails. + + The test tries to allocate more than 2^31 bytes which will always fail on s390 + as it has maximum 2^31bit of memory. + Before commit 6c3a8a9d868a8deddf0d6dcc785b6d120de90523, this test returned + unsupported if malloc fails. This patch re enables this behaviour. + + Furthermore support_delete_temp_files() failed to remove the temp directory + in this case as it is not empty due to the created symlink. + Thus the creation of the symlink is moved behind malloc. + + Reviewed-by: Carlos O'Donell <carlos@redhat.com> + + ChangeLog: + + * stdlib/test-bz22786.c (do_test): Return EXIT_UNSUPPORTED + if malloc fails. + +diff --git a/stdlib/test-bz22786.c b/stdlib/test-bz22786.c +index d1aa69106ccf6ac5..777bf9180f4b5022 100644 +--- a/stdlib/test-bz22786.c ++++ b/stdlib/test-bz22786.c +@@ -39,16 +39,25 @@ do_test (void) + const char *lnk = xasprintf ("%s/symlink", dir); + const size_t path_len = (size_t) INT_MAX + strlen (lnk) + 1; + +- TEST_VERIFY_EXIT (symlink (".", lnk) == 0); +- + DIAG_PUSH_NEEDS_COMMENT; + #if __GNUC_PREREQ (7, 0) + /* GCC 7 warns about too-large allocations; here we need such + allocation to succeed for the test to work. */ + DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than="); + #endif +- char *path = xmalloc (path_len); ++ char *path = malloc (path_len); + DIAG_POP_NEEDS_COMMENT; ++ if (path == NULL) ++ { ++ printf ("malloc (%zu): %m\n", path_len); ++ /* On 31-bit s390 the malloc will always fail as we do not have ++ so much memory, and we want to mark the test unsupported. ++ Likewise on systems with little physical memory the test will ++ fail and should be unsupported. */ ++ return EXIT_UNSUPPORTED; ++ } ++ ++ TEST_VERIFY_EXIT (symlink (".", lnk) == 0); + + /* Construct very long path = "/tmp/bz22786.XXXX/symlink/aaaa....." */ + char *p = mempcpy (path, lnk, strlen (lnk)); diff --git a/SOURCES/glibc-rh1647490-3.patch b/SOURCES/glibc-rh1647490-3.patch new file mode 100644 index 0000000..7f68b16 --- /dev/null +++ b/SOURCES/glibc-rh1647490-3.patch @@ -0,0 +1,64 @@ +commit f5e7e95921847bd83186bfe621fc2b48c4de5477 +Author: Florian Weimer <fweimer@redhat.com> +Date: Tue Oct 30 13:11:47 2018 +0100 + + stdlib/test-bz22786: Avoid spurious test failures using alias mappings + + On systems without enough random-access memory, stdlib/test-bz22786 + will go deeply into swap and time out, even with a substantial + TIMEOUTFACTOR. This commit adds a facility to construct repeating + strings with alias mappings, so that the requirement for physical + memory, and uses it in stdlib/test-bz22786. + +Adjusted here for the support/ backport in glibc-rh1418978-1.patch. + +diff --git a/stdlib/test-bz22786.c b/stdlib/test-bz22786.c +index 777bf9180f4b5022..bb1e04f2debe9042 100644 +--- a/stdlib/test-bz22786.c ++++ b/stdlib/test-bz22786.c +@@ -26,6 +26,7 @@ + #include <unistd.h> + #include <sys/stat.h> + #include <sys/types.h> ++#include <support/blob_repeat.h> + #include <support/check.h> + #include <support/support.h> + #include <support/temp_file.h> +@@ -39,17 +40,12 @@ do_test (void) + const char *lnk = xasprintf ("%s/symlink", dir); + const size_t path_len = (size_t) INT_MAX + strlen (lnk) + 1; + +- DIAG_PUSH_NEEDS_COMMENT; +-#if __GNUC_PREREQ (7, 0) +- /* GCC 7 warns about too-large allocations; here we need such +- allocation to succeed for the test to work. */ +- DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than="); +-#endif +- char *path = malloc (path_len); +- DIAG_POP_NEEDS_COMMENT; ++ struct support_blob_repeat repeat ++ = support_blob_repeat_allocate ("a", 1, path_len); ++ char *path = repeat.start; + if (path == NULL) + { +- printf ("malloc (%zu): %m\n", path_len); ++ printf ("Repeated allocation (%zu bytes): %m\n", path_len); + /* On 31-bit s390 the malloc will always fail as we do not have + so much memory, and we want to mark the test unsupported. + Likewise on systems with little physical memory the test will +@@ -62,7 +58,6 @@ do_test (void) + /* Construct very long path = "/tmp/bz22786.XXXX/symlink/aaaa....." */ + char *p = mempcpy (path, lnk, strlen (lnk)); + *(p++) = '/'; +- memset (p, 'a', path_len - (p - path) - 2); + p[path_len - (p - path) - 1] = '\0'; + + /* This call crashes before the fix for bz22786 on 32-bit platforms. */ +@@ -76,6 +71,7 @@ do_test (void) + + /* Cleanup. */ + unlink (lnk); ++ support_blob_repeat_free (&repeat); + + return 0; + } diff --git a/SOURCES/glibc-rh1647490-4.patch b/SOURCES/glibc-rh1647490-4.patch new file mode 100644 index 0000000..77866a1 --- /dev/null +++ b/SOURCES/glibc-rh1647490-4.patch @@ -0,0 +1,51 @@ +commit 07da99aad93c9364acb7efdab47c27ba698f6313 +Author: Florian Weimer <fweimer@redhat.com> +Date: Tue Oct 30 13:55:01 2018 +0100 + + stdlib/tst-strtod-overflow: Switch to support_blob_repeat + + This is another test with an avoidable large memory allocation. + +diff --git a/stdlib/tst-strtod-overflow.c b/stdlib/tst-strtod-overflow.c +index 6c5b2828551dd580..fd1be79f3f58c64b 100644 +--- a/stdlib/tst-strtod-overflow.c ++++ b/stdlib/tst-strtod-overflow.c +@@ -19,6 +19,8 @@ + #include <stdio.h> + #include <stdlib.h> + #include <string.h> ++#include <support/blob_repeat.h> ++#include <support/test-driver.h> + + #define EXPONENT "e-2147483649" + #define SIZE 214748364 +@@ -26,21 +28,23 @@ + static int + do_test (void) + { +- char *p = malloc (1 + SIZE + sizeof (EXPONENT)); +- if (p == NULL) ++ struct support_blob_repeat repeat = support_blob_repeat_allocate ++ ("0", 1, 1 + SIZE + sizeof (EXPONENT)); ++ if (repeat.size == 0) + { +- puts ("malloc failed, cannot test for overflow"); +- return 0; ++ puts ("warning: memory allocation failed, cannot test for overflow"); ++ return EXIT_UNSUPPORTED; + } ++ char *p = repeat.start; + p[0] = '1'; +- memset (p + 1, '0', SIZE); + memcpy (p + 1 + SIZE, EXPONENT, sizeof (EXPONENT)); + double d = strtod (p, NULL); + if (d != 0) + { +- printf ("strtod returned wrong value: %a\n", d); ++ printf ("error: strtod returned wrong value: %a\n", d); + return 1; + } ++ support_blob_repeat_free (&repeat); + return 0; + } + diff --git a/SOURCES/glibc-rh1647490-5.patch b/SOURCES/glibc-rh1647490-5.patch new file mode 100644 index 0000000..ea8509f --- /dev/null +++ b/SOURCES/glibc-rh1647490-5.patch @@ -0,0 +1,30 @@ +commit 60708030536df82616c16aa2f14f533c4362b969 +Author: Florian Weimer <fweimer@redhat.com> +Date: Tue Oct 30 13:56:40 2018 +0100 + + stdlib/test-bz22786: Avoid memory leaks in the test itself + +diff --git a/stdlib/test-bz22786.c b/stdlib/test-bz22786.c +index bb1e04f2debe9042..8035e8a394e7d034 100644 +--- a/stdlib/test-bz22786.c ++++ b/stdlib/test-bz22786.c +@@ -36,8 +36,8 @@ + static int + do_test (void) + { +- const char *dir = support_create_temp_directory ("bz22786."); +- const char *lnk = xasprintf ("%s/symlink", dir); ++ char *dir = support_create_temp_directory ("bz22786."); ++ char *lnk = xasprintf ("%s/symlink", dir); + const size_t path_len = (size_t) INT_MAX + strlen (lnk) + 1; + + struct support_blob_repeat repeat +@@ -72,6 +72,8 @@ do_test (void) + /* Cleanup. */ + unlink (lnk); + support_blob_repeat_free (&repeat); ++ free (lnk); ++ free (dir); + + return 0; + } diff --git a/SOURCES/glibc-rh1647490-6.patch b/SOURCES/glibc-rh1647490-6.patch new file mode 100644 index 0000000..7ae5a66 --- /dev/null +++ b/SOURCES/glibc-rh1647490-6.patch @@ -0,0 +1,27 @@ +Use <support/test-driver.c> in stdlib/tst-strtod-overflow.c + +This downstream-only patch is needed because test-skeleton.c contains +a copy of the old test skeleton (unlike upstream), resulting in the +following error: + +In file included from tst-strtod-overflow.c:53:0: +../test-skeleton.c:65:20: error: static declaration of 'test_dir' follows non-static declaration + static const char *test_dir; + ^ +In file included from tst-strtod-overflow.c:23:0: +../support/test-driver.h:65:20: note: previous declaration of 'test_dir' was here + extern const char *test_dir; + ^ + +diff --git a/stdlib/tst-strtod-overflow.c b/stdlib/tst-strtod-overflow.c +index fd1be79f3f58c64b..2b30947d9a9fa03a 100644 +--- a/stdlib/tst-strtod-overflow.c ++++ b/stdlib/tst-strtod-overflow.c +@@ -48,6 +48,4 @@ do_test (void) + return 0; + } + +-#define TEST_FUNCTION do_test () +-#define TIMEOUT 5 +-#include "../test-skeleton.c" ++#include <support/test-driver.c> diff --git a/SOURCES/glibc-rh1657015-1.patch b/SOURCES/glibc-rh1657015-1.patch new file mode 100644 index 0000000..cec18d7 --- /dev/null +++ b/SOURCES/glibc-rh1657015-1.patch @@ -0,0 +1,41 @@ +Update kernel version in syscall-names.list to 4.17. + +As far as I can tell, Linux 4.17 does not add any new syscalls; this +patch updates the version number in syscall-names.list to reflect that +it's still current for 4.17. + +Tested for x86_64-linux-gnu with build-many-glibcs.py. + + * sysdeps/unix/sysv/linux/syscall-names.list: Update kernel + version to 4.17. + +(cherry picked from commit 0e0577c93fcdd8922ca83763400f74ca10e46019) + +diff --git a/ChangeLog b/ChangeLog +index 77c3dae5b015ecad..77aa2a8cf78e568f 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2018-06-05 Joseph Myers <joseph@codesourcery.com> ++ ++ * sysdeps/unix/sysv/linux/syscall-names.list: Update kernel ++ version to 4.17. ++ + 2012-12-21 David S. Miller <davem@davemloft.net> + + * po/hr.po: Update from translation team. +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index fab3ff2328373a1f..5306d538e6448163 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -22,8 +22,8 @@ + # names are only used if the installed kernel headers also provide + # them. + +-# The list of system calls is current as of Linux 4.16. +-kernel 4.16 ++# The list of system calls is current as of Linux 4.17. ++kernel 4.17 + + FAST_atomic_update + FAST_cmpxchg diff --git a/SOURCES/glibc-rh1657015-2.patch b/SOURCES/glibc-rh1657015-2.patch new file mode 100644 index 0000000..ced8bd8 --- /dev/null +++ b/SOURCES/glibc-rh1657015-2.patch @@ -0,0 +1,61 @@ +Update syscall-names.list for Linux 4.18. + +This patch updates sysdeps/unix/sysv/linux/syscall-names.list for +Linux 4.18. The io_pgetevents and rseq syscalls are added to the +kernel on various architectures, so need to be mentioned in this file. + +Tested with build-many-glibcs.py. + + * sysdeps/unix/sysv/linux/syscall-names.list: Update kernel + version to 4.18. + (io_pgetevents): New syscall. + (rseq): Likewise. + +(cherry picked from commit 17b26500f9bb926d85e86821d014f7c1bb88043c) + +diff --git a/ChangeLog b/ChangeLog +index 77aa2a8cf78e568f..3ccca34563e5b71f 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,10 @@ ++2018-08-13 Joseph Myers <joseph@codesourcery.com> ++ ++ * sysdeps/unix/sysv/linux/syscall-names.list: Update kernel ++ version to 4.18. ++ (io_pgetevents): New syscall. ++ (rseq): Likewise. ++ + 2018-06-05 Joseph Myers <joseph@codesourcery.com> + + * sysdeps/unix/sysv/linux/syscall-names.list: Update kernel +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index 5306d538e6448163..9982a6334d46ae62 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -22,8 +22,8 @@ + # names are only used if the installed kernel headers also provide + # them. + +-# The list of system calls is current as of Linux 4.17. +-kernel 4.17 ++# The list of system calls is current as of Linux 4.18. ++kernel 4.18 + + FAST_atomic_update + FAST_cmpxchg +@@ -186,6 +186,7 @@ inotify_rm_watch + io_cancel + io_destroy + io_getevents ++io_pgetevents + io_setup + io_submit + ioctl +@@ -431,6 +432,7 @@ renameat2 + request_key + restart_syscall + rmdir ++rseq + rt_sigaction + rt_sigpending + rt_sigprocmask diff --git a/SOURCES/glibc-rh1657015-3.patch b/SOURCES/glibc-rh1657015-3.patch new file mode 100644 index 0000000..df258a9 --- /dev/null +++ b/SOURCES/glibc-rh1657015-3.patch @@ -0,0 +1,41 @@ +Update kernel version in syscall-names.list to 4.19. + +Linux 4.19 does not add any new syscalls (some existing ones are added +to more architectures); this patch updates the version number in +syscall-names.list to reflect that it's still current for 4.19. + +Tested with build-many-glibcs.py. + + * sysdeps/unix/sysv/linux/syscall-names.list: Update kernel + version to 4.19. + +(cherry picked from commit 029ad711b8ad4cf0e5d98e0c138a35a23a376a74) + +diff --git a/ChangeLog b/ChangeLog +index 3ccca34563e5b71f..30a5bed6b09efcef 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,8 @@ ++2018-10-22 Joseph Myers <joseph@codesourcery.com> ++ ++ * sysdeps/unix/sysv/linux/syscall-names.list: Update kernel ++ version to 4.19. ++ + 2018-08-13 Joseph Myers <joseph@codesourcery.com> + + * sysdeps/unix/sysv/linux/syscall-names.list: Update kernel +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index 9982a6334d46ae62..f88001c9c38d5fc7 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -22,8 +22,8 @@ + # names are only used if the installed kernel headers also provide + # them. + +-# The list of system calls is current as of Linux 4.18. +-kernel 4.18 ++# The list of system calls is current as of Linux 4.19. ++kernel 4.19 + + FAST_atomic_update + FAST_cmpxchg diff --git a/SOURCES/glibc-rh1657015-4.patch b/SOURCES/glibc-rh1657015-4.patch new file mode 100644 index 0000000..c4f98dc --- /dev/null +++ b/SOURCES/glibc-rh1657015-4.patch @@ -0,0 +1,52 @@ +Update syscall-names.list for Linux 4.20. + +This patch updates sysdeps/unix/sysv/linux/syscall-names.list for +Linux 4.20. Although there are no new syscalls, the +riscv_flush_icache syscall has moved to asm/unistd.h (previously in +asm/syscalls.h) and so now needs to be added to the list. + +Tested with build-many-glibcs.py. + + * sysdeps/unix/sysv/linux/syscall-names.list: Update kernel + version to 4.20. + (riscv_flush_icache): New syscall. + +(cherry picked from commit 47ad5e1a2a3ab8eeda491454cbef3b1c5239dc02) + +diff --git a/ChangeLog b/ChangeLog +index 30a5bed6b09efcef..0f4f95193ff07d45 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,9 @@ ++2019-01-01 Joseph Myers <joseph@codesourcery.com> ++ ++ * sysdeps/unix/sysv/linux/syscall-names.list: Update kernel ++ version to 4.20. ++ (riscv_flush_icache): New syscall. ++ + 2018-10-22 Joseph Myers <joseph@codesourcery.com> + + * sysdeps/unix/sysv/linux/syscall-names.list: Update kernel +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index f88001c9c38d5fc7..d623dc1d9af027be 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -22,8 +22,8 @@ + # names are only used if the installed kernel headers also provide + # them. + +-# The list of system calls is current as of Linux 4.19. +-kernel 4.19 ++# The list of system calls is current as of Linux 4.20. ++kernel 4.20 + + FAST_atomic_update + FAST_cmpxchg +@@ -431,6 +431,7 @@ renameat + renameat2 + request_key + restart_syscall ++riscv_flush_icache + rmdir + rseq + rt_sigaction diff --git a/SOURCES/glibc-rh1661242-1.patch b/SOURCES/glibc-rh1661242-1.patch deleted file mode 100644 index 971c251..0000000 --- a/SOURCES/glibc-rh1661242-1.patch +++ /dev/null @@ -1,486 +0,0 @@ -commit e5d262effe3a87164308a3f37e61b32d0348692a -Author: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> -Date: Fri Nov 30 18:05:32 2018 -0200 - - Fix _dl_profile_fixup data-dependency issue (Bug 23690) - - There is a data-dependency between the fields of struct l_reloc_result - and the field used as the initialization guard. Users of the guard - expect writes to the structure to be observable when they also observe - the guard initialized. The solution for this problem is to use an acquire - and release load and store to ensure previous writes to the structure are - observable if the guard is initialized. - - The previous implementation used DL_FIXUP_VALUE_ADDR (l_reloc_result->addr) - as the initialization guard, making it impossible for some architectures - to load and store it atomically, i.e. hppa and ia64, due to its larger size. - - This commit adds an unsigned int to l_reloc_result to be used as the new - initialization guard of the struct, making it possible to load and store - it atomically in all architectures. The fix ensures that the values - observed in l_reloc_result are consistent and do not lead to crashes. - The algorithm is documented in the code in elf/dl-runtime.c - (_dl_profile_fixup). Not all data races have been eliminated. - - Tested with build-many-glibcs and on powerpc, powerpc64, and powerpc64le. - - [BZ #23690] - * elf/dl-runtime.c (_dl_profile_fixup): Guarantee memory - modification order when accessing reloc_result->addr. - * include/link.h (reloc_result): Add field init. - * nptl/Makefile (tests): Add tst-audit-threads. - (modules-names): Add tst-audit-threads-mod1 and - tst-audit-threads-mod2. - Add rules to build tst-audit-threads. - * nptl/tst-audit-threads-mod1.c: New file. - * nptl/tst-audit-threads-mod2.c: Likewise. - * nptl/tst-audit-threads.c: Likewise. - * nptl/tst-audit-threads.h: Likewise. - - Signed-off-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> - Reviewed-by: Carlos O'Donell <carlos@redhat.com> - -(elf/dl-runtime.c adjusted here for lack of __builtin_expect cleanup, -nptl/Makefile for the usual test-related conflicts.) - -diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c -index a42e3c4924e067ba..3678a98c98d726f3 100644 ---- a/elf/dl-runtime.c -+++ b/elf/dl-runtime.c -@@ -183,10 +183,36 @@ _dl_profile_fixup ( - /* This is the address in the array where we store the result of previous - relocations. */ - struct reloc_result *reloc_result = &l->l_reloc_result[reloc_index]; -- DL_FIXUP_VALUE_TYPE *resultp = &reloc_result->addr; - -- DL_FIXUP_VALUE_TYPE value = *resultp; -- if (DL_FIXUP_VALUE_CODE_ADDR (value) == 0) -+ /* CONCURRENCY NOTES: -+ -+ Multiple threads may be calling the same PLT sequence and with -+ LD_AUDIT enabled they will be calling into _dl_profile_fixup to -+ update the reloc_result with the result of the lazy resolution. -+ The reloc_result guard variable is reloc_init, and we use -+ acquire/release loads and store to it to ensure that the results of -+ the structure are consistent with the loaded value of the guard. -+ This does not fix all of the data races that occur when two or more -+ threads read reloc_result->reloc_init with a value of zero and read -+ and write to that reloc_result concurrently. The expectation is -+ generally that while this is a data race it works because the -+ threads write the same values. Until the data races are fixed -+ there is a potential for problems to arise from these data races. -+ The reloc result updates should happen in parallel but there should -+ be an atomic RMW which does the final update to the real result -+ entry (see bug 23790). -+ -+ The following code uses reloc_result->init set to 0 to indicate if it is -+ the first time this object is being relocated, otherwise 1 which -+ indicates the object has already been relocated. -+ -+ Reading/Writing from/to reloc_result->reloc_init must not happen -+ before previous writes to reloc_result complete as they could -+ end-up with an incomplete struct. */ -+ DL_FIXUP_VALUE_TYPE value; -+ unsigned int init = atomic_load_acquire (&reloc_result->init); -+ -+ if (init == 0) - { - /* This is the first time we have to relocate this object. */ - const ElfW(Sym) *const symtab -@@ -347,20 +373,32 @@ _dl_profile_fixup ( - #endif - - /* Store the result for later runs. */ -- if (__builtin_expect (! GLRO(dl_bind_not), 1)) -- *resultp = value; -+ if (__glibc_likely (! GLRO(dl_bind_not))) -+ { -+ reloc_result->addr = value; -+ /* Guarantee all previous writes complete before -+ init is updated. See CONCURRENCY NOTES earlier */ -+ atomic_store_release (&reloc_result->init, 1); -+ } -+ init = 1; - } -+ else -+ value = reloc_result->addr; - - /* By default we do not call the pltexit function. */ - long int framesize = -1; - -+ - #ifdef SHARED - /* Auditing checkpoint: report the PLT entering and allow the - auditors to change the value. */ -- if (DL_FIXUP_VALUE_CODE_ADDR (value) != 0 && GLRO(dl_naudit) > 0 -+ if (GLRO(dl_naudit) > 0 - /* Don't do anything if no auditor wants to intercept this call. */ - && (reloc_result->enterexit & LA_SYMB_NOPLTENTER) == 0) - { -+ /* Sanity check: DL_FIXUP_VALUE_CODE_ADDR (value) should have been -+ initialized earlier in this function or in another thread. */ -+ assert (DL_FIXUP_VALUE_CODE_ADDR (value) != 0); - ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound, - l_info[DT_SYMTAB]) - + reloc_result->boundndx); -diff --git a/include/link.h b/include/link.h -index d7590640aa9285e5..22d020d833ae3a7c 100644 ---- a/include/link.h -+++ b/include/link.h -@@ -206,6 +206,10 @@ struct link_map - unsigned int boundndx; - uint32_t enterexit; - unsigned int flags; -+ /* CONCURRENCY NOTE: This is used to guard the concurrent initialization -+ of the relocation result across multiple threads. See the more -+ detailed notes in elf/dl-runtime.c. */ -+ unsigned int init; - } *l_reloc_result; - - /* Pointer to the version information if available. */ -diff --git a/nptl/Makefile b/nptl/Makefile -index cf47a6f097916766..1b9639f3566a63fd 100644 ---- a/nptl/Makefile -+++ b/nptl/Makefile -@@ -298,7 +298,7 @@ tests += tst-cancelx2 tst-cancelx3 tst-cancelx4 tst-cancelx5 \ - endif - ifeq ($(build-shared),yes) - tests += tst-atfork2 tst-tls3 tst-tls4 tst-tls5 tst-_res1 tst-fini1 \ -- tst-stackguard1 -+ tst-stackguard1 tst-audit-threads - tests-nolibpthread += tst-fini1 - ifeq ($(have-z-execstack),yes) - tests += tst-execstack -@@ -309,7 +309,7 @@ modules-names = tst-atfork2mod tst-tls3mod tst-tls4moda tst-tls4modb \ - tst-tls5mod tst-tls5moda tst-tls5modb tst-tls5modc \ - tst-tls5modd tst-tls5mode tst-tls5modf tst-stack4mod \ - tst-_res1mod1 tst-_res1mod2 tst-execstack-mod tst-fini1mod \ -- tst-join7mod -+ tst-join7mod tst-audit-threads-mod1 tst-audit-threads-mod2 - extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) tst-cleanup4aux.o - test-extras += $(modules-names) tst-cleanup4aux - test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names))) -@@ -627,6 +627,14 @@ $(objpfx)tst-oddstacklimit.out: $(objpfx)tst-oddstacklimit $(objpfx)tst-basic1 - $(run-program-prefix) $< --command '$(host-built-program-cmd)' > $@ - endif - -+# Protect against a build using -Wl,-z,now. -+LDFLAGS-tst-audit-threads-mod1.so = -Wl,-z,lazy -+LDFLAGS-tst-audit-threads-mod2.so = -Wl,-z,lazy -+LDFLAGS-tst-audit-threads = -Wl,-z,lazy -+$(objpfx)tst-audit-threads: $(objpfx)tst-audit-threads-mod2.so -+$(objpfx)tst-audit-threads.out: $(objpfx)tst-audit-threads-mod1.so -+tst-audit-threads-ENV = LD_AUDIT=$(objpfx)tst-audit-threads-mod1.so -+ - # The tests here better do not run in parallel - ifneq ($(filter %tests,$(MAKECMDGOALS)),) - .NOTPARALLEL: -diff --git a/nptl/tst-audit-threads-mod1.c b/nptl/tst-audit-threads-mod1.c -new file mode 100644 -index 0000000000000000..615d5ee5121962df ---- /dev/null -+++ b/nptl/tst-audit-threads-mod1.c -@@ -0,0 +1,74 @@ -+/* Dummy audit library for test-audit-threads. -+ -+ Copyright (C) 2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ <http://www.gnu.org/licenses/>. */ -+ -+#include <elf.h> -+#include <link.h> -+#include <stdio.h> -+#include <assert.h> -+#include <string.h> -+ -+/* We must use a dummy LD_AUDIT module to force the dynamic loader to -+ *not* update the real PLT, and instead use a cached value for the -+ lazy resolution result. It is the update of that cached value that -+ we are testing for correctness by doing this. */ -+ -+/* Library to be audited. */ -+#define LIB "tst-audit-threads-mod2.so" -+/* CALLNUM is the number of retNum functions. */ -+#define CALLNUM 7999 -+ -+#define CONCATX(a, b) __CONCAT (a, b) -+ -+static int previous = 0; -+ -+unsigned int -+la_version (unsigned int ver) -+{ -+ return 1; -+} -+ -+unsigned int -+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie) -+{ -+ return LA_FLG_BINDTO | LA_FLG_BINDFROM; -+} -+ -+uintptr_t -+CONCATX(la_symbind, __ELF_NATIVE_CLASS) (ElfW(Sym) *sym, -+ unsigned int ndx, -+ uintptr_t *refcook, -+ uintptr_t *defcook, -+ unsigned int *flags, -+ const char *symname) -+{ -+ const char * retnum = "retNum"; -+ char * num = strstr (symname, retnum); -+ int n; -+ /* Validate if the symbols are getting called in the correct order. -+ This code is here to verify binutils does not optimize out the PLT -+ entries that require the symbol binding. */ -+ if (num != NULL) -+ { -+ n = atoi (num); -+ assert (n >= previous); -+ assert (n <= CALLNUM); -+ previous = n; -+ } -+ return sym->st_value; -+} -diff --git a/nptl/tst-audit-threads-mod2.c b/nptl/tst-audit-threads-mod2.c -new file mode 100644 -index 0000000000000000..f9817dd3dc7f4910 ---- /dev/null -+++ b/nptl/tst-audit-threads-mod2.c -@@ -0,0 +1,22 @@ -+/* Shared object with a huge number of functions for test-audit-threads. -+ -+ Copyright (C) 2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ <http://www.gnu.org/licenses/>. */ -+ -+/* Define all the retNumN functions in a library. */ -+#define definenum -+#include "tst-audit-threads.h" -diff --git a/nptl/tst-audit-threads.c b/nptl/tst-audit-threads.c -new file mode 100644 -index 0000000000000000..e4bf433bd85f3715 ---- /dev/null -+++ b/nptl/tst-audit-threads.c -@@ -0,0 +1,97 @@ -+/* Test multi-threading using LD_AUDIT. -+ -+ Copyright (C) 2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ <http://www.gnu.org/licenses/>. */ -+ -+/* This test uses a dummy LD_AUDIT library (test-audit-threads-mod1) and a -+ library with a huge number of functions in order to validate lazy symbol -+ binding with an audit library. We use one thread per CPU to test that -+ concurrent lazy resolution does not have any defects which would cause -+ the process to fail. We use an LD_AUDIT library to force the testing of -+ the relocation resolution caching code in the dynamic loader i.e. -+ _dl_runtime_profile and _dl_profile_fixup. */ -+ -+#include <support/xthread.h> -+#include <strings.h> -+#include <stdlib.h> -+#include <sys/sysinfo.h> -+ -+static int do_test (void); -+ -+/* This test usually takes less than 3s to run. However, there are cases that -+ take up to 30s. */ -+#define TIMEOUT 60 -+#define TEST_FUNCTION do_test () -+#include "../test-skeleton.c" -+ -+/* Declare the functions we are going to call. */ -+#define externnum -+#include "tst-audit-threads.h" -+#undef externnum -+ -+int num_threads; -+pthread_barrier_t barrier; -+ -+void -+sync_all (int num) -+{ -+ pthread_barrier_wait (&barrier); -+} -+ -+void -+call_all_ret_nums (void) -+{ -+ /* Call each function one at a time from all threads. */ -+#define callnum -+#include "tst-audit-threads.h" -+#undef callnum -+} -+ -+void * -+thread_main (void *unused) -+{ -+ call_all_ret_nums (); -+ return NULL; -+} -+ -+#define STR2(X) #X -+#define STR(X) STR2(X) -+ -+static int -+do_test (void) -+{ -+ int i; -+ pthread_t *threads; -+ -+ num_threads = get_nprocs (); -+ if (num_threads <= 1) -+ num_threads = 2; -+ -+ /* Used to synchronize all the threads after calling each retNumN. */ -+ xpthread_barrier_init (&barrier, NULL, num_threads); -+ -+ threads = (pthread_t *) xcalloc (num_threads, sizeof(pthread_t)); -+ for (i = 0; i < num_threads; i++) -+ threads[i] = xpthread_create(NULL, thread_main, NULL); -+ -+ for (i = 0; i < num_threads; i++) -+ xpthread_join(threads[i]); -+ -+ free (threads); -+ -+ return 0; -+} -diff --git a/nptl/tst-audit-threads.h b/nptl/tst-audit-threads.h -new file mode 100644 -index 0000000000000000..1c9ecc08dfcd3e65 ---- /dev/null -+++ b/nptl/tst-audit-threads.h -@@ -0,0 +1,92 @@ -+/* Helper header for test-audit-threads. -+ -+ Copyright (C) 2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ <http://www.gnu.org/licenses/>. */ -+ -+/* We use this helper to create a large number of functions, all of -+ which will be resolved lazily and thus have their PLT updated. -+ This is done to provide enough functions that we can statistically -+ observe a thread vs. PLT resolution failure if one exists. */ -+ -+#define CONCAT(a, b) a ## b -+#define NUM(x, y) CONCAT (x, y) -+ -+#define FUNC10(x) \ -+ FUNC (NUM (x, 0)); \ -+ FUNC (NUM (x, 1)); \ -+ FUNC (NUM (x, 2)); \ -+ FUNC (NUM (x, 3)); \ -+ FUNC (NUM (x, 4)); \ -+ FUNC (NUM (x, 5)); \ -+ FUNC (NUM (x, 6)); \ -+ FUNC (NUM (x, 7)); \ -+ FUNC (NUM (x, 8)); \ -+ FUNC (NUM (x, 9)) -+ -+#define FUNC100(x) \ -+ FUNC10 (NUM (x, 0)); \ -+ FUNC10 (NUM (x, 1)); \ -+ FUNC10 (NUM (x, 2)); \ -+ FUNC10 (NUM (x, 3)); \ -+ FUNC10 (NUM (x, 4)); \ -+ FUNC10 (NUM (x, 5)); \ -+ FUNC10 (NUM (x, 6)); \ -+ FUNC10 (NUM (x, 7)); \ -+ FUNC10 (NUM (x, 8)); \ -+ FUNC10 (NUM (x, 9)) -+ -+#define FUNC1000(x) \ -+ FUNC100 (NUM (x, 0)); \ -+ FUNC100 (NUM (x, 1)); \ -+ FUNC100 (NUM (x, 2)); \ -+ FUNC100 (NUM (x, 3)); \ -+ FUNC100 (NUM (x, 4)); \ -+ FUNC100 (NUM (x, 5)); \ -+ FUNC100 (NUM (x, 6)); \ -+ FUNC100 (NUM (x, 7)); \ -+ FUNC100 (NUM (x, 8)); \ -+ FUNC100 (NUM (x, 9)) -+ -+#define FUNC7000() \ -+ FUNC1000 (1); \ -+ FUNC1000 (2); \ -+ FUNC1000 (3); \ -+ FUNC1000 (4); \ -+ FUNC1000 (5); \ -+ FUNC1000 (6); \ -+ FUNC1000 (7); -+ -+#ifdef FUNC -+# undef FUNC -+#endif -+ -+#ifdef externnum -+# define FUNC(x) extern int CONCAT (retNum, x) (void) -+#endif -+ -+#ifdef definenum -+# define FUNC(x) int CONCAT (retNum, x) (void) { return x; } -+#endif -+ -+#ifdef callnum -+# define FUNC(x) CONCAT (retNum, x) (); sync_all (x) -+#endif -+ -+/* A value of 7000 functions is chosen as an arbitrarily large -+ number of functions that will allow us enough attempts to -+ verify lazy resolution operation. */ -+FUNC7000 (); diff --git a/SOURCES/glibc-rh1661242-2.patch b/SOURCES/glibc-rh1661242-2.patch deleted file mode 100644 index e2bf37b..0000000 --- a/SOURCES/glibc-rh1661242-2.patch +++ /dev/null @@ -1,48 +0,0 @@ -nptl/tst-audit-threads: Switch to <support/test-driver.c> - -The downstream version of test-skeleton.c does not include -<support/support.h> for backwards compatibility reasons, leading to a -compilation failure: - -tst-audit-threads.c: In function 'do_test': -tst-audit-threads.c:87:3: error: implicit declaration of function 'xcalloc' [-Werror=implicit-function-declaration] - threads = (pthread_t *) xcalloc (num_threads, sizeof(pthread_t)); - ^ -tst-audit-threads.c:87:13: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] - threads = (pthread_t *) xcalloc (num_threads, sizeof(pthread_t)); - ^ - -diff --git a/nptl/tst-audit-threads.c b/nptl/tst-audit-threads.c -index e4bf433bd85f3715..42742d51e4bc06a3 100644 ---- a/nptl/tst-audit-threads.c -+++ b/nptl/tst-audit-threads.c -@@ -25,19 +25,12 @@ - the relocation resolution caching code in the dynamic loader i.e. - _dl_runtime_profile and _dl_profile_fixup. */ - -+#include <support/support.h> - #include <support/xthread.h> - #include <strings.h> - #include <stdlib.h> - #include <sys/sysinfo.h> - --static int do_test (void); -- --/* This test usually takes less than 3s to run. However, there are cases that -- take up to 30s. */ --#define TIMEOUT 60 --#define TEST_FUNCTION do_test () --#include "../test-skeleton.c" -- - /* Declare the functions we are going to call. */ - #define externnum - #include "tst-audit-threads.h" -@@ -95,3 +88,8 @@ do_test (void) - - return 0; - } -+ -+/* This test usually takes less than 3s to run. However, there are cases that -+ take up to 30s. */ -+#define TIMEOUT 60 -+#include <support/test-driver.c> diff --git a/SOURCES/glibc-rh1661244.patch b/SOURCES/glibc-rh1661244.patch deleted file mode 100644 index 05ae724..0000000 --- a/SOURCES/glibc-rh1661244.patch +++ /dev/null @@ -1,75 +0,0 @@ -Note: the context of this patch differs from upstream slightly, -to accomodate the lack of ILP32 in RHEL. - -commit b7cf203b5c17dd6d9878537d41e0c7cc3d270a67 -Author: Szabolcs Nagy <szabolcs.nagy@arm.com> -Date: Wed Sep 27 16:55:14 2017 +0100 - - aarch64: Disable lazy symbol binding of TLSDESC - - Always do TLS descriptor initialization at load time during relocation - processing to avoid barriers at every TLS access. In non-dlopened shared - libraries the overhead of tls access vs static global access is > 3x - bigger when lazy initialization is used (_dl_tlsdesc_return_lazy) - compared to bind-now (_dl_tlsdesc_return) so the barriers dominate tls - access performance. - - TLSDESC relocs are in DT_JMPREL which are processed at load time using - elf_machine_lazy_rel which is only supposed to do lightweight - initialization using the DT_TLSDESC_PLT trampoline (the trampoline code - jumps to the entry point in DT_TLSDESC_GOT which does the lazy tlsdesc - initialization at runtime). This patch changes elf_machine_lazy_rel - in aarch64 to do the symbol binding and initialization as if DF_BIND_NOW - was set, so the non-lazy code path of elf/do-rel.h was replicated. - - The static linker could be changed to emit TLSDESC relocs in DT_REL*, - which are processed non-lazily, but the goal of this patch is to always - guarantee bind-now semantics, even if the binary was produced with an - old linker, so the barriers can be dropped in tls descriptor functions. - - After this change the synchronizing ldar instructions can be dropped - as well as the lazy initialization machinery including the DT_TLSDESC_GOT - setup. - - I believe this should be done on all targets, including ones where no - barrier is needed for lazy initialization. There is very little gain in - optimizing for large number of symbolic tlsdesc relocations which is an - extremely uncommon case. And currently the tlsdesc entries are only - readonly protected with -z now and some hardennings against writable - JUMPSLOT relocs don't work for TLSDESC so they are a security hazard. - (But to fix that the static linker has to be changed.) - - * sysdeps/aarch64/dl-machine.h (elf_machine_lazy_rel): Do symbol - binding and initialization non-lazily for R_AARCH64_TLSDESC. - -diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h -index 4faf818b710d6ed7..185402f6dc550dc1 100644 ---- a/sysdeps/aarch64/dl-machine.h -+++ b/sysdeps/aarch64/dl-machine.h -@@ -376,12 +376,21 @@ elf_machine_lazy_rel (struct link_map *map, - } - else if (__builtin_expect (r_type == R_AARCH64_TLSDESC, 1)) - { -- struct tlsdesc volatile *td = -- (struct tlsdesc volatile *)reloc_addr; -+ const Elf_Symndx symndx = ELFW (R_SYM) (reloc->r_info); -+ const ElfW (Sym) *symtab = (const void *)D_PTR (map, l_info[DT_SYMTAB]); -+ const ElfW (Sym) *sym = &symtab[symndx]; -+ const struct r_found_version *version = NULL; - -- td->arg = (void*)reloc; -- td->entry = (void*)(D_PTR (map, l_info[ADDRIDX (DT_TLSDESC_PLT)]) -- + map->l_addr); -+ if (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL) -+ { -+ const ElfW (Half) *vernum = -+ (const void *)D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]); -+ version = &map->l_versions[vernum[symndx] & 0x7fff]; -+ } -+ -+ /* Always initialize TLS descriptors completely, because lazy -+ initialization requires synchronization at every TLS access. */ -+ elf_machine_rela (map, reloc, sym, version, reloc_addr, skip_ifunc); - } - else if (__glibc_unlikely (r_type == R_AARCH64_IRELATIVE)) - { diff --git a/SOURCES/glibc-rh1662842.patch b/SOURCES/glibc-rh1662842.patch new file mode 100644 index 0000000..58be2be --- /dev/null +++ b/SOURCES/glibc-rh1662842.patch @@ -0,0 +1,68 @@ +commit b50dd3bc8cbb1efe85399b03d7e6c0310c2ead84 +Author: Florian Weimer <fw@deneb.enyo.de> +Date: Mon Dec 31 22:04:36 2018 +0100 + + malloc: Always call memcpy in _int_realloc [BZ #24027] + + This commit removes the custom memcpy implementation from _int_realloc + for small chunk sizes. The ncopies variable has the wrong type, and + an integer wraparound could cause the existing code to copy too few + elements (leaving the new memory region mostly uninitialized). + Therefore, removing this code fixes bug 24027. + +diff -rup a/malloc/malloc.c b/malloc/malloc.c +--- a/malloc/malloc.c 2019-03-26 14:12:59.364333388 -0400 ++++ b/malloc/malloc.c 2019-03-26 14:17:17.373475418 -0400 +@@ -4214,11 +4214,6 @@ _int_realloc(mstate av, mchunkptr oldp, + mchunkptr bck; /* misc temp for linking */ + mchunkptr fwd; /* misc temp for linking */ + +- unsigned long copysize; /* bytes to copy */ +- unsigned int ncopies; /* INTERNAL_SIZE_T words to copy */ +- INTERNAL_SIZE_T* s; /* copy source */ +- INTERNAL_SIZE_T* d; /* copy destination */ +- + const char *errstr = NULL; + + /* oldmem size */ +@@ -4291,39 +4286,7 @@ _int_realloc(mstate av, mchunkptr oldp, + newp = oldp; + } + else { +- /* +- Unroll copy of <= 36 bytes (72 if 8byte sizes) +- We know that contents have an odd number of +- INTERNAL_SIZE_T-sized words; minimally 3. +- */ +- +- copysize = oldsize - SIZE_SZ; +- s = (INTERNAL_SIZE_T*)(chunk2mem(oldp)); +- d = (INTERNAL_SIZE_T*)(newmem); +- ncopies = copysize / sizeof(INTERNAL_SIZE_T); +- assert(ncopies >= 3); +- +- if (ncopies > 9) +- MALLOC_COPY(d, s, copysize); +- +- else { +- *(d+0) = *(s+0); +- *(d+1) = *(s+1); +- *(d+2) = *(s+2); +- if (ncopies > 4) { +- *(d+3) = *(s+3); +- *(d+4) = *(s+4); +- if (ncopies > 6) { +- *(d+5) = *(s+5); +- *(d+6) = *(s+6); +- if (ncopies > 8) { +- *(d+7) = *(s+7); +- *(d+8) = *(s+8); +- } +- } +- } +- } +- ++ memcpy (newmem, chunk2mem (oldp), oldsize - SIZE_SZ); + _int_free(av, oldp, 1); + check_inuse_chunk(av, newp); + return chunk2mem(newp); diff --git a/SOURCES/glibc-rh1673465-1.patch b/SOURCES/glibc-rh1673465-1.patch new file mode 100644 index 0000000..b548f3c --- /dev/null +++ b/SOURCES/glibc-rh1673465-1.patch @@ -0,0 +1,48 @@ +commit c94a5688fb1228a862b2d4a3f1239cdc0e3349e5 +Author: Florian Weimer <fweimer@redhat.com> +Date: Thu Nov 2 12:14:01 2017 +0100 + + <array_length.h>: New array_length and array_end macros + +diff --git a/include/array_length.h b/include/array_length.h +new file mode 100644 +index 0000000000000000..cb4a8b2a56bca3ad +--- /dev/null ++++ b/include/array_length.h +@@ -0,0 +1,36 @@ ++/* The array_length and array_end macros. ++ 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 ++ <http://www.gnu.org/licenses/>. */ ++ ++#ifndef _ARRAY_LENGTH_H ++#define _ARRAY_LENGTH_H ++ ++/* array_length (VAR) is the number of elements in the array VAR. VAR ++ must evaluate to an array, not a pointer. */ ++#define array_length(var) \ ++ __extension__ ({ \ ++ _Static_assert (!__builtin_types_compatible_p \ ++ (__typeof (var), __typeof (&(var)[0])), \ ++ "argument must be an array"); \ ++ sizeof (var) / sizeof ((var)[0]); \ ++ }) ++ ++/* array_end (VAR) is a pointer one past the end of the array VAR. ++ VAR must evaluate to an array, not a pointer. */ ++#define array_end(var) (&(var)[array_length (var)]) ++ ++#endif /* _ARRAY_LENGTH_H */ diff --git a/SOURCES/glibc-rh1673465-2.patch b/SOURCES/glibc-rh1673465-2.patch new file mode 100644 index 0000000..5c4cbab --- /dev/null +++ b/SOURCES/glibc-rh1673465-2.patch @@ -0,0 +1,34 @@ +commit 8311c83f91a3127ccd2fe684e25bc60c5178d23b +Author: Florian Weimer <fweimer@redhat.com> +Date: Thu Feb 7 09:03:02 2019 +0100 + + array_length: Make usable as a constant expression + + Do not use a statement expression in array_length, so that + array_length can be used at file scope and as a constant expression. + Instead, put the _Static_assert into a struct (as a declaration), + and nest this in the expression using a sizeof expression. + +diff --git a/include/array_length.h b/include/array_length.h +index cb4a8b2a56bca3ad..ccb253c1dc1641cf 100644 +--- a/include/array_length.h ++++ b/include/array_length.h +@@ -22,12 +22,12 @@ + /* array_length (VAR) is the number of elements in the array VAR. VAR + must evaluate to an array, not a pointer. */ + #define array_length(var) \ +- __extension__ ({ \ +- _Static_assert (!__builtin_types_compatible_p \ +- (__typeof (var), __typeof (&(var)[0])), \ +- "argument must be an array"); \ +- sizeof (var) / sizeof ((var)[0]); \ +- }) ++ (sizeof (var) / sizeof ((var)[0]) \ ++ + 0 * sizeof (struct { \ ++ _Static_assert (!__builtin_types_compatible_p \ ++ (__typeof (var), __typeof (&(var)[0])), \ ++ "argument must be an array"); \ ++ })) + + /* array_end (VAR) is a pointer one past the end of the array VAR. + VAR must evaluate to an array, not a pointer. */ diff --git a/SOURCES/glibc-rh1673465-3.patch b/SOURCES/glibc-rh1673465-3.patch new file mode 100644 index 0000000..5e8faa2 --- /dev/null +++ b/SOURCES/glibc-rh1673465-3.patch @@ -0,0 +1,142 @@ +commit c74a91deaa5de416237c02bbb3e41bda76ca4c7b +Author: Florian Weimer <fweimer@redhat.com> +Date: Tue Nov 27 21:35:56 2018 +0100 + + support: Implement support_quote_string + + Reviewed-by: Jonathan Nieder <jrnieder@gmail.com> + +diff --git a/support/Makefile b/support/Makefile +index 2b663fbbfa334ea2..a2536980d1d5a89b 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -58,6 +58,7 @@ libsupport-routines = \ + support_openpty \ + support_paths \ + support_quote_blob \ ++ support_quote_string \ + support_record_failure \ + support_run_diff \ + support_shared_allocate \ +@@ -196,6 +197,7 @@ tests = \ + tst-support_capture_subprocess \ + tst-support_format_dns_packet \ + tst-support_quote_blob \ ++ tst-support_quote_string \ + tst-support_record_failure \ + tst-test_compare \ + tst-test_compare_blob \ +diff --git a/support/support.h b/support/support.h +index 9418cd11ef6e684d..835e7173eb566355 100644 +--- a/support/support.h ++++ b/support/support.h +@@ -69,6 +69,11 @@ void support_write_file_string (const char *path, const char *contents); + the result). */ + char *support_quote_blob (const void *blob, size_t length); + ++/* Quote the contents of the at STR, in such a way that the result ++ string can be included in a C literal (in single/double quotes, ++ without putting the quotes into the result). */ ++char *support_quote_string (const char *str); ++ + /* Returns non-zero if the file descriptor is a regular file on a file + system which supports holes (that is, seeking and writing does not + allocate storage for the range of zeros). FD must refer to a +diff --git a/support/support_quote_string.c b/support/support_quote_string.c +new file mode 100644 +index 0000000000000000..d324371b133a4d66 +--- /dev/null ++++ b/support/support_quote_string.c +@@ -0,0 +1,26 @@ ++/* Quote a string so that it can be used in C literals. ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <string.h> ++#include <support/support.h> ++ ++char * ++support_quote_string (const char *str) ++{ ++ return support_quote_blob (str, strlen (str)); ++} +diff --git a/support/tst-support_quote_string.c b/support/tst-support_quote_string.c +new file mode 100644 +index 0000000000000000..3c004759b76e21d7 +--- /dev/null ++++ b/support/tst-support_quote_string.c +@@ -0,0 +1,60 @@ ++/* Test the support_quote_string function. ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <support/check.h> ++#include <support/support.h> ++#include <string.h> ++#include <stdlib.h> ++ ++static int ++do_test (void) ++{ ++ char *p = support_quote_string (""); ++ TEST_COMPARE (strlen (p), 0); ++ free (p); ++ p = support_quote_string ("X"); ++ TEST_COMPARE (strlen (p), 1); ++ TEST_COMPARE (p[0], 'X'); ++ free (p); ++ ++ /* Check escaping of backslash-escaped characters, and lack of ++ escaping for other shell meta-characters. */ ++ p = support_quote_string ("$()*?`@[]{}~\'\"X"); ++ TEST_COMPARE (strcmp (p, "$()*?`@[]{}~\\'\\\"X"), 0); ++ free (p); ++ ++ /* Check lack of escaping for letters and digits. */ ++#define LETTERS_AND_DIGTS \ ++ "abcdefghijklmnopqrstuvwxyz" \ ++ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ ++ "0123456789" ++ p = support_quote_string (LETTERS_AND_DIGTS "@"); ++ TEST_COMPARE (strcmp (p, LETTERS_AND_DIGTS "@"), 0); ++ free (p); ++ ++ /* Check escaping of control characters and other non-printable ++ characters. */ ++ p = support_quote_string ("\r\n\t\a\b\f\v\1\177\200\377@"); ++ TEST_COMPARE (strcmp (p, "\\r\\n\\t\\a\\b\\f\\v\\001" ++ "\\177\\200\\377@"), 0); ++ free (p); ++ ++ return 0; ++} ++ ++#include <support/test-driver.c> diff --git a/SOURCES/glibc-rh1673465-4.patch b/SOURCES/glibc-rh1673465-4.patch new file mode 100644 index 0000000..5842b08 --- /dev/null +++ b/SOURCES/glibc-rh1673465-4.patch @@ -0,0 +1,221 @@ +commit 5e30b8ef0758763effa115634e0ed7d8938e4bc0 +Author: Florian Weimer <fweimer@redhat.com> +Date: Mon Jan 21 08:59:42 2019 +0100 + + resolv: Reformat inet_addr, inet_aton to GNU style + +diff --git a/resolv/inet_addr.c b/resolv/inet_addr.c +index 022f7ea0841b6bae..32f58b0e13598b32 100644 +--- a/resolv/inet_addr.c ++++ b/resolv/inet_addr.c +@@ -1,3 +1,21 @@ ++/* Legacy IPv4 text-to-address functions. ++ Copyright (C) 2019 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 ++ <http://www.gnu.org/licenses/>. */ ++ + /* + * Copyright (c) 1983, 1990, 1993 + * The Regents of the University of California. All rights reserved. +@@ -78,105 +96,97 @@ + #include <limits.h> + #include <errno.h> + +-/* +- * Ascii internet address interpretation routine. +- * The value returned is in network order. +- */ ++/* ASCII IPv4 Internet address interpretation routine. The value ++ returned is in network order. */ + in_addr_t +-__inet_addr(const char *cp) { +- struct in_addr val; ++__inet_addr (const char *cp) ++{ ++ struct in_addr val; + +- if (__inet_aton(cp, &val)) +- return (val.s_addr); +- return (INADDR_NONE); ++ if (__inet_aton (cp, &val)) ++ return val.s_addr; ++ return INADDR_NONE; + } + weak_alias (__inet_addr, inet_addr) + +-/* +- * Check whether "cp" is a valid ascii representation +- * of an Internet address and convert to a binary address. +- * Returns 1 if the address is valid, 0 if not. +- * This replaces inet_addr, the return value from which +- * cannot distinguish between failure and a local broadcast address. +- */ ++/* Check whether "cp" is a valid ASCII representation of an IPv4 ++ Internet address and convert it to a binary address. Returns 1 if ++ the address is valid, 0 if not. This replaces inet_addr, the ++ return value from which cannot distinguish between failure and a ++ local broadcast address. */ + int +-__inet_aton(const char *cp, struct in_addr *addr) ++__inet_aton (const char *cp, struct in_addr *addr) + { +- static const in_addr_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff }; +- in_addr_t val; +- char c; +- union iaddr { +- uint8_t bytes[4]; +- uint32_t word; +- } res; +- uint8_t *pp = res.bytes; +- int digit; +- +- int saved_errno = errno; +- __set_errno (0); +- +- res.word = 0; +- +- c = *cp; +- for (;;) { +- /* +- * Collect number up to ``.''. +- * Values are specified as for C: +- * 0x=hex, 0=octal, isdigit=decimal. +- */ +- if (!isdigit(c)) +- goto ret_0; +- { +- char *endp; +- unsigned long ul = strtoul (cp, (char **) &endp, 0); +- if (ul == ULONG_MAX && errno == ERANGE) +- goto ret_0; +- if (ul > 0xfffffffful) +- goto ret_0; +- val = ul; +- digit = cp != endp; +- cp = endp; +- } +- c = *cp; +- if (c == '.') { +- /* +- * Internet format: +- * a.b.c.d +- * a.b.c (with c treated as 16 bits) +- * a.b (with b treated as 24 bits) +- */ +- if (pp > res.bytes + 2 || val > 0xff) +- goto ret_0; +- *pp++ = val; +- c = *++cp; +- } else +- break; +- } +- /* +- * Check for trailing characters. +- */ +- if (c != '\0' && (!isascii(c) || !isspace(c))) +- goto ret_0; +- /* +- * Did we get a valid digit? +- */ +- if (!digit) +- goto ret_0; +- +- /* Check whether the last part is in its limits depending on +- the number of parts in total. */ +- if (val > max[pp - res.bytes]) ++ static const in_addr_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff }; ++ in_addr_t val; ++ char c; ++ union iaddr ++ { ++ uint8_t bytes[4]; ++ uint32_t word; ++ } res; ++ uint8_t *pp = res.bytes; ++ int digit; ++ ++ int saved_errno = errno; ++ __set_errno (0); ++ ++ res.word = 0; ++ ++ c = *cp; ++ for (;;) ++ { ++ /* Collect number up to ``.''. Values are specified as for C: ++ 0x=hex, 0=octal, isdigit=decimal. */ ++ if (!isdigit (c)) ++ goto ret_0; ++ { ++ char *endp; ++ unsigned long ul = strtoul (cp, &endp, 0); ++ if (ul == ULONG_MAX && errno == ERANGE) + goto ret_0; +- +- if (addr != NULL) +- addr->s_addr = res.word | htonl (val); +- +- __set_errno (saved_errno); +- return (1); +- +-ret_0: +- __set_errno (saved_errno); +- return (0); ++ if (ul > 0xfffffffful) ++ goto ret_0; ++ val = ul; ++ digit = cp != endp; ++ cp = endp; ++ } ++ c = *cp; ++ if (c == '.') ++ { ++ /* Internet format: ++ a.b.c.d ++ a.b.c (with c treated as 16 bits) ++ a.b (with b treated as 24 bits). */ ++ if (pp > res.bytes + 2 || val > 0xff) ++ goto ret_0; ++ *pp++ = val; ++ c = *++cp; ++ } ++ else ++ break; ++ } ++ /* Check for trailing characters. */ ++ if (c != '\0' && (!isascii (c) || !isspace (c))) ++ goto ret_0; ++ /* Did we get a valid digit? */ ++ if (!digit) ++ goto ret_0; ++ ++ /* Check whether the last part is in its limits depending on the ++ number of parts in total. */ ++ if (val > max[pp - res.bytes]) ++ goto ret_0; ++ ++ if (addr != NULL) ++ addr->s_addr = res.word | htonl (val); ++ ++ __set_errno (saved_errno); ++ return 1; ++ ++ ret_0: ++ __set_errno (saved_errno); ++ return 0; + } + weak_alias (__inet_aton, inet_aton) + libc_hidden_def (__inet_aton) diff --git a/SOURCES/glibc-rh1673465-5.patch b/SOURCES/glibc-rh1673465-5.patch new file mode 100644 index 0000000..6177dd1 --- /dev/null +++ b/SOURCES/glibc-rh1673465-5.patch @@ -0,0 +1,80 @@ +commit 6ca53a2453598804a2559a548a08424fca96434a +Author: Florian Weimer <fweimer@redhat.com> +Date: Mon Jan 21 09:26:41 2019 +0100 + + resolv: Do not send queries for non-host-names in nss_dns [BZ #24112] + + Before this commit, nss_dns would send a query which did not contain a + host name as the query name (such as invalid\032name.example.com) and + then reject the answer in getanswer_r and gaih_getanswer_slice, using + a check based on res_hnok. With this commit, no query is sent, and a + host-not-found error is returned to NSS without network interaction. + +diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c +index 1e85e4f08ffc8600..e697d9103797341b 100644 +--- a/resolv/nss_dns/dns-host.c ++++ b/resolv/nss_dns/dns-host.c +@@ -273,11 +273,26 @@ gethostbyname3_context (struct resolv_context *ctx, + return status; + } + ++/* Verify that the name looks like a host name. There is no point in ++ sending a query which will not produce a usable name in the ++ response. */ ++static enum nss_status ++check_name (const char *name, int *h_errnop) ++{ ++ if (res_hnok (name)) ++ return NSS_STATUS_SUCCESS; ++ *h_errnop = HOST_NOT_FOUND; ++ return NSS_STATUS_NOTFOUND; ++} ++ + enum nss_status + _nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result, + char *buffer, size_t buflen, int *errnop, + int *h_errnop) + { ++ enum nss_status status = check_name (name, h_errnop); ++ if (status != NSS_STATUS_SUCCESS) ++ return status; + return _nss_dns_gethostbyname3_r (name, af, result, buffer, buflen, errnop, + h_errnop, NULL, NULL); + } +@@ -288,6 +303,9 @@ _nss_dns_gethostbyname_r (const char *name, struct hostent *result, + char *buffer, size_t buflen, int *errnop, + int *h_errnop) + { ++ enum nss_status status = check_name (name, h_errnop); ++ if (status != NSS_STATUS_SUCCESS) ++ return status; + struct resolv_context *ctx = __resolv_context_get (); + if (ctx == NULL) + { +@@ -295,7 +313,7 @@ _nss_dns_gethostbyname_r (const char *name, struct hostent *result, + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_UNAVAIL; + } +- enum nss_status status = NSS_STATUS_NOTFOUND; ++ status = NSS_STATUS_NOTFOUND; + if (res_use_inet6 ()) + status = gethostbyname3_context (ctx, name, AF_INET6, result, buffer, + buflen, errnop, h_errnop, NULL, NULL); +@@ -312,6 +330,9 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, + char *buffer, size_t buflen, int *errnop, + int *herrnop, int32_t *ttlp) + { ++ enum nss_status status = check_name (name, herrnop); ++ if (status != NSS_STATUS_SUCCESS) ++ return status; + struct resolv_context *ctx = __resolv_context_get (); + if (ctx == NULL) + { +@@ -346,7 +367,6 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, + int ans2p_malloced = 0; + + int olderr = errno; +- enum nss_status status; + int n = __res_context_search (ctx, name, C_IN, T_QUERY_A_AND_AAAA, + host_buffer.buf->buf, 2048, &host_buffer.ptr, + &ans2p, &nans2p, &resplen2, &ans2p_malloced); diff --git a/SOURCES/glibc-rh1673465-6.patch b/SOURCES/glibc-rh1673465-6.patch new file mode 100644 index 0000000..78aa0c8 --- /dev/null +++ b/SOURCES/glibc-rh1673465-6.patch @@ -0,0 +1,698 @@ +commit 108bc4049f8ae82710aec26a92ffdb4b439c83fd +Author: Florian Weimer <fweimer@redhat.com> +Date: Mon Jan 21 21:26:03 2019 +0100 + + CVE-2016-10739: getaddrinfo: Fully parse IPv4 address strings [BZ #20018] + + The IPv4 address parser in the getaddrinfo function is changed so that + it does not ignore trailing whitespace and all characters after it. + For backwards compatibility, the getaddrinfo function still recognizes + legacy name syntax, such as 192.000.002.010 interpreted as 192.0.2.8 + (octal). + + This commit does not change the behavior of inet_addr and inet_aton. + gethostbyname already had additional sanity checks (but is switched + over to the new __inet_aton_exact function for completeness as well). + + To avoid sending the problematic query names over DNS, commit + 6ca53a2453598804a2559a548a08424fca96434a ("resolv: Do not send queries + for non-host-names in nss_dns [BZ #24112]") is needed. + +diff --git a/include/arpa/inet.h b/include/arpa/inet.h +index c3f28f2baaa2ed66..19aec74275069a45 100644 +--- a/include/arpa/inet.h ++++ b/include/arpa/inet.h +@@ -1,10 +1,10 @@ + #include <inet/arpa/inet.h> + + #ifndef _ISOMAC +-extern int __inet_aton (const char *__cp, struct in_addr *__inp); +-libc_hidden_proto (__inet_aton) ++/* Variant of inet_aton which rejects trailing garbage. */ ++extern int __inet_aton_exact (const char *__cp, struct in_addr *__inp); ++libc_hidden_proto (__inet_aton_exact) + +-libc_hidden_proto (inet_aton) + libc_hidden_proto (inet_ntop) + libc_hidden_proto (inet_pton) + extern __typeof (inet_pton) __inet_pton; +diff --git a/nscd/gai.c b/nscd/gai.c +index 018b449339813df5..dbe878fcf699dbc1 100644 +--- a/nscd/gai.c ++++ b/nscd/gai.c +@@ -20,7 +20,6 @@ + + /* This file uses the getaddrinfo code but it compiles it without NSCD + support. We just need a few symbol renames. */ +-#define __inet_aton inet_aton + #define __ioctl ioctl + #define __getsockname getsockname + #define __socket socket +diff --git a/nscd/gethstbynm3_r.c b/nscd/gethstbynm3_r.c +index 2ab75e469eca1589..958a12d063f1e3e6 100644 +--- a/nscd/gethstbynm3_r.c ++++ b/nscd/gethstbynm3_r.c +@@ -38,8 +38,6 @@ + #define HAVE_LOOKUP_BUFFER 1 + #define HAVE_AF 1 + +-#define __inet_aton inet_aton +- + /* We are nscd, so we don't want to be talking to ourselves. */ + #undef USE_NSCD + +diff --git a/nss/digits_dots.c b/nss/digits_dots.c +index 0c1fa97e3977a81e..5f7e5b5fb120c387 100644 +--- a/nss/digits_dots.c ++++ b/nss/digits_dots.c +@@ -29,7 +29,6 @@ + #include "nsswitch.h" + + #ifdef USE_NSCD +-# define inet_aton __inet_aton + # include <nscd/nscd_proto.h> + #endif + +@@ -160,7 +159,7 @@ __nss_hostname_digits_dots_context (struct resolv_context *ctx, + 255.255.255.255? The test below will succeed + spuriously... ??? */ + if (af == AF_INET) +- ok = __inet_aton (name, (struct in_addr *) host_addr); ++ ok = __inet_aton_exact (name, (struct in_addr *) host_addr); + else + { + assert (af == AF_INET6); +diff --git a/resolv/Makefile b/resolv/Makefile +index 1124897ce5f9610b..988871086a70b291 100644 +--- a/resolv/Makefile ++++ b/resolv/Makefile +@@ -34,6 +34,9 @@ routines := herror inet_addr inet_ntop inet_pton nsap_addr res_init \ + tests = tst-aton tst-leaks tst-inet_ntop + xtests = tst-leaks2 + ++tests-internal += tst-inet_aton_exact ++ ++ + generate := mtrace-tst-leaks.out tst-leaks.mtrace tst-leaks2.mtrace + + extra-libs := libresolv libnss_dns +@@ -51,8 +54,10 @@ tests += \ + tst-resolv-basic \ + tst-resolv-edns \ + tst-resolv-network \ ++ tst-resolv-nondecimal \ + tst-resolv-res_init-multi \ + tst-resolv-search \ ++ tst-resolv-trailing \ + + # These tests need libdl. + ifeq (yes,$(build-shared)) +@@ -164,9 +169,11 @@ $(objpfx)tst-resolv-res_init-multi: $(objpfx)libresolv.so \ + $(shared-thread-library) + $(objpfx)tst-resolv-res_init-thread: $(libdl) $(objpfx)libresolv.so \ + $(shared-thread-library) ++$(objpfx)tst-resolv-nondecimal: $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-rotate: $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-search: $(objpfx)libresolv.so $(shared-thread-library) ++$(objpfx)tst-resolv-trailing: $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-threads: \ + $(libdl) $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-canonname: \ +diff --git a/resolv/Versions b/resolv/Versions +index b05778d9654aa0f2..9a82704af75f789b 100644 +--- a/resolv/Versions ++++ b/resolv/Versions +@@ -27,6 +27,7 @@ libc { + __h_errno; __resp; + + __res_iclose; ++ __inet_aton_exact; + __inet_pton_length; + __resolv_context_get; + __resolv_context_get_preinit; +diff --git a/resolv/inet_addr.c b/resolv/inet_addr.c +index 32f58b0e13598b32..41b6166a5bd5a44b 100644 +--- a/resolv/inet_addr.c ++++ b/resolv/inet_addr.c +@@ -96,26 +96,14 @@ + #include <limits.h> + #include <errno.h> + +-/* ASCII IPv4 Internet address interpretation routine. The value +- returned is in network order. */ +-in_addr_t +-__inet_addr (const char *cp) +-{ +- struct in_addr val; +- +- if (__inet_aton (cp, &val)) +- return val.s_addr; +- return INADDR_NONE; +-} +-weak_alias (__inet_addr, inet_addr) +- + /* Check whether "cp" is a valid ASCII representation of an IPv4 + Internet address and convert it to a binary address. Returns 1 if + the address is valid, 0 if not. This replaces inet_addr, the + return value from which cannot distinguish between failure and a +- local broadcast address. */ +-int +-__inet_aton (const char *cp, struct in_addr *addr) ++ local broadcast address. Write a pointer to the first ++ non-converted character to *endp. */ ++static int ++inet_aton_end (const char *cp, struct in_addr *addr, const char **endp) + { + static const in_addr_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff }; + in_addr_t val; +@@ -180,6 +168,7 @@ __inet_aton (const char *cp, struct in_addr *addr) + + if (addr != NULL) + addr->s_addr = res.word | htonl (val); ++ *endp = cp; + + __set_errno (saved_errno); + return 1; +@@ -188,6 +177,41 @@ __inet_aton (const char *cp, struct in_addr *addr) + __set_errno (saved_errno); + return 0; + } +-weak_alias (__inet_aton, inet_aton) +-libc_hidden_def (__inet_aton) +-libc_hidden_weak (inet_aton) ++ ++int ++__inet_aton_exact (const char *cp, struct in_addr *addr) ++{ ++ struct in_addr val; ++ const char *endp; ++ /* Check that inet_aton_end parsed the entire string. */ ++ if (inet_aton_end (cp, &val, &endp) != 0 && *endp == 0) ++ { ++ *addr = val; ++ return 1; ++ } ++ else ++ return 0; ++} ++libc_hidden_def (__inet_aton_exact) ++ ++/* inet_aton ignores trailing garbage. */ ++int ++__inet_aton_ignore_trailing (const char *cp, struct in_addr *addr) ++{ ++ const char *endp; ++ return inet_aton_end (cp, addr, &endp); ++} ++weak_alias (__inet_aton_ignore_trailing, inet_aton) ++ ++/* ASCII IPv4 Internet address interpretation routine. The value ++ returned is in network order. */ ++in_addr_t ++__inet_addr (const char *cp) ++{ ++ struct in_addr val; ++ const char *endp; ++ if (inet_aton_end (cp, &val, &endp)) ++ return val.s_addr; ++ return INADDR_NONE; ++} ++weak_alias (__inet_addr, inet_addr) +diff --git a/resolv/res_init.c b/resolv/res_init.c +index c29bc4e9b99b6bee..9ea9c01d1029ba5f 100644 +--- a/resolv/res_init.c ++++ b/resolv/res_init.c +@@ -399,8 +399,16 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser) + cp = parser->buffer + sizeof ("nameserver") - 1; + while (*cp == ' ' || *cp == '\t') + cp++; ++ ++ /* Ignore trailing contents on the name server line. */ ++ { ++ char *el; ++ if ((el = strpbrk (cp, " \t\n")) != NULL) ++ *el = '\0'; ++ } ++ + struct sockaddr *sa; +- if ((*cp != '\0') && (*cp != '\n') && __inet_aton (cp, &a)) ++ if ((*cp != '\0') && (*cp != '\n') && __inet_aton_exact (cp, &a)) + { + sa = allocate_address_v4 (a, NAMESERVER_PORT); + if (sa == NULL) +@@ -410,9 +418,6 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser) + { + struct in6_addr a6; + char *el; +- +- if ((el = strpbrk (cp, " \t\n")) != NULL) +- *el = '\0'; + if ((el = strchr (cp, SCOPE_DELIMITER)) != NULL) + *el = '\0'; + if ((*cp != '\0') && (__inet_pton (AF_INET6, cp, &a6) > 0)) +@@ -472,7 +477,7 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser) + char separator = *cp; + *cp = 0; + struct resolv_sortlist_entry e; +- if (__inet_aton (net, &a)) ++ if (__inet_aton_exact (net, &a)) + { + e.addr = a; + if (is_sort_mask (separator)) +@@ -484,7 +489,7 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser) + cp++; + separator = *cp; + *cp = 0; +- if (__inet_aton (net, &a)) ++ if (__inet_aton_exact (net, &a)) + e.mask = a.s_addr; + else + e.mask = net_mask (e.addr); +diff --git a/resolv/tst-aton.c b/resolv/tst-aton.c +index 08110a007af909ff..eb734d7758d6ed87 100644 +--- a/resolv/tst-aton.c ++++ b/resolv/tst-aton.c +@@ -1,11 +1,29 @@ ++/* Test legacy IPv4 text-to-address function inet_aton. ++ Copyright (C) 1998-2019 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 ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <array_length.h> + #include <stdio.h> + #include <stdint.h> + #include <sys/socket.h> + #include <netinet/in.h> + #include <arpa/inet.h> + +- +-static struct tests ++static const struct tests + { + const char *input; + int valid; +@@ -16,6 +34,7 @@ static struct tests + { "-1", 0, 0 }, + { "256", 1, 0x00000100 }, + { "256.", 0, 0 }, ++ { "255a", 0, 0 }, + { "256a", 0, 0 }, + { "0x100", 1, 0x00000100 }, + { "0200.0x123456", 1, 0x80123456 }, +@@ -40,7 +59,12 @@ static struct tests + { "1.2.256.4", 0, 0 }, + { "1.2.3.0x100", 0, 0 }, + { "323543357756889", 0, 0 }, +- { "10.1.2.3.4", 0, 0}, ++ { "10.1.2.3.4", 0, 0 }, ++ { "192.0.2.1", 1, 0xc0000201 }, ++ { "192.0.2.2\nX", 1, 0xc0000202 }, ++ { "192.0.2.3 Y", 1, 0xc0000203 }, ++ { "192.0.2.3Z", 0, 0 }, ++ { "192.000.002.010", 1, 0xc0000208 }, + }; + + +@@ -50,7 +74,7 @@ do_test (void) + int result = 0; + size_t cnt; + +- for (cnt = 0; cnt < sizeof (tests) / sizeof (tests[0]); ++cnt) ++ for (cnt = 0; cnt < array_length (tests); ++cnt) + { + struct in_addr addr; + +@@ -73,5 +97,4 @@ do_test (void) + return result; + } + +-#define TEST_FUNCTION do_test () +-#include "../test-skeleton.c" ++#include <support/test-driver.c> +diff --git a/resolv/tst-inet_aton_exact.c b/resolv/tst-inet_aton_exact.c +new file mode 100644 +index 0000000000000000..0fdfa3d6aa9aef91 +--- /dev/null ++++ b/resolv/tst-inet_aton_exact.c +@@ -0,0 +1,47 @@ ++/* Test internal legacy IPv4 text-to-address function __inet_aton_exact. ++ Copyright (C) 2019 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 ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <arpa/inet.h> ++#include <support/check.h> ++ ++static int ++do_test (void) ++{ ++ struct in_addr addr = { }; ++ ++ TEST_COMPARE (__inet_aton_exact ("192.0.2.1", &addr), 1); ++ TEST_COMPARE (ntohl (addr.s_addr), 0xC0000201); ++ ++ TEST_COMPARE (__inet_aton_exact ("192.000.002.010", &addr), 1); ++ TEST_COMPARE (ntohl (addr.s_addr), 0xC0000208); ++ TEST_COMPARE (__inet_aton_exact ("0xC0000234", &addr), 1); ++ TEST_COMPARE (ntohl (addr.s_addr), 0xC0000234); ++ ++ /* Trailing content is not accepted. */ ++ TEST_COMPARE (__inet_aton_exact ("192.0.2.2X", &addr), 0); ++ TEST_COMPARE (__inet_aton_exact ("192.0.2.3 Y", &addr), 0); ++ TEST_COMPARE (__inet_aton_exact ("192.0.2.4\nZ", &addr), 0); ++ TEST_COMPARE (__inet_aton_exact ("192.0.2.5\tT", &addr), 0); ++ TEST_COMPARE (__inet_aton_exact ("192.0.2.6 Y", &addr), 0); ++ TEST_COMPARE (__inet_aton_exact ("192.0.2.7\n", &addr), 0); ++ TEST_COMPARE (__inet_aton_exact ("192.0.2.8\t", &addr), 0); ++ ++ return 0; ++} ++ ++#include <support/test-driver.c> +diff --git a/resolv/tst-resolv-nondecimal.c b/resolv/tst-resolv-nondecimal.c +new file mode 100644 +index 0000000000000000..a0df6f332ae8faf7 +--- /dev/null ++++ b/resolv/tst-resolv-nondecimal.c +@@ -0,0 +1,139 @@ ++/* Test name resolution behavior for octal, hexadecimal IPv4 addresses. ++ Copyright (C) 2019 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 ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <netdb.h> ++#include <stdlib.h> ++#include <support/check.h> ++#include <support/check_nss.h> ++#include <support/resolv_test.h> ++#include <support/support.h> ++ ++static void ++response (const struct resolv_response_context *ctx, ++ struct resolv_response_builder *b, ++ const char *qname, uint16_t qclass, uint16_t qtype) ++{ ++ /* The tests are not supposed send any DNS queries. */ ++ FAIL_EXIT1 ("unexpected DNS query for %s/%d/%d", qname, qclass, qtype); ++} ++ ++static void ++run_query_addrinfo (const char *query, const char *address) ++{ ++ char *quoted_query = support_quote_string (query); ++ ++ struct addrinfo *ai; ++ struct addrinfo hints = ++ { ++ .ai_socktype = SOCK_STREAM, ++ .ai_protocol = IPPROTO_TCP, ++ }; ++ ++ char *context = xasprintf ("getaddrinfo \"%s\" AF_INET", quoted_query); ++ char *expected = xasprintf ("address: STREAM/TCP %s 80\n", address); ++ hints.ai_family = AF_INET; ++ int ret = getaddrinfo (query, "80", &hints, &ai); ++ check_addrinfo (context, ai, ret, expected); ++ if (ret == 0) ++ freeaddrinfo (ai); ++ free (context); ++ ++ context = xasprintf ("getaddrinfo \"%s\" AF_UNSPEC", quoted_query); ++ hints.ai_family = AF_UNSPEC; ++ ret = getaddrinfo (query, "80", &hints, &ai); ++ check_addrinfo (context, ai, ret, expected); ++ if (ret == 0) ++ freeaddrinfo (ai); ++ free (expected); ++ free (context); ++ ++ context = xasprintf ("getaddrinfo \"%s\" AF_INET6", quoted_query); ++ expected = xasprintf ("flags: AI_V4MAPPED\n" ++ "address: STREAM/TCP ::ffff:%s 80\n", ++ address); ++ hints.ai_family = AF_INET6; ++ hints.ai_flags = AI_V4MAPPED; ++ ret = getaddrinfo (query, "80", &hints, &ai); ++ check_addrinfo (context, ai, ret, expected); ++ if (ret == 0) ++ freeaddrinfo (ai); ++ free (expected); ++ free (context); ++ ++ free (quoted_query); ++} ++ ++static void ++run_query (const char *query, const char *address) ++{ ++ char *quoted_query = support_quote_string (query); ++ char *context = xasprintf ("gethostbyname (\"%s\")", quoted_query); ++ char *expected = xasprintf ("name: %s\n" ++ "address: %s\n", query, address); ++ check_hostent (context, gethostbyname (query), expected); ++ free (context); ++ ++ context = xasprintf ("gethostbyname_r \"%s\"", quoted_query); ++ struct hostent storage; ++ char buf[4096]; ++ struct hostent *e = NULL; ++ TEST_COMPARE (gethostbyname_r (query, &storage, buf, sizeof (buf), ++ &e, &h_errno), 0); ++ check_hostent (context, e, expected); ++ free (context); ++ ++ context = xasprintf ("gethostbyname2 (\"%s\", AF_INET)", quoted_query); ++ check_hostent (context, gethostbyname2 (query, AF_INET), expected); ++ free (context); ++ ++ context = xasprintf ("gethostbyname2_r \"%s\" AF_INET", quoted_query); ++ e = NULL; ++ TEST_COMPARE (gethostbyname2_r (query, AF_INET, &storage, buf, sizeof (buf), ++ &e, &h_errno), 0); ++ check_hostent (context, e, expected); ++ free (context); ++ free (expected); ++ ++ free (quoted_query); ++ ++ /* The gethostbyname tests are always valid for getaddrinfo, but not ++ vice versa. */ ++ run_query_addrinfo (query, address); ++} ++ ++static int ++do_test (void) ++{ ++ struct resolv_test *aux = resolv_test_start ++ ((struct resolv_redirect_config) ++ { ++ .response_callback = response, ++ }); ++ ++ run_query ("192.000.002.010", "192.0.2.8"); ++ ++ /* Hexadecimal numbers are not accepted by gethostbyname. */ ++ run_query_addrinfo ("0xc0000210", "192.0.2.16"); ++ run_query_addrinfo ("192.0x234", "192.0.2.52"); ++ ++ resolv_test_end (aux); ++ ++ return 0; ++} ++ ++#include <support/test-driver.c> +diff --git a/resolv/tst-resolv-trailing.c b/resolv/tst-resolv-trailing.c +new file mode 100644 +index 0000000000000000..7504bdae572ed8d0 +--- /dev/null ++++ b/resolv/tst-resolv-trailing.c +@@ -0,0 +1,136 @@ ++/* Test name resolution behavior with trailing characters. ++ Copyright (C) 2019 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 ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <array_length.h> ++#include <netdb.h> ++#include <support/check.h> ++#include <support/check_nss.h> ++#include <support/resolv_test.h> ++#include <support/support.h> ++ ++static void ++response (const struct resolv_response_context *ctx, ++ struct resolv_response_builder *b, ++ const char *qname, uint16_t qclass, uint16_t qtype) ++{ ++ /* The tests are not supposed send any DNS queries. */ ++ FAIL_EXIT1 ("unexpected DNS query for %s/%d/%d", qname, qclass, qtype); ++} ++ ++static int ++do_test (void) ++{ ++ struct resolv_test *aux = resolv_test_start ++ ((struct resolv_redirect_config) ++ { ++ .response_callback = response, ++ }); ++ ++ static const char *const queries[] = ++ { ++ "192.0.2.1 ", ++ "192.0.2.2\t", ++ "192.0.2.3\n", ++ "192.0.2.4 X", ++ "192.0.2.5\tY", ++ "192.0.2.6\nZ", ++ "192.0.2. ", ++ "192.0.2.\t", ++ "192.0.2.\n", ++ "192.0.2. X", ++ "192.0.2.\tY", ++ "192.0.2.\nZ", ++ "2001:db8::1 ", ++ "2001:db8::2\t", ++ "2001:db8::3\n", ++ "2001:db8::4 X", ++ "2001:db8::5\tY", ++ "2001:db8::6\nZ", ++ }; ++ for (size_t query_idx = 0; query_idx < array_length (queries); ++query_idx) ++ { ++ const char *query = queries[query_idx]; ++ struct hostent storage; ++ char buf[4096]; ++ struct hostent *e; ++ ++ h_errno = 0; ++ TEST_VERIFY (gethostbyname (query) == NULL); ++ TEST_COMPARE (h_errno, HOST_NOT_FOUND); ++ ++ h_errno = 0; ++ e = NULL; ++ TEST_COMPARE (gethostbyname_r (query, &storage, buf, sizeof (buf), ++ &e, &h_errno), 0); ++ TEST_VERIFY (e == NULL); ++ TEST_COMPARE (h_errno, HOST_NOT_FOUND); ++ ++ h_errno = 0; ++ TEST_VERIFY (gethostbyname2 (query, AF_INET) == NULL); ++ TEST_COMPARE (h_errno, HOST_NOT_FOUND); ++ ++ h_errno = 0; ++ e = NULL; ++ TEST_COMPARE (gethostbyname2_r (query, AF_INET, ++ &storage, buf, sizeof (buf), ++ &e, &h_errno), 0); ++ TEST_VERIFY (e == NULL); ++ TEST_COMPARE (h_errno, HOST_NOT_FOUND); ++ ++ h_errno = 0; ++ TEST_VERIFY (gethostbyname2 (query, AF_INET6) == NULL); ++ TEST_COMPARE (h_errno, HOST_NOT_FOUND); ++ ++ h_errno = 0; ++ e = NULL; ++ TEST_COMPARE (gethostbyname2_r (query, AF_INET6, ++ &storage, buf, sizeof (buf), ++ &e, &h_errno), 0); ++ TEST_VERIFY (e == NULL); ++ TEST_COMPARE (h_errno, HOST_NOT_FOUND); ++ ++ static const int gai_flags[] = ++ { ++ 0, ++ AI_ADDRCONFIG, ++ AI_NUMERICHOST, ++ AI_IDN, ++ AI_IDN | AI_NUMERICHOST, ++ AI_V4MAPPED, ++ AI_V4MAPPED | AI_NUMERICHOST, ++ }; ++ for (size_t gai_flags_idx; gai_flags_idx < array_length (gai_flags); ++ ++gai_flags_idx) ++ { ++ struct addrinfo hints = { .ai_flags = gai_flags[gai_flags_idx], }; ++ struct addrinfo *ai; ++ hints.ai_family = AF_INET; ++ TEST_COMPARE (getaddrinfo (query, "80", &hints, &ai), EAI_NONAME); ++ hints.ai_family = AF_INET6; ++ TEST_COMPARE (getaddrinfo (query, "80", &hints, &ai), EAI_NONAME); ++ hints.ai_family = AF_UNSPEC; ++ TEST_COMPARE (getaddrinfo (query, "80", &hints, &ai), EAI_NONAME); ++ } ++ }; ++ ++ resolv_test_end (aux); ++ ++ return 0; ++} ++ ++#include <support/test-driver.c> +diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c +index 2c4b6d6793a4c3a9..52f1b590f00c518e 100644 +--- a/sysdeps/posix/getaddrinfo.c ++++ b/sysdeps/posix/getaddrinfo.c +@@ -508,7 +508,7 @@ gaih_inet (const char *name, const struct gaih_service *service, + } + #endif + +- if (__inet_aton (name, (struct in_addr *) at->addr) != 0) ++ if (__inet_aton_exact (name, (struct in_addr *) at->addr) != 0) + { + if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET) + at->family = AF_INET; diff --git a/SOURCES/glibc-rh1673465-7.patch b/SOURCES/glibc-rh1673465-7.patch new file mode 100644 index 0000000..ea20dbc --- /dev/null +++ b/SOURCES/glibc-rh1673465-7.patch @@ -0,0 +1,81 @@ +commit c533244b8e00ae701583ec50aeb43377d292452d +Author: Florian Weimer <fweimer@redhat.com> +Date: Mon Feb 4 20:07:18 2019 +0100 + + nscd: Do not use __inet_aton_exact@GLIBC_PRIVATE [BZ #20018] + + This commit avoids referencing the __inet_aton_exact@GLIBC_PRIVATE + symbol from nscd. In master, the separately-compiled getaddrinfo + implementation in nscd needs it, however such an internal ABI change + is not desirable on a release branch if it can be avoided. + +(Note: This commit was backported from the release/2.28/master branch.) + +diff --git a/nscd/Makefile b/nscd/Makefile +index 2dc98d3a3347f998..62f38fa824527e0a 100644 +--- a/nscd/Makefile ++++ b/nscd/Makefile +@@ -36,7 +36,7 @@ nscd-modules := nscd connections pwdcache getpwnam_r getpwuid_r grpcache \ + 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-inet_addr + + ifeq ($(build-nscd)$(have-thread-library),yesyes) + +diff --git a/nscd/gai.c b/nscd/gai.c +index dbe878fcf699dbc1..e7443904b4514836 100644 +--- a/nscd/gai.c ++++ b/nscd/gai.c +@@ -32,6 +32,12 @@ + /* nscd uses 1MB or 2MB thread stacks. */ + #define __libc_use_alloca(size) (size <= __MAX_ALLOCA_CUTOFF) + ++/* We do not want to export __inet_aton_exact. Get the prototype and ++ change its visibility to hidden. */ ++#include <arpa/inet.h> ++__typeof__ (__inet_aton_exact) __inet_aton_exact ++ __attribute__ ((visibility ("hidden"))); ++ + /* We are nscd, so we don't want to be talking to ourselves. */ + #undef USE_NSCD + +diff --git a/nscd/nscd-inet_addr.c b/nscd/nscd-inet_addr.c +new file mode 100644 +index 0000000000000000..f366b9567d914f99 +--- /dev/null ++++ b/nscd/nscd-inet_addr.c +@@ -0,0 +1,32 @@ ++/* Legacy IPv4 text-to-address functions. Version for nscd. ++ Copyright (C) 2019 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 ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <arpa/inet.h> ++ ++/* We do not want to export __inet_aton_exact. Get the prototype and ++ change the visibility to hidden. */ ++#include <arpa/inet.h> ++__typeof__ (__inet_aton_exact) __inet_aton_exact ++ __attribute__ ((visibility ("hidden"))); ++ ++/* Do not provide definitions of the public symbols exported from ++ libc. */ ++#undef weak_alias ++#define weak_alias(from, to) ++ ++#include <resolv/inet_addr.c> diff --git a/SOURCES/glibc-rh1673465-8.patch b/SOURCES/glibc-rh1673465-8.patch new file mode 100644 index 0000000..51954e1 --- /dev/null +++ b/SOURCES/glibc-rh1673465-8.patch @@ -0,0 +1,16 @@ +Adjust resolv/tst-inet_aton_exact to use tests instead of tests-internal. +Downstream, tests-internal is currently ignored. + +diff --git a/resolv/Makefile b/resolv/Makefile +index 0130a09db2d69451..033c3c651f0deb1b 100644 +--- a/resolv/Makefile ++++ b/resolv/Makefile +@@ -34,7 +34,7 @@ routines := herror inet_addr inet_ntop inet_pton nsap_addr res_init \ + tests = tst-aton tst-leaks tst-inet_ntop + xtests = tst-leaks2 + +-tests-internal += tst-inet_aton_exact ++tests += tst-inet_aton_exact + + + generate := mtrace-tst-leaks.out tst-leaks.mtrace tst-leaks2.mtrace diff --git a/SOURCES/glibc-rh1684874-1.patch b/SOURCES/glibc-rh1684874-1.patch new file mode 100644 index 0000000..2f1fc76 --- /dev/null +++ b/SOURCES/glibc-rh1684874-1.patch @@ -0,0 +1,54 @@ +commit 7c70f2272edd4efcc4525f1bbb50e92de1a27a57 +Author: Mike Frysinger <vapier@gentoo.org> +Date: Thu Jan 30 18:56:56 2014 -0500 + + linux: bits/in.h: sync with latest kernel headers + + This pulls in the latest defines for {g,s}etsockopt. + + Reviewed-by: Carlos O'Donell <carlos@redhat.com> + Signed-off-by: Mike Frysinger <vapier@gentoo.org> + +diff --git a/sysdeps/unix/sysv/linux/bits/in.h b/sysdeps/unix/sysv/linux/bits/in.h +index 022082da1c0ca9f7..ac07d17d0e9dc9c9 100644 +--- a/sysdeps/unix/sysv/linux/bits/in.h ++++ b/sysdeps/unix/sysv/linux/bits/in.h +@@ -98,13 +98,37 @@ + #define IP_RECVORIGDSTADDR IP_ORIGDSTADDR + + #define IP_MINTTL 21 +- ++#define IP_NODEFRAG 22 + + /* IP_MTU_DISCOVER arguments. */ + #define IP_PMTUDISC_DONT 0 /* Never send DF frames. */ + #define IP_PMTUDISC_WANT 1 /* Use per route hints. */ + #define IP_PMTUDISC_DO 2 /* Always DF. */ + #define IP_PMTUDISC_PROBE 3 /* Ignore dst pmtu. */ ++/* Always use interface mtu (ignores dst pmtu) but don't set DF flag. ++ Also incoming ICMP frag_needed notifications will be ignored on ++ this socket to prevent accepting spoofed ones. */ ++#define IP_PMTUDISC_INTERFACE 4 ++ ++#define IP_MULTICAST_IF 32 ++#define IP_MULTICAST_TTL 33 ++#define IP_MULTICAST_LOOP 34 ++#define IP_ADD_MEMBERSHIP 35 ++#define IP_DROP_MEMBERSHIP 36 ++#define IP_UNBLOCK_SOURCE 37 ++#define IP_BLOCK_SOURCE 38 ++#define IP_ADD_SOURCE_MEMBERSHIP 39 ++#define IP_DROP_SOURCE_MEMBERSHIP 40 ++#define IP_MSFILTER 41 ++#define MCAST_JOIN_GROUP 42 ++#define MCAST_BLOCK_SOURCE 43 ++#define MCAST_UNBLOCK_SOURCE 44 ++#define MCAST_LEAVE_GROUP 45 ++#define MCAST_JOIN_SOURCE_GROUP 46 ++#define MCAST_LEAVE_SOURCE_GROUP 47 ++#define MCAST_MSFILTER 48 ++#define IP_MULTICAST_ALL 49 ++#define IP_UNICAST_IF 50 + + /* To select the IP level. */ + #define SOL_IP 0 diff --git a/SOURCES/glibc-rh1684874-2.patch b/SOURCES/glibc-rh1684874-2.patch new file mode 100644 index 0000000..7264d5b --- /dev/null +++ b/SOURCES/glibc-rh1684874-2.patch @@ -0,0 +1,49 @@ +commit 76e5216e317f39da2bc5bf905721cd9554ee6d09 +Author: Joseph Myers <joseph@codesourcery.com> +Date: Mon Jun 23 15:48:42 2014 +0000 + + Update headers for Linux 3.15. + + This patch updates glibc headers for changes / new definitions in + Linux 3.15. In the course of my review I noticed that + IPV6_PMTUDISC_INTERFACE was absent from glibc despite the inclusion of + IP_PMTUDISC_INTERFACE; I added it along with IP_PMTUDISC_OMIT and + IPV6_PMTUDISC_OMIT. I did not add FALLOC_FL_NO_HIDE_STALE given the + kernel header comment that it is reserved. + + Tested x86_64. + + * sysdeps/unix/sysv/linux/bits/fcntl-linux.h [__USE_GNU] + (FALLOC_FL_COLLAPSE_RANGE): New macro. + [__USE_GNU] (FALLOC_FL_ZERO_RANGE): Likewise. + * sysdeps/unix/sysv/linux/bits/in.h (IP_PMTUDISC_OMIT): Likewise. + (IPV6_PMTUDISC_INTERFACE): Likewise. + (IPV6_PMTUDISC_OMIT): Likewise. + +Only the sysdeps/unix/sysv/linux/bits/in.h part is backported in this +patch. The sysdeps/unix/sysv/linux/bits/fcntl-linux.h part was +completely superseded by glibc-rh1476120.patch, which uses +<linux/falloc.h> in favor of duplicated constants. + +diff --git a/sysdeps/unix/sysv/linux/bits/in.h b/sysdeps/unix/sysv/linux/bits/in.h +index ac07d17d0e9dc9c9..23046d3b5a6b0d91 100644 +--- a/sysdeps/unix/sysv/linux/bits/in.h ++++ b/sysdeps/unix/sysv/linux/bits/in.h +@@ -109,6 +109,8 @@ + Also incoming ICMP frag_needed notifications will be ignored on + this socket to prevent accepting spoofed ones. */ + #define IP_PMTUDISC_INTERFACE 4 ++/* Like IP_PMTUDISC_INTERFACE but allow packets to be fragmented. */ ++#define IP_PMTUDISC_OMIT 5 + + #define IP_MULTICAST_IF 32 + #define IP_MULTICAST_TTL 33 +@@ -224,6 +226,8 @@ struct in_pktinfo + #define IPV6_PMTUDISC_WANT 1 /* Use per route hints. */ + #define IPV6_PMTUDISC_DO 2 /* Always DF. */ + #define IPV6_PMTUDISC_PROBE 3 /* Ignore dst pmtu. */ ++#define IPV6_PMTUDISC_INTERFACE 4 /* See IP_PMTUDISC_INTERFACE. */ ++#define IPV6_PMTUDISC_OMIT 5 /* See IP_PMTUDISC_OMIT. */ + + /* Socket level values for IPv6. */ + #define SOL_IPV6 41 diff --git a/SOURCES/glibc-rh1693152-1.patch b/SOURCES/glibc-rh1693152-1.patch deleted file mode 100644 index 772b293..0000000 --- a/SOURCES/glibc-rh1693152-1.patch +++ /dev/null @@ -1,35 +0,0 @@ -This patch replaces the era block in ja_JP with the non-escaped -version. It is a partial backport of commit -a259f5d388d6195da958b2d147d17c2e2d16b857 ("Replaced unicode sequences -in the ASCII printable range"), containing only the changes to this -part of the localedata/locales/ja_JP file. - -diff --git a/localedata/locales/ja_JP b/localedata/locales/ja_JP -index 54e55b1b52e90f29..594df82f05a23719 100644 ---- a/localedata/locales/ja_JP -+++ b/localedata/locales/ja_JP -@@ -14942,15 +14942,15 @@ am_pm "<U5348><U524D>";"<U5348><U5F8C>" - - t_fmt_ampm "<U0025><U0070><U0025><U0049><U6642><U0025><U004D><U5206><U0025><U0053><U79D2>" - --era "<U002B><U003A><U0032><U003A><U0031><U0039><U0039><U0030><U002F><U0030><U0031><U002F><U0030><U0031><U003A><U002B><U002A><U003A><U5E73><U6210><U003A><U0025><U0045><U0043><U0025><U0045><U0079><U5E74>";/ -- "<U002B><U003A><U0031><U003A><U0031><U0039><U0038><U0039><U002F><U0030><U0031><U002F><U0030><U0038><U003A><U0031><U0039><U0038><U0039><U002F><U0031><U0032><U002F><U0033><U0031><U003A><U5E73><U6210><U003A><U0025><U0045><U0043><U5143><U5E74>";/ -- "<U002B><U003A><U0032><U003A><U0031><U0039><U0032><U0037><U002F><U0030><U0031><U002F><U0030><U0031><U003A><U0031><U0039><U0038><U0039><U002F><U0030><U0031><U002F><U0030><U0037><U003A><U662D><U548C><U003A><U0025><U0045><U0043><U0025><U0045><U0079><U5E74>";/ -- "<U002B><U003A><U0031><U003A><U0031><U0039><U0032><U0036><U002F><U0031><U0032><U002F><U0032><U0035><U003A><U0031><U0039><U0032><U0036><U002F><U0031><U0032><U002F><U0033><U0031><U003A><U662D><U548C><U003A><U0025><U0045><U0043><U5143><U5E74>";/ -- "<U002B><U003A><U0032><U003A><U0031><U0039><U0031><U0033><U002F><U0030><U0031><U002F><U0030><U0031><U003A><U0031><U0039><U0032><U0036><U002F><U0031><U0032><U002F><U0032><U0034><U003A><U5927><U6B63><U003A><U0025><U0045><U0043><U0025><U0045><U0079><U5E74>";/ -- "<U002B><U003A><U0032><U003A><U0031><U0039><U0031><U0032><U002F><U0030><U0037><U002F><U0033><U0030><U003A><U0031><U0039><U0031><U0032><U002F><U0031><U0032><U002F><U0033><U0031><U003A><U5927><U6B63><U003A><U0025><U0045><U0043><U5143><U5E74>";/ -- "<U002B><U003A><U0036><U003A><U0031><U0038><U0037><U0033><U002F><U0030><U0031><U002F><U0030><U0031><U003A><U0031><U0039><U0031><U0032><U002F><U0030><U0037><U002F><U0032><U0039><U003A><U660E><U6CBB><U003A><U0025><U0045><U0043><U0025><U0045><U0079><U5E74>";/ -- "<U002B><U003A><U0031><U003A><U0030><U0030><U0030><U0031><U002F><U0030><U0031><U002F><U0030><U0031><U003A><U0031><U0038><U0037><U0032><U002F><U0031><U0032><U002F><U0033><U0031><U003A><U897F><U66A6><U003A><U0025><U0045><U0043><U0025><U0045><U0079><U5E74>";/ -- "<U002B><U003A><U0031><U003A><U002D><U0030><U0030><U0030><U0031><U002F><U0031><U0032><U002F><U0033><U0031><U003A><U002D><U002A><U003A><U7D00><U5143><U524D><U003A><U0025><U0045><U0043><U0025><U0045><U0079><U5E74>" -+era "+:2:1990//01//01:+*:<U5E73><U6210>:%EC%Ey<U5E74>";/ -+ "+:1:1989//01//08:1989//12//31:<U5E73><U6210>:%EC<U5143><U5E74>";/ -+ "+:2:1927//01//01:1989//01//07:<U662D><U548C>:%EC%Ey<U5E74>";/ -+ "+:1:1926//12//25:1926//12//31:<U662D><U548C>:%EC<U5143><U5E74>";/ -+ "+:2:1913//01//01:1926//12//24:<U5927><U6B63>:%EC%Ey<U5E74>";/ -+ "+:2:1912//07//30:1912//12//31:<U5927><U6B63>:%EC<U5143><U5E74>";/ -+ "+:6:1873//01//01:1912//07//29:<U660E><U6CBB>:%EC%Ey<U5E74>";/ -+ "+:1:0001//01//01:1872//12//31:<U897F><U66A6>:%EC%Ey<U5E74>";/ -+ "+:1:-0001//12//31:-*:<U7D00><U5143><U524D>:%EC%Ey<U5E74>" - - era_d_fmt "<U0025><U0045><U0059><U0025><U006d><U6708><U0025><U0064><U65E5>" - diff --git a/SOURCES/glibc-rh1693152-2.patch b/SOURCES/glibc-rh1693152-2.patch deleted file mode 100644 index f9cbc16..0000000 --- a/SOURCES/glibc-rh1693152-2.patch +++ /dev/null @@ -1,24 +0,0 @@ -Patch by Hanataka Shinya <hanataka.shinya@gmail.com> from -<https://sourceware.org/bugzilla/show_bug.cgi?id=24405>. Confirmed by TAMUKI -Shoichi's patch in -<https://sourceware.org/ml/libc-alpha/2019-04/msg00005.html>. - -The official announcement by the Japanese Prime Minister in -<https://www.kantei.go.jp/jp/tyoukanpress/201904/1_a.html> uses U+4EE4 U+548C -as well. - -diff --git a/localedata/locales/ja_JP b/localedata/locales/ja_JP -index 594df82f05a23719..40cb5795fea730a5 100644 ---- a/localedata/locales/ja_JP -+++ b/localedata/locales/ja_JP -@@ -14942,7 +14942,9 @@ am_pm "<U5348><U524D>";"<U5348><U5F8C>" - - t_fmt_ampm "<U0025><U0070><U0025><U0049><U6642><U0025><U004D><U5206><U0025><U0053><U79D2>" - --era "+:2:1990//01//01:+*:<U5E73><U6210>:%EC%Ey<U5E74>";/ -+era "+:2:2020//01//01:+*:<U4EE4><U548C>:%EC%Ey<U5E74>";/ -+ "+:1:2019//05//01:2019//12//31:<U4EE4><U548C>:%EC<U5143><U5E74>";/ -+ "+:2:1990//01//01:2019//04//30:<U5E73><U6210>:%EC%Ey<U5E74>";/ - "+:1:1989//01//08:1989//12//31:<U5E73><U6210>:%EC<U5143><U5E74>";/ - "+:2:1927//01//01:1989//01//07:<U662D><U548C>:%EC%Ey<U5E74>";/ - "+:1:1926//12//25:1926//12//31:<U662D><U548C>:%EC<U5143><U5E74>";/ diff --git a/SOURCES/glibc-rh1705899-1.patch b/SOURCES/glibc-rh1705899-1.patch deleted file mode 100644 index 9955c76..0000000 --- a/SOURCES/glibc-rh1705899-1.patch +++ /dev/null @@ -1,466 +0,0 @@ -commit 2afece36f6006844e87d7cb2fcb1ad8b220b2623 -Author: Florian Weimer <fweimer@redhat.com> -Date: Wed May 16 17:00:35 2018 +0200 - - support: Add TEST_COMPARE_BLOB, support_quote_blob - - The declaration of support_test_compare_blob uses unsigned long int, - to avoid including <stddef.h>. - - Reviewed-by: Carlos O'Donell <carlos@redhat.com> - -(Adjusted for minor conflict in support/Makefile.) - -diff --git a/support/Makefile b/support/Makefile -index 1bda81e55e519a57..fb9f4291d72156df 100644 ---- a/support/Makefile -+++ b/support/Makefile -@@ -52,9 +52,11 @@ libsupport-routines = \ - support_format_hostent \ - support_format_netent \ - support_isolate_in_subprocess \ -+ support_quote_blob \ - support_record_failure \ - support_run_diff \ - support_shared_allocate \ -+ support_test_compare_blob \ - support_test_compare_failure \ - support_write_file_string \ - support_test_main \ -@@ -150,8 +152,10 @@ tests = \ - tst-support-namespace \ - tst-support_capture_subprocess \ - tst-support_format_dns_packet \ -+ tst-support_quote_blob \ - tst-support_record_failure \ - tst-test_compare \ -+ tst-test_compare_blob \ - tst-xreadlink \ - - ifeq ($(run-built-tests),yes) -diff --git a/support/check.h b/support/check.h -index 2192f38941af2515..b3a4645e9255e90d 100644 ---- a/support/check.h -+++ b/support/check.h -@@ -64,6 +64,8 @@ __BEGIN_DECLS - (1, __FILE__, __LINE__, #expr); \ - }) - -+ -+ - int support_print_failure_impl (const char *file, int line, - const char *format, ...) - __attribute__ ((nonnull (1), format (printf, 3, 4))); -@@ -141,6 +143,26 @@ void support_test_compare_failure (const char *file, int line, - int right_size); - - -+/* Compare [LEFT, LEFT + LEFT_LENGTH) with [RIGHT, RIGHT + -+ RIGHT_LENGTH) and report a test failure if the arrays are -+ different. LEFT_LENGTH and RIGHT_LENGTH are measured in bytes. If -+ the length is null, the corresponding pointer is ignored (i.e., it -+ can be NULL). The blobs should be reasonably short because on -+ mismatch, both are printed. */ -+#define TEST_COMPARE_BLOB(left, left_length, right, right_length) \ -+ (support_test_compare_blob (left, left_length, right, right_length, \ -+ __FILE__, __LINE__, \ -+ #left, #left_length, #right, #right_length)) -+ -+void support_test_compare_blob (const void *left, -+ unsigned long int left_length, -+ const void *right, -+ unsigned long int right_length, -+ const char *file, int line, -+ const char *left_exp, const char *left_len_exp, -+ const char *right_exp, -+ const char *right_len_exp); -+ - /* Internal function called by the test driver. */ - int support_report_failure (int status) - __attribute__ ((weak, warn_unused_result)); -diff --git a/support/support.h b/support/support.h -index bc5827ed87d0d96c..b61fe0735c9204de 100644 ---- a/support/support.h -+++ b/support/support.h -@@ -59,6 +59,12 @@ void support_shared_free (void *); - process on error. */ - void support_write_file_string (const char *path, const char *contents); - -+/* Quote the contents of the byte array starting at BLOB, of LENGTH -+ bytes, in such a way that the result string can be included in a C -+ literal (in single/double quotes, without putting the quotes into -+ the result). */ -+char *support_quote_blob (const void *blob, size_t length); -+ - /* Error-checking wrapper functions which terminate the process on - error. */ - -diff --git a/support/support_quote_blob.c b/support/support_quote_blob.c -new file mode 100644 -index 0000000000000000..d6a678d8d69160a8 ---- /dev/null -+++ b/support/support_quote_blob.c -@@ -0,0 +1,83 @@ -+/* Quote a blob so that it can be used in C literals. -+ Copyright (C) 2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ <http://www.gnu.org/licenses/>. */ -+ -+#include <support/support.h> -+#include <support/xmemstream.h> -+ -+char * -+support_quote_blob (const void *blob, size_t length) -+{ -+ struct xmemstream out; -+ xopen_memstream (&out); -+ -+ const unsigned char *p = blob; -+ for (size_t i = 0; i < length; ++i) -+ { -+ unsigned char ch = p[i]; -+ -+ /* Use C backslash escapes for those control characters for -+ which they are defined. */ -+ switch (ch) -+ { -+ case '\a': -+ putc_unlocked ('\\', out.out); -+ putc_unlocked ('a', out.out); -+ break; -+ case '\b': -+ putc_unlocked ('\\', out.out); -+ putc_unlocked ('b', out.out); -+ break; -+ case '\f': -+ putc_unlocked ('\\', out.out); -+ putc_unlocked ('f', out.out); -+ break; -+ case '\n': -+ putc_unlocked ('\\', out.out); -+ putc_unlocked ('n', out.out); -+ break; -+ case '\r': -+ putc_unlocked ('\\', out.out); -+ putc_unlocked ('r', out.out); -+ break; -+ case '\t': -+ putc_unlocked ('\\', out.out); -+ putc_unlocked ('t', out.out); -+ break; -+ case '\v': -+ putc_unlocked ('\\', out.out); -+ putc_unlocked ('v', out.out); -+ break; -+ case '\\': -+ case '\'': -+ case '\"': -+ putc_unlocked ('\\', out.out); -+ putc_unlocked (ch, out.out); -+ break; -+ default: -+ if (ch < ' ' || ch > '~') -+ /* Use octal sequences because they are fixed width, -+ unlike hexadecimal sequences. */ -+ fprintf (out.out, "\\%03o", ch); -+ else -+ putc_unlocked (ch, out.out); -+ } -+ } -+ -+ xfclose_memstream (&out); -+ return out.buffer; -+} -diff --git a/support/support_test_compare_blob.c b/support/support_test_compare_blob.c -new file mode 100644 -index 0000000000000000..c5e63d1b9327c9fe ---- /dev/null -+++ b/support/support_test_compare_blob.c -@@ -0,0 +1,76 @@ -+/* Check two binary blobs for equality. -+ Copyright (C) 2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ <http://www.gnu.org/licenses/>. */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <string.h> -+#include <support/check.h> -+#include <support/support.h> -+#include <support/xmemstream.h> -+ -+static void -+report_length (const char *what, unsigned long int length, const char *expr) -+{ -+ printf (" %s %lu bytes (from %s)\n", what, length, expr); -+} -+ -+static void -+report_blob (const char *what, const unsigned char *blob, -+ unsigned long int length, const char *expr) -+{ -+ if (length > 0) -+ { -+ printf (" %s (evaluated from %s):\n", what, expr); -+ char *quoted = support_quote_blob (blob, length); -+ printf (" \"%s\"\n", quoted); -+ free (quoted); -+ -+ fputs (" ", stdout); -+ for (unsigned long i = 0; i < length; ++i) -+ printf (" %02X", blob[i]); -+ putc ('\n', stdout); -+ } -+} -+ -+void -+support_test_compare_blob (const void *left, unsigned long int left_length, -+ const void *right, unsigned long int right_length, -+ const char *file, int line, -+ const char *left_expr, const char *left_len_expr, -+ const char *right_expr, const char *right_len_expr) -+{ -+ /* No differences are possible if both lengths are null. */ -+ if (left_length == 0 && right_length == 0) -+ return; -+ -+ if (left_length != right_length || left == NULL || right == NULL -+ || memcmp (left, right, left_length) != 0) -+ { -+ support_record_failure (); -+ printf ("%s:%d: error: blob comparison failed\n", file, line); -+ if (left_length == right_length) -+ printf (" blob length: %lu bytes\n", left_length); -+ else -+ { -+ report_length ("left length: ", left_length, left_len_expr); -+ report_length ("right length:", right_length, right_len_expr); -+ } -+ report_blob ("left", left, left_length, left_expr); -+ report_blob ("right", right, right_length, right_expr); -+ } -+} -diff --git a/support/tst-support_quote_blob.c b/support/tst-support_quote_blob.c -new file mode 100644 -index 0000000000000000..5467a190a6e0725c ---- /dev/null -+++ b/support/tst-support_quote_blob.c -@@ -0,0 +1,61 @@ -+/* Test the support_quote_blob function. -+ Copyright (C) 2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ <http://www.gnu.org/licenses/>. */ -+ -+#include <support/check.h> -+#include <support/support.h> -+#include <string.h> -+#include <stdlib.h> -+ -+static int -+do_test (void) -+{ -+ /* Check handling of the empty blob, both with and without trailing -+ NUL byte. */ -+ char *p = support_quote_blob ("", 0); -+ TEST_COMPARE (strlen (p), 0); -+ free (p); -+ p = support_quote_blob ("X", 0); -+ TEST_COMPARE (strlen (p), 0); -+ free (p); -+ -+ /* Check escaping of backslash-escaped characters, and lack of -+ escaping for other shell meta-characters. */ -+ p = support_quote_blob ("$()*?`@[]{}~\'\"X", 14); -+ TEST_COMPARE (strcmp (p, "$()*?`@[]{}~\\'\\\""), 0); -+ free (p); -+ -+ /* Check lack of escaping for letters and digits. */ -+#define LETTERS_AND_DIGTS \ -+ "abcdefghijklmnopqrstuvwxyz" \ -+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ -+ "0123456789" -+ p = support_quote_blob (LETTERS_AND_DIGTS "@", 2 * 26 + 10); -+ TEST_COMPARE (strcmp (p, LETTERS_AND_DIGTS), 0); -+ free (p); -+ -+ /* Check escaping of control characters and other non-printable -+ characters. */ -+ p = support_quote_blob ("\r\n\t\a\b\f\v\1\177\200\377\0@", 14); -+ TEST_COMPARE (strcmp (p, "\\r\\n\\t\\a\\b\\f\\v\\001" -+ "\\177\\200\\377\\000@\\000"), 0); -+ free (p); -+ -+ return 0; -+} -+ -+#include <support/test-driver.c> -diff --git a/support/tst-test_compare_blob.c b/support/tst-test_compare_blob.c -new file mode 100644 -index 0000000000000000..aa8643e18227da85 ---- /dev/null -+++ b/support/tst-test_compare_blob.c -@@ -0,0 +1,125 @@ -+/* Basic test for the TEST_COMPARE_BLOB macro. -+ Copyright (C) 2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ <http://www.gnu.org/licenses/>. */ -+ -+#include <string.h> -+#include <support/check.h> -+#include <support/capture_subprocess.h> -+ -+static void -+subprocess (void *closure) -+{ -+ /* These tests should fail. They were chosen to cover differences -+ in length (with the same contents), single-bit mismatches, and -+ mismatching null pointers. */ -+ TEST_COMPARE_BLOB ("", 0, "", 1); /* Line 29. */ -+ TEST_COMPARE_BLOB ("X", 1, "", 1); /* Line 30. */ -+ TEST_COMPARE_BLOB ("abcd", 3, "abcd", 4); /* Line 31. */ -+ TEST_COMPARE_BLOB ("abcd", 4, "abcD", 4); /* Line 32. */ -+ TEST_COMPARE_BLOB ("abcd", 4, NULL, 0); /* Line 33. */ -+ TEST_COMPARE_BLOB (NULL, 0, "abcd", 4); /* Line 34. */ -+} -+ -+/* Same contents, different addresses. */ -+char buffer_abc_1[] = "abc"; -+char buffer_abc_2[] = "abc"; -+ -+static int -+do_test (void) -+{ -+ /* This should succeed. Even if the pointers and array contents are -+ different, zero-length inputs are not different. */ -+ TEST_COMPARE_BLOB ("", 0, "", 0); -+ TEST_COMPARE_BLOB ("", 0, buffer_abc_1, 0); -+ TEST_COMPARE_BLOB (buffer_abc_1, 0, "", 0); -+ TEST_COMPARE_BLOB (NULL, 0, "", 0); -+ TEST_COMPARE_BLOB ("", 0, NULL, 0); -+ TEST_COMPARE_BLOB (NULL, 0, NULL, 0); -+ -+ /* Check equality of blobs containing a single NUL byte. */ -+ TEST_COMPARE_BLOB ("", 1, "", 1); -+ TEST_COMPARE_BLOB ("", 1, &buffer_abc_1[3], 1); -+ -+ /* Check equality of blobs of varying lengths. */ -+ for (size_t i = 0; i <= sizeof (buffer_abc_1); ++i) -+ TEST_COMPARE_BLOB (buffer_abc_1, i, buffer_abc_2, i); -+ -+ struct support_capture_subprocess proc = support_capture_subprocess -+ (&subprocess, NULL); -+ -+ /* Discard the reported error. */ -+ support_record_failure_reset (); -+ -+ puts ("info: *** subprocess output starts ***"); -+ fputs (proc.out.buffer, stdout); -+ puts ("info: *** subprocess output ends ***"); -+ -+ TEST_VERIFY -+ (strcmp (proc.out.buffer, -+"tst-test_compare_blob.c:29: error: blob comparison failed\n" -+" left length: 0 bytes (from 0)\n" -+" right length: 1 bytes (from 1)\n" -+" right (evaluated from \"\"):\n" -+" \"\\000\"\n" -+" 00\n" -+"tst-test_compare_blob.c:30: error: blob comparison failed\n" -+" blob length: 1 bytes\n" -+" left (evaluated from \"X\"):\n" -+" \"X\"\n" -+" 58\n" -+" right (evaluated from \"\"):\n" -+" \"\\000\"\n" -+" 00\n" -+"tst-test_compare_blob.c:31: error: blob comparison failed\n" -+" left length: 3 bytes (from 3)\n" -+" right length: 4 bytes (from 4)\n" -+" left (evaluated from \"abcd\"):\n" -+" \"abc\"\n" -+" 61 62 63\n" -+" right (evaluated from \"abcd\"):\n" -+" \"abcd\"\n" -+" 61 62 63 64\n" -+"tst-test_compare_blob.c:32: error: blob comparison failed\n" -+" blob length: 4 bytes\n" -+" left (evaluated from \"abcd\"):\n" -+" \"abcd\"\n" -+" 61 62 63 64\n" -+" right (evaluated from \"abcD\"):\n" -+" \"abcD\"\n" -+" 61 62 63 44\n" -+"tst-test_compare_blob.c:33: error: blob comparison failed\n" -+" left length: 4 bytes (from 4)\n" -+" right length: 0 bytes (from 0)\n" -+" left (evaluated from \"abcd\"):\n" -+" \"abcd\"\n" -+" 61 62 63 64\n" -+"tst-test_compare_blob.c:34: error: blob comparison failed\n" -+" left length: 0 bytes (from 0)\n" -+" right length: 4 bytes (from 4)\n" -+" right (evaluated from \"abcd\"):\n" -+" \"abcd\"\n" -+" 61 62 63 64\n" -+ ) == 0); -+ -+ /* Check that there is no output on standard error. */ -+ support_capture_subprocess_check (&proc, "TEST_COMPARE_BLOB", -+ 0, sc_allow_stdout); -+ -+ return 0; -+} -+ -+#include <support/test-driver.c> diff --git a/SOURCES/glibc-rh1705899-2.patch b/SOURCES/glibc-rh1705899-2.patch deleted file mode 100644 index 5e0e669..0000000 --- a/SOURCES/glibc-rh1705899-2.patch +++ /dev/null @@ -1,50 +0,0 @@ -commit 5c0202af4b3d588c04bcec7baf05706b21cd7416 -Author: Florian Weimer <fweimer@redhat.com> -Date: Tue Jun 26 12:05:21 2018 +0200 - - support: Add TEST_NO_SETVBUF - - This is sometimes needed for testing stdio streams, where the - setvbuf call in the test driver could interfere with the test. - -diff --git a/support/support_test_main.c b/support/support_test_main.c -index 396385729b6809ad..23429779aca85613 100644 ---- a/support/support_test_main.c -+++ b/support/support_test_main.c -@@ -270,7 +270,8 @@ support_test_main (int argc, char **argv, const struct test_config *config) - timeout = DEFAULT_TIMEOUT; - - /* Make sure we see all message, even those on stdout. */ -- setvbuf (stdout, NULL, _IONBF, 0); -+ if (!config->no_setvbuf) -+ setvbuf (stdout, NULL, _IONBF, 0); - - /* Make sure temporary files are deleted. */ - if (support_delete_temp_files != NULL) -diff --git a/support/test-driver.c b/support/test-driver.c -index 09c8783e4f54d809..9798f16227b9d467 100644 ---- a/support/test-driver.c -+++ b/support/test-driver.c -@@ -140,6 +140,10 @@ main (int argc, char **argv) - test_config.no_mallopt = 1; - #endif - -+#ifdef TEST_NO_SETVBUF -+ test_config.no_setvbuf = 1; -+#endif -+ - #ifdef TIMEOUT - test_config.timeout = TIMEOUT; - #endif -diff --git a/support/test-driver.h b/support/test-driver.h -index 1708d68d608ee4a4..549179b254946390 100644 ---- a/support/test-driver.h -+++ b/support/test-driver.h -@@ -35,6 +35,7 @@ struct test_config - int expected_status; /* Expected exit status. */ - int expected_signal; /* If non-zero, expect termination by signal. */ - char no_mallopt; /* Boolean flag to disable mallopt. */ -+ char no_setvbuf; /* Boolean flag to disable setvbuf. */ - const char *optstring; /* Short command line options. */ - }; - diff --git a/SOURCES/glibc-rh1705899-3.patch b/SOURCES/glibc-rh1705899-3.patch deleted file mode 100644 index 3e3fa24..0000000 --- a/SOURCES/glibc-rh1705899-3.patch +++ /dev/null @@ -1,230 +0,0 @@ -commit 0262507918cfad7223bf81b8f162b7adc7a2af01 -Author: Florian Weimer <fweimer@redhat.com> -Date: Fri Jun 1 10:43:06 2018 +0200 - - libio: Avoid _allocate_buffer, _free_buffer function pointers [BZ #23236] - - These unmangled function pointers reside on the heap and could - be targeted by exploit writers, effectively bypassing libio vtable - validation. Instead, we ignore these pointers and always call - malloc or free. - - In theory, this is a backwards-incompatible change, but using the - global heap instead of the user-supplied callback functions should - have little application impact. (The old libstdc++ implementation - exposed this functionality via a public, undocumented constructor - in its strstreambuf class.) - - (cherry picked from commit 4e8a6346cd3da2d88bbad745a1769260d36f2783) - -Backported from the upstream release/2.27/master branch. - -diff --git a/debug/vasprintf_chk.c b/debug/vasprintf_chk.c -index a8ca32bad57b4d13..113354749ccf8d9a 100644 ---- a/debug/vasprintf_chk.c -+++ b/debug/vasprintf_chk.c -@@ -55,8 +55,8 @@ __vasprintf_chk (char **result_ptr, int flags, const char *format, - _IO_JUMPS (&sf._sbf) = &_IO_str_jumps; - _IO_str_init_static_internal (&sf, string, init_string_size, string); - sf._sbf._f._flags &= ~_IO_USER_BUF; -- sf._s._allocate_buffer = (_IO_alloc_type) malloc; -- sf._s._free_buffer = (_IO_free_type) free; -+ sf._s._allocate_buffer_unused = (_IO_alloc_type) malloc; -+ sf._s._free_buffer_unused = (_IO_free_type) free; - - /* For flags > 0 (i.e. __USE_FORTIFY_LEVEL > 1) request that %n - can only come from read-only format strings. */ -diff --git a/libio/memstream.c b/libio/memstream.c -index e18a7756b297c9f4..9a51331e525c3468 100644 ---- a/libio/memstream.c -+++ b/libio/memstream.c -@@ -87,8 +87,8 @@ open_memstream (char **bufloc, _IO_size_t *sizeloc) - _IO_JUMPS ((struct _IO_FILE_plus *) &new_f->fp._sf._sbf) = &_IO_mem_jumps; - _IO_str_init_static_internal (&new_f->fp._sf, buf, _IO_BUFSIZ, buf); - new_f->fp._sf._sbf._f._flags &= ~_IO_USER_BUF; -- new_f->fp._sf._s._allocate_buffer = (_IO_alloc_type) malloc; -- new_f->fp._sf._s._free_buffer = (_IO_free_type) free; -+ new_f->fp._sf._s._allocate_buffer_unused = (_IO_alloc_type) malloc; -+ new_f->fp._sf._s._free_buffer_unused = (_IO_free_type) free; - - new_f->fp.bufloc = bufloc; - new_f->fp.sizeloc = sizeloc; -diff --git a/libio/strfile.h b/libio/strfile.h -index 4ea7548f9fa92638..9cd8e7c466616b52 100644 ---- a/libio/strfile.h -+++ b/libio/strfile.h -@@ -34,8 +34,11 @@ typedef void (*_IO_free_type) (void*); - - struct _IO_str_fields - { -- _IO_alloc_type _allocate_buffer; -- _IO_free_type _free_buffer; -+ /* These members are preserved for ABI compatibility. The glibc -+ implementation always calls malloc/free for user buffers if -+ _IO_USER_BUF or _IO_FLAGS2_USER_WBUF are not set. */ -+ _IO_alloc_type _allocate_buffer_unused; -+ _IO_free_type _free_buffer_unused; - }; - - /* This is needed for the Irix6 N32 ABI, which has a 64 bit off_t type, -@@ -55,10 +58,6 @@ typedef struct _IO_strfile_ - struct _IO_str_fields _s; - } _IO_strfile; - --/* dynamic: set when the array object is allocated (or reallocated) as -- necessary to hold a character sequence that can change in length. */ --#define _IO_STR_DYNAMIC(FP) ((FP)->_s._allocate_buffer != (_IO_alloc_type)0) -- - /* frozen: set when the program has requested that the array object not - be altered, reallocated, or freed. */ - #define _IO_STR_FROZEN(FP) ((FP)->_f._IO_file_flags & _IO_USER_BUF) -diff --git a/libio/strops.c b/libio/strops.c -index fdd113a60811e593..129a0f6aeca818fd 100644 ---- a/libio/strops.c -+++ b/libio/strops.c -@@ -61,7 +61,7 @@ _IO_str_init_static_internal (_IO_strfile *sf, char *ptr, _IO_size_t size, - fp->_IO_read_end = end; - } - /* A null _allocate_buffer function flags the strfile as being static. */ -- sf->_s._allocate_buffer = (_IO_alloc_type) 0; -+ sf->_s._allocate_buffer_unused = (_IO_alloc_type) 0; - } - - void -@@ -103,8 +103,7 @@ _IO_str_overflow (_IO_FILE *fp, int c) - _IO_size_t new_size = 2 * old_blen + 100; - if (new_size < old_blen) - return EOF; -- new_buf -- = (char *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size); -+ new_buf = malloc (new_size); - if (new_buf == NULL) - { - /* __ferror(fp) = 1; */ -@@ -113,7 +112,7 @@ _IO_str_overflow (_IO_FILE *fp, int c) - if (old_buf) - { - memcpy (new_buf, old_buf, old_blen); -- (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf); -+ free (old_buf); - /* Make sure _IO_setb won't try to delete _IO_buf_base. */ - fp->_IO_buf_base = NULL; - } -@@ -182,15 +181,14 @@ enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading) - - _IO_size_t newsize = offset + 100; - char *oldbuf = fp->_IO_buf_base; -- char *newbuf -- = (char *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (newsize); -+ char *newbuf = malloc (newsize); - if (newbuf == NULL) - return 1; - - if (oldbuf != NULL) - { - memcpy (newbuf, oldbuf, _IO_blen (fp)); -- (*((_IO_strfile *) fp)->_s._free_buffer) (oldbuf); -+ free (oldbuf); - /* Make sure _IO_setb won't try to delete - _IO_buf_base. */ - fp->_IO_buf_base = NULL; -@@ -317,7 +315,7 @@ void - _IO_str_finish (_IO_FILE *fp, int dummy) - { - if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF)) -- (((_IO_strfile *) fp)->_s._free_buffer) (fp->_IO_buf_base); -+ free (fp->_IO_buf_base); - fp->_IO_buf_base = NULL; - - _IO_default_finish (fp, 0); -diff --git a/libio/vasprintf.c b/libio/vasprintf.c -index 282c86fff0a7ae0e..867ef4fe4ca4ec56 100644 ---- a/libio/vasprintf.c -+++ b/libio/vasprintf.c -@@ -54,8 +54,8 @@ _IO_vasprintf (char **result_ptr, const char *format, _IO_va_list args) - _IO_JUMPS (&sf._sbf) = &_IO_str_jumps; - _IO_str_init_static_internal (&sf, string, init_string_size, string); - sf._sbf._f._flags &= ~_IO_USER_BUF; -- sf._s._allocate_buffer = (_IO_alloc_type) malloc; -- sf._s._free_buffer = (_IO_free_type) free; -+ sf._s._allocate_buffer_unused = (_IO_alloc_type) malloc; -+ sf._s._free_buffer_unused = (_IO_free_type) free; - ret = _IO_vfprintf (&sf._sbf._f, format, args); - if (ret < 0) - { -diff --git a/libio/wmemstream.c b/libio/wmemstream.c -index bd6d1798b1685fe9..3a9a681c80a321a7 100644 ---- a/libio/wmemstream.c -+++ b/libio/wmemstream.c -@@ -90,8 +90,8 @@ open_wmemstream (wchar_t **bufloc, _IO_size_t *sizeloc) - _IO_wstr_init_static (&new_f->fp._sf._sbf._f, buf, - _IO_BUFSIZ / sizeof (wchar_t), buf); - new_f->fp._sf._sbf._f._flags2 &= ~_IO_FLAGS2_USER_WBUF; -- new_f->fp._sf._s._allocate_buffer = (_IO_alloc_type) malloc; -- new_f->fp._sf._s._free_buffer = (_IO_free_type) free; -+ new_f->fp._sf._s._allocate_buffer_unused = (_IO_alloc_type) malloc; -+ new_f->fp._sf._s._free_buffer_unused = (_IO_free_type) free; - - new_f->fp.bufloc = bufloc; - new_f->fp.sizeloc = sizeloc; -diff --git a/libio/wstrops.c b/libio/wstrops.c -index 7a9a33ab8763b8ff..a31d0e23341b2aad 100644 ---- a/libio/wstrops.c -+++ b/libio/wstrops.c -@@ -63,7 +63,7 @@ _IO_wstr_init_static (_IO_FILE *fp, wchar_t *ptr, _IO_size_t size, - fp->_wide_data->_IO_read_end = end; - } - /* A null _allocate_buffer function flags the strfile as being static. */ -- (((_IO_strfile *) fp)->_s._allocate_buffer) = (_IO_alloc_type)0; -+ (((_IO_strfile *) fp)->_s._allocate_buffer_unused) = (_IO_alloc_type)0; - } - - _IO_wint_t -@@ -95,9 +95,7 @@ _IO_wstr_overflow (_IO_FILE *fp, _IO_wint_t c) - || __glibc_unlikely (new_size > SIZE_MAX / sizeof (wchar_t))) - return EOF; - -- new_buf -- = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size -- * sizeof (wchar_t)); -+ new_buf = malloc (new_size * sizeof (wchar_t)); - if (new_buf == NULL) - { - /* __ferror(fp) = 1; */ -@@ -106,7 +104,7 @@ _IO_wstr_overflow (_IO_FILE *fp, _IO_wint_t c) - if (old_buf) - { - __wmemcpy (new_buf, old_buf, old_wblen); -- (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf); -+ free (old_buf); - /* Make sure _IO_setb won't try to delete _IO_buf_base. */ - fp->_wide_data->_IO_buf_base = NULL; - } -@@ -186,16 +184,14 @@ enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading) - return 1; - - wchar_t *oldbuf = wd->_IO_buf_base; -- wchar_t *newbuf -- = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (newsize -- * sizeof (wchar_t)); -+ wchar_t *newbuf = malloc (newsize * sizeof (wchar_t)); - if (newbuf == NULL) - return 1; - - if (oldbuf != NULL) - { - __wmemcpy (newbuf, oldbuf, _IO_wblen (fp)); -- (*((_IO_strfile *) fp)->_s._free_buffer) (oldbuf); -+ free (oldbuf); - /* Make sure _IO_setb won't try to delete - _IO_buf_base. */ - wd->_IO_buf_base = NULL; -@@ -326,7 +322,7 @@ void - _IO_wstr_finish (_IO_FILE *fp, int dummy) - { - if (fp->_wide_data->_IO_buf_base && !(fp->_flags2 & _IO_FLAGS2_USER_WBUF)) -- (((_IO_strfile *) fp)->_s._free_buffer) (fp->_wide_data->_IO_buf_base); -+ free (fp->_wide_data->_IO_buf_base); - fp->_wide_data->_IO_buf_base = NULL; - - _IO_wdefault_finish (fp, 0); diff --git a/SOURCES/glibc-rh1705899-4.patch b/SOURCES/glibc-rh1705899-4.patch deleted file mode 100644 index 80c7606..0000000 --- a/SOURCES/glibc-rh1705899-4.patch +++ /dev/null @@ -1,34 +0,0 @@ -commit 3bb748257405e94e13de76573a4e9da1cfd961d0 -Author: Florian Weimer <fweimer@redhat.com> -Date: Tue Jul 3 15:54:49 2018 +0200 - - libio: Disable vtable validation in case of interposition [BZ #23313] - - (cherry picked from commit c402355dfa7807b8e0adb27c009135a7e2b9f1b0) - -Backported from the upstream release/2.27/master branch. - -diff --git a/libio/vtables.c b/libio/vtables.c -index e364ea03edbfa75b..d6478e4bab9050ce 100644 ---- a/libio/vtables.c -+++ b/libio/vtables.c -@@ -68,3 +68,19 @@ _IO_vtable_check (void) - - __libc_fatal ("Fatal error: glibc detected an invalid stdio handle\n"); - } -+ -+/* Some variants of libstdc++ interpose _IO_2_1_stdin_ etc. and -+ install their own vtables directly, without calling _IO_init or -+ other functions. Detect this by looking at the vtables values -+ during startup, and disable vtable validation in this case. */ -+#ifdef SHARED -+__attribute__ ((constructor)) -+static void -+check_stdfiles_vtables (void) -+{ -+ if (_IO_2_1_stdin_.vtable != &_IO_file_jumps -+ || _IO_2_1_stdout_.vtable != &_IO_file_jumps -+ || _IO_2_1_stderr_.vtable != &_IO_file_jumps) -+ IO_set_accept_foreign_vtables (&_IO_vtable_check); -+} -+#endif diff --git a/SOURCES/glibc-rh1705899-5.patch b/SOURCES/glibc-rh1705899-5.patch deleted file mode 100644 index 1500ba3..0000000 --- a/SOURCES/glibc-rh1705899-5.patch +++ /dev/null @@ -1,624 +0,0 @@ -commit 44927211651adde42bbd431ef5ebe568186125e5 -Author: Florian Weimer <fweimer@redhat.com> -Date: Tue Jul 3 17:57:14 2018 +0200 - - libio: Add tst-vtables, tst-vtables-interposed - - (cherry picked from commit 29055464a03c72762969a2e8734d0d05d4d70e58) - - Some adjustments were needed for a tricky multi-inclusion issue related - to libioP.h. - -Backported from the upsteam release/2.27/master branch, adjusted for -lack of tests-internal support downstream. - -diff --git a/libio/Makefile b/libio/Makefile -index 0cef96141209fe99..1e923da42e45c492 100644 ---- a/libio/Makefile -+++ b/libio/Makefile -@@ -61,7 +61,9 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \ - bug-memstream1 bug-wmemstream1 \ - tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos tst-fseek \ - tst-fwrite-error tst-ftell-active-handler \ -- tst-ftell-append -+ tst-ftell-append \ -+ tst-vtables tst-vtables-interposed -+ - ifeq (yes,$(build-shared)) - # Add test-fopenloc only if shared library is enabled since it depends on - # shared localedata objects. -diff --git a/libio/tst-vtables-common.c b/libio/tst-vtables-common.c -new file mode 100644 -index 0000000000000000..dc8d89c195b95b8d ---- /dev/null -+++ b/libio/tst-vtables-common.c -@@ -0,0 +1,511 @@ -+/* Test for libio vtables and their validation. Common code. -+ Copyright (C) 2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ <http://www.gnu.org/licenses/>. */ -+ -+/* This test provides some coverage for how various stdio functions -+ use the vtables in FILE * objects. The focus is mostly on which -+ functions call which methods, not so much on validating data -+ processing. An initial series of tests check that custom vtables -+ do not work without activation through _IO_init. -+ -+ Note: libio vtables are deprecated feature. Do not use this test -+ as a documentation source for writing custom vtables. See -+ fopencookie for a different way of creating custom stdio -+ streams. */ -+ -+#include <stdbool.h> -+#include <string.h> -+#include <support/capture_subprocess.h> -+#include <support/check.h> -+#include <support/namespace.h> -+#include <support/support.h> -+#include <support/test-driver.h> -+#include <support/xunistd.h> -+ -+/* Data shared between the test subprocess and the test driver in the -+ parent. Note that *shared is reset at the start of the check_call -+ function. */ -+struct shared -+{ -+ /* Expected file pointer for method calls. */ -+ FILE *fp; -+ -+ /* If true, assume that a call to _IO_init is needed to enable -+ custom vtables. */ -+ bool initially_disabled; -+ -+ /* Requested return value for the methods which have one. */ -+ int return_value; -+ -+ /* A value (usually a character) recorded by some of the methods -+ below. */ -+ int value; -+ -+ /* Likewise, for some data. */ -+ char buffer[16]; -+ size_t buffer_length; -+ -+ /* Total number of method calls. */ -+ unsigned int calls; -+ -+ /* Individual method call counts. */ -+ unsigned int calls_finish; -+ unsigned int calls_overflow; -+ unsigned int calls_underflow; -+ unsigned int calls_uflow; -+ unsigned int calls_pbackfail; -+ unsigned int calls_xsputn; -+ unsigned int calls_xsgetn; -+ unsigned int calls_seekoff; -+ unsigned int calls_seekpos; -+ unsigned int calls_setbuf; -+ unsigned int calls_sync; -+ unsigned int calls_doallocate; -+ unsigned int calls_read; -+ unsigned int calls_write; -+ unsigned int calls_seek; -+ unsigned int calls_close; -+ unsigned int calls_stat; -+ unsigned int calls_showmanyc; -+ unsigned int calls_imbue; -+} *shared; -+ -+/* Method implementations which increment the counters in *shared. */ -+ -+static void -+log_method (FILE *fp, const char *name) -+{ -+ if (test_verbose > 0) -+ printf ("info: %s (%p) called\n", name, fp); -+} -+ -+static void -+method_finish (FILE *fp, int dummy) -+{ -+ log_method (fp, __func__); -+ TEST_VERIFY (fp == shared->fp); -+ ++shared->calls; -+ ++shared->calls_finish; -+} -+ -+static int -+method_overflow (FILE *fp, int ch) -+{ -+ log_method (fp, __func__); -+ TEST_VERIFY (fp == shared->fp); -+ ++shared->calls; -+ ++shared->calls_overflow; -+ shared->value = ch; -+ return shared->return_value; -+} -+ -+static int -+method_underflow (FILE *fp) -+{ -+ log_method (fp, __func__); -+ TEST_VERIFY (fp == shared->fp); -+ ++shared->calls; -+ ++shared->calls_underflow; -+ return shared->return_value; -+} -+ -+static int -+method_uflow (FILE *fp) -+{ -+ log_method (fp, __func__); -+ TEST_VERIFY (fp == shared->fp); -+ ++shared->calls; -+ ++shared->calls_uflow; -+ return shared->return_value; -+} -+ -+static int -+method_pbackfail (FILE *fp, int ch) -+{ -+ log_method (fp, __func__); -+ TEST_VERIFY (fp == shared->fp); -+ ++shared->calls; -+ ++shared->calls_pbackfail; -+ shared->value = ch; -+ return shared->return_value; -+} -+ -+static size_t -+method_xsputn (FILE *fp, const void *data, size_t n) -+{ -+ log_method (fp, __func__); -+ TEST_VERIFY (fp == shared->fp); -+ ++shared->calls; -+ ++shared->calls_xsputn; -+ -+ size_t to_copy = n; -+ if (n > sizeof (shared->buffer)) -+ to_copy = sizeof (shared->buffer); -+ memcpy (shared->buffer, data, to_copy); -+ shared->buffer_length = to_copy; -+ return to_copy; -+} -+ -+static size_t -+method_xsgetn (FILE *fp, void *data, size_t n) -+{ -+ log_method (fp, __func__); -+ TEST_VERIFY (fp == shared->fp); -+ ++shared->calls; -+ ++shared->calls_xsgetn; -+ return 0; -+} -+ -+static off64_t -+method_seekoff (FILE *fp, off64_t offset, int dir, int mode) -+{ -+ log_method (fp, __func__); -+ TEST_VERIFY (fp == shared->fp); -+ ++shared->calls; -+ ++shared->calls_seekoff; -+ return shared->return_value; -+} -+ -+static off64_t -+method_seekpos (FILE *fp, off64_t offset, int mode) -+{ -+ log_method (fp, __func__); -+ TEST_VERIFY (fp == shared->fp); -+ ++shared->calls; -+ ++shared->calls_seekpos; -+ return shared->return_value; -+} -+ -+static FILE * -+method_setbuf (FILE *fp, char *buffer, ssize_t length) -+{ -+ log_method (fp, __func__); -+ TEST_VERIFY (fp == shared->fp); -+ ++shared->calls; -+ ++shared->calls_setbuf; -+ return fp; -+} -+ -+static int -+method_sync (FILE *fp) -+{ -+ log_method (fp, __func__); -+ TEST_VERIFY (fp == shared->fp); -+ ++shared->calls; -+ ++shared->calls_sync; -+ return shared->return_value; -+} -+ -+static int -+method_doallocate (FILE *fp) -+{ -+ log_method (fp, __func__); -+ TEST_VERIFY (fp == shared->fp); -+ ++shared->calls; -+ ++shared->calls_doallocate; -+ return shared->return_value; -+} -+ -+static ssize_t -+method_read (FILE *fp, void *data, ssize_t length) -+{ -+ log_method (fp, __func__); -+ TEST_VERIFY (fp == shared->fp); -+ ++shared->calls; -+ ++shared->calls_read; -+ return shared->return_value; -+} -+ -+static ssize_t -+method_write (FILE *fp, const void *data, ssize_t length) -+{ -+ log_method (fp, __func__); -+ TEST_VERIFY (fp == shared->fp); -+ ++shared->calls; -+ ++shared->calls_write; -+ return shared->return_value; -+} -+ -+static off64_t -+method_seek (FILE *fp, off64_t offset, int mode) -+{ -+ log_method (fp, __func__); -+ TEST_VERIFY (fp == shared->fp); -+ ++shared->calls; -+ ++shared->calls_seek; -+ return shared->return_value; -+} -+ -+static int -+method_close (FILE *fp) -+{ -+ log_method (fp, __func__); -+ TEST_VERIFY (fp == shared->fp); -+ ++shared->calls; -+ ++shared->calls_close; -+ return shared->return_value; -+} -+ -+static int -+method_stat (FILE *fp, void *buffer) -+{ -+ log_method (fp, __func__); -+ TEST_VERIFY (fp == shared->fp); -+ ++shared->calls; -+ ++shared->calls_stat; -+ return shared->return_value; -+} -+ -+static int -+method_showmanyc (FILE *fp) -+{ -+ log_method (fp, __func__); -+ TEST_VERIFY (fp == shared->fp); -+ ++shared->calls; -+ ++shared->calls_showmanyc; -+ return shared->return_value; -+} -+ -+static void -+method_imbue (FILE *fp, void *locale) -+{ -+ log_method (fp, __func__); -+ TEST_VERIFY (fp == shared->fp); -+ ++shared->calls; -+ ++shared->calls_imbue; -+} -+ -+/* Our custom vtable. */ -+ -+static const struct _IO_jump_t jumps = -+{ -+ JUMP_INIT_DUMMY, -+ JUMP_INIT (finish, method_finish), -+ JUMP_INIT (overflow, method_overflow), -+ JUMP_INIT (underflow, method_underflow), -+ JUMP_INIT (uflow, method_uflow), -+ JUMP_INIT (pbackfail, method_pbackfail), -+ JUMP_INIT (xsputn, method_xsputn), -+ JUMP_INIT (xsgetn, method_xsgetn), -+ JUMP_INIT (seekoff, method_seekoff), -+ JUMP_INIT (seekpos, method_seekpos), -+ JUMP_INIT (setbuf, method_setbuf), -+ JUMP_INIT (sync, method_sync), -+ JUMP_INIT (doallocate, method_doallocate), -+ JUMP_INIT (read, method_read), -+ JUMP_INIT (write, method_write), -+ JUMP_INIT (seek, method_seek), -+ JUMP_INIT (close, method_close), -+ JUMP_INIT (stat, method_stat), -+ JUMP_INIT (showmanyc, method_showmanyc), -+ JUMP_INIT (imbue, method_imbue) -+}; -+ -+/* Our file implementation. */ -+ -+struct my_file -+{ -+ FILE f; -+ const struct _IO_jump_t *vtable; -+}; -+ -+struct my_file -+my_file_create (void) -+{ -+ return (struct my_file) -+ { -+ /* Disable locking, so that we do not have to set up a lock -+ pointer. */ -+ .f._flags = _IO_USER_LOCK, -+ -+ /* Copy the offset from the an initialized handle, instead of -+ figuring it out from scratch. */ -+ .f._vtable_offset = stdin->_vtable_offset, -+ -+ .vtable = &jumps, -+ }; -+} -+ -+/* Initial tests which do not enable vtable compatibility. */ -+ -+/* Inhibit GCC optimization of fprintf. */ -+typedef int (*fprintf_type) (FILE *, const char *, ...); -+static const volatile fprintf_type fprintf_ptr = &fprintf; -+ -+static void -+without_compatibility_fprintf (void *closure) -+{ -+ /* This call should abort. */ -+ fprintf_ptr (shared->fp, " "); -+ _exit (1); -+} -+ -+static void -+without_compatibility_fputc (void *closure) -+{ -+ /* This call should abort. */ -+ fputc (' ', shared->fp); -+ _exit (1); -+} -+ -+static void -+without_compatibility_fgetc (void *closure) -+{ -+ /* This call should abort. */ -+ fgetc (shared->fp); -+ _exit (1); -+} -+ -+static void -+without_compatibility_fflush (void *closure) -+{ -+ /* This call should abort. */ -+ fflush (shared->fp); -+ _exit (1); -+} -+ -+/* Exit status after abnormal termination. */ -+static int termination_status; -+ -+static void -+init_termination_status (void) -+{ -+ pid_t pid = xfork (); -+ if (pid == 0) -+ abort (); -+ xwaitpid (pid, &termination_status, 0); -+ -+ TEST_VERIFY (WIFSIGNALED (termination_status)); -+ TEST_COMPARE (WTERMSIG (termination_status), SIGABRT); -+} -+ -+static void -+check_for_termination (const char *name, void (*callback) (void *)) -+{ -+ struct my_file file = my_file_create (); -+ shared->fp = &file.f; -+ shared->return_value = -1; -+ shared->calls = 0; -+ struct support_capture_subprocess proc -+ = support_capture_subprocess (callback, NULL); -+ support_capture_subprocess_check (&proc, name, termination_status, -+ sc_allow_stderr); -+ const char *message -+ = "Fatal error: glibc detected an invalid stdio handle\n"; -+ TEST_COMPARE_BLOB (proc.err.buffer, proc.err.length, -+ message, strlen (message)); -+ TEST_COMPARE (shared->calls, 0); -+ support_capture_subprocess_free (&proc); -+} -+ -+/* The test with vtable validation disabled. */ -+ -+/* This function does not have a prototype in libioP.h to prevent -+ accidental use from within the library (which would disable vtable -+ verification). */ -+void _IO_init (FILE *fp, int flags); -+ -+static void -+with_compatibility_fprintf (void *closure) -+{ -+ TEST_COMPARE (fprintf_ptr (shared->fp, "A%sCD", "B"), 4); -+ TEST_COMPARE (shared->calls, 3); -+ TEST_COMPARE (shared->calls_xsputn, 3); -+ TEST_COMPARE_BLOB (shared->buffer, shared->buffer_length, -+ "CD", 2); -+} -+ -+static void -+with_compatibility_fputc (void *closure) -+{ -+ shared->return_value = '@'; -+ TEST_COMPARE (fputc ('@', shared->fp), '@'); -+ TEST_COMPARE (shared->calls, 1); -+ TEST_COMPARE (shared->calls_overflow, 1); -+ TEST_COMPARE (shared->value, '@'); -+} -+ -+static void -+with_compatibility_fgetc (void *closure) -+{ -+ shared->return_value = 'X'; -+ TEST_COMPARE (fgetc (shared->fp), 'X'); -+ TEST_COMPARE (shared->calls, 1); -+ TEST_COMPARE (shared->calls_uflow, 1); -+} -+ -+static void -+with_compatibility_fflush (void *closure) -+{ -+ TEST_COMPARE (fflush (shared->fp), 0); -+ TEST_COMPARE (shared->calls, 1); -+ TEST_COMPARE (shared->calls_sync, 1); -+} -+ -+/* Call CALLBACK in a subprocess, after setting up a custom file -+ object and updating shared->fp. */ -+static void -+check_call (const char *name, void (*callback) (void *), -+ bool initially_disabled) -+{ -+ *shared = (struct shared) -+ { -+ .initially_disabled = initially_disabled, -+ }; -+ -+ /* Set up a custom file object. */ -+ struct my_file file = my_file_create (); -+ shared->fp = &file.f; -+ if (shared->initially_disabled) -+ _IO_init (shared->fp, file.f._flags); -+ -+ if (test_verbose > 0) -+ printf ("info: calling test %s\n", name); -+ support_isolate_in_subprocess (callback, NULL); -+} -+ -+/* Run the tests. INITIALLY_DISABLED indicates whether custom vtables -+ are disabled when the test starts. */ -+static int -+run_tests (bool initially_disabled) -+{ -+ /* The test relies on fatal error messages being printed to standard -+ error. */ -+ setenv ("LIBC_FATAL_STDERR_", "1", 1); -+ -+ shared = support_shared_allocate (sizeof (*shared)); -+ shared->initially_disabled = initially_disabled; -+ init_termination_status (); -+ -+ if (initially_disabled) -+ { -+ check_for_termination ("fprintf", without_compatibility_fprintf); -+ check_for_termination ("fputc", without_compatibility_fputc); -+ check_for_termination ("fgetc", without_compatibility_fgetc); -+ check_for_termination ("fflush", without_compatibility_fflush); -+ } -+ -+ check_call ("fprintf", with_compatibility_fprintf, initially_disabled); -+ check_call ("fputc", with_compatibility_fputc, initially_disabled); -+ check_call ("fgetc", with_compatibility_fgetc, initially_disabled); -+ check_call ("fflush", with_compatibility_fflush, initially_disabled); -+ -+ support_shared_free (shared); -+ shared = NULL; -+ -+ return 0; -+} -diff --git a/libio/tst-vtables-interposed.c b/libio/tst-vtables-interposed.c -new file mode 100644 -index 0000000000000000..c8f4e8c7c386af39 ---- /dev/null -+++ b/libio/tst-vtables-interposed.c -@@ -0,0 +1,37 @@ -+/* Test for libio vtables and their validation. Enabled through interposition. -+ Copyright (C) 2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ <http://www.gnu.org/licenses/>. */ -+ -+/* Provide an interposed definition of the standard file handles with -+ our own vtable. stdout/stdin/stderr will not work as a result, but -+ a succesful test does not print anything, so this is fine. */ -+static const struct _IO_jump_t jumps; -+#define _IO_file_jumps jumps -+#include "stdfiles.c" -+ -+#include "tst-vtables-common.c" -+ -+static int -+do_test (void) -+{ -+ return run_tests (false); -+} -+ -+/* Calling setvbuf in the test driver is not supported with our -+ interposed file handles. */ -+#define TEST_NO_SETVBUF -+#include <support/test-driver.c> -diff --git a/libio/tst-vtables.c b/libio/tst-vtables.c -new file mode 100644 -index 0000000000000000..f16acf5d23b0fff6 ---- /dev/null -+++ b/libio/tst-vtables.c -@@ -0,0 +1,29 @@ -+/* Test for libio vtables and their validation. Initially disabled case. -+ Copyright (C) 2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ <http://www.gnu.org/licenses/>. */ -+ -+#include "libioP.h" -+ -+#include "tst-vtables-common.c" -+ -+static int -+do_test (void) -+{ -+ return run_tests (true); -+} -+ -+#include <support/test-driver.c> diff --git a/SOURCES/glibc-rh1705899-6.patch b/SOURCES/glibc-rh1705899-6.patch deleted file mode 100644 index 4ff1252..0000000 --- a/SOURCES/glibc-rh1705899-6.patch +++ /dev/null @@ -1,24 +0,0 @@ -commit 2d1c89a5d7c872a1109768f50e2508cf9a4b0348 -Author: Florian Weimer <fweimer@redhat.com> -Date: Wed Jun 20 09:45:19 2018 +0200 - - libio: Avoid ptrdiff_t overflow in IO_validate_vtable - - If the candidate pointer is sufficiently far away from - __start___libc_IO_vtables, the result might not fit into ptrdiff_t. - -diff --git a/libio/libioP.h b/libio/libioP.h -index b60244ac5fc3d908..f1576381500ffc85 100644 ---- a/libio/libioP.h -+++ b/libio/libioP.h -@@ -957,8 +957,8 @@ IO_validate_vtable (const struct _IO_jump_t *vtable) - /* Fast path: The vtable pointer is within the __libc_IO_vtables - section. */ - uintptr_t section_length = __stop___libc_IO_vtables - __start___libc_IO_vtables; -- const char *ptr = (const char *) vtable; -- uintptr_t offset = ptr - __start___libc_IO_vtables; -+ uintptr_t ptr = (uintptr_t) vtable; -+ uintptr_t offset = ptr - (uintptr_t) __start___libc_IO_vtables; - if (__glibc_unlikely (offset >= section_length)) - /* The vtable pointer is not in the expected section. Use the - slow path, which will terminate the process if necessary. */ diff --git a/SPECS/glibc.spec b/SPECS/glibc.spec index 5e9fe6c..ebf161b 100644 --- a/SPECS/glibc.spec +++ b/SPECS/glibc.spec @@ -1,6 +1,6 @@ %define glibcsrcdir glibc-2.17-c758a686 %define glibcversion 2.17 -%define glibcrelease 260%{?dist}.6 +%define glibcrelease 292%{?dist} ############################################################################## # We support the following options: # --with/--without, @@ -258,11 +258,6 @@ Patch0068: glibc-rh1349982.patch # These changes were brought forward from RHEL 6 for compatibility Patch0069: glibc-rh1448107.patch - -# Armhfp build issue -Patch9998: glibc-armhfp-ELF_MACHINE_NO_REL-undefined.patch -Patch9999: glibc-rh1256317-armhfp-build-issue.patch - ############################################################################## # # Patches from upstream @@ -942,6 +937,7 @@ Patch1757: glibc-rh1337242.patch Patch17580: glibc-rh1418978-max_align_t.patch Patch1758: glibc-rh1418978-0.patch Patch1759: glibc-rh1418978-1.patch +Patch2752: glibc-rh1418978-1a.patch Patch1760: glibc-rh1418978-2-1.patch Patch1761: glibc-rh1418978-2-2.patch Patch1762: glibc-rh1418978-2-3.patch @@ -1164,6 +1160,10 @@ Patch1900: glibc-rh1534635.patch Patch1901: glibc-rh1529982.patch Patch1902: glibc-rh1523119-compat-symbols.patch + +# RHBZ #1609067: Backfort of upstream [#15804] - fix race condition in pldd +Patch1903: glibc-rh1609067.patch + Patch2500: glibc-rh1505492-nscd_stat.patch Patch2501: glibc-rh1564638.patch Patch2502: glibc-rh1566623.patch @@ -1422,17 +1422,63 @@ Patch2748: glibc-rh1401665-2.patch Patch2749: glibc-rh1401665-3.patch Patch2750: glibc-rh1401665-4.patch Patch2751: glibc-rh1401665-5.patch -Patch2752: glibc-rh1661244.patch -Patch2753: glibc-rh1661242-1.patch -Patch2754: glibc-rh1661242-2.patch -Patch2755: glibc-rh1693152-1.patch -Patch2756: glibc-rh1693152-2.patch -Patch2757: glibc-rh1705899-1.patch -Patch2758: glibc-rh1705899-2.patch -Patch2759: glibc-rh1705899-3.patch -Patch2760: glibc-rh1705899-4.patch -Patch2761: glibc-rh1705899-5.patch -Patch2762: glibc-rh1705899-6.patch +Patch2753: glibc-rh1595191-1.patch +Patch2754: glibc-rh1595191-2.patch +Patch2755: glibc-rh1595191-3.patch +Patch2756: glibc-rh1595191-4.patch +Patch2757: glibc-rh1647490-1.patch +Patch2758: glibc-rh1647490-2.patch +Patch2759: glibc-rh1647490-3.patch +Patch2760: glibc-rh1647490-4.patch +Patch2761: glibc-rh1647490-5.patch +Patch2762: glibc-rh1639524.patch +Patch2763: glibc-rh1647490-6.patch +Patch2764: glibc-rh1579730-1.patch +Patch2765: glibc-rh1579730-2.patch +Patch2766: glibc-rh1579730-3.patch +Patch2767: glibc-rh1630440-1.patch +Patch2768: glibc-rh1630440-2.patch +Patch2769: glibc-rh1646373.patch +Patch2770: glibc-rh1591268.patch +Patch2771: glibc-rh1592475-1.patch +Patch2772: glibc-rh1592475-2.patch +Patch2773: glibc-rh1592475-3.patch +Patch2774: glibc-rh1657015-1.patch +Patch2775: glibc-rh1657015-2.patch +Patch2776: glibc-rh1657015-3.patch +Patch2777: glibc-rh1657015-4.patch +Patch2778: glibc-rh1673465-1.patch +Patch2779: glibc-rh1673465-2.patch +Patch2780: glibc-rh1673465-3.patch +Patch2781: glibc-rh1673465-4.patch +Patch2782: glibc-rh1673465-5.patch +Patch2783: glibc-rh1673465-6.patch +Patch2784: glibc-rh1673465-7.patch +Patch2785: glibc-rh1039304-1.patch +Patch2786: glibc-rh1039304-2.patch +Patch2787: glibc-rh1039304-3.patch +Patch2788: glibc-rh1039304-4.patch +Patch2789: glibc-rh1443872.patch +Patch2790: glibc-rh1472832.patch +Patch2791: glibc-rh1673465-8.patch +Patch2792: glibc-rh1443872-2.patch +Patch2793: glibc-rh1579354.patch +Patch2794: glibc-rh1579739.patch +Patch2795: glibc-rh1641981.patch +Patch2796: glibc-rh1579739-2.patch +Patch2797: glibc-rh1684874-1.patch +Patch2798: glibc-rh1684874-2.patch +Patch2799: glibc-rh1488370.patch +Patch2800: glibc-rh1662842.patch +Patch2801: glibc-rh1163509-1.patch +Patch2802: glibc-rh1163509-2.patch +Patch2803: glibc-rh1163509-3.patch +Patch2804: glibc-rh1163509-4.patch +Patch2805: glibc-rh1163509-5.patch +Patch2806: glibc-rh1555189-1.patch +Patch2807: glibc-rh1555189-2.patch +Patch2808: glibc-rh1427734-1.patch +Patch2809: glibc-rh1427734-2.patch ############################################################################## # @@ -1634,6 +1680,9 @@ BuildRequires: systemd # the required semantics. BuildRequires: gcc >= 4.8.5-25 +# This RPM version introduced --g-libs. +BuildRequires: rpm-build >= 4.11.3-38.el7 + %define enablekernel 2.6.32 Conflicts: kernel < %{enablekernel} %define target %{_target_cpu}-redhat-linux @@ -2397,6 +2446,7 @@ package or when debugging this package. %patch17580 -p1 %patch1758 -p1 %patch1759 -p1 +%patch2752 -p1 %patch1760 -p1 %patch1761 -p1 %patch1762 -p1 @@ -2577,6 +2627,7 @@ package or when debugging this package. %patch1900 -p1 %patch1901 -p1 %patch1902 -p1 +%patch1903 -p1 %patch2500 -p1 %patch2501 -p1 %patch2502 -p1 @@ -2833,7 +2884,6 @@ package or when debugging this package. %patch2749 -p1 %patch2750 -p1 %patch2751 -p1 -%patch2752 -p1 %patch2753 -p1 %patch2754 -p1 %patch2755 -p1 @@ -2844,11 +2894,53 @@ package or when debugging this package. %patch2760 -p1 %patch2761 -p1 %patch2762 -p1 - -%ifarch %{arm} -%patch9998 -p1 -%patch9999 -p1 -%endif +%patch2763 -p1 +%patch2764 -p1 +%patch2765 -p1 +%patch2766 -p1 +%patch2767 -p1 +%patch2768 -p1 +%patch2769 -p1 +%patch2770 -p1 +%patch2771 -p1 +%patch2772 -p1 +%patch2773 -p1 +%patch2774 -p1 +%patch2775 -p1 +%patch2776 -p1 +%patch2777 -p1 +%patch2778 -p1 +%patch2779 -p1 +%patch2780 -p1 +%patch2781 -p1 +%patch2782 -p1 +%patch2783 -p1 +%patch2784 -p1 +%patch2785 -p1 +%patch2786 -p1 +%patch2787 -p1 +%patch2788 -p1 +%patch2789 -p1 +%patch2790 -p1 +%patch2791 -p1 +%patch2792 -p1 +%patch2793 -p1 +%patch2794 -p1 +%patch2795 -p1 +%patch2796 -p1 +%patch2797 -p1 +%patch2798 -p1 +%patch2799 -p1 +%patch2800 -p1 +%patch2801 -p1 +%patch2802 -p1 +%patch2803 -p1 +%patch2804 -p1 +%patch2805 -p1 +%patch2806 -p1 +%patch2807 -p1 +%patch2808 -p1 +%patch2809 -p1 ############################################################################## # %%prep - Additional prep required... @@ -2889,6 +2981,9 @@ touch `find . -name configure` # Ensure *-kw.h files are current to prevent regenerating them. touch locale/programs/*-kw.h +# RHBZ #1640764: Ensure plural.c is current to prevent regenerating it (bison) +touch intl/plural.c + ############################################################################## # Build glibc... ############################################################################## @@ -3725,7 +3820,7 @@ ls -l $RPM_BUILD_ROOT/usr/bin/getconf ls -l $RPM_BUILD_ROOT/usr/libexec/getconf eu-readelf -hS $RPM_BUILD_ROOT/usr/bin/getconf $RPM_BUILD_ROOT/usr/libexec/getconf/* -find_debuginfo_args='--strict-build-id -g' +find_debuginfo_args='--strict-build-id --g-libs' %ifarch %{debuginfocommonarches} find_debuginfo_args="$find_debuginfo_args \ -l common.filelist -l utils.filelist -l nscd.filelist \ @@ -4012,20 +4107,102 @@ rm -f *.filelist* %endif %changelog -* Fri May 3 2019 Florian Weimer <fweimer@redhat.com> - 2.17-260.6 -- Backport libio vtable validation improvements (#1705899) +* Tue Apr 30 2019 Arjun Shankar <arjun@redhat.com> - 2.17-292 +- Avoid iconv hang on invalid multi-byte sequences (#1427734) + +* Tue Apr 30 2019 Florian Weimer <fweimer@redhat.com> - 2.17-291 +- Use versioned Obsoletes: for nss_db (#1703565) + +* Mon Apr 1 2019 Florian Weimer <fweimer@redhat.com> - 2.17-290 +- Adjust to find-debuginfo.sh changes (#1661508) + +* Mon Apr 1 2019 Florian Weimer <fweimer@redhat.com> - 2.17-289 +- ja_JP: Add new Japanese Era name (#1555189) + +* Wed Mar 27 2019 Arjun Shankar <arjun@redhat.com> - 2.17-288 +- Unify and improve pthread_once implementation for all architectures (#1163509) + +* Tue Mar 26 2019 DJ Delorie <dj@redhat.com> - 2.17.287 +- malloc: Always call memcpy in _int_realloc (#1662842) + +* Wed Mar 20 2019 Carlos O'Donell <carlos@redhat.com> - 2.17-286 +- Update comments in nscd.conf and nsswitch.conf (#1488370) + +* Tue Mar 19 2019 Arjun Shankar <arjun@redhat.com> - 2.17-285 +- intl: Ensure plural.c is current to prevent regenerating it (#1640764) + +* Tue Mar 5 2019 Florian Weimer <fweimer@redhat.com> - 2.17-284 +- Update <netinet/in.h> to include IP*_PMTUDISC_OMIT and others (#1684874) + +* Fri Mar 1 2019 Florian Weimer <fweimer@redhat.com> - 2.17-283 +- elf: Adjust the big PT_NOTE test to exercise the bug in more cases (#1579739) + +* Fri Mar 1 2019 Florian Weimer <fweimer@redhat.com> - 2.17-282 +- x86: Fix incorrect selection of string functions (#1641981) + +* Fri Mar 1 2019 Florian Weimer <fweimer@redhat.com> - 2.17-281 +- elf: Avoid stack overflow with large PT_NOTE segments (#1579739) + +* Fri Mar 1 2019 Florian Weimer <fweimer@redhat.com> - 2.17-280 +- resolv: Fully initialize sendmmsg argument data (#1579354) + +* Fri Mar 1 2019 Florian Weimer <fweimer@redhat.com> - 2.17-279 +- Improve formatting of Netlink error messages (#1443872) + +* Fri Mar 1 2019 Florian Weimer <fweimer@redhat.com> - 2.17-278 +- Run resolv/tst-inet_aton_exact test (#1673465) + +* Thu Feb 28 2019 Florian Weimer <fweimer@redhat.com> - 2.17-277 +- getifaddrs could return interfaces with ifa_name set to NULL (#1472832) + +* Thu Feb 28 2019 Florian Weimer <fweimer@redhat.com> - 2.17-276 +- Terminate process on invalid netlink response from kernel (#1443872) + +* Thu Feb 28 2019 Florian Weimer <fweimer@redhat.com> - 2.17-275 +- resolv: Support host names with trailing dashes (#1039304) + +* Thu Feb 28 2019 Florian Weimer <fweimer@redhat.com> - 2.17-274 +- CVE-2016-10739: Reject trailing characters in getaddrinfo (#1673465) + +* Thu Feb 28 2019 Carlos O'Donell <carlos@redhat.com> - 2.17-273 +- Update syscall list for Linux 4.20 (#1657015) + +* Wed Feb 20 2019 Arjun Shankar <arjun@redhat.com> - 2.17-272 +- glibc-headers: Add ipc STAT_ANY constants (#1592475) + +* Wed Feb 13 2019 Arjun Shankar <arjun@redhat.com> - 2.17-271 +- localedata: Make IBM273 compatible with ISO-8859-1 (#1591268) + +* Mon Jan 28 2019 Patsy Griffin Franklin <pfrankli@redhat.com> - 2.17-270 +- Fix pldd race condition that may leave the process stopped after + detaching. (#1609067) + +* Tue Jan 22 2019 DJ Delorie <dj@redhat.com> - 2.17-269 +- libanl: properly cleanup if first helper thread creation failed (#1646373) + +* Mon Jan 21 2019 DJ Delorie <dj@redhat.com> - 2.17-268 +- Add note about missing test case for BZ1457479 (#1635325) + +* Thu Dec 20 2018 Florian Weimer <fweimer@redhat.com> - 2.17-267 +- elf: Fix data race in _dl_profile_fixup (#1630440) + +* Wed Dec 19 2018 Florian Weimer <fweimer@redhat.com> - 2.17-266 +- Fix i386 sigaction sa_restorer initialization (#1579730) + +* Wed Dec 19 2018 Florian Weimer <fweimer@redhat.com> - 2.17-265 +- Fix compilation error in stdlib/tst-strtod-overflow.c (#1647490) -* Tue Apr 30 2019 Florian Weimer <fweimer@redhat.com> - 2.17-260.5 -- Use versioned Obsoletes: for nss_db (#1704593) +* Thu Dec 13 2018 DJ Delorie <dj@redhat.com> - 2.17-264 +- aarch64: Disable lazy symbol binding of TLSDESC (#1639524) -* Mon Apr 1 2019 Florian Weimer <fweimer@redhat.com> - 2.17-260.4 -- ja_JP: Add new Japanese Era name (#1693152) +* Fri Nov 9 2018 Florian Weimer <fweimer@redhat.com> - 2.17-263 +- Reduce RAM requirements for stdlib/test-bz22786 (#1647490) -* Thu Jan 3 2019 Florian Weimer <fweimer@redhat.com> - 2.17-260.3 -- elf: Fix data race in _dl_profile_fixup (#1661242) +* Wed Nov 7 2018 Florian Weimer <fweimer@redhat.com> - 2.17-262 +- libio vtable validation improvements (#1595191) -* Thu Dec 20 2018 Florian Weimer <fweimer@redhat.com> - 2.17-260.1 -- aarch64: Disable lazy symbol binding of TLSDESC (#1661244) +* Wed Nov 7 2018 Florian Weimer <fweimer@redhat.com> - 2.17-261 +- Update support/ to the most recent upstream version (#1595191) * Wed Jun 27 2018 Patsy Franklin <pfrankli@redhat.com> - 2.17-260 - Update glibc-rh1560641.patch to initialize pad outside