diff --git a/SOURCES/glibc-rh1871394-1.patch b/SOURCES/glibc-rh1871394-1.patch new file mode 100644 index 0000000..bc36d64 --- /dev/null +++ b/SOURCES/glibc-rh1871394-1.patch @@ -0,0 +1,47 @@ +commit 75870237ff3bb363447b03f4b0af100227570910 +Author: Sunil K Pandey +Date: Fri Jun 12 08:57:16 2020 -0700 + + Fix avx2 strncmp offset compare condition check [BZ #25933] + + strcmp-avx2.S: In avx2 strncmp function, strings are compared in + chunks of 4 vector size(i.e. 32x4=128 byte for avx2). After first 4 + vector size comparison, code must check whether it already passed + the given offset. This patch implement avx2 offset check condition + for strncmp function, if both string compare same for first 4 vector + size. + +diff --git a/sysdeps/x86_64/multiarch/strcmp-avx2.S b/sysdeps/x86_64/multiarch/strcmp-avx2.S +index 5f88a68262..d42b04b54f 100644 +--- a/sysdeps/x86_64/multiarch/strcmp-avx2.S ++++ b/sysdeps/x86_64/multiarch/strcmp-avx2.S +@@ -591,7 +591,14 @@ L(loop_cross_page_2_vec): + movl $(PAGE_SIZE / (VEC_SIZE * 4) - 1), %esi + + testq %rdi, %rdi ++# ifdef USE_AS_STRNCMP ++ /* At this point, if %rdi value is 0, it already tested ++ VEC_SIZE*4+%r10 byte starting from %rax. This label ++ checks whether strncmp maximum offset reached or not. */ ++ je L(string_nbyte_offset_check) ++# else + je L(back_to_loop) ++# endif + tzcntq %rdi, %rcx + addq %r10, %rcx + /* Adjust for number of bytes skipped. */ +@@ -627,6 +634,14 @@ L(loop_cross_page_2_vec): + VZEROUPPER + ret + ++# ifdef USE_AS_STRNCMP ++L(string_nbyte_offset_check): ++ leaq (VEC_SIZE * 4)(%r10), %r10 ++ cmpq %r10, %r11 ++ jbe L(zero) ++ jmp L(back_to_loop) ++# endif ++ + .p2align 4 + L(cross_page_loop): + /* Check one byte/dword at a time. */ diff --git a/SOURCES/glibc-rh1871394-2.patch b/SOURCES/glibc-rh1871394-2.patch new file mode 100644 index 0000000..11ae1e3 --- /dev/null +++ b/SOURCES/glibc-rh1871394-2.patch @@ -0,0 +1,69 @@ +commit f7e3f92b7c45663be808279a43b5221c16001229 +Author: H.J. Lu +Date: Thu May 7 07:29:46 2020 -0700 + + strncmp: Add a testcase for page boundary [BZ #25933] + + Add a strncmp testcase to cover cases where one of strings ends on the + page boundary with the maximum string length less than the number bytes + of each AVX2 loop iteration and different offsets from page boundary. + + The updated string/test-strncmp fails on Intel Core i7-8559U without + + ommit 1c6432316bc434a72108d7b0c7cfbfdde64c3124 + Author: Sunil K Pandey + Date: Fri Jun 12 08:57:16 2020 -0700 + + Fix avx2 strncmp offset compare condition check [BZ #25933] + +diff --git a/string/test-strncmp.c b/string/test-strncmp.c +index d961ac4493..962679b384 100644 +--- a/string/test-strncmp.c ++++ b/string/test-strncmp.c +@@ -403,6 +403,38 @@ check2 (void) + free (s2); + } + ++static void ++check3 (void) ++{ ++ /* To trigger bug 25933, we need a size that is equal to the vector ++ length times 4. In the case of AVX2 for Intel, we need 32 * 4. We ++ make this test generic and run it for all architectures as additional ++ boundary testing for such related algorithms. */ ++ size_t size = 32 * 4; ++ CHAR *s1 = (CHAR *) (buf1 + (BUF1PAGES - 1) * page_size); ++ CHAR *s2 = (CHAR *) (buf2 + (BUF1PAGES - 1) * page_size); ++ int exp_result; ++ ++ memset (s1, 'a', page_size); ++ memset (s2, 'a', page_size); ++ s1[(page_size / CHARBYTES) - 1] = (CHAR) 0; ++ ++ /* Iterate over a size that is just below where we expect the bug to ++ trigger up to the size we expect will trigger the bug e.g. [99-128]. ++ Likewise iterate the start of two strings between 30 and 31 bytes ++ away from the boundary to simulate alignment changes. */ ++ for (size_t s = 99; s <= size; s++) ++ for (size_t s1a = 30; s1a < 32; s1a++) ++ for (size_t s2a = 30; s2a < 32; s2a++) ++ { ++ CHAR *s1p = s1 + (page_size / CHARBYTES - s) - s1a; ++ CHAR *s2p = s2 + (page_size / CHARBYTES - s) - s2a; ++ exp_result = SIMPLE_STRNCMP (s1p, s2p, s); ++ FOR_EACH_IMPL (impl, 0) ++ check_result (impl, s1p, s2p, s, exp_result); ++ } ++} ++ + int + test_main (void) + { +@@ -412,6 +444,7 @@ test_main (void) + + check1 (); + check2 (); ++ check3 (); + + printf ("%23s", ""); + FOR_EACH_IMPL (impl, 0) diff --git a/SOURCES/glibc-rh1871394-3.patch b/SOURCES/glibc-rh1871394-3.patch new file mode 100644 index 0000000..fd47aff --- /dev/null +++ b/SOURCES/glibc-rh1871394-3.patch @@ -0,0 +1,60 @@ +commit 659c0411880328ed341ca26b43d069ec5269a8b5 +Author: H.J. Lu +Date: Thu Jun 11 09:03:56 2020 -0700 + + strcmp: Add a testcase for page boundary + + Add a strcmp testcase to cover cases where both strings end on the page + boundary. + +diff --git a/string/test-strcmp.c b/string/test-strcmp.c +index 8d4784de80..6a840fc04b 100644 +--- a/string/test-strcmp.c ++++ b/string/test-strcmp.c +@@ -359,6 +359,38 @@ check (void) + } + } + ++static void ++check2 (void) ++{ ++ /* To trigger bug 25933, we need a size that is equal to the vector ++ length times 4. In the case of AVX2 for Intel, we need 32 * 4. We ++ make this test generic and run it for all architectures as additional ++ boundary testing for such related algorithms. */ ++ size_t size = 32 * 4; ++ CHAR *s1 = (CHAR *) (buf1 + (BUF1PAGES - 1) * page_size); ++ CHAR *s2 = (CHAR *) (buf2 + (BUF1PAGES - 1) * page_size); ++ int exp_result; ++ ++ memset (s1, 'a', page_size); ++ memset (s2, 'a', page_size); ++ s1[(page_size / CHARBYTES) - 1] = (CHAR) 0; ++ s2[(page_size / CHARBYTES) - 1] = (CHAR) 0; ++ ++ /* Iterate over a size that is just below where we expect the bug to ++ trigger up to the size we expect will trigger the bug e.g. [99-128]. ++ Likewise iterate the start of two strings between 30 and 31 bytes ++ away from the boundary to simulate alignment changes. */ ++ for (size_t s = 99; s <= size; s++) ++ for (size_t s1a = 30; s1a < 32; s1a++) ++ for (size_t s2a = 30; s2a < 32; s2a++) ++ { ++ CHAR *s1p = s1 + (page_size / CHARBYTES - s) - s1a; ++ CHAR *s2p = s2 + (page_size / CHARBYTES - s) - s2a; ++ exp_result = SIMPLE_STRCMP (s1p, s2p); ++ FOR_EACH_IMPL (impl, 0) ++ check_result (impl, s1p, s2p, exp_result); ++ } ++} + + int + test_main (void) +@@ -367,6 +399,7 @@ test_main (void) + + test_init (); + check(); ++ check2 (); + + printf ("%23s", ""); + FOR_EACH_IMPL (impl, 0) diff --git a/SOURCES/glibc-rh1871395-1.patch b/SOURCES/glibc-rh1871395-1.patch new file mode 100644 index 0000000..8f87702 --- /dev/null +++ b/SOURCES/glibc-rh1871395-1.patch @@ -0,0 +1,55 @@ +commit 0792c8ae1aebf538de45ff9a0e2e401a60525de2 +Author: Stefan Liebler +Date: Fri Jun 26 09:45:11 2020 +0200 + + S390: Optimize __memcpy_z196. + + This patch introduces an extra loop without pfd instructions + as it turned out that the pfd instructions are usefull + for copies >=64KB but are counterproductive for smaller copies. + +diff --git a/sysdeps/s390/memcpy-z900.S b/sysdeps/s390/memcpy-z900.S +index f2e9aaeb2d..dc2f491ec3 100644 +--- a/sysdeps/s390/memcpy-z900.S ++++ b/sysdeps/s390/memcpy-z900.S +@@ -184,25 +184,34 @@ ENTRY(MEMCPY_Z196) + je .L_Z196_4 + .L_Z196_start2: + aghi %r4,-1 +- srlg %r5,%r4,8 +- ltgr %r5,%r5 ++ risbg %r5,%r4,8,128+63,56 # r0 = r5 / 256 + jne .L_Z196_5 + .L_Z196_3: + exrl %r4,.L_Z196_14 + .L_Z196_4: + br %r14 + .L_Z196_5: +- cgfi %r5,262144 # Switch to mvcle for copies >64MB +- jh __memcpy_mvcle ++ cgfi %r5,255 # Switch to loop with pfd for copies >=64kB ++ jh .L_Z196_6 + .L_Z196_2: +- pfd 1,768(%r3) +- pfd 2,768(%r1) + mvc 0(256,%r1),0(%r3) + aghi %r5,-1 + la %r1,256(%r1) + la %r3,256(%r3) + jne .L_Z196_2 + j .L_Z196_3 ++.L_Z196_6: ++ cgfi %r5,262144 # Switch to mvcle for copies >64MB ++ jh __memcpy_mvcle ++.L_Z196_7: ++ pfd 1,1024(%r3) ++ pfd 2,1024(%r1) ++ mvc 0(256,%r1),0(%r3) ++ aghi %r5,-1 ++ la %r1,256(%r1) ++ la %r3,256(%r3) ++ jne .L_Z196_7 ++ j .L_Z196_3 + .L_Z196_14: + mvc 0(1,%r1),0(%r3) + END(MEMCPY_Z196) diff --git a/SOURCES/glibc-rh1871395-2.patch b/SOURCES/glibc-rh1871395-2.patch new file mode 100644 index 0000000..d215b5f --- /dev/null +++ b/SOURCES/glibc-rh1871395-2.patch @@ -0,0 +1,54 @@ +commit 1d21fb1061cbeb50414a8f371abb36548d90f150 +Author: Stefan Liebler +Date: Fri Jun 26 09:45:11 2020 +0200 + + S390: Optimize __memset_z196. + + It turned out that an 256b-mvc instruction which depends on the + result of a previous 256b-mvc instruction is counterproductive. + Therefore this patch adjusts the 256b-loop by storing the + first byte with stc and setting the remaining 255b with mvc. + Now the 255b-mvc instruction depends on the stc instruction. + +diff --git a/sysdeps/s390/memset-z900.S b/sysdeps/s390/memset-z900.S +index ca3eac0522..1e0c334156 100644 +--- a/sysdeps/s390/memset-z900.S ++++ b/sysdeps/s390/memset-z900.S +@@ -157,28 +157,27 @@ ENTRY(MEMSET_Z196) + # if !defined __s390x__ + llgfr %r4,%r4 + # endif /* !defined __s390x__ */ +- ltgr %r4,%r4 +- je .L_Z196_4 ++ clgfi %r4,1 ++ jl .L_Z196_4 # n == 0 + stc %r3,0(%r2) ++ je .L_Z196_4 # n == 1 ++ aghi %r4,-2 + lgr %r1,%r2 +- cghi %r4,1 +- je .L_Z196_4 +- aghi %r4,-2 +- srlg %r5,%r4,8 +- ltgr %r5,%r5 +- jne .L_Z196_1 ++ risbg %r5,%r4,8,128+63,56 # r5 = n / 256 ++ jne .L_Z196_1 # Jump away if r5 != 0 + .L_Z196_3: + exrl %r4,.L_Z196_17 + .L_Z196_4: + br %r14 + .L_Z196_1: + cgfi %r5,1048576 +- jh __memset_mvcle # Switch to mvcle for >256MB ++ jh __memset_mvcle # Switch to mvcle for >256MB + .L_Z196_2: + pfd 2,1024(%r1) +- mvc 1(256,%r1),0(%r1) ++ mvc 1(255,%r1),0(%r1) + aghi %r5,-1 + la %r1,256(%r1) ++ stc %r3,0(%r1) + jne .L_Z196_2 + j .L_Z196_3 + .L_Z196_17: diff --git a/SOURCES/glibc-rh1871397-1.patch b/SOURCES/glibc-rh1871397-1.patch new file mode 100644 index 0000000..bf1e46a --- /dev/null +++ b/SOURCES/glibc-rh1871397-1.patch @@ -0,0 +1,233 @@ +From 299210c1fa67e2dfb564475986fce11cd33db9ad Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 16 Jul 2020 16:12:46 +0200 +Subject: [PATCH 01/11] nss_files: Consolidate file opening in + __nss_files_fopen + +Tested-by: Carlos O'Donell +Reviewed-by: Carlos O'Donell +--- + include/nss_files.h | 28 ++++++++++++++++++++++++ + nss/Makefile | 2 +- + nss/Versions | 1 + + nss/nss_files/files-XXX.c | 3 ++- + nss/nss_files/files-alias.c | 5 +++-- + nss/nss_files/files-initgroups.c | 6 ++--- + nss/nss_files/files-netgrp.c | 5 ++--- + nss/nss_files_fopen.c | 47 ++++++++++++++++++++++++++++++++++++++++ + 8 files changed, 86 insertions(+), 11 deletions(-) + create mode 100644 include/nss_files.h + create mode 100644 nss/nss_files_fopen.c + +diff -rupN a/include/nss_files.h b/include/nss_files.h +--- a/include/nss_files.h 1969-12-31 19:00:00.000000000 -0500 ++++ b/include/nss_files.h 2020-09-11 21:28:42.027034988 -0400 +@@ -0,0 +1,28 @@ ++/* Internal routines for nss_files. ++ Copyright (C) 2020 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifndef _NSS_FILES_H ++#define _NSS_FILES_H ++ ++#include ++ ++/* Open PATH for reading, as a data source for nss_files. */ ++FILE *__nss_files_fopen (const char *path); ++libc_hidden_proto (__nss_files_fopen) ++ ++#endif /* _NSS_FILES_H */ +diff -rupN a/nss/Makefile b/nss/Makefile +--- a/nss/Makefile 2020-09-11 21:24:05.569544894 -0400 ++++ b/nss/Makefile 2020-09-11 21:28:42.035035292 -0400 +@@ -28,7 +28,7 @@ headers := nss.h + routines = nsswitch getnssent getnssent_r digits_dots \ + valid_field valid_list_field rewrite_field \ + $(addsuffix -lookup,$(databases)) \ +- compat-lookup nss_hash ++ compat-lookup nss_hash nss_files_fopen + + # These are the databases that go through nss dispatch. + # Caution: if you add a database here, you must add its real name +diff -rupN a/nss/Versions b/nss/Versions +--- a/nss/Versions 2020-09-11 21:24:04.852517683 -0400 ++++ b/nss/Versions 2020-09-11 21:28:42.041035519 -0400 +@@ -21,6 +21,7 @@ libc { + __nss_passwd_lookup2; __nss_group_lookup2; __nss_hosts_lookup2; + __nss_services_lookup2; __nss_next2; __nss_lookup; + __nss_hash; __nss_database_lookup2; ++ __nss_files_fopen; + } + } + +diff -rupN a/nss/nss_files/files-XXX.c b/nss/nss_files/files-XXX.c +--- a/nss/nss_files/files-XXX.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/nss/nss_files/files-XXX.c 2020-09-11 21:28:42.049035823 -0400 +@@ -22,6 +22,7 @@ + #include + #include + #include "nsswitch.h" ++#include + + #include + +@@ -74,7 +75,7 @@ internal_setent (FILE **stream) + + if (*stream == NULL) + { +- *stream = fopen (DATAFILE, "rce"); ++ *stream = __nss_files_fopen (DATAFILE); + + if (*stream == NULL) + status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; +diff -rupN a/nss/nss_files/files-alias.c b/nss/nss_files/files-alias.c +--- a/nss/nss_files/files-alias.c 2020-09-11 21:24:02.004409596 -0400 ++++ b/nss/nss_files/files-alias.c 2020-09-11 21:28:42.055036051 -0400 +@@ -29,6 +29,7 @@ + #include + + #include "nsswitch.h" ++#include + + /* Locks the static variables in this file. */ + __libc_lock_define_initialized (static, lock) +@@ -47,7 +48,7 @@ internal_setent (FILE **stream) + + if (*stream == NULL) + { +- *stream = fopen ("/etc/aliases", "rce"); ++ *stream = __nss_files_fopen ("/etc/aliases"); + + if (*stream == NULL) + status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; +@@ -213,7 +214,7 @@ get_next_alias (FILE *stream, const char + + first_unused = cp; + +- listfile = fopen (&cp[9], "rce"); ++ listfile = __nss_files_fopen (&cp[9]); + /* If the file does not exist we simply ignore + the statement. */ + if (listfile != NULL +diff -rupN a/nss/nss_files/files-initgroups.c b/nss/nss_files/files-initgroups.c +--- a/nss/nss_files/files-initgroups.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/nss/nss_files/files-initgroups.c 2020-09-11 22:08:25.130740010 -0400 +@@ -25,22 +25,20 @@ + #include + #include + #include ++#include + + enum nss_status + _nss_files_initgroups_dyn (const char *user, gid_t group, long int *start, + long int *size, gid_t **groupsp, long int limit, + int *errnop) + { +- FILE *stream = fopen ("/etc/group", "rce"); ++ FILE *stream = __nss_files_fopen ("/etc/group"); + if (stream == NULL) + { + *errnop = errno; + return *errnop == ENOMEM ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; + } + +- /* No other thread using this stream. */ +- __fsetlocking (stream, FSETLOCKING_BYCALLER); +- + char *line = NULL; + size_t linelen = 0; + enum nss_status status = NSS_STATUS_SUCCESS; +diff -rupN a/nss/nss_files/files-netgrp.c b/nss/nss_files/files-netgrp.c +--- a/nss/nss_files/files-netgrp.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/nss/nss_files/files-netgrp.c 2020-09-11 21:28:42.068036544 -0400 +@@ -26,6 +26,7 @@ + #include + #include "nsswitch.h" + #include "netgroup.h" ++#include + + #define DATAFILE "/etc/netgroup" + +@@ -62,7 +63,7 @@ _nss_files_setnetgrent (const char *grou + return NSS_STATUS_UNAVAIL; + + /* Find the netgroups file and open it. */ +- fp = fopen (DATAFILE, "rce"); ++ fp = __nss_files_fopen (DATAFILE); + if (fp == NULL) + status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; + else +@@ -76,8 +77,6 @@ _nss_files_setnetgrent (const char *grou + status = NSS_STATUS_NOTFOUND; + result->cursor = result->data; + +- __fsetlocking (fp, FSETLOCKING_BYCALLER); +- + while (!feof_unlocked (fp)) + { + ssize_t curlen = getline (&line, &line_len, fp); +diff -rupN a/nss/nss_files_fopen.c b/nss/nss_files_fopen.c +--- a/nss/nss_files_fopen.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/nss/nss_files_fopen.c 2020-09-11 21:28:42.074036771 -0400 +@@ -0,0 +1,47 @@ ++/* Open an nss_files database file. ++ Copyright (C) 2020 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++#include ++#include ++ ++FILE * ++__nss_files_fopen (const char *path) ++{ ++ FILE *fp = fopen (path, "rce"); ++ if (fp == NULL) ++ return NULL; ++ ++ /* The stream is not shared across threads. */ ++ __fsetlocking (fp, FSETLOCKING_BYCALLER); ++ ++ /* This tells libio that the file is seekable, and that fp->_offset ++ is correct, ensuring that __ftello64 is efficient (bug 26257). */ ++ if (__fseeko64 (fp, 0, SEEK_SET) < 0) ++ { ++ /* nss_files requires seekable files, to deal with repeated ++ reads of the same line after reporting ERANGE. */ ++ fclose (fp); ++ __set_errno (ESPIPE); ++ return NULL; ++ } ++ ++ return fp; ++} ++libc_hidden_def (__nss_files_fopen) diff --git a/SOURCES/glibc-rh1871397-10.patch b/SOURCES/glibc-rh1871397-10.patch new file mode 100644 index 0000000..106a868 --- /dev/null +++ b/SOURCES/glibc-rh1871397-10.patch @@ -0,0 +1,82 @@ +From 00bc6830e3fe3f10495917afe0835ddd19133c6a Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 16 Jul 2020 17:34:43 +0200 +Subject: [PATCH 10/11] shadow: Implement fgetspent_r using __nss_fgetent_r + +Tested-by: Carlos O'Donell +Reviewed-by: Carlos O'Donell +--- + gshadow/tst-fgetsgent_r.c | 1 + + shadow/fgetspent_r.c | 43 ++++++------------------------------------- + 2 files changed, 7 insertions(+), 37 deletions(-) + +diff -rup a/gshadow/tst-fgetsgent_r.c b/gshadow/tst-fgetsgent_r.c +--- a/gshadow/tst-fgetsgent_r.c 2020-09-14 18:00:57.174146151 -0400 ++++ b/gshadow/tst-fgetsgent_r.c 2020-09-14 19:12:57.867548005 -0400 +@@ -168,6 +168,7 @@ run_test (const char *path, size_t buffe + free (result_storage); + } + ++ xfclose (fp); + return resized; + } + +diff -rup a/shadow/fgetspent_r.c b/shadow/fgetspent_r.c +--- a/shadow/fgetspent_r.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/shadow/fgetspent_r.c 2020-09-14 19:17:15.623285970 -0400 +@@ -20,9 +20,6 @@ + #include + #include + +-#define flockfile(s) _IO_flockfile (s) +-#define funlockfile(s) _IO_funlockfile (s) +- + /* Define a line parsing function using the common code + used in the nss_files module. */ + +@@ -39,39 +36,11 @@ int + __fgetspent_r (FILE *stream, struct spwd *resbuf, char *buffer, size_t buflen, + struct spwd **result) + { +- char *p; +- +- flockfile (stream); +- do +- { +- buffer[buflen - 1] = '\xff'; +- p = fgets_unlocked (buffer, buflen, stream); +- if (p == NULL && feof_unlocked (stream)) +- { +- funlockfile (stream); +- *result = NULL; +- __set_errno (ENOENT); +- return errno; +- } +- if (p == NULL || buffer[buflen - 1] != '\xff') +- { +- funlockfile (stream); +- *result = NULL; +- __set_errno (ERANGE); +- return errno; +- } +- +- /* Skip leading blanks. */ +- while (isspace (*p)) +- ++p; +- } while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */ +- /* Parse the line. If it is invalid, loop to +- get the next line of the file to parse. */ +- ! parse_line (buffer, (void *) resbuf, NULL, 0, &errno)); +- +- funlockfile (stream); +- +- *result = resbuf; +- return 0; ++ int ret = __nss_fgetent_r (stream, resbuf, buffer, buflen, parse_line); ++ if (ret == 0) ++ *result = resbuf; ++ else ++ *result = NULL; ++ return ret; + } + weak_alias (__fgetspent_r, fgetspent_r) diff --git a/SOURCES/glibc-rh1871397-11.patch b/SOURCES/glibc-rh1871397-11.patch new file mode 100644 index 0000000..e045949 --- /dev/null +++ b/SOURCES/glibc-rh1871397-11.patch @@ -0,0 +1,492 @@ +From ec2f1fddf29053957d061dfe310f106388472a4f Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Wed, 15 Jul 2020 12:37:01 +0200 +Subject: [PATCH 11/11] libio: Remove __libc_readline_unlocked + +__nss_readline supersedes it. This reverts part of commit +3f5e3f5d066dcffb80af48ae2cf35a01a85a8f10 ("libio: Implement +internal function __libc_readline_unlocked"). The internal +aliases __fseeko64 and __ftello64 are preserved because +they are needed by __nss_readline as well. + +Tested-by: Carlos O'Donell +Reviewed-by: Carlos O'Donell +--- + include/stdio.h | 13 --- + libio/Makefile | 4 +- + libio/Versions | 1 - + libio/readline.c | 170 ------------------------------------ + libio/tst-readline.c | 237 --------------------------------------------------- + 5 files changed, 2 insertions(+), 423 deletions(-) + delete mode 100644 libio/readline.c + delete mode 100644 libio/tst-readline.c + +diff -rupN a/include/stdio.h b/include/stdio.h +--- a/include/stdio.h 2020-09-14 17:48:49.359699532 -0400 ++++ b/include/stdio.h 2020-09-14 19:20:51.204429471 -0400 +@@ -135,19 +135,6 @@ extern int __fxprintf (FILE *__fp, const + extern int __fxprintf_nocancel (FILE *__fp, const char *__fmt, ...) + __attribute__ ((__format__ (__printf__, 2, 3))) attribute_hidden; + +-/* Read the next line from FP into BUFFER, of LENGTH bytes. LINE will +- include the line terminator and a NUL terminator. On success, +- return the length of the line, including the line terminator, but +- excluding the NUL termintor. On EOF, return zero and write a NUL +- terminator. On error, return -1 and set errno. If the total byte +- count (line and both terminators) exceeds LENGTH, return -1 and set +- errno to ERANGE (but do not mark the stream as failed). +- +- The behavior is undefined if FP is not seekable, or if the stream +- is already in an error state. */ +-ssize_t __libc_readline_unlocked (FILE *fp, char *buffer, size_t length); +-libc_hidden_proto (__libc_readline_unlocked); +- + extern const char *const _sys_errlist_internal[] attribute_hidden; + extern int _sys_nerr_internal attribute_hidden; + +diff -rupN a/libio/Makefile b/libio/Makefile +--- a/libio/Makefile 2020-09-14 17:48:45.722562485 -0400 ++++ b/libio/Makefile 2020-09-14 19:20:51.211429735 -0400 +@@ -49,7 +49,7 @@ routines := \ + __fbufsize __freading __fwriting __freadable __fwritable __flbf \ + __fpurge __fpending __fsetlocking \ + \ +- libc_fatal fmemopen oldfmemopen vtables readline ++ libc_fatal fmemopen oldfmemopen vtables + + tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \ + tst_wprintf2 tst-widetext test-fmemopen tst-ext tst-ext2 \ +@@ -67,7 +67,7 @@ tests = tst_swprintf tst_wprintf tst_sws + tst-ftell-append tst-fputws tst-bz22415 tst-fgetc-after-eof \ + tst-wfile-sync + +-tests-internal = tst-vtables tst-vtables-interposed tst-readline ++tests-internal = tst-vtables tst-vtables-interposed + + ifeq (yes,$(build-shared)) + # Add test-fopenloc only if shared library is enabled since it depends on +diff -rupN a/libio/Versions b/libio/Versions +--- a/libio/Versions 2018-08-01 01:10:47.000000000 -0400 ++++ b/libio/Versions 2020-09-14 19:20:51.217429962 -0400 +@@ -161,6 +161,5 @@ libc { + + __fseeko64; + __ftello64; +- __libc_readline_unlocked; + } + } +diff -rupN a/libio/readline.c b/libio/readline.c +--- a/libio/readline.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/libio/readline.c 1969-12-31 19:00:00.000000000 -0500 +@@ -1,170 +0,0 @@ +-/* fgets with ERANGE error reporting and size_t buffer length. +- Copyright (C) 2018 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +-#include +- +-#include "libioP.h" +- +-/* Return -1 and set errno to EINVAL if it is ERANGE. */ +-static ssize_t +-fail_no_erange (void) +-{ +- if (errno == ERANGE) +- __set_errno (EINVAL); +- return -1; +-} +- +-/* Slow path for reading the line. Called with no data in the stream +- read buffer. Write data to [BUFFER, BUFFER_END). */ +-static ssize_t +-readline_slow (FILE *fp, char *buffer, char *buffer_end) +-{ +- char *start = buffer; +- +- while (buffer < buffer_end) +- { +- if (__underflow (fp) == EOF) +- { +- if (_IO_ferror_unlocked (fp)) +- /* If the EOF was caused by a read error, report it. */ +- return fail_no_erange (); +- *buffer = '\0'; +- /* Do not include the null terminator. */ +- return buffer - start; +- } +- +- /* __underflow has filled the buffer. */ +- char *readptr = fp->_IO_read_ptr; +- ssize_t readlen = fp->_IO_read_end - readptr; +- /* Make sure that __underflow really has acquired some data. */ +- assert (readlen > 0); +- char *pnl = memchr (readptr, '\n', readlen); +- if (pnl != NULL) +- { +- /* We found the terminator. */ +- size_t line_length = pnl - readptr; +- if (line_length + 2 > buffer_end - buffer) +- /* Not enough room in the caller-supplied buffer. */ +- break; +- memcpy (buffer, readptr, line_length + 1); +- buffer[line_length + 1] = '\0'; +- fp->_IO_read_ptr = pnl + 1; +- /* Do not include the null terminator. */ +- return buffer - start + line_length + 1; +- } +- +- if (readlen >= buffer_end - buffer) +- /* Not enough room in the caller-supplied buffer. */ +- break; +- +- /* Save and consume the stream buffer. */ +- memcpy (buffer, readptr, readlen); +- fp->_IO_read_ptr = fp->_IO_read_end; +- buffer += readlen; +- } +- +- /* The line does not fit into the buffer. */ +- __set_errno (ERANGE); +- return -1; +-} +- +-ssize_t +-__libc_readline_unlocked (FILE *fp, char *buffer, size_t buffer_length) +-{ +- char *buffer_end = buffer + buffer_length; +- +- /* Orient the stream. */ +- if (__builtin_expect (fp->_mode, -1) == 0) +- _IO_fwide (fp, -1); +- +- /* Fast path: The line terminator is found in the buffer. */ +- char *readptr = fp->_IO_read_ptr; +- ssize_t readlen = fp->_IO_read_end - readptr; +- off64_t start_offset; /* File offset before reading anything. */ +- if (readlen > 0) +- { +- char *pnl = memchr (readptr, '\n', readlen); +- if (pnl != NULL) +- { +- size_t line_length = pnl - readptr; +- /* Account for line and null terminators. */ +- if (line_length + 2 > buffer_length) +- { +- __set_errno (ERANGE); +- return -1; +- } +- memcpy (buffer, readptr, line_length + 1); +- buffer[line_length + 1] = '\0'; +- /* Consume the entire line. */ +- fp->_IO_read_ptr = pnl + 1; +- return line_length + 1; +- } +- +- /* If the buffer does not have enough space for what is pending +- in the stream (plus a NUL terminator), the buffer is too +- small. */ +- if (readlen + 1 > buffer_length) +- { +- __set_errno (ERANGE); +- return -1; +- } +- +- /* End of line not found. We need all the buffered data. Fall +- through to the slow path. */ +- memcpy (buffer, readptr, readlen); +- buffer += readlen; +- /* The original length is invalid after this point. Use +- buffer_end instead. */ +-#pragma GCC poison buffer_length +- /* Read the old offset before updating the read pointer. */ +- start_offset = __ftello64 (fp); +- fp->_IO_read_ptr = fp->_IO_read_end; +- } +- else +- { +- readlen = 0; +- start_offset = __ftello64 (fp); +- } +- +- /* Slow path: Read more data from the underlying file. We need to +- restore the file pointer if the buffer is too small. First, +- check if the __ftello64 call above failed. */ +- if (start_offset < 0) +- return fail_no_erange (); +- +- ssize_t result = readline_slow (fp, buffer, buffer_end); +- if (result < 0) +- { +- if (errno == ERANGE) +- { +- /* Restore the file pointer so that the caller may read the +- same line again. */ +- if (__fseeko64 (fp, start_offset, SEEK_SET) < 0) +- return fail_no_erange (); +- __set_errno (ERANGE); +- } +- /* Do not restore the file position on other errors; it is +- likely that the __fseeko64 call would fail, too. */ +- return -1; +- } +- return readlen + result; +-} +-libc_hidden_def (__libc_readline_unlocked) +diff -rupN a/libio/tst-readline.c b/libio/tst-readline.c +--- a/libio/tst-readline.c 2020-09-14 17:48:41.969421067 -0400 ++++ b/libio/tst-readline.c 1969-12-31 19:00:00.000000000 -0500 +@@ -1,237 +0,0 @@ +-/* Test the __libc_readline_unlocked 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 +- . */ +- +-/* Exercise __libc_readline_unlocked with various combinations of line +- lengths, stdio buffer sizes, and line read buffer sizes. */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-enum +- { +- maximum_line_length = 7, +- number_of_lines = 3, +- }; +- +-/* -1: Do not set buffer size. 0: unbuffered. Otherwise, use this as +- the size of the buffer. */ +-static int buffer_size; +- +-/* These size of the buffer used for reading. Must be at least 2. */ +-static int read_size; +- +-/* If a read files with ERANGE, increase the buffer size by this +- amount. Must be positive. */ +-static int read_size_increment; +- +-/* If non-zero, do not reset the read size after an ERANGE error. */ +-static int read_size_preserve; +- +-/* If non-zero, no '\n' at the end of the file. */ +-static int no_newline_at_eof; +- +-/* Length of the line, or -1 if the line is not present. */ +-static int line_lengths[number_of_lines]; +- +-/* The name of the test file. */ +-static char *test_file_path; +- +-/* The contents of the test file. */ +-static char expected_contents[(maximum_line_length + 2) * number_of_lines + 1]; +-static size_t expected_length; +- +-/* Returns a random byte which is not zero or the line terminator. */ +-static char +-random_char (void) +-{ +- static unsigned int rand_state = 1; +- while (true) +- { +- char result = rand_r (&rand_state) >> 16; +- if (result != 0 && result != '\n') +- return result; +- } +-} +- +-/* Create the test file. */ +-static void +-prepare (int argc, char **argv) +-{ +- int fd = create_temp_file ("tst-readline-", &test_file_path); +- TEST_VERIFY_EXIT (fd >= 0); +- xclose (fd); +-} +- +-/* Prepare the test file. Return false if the test parameters are +- incongruent and the test should be skipped. */ +-static bool +-write_test_file (void) +-{ +- expected_length = 0; +- char *p = expected_contents; +- for (int lineno = 0; lineno < number_of_lines; ++lineno) +- for (int i = 0; i < line_lengths[lineno]; ++i) +- *p++ = random_char (); +- expected_length = p - &expected_contents[0]; +- if (no_newline_at_eof) +- { +- if (expected_length == 0) +- return false; +- --expected_length; +- --p; +- } +- if (test_verbose > 0) +- { +- printf ("info: writing test file of %zu bytes:\n", expected_length); +- for (int i = 0; i < number_of_lines; ++i) +- printf (" line %d: %d\n", i, line_lengths[i]); +- if (no_newline_at_eof) +- puts (" (no newline at EOF)"); +- } +- TEST_VERIFY_EXIT (expected_length < sizeof (expected_contents)); +- *p++ = '\0'; +- support_write_file_string (test_file_path, expected_contents); +- return true; +-} +- +-/* Run a single test (a combination of a test file and read +- parameters). */ +-static void +-run_test (void) +-{ +- TEST_VERIFY_EXIT (read_size_increment > 0); +- if (test_verbose > 0) +- { +- printf ("info: running test: buffer_size=%d read_size=%d\n" +- " read_size_increment=%d read_size_preserve=%d\n", +- buffer_size, read_size, read_size_increment, read_size_preserve); +- } +- +- struct xmemstream result; +- xopen_memstream (&result); +- +- FILE *fp = xfopen (test_file_path, "rce"); +- char *fp_buffer = NULL; +- if (buffer_size == 0) +- TEST_VERIFY_EXIT (setvbuf (fp, NULL, _IONBF, 0) == 0); +- if (buffer_size > 0) +- { +- fp_buffer = xmalloc (buffer_size); +- TEST_VERIFY_EXIT (setvbuf (fp, fp_buffer, _IOFBF, buffer_size) == 0); +- } +- +- char *line_buffer = xmalloc (read_size); +- size_t line_buffer_size = read_size; +- +- while (true) +- { +- ssize_t ret = __libc_readline_unlocked +- (fp, line_buffer, line_buffer_size); +- if (ret < 0) +- { +- TEST_VERIFY (ret == -1); +- if (errno != ERANGE) +- FAIL_EXIT1 ("__libc_readline_unlocked: %m"); +- line_buffer_size += read_size_increment; +- free (line_buffer); +- line_buffer = xmalloc (line_buffer_size); +- /* Try reading this line again. */ +- } +- else if (ret == 0) +- break; +- else +- { +- /* A line has been read. Save it. */ +- TEST_VERIFY (ret == strlen (line_buffer)); +- const char *pnl = strchr (line_buffer, '\n'); +- /* If there is a \n, it must be at the end. */ +- TEST_VERIFY (pnl == NULL || pnl == line_buffer + ret - 1); +- fputs (line_buffer, result.out); +- +- /* Restore the original read size if required. */ +- if (line_buffer_size > read_size && !read_size_preserve) +- { +- line_buffer_size = read_size; +- free (line_buffer); +- line_buffer = xmalloc (line_buffer_size); +- } +- } +- } +- +- xfclose (fp); +- free (fp_buffer); +- free (line_buffer); +- +- xfclose_memstream (&result); +- TEST_VERIFY (result.length == expected_length); +- TEST_VERIFY (strcmp (result.buffer, expected_contents) == 0); +- if (test_verbose > 0) +- { +- printf ("info: expected (%zu): [[%s]]\n", +- expected_length, expected_contents); +- printf ("info: actual (%zu): [[%s]]\n", result.length, result.buffer); +- } +- free (result.buffer); +-} +- +-/* Test one test file with multiple read parameters. */ +-static void +-test_one_file (void) +-{ +- for (buffer_size = -1; buffer_size <= maximum_line_length + 1; ++buffer_size) +- for (read_size = 2; read_size <= maximum_line_length + 2; ++read_size) +- for (read_size_increment = 1; read_size_increment <= 4; +- ++read_size_increment) +- for (read_size_preserve = 0; read_size_preserve < 2; +- ++read_size_preserve) +- run_test (); +-} +- +- +-static int +-do_test (void) +-{ +- /* Set up the test file contents. */ +- for (line_lengths[0] = -1; line_lengths[0] <= maximum_line_length; +- ++line_lengths[0]) +- for (line_lengths[1] = -1; line_lengths[1] <= maximum_line_length; +- ++line_lengths[1]) +- for (line_lengths[2] = -1; line_lengths[2] <= maximum_line_length; +- ++line_lengths[2]) +- for (no_newline_at_eof = 0; no_newline_at_eof < 2; ++no_newline_at_eof) +- { +- if (!write_test_file ()) +- continue; +- test_one_file (); +- } +- free (test_file_path); +- return 0; +-} +- +-#define TIMEOUT 100 +-#define PREPARE prepare +-#include diff --git a/SOURCES/glibc-rh1871397-2.patch b/SOURCES/glibc-rh1871397-2.patch new file mode 100644 index 0000000..1b95b01 --- /dev/null +++ b/SOURCES/glibc-rh1871397-2.patch @@ -0,0 +1,123 @@ +From 23ed36735af09c258e542266aaed92cdd8571c6c Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 16 Jul 2020 16:21:28 +0200 +Subject: [PATCH 02/11] nss_compat: Do not use mmap to read database files (bug + 26258) + +This avoids crashes in case the files are truncated for some reason. +For typically file sizes, it is also going to be slightly faster. +Using __nss_files_fopen instead mirrors what nss_files does. + +Tested-by: Carlos O'Donell +Reviewed-by: Carlos O'Donell +--- + nss/nss_compat/compat-grp.c | 6 ++---- + nss/nss_compat/compat-initgroups.c | 6 ++---- + nss/nss_compat/compat-pwd.c | 6 ++---- + nss/nss_compat/compat-spwd.c | 6 ++---- + 4 files changed, 8 insertions(+), 16 deletions(-) + +diff -rup a/nss/nss_compat/compat-grp.c b/nss/nss_compat/compat-grp.c +--- a/nss/nss_compat/compat-grp.c 2020-09-14 15:49:18.248178627 -0400 ++++ b/nss/nss_compat/compat-grp.c 2020-09-14 17:18:22.514977541 -0400 +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + static service_user *ni; + static enum nss_status (*nss_setgrent) (int stayopen); +@@ -106,13 +107,10 @@ internal_setgrent (ent_t *ent, int stayo + + if (ent->stream == NULL) + { +- ent->stream = fopen ("/etc/group", "rme"); ++ ent->stream = __nss_files_fopen ("/etc/group"); + + if (ent->stream == NULL) + status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; +- else +- /* We take care of locking ourself. */ +- __fsetlocking (ent->stream, FSETLOCKING_BYCALLER); + } + else + rewind (ent->stream); +diff -rup a/nss/nss_compat/compat-initgroups.c b/nss/nss_compat/compat-initgroups.c +--- a/nss/nss_compat/compat-initgroups.c 2020-09-14 15:49:18.255178892 -0400 ++++ b/nss/nss_compat/compat-initgroups.c 2020-09-14 17:18:22.519977728 -0400 +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + + static service_user *ni; + /* Type of the lookup function. */ +@@ -121,13 +122,10 @@ internal_setgrent (ent_t *ent) + else + ent->blacklist.current = 0; + +- ent->stream = fopen ("/etc/group", "rme"); ++ ent->stream = __nss_files_fopen ("/etc/group"); + + if (ent->stream == NULL) + status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; +- else +- /* We take care of locking ourself. */ +- __fsetlocking (ent->stream, FSETLOCKING_BYCALLER); + + return status; + } +diff -rup a/nss/nss_compat/compat-pwd.c b/nss/nss_compat/compat-pwd.c +--- a/nss/nss_compat/compat-pwd.c 2020-09-14 15:49:18.260179081 -0400 ++++ b/nss/nss_compat/compat-pwd.c 2020-09-14 17:18:22.523977879 -0400 +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + #include "netgroup.h" + #include "nisdomain.h" +@@ -221,13 +222,10 @@ internal_setpwent (ent_t *ent, int stayo + + if (ent->stream == NULL) + { +- ent->stream = fopen ("/etc/passwd", "rme"); ++ ent->stream = __nss_files_fopen ("/etc/passwd"); + + if (ent->stream == NULL) + status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; +- else +- /* We take care of locking ourself. */ +- __fsetlocking (ent->stream, FSETLOCKING_BYCALLER); + } + else + rewind (ent->stream); +diff -rup a/nss/nss_compat/compat-spwd.c b/nss/nss_compat/compat-spwd.c +--- a/nss/nss_compat/compat-spwd.c 2020-09-14 15:49:18.264179232 -0400 ++++ b/nss/nss_compat/compat-spwd.c 2020-09-14 17:18:22.527978029 -0400 +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + #include "netgroup.h" + #include "nisdomain.h" +@@ -177,13 +178,10 @@ internal_setspent (ent_t *ent, int stayo + + if (ent->stream == NULL) + { +- ent->stream = fopen ("/etc/shadow", "rme"); ++ ent->stream = __nss_files_fopen ("/etc/shadow"); + + if (ent->stream == NULL) + status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; +- else +- /* We take care of locking ourself. */ +- __fsetlocking (ent->stream, FSETLOCKING_BYCALLER); + } + else + rewind (ent->stream); diff --git a/SOURCES/glibc-rh1871397-3.patch b/SOURCES/glibc-rh1871397-3.patch new file mode 100644 index 0000000..474ab8b --- /dev/null +++ b/SOURCES/glibc-rh1871397-3.patch @@ -0,0 +1,227 @@ +From e9b2340998ab22402a8e968ba674c380a625b9dc Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 16 Jul 2020 16:40:44 +0200 +Subject: [PATCH 03/11] nss_files: Consolidate line parse declarations in + + +These functions should eventually have the same type, so it makes +sense to declare them together. + +Tested-by: Carlos O'Donell +Reviewed-by: Carlos O'Donell +--- + include/grp.h | 6 ------ + include/gshadow.h | 6 ------ + include/netdb.h | 13 ------------ + include/netinet/ether.h | 6 ------ + include/nss_files.h | 51 +++++++++++++++++++++++++++++++++++++++++++++ + include/pwd.h | 6 ------ + include/rpc/netdb.h | 6 ------ + include/shadow.h | 6 ------ + nss/nss_files/files-parse.c | 1 + + 9 files changed, 52 insertions(+), 49 deletions(-) + +diff --git a/include/grp.h b/include/grp.h +index 58f7b4d..2cd2475 100644 +--- a/include/grp.h ++++ b/include/grp.h +@@ -30,12 +30,6 @@ extern int __old_getgrnam_r (const char *__name, struct group *__resultbuf, + char *__buffer, size_t __buflen, + struct group **__result); + +-struct parser_data; +-extern int _nss_files_parse_grent (char *line, struct group *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-libc_hidden_proto (_nss_files_parse_grent) +- + #define DECLARE_NSS_PROTOTYPES(service) \ + extern enum nss_status _nss_ ## service ## _setgrent (int); \ + extern enum nss_status _nss_ ## service ## _endgrent (void); \ +diff --git a/include/gshadow.h b/include/gshadow.h +index aa6a5a6..1cefcfc 100644 +--- a/include/gshadow.h ++++ b/include/gshadow.h +@@ -10,11 +10,5 @@ extern int __sgetsgent_r (const char *string, struct sgrp *resbuf, + char *buffer, size_t buflen, struct sgrp **result) + attribute_hidden; + +-struct parser_data; +-extern int _nss_files_parse_sgent (char *line, struct sgrp *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-libc_hidden_proto (_nss_files_parse_sgent) +- + # endif /* !_ISOMAC */ + #endif +diff --git a/include/netdb.h b/include/netdb.h +index 6b43135..49d63c1 100644 +--- a/include/netdb.h ++++ b/include/netdb.h +@@ -202,23 +202,10 @@ libc_hidden_proto (ruserpass) + + #include + +-struct parser_data; +-extern int _nss_files_parse_protoent (char *line, struct protoent *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-extern int _nss_files_parse_servent (char *line, struct servent *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-extern int _nss_files_parse_netent (char *line, struct netent *result, +- struct parser_data *data, +- size_t datalen, int *errnop); + extern enum nss_status _nss_netgroup_parseline (char **cursor, + struct __netgrent *result, + char *buffer, size_t buflen, + int *errnop); +-libnss_files_hidden_proto (_nss_files_parse_protoent) +-libnss_files_hidden_proto (_nss_files_parse_servent) +-libnss_files_hidden_proto (_nss_files_parse_netent) + libnss_files_hidden_proto (_nss_netgroup_parseline) + + #define DECLARE_NSS_PROTOTYPES(service) \ +diff --git a/include/netinet/ether.h b/include/netinet/ether.h +index 8fd05f8..1763a7e 100644 +--- a/include/netinet/ether.h ++++ b/include/netinet/ether.h +@@ -15,12 +15,6 @@ struct etherent + struct ether_addr e_addr; + }; + +-struct parser_data; +-extern int _nss_files_parse_etherent (char *line, struct etherent *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-libnss_files_hidden_proto (_nss_files_parse_etherent) +- + #define DECLARE_NSS_PROTOTYPES(service) \ + extern enum nss_status _nss_ ## service ## _setetherent (int __stayopen); \ + extern enum nss_status _nss_ ## service ## _endetherent (void); \ +diff --git a/include/nss_files.h b/include/nss_files.h +index 17144b7..54b354a 100644 +--- a/include/nss_files.h ++++ b/include/nss_files.h +@@ -25,4 +25,55 @@ + FILE *__nss_files_fopen (const char *path); + libc_hidden_proto (__nss_files_fopen) + ++struct parser_data; ++struct etherent; ++struct group; ++struct netent; ++struct passwd; ++struct protoent; ++struct rpcent; ++struct servent; ++struct sgrp; ++struct spwd; ++ ++/* Instances of the parse_line function from ++ nss/nss_files/files-parse.c. */ ++extern int _nss_files_parse_etherent (char *line, struct etherent *result, ++ struct parser_data *data, ++ size_t datalen, int *errnop); ++extern int _nss_files_parse_grent (char *line, struct group *result, ++ struct parser_data *data, ++ size_t datalen, int *errnop); ++extern int _nss_files_parse_netent (char *line, struct netent *result, ++ struct parser_data *data, ++ size_t datalen, int *errnop); ++extern int _nss_files_parse_protoent (char *line, struct protoent *result, ++ struct parser_data *data, ++ size_t datalen, int *errnop); ++extern int _nss_files_parse_pwent (char *line, struct passwd *result, ++ struct parser_data *data, ++ size_t datalen, int *errnop); ++extern int _nss_files_parse_rpcent (char *line, struct rpcent *result, ++ struct parser_data *data, ++ size_t datalen, int *errnop); ++extern int _nss_files_parse_servent (char *line, struct servent *result, ++ struct parser_data *data, ++ size_t datalen, int *errnop); ++extern int _nss_files_parse_sgent (char *line, struct sgrp *result, ++ struct parser_data *data, ++ size_t datalen, int *errnop); ++extern int _nss_files_parse_spent (char *line, struct spwd *result, ++ struct parser_data *data, ++ size_t datalen, int *errnop); ++ ++libnss_files_hidden_proto (_nss_files_parse_etherent) ++libc_hidden_proto (_nss_files_parse_grent) ++libnss_files_hidden_proto (_nss_files_parse_netent) ++libnss_files_hidden_proto (_nss_files_parse_protoent) ++libc_hidden_proto (_nss_files_parse_pwent) ++libnss_files_hidden_proto (_nss_files_parse_rpcent) ++libnss_files_hidden_proto (_nss_files_parse_servent) ++libc_hidden_proto (_nss_files_parse_sgent) ++libc_hidden_proto (_nss_files_parse_spent) ++ + #endif /* _NSS_FILES_H */ +diff --git a/include/pwd.h b/include/pwd.h +index fd23fe9..f8975d4 100644 +--- a/include/pwd.h ++++ b/include/pwd.h +@@ -26,12 +26,6 @@ extern int __fgetpwent_r (FILE * __stream, struct passwd *__resultbuf, + + #include + +-struct parser_data; +-extern int _nss_files_parse_pwent (char *line, struct passwd *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-libc_hidden_proto (_nss_files_parse_pwent) +- + #define DECLARE_NSS_PROTOTYPES(service) \ + extern enum nss_status _nss_ ## service ## _setpwent (int); \ + extern enum nss_status _nss_ ## service ## _endpwent (void); \ +diff --git a/include/rpc/netdb.h b/include/rpc/netdb.h +index 5ddd776..c1a936e 100644 +--- a/include/rpc/netdb.h ++++ b/include/rpc/netdb.h +@@ -24,12 +24,6 @@ extern int __getrpcent_r (struct rpcent *__result_buf, char *__buffer, + extern int __old_getrpcent_r (struct rpcent *__result_buf, char *__buffer, + size_t __buflen, struct rpcent **__result); + +-struct parser_data; +-extern int _nss_files_parse_rpcent (char *line, struct rpcent *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-libnss_files_hidden_proto (_nss_files_parse_rpcent) +- + #define DECLARE_NSS_PROTOTYPES(service) \ + extern enum nss_status _nss_ ## service ## _setrpcent (int); \ + extern enum nss_status _nss_ ## service ## _endrpcent (void); \ +diff --git a/include/shadow.h b/include/shadow.h +index 5168d8d..fb16819 100644 +--- a/include/shadow.h ++++ b/include/shadow.h +@@ -25,12 +25,6 @@ extern int __fgetspent_r (FILE *__stream, struct spwd *__result_buf, + extern int __lckpwdf (void); + extern int __ulckpwdf (void); + +-struct parser_data; +-extern int _nss_files_parse_spent (char *line, struct spwd *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-libc_hidden_proto (_nss_files_parse_spent) +- + #define DECLARE_NSS_PROTOTYPES(service) \ + extern enum nss_status _nss_ ## service ## _setspent (int); \ + extern enum nss_status _nss_ ## service ## _endspent (void); \ +diff --git a/nss/nss_files/files-parse.c b/nss/nss_files/files-parse.c +index a563d81..3820287 100644 +--- a/nss/nss_files/files-parse.c ++++ b/nss/nss_files/files-parse.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + /* These symbols are defined by the including source file: + +-- +1.8.3.1 + diff --git a/SOURCES/glibc-rh1871397-4.patch b/SOURCES/glibc-rh1871397-4.patch new file mode 100644 index 0000000..aed1bd8 --- /dev/null +++ b/SOURCES/glibc-rh1871397-4.patch @@ -0,0 +1,111 @@ +From 9980bf0b307368959cb29f3ca3f7446ad92347f1 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 16 Jul 2020 16:55:45 +0200 +Subject: [PATCH 04/11] nss_files: Use generic result pointer in parse_line + +As a result, all parse_line functions have the same prototype, except +for that producing struct hostent. This change is ABI-compatible, so +it does not alter the internal GLIBC_PRIVATE ABI (otherwise we should +probably have renamed the exported functions). + +A future change will use this to implement a generict fget*ent_r +function. + +Tested-by: Carlos O'Donell +Reviewed-by: Carlos O'Donell +--- + include/nss_files.h | 48 ++++++++++++--------------------------------- + nss/nss_files/files-parse.c | 5 +++-- + 2 files changed, 15 insertions(+), 38 deletions(-) + +diff --git a/include/nss_files.h b/include/nss_files.h +index 54b354a..d0f2681 100644 +--- a/include/nss_files.h ++++ b/include/nss_files.h +@@ -26,45 +26,21 @@ FILE *__nss_files_fopen (const char *path); + libc_hidden_proto (__nss_files_fopen) + + struct parser_data; +-struct etherent; +-struct group; +-struct netent; +-struct passwd; +-struct protoent; +-struct rpcent; +-struct servent; +-struct sgrp; +-struct spwd; + + /* Instances of the parse_line function from + nss/nss_files/files-parse.c. */ +-extern int _nss_files_parse_etherent (char *line, struct etherent *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-extern int _nss_files_parse_grent (char *line, struct group *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-extern int _nss_files_parse_netent (char *line, struct netent *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-extern int _nss_files_parse_protoent (char *line, struct protoent *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-extern int _nss_files_parse_pwent (char *line, struct passwd *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-extern int _nss_files_parse_rpcent (char *line, struct rpcent *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-extern int _nss_files_parse_servent (char *line, struct servent *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-extern int _nss_files_parse_sgent (char *line, struct sgrp *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-extern int _nss_files_parse_spent (char *line, struct spwd *result, +- struct parser_data *data, +- size_t datalen, int *errnop); ++typedef int nss_files_parse_line (char *line, void *result, ++ struct parser_data *data, ++ size_t datalen, int *errnop); ++extern nss_files_parse_line _nss_files_parse_etherent; ++extern nss_files_parse_line _nss_files_parse_grent; ++extern nss_files_parse_line _nss_files_parse_netent; ++extern nss_files_parse_line _nss_files_parse_protoent; ++extern nss_files_parse_line _nss_files_parse_pwent; ++extern nss_files_parse_line _nss_files_parse_rpcent; ++extern nss_files_parse_line _nss_files_parse_servent; ++extern nss_files_parse_line _nss_files_parse_sgent; ++extern nss_files_parse_line _nss_files_parse_spent; + + libnss_files_hidden_proto (_nss_files_parse_etherent) + libc_hidden_proto (_nss_files_parse_grent) +diff --git a/nss/nss_files/files-parse.c b/nss/nss_files/files-parse.c +index 3820287..c6cd43b 100644 +--- a/nss/nss_files/files-parse.c ++++ b/nss/nss_files/files-parse.c +@@ -87,7 +87,7 @@ struct parser_data + #ifdef EXTERN_PARSER + + /* The parser is defined in a different module. */ +-extern int parse_line (char *line, struct STRUCTURE *result, ++extern int parse_line (char *line, void *result, + struct parser_data *data, size_t datalen, int *errnop + EXTRA_ARGS_DECL); + +@@ -99,10 +99,11 @@ extern int parse_line (char *line, struct STRUCTURE *result, + + # define LINE_PARSER(EOLSET, BODY) \ + parser_stclass int \ +-parse_line (char *line, struct STRUCTURE *result, \ ++parse_line (char *line, void *generic_result, \ + struct parser_data *data, size_t datalen, int *errnop \ + EXTRA_ARGS_DECL) \ + { \ ++ struct STRUCTURE *result = generic_result; \ + ENTDATA_DECL (data) \ + BUFFER_PREPARE \ + char *p = strpbrk (line, EOLSET "\n"); \ +-- +1.8.3.1 + diff --git a/SOURCES/glibc-rh1871397-5.patch b/SOURCES/glibc-rh1871397-5.patch new file mode 100644 index 0000000..857cd83 --- /dev/null +++ b/SOURCES/glibc-rh1871397-5.patch @@ -0,0 +1,28 @@ +From d4b4586315974d2471486d41891aa9463a5838ad Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 16 Jul 2020 17:00:46 +0200 +Subject: [PATCH 05/11] libio: Add fseterr_unlocked for internal use + +Tested-by: Carlos O'Donell +Reviewed-by: Carlos O'Donell +--- + include/stdio.h | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff -rup a/include/stdio.h b/include/stdio.h +--- a/include/stdio.h 2020-09-14 17:39:06.191727167 -0400 ++++ b/include/stdio.h 2020-09-14 17:43:44.780222972 -0400 +@@ -9,6 +9,13 @@ + + /* Now define the internal interfaces. */ + ++/* Set the error indicator on FP. */ ++static inline void ++fseterr_unlocked (FILE *fp) ++{ ++ fp->_flags |= _IO_ERR_SEEN; ++} ++ + extern int __fcloseall (void) attribute_hidden; + extern int __snprintf (char *__restrict __s, size_t __maxlen, + const char *__restrict __format, ...) diff --git a/SOURCES/glibc-rh1871397-6.patch b/SOURCES/glibc-rh1871397-6.patch new file mode 100644 index 0000000..997f84a --- /dev/null +++ b/SOURCES/glibc-rh1871397-6.patch @@ -0,0 +1,406 @@ +commit bdee910e88006ae33dc83ac3d2c0708adb6627d0 +Author: Florian Weimer +Date: Wed Jul 15 13:41:31 2020 +0200 + + nss: Add __nss_fgetent_r + + And helper functions __nss_readline, __nss_readline_seek, + __nss_parse_line_result. + + This consolidates common code for handling overlong lines and + parse files. Use the new functionality in internal_getent + in nss/nss_files/files-XXX.c. + + Tested-by: Carlos O'Donell + Reviewed-by: Carlos O'Donell + +diff -rupN a/include/nss_files.h b/include/nss_files.h +--- a/include/nss_files.h 2020-09-14 17:48:49.353699306 -0400 ++++ b/include/nss_files.h 2020-09-14 17:55:21.856488740 -0400 +@@ -25,6 +25,28 @@ + FILE *__nss_files_fopen (const char *path); + libc_hidden_proto (__nss_files_fopen) + ++/* Read a line from FP, storing it BUF. Strip leading blanks and skip ++ comments. Sets errno and returns error code on failure. Special ++ failure: ERANGE means the buffer is too small. The function writes ++ the original offset to *POFFSET (which can be negative in the case ++ of non-seekable input). */ ++int __nss_readline (FILE *fp, char *buf, size_t len, off64_t *poffset); ++libc_hidden_proto (__nss_readline) ++ ++/* Seek FP to OFFSET. Sets errno and returns error code on failure. ++ On success, sets errno to ERANGE and returns ERANGE (to indicate ++ re-reading of the same input line to the caller). If OFFSET is ++ negative, fail with ESPIPE without seeking. Intended to be used ++ after parsing data read by __nss_readline failed with ERANGE. */ ++int __nss_readline_seek (FILE *fp, off64_t offset) attribute_hidden; ++ ++/* Handles the result of a parse_line call (as defined by ++ nss/nss_files/files-parse.c). Adjusts the file offset of FP as ++ necessary. Returns 0 on success, and updates errno on failure (and ++ returns that error code). */ ++int __nss_parse_line_result (FILE *fp, off64_t offset, int parse_line_result); ++libc_hidden_proto (__nss_parse_line_result) ++ + struct parser_data; + + /* Instances of the parse_line function from +@@ -52,4 +74,11 @@ libnss_files_hidden_proto (_nss_files_pa + libc_hidden_proto (_nss_files_parse_sgent) + libc_hidden_proto (_nss_files_parse_spent) + ++/* Generic implementation of fget*ent_r. Reads lines from FP until ++ EOF or a successful parse into *RESULT using PARSER. Returns 0 on ++ success, ENOENT on EOF, ERANGE on too-small buffer. */ ++int __nss_fgetent_r (FILE *fp, void *result, ++ char *buffer, size_t buffer_length, ++ nss_files_parse_line parser) attribute_hidden; ++ + #endif /* _NSS_FILES_H */ +diff -rupN a/nss/Makefile b/nss/Makefile +--- a/nss/Makefile 2020-09-14 17:48:49.293697045 -0400 ++++ b/nss/Makefile 2020-09-14 17:55:21.860488891 -0400 +@@ -28,7 +28,9 @@ headers := nss.h + routines = nsswitch getnssent getnssent_r digits_dots \ + valid_field valid_list_field rewrite_field \ + $(addsuffix -lookup,$(databases)) \ +- compat-lookup nss_hash nss_files_fopen ++ compat-lookup nss_hash nss_files_fopen \ ++ nss_readline nss_parse_line_result \ ++ nss_fgetent_r + + # These are the databases that go through nss dispatch. + # Caution: if you add a database here, you must add its real name +diff -rupN a/nss/Versions b/nss/Versions +--- a/nss/Versions 2020-09-14 17:48:49.294697083 -0400 ++++ b/nss/Versions 2020-09-14 17:55:21.867489155 -0400 +@@ -21,7 +21,7 @@ libc { + __nss_passwd_lookup2; __nss_group_lookup2; __nss_hosts_lookup2; + __nss_services_lookup2; __nss_next2; __nss_lookup; + __nss_hash; __nss_database_lookup2; +- __nss_files_fopen; ++ __nss_files_fopen; __nss_readline; __nss_parse_line_result; + } + } + +diff -rupN a/nss/nss_fgetent_r.c b/nss/nss_fgetent_r.c +--- a/nss/nss_fgetent_r.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/nss/nss_fgetent_r.c 2020-09-14 17:55:21.870489268 -0400 +@@ -0,0 +1,55 @@ ++/* Generic implementation of fget*ent_r. ++ Copyright (C) 2020 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++ ++int ++__nss_fgetent_r (FILE *fp, void *result, char *buffer, size_t buffer_length, ++ nss_files_parse_line parser) ++{ ++ int ret; ++ ++ _IO_flockfile (fp); ++ ++ while (true) ++ { ++ off64_t original_offset; ++ ret = __nss_readline (fp, buffer, buffer_length, &original_offset); ++ if (ret == 0) ++ { ++ /* Parse the line into *RESULT. */ ++ ret = parser (buffer, result, ++ (struct parser_data *) buffer, buffer_length, &errno); ++ ++ /* Translate the result code from the parser into an errno ++ value. Also seeks back to the start of the line if ++ necessary. */ ++ ret = __nss_parse_line_result (fp, original_offset, ret); ++ ++ if (ret == EINVAL) ++ /* Skip over malformed lines. */ ++ continue; ++ } ++ break; ++ } ++ ++ _IO_funlockfile (fp); ++ ++ return ret; ++} +diff -rupN a/nss/nss_files/files-XXX.c b/nss/nss_files/files-XXX.c +--- a/nss/nss_files/files-XXX.c 2020-09-14 17:48:49.296697158 -0400 ++++ b/nss/nss_files/files-XXX.c 2020-09-14 17:55:21.878489569 -0400 +@@ -135,10 +135,9 @@ internal_getent (FILE *stream, struct ST + char *buffer, size_t buflen, int *errnop H_ERRNO_PROTO + EXTRA_ARGS_DECL) + { +- char *p; + struct parser_data *data = (void *) buffer; + size_t linebuflen = buffer + buflen - data->linebuffer; +- int parse_result; ++ int saved_errno = errno; /* Do not clobber errno on success. */ + + if (buflen < sizeof *data + 2) + { +@@ -149,66 +148,42 @@ internal_getent (FILE *stream, struct ST + + while (true) + { +- ssize_t r = __libc_readline_unlocked +- (stream, data->linebuffer, linebuflen); +- if (r < 0) +- { +- *errnop = errno; +- H_ERRNO_SET (NETDB_INTERNAL); +- if (*errnop == ERANGE) +- /* Request larger buffer. */ +- return NSS_STATUS_TRYAGAIN; +- else +- /* Other read failure. */ +- return NSS_STATUS_UNAVAIL; +- } +- else if (r == 0) ++ off64_t original_offset; ++ int ret = __nss_readline (stream, data->linebuffer, linebuflen, ++ &original_offset); ++ if (ret == ENOENT) + { + /* End of file. */ + H_ERRNO_SET (HOST_NOT_FOUND); ++ __set_errno (saved_errno); + return NSS_STATUS_NOTFOUND; + } +- +- /* Everything OK. Now skip leading blanks. */ +- p = data->linebuffer; +- while (isspace (*p)) +- ++p; +- +- /* Ignore empty and comment lines. */ +- if (*p == '\0' || *p == '#') +- continue; +- +- /* Parse the line. */ +- *errnop = EINVAL; +- parse_result = parse_line (p, result, data, buflen, errnop EXTRA_ARGS); +- +- if (parse_result == -1) ++ else if (ret == 0) + { +- if (*errnop == ERANGE) ++ ret = __nss_parse_line_result (stream, original_offset, ++ parse_line (data->linebuffer, ++ result, data, buflen, ++ errnop EXTRA_ARGS)); ++ if (ret == 0) + { +- /* Return to the original file position at the beginning +- of the line, so that the next call can read it again +- if necessary. */ +- if (__fseeko64 (stream, -r, SEEK_CUR) != 0) +- { +- if (errno == ERANGE) +- *errnop = EINVAL; +- else +- *errnop = errno; +- H_ERRNO_SET (NETDB_INTERNAL); +- return NSS_STATUS_UNAVAIL; +- } ++ /* Line has been parsed successfully. */ ++ __set_errno (saved_errno); ++ return NSS_STATUS_SUCCESS; + } +- H_ERRNO_SET (NETDB_INTERNAL); +- return NSS_STATUS_TRYAGAIN; ++ else if (ret == EINVAL) ++ /* If it is invalid, loop to get the next line of the file ++ to parse. */ ++ continue; + } + +- /* Return the data if parsed successfully. */ +- if (parse_result != 0) +- return NSS_STATUS_SUCCESS; +- +- /* If it is invalid, loop to get the next line of the file to +- parse. */ ++ *errnop = ret; ++ H_ERRNO_SET (NETDB_INTERNAL); ++ if (ret == ERANGE) ++ /* Request larger buffer. */ ++ return NSS_STATUS_TRYAGAIN; ++ else ++ /* Other read failure. */ ++ return NSS_STATUS_UNAVAIL; + } + } + +diff -rupN a/nss/nss_parse_line_result.c b/nss/nss_parse_line_result.c +--- a/nss/nss_parse_line_result.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/nss/nss_parse_line_result.c 2020-09-14 17:55:21.880489645 -0400 +@@ -0,0 +1,46 @@ ++/* Implementation of __nss_parse_line_result. ++ Copyright (C) 2020 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++#include ++#include ++ ++int ++__nss_parse_line_result (FILE *fp, off64_t offset, int parse_line_result) ++{ ++ assert (parse_line_result >= -1 && parse_line_result <= 1); ++ ++ switch (__builtin_expect (parse_line_result, 1)) ++ { ++ case 1: ++ /* Sucess. */ ++ return 0; ++ case 0: ++ /* Parse error. */ ++ __set_errno (EINVAL); ++ return EINVAL; ++ case -1: ++ /* Out of buffer space. */ ++ return __nss_readline_seek (fp, offset); ++ ++ default: ++ __builtin_unreachable (); ++ } ++} ++libc_hidden_def (__nss_parse_line_result) +diff -rupN a/nss/nss_readline.c b/nss/nss_readline.c +--- a/nss/nss_readline.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/nss/nss_readline.c 2020-09-14 17:55:21.883489758 -0400 +@@ -0,0 +1,99 @@ ++/* Read a line from an nss_files database file. ++ Copyright (C) 2020 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++#include ++#include ++#include ++ ++int ++__nss_readline (FILE *fp, char *buf, size_t len, off64_t *poffset) ++{ ++ /* We need space for at least one character, the line terminator, ++ and the NUL byte. */ ++ if (len < 3) ++ { ++ *poffset = -1; ++ __set_errno (ERANGE); ++ return ERANGE; ++ } ++ ++ while (true) ++ { ++ /* Keep original offset for retries. */ ++ *poffset = __ftello64 (fp); ++ ++ buf[len - 1] = '\xff'; /* Marker to recognize truncation. */ ++ if (fgets_unlocked (buf, len, fp) == NULL) ++ { ++ if (feof_unlocked (fp)) ++ { ++ __set_errno (ENOENT); ++ return ENOENT; ++ } ++ else ++ { ++ /* Any other error. Do not return ERANGE in this case ++ because the caller would retry. */ ++ if (errno == ERANGE) ++ __set_errno (EINVAL); ++ return errno; ++ } ++ } ++ else if (buf[len - 1] != '\xff') ++ /* The buffer is too small. Arrange for re-reading the same ++ line on the next call. */ ++ return __nss_readline_seek (fp, *poffset); ++ ++ /* fgets_unlocked succeeded. */ ++ ++ /* Remove leading whitespace. */ ++ char *p = buf; ++ while (isspace (*p)) ++ ++p; ++ if (*p == '\0' || *p == '#') ++ /* Skip empty lines and comments. */ ++ continue; ++ if (p != buf) ++ memmove (buf, p, strlen (p)); ++ ++ /* Return line to the caller. */ ++ return 0; ++ } ++} ++libc_hidden_def (__nss_readline) ++ ++int ++__nss_readline_seek (FILE *fp, off64_t offset) ++{ ++ if (offset < 0 /* __ftello64 failed. */ ++ || __fseeko64 (fp, offset, SEEK_SET) < 0) ++ { ++ /* Without seeking support, it is not possible to ++ re-read the same line, so this is a hard failure. */ ++ fseterr_unlocked (fp); ++ __set_errno (ESPIPE); ++ return ESPIPE; ++ } ++ else ++ { ++ __set_errno (ERANGE); ++ return ERANGE; ++ } ++} diff --git a/SOURCES/glibc-rh1871397-7.patch b/SOURCES/glibc-rh1871397-7.patch new file mode 100644 index 0000000..3465d9d --- /dev/null +++ b/SOURCES/glibc-rh1871397-7.patch @@ -0,0 +1,85 @@ +From 4f62a21d0ed19ff29bba704167179b862140d011 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 16 Jul 2020 17:28:28 +0200 +Subject: [PATCH 07/11] grp: Implement fgetgrent_r using __nss_fgetent_r + +Tested-by: Carlos O'Donell +Reviewed-by: Carlos O'Donell +--- + grp/fgetgrent_r.c | 54 ++++++------------------------------------------------ + 1 file changed, 6 insertions(+), 48 deletions(-) + +diff --git a/grp/fgetgrent_r.c b/grp/fgetgrent_r.c +index 03daf4f..b598584 100644 +--- a/grp/fgetgrent_r.c ++++ b/grp/fgetgrent_r.c +@@ -20,10 +20,6 @@ + #include + #include + +-#include +-#define flockfile(s) _IO_flockfile (s) +-#define funlockfile(s) _IO_funlockfile (s) +- + /* Define a line parsing function using the common code + used in the nss_files module. */ + +@@ -59,49 +55,11 @@ int + __fgetgrent_r (FILE *stream, struct group *resbuf, char *buffer, size_t buflen, + struct group **result) + { +- char *p; +- int parse_result; +- +- flockfile (stream); +- do +- { +- buffer[buflen - 1] = '\xff'; +- p = fgets_unlocked (buffer, buflen, stream); +- if (__builtin_expect (p == NULL, 0) && feof_unlocked (stream)) +- { +- funlockfile (stream); +- *result = NULL; +- __set_errno (ENOENT); +- return errno; +- } +- if (__builtin_expect (p == NULL, 0) || buffer[buflen - 1] != '\xff') +- { +- funlockfile (stream); +- *result = NULL; +- __set_errno (ERANGE); +- return errno; +- } +- +- /* Skip leading blanks. */ +- while (isspace (*p)) +- ++p; +- } while (*p == '\0' || *p == '#' /* Ignore empty and comment lines. */ +- /* Parse the line. If it is invalid, loop to +- get the next line of the file to parse. */ +- || ! (parse_result = parse_line (p, resbuf, +- (void *) buffer, buflen, +- &errno))); +- +- funlockfile (stream); +- +- if (__builtin_expect (parse_result, 0) == -1) +- { +- /* The parser ran out of space. */ +- *result = NULL; +- return errno; +- } +- +- *result = resbuf; +- return 0; ++ int ret = __nss_fgetent_r (stream, resbuf, buffer, buflen, parse_line); ++ if (ret == 0) ++ *result = resbuf; ++ else ++ *result = NULL; ++ return ret; + } + weak_alias (__fgetgrent_r, fgetgrent_r) +-- +1.8.3.1 + diff --git a/SOURCES/glibc-rh1871397-8.patch b/SOURCES/glibc-rh1871397-8.patch new file mode 100644 index 0000000..58bd476 --- /dev/null +++ b/SOURCES/glibc-rh1871397-8.patch @@ -0,0 +1,272 @@ +From 2add4235ef674988948155f9a8f60a8c7b09bcff Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 16 Jul 2020 17:31:20 +0200 +Subject: [PATCH 08/11] gshadow: Implement fgetsgent_r using __nss_fgetent_r + (bug 20338) + +Tested-by: Carlos O'Donell +Reviewed-by: Carlos O'Donell +--- + gshadow/Makefile | 2 +- + gshadow/fgetsgent_r.c | 41 ++-------- + gshadow/tst-fgetsgent_r.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 198 insertions(+), 36 deletions(-) + create mode 100644 gshadow/tst-fgetsgent_r.c + +diff -rupN a/gshadow/Makefile b/gshadow/Makefile +--- a/gshadow/Makefile 2018-08-01 01:10:47.000000000 -0400 ++++ b/gshadow/Makefile 2020-09-14 18:00:57.167145887 -0400 +@@ -26,7 +26,7 @@ headers = gshadow.h + routines = getsgent getsgnam sgetsgent fgetsgent putsgent \ + getsgent_r getsgnam_r sgetsgent_r fgetsgent_r + +-tests = tst-gshadow tst-putsgent ++tests = tst-gshadow tst-putsgent tst-fgetsgent_r + + CFLAGS-getsgent_r.c += -fexceptions + CFLAGS-getsgent.c += -fexceptions +diff -rupN a/gshadow/fgetsgent_r.c b/gshadow/fgetsgent_r.c +--- a/gshadow/fgetsgent_r.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/gshadow/fgetsgent_r.c 2020-09-14 18:45:59.189353065 -0400 +@@ -36,40 +36,11 @@ int + __fgetsgent_r (FILE *stream, struct sgrp *resbuf, char *buffer, size_t buflen, + struct sgrp **result) + { +- char *p; +- +- _IO_flockfile (stream); +- do +- { +- buffer[buflen - 1] = '\xff'; +- p = fgets_unlocked (buffer, buflen, stream); +- if (p == NULL && feof_unlocked (stream)) +- { +- _IO_funlockfile (stream); +- *result = NULL; +- __set_errno (ENOENT); +- return errno; +- } +- if (p == NULL || buffer[buflen - 1] != '\xff') +- { +- _IO_funlockfile (stream); +- *result = NULL; +- __set_errno (ERANGE); +- return errno; +- } +- +- /* Skip leading blanks. */ +- while (isspace (*p)) +- ++p; +- } while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */ +- /* Parse the line. If it is invalid, loop to +- get the next line of the file to parse. */ +- ! parse_line (buffer, (void *) resbuf, (void *) buffer, buflen, +- &errno)); +- +- _IO_funlockfile (stream); +- +- *result = resbuf; +- return 0; ++ int ret = __nss_fgetent_r (stream, resbuf, buffer, buflen, parse_line); ++ if (ret == 0) ++ *result = resbuf; ++ else ++ *result = NULL; ++ return ret; + } + weak_alias (__fgetsgent_r, fgetsgent_r) +diff -rupN a/gshadow/tst-fgetsgent_r.c b/gshadow/tst-fgetsgent_r.c +--- a/gshadow/tst-fgetsgent_r.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/gshadow/tst-fgetsgent_r.c 2020-09-14 18:00:57.174146151 -0400 +@@ -0,0 +1,191 @@ ++/* Test for fgetsgent_r and buffer sizes. ++ Copyright (C) 2020 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Turn a parsed struct back into a line string. The returned string ++ should be freed. */ ++static char * ++format_ent (const struct sgrp *e) ++{ ++ struct xmemstream stream; ++ xopen_memstream (&stream); ++ TEST_COMPARE (putsgent (e, stream.out), 0); ++ xfclose_memstream (&stream); ++ return stream.buffer; ++} ++ ++/* An entry in the input file along with the expected output. */ ++struct input ++{ ++ const char *line; /* Line in the file. */ ++ const char *expected; /* Expected output. NULL if skipped. */ ++}; ++ ++const struct input inputs[] = ++ { ++ /* Regular entries. */ ++ { "g1:x1::\n", "g1:x1::\n" }, ++ { "g2:x2:a1:\n", "g2:x2:a1:\n" }, ++ { "g3:x3:a2:u1\n", "g3:x3:a2:u1\n" }, ++ { "g4:x4:a3,a4:u2,u3,u4\n", "g4:x4:a3,a4:u2,u3,u4\n" }, ++ ++ /* Comments and empty lines. */ ++ { "\n", NULL }, ++ { " \n", NULL }, ++ { "\t\n", NULL }, ++ { "#g:x::\n", NULL }, ++ { " #g:x::\n", NULL }, ++ { "\t#g:x::\n", NULL }, ++ { " \t#g:x::\n", NULL }, ++ ++ /* Marker for synchronization. */ ++ { "g5:x5::\n", "g5:x5::\n" }, ++ ++ /* Leading whitespace. */ ++ { " g6:x6::\n", "g6:x6::\n" }, ++ { "\tg7:x7::\n", "g7:x7::\n" }, ++ ++ /* This is expected to trigger buffer exhaustion during parsing ++ (bug 20338). */ ++ { ++ "g8:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:u5,u6,u7,u8,u9:\n", ++ "g8:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:u5,u6,u7,u8,u9:\n", ++ }, ++ { ++ "g9:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx::a5,a6,a7,a8,a9,a10\n", ++ "g9:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx::a5,a6,a7,a8,a9,a10\n", ++ }, ++ }; ++ ++/* Writes the test data to a temporary file and returns its name. The ++ returned pointer should be freed. */ ++static char * ++create_test_file (void) ++{ ++ char *path; ++ int fd = create_temp_file ("tst-fgetsgent_r-", &path); ++ FILE *fp = fdopen (fd, "w"); ++ TEST_VERIFY_EXIT (fp != NULL); ++ ++ for (size_t i = 0; i < array_length (inputs); ++i) ++ fputs (inputs[i].line, fp); ++ ++ xfclose (fp); ++ return path; ++} ++ ++/* Read the test file with the indicated start buffer size. Return ++ true if the buffer size had to be increased during reading. */ ++static bool ++run_test (const char *path, size_t buffer_size) ++{ ++ bool resized = false; ++ FILE *fp = xfopen (path, "r"); ++ ++ /* This avoids repeated lseek system calls (bug 26257). */ ++ TEST_COMPARE (fseeko64 (fp, 0, SEEK_SET), 0); ++ ++ size_t i = 0; ++ while (true) ++ { ++ /* Skip over unused expected entries. */ ++ while (i < array_length (inputs) && inputs[i].expected == NULL) ++ ++i; ++ ++ /* Store the data on the heap, to help valgrind to detect ++ invalid accesses. */ ++ struct sgrp *result_storage = xmalloc (sizeof (*result_storage)); ++ char *buffer = xmalloc (buffer_size); ++ struct sgrp **result_pointer_storage ++ = xmalloc (sizeof (*result_pointer_storage)); ++ ++ int ret = fgetsgent_r (fp, result_storage, buffer, buffer_size, ++ result_pointer_storage); ++ if (ret == 0) ++ { ++ TEST_VERIFY (*result_pointer_storage != NULL); ++ TEST_VERIFY (i < array_length (inputs)); ++ if (*result_pointer_storage != NULL ++ && i < array_length (inputs)) ++ { ++ char * actual = format_ent (*result_pointer_storage); ++ TEST_COMPARE_STRING (inputs[i].expected, actual); ++ free (actual); ++ ++i; ++ } ++ else ++ break; ++ } ++ else ++ { ++ TEST_VERIFY (*result_pointer_storage == NULL); ++ TEST_COMPARE (ret, errno); ++ ++ if (ret == ENOENT) ++ { ++ TEST_COMPARE (i, array_length (inputs)); ++ free (result_pointer_storage); ++ free (buffer); ++ free (result_storage); ++ break; ++ } ++ else if (ret == ERANGE) ++ { ++ resized = true; ++ ++buffer_size; ++ } ++ else ++ FAIL_EXIT1 ("read failure: %m"); ++ } ++ ++ free (result_pointer_storage); ++ free (buffer); ++ free (result_storage); ++ } ++ ++ return resized; ++} ++ ++static int ++do_test (void) ++{ ++ char *path = create_test_file (); ++ ++ for (size_t buffer_size = 3; ; ++buffer_size) ++ { ++ bool resized = run_test (path, buffer_size); ++ if (!resized) ++ break; ++ } ++ ++ free (path); ++ ++ return 0; ++} ++ ++#include diff --git a/SOURCES/glibc-rh1871397-9.patch b/SOURCES/glibc-rh1871397-9.patch new file mode 100644 index 0000000..4e0396e --- /dev/null +++ b/SOURCES/glibc-rh1871397-9.patch @@ -0,0 +1,70 @@ +From ee1c062be09da006e82ab34c1c9b5c82dd2af92c Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 16 Jul 2020 17:34:19 +0200 +Subject: [PATCH 09/11] pwd: Implement fgetpwent_r using __nss_fgetent_r + +Tested-by: Carlos O'Donell +Reviewed-by: Carlos O'Donell +--- + pwd/fgetpwent_r.c | 43 ++++++------------------------------------- + 1 file changed, 6 insertions(+), 37 deletions(-) + +diff -rup a/pwd/fgetpwent_r.c b/pwd/fgetpwent_r.c +--- a/pwd/fgetpwent_r.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/pwd/fgetpwent_r.c 2020-09-14 19:03:41.277514743 -0400 +@@ -20,9 +20,6 @@ + #include + #include + +-#define flockfile(s) _IO_flockfile (s) +-#define funlockfile(s) _IO_funlockfile (s) +- + /* Define a line parsing function using the common code + used in the nss_files module. */ + +@@ -72,39 +69,11 @@ int + __fgetpwent_r (FILE *stream, struct passwd *resbuf, char *buffer, + size_t buflen, struct passwd **result) + { +- char *p; +- +- flockfile (stream); +- do +- { +- buffer[buflen - 1] = '\xff'; +- p = fgets_unlocked (buffer, buflen, stream); +- if (p == NULL && feof_unlocked (stream)) +- { +- funlockfile (stream); +- *result = NULL; +- __set_errno (ENOENT); +- return errno; +- } +- if (p == NULL || buffer[buflen - 1] != '\xff') +- { +- funlockfile (stream); +- *result = NULL; +- __set_errno (ERANGE); +- return errno; +- } +- +- /* Skip leading blanks. */ +- while (isspace (*p)) +- ++p; +- } while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */ +- /* Parse the line. If it is invalid, loop to +- get the next line of the file to parse. */ +- ! parse_line (p, resbuf, (void *) buffer, buflen, &errno)); +- +- funlockfile (stream); +- +- *result = resbuf; +- return 0; ++ int ret = __nss_fgetent_r (stream, resbuf, buffer, buflen, parse_line); ++ if (ret == 0) ++ *result = resbuf; ++ else ++ *result = NULL; ++ return ret; + } + weak_alias (__fgetpwent_r, fgetpwent_r) diff --git a/SPECS/glibc.spec b/SPECS/glibc.spec index a341012..d8bef1d 100644 --- a/SPECS/glibc.spec +++ b/SPECS/glibc.spec @@ -1,6 +1,6 @@ %define glibcsrcdir glibc-2.28 %define glibcversion 2.28 -%define glibcrelease 129%{?dist} +%define glibcrelease 132%{?dist} # Pre-release tarballs are pulled in from git using a command that is # effectively: # @@ -495,6 +495,22 @@ Patch361: glibc-rh1871387-3.patch Patch362: glibc-rh1871387-4.patch Patch363: glibc-rh1871387-5.patch Patch364: glibc-rh1871387-6.patch +Patch365: glibc-rh1871394-1.patch +Patch366: glibc-rh1871394-2.patch +Patch367: glibc-rh1871394-3.patch +Patch368: glibc-rh1871395-1.patch +Patch369: glibc-rh1871395-2.patch +Patch370: glibc-rh1871397-1.patch +Patch371: glibc-rh1871397-2.patch +Patch372: glibc-rh1871397-3.patch +Patch373: glibc-rh1871397-4.patch +Patch374: glibc-rh1871397-5.patch +Patch375: glibc-rh1871397-6.patch +Patch376: glibc-rh1871397-7.patch +Patch377: glibc-rh1871397-8.patch +Patch378: glibc-rh1871397-9.patch +Patch379: glibc-rh1871397-10.patch +Patch380: glibc-rh1871397-11.patch ############################################################################## # Continued list of core "glibc" package information: @@ -2393,6 +2409,16 @@ fi %files -f compat-libpthread-nonshared.filelist -n compat-libpthread-nonshared %changelog +* Mon Oct 5 2020 DJ Delorie - 2.28-132 +- Fix fgetsgent_r data corruption bug (#1871397) + +* Fri Oct 02 2020 Patsy Griffin - 2.28-131 +- Improve IBM zSeries (s390x) Performance (#1871395) + +* Fri Oct 02 2020 Patsy Griffin - 2.28-130 +- Fix avx2 strncmp offset compare condition check (#1871394) +- Add strncmp and strcmp testcases for page boundary + * Fri Sep 18 2020 Arjun Shankar - 2.28-129 - Improve IBM POWER9 architecture performance (#1871387)