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 <skpgkp1@gmail.com>
+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 <hjl.tools@gmail.com>
+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 <skpgkp1@gmail.com>
+    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 <hjl.tools@gmail.com>
+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 <stli@linux.ibm.com>
+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 <stli@linux.ibm.com>
+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 <fweimer@redhat.com>
+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 <carlos@redhat.com>
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+---
+ 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
++   <https://www.gnu.org/licenses/>.  */
++
++#ifndef _NSS_FILES_H
++#define _NSS_FILES_H
++
++#include <stdio.h>
++
++/* 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 <fcntl.h>
+ #include <libc-lock.h>
+ #include "nsswitch.h"
++#include <nss_files.h>
+ 
+ #include <kernel-features.h>
+ 
+@@ -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 <kernel-features.h>
+ 
+ #include "nsswitch.h"
++#include <nss_files.h>
+ 
+ /* 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 <stdbool.h>
+ #include <stdlib.h>
+ #include <scratch_buffer.h>
++#include <nss_files.h>
+ 
+ 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 <string.h>
+ #include "nsswitch.h"
+ #include "netgroup.h"
++#include <nss_files.h>
+ 
+ #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
++   <https://www.gnu.org/licenses/>.  */
++
++#include <nss_files.h>
++
++#include <errno.h>
++#include <stdio_ext.h>
++
++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 <fweimer@redhat.com>
+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 <carlos@redhat.com>
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+---
+ 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 <shadow.h>
+ #include <stdio.h>
+ 
+-#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 <fweimer@redhat.com>
+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 <carlos@redhat.com>
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+---
+ 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
+-   <http://www.gnu.org/licenses/>.  */
+-
+-#include <assert.h>
+-#include <errno.h>
+-#include <stdio.h>
+-#include <string.h>
+-
+-#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
+-   <http://www.gnu.org/licenses/>.  */
+-
+-/* Exercise __libc_readline_unlocked with various combinations of line
+-   lengths, stdio buffer sizes, and line read buffer sizes.  */
+-
+-#include <errno.h>
+-#include <stdbool.h>
+-#include <stdio.h>
+-#include <string.h>
+-#include <support/check.h>
+-#include <support/support.h>
+-#include <support/temp_file.h>
+-#include <support/test-driver.h>
+-#include <support/xmemstream.h>
+-#include <support/xstdio.h>
+-#include <support/xunistd.h>
+-
+-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 <support/test-driver.c>
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 <fweimer@redhat.com>
+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 <carlos@redhat.com>
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+---
+ 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 <string.h>
+ #include <libc-lock.h>
+ #include <kernel-features.h>
++#include <nss_files.h>
+ 
+ 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 <libc-lock.h>
+ #include <kernel-features.h>
+ #include <scratch_buffer.h>
++#include <nss_files.h>
+ 
+ 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 <string.h>
+ #include <libc-lock.h>
+ #include <kernel-features.h>
++#include <nss_files.h>
+ 
+ #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 <string.h>
+ #include <libc-lock.h>
+ #include <kernel-features.h>
++#include <nss_files.h>
+ 
+ #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 <fweimer@redhat.com>
+Date: Thu, 16 Jul 2020 16:40:44 +0200
+Subject: [PATCH 03/11] nss_files: Consolidate line parse declarations in
+ <nss_files.h>
+
+These functions should eventually have the same type, so it makes
+sense to declare them together.
+
+Tested-by: Carlos O'Donell <carlos@redhat.com>
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+---
+ 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 <inet/netgroup.h>
+ 
+-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 <nss.h>
+ 
+-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 <string.h>
+ #include <stdlib.h>
+ #include <stdint.h>
++#include <nss_files.h>
+ 
+ /* 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 <fweimer@redhat.com>
+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 <carlos@redhat.com>
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+---
+ 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 <fweimer@redhat.com>
+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 <carlos@redhat.com>
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+---
+ 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 <fweimer@redhat.com>
+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 <carlos@redhat.com>
+    Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+
+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
++   <https://www.gnu.org/licenses/>.  */
++
++#include <errno.h>
++#include <nss_files.h>
++
++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
++   <https://www.gnu.org/licenses/>.  */
++
++#include <nss_files.h>
++
++#include <assert.h>
++#include <errno.h>
++
++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
++   <https://www.gnu.org/licenses/>.  */
++
++#include <nss_files.h>
++
++#include <ctype.h>
++#include <errno.h>
++#include <string.h>
++
++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 <fweimer@redhat.com>
+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 <carlos@redhat.com>
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+---
+ 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 <grp.h>
+ #include <stdio.h>
+ 
+-#include <libio/iolibio.h>
+-#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 <fweimer@redhat.com>
+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 <carlos@redhat.com>
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+---
+ 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
++   <https://www.gnu.org/licenses/>.  */
++
++#include <array_length.h>
++#include <errno.h>
++#include <gshadow.h>
++#include <stdbool.h>
++#include <stdlib.h>
++#include <support/check.h>
++#include <support/support.h>
++#include <support/temp_file.h>
++#include <support/xmemstream.h>
++#include <support/xstdio.h>
++
++/* 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 <support/test-driver.c>
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 <fweimer@redhat.com>
+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 <carlos@redhat.com>
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+---
+ 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 <stdio.h>
+ #include <pwd.h>
+ 
+-#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 <dj@redhat.com> - 2.28-132
+- Fix fgetsgent_r data corruption bug (#1871397)
+
+* Fri Oct 02 2020 Patsy Griffin <patsy@redhat.com> - 2.28-131
+- Improve IBM zSeries (s390x) Performance (#1871395)
+
+* Fri Oct 02 2020 Patsy Griffin <patsy@redhat.com> - 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 <arjun@redhat.com> - 2.28-129
 - Improve IBM POWER9 architecture performance (#1871387)