diff --git a/SOURCES/build-locale-archive.c b/SOURCES/build-locale-archive.c
index 9183972..3cb3b47 100644
--- a/SOURCES/build-locale-archive.c
+++ b/SOURCES/build-locale-archive.c
@@ -448,7 +448,7 @@ fill_archive (struct locarhandle *tmpl_ah,
 		      char fullname[fnamelen + 2 * strlen (d->d_name) + 7];
 
 #ifdef _DIRENT_HAVE_D_TYPE
-		      if (d_type == DT_UNKNOWN)
+		      if (d_type == DT_UNKNOWN || d_type == DT_LNK)
 #endif
 			{
 			  strcpy (stpcpy (stpcpy (fullname, fname), "/"),
diff --git a/SOURCES/glibc-rh2033684-1.patch b/SOURCES/glibc-rh2033684-1.patch
new file mode 100644
index 0000000..8734628
--- /dev/null
+++ b/SOURCES/glibc-rh2033684-1.patch
@@ -0,0 +1,27 @@
+commit 2a08b6e8331a611dc29325bfa6e29fecc9a3a46e
+Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date:   Thu Dec 10 16:47:02 2020 +0530
+
+    Warn on unsupported fortification levels
+    
+    Make the _FORTIFY_SOURCE macro soup in features.h warn about
+    unsupported fortification levels.  For example, it will warn about
+    _FORTIFY_SOURCE=3 and over with an indication of which level has been
+    selected.
+    
+    Co-authored-by: Paul Eggert <eggert@cs.ucla.edu>
+
+diff --git a/include/features.h b/include/features.h
+index 5bed0a499605a3a2..ea7673ee115bcf0a 100644
+--- a/include/features.h
++++ b/include/features.h
+@@ -382,6 +382,9 @@
+ # elif !__GNUC_PREREQ (4, 1)
+ #  warning _FORTIFY_SOURCE requires GCC 4.1 or later
+ # elif _FORTIFY_SOURCE > 1
++#  if _FORTIFY_SOURCE > 2
++#   warning _FORTIFY_SOURCE > 2 is treated like 2 on this platform
++#  endif
+ #  define __USE_FORTIFY_LEVEL 2
+ # else
+ #  define __USE_FORTIFY_LEVEL 1
diff --git a/SOURCES/glibc-rh2033684-10.patch b/SOURCES/glibc-rh2033684-10.patch
new file mode 100644
index 0000000..94b4519
--- /dev/null
+++ b/SOURCES/glibc-rh2033684-10.patch
@@ -0,0 +1,90 @@
+commit 2bbd07c715275eb6c616988925738a0517180d57
+Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date:   Fri Dec 17 18:35:44 2021 +0530
+
+    fortify: Fix spurious warning with realpath
+    
+    The length and object size arguments were swapped around for realpath.
+    Also add a smoke test so that any changes in this area get caught in
+    future.
+    
+    Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+    Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+
+diff --git a/debug/Makefile b/debug/Makefile
+index 81361438fc3d2aa9..b43f42ee3851f360 100644
+--- a/debug/Makefile
++++ b/debug/Makefile
+@@ -108,6 +108,7 @@ CFLAGS-tst-longjmp_chk2.c += -fexceptions -fasynchronous-unwind-tables
+ CPPFLAGS-tst-longjmp_chk2.c += -D_FORTIFY_SOURCE=1
+ CFLAGS-tst-longjmp_chk3.c += -fexceptions -fasynchronous-unwind-tables
+ CPPFLAGS-tst-longjmp_chk3.c += -D_FORTIFY_SOURCE=1
++CPPFLAGS-tst-realpath-chk.c += -D_FORTIFY_SOURCE=2
+ 
+ # We know these tests have problems with format strings, this is what
+ # we are testing.  Disable that warning.  They are also testing
+@@ -155,7 +156,7 @@ tests = backtrace-tst tst-longjmp_chk tst-chk1 tst-chk2 tst-chk3 \
+ 	tst-lfschk1 tst-lfschk2 tst-lfschk3 test-strcpy_chk test-stpcpy_chk \
+ 	tst-chk4 tst-chk5 tst-chk6 tst-chk7 tst-chk8 tst-lfschk4 tst-lfschk5 \
+ 	tst-lfschk6 tst-longjmp_chk2 tst-backtrace2 tst-backtrace3 \
+-	tst-backtrace4 tst-backtrace5 tst-backtrace6
++	tst-backtrace4 tst-backtrace5 tst-backtrace6 tst-realpath-chk
+ 
+ ifeq ($(have-ssp),yes)
+ tests += tst-ssp-1
+diff --git a/debug/tst-realpath-chk.c b/debug/tst-realpath-chk.c
+new file mode 100644
+index 0000000000000000..a8fcb327c43fb34d
+--- /dev/null
++++ b/debug/tst-realpath-chk.c
+@@ -0,0 +1,37 @@
++/* Smoke test to verify that realpath does not cause spurious warnings.
++   Copyright The GNU Toolchain Authors.
++   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 <limits.h>
++#include <stdlib.h>
++
++#include <support/check.h>
++#include <support/support.h>
++
++static int
++do_test (void)
++{
++#ifdef PATH_MAX
++  char buf[PATH_MAX + 1];
++  char *res = realpath (".", buf);
++  TEST_VERIFY (res == buf);
++#endif
++
++  return 0;
++}
++
++#include <support/test-driver.c>
+diff --git a/stdlib/bits/stdlib.h b/stdlib/bits/stdlib.h
+index 7ea364a276497720..81ec9bdb32215e3b 100644
+--- a/stdlib/bits/stdlib.h
++++ b/stdlib/bits/stdlib.h
+@@ -42,7 +42,7 @@ __NTH (realpath (const char *__restrict __name, char *__restrict __resolved))
+     return __realpath_alias (__name, __resolved);
+ 
+ #if defined _LIBC_LIMITS_H_ && defined PATH_MAX
+-  if (__glibc_unsafe_len (sz, sizeof (char), PATH_MAX))
++  if (__glibc_unsafe_len (PATH_MAX, sizeof (char), sz))
+     return __realpath_chk_warn (__name, __resolved, sz);
+ #endif
+   return __realpath_chk (__name, __resolved, sz);
diff --git a/SOURCES/glibc-rh2033684-11.patch b/SOURCES/glibc-rh2033684-11.patch
new file mode 100644
index 0000000..41ce66c
--- /dev/null
+++ b/SOURCES/glibc-rh2033684-11.patch
@@ -0,0 +1,41 @@
+commit 86bf0feb0e3ec8e37872f72499d6ae33406561d7
+Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date:   Wed Jan 12 18:46:28 2022 +0530
+
+    Enable _FORTIFY_SOURCE=3 for gcc 12 and above
+    
+    gcc 12 now has support for the __builtin_dynamic_object_size builtin.
+    Adapt the macro checks to enable _FORTIFY_SOURCE=3 on gcc 12 and above.
+    
+    Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+    Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
+
+diff --git a/include/features.h b/include/features.h
+index fe9fe16d034fad1b..2e9ca6ec2f4a0380 100644
+--- a/include/features.h
++++ b/include/features.h
+@@ -381,7 +381,9 @@
+ #  warning _FORTIFY_SOURCE requires compiling with optimization (-O)
+ # elif !__GNUC_PREREQ (4, 1)
+ #  warning _FORTIFY_SOURCE requires GCC 4.1 or later
+-# elif _FORTIFY_SOURCE > 2 && __glibc_clang_prereq (9, 0)
++# elif _FORTIFY_SOURCE > 2 && (__glibc_clang_prereq (9, 0)		      \
++			       || __GNUC_PREREQ (12, 0))
++
+ #  if _FORTIFY_SOURCE > 3
+ #   warning _FORTIFY_SOURCE > 3 is treated like 3 on this platform
+ #  endif
+diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h
+index 147339957c4ad490..a17ae0ed87e6163f 100644
+--- a/misc/sys/cdefs.h
++++ b/misc/sys/cdefs.h
+@@ -124,7 +124,8 @@
+ #define __bos0(ptr) __builtin_object_size (ptr, 0)
+ 
+ /* Use __builtin_dynamic_object_size at _FORTIFY_SOURCE=3 when available.  */
+-#if __USE_FORTIFY_LEVEL == 3 && __glibc_clang_prereq (9, 0)
++#if __USE_FORTIFY_LEVEL == 3 && (__glibc_clang_prereq (9, 0)		      \
++				 || __GNUC_PREREQ (12, 0))
+ # define __glibc_objsize0(__o) __builtin_dynamic_object_size (__o, 0)
+ # define __glibc_objsize(__o) __builtin_dynamic_object_size (__o, 1)
+ #else
diff --git a/SOURCES/glibc-rh2033684-12.patch b/SOURCES/glibc-rh2033684-12.patch
new file mode 100644
index 0000000..9c9c98f
--- /dev/null
+++ b/SOURCES/glibc-rh2033684-12.patch
@@ -0,0 +1,295 @@
+commit db27f1251b008280a29d540b4f8ab2a38a0d80af
+Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date:   Wed Jan 12 23:34:23 2022 +0530
+
+    debug: Autogenerate _FORTIFY_SOURCE tests
+    
+    Rename debug/tst-chk1.c to debug/tst-fortify.c and add make hackery to
+    autogenerate tests with different macros enabled to build and run the
+    same test with different configurations as well as different
+    fortification levels.
+    
+    The change also ends up expanding the -lfs tests to include
+    _FORTIFY_SOURCE=3.
+    
+    Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+    Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
+
+# Conflicts:
+#	debug/Makefile
+
+diff --git a/Makerules b/Makerules
+index 5d6434c74bf9bfe5..05a549eb0f259113 100644
+--- a/Makerules
++++ b/Makerules
+@@ -444,6 +444,12 @@ $(objpfx)%$o: $(objpfx)%.c $(before-compile); $$(compile-command.c)
+ endef
+ object-suffixes-left := $(all-object-suffixes)
+ include $(o-iterator)
++
++define o-iterator-doit
++$(objpfx)%$o: $(objpfx)%.cc $(before-compile); $$(compile-command.cc)
++endef
++object-suffixes-left := $(all-object-suffixes)
++include $(o-iterator)
+ endif
+ 
+ # Generate version maps, but wait until sysdep-subdirs is known
+diff --git a/debug/Makefile b/debug/Makefile
+index b43f42ee3851f360..c92fd23dda1a7279 100644
+--- a/debug/Makefile
++++ b/debug/Makefile
+@@ -1,4 +1,5 @@
+-# Copyright (C) 1998-2018 Free Software Foundation, Inc.
++# Copyright (C) 1998-2022 Free Software Foundation, Inc.
++# Copyright The GNU Toolchain Authors.
+ # This file is part of the GNU C Library.
+ 
+ # The GNU C Library is free software; you can redistribute it and/or
+@@ -110,32 +111,60 @@ CFLAGS-tst-longjmp_chk3.c += -fexceptions -fasynchronous-unwind-tables
+ CPPFLAGS-tst-longjmp_chk3.c += -D_FORTIFY_SOURCE=1
+ CPPFLAGS-tst-realpath-chk.c += -D_FORTIFY_SOURCE=2
+ 
++# _FORTIFY_SOURCE tests.
++# Auto-generate tests for _FORTIFY_SOURCE for different levels, compilers and
++# preprocessor conditions based on tst-fortify.c.
++#
++# To add a new test condition, define a cflags-$(cond) make variable to set
++# CFLAGS for the file.
++
++tests-all-chk = tst-fortify
++tests-c-chk =
++tests-cc-chk =
++
++CFLAGS-tst-fortify.c += -Wno-format -Wno-deprecated-declarations -Wno-error
++
++# No additional flags for the default tests.
++define cflags-default
++endef
++
++define cflags-lfs
++CFLAGS-tst-fortify-$(1)-lfs-$(2).$(1) += -D_FILE_OFFSET_BITS=64
++endef
++
+ # We know these tests have problems with format strings, this is what
+ # we are testing.  Disable that warning.  They are also testing
+ # deprecated functions (notably gets) so disable that warning as well.
+ # And they also generate warnings from warning attributes, which
+ # cannot be disabled via pragmas, so require -Wno-error to be used.
+-CFLAGS-tst-chk1.c += -Wno-format -Wno-deprecated-declarations -Wno-error
+-CFLAGS-tst-chk2.c += -Wno-format -Wno-deprecated-declarations -Wno-error
+-CFLAGS-tst-chk3.c += -Wno-format -Wno-deprecated-declarations -Wno-error
+-CFLAGS-tst-chk4.cc += -Wno-format -Wno-deprecated-declarations -Wno-error
+-CFLAGS-tst-chk5.cc += -Wno-format -Wno-deprecated-declarations -Wno-error
+-CFLAGS-tst-chk6.cc += -Wno-format -Wno-deprecated-declarations -Wno-error
+-CFLAGS-tst-chk7.c += -Wno-format -Wno-deprecated-declarations -Wno-error
+-CFLAGS-tst-chk8.cc += -Wno-format -Wno-deprecated-declarations -Wno-error
+-CFLAGS-tst-lfschk1.c += -Wno-format -Wno-deprecated-declarations -Wno-error
+-CFLAGS-tst-lfschk2.c += -Wno-format -Wno-deprecated-declarations -Wno-error
+-CFLAGS-tst-lfschk3.c += -Wno-format -Wno-deprecated-declarations -Wno-error
+-CFLAGS-tst-lfschk4.cc += -Wno-format -Wno-deprecated-declarations -Wno-error
+-CFLAGS-tst-lfschk5.cc += -Wno-format -Wno-deprecated-declarations -Wno-error
+-CFLAGS-tst-lfschk6.cc += -Wno-format -Wno-deprecated-declarations -Wno-error
+-LDLIBS-tst-chk4 = -lstdc++
+-LDLIBS-tst-chk5 = -lstdc++
+-LDLIBS-tst-chk6 = -lstdc++
+-LDLIBS-tst-chk8 = -lstdc++
+-LDLIBS-tst-lfschk4 = -lstdc++
+-LDLIBS-tst-lfschk5 = -lstdc++
+-LDLIBS-tst-lfschk6 = -lstdc++
++define gen-chk-test
++tests-$(1)-chk += tst-fortify-$(1)-$(2)-$(3)
++CFLAGS-tst-fortify-$(1)-$(2)-$(3).$(1) += -D_FORTIFY_SOURCE=$(3) -Wno-format \
++					  -Wno-deprecated-declarations \
++					  -Wno-error
++$(eval $(call cflags-$(2),$(1),$(3)))
++$(objpfx)tst-fortify-$(1)-$(2)-$(3).$(1): tst-fortify.c Makefile
++	( echo "/* Autogenerated from Makefile.  */"; \
++	  echo ""; \
++	  echo "#include \"tst-fortify.c\"" ) > $$@.tmp
++	mv $$@.tmp $$@
++endef
++
++chk-extensions = c cc
++chk-types = default lfs
++chk-levels = 1 2 3
++
++$(foreach e,$(chk-extensions), \
++  $(foreach t,$(chk-types), \
++    $(foreach l,$(chk-levels), \
++      $(eval $(call gen-chk-test,$(e),$(t),$(l))))))
++
++tests-all-chk += $(tests-c-chk) $(tests-cc-chk)
++
++define link-cc
++LDLIBS-$(1) = -lstdc++
++endef
++$(foreach t,$(tests-cc-chk), $(eval $(call link-cc,$(t))))
+ 
+ # backtrace_symbols only works if we link with -rdynamic.  backtrace
+ # requires unwind tables on most architectures.
+@@ -152,19 +181,25 @@ LDFLAGS-tst-backtrace6 = -rdynamic
+ 
+ CFLAGS-tst-ssp-1.c += -fstack-protector-all
+ 
+-tests = backtrace-tst tst-longjmp_chk tst-chk1 tst-chk2 tst-chk3 \
+-	tst-lfschk1 tst-lfschk2 tst-lfschk3 test-strcpy_chk test-stpcpy_chk \
+-	tst-chk4 tst-chk5 tst-chk6 tst-chk7 tst-chk8 tst-lfschk4 tst-lfschk5 \
+-	tst-lfschk6 tst-longjmp_chk2 tst-backtrace2 tst-backtrace3 \
+-	tst-backtrace4 tst-backtrace5 tst-backtrace6 tst-realpath-chk
++tests = backtrace-tst \
++	tst-longjmp_chk \
++	test-strcpy_chk \
++	test-stpcpy_chk \
++	tst-longjmp_chk2 \
++	tst-backtrace2 \
++	tst-backtrace3 \
++	tst-backtrace4 \
++	tst-backtrace5 \
++	tst-backtrace6 \
++	tst-realpath-chk \
++	$(tests-all-chk)
+ 
+ ifeq ($(have-ssp),yes)
+ tests += tst-ssp-1
+ endif
+ 
+ ifeq (,$(CXX))
+-tests-unsupported = tst-chk4 tst-chk5 tst-chk6 tst-chk8 \
+-		    tst-lfschk4 tst-lfschk5 tst-lfschk6
++tests-unsupported = $(tests-cc-chk)
+ endif
+ 
+ extra-libs = libSegFault libpcprofile
+@@ -191,20 +226,10 @@ ifeq ($(run-built-tests),yes)
+ LOCALES := de_DE.UTF-8
+ include ../gen-locales.mk
+ 
+-$(objpfx)tst-chk1.out: $(gen-locales)
+-$(objpfx)tst-chk2.out: $(gen-locales)
+-$(objpfx)tst-chk3.out: $(gen-locales)
+-$(objpfx)tst-chk4.out: $(gen-locales)
+-$(objpfx)tst-chk5.out: $(gen-locales)
+-$(objpfx)tst-chk6.out: $(gen-locales)
+-$(objpfx)tst-chk7.out: $(gen-locales)
+-$(objpfx)tst-chk8.out: $(gen-locales)
+-$(objpfx)tst-lfschk1.out: $(gen-locales)
+-$(objpfx)tst-lfschk2.out: $(gen-locales)
+-$(objpfx)tst-lfschk3.out: $(gen-locales)
+-$(objpfx)tst-lfschk4.out: $(gen-locales)
+-$(objpfx)tst-lfschk5.out: $(gen-locales)
+-$(objpfx)tst-lfschk6.out: $(gen-locales)
++define chk-gen-locales
++$(objpfx)$(1).out: $(gen-locales)
++endef
++$(foreach t, $(tests-all-chk), $(eval $(call chk-gen-locales,$(t))))
+ endif
+ 
+ sLIBdir := $(shell echo $(slibdir) | sed 's,lib\(\|64\)$$,\\\\$$LIB,')
+diff --git a/debug/tst-chk2.c b/debug/tst-chk2.c
+deleted file mode 100644
+index be37ce2d22f0760a..0000000000000000
+--- a/debug/tst-chk2.c
++++ /dev/null
+@@ -1,2 +0,0 @@
+-#define _FORTIFY_SOURCE 1
+-#include "tst-chk1.c"
+diff --git a/debug/tst-chk3.c b/debug/tst-chk3.c
+deleted file mode 100644
+index 38b8e4fb360ba722..0000000000000000
+--- a/debug/tst-chk3.c
++++ /dev/null
+@@ -1,2 +0,0 @@
+-#define _FORTIFY_SOURCE 2
+-#include "tst-chk1.c"
+diff --git a/debug/tst-chk4.cc b/debug/tst-chk4.cc
+deleted file mode 100644
+index c82e6aac86038791..0000000000000000
+--- a/debug/tst-chk4.cc
++++ /dev/null
+@@ -1 +0,0 @@
+-#include "tst-chk1.c"
+diff --git a/debug/tst-chk5.cc b/debug/tst-chk5.cc
+deleted file mode 100644
+index be37ce2d22f0760a..0000000000000000
+--- a/debug/tst-chk5.cc
++++ /dev/null
+@@ -1,2 +0,0 @@
+-#define _FORTIFY_SOURCE 1
+-#include "tst-chk1.c"
+diff --git a/debug/tst-chk6.cc b/debug/tst-chk6.cc
+deleted file mode 100644
+index 38b8e4fb360ba722..0000000000000000
+--- a/debug/tst-chk6.cc
++++ /dev/null
+@@ -1,2 +0,0 @@
+-#define _FORTIFY_SOURCE 2
+-#include "tst-chk1.c"
+diff --git a/debug/tst-chk7.c b/debug/tst-chk7.c
+deleted file mode 100644
+index 2a7b32381268135c..0000000000000000
+--- a/debug/tst-chk7.c
++++ /dev/null
+@@ -1,2 +0,0 @@
+-#define _FORTIFY_SOURCE 3
+-#include "tst-chk1.c"
+diff --git a/debug/tst-chk8.cc b/debug/tst-chk8.cc
+deleted file mode 100644
+index 2a7b32381268135c..0000000000000000
+--- a/debug/tst-chk8.cc
++++ /dev/null
+@@ -1,2 +0,0 @@
+-#define _FORTIFY_SOURCE 3
+-#include "tst-chk1.c"
+diff --git a/debug/tst-chk1.c b/debug/tst-fortify.c
+similarity index 100%
+rename from debug/tst-chk1.c
+rename to debug/tst-fortify.c
+diff --git a/debug/tst-lfschk1.c b/debug/tst-lfschk1.c
+deleted file mode 100644
+index f3e6d47d5e4484c3..0000000000000000
+--- a/debug/tst-lfschk1.c
++++ /dev/null
+@@ -1,2 +0,0 @@
+-#define _FILE_OFFSET_BITS 64
+-#include "tst-chk1.c"
+diff --git a/debug/tst-lfschk2.c b/debug/tst-lfschk2.c
+deleted file mode 100644
+index 95d4db1d32d2eeb3..0000000000000000
+--- a/debug/tst-lfschk2.c
++++ /dev/null
+@@ -1,2 +0,0 @@
+-#define _FILE_OFFSET_BITS 64
+-#include "tst-chk2.c"
+diff --git a/debug/tst-lfschk3.c b/debug/tst-lfschk3.c
+deleted file mode 100644
+index 50a1ae1258f1553d..0000000000000000
+--- a/debug/tst-lfschk3.c
++++ /dev/null
+@@ -1,2 +0,0 @@
+-#define _FILE_OFFSET_BITS 64
+-#include "tst-chk3.c"
+diff --git a/debug/tst-lfschk4.cc b/debug/tst-lfschk4.cc
+deleted file mode 100644
+index f3e6d47d5e4484c3..0000000000000000
+--- a/debug/tst-lfschk4.cc
++++ /dev/null
+@@ -1,2 +0,0 @@
+-#define _FILE_OFFSET_BITS 64
+-#include "tst-chk1.c"
+diff --git a/debug/tst-lfschk5.cc b/debug/tst-lfschk5.cc
+deleted file mode 100644
+index 95d4db1d32d2eeb3..0000000000000000
+--- a/debug/tst-lfschk5.cc
++++ /dev/null
+@@ -1,2 +0,0 @@
+-#define _FILE_OFFSET_BITS 64
+-#include "tst-chk2.c"
+diff --git a/debug/tst-lfschk6.cc b/debug/tst-lfschk6.cc
+deleted file mode 100644
+index 50a1ae1258f1553d..0000000000000000
+--- a/debug/tst-lfschk6.cc
++++ /dev/null
+@@ -1,2 +0,0 @@
+-#define _FILE_OFFSET_BITS 64
+-#include "tst-chk3.c"
diff --git a/SOURCES/glibc-rh2033684-2.patch b/SOURCES/glibc-rh2033684-2.patch
new file mode 100644
index 0000000..4651008
--- /dev/null
+++ b/SOURCES/glibc-rh2033684-2.patch
@@ -0,0 +1,101 @@
+commit c43c5796121bc5bcc0867f02e5536874aa8196c1
+Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date:   Wed Dec 30 11:54:00 2020 +0530
+
+    Introduce _FORTIFY_SOURCE=3
+    
+    Introduce a new _FORTIFY_SOURCE level of 3 to enable additional
+    fortifications that may have a noticeable performance impact, allowing
+    more fortification coverage at the cost of some performance.
+    
+    With llvm 9.0 or later, this will replace the use of
+    __builtin_object_size with __builtin_dynamic_object_size.
+    
+    __builtin_dynamic_object_size
+    -----------------------------
+    
+    __builtin_dynamic_object_size is an LLVM builtin that is similar to
+    __builtin_object_size.  In addition to what __builtin_object_size
+    does, i.e. replace the builtin call with a constant object size,
+    __builtin_dynamic_object_size will replace the call site with an
+    expression that evaluates to the object size, thus expanding its
+    applicability.  In practice, __builtin_dynamic_object_size evaluates
+    these expressions through malloc/calloc calls that it can associate
+    with the object being evaluated.
+    
+    A simple motivating example is below; -D_FORTIFY_SOURCE=2 would miss
+    this and emit memcpy, but -D_FORTIFY_SOURCE=3 with the help of
+    __builtin_dynamic_object_size is able to emit __memcpy_chk with the
+    allocation size expression passed into the function:
+    
+    void *copy_obj (const void *src, size_t alloc, size_t copysize)
+    {
+      void *obj = malloc (alloc);
+      memcpy (obj, src, copysize);
+      return obj;
+    }
+    
+    Limitations
+    -----------
+    
+    If the object was allocated elsewhere that the compiler cannot see, or
+    if it was allocated in the function with a function that the compiler
+    does not recognize as an allocator then __builtin_dynamic_object_size
+    also returns -1.
+    
+    Further, the expression used to compute object size may be non-trivial
+    and may potentially incur a noticeable performance impact.  These
+    fortifications are hence enabled at a new _FORTIFY_SOURCE level to
+    allow developers to make a choice on the tradeoff according to their
+    environment.
+
+diff --git a/include/features.h b/include/features.h
+index ea7673ee115bcf0a..fe9fe16d034fad1b 100644
+--- a/include/features.h
++++ b/include/features.h
+@@ -381,6 +381,11 @@
+ #  warning _FORTIFY_SOURCE requires compiling with optimization (-O)
+ # elif !__GNUC_PREREQ (4, 1)
+ #  warning _FORTIFY_SOURCE requires GCC 4.1 or later
++# elif _FORTIFY_SOURCE > 2 && __glibc_clang_prereq (9, 0)
++#  if _FORTIFY_SOURCE > 3
++#   warning _FORTIFY_SOURCE > 3 is treated like 3 on this platform
++#  endif
++#  define __USE_FORTIFY_LEVEL 3
+ # elif _FORTIFY_SOURCE > 1
+ #  if _FORTIFY_SOURCE > 2
+ #   warning _FORTIFY_SOURCE > 2 is treated like 2 on this platform
+diff --git a/manual/creature.texi b/manual/creature.texi
+index 8876b2ab779c988f..64f361f27a7d6cdf 100644
+--- a/manual/creature.texi
++++ b/manual/creature.texi
+@@ -247,7 +247,8 @@ included.
+ @standards{GNU, (none)}
+ If this macro is defined to @math{1}, security hardening is added to
+ various library functions.  If defined to @math{2}, even stricter
+-checks are applied.
++checks are applied. If defined to @math{3}, @theglibc{} may also use
++checks that may have an additional performance overhead.
+ @end defvr
+ 
+ @defvr Macro _REENTRANT
+diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h
+index 3f6fe3cc8563b493..1e39307b0ebcf38f 100644
+--- a/misc/sys/cdefs.h
++++ b/misc/sys/cdefs.h
+@@ -123,6 +123,15 @@
+ #define __bos(ptr) __builtin_object_size (ptr, __USE_FORTIFY_LEVEL > 1)
+ #define __bos0(ptr) __builtin_object_size (ptr, 0)
+ 
++/* Use __builtin_dynamic_object_size at _FORTIFY_SOURCE=3 when available.  */
++#if __USE_FORTIFY_LEVEL == 3 && __glibc_clang_prereq (9, 0)
++# define __glibc_objsize0(__o) __builtin_dynamic_object_size (__o, 0)
++# define __glibc_objsize(__o) __builtin_dynamic_object_size (__o, 1)
++#else
++# define __glibc_objsize0(__o) __bos0 (__o)
++# define __glibc_objsize(__o) __bos (__o)
++#endif
++
+ #if __GNUC_PREREQ (4,3)
+ # define __warndecl(name, msg) \
+   extern void name (void) __attribute__((__warning__ (msg)))
diff --git a/SOURCES/glibc-rh2033684-3.patch b/SOURCES/glibc-rh2033684-3.patch
new file mode 100644
index 0000000..b8d0093
--- /dev/null
+++ b/SOURCES/glibc-rh2033684-3.patch
@@ -0,0 +1,43 @@
+commit 7163ace3318d666d40771f5c8e7c4a148827070f
+Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date:   Thu Nov 12 12:09:56 2020 +0530
+
+    Use __builtin___stpncpy_chk when available
+    
+    The builtin has been available in gcc since 4.7.0 and in clang since
+    2.6.  This fixes stpncpy fortification with clang since it does a
+    better job of plugging in __stpncpy_chk in the right place than the
+    header hackery.
+    
+    This has been tested by building and running all tests with gcc 10.2.1
+    and also with clang tip as of a few days ago (just the tests in debug/
+    since running all tests don't work with clang at the moment) to make
+    sure that both compilers pass the stpncpy tests.
+
+diff --git a/string/bits/string_fortified.h b/string/bits/string_fortified.h
+index a07ab0dbc8c8dd5b..4ed6755a6c1ca247 100644
+--- a/string/bits/string_fortified.h
++++ b/string/bits/string_fortified.h
+@@ -106,7 +106,13 @@ __NTH (strncpy (char *__restrict __dest, const char *__restrict __src,
+   return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest));
+ }
+ 
+-/* XXX We have no corresponding builtin yet.  */
++#if __GNUC_PREREQ (4, 7) || __glibc_clang_prereq (2, 6)
++__fortify_function char *
++__NTH (stpncpy (char *__dest, const char *__src, size_t __n))
++{
++  return __builtin___stpncpy_chk (__dest, __src, __n, __bos (__dest));
++}
++#else
+ extern char *__stpncpy_chk (char *__dest, const char *__src, size_t __n,
+ 			    size_t __destlen) __THROW;
+ extern char *__REDIRECT_NTH (__stpncpy_alias, (char *__dest, const char *__src,
+@@ -120,6 +126,7 @@ __NTH (stpncpy (char *__dest, const char *__src, size_t __n))
+     return __stpncpy_chk (__dest, __src, __n, __bos (__dest));
+   return __stpncpy_alias (__dest, __src, __n);
+ }
++#endif
+ 
+ 
+ __fortify_function char *
diff --git a/SOURCES/glibc-rh2033684-4.patch b/SOURCES/glibc-rh2033684-4.patch
new file mode 100644
index 0000000..ebd0c33
--- /dev/null
+++ b/SOURCES/glibc-rh2033684-4.patch
@@ -0,0 +1,161 @@
+commit 2a3224c53653214cbba2ec23424702193c80ea3b
+Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date:   Wed Dec 30 11:09:58 2020 +0530
+
+    string: Enable __FORTIFY_LEVEL=3
+    
+    This change enhances fortified string functions to use
+    __builtin_dynamic_object_size under _FORTIFY_SOURCE=3 whenever the
+    compiler supports it.
+
+# Conflicts:
+#	string/bits/string_fortified.h
+
+Conflict resolved to retain __GNUC_PREREQ (5,0) macro check in RHEL-8
+glibc.
+
+diff --git a/include/string.h b/include/string.h
+index 4d622f1c0305e78e..bbc97082661caf42 100644
+--- a/include/string.h
++++ b/include/string.h
+@@ -119,10 +119,11 @@ libc_hidden_proto (__ffs)
+ void __explicit_bzero_chk_internal (void *, size_t, size_t)
+   __THROW __nonnull ((1)) attribute_hidden;
+ # define explicit_bzero(buf, len) \
+-  __explicit_bzero_chk_internal (buf, len, __bos0 (buf))
++  __explicit_bzero_chk_internal (buf, len, __glibc_objsize0 (buf))
+ #elif !IS_IN (nonlib)
+ void __explicit_bzero_chk (void *, size_t, size_t) __THROW __nonnull ((1));
+-# define explicit_bzero(buf, len) __explicit_bzero_chk (buf, len, __bos0 (buf))
++# define explicit_bzero(buf, len) __explicit_bzero_chk (buf, len,	      \
++							__glibc_objsize0 (buf))
+ #endif
+ 
+ libc_hidden_builtin_proto (memchr)
+diff --git a/string/bits/string_fortified.h b/string/bits/string_fortified.h
+index 4ed6755a6c1ca247..27ec273ec41cd81c 100644
+--- a/string/bits/string_fortified.h
++++ b/string/bits/string_fortified.h
+@@ -31,13 +31,15 @@ __fortify_function void *
+ __NTH (memcpy (void *__restrict __dest, const void *__restrict __src,
+ 	       size_t __len))
+ {
+-  return __builtin___memcpy_chk (__dest, __src, __len, __bos0 (__dest));
++  return __builtin___memcpy_chk (__dest, __src, __len,
++				 __glibc_objsize0 (__dest));
+ }
+ 
+ __fortify_function void *
+ __NTH (memmove (void *__dest, const void *__src, size_t __len))
+ {
+-  return __builtin___memmove_chk (__dest, __src, __len, __bos0 (__dest));
++  return __builtin___memmove_chk (__dest, __src, __len,
++				  __glibc_objsize0 (__dest));
+ }
+ 
+ #ifdef __USE_GNU
+@@ -45,7 +47,8 @@ __fortify_function void *
+ __NTH (mempcpy (void *__restrict __dest, const void *__restrict __src,
+ 		size_t __len))
+ {
+-  return __builtin___mempcpy_chk (__dest, __src, __len, __bos0 (__dest));
++  return __builtin___mempcpy_chk (__dest, __src, __len,
++				  __glibc_objsize0 (__dest));
+ }
+ #endif
+ 
+@@ -68,7 +71,8 @@ __NTH (memset (void *__dest, int __ch, size_t __len))
+       return __dest;
+     }
+ #endif
+-  return __builtin___memset_chk (__dest, __ch, __len, __bos0 (__dest));
++  return __builtin___memset_chk (__dest, __ch, __len,
++				 __glibc_objsize0 (__dest));
+ }
+ 
+ #ifdef __USE_MISC
+@@ -80,21 +84,21 @@ void __explicit_bzero_chk (void *__dest, size_t __len, size_t __destlen)
+ __fortify_function void
+ __NTH (explicit_bzero (void *__dest, size_t __len))
+ {
+-  __explicit_bzero_chk (__dest, __len, __bos0 (__dest));
++  __explicit_bzero_chk (__dest, __len, __glibc_objsize0 (__dest));
+ }
+ #endif
+ 
+ __fortify_function char *
+ __NTH (strcpy (char *__restrict __dest, const char *__restrict __src))
+ {
+-  return __builtin___strcpy_chk (__dest, __src, __bos (__dest));
++  return __builtin___strcpy_chk (__dest, __src, __glibc_objsize (__dest));
+ }
+ 
+ #ifdef __USE_GNU
+ __fortify_function char *
+ __NTH (stpcpy (char *__restrict __dest, const char *__restrict __src))
+ {
+-  return __builtin___stpcpy_chk (__dest, __src, __bos (__dest));
++  return __builtin___stpcpy_chk (__dest, __src, __glibc_objsize (__dest));
+ }
+ #endif
+ 
+@@ -103,14 +107,16 @@ __fortify_function char *
+ __NTH (strncpy (char *__restrict __dest, const char *__restrict __src,
+ 		size_t __len))
+ {
+-  return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest));
++  return __builtin___strncpy_chk (__dest, __src, __len,
++				  __glibc_objsize (__dest));
+ }
+ 
+ #if __GNUC_PREREQ (4, 7) || __glibc_clang_prereq (2, 6)
+ __fortify_function char *
+ __NTH (stpncpy (char *__dest, const char *__src, size_t __n))
+ {
+-  return __builtin___stpncpy_chk (__dest, __src, __n, __bos (__dest));
++  return __builtin___stpncpy_chk (__dest, __src, __n,
++				  __glibc_objsize (__dest));
+ }
+ #else
+ extern char *__stpncpy_chk (char *__dest, const char *__src, size_t __n,
+@@ -132,7 +138,7 @@ __NTH (stpncpy (char *__dest, const char *__src, size_t __n))
+ __fortify_function char *
+ __NTH (strcat (char *__restrict __dest, const char *__restrict __src))
+ {
+-  return __builtin___strcat_chk (__dest, __src, __bos (__dest));
++  return __builtin___strcat_chk (__dest, __src, __glibc_objsize (__dest));
+ }
+ 
+ 
+@@ -140,7 +146,8 @@ __fortify_function char *
+ __NTH (strncat (char *__restrict __dest, const char *__restrict __src,
+ 		size_t __len))
+ {
+-  return __builtin___strncat_chk (__dest, __src, __len, __bos (__dest));
++  return __builtin___strncat_chk (__dest, __src, __len,
++				  __glibc_objsize (__dest));
+ }
+ 
+ #endif /* bits/string_fortified.h */
+diff --git a/string/bits/strings_fortified.h b/string/bits/strings_fortified.h
+index d9b2804525cfa994..871515bd2cba1f8a 100644
+--- a/string/bits/strings_fortified.h
++++ b/string/bits/strings_fortified.h
+@@ -22,13 +22,15 @@
+ __fortify_function void
+ __NTH (bcopy (const void *__src, void *__dest, size_t __len))
+ {
+-  (void) __builtin___memmove_chk (__dest, __src, __len, __bos0 (__dest));
++  (void) __builtin___memmove_chk (__dest, __src, __len,
++				  __glibc_objsize0 (__dest));
+ }
+ 
+ __fortify_function void
+ __NTH (bzero (void *__dest, size_t __len))
+ {
+-  (void) __builtin___memset_chk (__dest, '\0', __len, __bos0 (__dest));
++  (void) __builtin___memset_chk (__dest, '\0', __len,
++				 __glibc_objsize0 (__dest));
+ }
+ 
+ #endif
diff --git a/SOURCES/glibc-rh2033684-5.patch b/SOURCES/glibc-rh2033684-5.patch
new file mode 100644
index 0000000..8c1f7f3
--- /dev/null
+++ b/SOURCES/glibc-rh2033684-5.patch
@@ -0,0 +1,963 @@
+commit f9de8bfe1a731c309b91d175b4f6f4aeb786effa
+Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date:   Tue Dec 15 23:50:09 2020 +0530
+
+    nonstring: Enable __FORTIFY_LEVEL=3
+    
+    Use __builtin_dynamic_object_size in the remaining functions that
+    don't have compiler builtins as is the case for string functions.
+
+diff --git a/io/bits/poll2.h b/io/bits/poll2.h
+index 7e8406b87d6319f8..f47fd9ad0945234f 100644
+--- a/io/bits/poll2.h
++++ b/io/bits/poll2.h
+@@ -35,12 +35,13 @@ extern int __REDIRECT (__poll_chk_warn, (struct pollfd *__fds, nfds_t __nfds,
+ __fortify_function int
+ poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
+ {
+-  if (__bos (__fds) != (__SIZE_TYPE__) -1)
++  if (__glibc_objsize (__fds) != (__SIZE_TYPE__) -1)
+     {
+       if (! __builtin_constant_p (__nfds))
+-	return __poll_chk (__fds, __nfds, __timeout, __bos (__fds));
+-      else if (__bos (__fds) / sizeof (*__fds) < __nfds)
+-	return __poll_chk_warn (__fds, __nfds, __timeout, __bos (__fds));
++	return __poll_chk (__fds, __nfds, __timeout, __glibc_objsize (__fds));
++      else if (__glibc_objsize (__fds) / sizeof (*__fds) < __nfds)
++	return __poll_chk_warn (__fds, __nfds, __timeout,
++				__glibc_objsize (__fds));
+     }
+ 
+   return __poll_alias (__fds, __nfds, __timeout);
+@@ -65,13 +66,14 @@ __fortify_function int
+ ppoll (struct pollfd *__fds, nfds_t __nfds, const struct timespec *__timeout,
+        const __sigset_t *__ss)
+ {
+-  if (__bos (__fds) != (__SIZE_TYPE__) -1)
++  if (__glibc_objsize (__fds) != (__SIZE_TYPE__) -1)
+     {
+       if (! __builtin_constant_p (__nfds))
+-	return __ppoll_chk (__fds, __nfds, __timeout, __ss, __bos (__fds));
+-      else if (__bos (__fds) / sizeof (*__fds) < __nfds)
++	return __ppoll_chk (__fds, __nfds, __timeout, __ss,
++			    __glibc_objsize (__fds));
++      else if (__glibc_objsize (__fds) / sizeof (*__fds) < __nfds)
+ 	return __ppoll_chk_warn (__fds, __nfds, __timeout, __ss,
+-				 __bos (__fds));
++				 __glibc_objsize (__fds));
+     }
+ 
+   return __ppoll_alias (__fds, __nfds, __timeout, __ss);
+diff --git a/libio/bits/stdio.h b/libio/bits/stdio.h
+index 4ab919031f77a960..1372d4bf70c43d53 100644
+--- a/libio/bits/stdio.h
++++ b/libio/bits/stdio.h
+@@ -31,7 +31,7 @@
+ 
+ 
+ #ifdef __USE_EXTERN_INLINES
+-/* For -D_FORTIFY_SOURCE{,=2} bits/stdio2.h will define a different
++/* For -D_FORTIFY_SOURCE{,=2,=3} bits/stdio2.h will define a different
+    inline.  */
+ # if !(__USE_FORTIFY_LEVEL > 0 && defined __fortify_function)
+ /* Write formatted output to stdout from argument list ARG.  */
+diff --git a/libio/bits/stdio2.h b/libio/bits/stdio2.h
+index 11651506a67daea0..2cd69f44cfadfc9f 100644
+--- a/libio/bits/stdio2.h
++++ b/libio/bits/stdio2.h
+@@ -34,12 +34,13 @@ __fortify_function int
+ __NTH (sprintf (char *__restrict __s, const char *__restrict __fmt, ...))
+ {
+   return __builtin___sprintf_chk (__s, __USE_FORTIFY_LEVEL - 1,
+-				  __bos (__s), __fmt, __va_arg_pack ());
++				  __glibc_objsize (__s), __fmt,
++				  __va_arg_pack ());
+ }
+ #elif !defined __cplusplus
+ # define sprintf(str, ...) \
+-  __builtin___sprintf_chk (str, __USE_FORTIFY_LEVEL - 1, __bos (str), \
+-			   __VA_ARGS__)
++  __builtin___sprintf_chk (str, __USE_FORTIFY_LEVEL - 1,		      \
++			   __glibc_objsize (str), __VA_ARGS__)
+ #endif
+ 
+ __fortify_function int
+@@ -47,7 +48,7 @@ __NTH (vsprintf (char *__restrict __s, const char *__restrict __fmt,
+ 		 __gnuc_va_list __ap))
+ {
+   return __builtin___vsprintf_chk (__s, __USE_FORTIFY_LEVEL - 1,
+-				   __bos (__s), __fmt, __ap);
++				   __glibc_objsize (__s), __fmt, __ap);
+ }
+ 
+ #if defined __USE_ISOC99 || defined __USE_UNIX98
+@@ -65,12 +66,13 @@ __NTH (snprintf (char *__restrict __s, size_t __n,
+ 		 const char *__restrict __fmt, ...))
+ {
+   return __builtin___snprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1,
+-				   __bos (__s), __fmt, __va_arg_pack ());
++				   __glibc_objsize (__s), __fmt,
++				   __va_arg_pack ());
+ }
+ # elif !defined __cplusplus
+ #  define snprintf(str, len, ...) \
+-  __builtin___snprintf_chk (str, len, __USE_FORTIFY_LEVEL - 1, __bos (str), \
+-			    __VA_ARGS__)
++  __builtin___snprintf_chk (str, len, __USE_FORTIFY_LEVEL - 1,		      \
++			    __glibc_objsize (str), __VA_ARGS__)
+ # endif
+ 
+ __fortify_function int
+@@ -78,7 +80,7 @@ __NTH (vsnprintf (char *__restrict __s, size_t __n,
+ 		  const char *__restrict __fmt, __gnuc_va_list __ap))
+ {
+   return __builtin___vsnprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1,
+-				    __bos (__s), __fmt, __ap);
++				    __glibc_objsize (__s), __fmt, __ap);
+ }
+ 
+ #endif
+@@ -234,8 +236,8 @@ extern char *__REDIRECT (__gets_warn, (char *__str), gets)
+ __fortify_function __wur char *
+ gets (char *__str)
+ {
+-  if (__bos (__str) != (size_t) -1)
+-    return __gets_chk (__str, __bos (__str));
++  if (__glibc_objsize (__str) != (size_t) -1)
++    return __gets_chk (__str, __glibc_objsize (__str));
+   return __gets_warn (__str);
+ }
+ #endif
+@@ -254,13 +256,13 @@ extern char *__REDIRECT (__fgets_chk_warn,
+ __fortify_function __wur char *
+ fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
+ {
+-  if (__bos (__s) != (size_t) -1)
++  if (__glibc_objsize (__s) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__n) || __n <= 0)
+-	return __fgets_chk (__s, __bos (__s), __n, __stream);
++	return __fgets_chk (__s, __glibc_objsize (__s), __n, __stream);
+ 
+-      if ((size_t) __n > __bos (__s))
+-	return __fgets_chk_warn (__s, __bos (__s), __n, __stream);
++      if ((size_t) __n > __glibc_objsize (__s))
++	return __fgets_chk_warn (__s, __glibc_objsize (__s), __n, __stream);
+     }
+   return __fgets_alias (__s, __n, __stream);
+ }
+@@ -284,15 +286,17 @@ __fortify_function __wur size_t
+ fread (void *__restrict __ptr, size_t __size, size_t __n,
+        FILE *__restrict __stream)
+ {
+-  if (__bos0 (__ptr) != (size_t) -1)
++  if (__glibc_objsize0 (__ptr) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__size)
+ 	  || !__builtin_constant_p (__n)
+ 	  || (__size | __n) >= (((size_t) 1) << (8 * sizeof (size_t) / 2)))
+-	return __fread_chk (__ptr, __bos0 (__ptr), __size, __n, __stream);
++	return __fread_chk (__ptr, __glibc_objsize0 (__ptr), __size, __n,
++			    __stream);
+ 
+-      if (__size * __n > __bos0 (__ptr))
+-	return __fread_chk_warn (__ptr, __bos0 (__ptr), __size, __n, __stream);
++      if (__size * __n > __glibc_objsize0 (__ptr))
++	return __fread_chk_warn (__ptr, __glibc_objsize0 (__ptr), __size, __n,
++				 __stream);
+     }
+   return __fread_alias (__ptr, __size, __n, __stream);
+ }
+@@ -312,13 +316,15 @@ extern char *__REDIRECT (__fgets_unlocked_chk_warn,
+ __fortify_function __wur char *
+ fgets_unlocked (char *__restrict __s, int __n, FILE *__restrict __stream)
+ {
+-  if (__bos (__s) != (size_t) -1)
++  if (__glibc_objsize (__s) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__n) || __n <= 0)
+-	return __fgets_unlocked_chk (__s, __bos (__s), __n, __stream);
++	return __fgets_unlocked_chk (__s, __glibc_objsize (__s), __n,
++				     __stream);
+ 
+-      if ((size_t) __n > __bos (__s))
+-	return __fgets_unlocked_chk_warn (__s, __bos (__s), __n, __stream);
++      if ((size_t) __n > __glibc_objsize (__s))
++	return __fgets_unlocked_chk_warn (__s, __glibc_objsize (__s), __n,
++					  __stream);
+     }
+   return __fgets_unlocked_alias (__s, __n, __stream);
+ }
+@@ -345,17 +351,17 @@ __fortify_function __wur size_t
+ fread_unlocked (void *__restrict __ptr, size_t __size, size_t __n,
+ 		FILE *__restrict __stream)
+ {
+-  if (__bos0 (__ptr) != (size_t) -1)
++  if (__glibc_objsize0 (__ptr) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__size)
+ 	  || !__builtin_constant_p (__n)
+ 	  || (__size | __n) >= (((size_t) 1) << (8 * sizeof (size_t) / 2)))
+-	return __fread_unlocked_chk (__ptr, __bos0 (__ptr), __size, __n,
+-				     __stream);
++	return __fread_unlocked_chk (__ptr, __glibc_objsize0 (__ptr), __size,
++				     __n, __stream);
+ 
+-      if (__size * __n > __bos0 (__ptr))
+-	return __fread_unlocked_chk_warn (__ptr, __bos0 (__ptr), __size, __n,
+-					  __stream);
++      if (__size * __n > __glibc_objsize0 (__ptr))
++	return __fread_unlocked_chk_warn (__ptr, __glibc_objsize0 (__ptr),
++					  __size, __n, __stream);
+     }
+ 
+ # ifdef __USE_EXTERN_INLINES
+diff --git a/posix/bits/unistd.h b/posix/bits/unistd.h
+index 9a749dccf8de65cd..a0c4dcfe9c61a7b8 100644
+--- a/posix/bits/unistd.h
++++ b/posix/bits/unistd.h
+@@ -33,13 +33,14 @@ extern ssize_t __REDIRECT (__read_chk_warn,
+ __fortify_function __wur ssize_t
+ read (int __fd, void *__buf, size_t __nbytes)
+ {
+-  if (__bos0 (__buf) != (size_t) -1)
++  if (__glibc_objsize0 (__buf) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__nbytes))
+-	return __read_chk (__fd, __buf, __nbytes, __bos0 (__buf));
++	return __read_chk (__fd, __buf, __nbytes, __glibc_objsize0 (__buf));
+ 
+-      if (__nbytes > __bos0 (__buf))
+-	return __read_chk_warn (__fd, __buf, __nbytes, __bos0 (__buf));
++      if (__nbytes > __glibc_objsize0 (__buf))
++	return __read_chk_warn (__fd, __buf, __nbytes,
++				__glibc_objsize0 (__buf));
+     }
+   return __read_alias (__fd, __buf, __nbytes);
+ }
+@@ -71,14 +72,15 @@ extern ssize_t __REDIRECT (__pread64_chk_warn,
+ __fortify_function __wur ssize_t
+ pread (int __fd, void *__buf, size_t __nbytes, __off_t __offset)
+ {
+-  if (__bos0 (__buf) != (size_t) -1)
++  if (__glibc_objsize0 (__buf) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__nbytes))
+-	return __pread_chk (__fd, __buf, __nbytes, __offset, __bos0 (__buf));
++	return __pread_chk (__fd, __buf, __nbytes, __offset,
++			    __glibc_objsize0 (__buf));
+ 
+-      if ( __nbytes > __bos0 (__buf))
++      if ( __nbytes > __glibc_objsize0 (__buf))
+ 	return __pread_chk_warn (__fd, __buf, __nbytes, __offset,
+-				 __bos0 (__buf));
++				 __glibc_objsize0 (__buf));
+     }
+   return __pread_alias (__fd, __buf, __nbytes, __offset);
+ }
+@@ -86,14 +88,15 @@ pread (int __fd, void *__buf, size_t __nbytes, __off_t __offset)
+ __fortify_function __wur ssize_t
+ pread (int __fd, void *__buf, size_t __nbytes, __off64_t __offset)
+ {
+-  if (__bos0 (__buf) != (size_t) -1)
++  if (__glibc_objsize0 (__buf) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__nbytes))
+-	return __pread64_chk (__fd, __buf, __nbytes, __offset, __bos0 (__buf));
++	return __pread64_chk (__fd, __buf, __nbytes, __offset,
++			      __glibc_objsize0 (__buf));
+ 
+-      if ( __nbytes > __bos0 (__buf))
++      if ( __nbytes > __glibc_objsize0 (__buf))
+ 	return __pread64_chk_warn (__fd, __buf, __nbytes, __offset,
+-				   __bos0 (__buf));
++				   __glibc_objsize0 (__buf));
+     }
+ 
+   return __pread64_alias (__fd, __buf, __nbytes, __offset);
+@@ -104,14 +107,15 @@ pread (int __fd, void *__buf, size_t __nbytes, __off64_t __offset)
+ __fortify_function __wur ssize_t
+ pread64 (int __fd, void *__buf, size_t __nbytes, __off64_t __offset)
+ {
+-  if (__bos0 (__buf) != (size_t) -1)
++  if (__glibc_objsize0 (__buf) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__nbytes))
+-	return __pread64_chk (__fd, __buf, __nbytes, __offset, __bos0 (__buf));
++	return __pread64_chk (__fd, __buf, __nbytes, __offset,
++			      __glibc_objsize0 (__buf));
+ 
+-      if ( __nbytes > __bos0 (__buf))
++      if ( __nbytes > __glibc_objsize0 (__buf))
+ 	return __pread64_chk_warn (__fd, __buf, __nbytes, __offset,
+-				   __bos0 (__buf));
++				   __glibc_objsize0 (__buf));
+     }
+ 
+   return __pread64_alias (__fd, __buf, __nbytes, __offset);
+@@ -139,13 +143,14 @@ __fortify_function __nonnull ((1, 2)) __wur ssize_t
+ __NTH (readlink (const char *__restrict __path, char *__restrict __buf,
+ 		 size_t __len))
+ {
+-  if (__bos (__buf) != (size_t) -1)
++  if (__glibc_objsize (__buf) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__len))
+-	return __readlink_chk (__path, __buf, __len, __bos (__buf));
++	return __readlink_chk (__path, __buf, __len, __glibc_objsize (__buf));
+ 
+-      if ( __len > __bos (__buf))
+-	return __readlink_chk_warn (__path, __buf, __len, __bos (__buf));
++      if ( __len > __glibc_objsize (__buf))
++	return __readlink_chk_warn (__path, __buf, __len,
++				    __glibc_objsize (__buf));
+     }
+   return __readlink_alias (__path, __buf, __len);
+ }
+@@ -173,14 +178,15 @@ __fortify_function __nonnull ((2, 3)) __wur ssize_t
+ __NTH (readlinkat (int __fd, const char *__restrict __path,
+ 		   char *__restrict __buf, size_t __len))
+ {
+-  if (__bos (__buf) != (size_t) -1)
++  if (__glibc_objsize (__buf) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__len))
+-	return __readlinkat_chk (__fd, __path, __buf, __len, __bos (__buf));
++	return __readlinkat_chk (__fd, __path, __buf, __len,
++				 __glibc_objsize (__buf));
+ 
+-      if (__len > __bos (__buf))
++      if (__len > __glibc_objsize (__buf))
+ 	return __readlinkat_chk_warn (__fd, __path, __buf, __len,
+-				      __bos (__buf));
++				      __glibc_objsize (__buf));
+     }
+   return __readlinkat_alias (__fd, __path, __buf, __len);
+ }
+@@ -199,13 +205,13 @@ extern char *__REDIRECT_NTH (__getcwd_chk_warn,
+ __fortify_function __wur char *
+ __NTH (getcwd (char *__buf, size_t __size))
+ {
+-  if (__bos (__buf) != (size_t) -1)
++  if (__glibc_objsize (__buf) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__size))
+-	return __getcwd_chk (__buf, __size, __bos (__buf));
++	return __getcwd_chk (__buf, __size, __glibc_objsize (__buf));
+ 
+-      if (__size > __bos (__buf))
+-	return __getcwd_chk_warn (__buf, __size, __bos (__buf));
++      if (__size > __glibc_objsize (__buf))
++	return __getcwd_chk_warn (__buf, __size, __glibc_objsize (__buf));
+     }
+   return __getcwd_alias (__buf, __size);
+ }
+@@ -220,8 +226,8 @@ extern char *__REDIRECT_NTH (__getwd_warn, (char *__buf), getwd)
+ __fortify_function __nonnull ((1)) __attribute_deprecated__ __wur char *
+ __NTH (getwd (char *__buf))
+ {
+-  if (__bos (__buf) != (size_t) -1)
+-    return __getwd_chk (__buf, __bos (__buf));
++  if (__glibc_objsize (__buf) != (size_t) -1)
++    return __getwd_chk (__buf, __glibc_objsize (__buf));
+   return __getwd_warn (__buf);
+ }
+ #endif
+@@ -239,13 +245,14 @@ extern size_t __REDIRECT_NTH (__confstr_chk_warn,
+ __fortify_function size_t
+ __NTH (confstr (int __name, char *__buf, size_t __len))
+ {
+-  if (__bos (__buf) != (size_t) -1)
++  if (__glibc_objsize (__buf) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__len))
+-	return __confstr_chk (__name, __buf, __len, __bos (__buf));
++	return __confstr_chk (__name, __buf, __len, __glibc_objsize (__buf));
+ 
+-      if (__bos (__buf) < __len)
+-	return __confstr_chk_warn (__name, __buf, __len, __bos (__buf));
++      if (__glibc_objsize (__buf) < __len)
++	return __confstr_chk_warn (__name, __buf, __len,
++				   __glibc_objsize (__buf));
+     }
+   return __confstr_alias (__name, __buf, __len);
+ }
+@@ -264,13 +271,13 @@ extern int __REDIRECT_NTH (__getgroups_chk_warn,
+ __fortify_function int
+ __NTH (getgroups (int __size, __gid_t __list[]))
+ {
+-  if (__bos (__list) != (size_t) -1)
++  if (__glibc_objsize (__list) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__size) || __size < 0)
+-	return __getgroups_chk (__size, __list, __bos (__list));
++	return __getgroups_chk (__size, __list, __glibc_objsize (__list));
+ 
+-      if (__size * sizeof (__gid_t) > __bos (__list))
+-	return __getgroups_chk_warn (__size, __list, __bos (__list));
++      if (__size * sizeof (__gid_t) > __glibc_objsize (__list))
++	return __getgroups_chk_warn (__size, __list, __glibc_objsize (__list));
+     }
+   return __getgroups_alias (__size, __list);
+ }
+@@ -290,13 +297,15 @@ extern int __REDIRECT_NTH (__ttyname_r_chk_warn,
+ __fortify_function int
+ __NTH (ttyname_r (int __fd, char *__buf, size_t __buflen))
+ {
+-  if (__bos (__buf) != (size_t) -1)
++  if (__glibc_objsize (__buf) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__buflen))
+-	return __ttyname_r_chk (__fd, __buf, __buflen, __bos (__buf));
++	return __ttyname_r_chk (__fd, __buf, __buflen,
++				__glibc_objsize (__buf));
+ 
+-      if (__buflen > __bos (__buf))
+-	return __ttyname_r_chk_warn (__fd, __buf, __buflen, __bos (__buf));
++      if (__buflen > __glibc_objsize (__buf))
++	return __ttyname_r_chk_warn (__fd, __buf, __buflen,
++				     __glibc_objsize (__buf));
+     }
+   return __ttyname_r_alias (__fd, __buf, __buflen);
+ }
+@@ -316,13 +325,14 @@ extern int __REDIRECT (__getlogin_r_chk_warn,
+ __fortify_function int
+ getlogin_r (char *__buf, size_t __buflen)
+ {
+-  if (__bos (__buf) != (size_t) -1)
++  if (__glibc_objsize (__buf) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__buflen))
+-	return __getlogin_r_chk (__buf, __buflen, __bos (__buf));
++	return __getlogin_r_chk (__buf, __buflen, __glibc_objsize (__buf));
+ 
+-      if (__buflen > __bos (__buf))
+-	return __getlogin_r_chk_warn (__buf, __buflen, __bos (__buf));
++      if (__buflen > __glibc_objsize (__buf))
++	return __getlogin_r_chk_warn (__buf, __buflen,
++				      __glibc_objsize (__buf));
+     }
+   return __getlogin_r_alias (__buf, __buflen);
+ }
+@@ -343,13 +353,14 @@ extern int __REDIRECT_NTH (__gethostname_chk_warn,
+ __fortify_function int
+ __NTH (gethostname (char *__buf, size_t __buflen))
+ {
+-  if (__bos (__buf) != (size_t) -1)
++  if (__glibc_objsize (__buf) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__buflen))
+-	return __gethostname_chk (__buf, __buflen, __bos (__buf));
++	return __gethostname_chk (__buf, __buflen, __glibc_objsize (__buf));
+ 
+-      if (__buflen > __bos (__buf))
+-	return __gethostname_chk_warn (__buf, __buflen, __bos (__buf));
++      if (__buflen > __glibc_objsize (__buf))
++	return __gethostname_chk_warn (__buf, __buflen,
++				       __glibc_objsize (__buf));
+     }
+   return __gethostname_alias (__buf, __buflen);
+ }
+@@ -372,13 +383,14 @@ extern int __REDIRECT_NTH (__getdomainname_chk_warn,
+ __fortify_function int
+ __NTH (getdomainname (char *__buf, size_t __buflen))
+ {
+-  if (__bos (__buf) != (size_t) -1)
++  if (__glibc_objsize (__buf) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__buflen))
+-	return __getdomainname_chk (__buf, __buflen, __bos (__buf));
++	return __getdomainname_chk (__buf, __buflen, __glibc_objsize (__buf));
+ 
+-      if (__buflen > __bos (__buf))
+-	return __getdomainname_chk_warn (__buf, __buflen, __bos (__buf));
++      if (__buflen > __glibc_objsize (__buf))
++	return __getdomainname_chk_warn (__buf, __buflen,
++					 __glibc_objsize (__buf));
+     }
+   return __getdomainname_alias (__buf, __buflen);
+ }
+diff --git a/socket/bits/socket2.h b/socket/bits/socket2.h
+index a129e697352fd7cb..729e5a4cc1f4cb92 100644
+--- a/socket/bits/socket2.h
++++ b/socket/bits/socket2.h
+@@ -33,13 +33,15 @@ extern ssize_t __REDIRECT (__recv_chk_warn,
+ __fortify_function ssize_t
+ recv (int __fd, void *__buf, size_t __n, int __flags)
+ {
+-  if (__bos0 (__buf) != (size_t) -1)
++  if (__glibc_objsize0 (__buf) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__n))
+-	return __recv_chk (__fd, __buf, __n, __bos0 (__buf), __flags);
++	return __recv_chk (__fd, __buf, __n, __glibc_objsize0 (__buf),
++			   __flags);
+ 
+-      if (__n > __bos0 (__buf))
+-	return __recv_chk_warn (__fd, __buf, __n, __bos0 (__buf), __flags);
++      if (__n > __glibc_objsize0 (__buf))
++	return __recv_chk_warn (__fd, __buf, __n, __glibc_objsize0 (__buf),
++				__flags);
+     }
+   return __recv_alias (__fd, __buf, __n, __flags);
+ }
+@@ -64,14 +66,14 @@ __fortify_function ssize_t
+ recvfrom (int __fd, void *__restrict __buf, size_t __n, int __flags,
+ 	  __SOCKADDR_ARG __addr, socklen_t *__restrict __addr_len)
+ {
+-  if (__bos0 (__buf) != (size_t) -1)
++  if (__glibc_objsize0 (__buf) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__n))
+-	return __recvfrom_chk (__fd, __buf, __n, __bos0 (__buf), __flags,
+-			       __addr, __addr_len);
+-      if (__n > __bos0 (__buf))
+-	return __recvfrom_chk_warn (__fd, __buf, __n, __bos0 (__buf), __flags,
+-				    __addr, __addr_len);
++	return __recvfrom_chk (__fd, __buf, __n, __glibc_objsize0 (__buf),
++			       __flags, __addr, __addr_len);
++      if (__n > __glibc_objsize0 (__buf))
++	return __recvfrom_chk_warn (__fd, __buf, __n, __glibc_objsize0 (__buf),
++				    __flags, __addr, __addr_len);
+     }
+   return __recvfrom_alias (__fd, __buf, __n, __flags, __addr, __addr_len);
+ }
+diff --git a/stdlib/bits/stdlib.h b/stdlib/bits/stdlib.h
+index 53c379b99ae9d5fe..5e4114ded33f2033 100644
+--- a/stdlib/bits/stdlib.h
++++ b/stdlib/bits/stdlib.h
+@@ -36,13 +36,14 @@ extern char *__REDIRECT_NTH (__realpath_chk_warn,
+ __fortify_function __wur char *
+ __NTH (realpath (const char *__restrict __name, char *__restrict __resolved))
+ {
+-  if (__bos (__resolved) != (size_t) -1)
++  if (__glibc_objsize (__resolved) != (size_t) -1)
+     {
+ #if defined _LIBC_LIMITS_H_ && defined PATH_MAX
+-      if (__bos (__resolved) < PATH_MAX)
+-	return __realpath_chk_warn (__name, __resolved, __bos (__resolved));
++      if (__glibc_objsize (__resolved) < PATH_MAX)
++	return __realpath_chk_warn (__name, __resolved,
++				    __glibc_objsize (__resolved));
+ #endif
+-      return __realpath_chk (__name, __resolved, __bos (__resolved));
++      return __realpath_chk (__name, __resolved, __glibc_objsize (__resolved));
+     }
+ 
+   return __realpath_alias (__name, __resolved);
+@@ -63,12 +64,14 @@ extern int __REDIRECT_NTH (__ptsname_r_chk_warn,
+ __fortify_function int
+ __NTH (ptsname_r (int __fd, char *__buf, size_t __buflen))
+ {
+-  if (__bos (__buf) != (size_t) -1)
++  if (__glibc_objsize (__buf) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__buflen))
+-	return __ptsname_r_chk (__fd, __buf, __buflen, __bos (__buf));
+-      if (__buflen > __bos (__buf))
+-	return __ptsname_r_chk_warn (__fd, __buf, __buflen, __bos (__buf));
++	return __ptsname_r_chk (__fd, __buf, __buflen,
++				__glibc_objsize (__buf));
++      if (__buflen > __glibc_objsize (__buf))
++	return __ptsname_r_chk_warn (__fd, __buf, __buflen,
++				     __glibc_objsize (__buf));
+     }
+   return __ptsname_r_alias (__fd, __buf, __buflen);
+ }
+@@ -89,8 +92,9 @@ __NTH (wctomb (char *__s, wchar_t __wchar))
+ #if defined MB_LEN_MAX && MB_LEN_MAX != __STDLIB_MB_LEN_MAX
+ # error "Assumed value of MB_LEN_MAX wrong"
+ #endif
+-  if (__bos (__s) != (size_t) -1 && __STDLIB_MB_LEN_MAX > __bos (__s))
+-    return __wctomb_chk (__s, __wchar, __bos (__s));
++  if (__glibc_objsize (__s) != (size_t) -1
++      && __STDLIB_MB_LEN_MAX > __glibc_objsize (__s))
++    return __wctomb_chk (__s, __wchar, __glibc_objsize (__s));
+   return __wctomb_alias (__s, __wchar);
+ }
+ 
+@@ -113,15 +117,16 @@ __fortify_function size_t
+ __NTH (mbstowcs (wchar_t *__restrict __dst, const char *__restrict __src,
+ 		 size_t __len))
+ {
+-  if (__bos (__dst) != (size_t) -1)
++  if (__glibc_objsize (__dst) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__len))
+ 	return __mbstowcs_chk (__dst, __src, __len,
+-			       __bos (__dst) / sizeof (wchar_t));
++			       __glibc_objsize (__dst) / sizeof (wchar_t));
+ 
+-      if (__len > __bos (__dst) / sizeof (wchar_t))
++      if (__len > __glibc_objsize (__dst) / sizeof (wchar_t))
+ 	return __mbstowcs_chk_warn (__dst, __src, __len,
+-				     __bos (__dst) / sizeof (wchar_t));
++				    (__glibc_objsize (__dst)
++				     / sizeof (wchar_t)));
+     }
+   return __mbstowcs_alias (__dst, __src, __len);
+ }
+@@ -144,12 +149,13 @@ __fortify_function size_t
+ __NTH (wcstombs (char *__restrict __dst, const wchar_t *__restrict __src,
+ 		 size_t __len))
+ {
+-  if (__bos (__dst) != (size_t) -1)
++  if (__glibc_objsize (__dst) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__len))
+-	return __wcstombs_chk (__dst, __src, __len, __bos (__dst));
+-      if (__len > __bos (__dst))
+-	return __wcstombs_chk_warn (__dst, __src, __len, __bos (__dst));
++	return __wcstombs_chk (__dst, __src, __len, __glibc_objsize (__dst));
++      if (__len > __glibc_objsize (__dst))
++	return __wcstombs_chk_warn (__dst, __src, __len,
++				    __glibc_objsize (__dst));
+     }
+   return __wcstombs_alias (__dst, __src, __len);
+ }
+diff --git a/wcsmbs/bits/wchar2.h b/wcsmbs/bits/wchar2.h
+index d62b86de3e288d53..838ba877ee4b4afe 100644
+--- a/wcsmbs/bits/wchar2.h
++++ b/wcsmbs/bits/wchar2.h
+@@ -39,15 +39,15 @@ __fortify_function wchar_t *
+ __NTH (wmemcpy (wchar_t *__restrict __s1, const wchar_t *__restrict __s2,
+ 		size_t __n))
+ {
+-  if (__bos0 (__s1) != (size_t) -1)
++  if (__glibc_objsize0 (__s1) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__n))
+ 	return __wmemcpy_chk (__s1, __s2, __n,
+-			      __bos0 (__s1) / sizeof (wchar_t));
++			      __glibc_objsize0 (__s1) / sizeof (wchar_t));
+ 
+-      if (__n > __bos0 (__s1) / sizeof (wchar_t))
++      if (__n > __glibc_objsize0 (__s1) / sizeof (wchar_t))
+ 	return __wmemcpy_chk_warn (__s1, __s2, __n,
+-				   __bos0 (__s1) / sizeof (wchar_t));
++				   __glibc_objsize0 (__s1) / sizeof (wchar_t));
+     }
+   return __wmemcpy_alias (__s1, __s2, __n);
+ }
+@@ -67,15 +67,16 @@ extern wchar_t *__REDIRECT_NTH (__wmemmove_chk_warn,
+ __fortify_function wchar_t *
+ __NTH (wmemmove (wchar_t *__s1, const wchar_t *__s2, size_t __n))
+ {
+-  if (__bos0 (__s1) != (size_t) -1)
++  if (__glibc_objsize0 (__s1) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__n))
+ 	return __wmemmove_chk (__s1, __s2, __n,
+-			       __bos0 (__s1) / sizeof (wchar_t));
++			       __glibc_objsize0 (__s1) / sizeof (wchar_t));
+ 
+-      if (__n > __bos0 (__s1) / sizeof (wchar_t))
++      if (__n > __glibc_objsize0 (__s1) / sizeof (wchar_t))
+ 	return __wmemmove_chk_warn (__s1, __s2, __n,
+-				    __bos0 (__s1) / sizeof (wchar_t));
++				    (__glibc_objsize0 (__s1)
++				     / sizeof (wchar_t)));
+     }
+   return __wmemmove_alias (__s1, __s2, __n);
+ }
+@@ -100,15 +101,16 @@ __fortify_function wchar_t *
+ __NTH (wmempcpy (wchar_t *__restrict __s1, const wchar_t *__restrict __s2,
+ 		 size_t __n))
+ {
+-  if (__bos0 (__s1) != (size_t) -1)
++  if (__glibc_objsize0 (__s1) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__n))
+ 	return __wmempcpy_chk (__s1, __s2, __n,
+-			       __bos0 (__s1) / sizeof (wchar_t));
++			       __glibc_objsize0 (__s1) / sizeof (wchar_t));
+ 
+-      if (__n > __bos0 (__s1) / sizeof (wchar_t))
++      if (__n > __glibc_objsize0 (__s1) / sizeof (wchar_t))
+ 	return __wmempcpy_chk_warn (__s1, __s2, __n,
+-				    __bos0 (__s1) / sizeof (wchar_t));
++				    (__glibc_objsize0 (__s1)
++				     / sizeof (wchar_t)));
+     }
+   return __wmempcpy_alias (__s1, __s2, __n);
+ }
+@@ -128,14 +130,15 @@ extern wchar_t *__REDIRECT_NTH (__wmemset_chk_warn,
+ __fortify_function wchar_t *
+ __NTH (wmemset (wchar_t *__s, wchar_t __c, size_t __n))
+ {
+-  if (__bos0 (__s) != (size_t) -1)
++  if (__glibc_objsize0 (__s) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__n))
+-	return __wmemset_chk (__s, __c, __n, __bos0 (__s) / sizeof (wchar_t));
++	return __wmemset_chk (__s, __c, __n,
++			      __glibc_objsize0 (__s) / sizeof (wchar_t));
+ 
+-      if (__n > __bos0 (__s) / sizeof (wchar_t))
++      if (__n > __glibc_objsize0 (__s) / sizeof (wchar_t))
+ 	return __wmemset_chk_warn (__s, __c, __n,
+-				   __bos0 (__s) / sizeof (wchar_t));
++				   __glibc_objsize0 (__s) / sizeof (wchar_t));
+     }
+   return __wmemset_alias (__s, __c, __n);
+ }
+@@ -151,8 +154,9 @@ extern wchar_t *__REDIRECT_NTH (__wcscpy_alias,
+ __fortify_function wchar_t *
+ __NTH (wcscpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src))
+ {
+-  if (__bos (__dest) != (size_t) -1)
+-    return __wcscpy_chk (__dest, __src, __bos (__dest) / sizeof (wchar_t));
++  if (__glibc_objsize (__dest) != (size_t) -1)
++    return __wcscpy_chk (__dest, __src,
++			 __glibc_objsize (__dest) / sizeof (wchar_t));
+   return __wcscpy_alias (__dest, __src);
+ }
+ 
+@@ -167,8 +171,9 @@ extern wchar_t *__REDIRECT_NTH (__wcpcpy_alias,
+ __fortify_function wchar_t *
+ __NTH (wcpcpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src))
+ {
+-  if (__bos (__dest) != (size_t) -1)
+-    return __wcpcpy_chk (__dest, __src, __bos (__dest) / sizeof (wchar_t));
++  if (__glibc_objsize (__dest) != (size_t) -1)
++    return __wcpcpy_chk (__dest, __src,
++			 __glibc_objsize (__dest) / sizeof (wchar_t));
+   return __wcpcpy_alias (__dest, __src);
+ }
+ 
+@@ -191,14 +196,15 @@ __fortify_function wchar_t *
+ __NTH (wcsncpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src,
+ 		size_t __n))
+ {
+-  if (__bos (__dest) != (size_t) -1)
++  if (__glibc_objsize (__dest) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__n))
+ 	return __wcsncpy_chk (__dest, __src, __n,
+-			      __bos (__dest) / sizeof (wchar_t));
+-      if (__n > __bos (__dest) / sizeof (wchar_t))
++			      __glibc_objsize (__dest) / sizeof (wchar_t));
++      if (__n > __glibc_objsize (__dest) / sizeof (wchar_t))
+ 	return __wcsncpy_chk_warn (__dest, __src, __n,
+-				   __bos (__dest) / sizeof (wchar_t));
++				   (__glibc_objsize (__dest)
++				    / sizeof (wchar_t)));
+     }
+   return __wcsncpy_alias (__dest, __src, __n);
+ }
+@@ -222,14 +228,15 @@ __fortify_function wchar_t *
+ __NTH (wcpncpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src,
+ 		size_t __n))
+ {
+-  if (__bos (__dest) != (size_t) -1)
++  if (__glibc_objsize (__dest) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__n))
+ 	return __wcpncpy_chk (__dest, __src, __n,
+-			      __bos (__dest) / sizeof (wchar_t));
+-      if (__n > __bos (__dest) / sizeof (wchar_t))
++			      __glibc_objsize (__dest) / sizeof (wchar_t));
++      if (__n > __glibc_objsize (__dest) / sizeof (wchar_t))
+ 	return __wcpncpy_chk_warn (__dest, __src, __n,
+-				   __bos (__dest) / sizeof (wchar_t));
++				   (__glibc_objsize (__dest)
++				    / sizeof (wchar_t)));
+     }
+   return __wcpncpy_alias (__dest, __src, __n);
+ }
+@@ -245,8 +252,9 @@ extern wchar_t *__REDIRECT_NTH (__wcscat_alias,
+ __fortify_function wchar_t *
+ __NTH (wcscat (wchar_t *__restrict __dest, const wchar_t *__restrict __src))
+ {
+-  if (__bos (__dest) != (size_t) -1)
+-    return __wcscat_chk (__dest, __src, __bos (__dest) / sizeof (wchar_t));
++  if (__glibc_objsize (__dest) != (size_t) -1)
++    return __wcscat_chk (__dest, __src,
++			 __glibc_objsize (__dest) / sizeof (wchar_t));
+   return __wcscat_alias (__dest, __src);
+ }
+ 
+@@ -263,9 +271,9 @@ __fortify_function wchar_t *
+ __NTH (wcsncat (wchar_t *__restrict __dest, const wchar_t *__restrict __src,
+ 		size_t __n))
+ {
+-  if (__bos (__dest) != (size_t) -1)
++  if (__glibc_objsize (__dest) != (size_t) -1)
+     return __wcsncat_chk (__dest, __src, __n,
+-			  __bos (__dest) / sizeof (wchar_t));
++			  __glibc_objsize (__dest) / sizeof (wchar_t));
+   return __wcsncat_alias (__dest, __src, __n);
+ }
+ 
+@@ -285,18 +293,18 @@ __fortify_function int
+ __NTH (swprintf (wchar_t *__restrict __s, size_t __n,
+ 		 const wchar_t *__restrict __fmt, ...))
+ {
+-  if (__bos (__s) != (size_t) -1 || __USE_FORTIFY_LEVEL > 1)
++  if (__glibc_objsize (__s) != (size_t) -1 || __USE_FORTIFY_LEVEL > 1)
+     return __swprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1,
+-			   __bos (__s) / sizeof (wchar_t),
++			   __glibc_objsize (__s) / sizeof (wchar_t),
+ 			   __fmt, __va_arg_pack ());
+   return __swprintf_alias (__s, __n, __fmt, __va_arg_pack ());
+ }
+ #elif !defined __cplusplus
+ /* XXX We might want to have support in gcc for swprintf.  */
+ # define swprintf(s, n, ...) \
+-  (__bos (s) != (size_t) -1 || __USE_FORTIFY_LEVEL > 1			      \
++  (__glibc_objsize (s) != (size_t) -1 || __USE_FORTIFY_LEVEL > 1		      \
+    ? __swprintf_chk (s, n, __USE_FORTIFY_LEVEL - 1,			      \
+-		     __bos (s) / sizeof (wchar_t), __VA_ARGS__)		      \
++		     __glibc_objsize (s) / sizeof (wchar_t), __VA_ARGS__)	      \
+    : swprintf (s, n, __VA_ARGS__))
+ #endif
+ 
+@@ -315,9 +323,10 @@ __fortify_function int
+ __NTH (vswprintf (wchar_t *__restrict __s, size_t __n,
+ 		  const wchar_t *__restrict __fmt, __gnuc_va_list __ap))
+ {
+-  if (__bos (__s) != (size_t) -1 || __USE_FORTIFY_LEVEL > 1)
++  if (__glibc_objsize (__s) != (size_t) -1 || __USE_FORTIFY_LEVEL > 1)
+     return __vswprintf_chk (__s, __n,  __USE_FORTIFY_LEVEL - 1,
+-			    __bos (__s) / sizeof (wchar_t), __fmt, __ap);
++			    __glibc_objsize (__s) / sizeof (wchar_t), __fmt,
++			    __ap);
+   return __vswprintf_alias (__s, __n, __fmt, __ap);
+ }
+ 
+@@ -383,14 +392,15 @@ extern wchar_t *__REDIRECT (__fgetws_chk_warn,
+ __fortify_function __wur wchar_t *
+ fgetws (wchar_t *__restrict __s, int __n, __FILE *__restrict __stream)
+ {
+-  if (__bos (__s) != (size_t) -1)
++  if (__glibc_objsize (__s) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__n) || __n <= 0)
+-	return __fgetws_chk (__s, __bos (__s) / sizeof (wchar_t),
++	return __fgetws_chk (__s, __glibc_objsize (__s) / sizeof (wchar_t),
+ 			     __n, __stream);
+ 
+-      if ((size_t) __n > __bos (__s) / sizeof (wchar_t))
+-	return __fgetws_chk_warn (__s, __bos (__s) / sizeof (wchar_t),
++      if ((size_t) __n > __glibc_objsize (__s) / sizeof (wchar_t))
++	return __fgetws_chk_warn (__s,
++				  __glibc_objsize (__s) / sizeof (wchar_t),
+ 				  __n, __stream);
+     }
+   return __fgetws_alias (__s, __n, __stream);
+@@ -414,14 +424,17 @@ extern wchar_t *__REDIRECT (__fgetws_unlocked_chk_warn,
+ __fortify_function __wur wchar_t *
+ fgetws_unlocked (wchar_t *__restrict __s, int __n, __FILE *__restrict __stream)
+ {
+-  if (__bos (__s) != (size_t) -1)
++  if (__glibc_objsize (__s) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__n) || __n <= 0)
+-	return __fgetws_unlocked_chk (__s, __bos (__s) / sizeof (wchar_t),
++	return __fgetws_unlocked_chk (__s,
++				      __glibc_objsize (__s) / sizeof (wchar_t),
+ 				      __n, __stream);
+ 
+-      if ((size_t) __n > __bos (__s) / sizeof (wchar_t))
+-	return __fgetws_unlocked_chk_warn (__s, __bos (__s) / sizeof (wchar_t),
++      if ((size_t) __n > __glibc_objsize (__s) / sizeof (wchar_t))
++	return __fgetws_unlocked_chk_warn (__s,
++					   (__glibc_objsize (__s)
++					    / sizeof (wchar_t)),
+ 					   __n, __stream);
+     }
+   return __fgetws_unlocked_alias (__s, __n, __stream);
+@@ -447,8 +460,9 @@ __NTH (wcrtomb (char *__restrict __s, wchar_t __wchar,
+ #if defined MB_LEN_MAX && MB_LEN_MAX != __WCHAR_MB_LEN_MAX
+ # error "Assumed value of MB_LEN_MAX wrong"
+ #endif
+-  if (__bos (__s) != (size_t) -1 && __WCHAR_MB_LEN_MAX > __bos (__s))
+-    return __wcrtomb_chk (__s, __wchar, __ps, __bos (__s));
++  if (__glibc_objsize (__s) != (size_t) -1
++      && __WCHAR_MB_LEN_MAX > __glibc_objsize (__s))
++    return __wcrtomb_chk (__s, __wchar, __ps, __glibc_objsize (__s));
+   return __wcrtomb_alias (__s, __wchar, __ps);
+ }
+ 
+@@ -474,15 +488,16 @@ __fortify_function size_t
+ __NTH (mbsrtowcs (wchar_t *__restrict __dst, const char **__restrict __src,
+ 		  size_t __len, mbstate_t *__restrict __ps))
+ {
+-  if (__bos (__dst) != (size_t) -1)
++  if (__glibc_objsize (__dst) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__len))
+ 	return __mbsrtowcs_chk (__dst, __src, __len, __ps,
+-				__bos (__dst) / sizeof (wchar_t));
++				__glibc_objsize (__dst) / sizeof (wchar_t));
+ 
+-      if (__len > __bos (__dst) / sizeof (wchar_t))
++      if (__len > __glibc_objsize (__dst) / sizeof (wchar_t))
+ 	return __mbsrtowcs_chk_warn (__dst, __src, __len, __ps,
+-				     __bos (__dst) / sizeof (wchar_t));
++				     (__glibc_objsize (__dst)
++				      / sizeof (wchar_t)));
+     }
+   return __mbsrtowcs_alias (__dst, __src, __len, __ps);
+ }
+@@ -508,13 +523,15 @@ __fortify_function size_t
+ __NTH (wcsrtombs (char *__restrict __dst, const wchar_t **__restrict __src,
+ 		  size_t __len, mbstate_t *__restrict __ps))
+ {
+-  if (__bos (__dst) != (size_t) -1)
++  if (__glibc_objsize (__dst) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__len))
+-	return __wcsrtombs_chk (__dst, __src, __len, __ps, __bos (__dst));
++	return __wcsrtombs_chk (__dst, __src, __len, __ps,
++				__glibc_objsize (__dst));
+ 
+-      if (__len > __bos (__dst))
+-	return __wcsrtombs_chk_warn (__dst, __src, __len, __ps, __bos (__dst));
++      if (__len > __glibc_objsize (__dst))
++	return __wcsrtombs_chk_warn (__dst, __src, __len, __ps,
++				     __glibc_objsize (__dst));
+     }
+   return __wcsrtombs_alias (__dst, __src, __len, __ps);
+ }
+@@ -542,15 +559,16 @@ __fortify_function size_t
+ __NTH (mbsnrtowcs (wchar_t *__restrict __dst, const char **__restrict __src,
+ 		   size_t __nmc, size_t __len, mbstate_t *__restrict __ps))
+ {
+-  if (__bos (__dst) != (size_t) -1)
++  if (__glibc_objsize (__dst) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__len))
+ 	return __mbsnrtowcs_chk (__dst, __src, __nmc, __len, __ps,
+-				 __bos (__dst) / sizeof (wchar_t));
++				 __glibc_objsize (__dst) / sizeof (wchar_t));
+ 
+-      if (__len > __bos (__dst) / sizeof (wchar_t))
++      if (__len > __glibc_objsize (__dst) / sizeof (wchar_t))
+ 	return __mbsnrtowcs_chk_warn (__dst, __src, __nmc, __len, __ps,
+-				      __bos (__dst) / sizeof (wchar_t));
++				      (__glibc_objsize (__dst)
++				       / sizeof (wchar_t)));
+     }
+   return __mbsnrtowcs_alias (__dst, __src, __nmc, __len, __ps);
+ }
+@@ -578,15 +596,15 @@ __fortify_function size_t
+ __NTH (wcsnrtombs (char *__restrict __dst, const wchar_t **__restrict __src,
+ 		   size_t __nwc, size_t __len, mbstate_t *__restrict __ps))
+ {
+-  if (__bos (__dst) != (size_t) -1)
++  if (__glibc_objsize (__dst) != (size_t) -1)
+     {
+       if (!__builtin_constant_p (__len))
+ 	return __wcsnrtombs_chk (__dst, __src, __nwc, __len, __ps,
+-				 __bos (__dst));
++				 __glibc_objsize (__dst));
+ 
+-      if (__len > __bos (__dst))
++      if (__len > __glibc_objsize (__dst))
+ 	return __wcsnrtombs_chk_warn (__dst, __src, __nwc, __len, __ps,
+-				      __bos (__dst));
++				      __glibc_objsize (__dst));
+     }
+   return __wcsnrtombs_alias (__dst, __src, __nwc, __len, __ps);
+ }
diff --git a/SOURCES/glibc-rh2033684-6.patch b/SOURCES/glibc-rh2033684-6.patch
new file mode 100644
index 0000000..b183d70
--- /dev/null
+++ b/SOURCES/glibc-rh2033684-6.patch
@@ -0,0 +1,1037 @@
+commit a643f60c53876be0d57b4b7373770e6cb356fd13
+Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date:   Wed Oct 20 18:12:41 2021 +0530
+
+    Make sure that the fortified function conditionals are constant
+    
+    In _FORTIFY_SOURCE=3, the size expression may be non-constant,
+    resulting in branches in the inline functions remaining intact and
+    causing a tiny overhead.  Clang (and in future, gcc) make sure that
+    the -1 case is always safe, i.e. any comparison of the generated
+    expression with (size_t)-1 is always false so that bit is taken care
+    of.  The rest is avoidable since we want the _chk variant whenever we
+    have a size expression and it's not -1.
+    
+    Rework the conditionals in a uniform way to clearly indicate two
+    conditions at compile time:
+    
+    - Either the size is unknown (-1) or we know at compile time that the
+      operation length is less than the object size.  We can call the
+      original function in this case.  It could be that either the length,
+      object size or both are non-constant, but the compiler, through
+      range analysis, is able to fold the *comparison* to a constant.
+    
+    - The size and length are known and the compiler can see at compile
+      time that operation length > object size.  This is valid grounds for
+      a warning at compile time, followed by emitting the _chk variant.
+    
+    For everything else, emit the _chk variant.
+    
+    This simplifies most of the fortified function implementations and at
+    the same time, ensures that only one call from _chk or the regular
+    function is emitted.
+    
+    Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+    Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
+
+diff --git a/io/bits/poll2.h b/io/bits/poll2.h
+index f47fd9ad0945234f..6f4dae77e5e2d0d3 100644
+--- a/io/bits/poll2.h
++++ b/io/bits/poll2.h
+@@ -35,16 +35,9 @@ extern int __REDIRECT (__poll_chk_warn, (struct pollfd *__fds, nfds_t __nfds,
+ __fortify_function int
+ poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
+ {
+-  if (__glibc_objsize (__fds) != (__SIZE_TYPE__) -1)
+-    {
+-      if (! __builtin_constant_p (__nfds))
+-	return __poll_chk (__fds, __nfds, __timeout, __glibc_objsize (__fds));
+-      else if (__glibc_objsize (__fds) / sizeof (*__fds) < __nfds)
+-	return __poll_chk_warn (__fds, __nfds, __timeout,
+-				__glibc_objsize (__fds));
+-    }
+-
+-  return __poll_alias (__fds, __nfds, __timeout);
++  return __glibc_fortify (poll, __nfds, sizeof (*__fds),
++			  __glibc_objsize (__fds),
++			  __fds, __nfds, __timeout);
+ }
+ 
+ 
+@@ -66,17 +59,9 @@ __fortify_function int
+ ppoll (struct pollfd *__fds, nfds_t __nfds, const struct timespec *__timeout,
+        const __sigset_t *__ss)
+ {
+-  if (__glibc_objsize (__fds) != (__SIZE_TYPE__) -1)
+-    {
+-      if (! __builtin_constant_p (__nfds))
+-	return __ppoll_chk (__fds, __nfds, __timeout, __ss,
+-			    __glibc_objsize (__fds));
+-      else if (__glibc_objsize (__fds) / sizeof (*__fds) < __nfds)
+-	return __ppoll_chk_warn (__fds, __nfds, __timeout, __ss,
+-				 __glibc_objsize (__fds));
+-    }
+-
+-  return __ppoll_alias (__fds, __nfds, __timeout, __ss);
++  return __glibc_fortify (ppoll, __nfds, sizeof (*__fds),
++			  __glibc_objsize (__fds),
++			  __fds, __nfds, __timeout, __ss);
+ }
+ #endif
+ 
+diff --git a/libio/bits/stdio2.h b/libio/bits/stdio2.h
+index 2cd69f44cfadfc9f..4630fe0256b1a562 100644
+--- a/libio/bits/stdio2.h
++++ b/libio/bits/stdio2.h
+@@ -256,15 +256,12 @@ extern char *__REDIRECT (__fgets_chk_warn,
+ __fortify_function __wur char *
+ fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
+ {
+-  if (__glibc_objsize (__s) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__n) || __n <= 0)
+-	return __fgets_chk (__s, __glibc_objsize (__s), __n, __stream);
+-
+-      if ((size_t) __n > __glibc_objsize (__s))
+-	return __fgets_chk_warn (__s, __glibc_objsize (__s), __n, __stream);
+-    }
+-  return __fgets_alias (__s, __n, __stream);
++  size_t sz = __glibc_objsize (__s);
++  if (__glibc_safe_or_unknown_len (__n, sizeof (char), sz))
++    return __fgets_alias (__s, __n, __stream);
++  if (__glibc_unsafe_len (__n, sizeof (char), sz))
++    return __fgets_chk_warn (__s, sz, __n, __stream);
++  return __fgets_chk (__s, sz, __n, __stream);
+ }
+ 
+ extern size_t __fread_chk (void *__restrict __ptr, size_t __ptrlen,
+@@ -286,19 +283,12 @@ __fortify_function __wur size_t
+ fread (void *__restrict __ptr, size_t __size, size_t __n,
+        FILE *__restrict __stream)
+ {
+-  if (__glibc_objsize0 (__ptr) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__size)
+-	  || !__builtin_constant_p (__n)
+-	  || (__size | __n) >= (((size_t) 1) << (8 * sizeof (size_t) / 2)))
+-	return __fread_chk (__ptr, __glibc_objsize0 (__ptr), __size, __n,
+-			    __stream);
+-
+-      if (__size * __n > __glibc_objsize0 (__ptr))
+-	return __fread_chk_warn (__ptr, __glibc_objsize0 (__ptr), __size, __n,
+-				 __stream);
+-    }
+-  return __fread_alias (__ptr, __size, __n, __stream);
++  size_t sz = __glibc_objsize0 (__ptr);
++  if (__glibc_safe_or_unknown_len (__n, __size, sz))
++    return __fread_alias (__ptr, __size, __n, __stream);
++  if (__glibc_unsafe_len (__n, __size, sz))
++    return __fread_chk_warn (__ptr, sz, __size, __n, __stream);
++  return __fread_chk (__ptr, sz, __size, __n, __stream);
+ }
+ 
+ #ifdef __USE_GNU
+@@ -316,17 +306,12 @@ extern char *__REDIRECT (__fgets_unlocked_chk_warn,
+ __fortify_function __wur char *
+ fgets_unlocked (char *__restrict __s, int __n, FILE *__restrict __stream)
+ {
+-  if (__glibc_objsize (__s) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__n) || __n <= 0)
+-	return __fgets_unlocked_chk (__s, __glibc_objsize (__s), __n,
+-				     __stream);
+-
+-      if ((size_t) __n > __glibc_objsize (__s))
+-	return __fgets_unlocked_chk_warn (__s, __glibc_objsize (__s), __n,
+-					  __stream);
+-    }
+-  return __fgets_unlocked_alias (__s, __n, __stream);
++  size_t sz = __glibc_objsize (__s);
++  if (__glibc_safe_or_unknown_len (__n, sizeof (char), sz))
++    return __fgets_unlocked_alias (__s, __n, __stream);
++  if (__glibc_unsafe_len (__n, sizeof (char), sz))
++    return __fgets_unlocked_chk_warn (__s, sz, __n, __stream);
++  return __fgets_unlocked_chk (__s, sz, __n, __stream);
+ }
+ #endif
+ 
+@@ -351,41 +336,36 @@ __fortify_function __wur size_t
+ fread_unlocked (void *__restrict __ptr, size_t __size, size_t __n,
+ 		FILE *__restrict __stream)
+ {
+-  if (__glibc_objsize0 (__ptr) != (size_t) -1)
++  size_t sz = __glibc_objsize0 (__ptr);
++  if (__glibc_safe_or_unknown_len (__n, __size, sz))
+     {
+-      if (!__builtin_constant_p (__size)
+-	  || !__builtin_constant_p (__n)
+-	  || (__size | __n) >= (((size_t) 1) << (8 * sizeof (size_t) / 2)))
+-	return __fread_unlocked_chk (__ptr, __glibc_objsize0 (__ptr), __size,
+-				     __n, __stream);
+-
+-      if (__size * __n > __glibc_objsize0 (__ptr))
+-	return __fread_unlocked_chk_warn (__ptr, __glibc_objsize0 (__ptr),
+-					  __size, __n, __stream);
+-    }
+-
+ # ifdef __USE_EXTERN_INLINES
+-  if (__builtin_constant_p (__size)
+-      && __builtin_constant_p (__n)
+-      && (__size | __n) < (((size_t) 1) << (8 * sizeof (size_t) / 2))
+-      && __size * __n <= 8)
+-    {
+-      size_t __cnt = __size * __n;
+-      char *__cptr = (char *) __ptr;
+-      if (__cnt == 0)
+-	return 0;
+-
+-      for (; __cnt > 0; --__cnt)
++      if (__builtin_constant_p (__size)
++	  && __builtin_constant_p (__n)
++	  && (__size | __n) < (((size_t) 1) << (8 * sizeof (size_t) / 2))
++	  && __size * __n <= 8)
+ 	{
+-	  int __c = getc_unlocked (__stream);
+-	  if (__c == EOF)
+-	    break;
+-	  *__cptr++ = __c;
++	  size_t __cnt = __size * __n;
++	  char *__cptr = (char *) __ptr;
++	  if (__cnt == 0)
++	    return 0;
++
++	  for (; __cnt > 0; --__cnt)
++	    {
++	      int __c = getc_unlocked (__stream);
++	      if (__c == EOF)
++		break;
++	      *__cptr++ = __c;
++	    }
++	  return (__cptr - (char *) __ptr) / __size;
+ 	}
+-      return (__cptr - (char *) __ptr) / __size;
+-    }
+ # endif
+-  return __fread_unlocked_alias (__ptr, __size, __n, __stream);
++      return __fread_unlocked_alias (__ptr, __size, __n, __stream);
++    }
++  if (__glibc_unsafe_len (__n, __size, sz))
++    return __fread_unlocked_chk_warn (__ptr, sz, __size, __n, __stream);
++  return __fread_unlocked_chk (__ptr, sz, __size, __n, __stream);
++
+ }
+ #endif
+ 
+diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h
+index 1e39307b0ebcf38f..17b84a2e6c69d961 100644
+--- a/misc/sys/cdefs.h
++++ b/misc/sys/cdefs.h
+@@ -132,6 +132,53 @@
+ # define __glibc_objsize(__o) __bos (__o)
+ #endif
+ 
++/* Compile time conditions to choose between the regular, _chk and _chk_warn
++   variants.  These conditions should get evaluated to constant and optimized
++   away.  */
++
++#define __glibc_safe_len_cond(__l, __s, __osz) ((__l) <= (__osz) / (__s))
++#define __glibc_unsigned_or_positive(__l) \
++  ((__typeof (__l)) 0 < (__typeof (__l)) -1				      \
++   || (__builtin_constant_p (__l) && (__l) > 0))
++
++/* Length is known to be safe at compile time if the __L * __S <= __OBJSZ
++   condition can be folded to a constant and if it is true.  The -1 check is
++   redundant because since it implies that __glibc_safe_len_cond is true.  */
++#define __glibc_safe_or_unknown_len(__l, __s, __osz) \
++  (__glibc_unsigned_or_positive (__l)					      \
++   && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l),     \
++						   __s, __osz))		      \
++   && __glibc_safe_len_cond ((__SIZE_TYPE__) (__l), __s, __osz))
++
++/* Conversely, we know at compile time that the length is safe if the
++   __L * __S <= __OBJSZ condition can be folded to a constant and if it is
++   false.  */
++#define __glibc_unsafe_len(__l, __s, __osz) \
++  (__glibc_unsigned_or_positive (__l)					      \
++   && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l),     \
++						   __s, __osz))		      \
++   && !__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), __s, __osz))
++
++/* Fortify function f.  __f_alias, __f_chk and __f_chk_warn must be
++   declared.  */
++
++#define __glibc_fortify(f, __l, __s, __osz, ...) \
++  (__glibc_safe_or_unknown_len (__l, __s, __osz)			      \
++   ? __ ## f ## _alias (__VA_ARGS__)					      \
++   : (__glibc_unsafe_len (__l, __s, __osz)				      \
++      ? __ ## f ## _chk_warn (__VA_ARGS__, __osz)			      \
++      : __ ## f ## _chk (__VA_ARGS__, __osz)))			      \
++
++/* Fortify function f, where object size argument passed to f is the number of
++   elements and not total size.  */
++
++#define __glibc_fortify_n(f, __l, __s, __osz, ...) \
++  (__glibc_safe_or_unknown_len (__l, __s, __osz)			      \
++   ? __ ## f ## _alias (__VA_ARGS__)					      \
++   : (__glibc_unsafe_len (__l, __s, __osz)				      \
++      ? __ ## f ## _chk_warn (__VA_ARGS__, (__osz) / (__s))		      \
++      : __ ## f ## _chk (__VA_ARGS__, (__osz) / (__s))))		      \
++
+ #if __GNUC_PREREQ (4,3)
+ # define __warndecl(name, msg) \
+   extern void name (void) __attribute__((__warning__ (msg)))
+diff --git a/posix/bits/unistd.h b/posix/bits/unistd.h
+index a0c4dcfe9c61a7b8..a456d1723547db70 100644
+--- a/posix/bits/unistd.h
++++ b/posix/bits/unistd.h
+@@ -33,16 +33,9 @@ extern ssize_t __REDIRECT (__read_chk_warn,
+ __fortify_function __wur ssize_t
+ read (int __fd, void *__buf, size_t __nbytes)
+ {
+-  if (__glibc_objsize0 (__buf) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__nbytes))
+-	return __read_chk (__fd, __buf, __nbytes, __glibc_objsize0 (__buf));
+-
+-      if (__nbytes > __glibc_objsize0 (__buf))
+-	return __read_chk_warn (__fd, __buf, __nbytes,
+-				__glibc_objsize0 (__buf));
+-    }
+-  return __read_alias (__fd, __buf, __nbytes);
++  return __glibc_fortify (read, __nbytes, sizeof (char),
++			  __glibc_objsize0 (__buf),
++			  __fd, __buf, __nbytes);
+ }
+ 
+ #ifdef __USE_UNIX98
+@@ -72,34 +65,17 @@ extern ssize_t __REDIRECT (__pread64_chk_warn,
+ __fortify_function __wur ssize_t
+ pread (int __fd, void *__buf, size_t __nbytes, __off_t __offset)
+ {
+-  if (__glibc_objsize0 (__buf) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__nbytes))
+-	return __pread_chk (__fd, __buf, __nbytes, __offset,
+-			    __glibc_objsize0 (__buf));
+-
+-      if ( __nbytes > __glibc_objsize0 (__buf))
+-	return __pread_chk_warn (__fd, __buf, __nbytes, __offset,
+-				 __glibc_objsize0 (__buf));
+-    }
+-  return __pread_alias (__fd, __buf, __nbytes, __offset);
++  return __glibc_fortify (pread, __nbytes, sizeof (char),
++			  __glibc_objsize0 (__buf),
++			  __fd, __buf, __nbytes, __offset);
+ }
+ # else
+ __fortify_function __wur ssize_t
+ pread (int __fd, void *__buf, size_t __nbytes, __off64_t __offset)
+ {
+-  if (__glibc_objsize0 (__buf) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__nbytes))
+-	return __pread64_chk (__fd, __buf, __nbytes, __offset,
+-			      __glibc_objsize0 (__buf));
+-
+-      if ( __nbytes > __glibc_objsize0 (__buf))
+-	return __pread64_chk_warn (__fd, __buf, __nbytes, __offset,
+-				   __glibc_objsize0 (__buf));
+-    }
+-
+-  return __pread64_alias (__fd, __buf, __nbytes, __offset);
++  return __glibc_fortify (pread64, __nbytes, sizeof (char),
++			  __glibc_objsize0 (__buf),
++			  __fd, __buf, __nbytes, __offset);
+ }
+ # endif
+ 
+@@ -107,18 +83,9 @@ pread (int __fd, void *__buf, size_t __nbytes, __off64_t __offset)
+ __fortify_function __wur ssize_t
+ pread64 (int __fd, void *__buf, size_t __nbytes, __off64_t __offset)
+ {
+-  if (__glibc_objsize0 (__buf) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__nbytes))
+-	return __pread64_chk (__fd, __buf, __nbytes, __offset,
+-			      __glibc_objsize0 (__buf));
+-
+-      if ( __nbytes > __glibc_objsize0 (__buf))
+-	return __pread64_chk_warn (__fd, __buf, __nbytes, __offset,
+-				   __glibc_objsize0 (__buf));
+-    }
+-
+-  return __pread64_alias (__fd, __buf, __nbytes, __offset);
++  return __glibc_fortify (pread64, __nbytes, sizeof (char),
++			  __glibc_objsize0 (__buf),
++			  __fd, __buf, __nbytes, __offset);
+ }
+ # endif
+ #endif
+@@ -143,16 +110,9 @@ __fortify_function __nonnull ((1, 2)) __wur ssize_t
+ __NTH (readlink (const char *__restrict __path, char *__restrict __buf,
+ 		 size_t __len))
+ {
+-  if (__glibc_objsize (__buf) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__len))
+-	return __readlink_chk (__path, __buf, __len, __glibc_objsize (__buf));
+-
+-      if ( __len > __glibc_objsize (__buf))
+-	return __readlink_chk_warn (__path, __buf, __len,
+-				    __glibc_objsize (__buf));
+-    }
+-  return __readlink_alias (__path, __buf, __len);
++  return __glibc_fortify (readlink, __len, sizeof (char),
++			  __glibc_objsize (__buf),
++			  __path, __buf, __len);
+ }
+ #endif
+ 
+@@ -178,17 +138,9 @@ __fortify_function __nonnull ((2, 3)) __wur ssize_t
+ __NTH (readlinkat (int __fd, const char *__restrict __path,
+ 		   char *__restrict __buf, size_t __len))
+ {
+-  if (__glibc_objsize (__buf) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__len))
+-	return __readlinkat_chk (__fd, __path, __buf, __len,
+-				 __glibc_objsize (__buf));
+-
+-      if (__len > __glibc_objsize (__buf))
+-	return __readlinkat_chk_warn (__fd, __path, __buf, __len,
+-				      __glibc_objsize (__buf));
+-    }
+-  return __readlinkat_alias (__fd, __path, __buf, __len);
++  return __glibc_fortify (readlinkat, __len, sizeof (char),
++			  __glibc_objsize (__buf),
++			  __fd, __path, __buf, __len);
+ }
+ #endif
+ 
+@@ -205,15 +157,9 @@ extern char *__REDIRECT_NTH (__getcwd_chk_warn,
+ __fortify_function __wur char *
+ __NTH (getcwd (char *__buf, size_t __size))
+ {
+-  if (__glibc_objsize (__buf) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__size))
+-	return __getcwd_chk (__buf, __size, __glibc_objsize (__buf));
+-
+-      if (__size > __glibc_objsize (__buf))
+-	return __getcwd_chk_warn (__buf, __size, __glibc_objsize (__buf));
+-    }
+-  return __getcwd_alias (__buf, __size);
++  return __glibc_fortify (getcwd, __size, sizeof (char),
++			  __glibc_objsize (__buf),
++			  __buf, __size);
+ }
+ 
+ #if defined __USE_MISC || defined __USE_XOPEN_EXTENDED
+@@ -245,16 +191,9 @@ extern size_t __REDIRECT_NTH (__confstr_chk_warn,
+ __fortify_function size_t
+ __NTH (confstr (int __name, char *__buf, size_t __len))
+ {
+-  if (__glibc_objsize (__buf) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__len))
+-	return __confstr_chk (__name, __buf, __len, __glibc_objsize (__buf));
+-
+-      if (__glibc_objsize (__buf) < __len)
+-	return __confstr_chk_warn (__name, __buf, __len,
+-				   __glibc_objsize (__buf));
+-    }
+-  return __confstr_alias (__name, __buf, __len);
++  return __glibc_fortify (confstr, __len, sizeof (char),
++			  __glibc_objsize (__buf),
++			  __name, __buf, __len);
+ }
+ 
+ 
+@@ -271,15 +210,9 @@ extern int __REDIRECT_NTH (__getgroups_chk_warn,
+ __fortify_function int
+ __NTH (getgroups (int __size, __gid_t __list[]))
+ {
+-  if (__glibc_objsize (__list) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__size) || __size < 0)
+-	return __getgroups_chk (__size, __list, __glibc_objsize (__list));
+-
+-      if (__size * sizeof (__gid_t) > __glibc_objsize (__list))
+-	return __getgroups_chk_warn (__size, __list, __glibc_objsize (__list));
+-    }
+-  return __getgroups_alias (__size, __list);
++  return __glibc_fortify (getgroups, __size, sizeof (__gid_t),
++			  __glibc_objsize (__list),
++			  __size, __list);
+ }
+ 
+ 
+@@ -297,17 +230,9 @@ extern int __REDIRECT_NTH (__ttyname_r_chk_warn,
+ __fortify_function int
+ __NTH (ttyname_r (int __fd, char *__buf, size_t __buflen))
+ {
+-  if (__glibc_objsize (__buf) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__buflen))
+-	return __ttyname_r_chk (__fd, __buf, __buflen,
+-				__glibc_objsize (__buf));
+-
+-      if (__buflen > __glibc_objsize (__buf))
+-	return __ttyname_r_chk_warn (__fd, __buf, __buflen,
+-				     __glibc_objsize (__buf));
+-    }
+-  return __ttyname_r_alias (__fd, __buf, __buflen);
++  return __glibc_fortify (ttyname_r, __buflen, sizeof (char),
++			  __glibc_objsize (__buf),
++			  __fd, __buf, __buflen);
+ }
+ 
+ 
+@@ -325,16 +250,9 @@ extern int __REDIRECT (__getlogin_r_chk_warn,
+ __fortify_function int
+ getlogin_r (char *__buf, size_t __buflen)
+ {
+-  if (__glibc_objsize (__buf) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__buflen))
+-	return __getlogin_r_chk (__buf, __buflen, __glibc_objsize (__buf));
+-
+-      if (__buflen > __glibc_objsize (__buf))
+-	return __getlogin_r_chk_warn (__buf, __buflen,
+-				      __glibc_objsize (__buf));
+-    }
+-  return __getlogin_r_alias (__buf, __buflen);
++  return __glibc_fortify (getlogin_r, __buflen, sizeof (char),
++			  __glibc_objsize (__buf),
++			  __buf, __buflen);
+ }
+ #endif
+ 
+@@ -353,16 +271,9 @@ extern int __REDIRECT_NTH (__gethostname_chk_warn,
+ __fortify_function int
+ __NTH (gethostname (char *__buf, size_t __buflen))
+ {
+-  if (__glibc_objsize (__buf) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__buflen))
+-	return __gethostname_chk (__buf, __buflen, __glibc_objsize (__buf));
+-
+-      if (__buflen > __glibc_objsize (__buf))
+-	return __gethostname_chk_warn (__buf, __buflen,
+-				       __glibc_objsize (__buf));
+-    }
+-  return __gethostname_alias (__buf, __buflen);
++  return __glibc_fortify (gethostname, __buflen, sizeof (char),
++			  __glibc_objsize (__buf),
++			  __buf, __buflen);
+ }
+ #endif
+ 
+@@ -383,15 +294,8 @@ extern int __REDIRECT_NTH (__getdomainname_chk_warn,
+ __fortify_function int
+ __NTH (getdomainname (char *__buf, size_t __buflen))
+ {
+-  if (__glibc_objsize (__buf) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__buflen))
+-	return __getdomainname_chk (__buf, __buflen, __glibc_objsize (__buf));
+-
+-      if (__buflen > __glibc_objsize (__buf))
+-	return __getdomainname_chk_warn (__buf, __buflen,
+-					 __glibc_objsize (__buf));
+-    }
+-  return __getdomainname_alias (__buf, __buflen);
++  return __glibc_fortify (getdomainname, __buflen, sizeof (char),
++			  __glibc_objsize (__buf),
++			  __buf, __buflen);
+ }
+ #endif
+diff --git a/socket/bits/socket2.h b/socket/bits/socket2.h
+index 729e5a4cc1f4cb92..68fe5435b3b29c2a 100644
+--- a/socket/bits/socket2.h
++++ b/socket/bits/socket2.h
+@@ -33,17 +33,12 @@ extern ssize_t __REDIRECT (__recv_chk_warn,
+ __fortify_function ssize_t
+ recv (int __fd, void *__buf, size_t __n, int __flags)
+ {
+-  if (__glibc_objsize0 (__buf) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__n))
+-	return __recv_chk (__fd, __buf, __n, __glibc_objsize0 (__buf),
+-			   __flags);
+-
+-      if (__n > __glibc_objsize0 (__buf))
+-	return __recv_chk_warn (__fd, __buf, __n, __glibc_objsize0 (__buf),
+-				__flags);
+-    }
+-  return __recv_alias (__fd, __buf, __n, __flags);
++  size_t sz = __glibc_objsize0 (__buf);
++  if (__glibc_safe_or_unknown_len (__n, sizeof (char), sz))
++    return __recv_alias (__fd, __buf, __n, __flags);
++  if (__glibc_unsafe_len (__n, sizeof (char), sz))
++    return __recv_chk_warn (__fd, __buf, __n, sz, __flags);
++  return __recv_chk (__fd, __buf, __n, sz, __flags);
+ }
+ 
+ extern ssize_t __recvfrom_chk (int __fd, void *__restrict __buf, size_t __n,
+@@ -66,14 +61,11 @@ __fortify_function ssize_t
+ recvfrom (int __fd, void *__restrict __buf, size_t __n, int __flags,
+ 	  __SOCKADDR_ARG __addr, socklen_t *__restrict __addr_len)
+ {
+-  if (__glibc_objsize0 (__buf) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__n))
+-	return __recvfrom_chk (__fd, __buf, __n, __glibc_objsize0 (__buf),
+-			       __flags, __addr, __addr_len);
+-      if (__n > __glibc_objsize0 (__buf))
+-	return __recvfrom_chk_warn (__fd, __buf, __n, __glibc_objsize0 (__buf),
+-				    __flags, __addr, __addr_len);
+-    }
+-  return __recvfrom_alias (__fd, __buf, __n, __flags, __addr, __addr_len);
++  size_t sz = __glibc_objsize0 (__buf);
++  if (__glibc_safe_or_unknown_len (__n, sizeof (char), sz))
++    return __recvfrom_alias (__fd, __buf, __n, __flags, __addr, __addr_len);
++  if (__glibc_unsafe_len (__n, sizeof (char), sz))
++    return __recvfrom_chk_warn (__fd, __buf, __n, sz, __flags, __addr,
++				__addr_len);
++  return __recvfrom_chk (__fd, __buf, __n, sz, __flags, __addr, __addr_len);
+ }
+diff --git a/stdlib/bits/stdlib.h b/stdlib/bits/stdlib.h
+index 5e4114ded33f2033..7ea364a276497720 100644
+--- a/stdlib/bits/stdlib.h
++++ b/stdlib/bits/stdlib.h
+@@ -36,17 +36,16 @@ extern char *__REDIRECT_NTH (__realpath_chk_warn,
+ __fortify_function __wur char *
+ __NTH (realpath (const char *__restrict __name, char *__restrict __resolved))
+ {
+-  if (__glibc_objsize (__resolved) != (size_t) -1)
+-    {
++  size_t sz = __glibc_objsize (__resolved);
++
++  if (sz == (size_t) -1)
++    return __realpath_alias (__name, __resolved);
++
+ #if defined _LIBC_LIMITS_H_ && defined PATH_MAX
+-      if (__glibc_objsize (__resolved) < PATH_MAX)
+-	return __realpath_chk_warn (__name, __resolved,
+-				    __glibc_objsize (__resolved));
++  if (__glibc_unsafe_len (sz, sizeof (char), PATH_MAX))
++    return __realpath_chk_warn (__name, __resolved, sz);
+ #endif
+-      return __realpath_chk (__name, __resolved, __glibc_objsize (__resolved));
+-    }
+-
+-  return __realpath_alias (__name, __resolved);
++  return __realpath_chk (__name, __resolved, sz);
+ }
+ 
+ 
+@@ -64,16 +63,9 @@ extern int __REDIRECT_NTH (__ptsname_r_chk_warn,
+ __fortify_function int
+ __NTH (ptsname_r (int __fd, char *__buf, size_t __buflen))
+ {
+-  if (__glibc_objsize (__buf) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__buflen))
+-	return __ptsname_r_chk (__fd, __buf, __buflen,
+-				__glibc_objsize (__buf));
+-      if (__buflen > __glibc_objsize (__buf))
+-	return __ptsname_r_chk_warn (__fd, __buf, __buflen,
+-				     __glibc_objsize (__buf));
+-    }
+-  return __ptsname_r_alias (__fd, __buf, __buflen);
++  return __glibc_fortify (ptsname_r, __buflen, sizeof (char),
++			  __glibc_objsize (__buf),
++			  __fd, __buf, __buflen);
+ }
+ 
+ 
+@@ -117,18 +109,9 @@ __fortify_function size_t
+ __NTH (mbstowcs (wchar_t *__restrict __dst, const char *__restrict __src,
+ 		 size_t __len))
+ {
+-  if (__glibc_objsize (__dst) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__len))
+-	return __mbstowcs_chk (__dst, __src, __len,
+-			       __glibc_objsize (__dst) / sizeof (wchar_t));
+-
+-      if (__len > __glibc_objsize (__dst) / sizeof (wchar_t))
+-	return __mbstowcs_chk_warn (__dst, __src, __len,
+-				    (__glibc_objsize (__dst)
+-				     / sizeof (wchar_t)));
+-    }
+-  return __mbstowcs_alias (__dst, __src, __len);
++  return __glibc_fortify_n (mbstowcs, __len, sizeof (wchar_t),
++			    __glibc_objsize (__dst),
++			    __dst, __src, __len);
+ }
+ 
+ 
+@@ -149,13 +132,7 @@ __fortify_function size_t
+ __NTH (wcstombs (char *__restrict __dst, const wchar_t *__restrict __src,
+ 		 size_t __len))
+ {
+-  if (__glibc_objsize (__dst) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__len))
+-	return __wcstombs_chk (__dst, __src, __len, __glibc_objsize (__dst));
+-      if (__len > __glibc_objsize (__dst))
+-	return __wcstombs_chk_warn (__dst, __src, __len,
+-				    __glibc_objsize (__dst));
+-    }
+-  return __wcstombs_alias (__dst, __src, __len);
++  return __glibc_fortify (wcstombs, __len, sizeof (char),
++			  __glibc_objsize (__dst),
++			  __dst, __src, __len);
+ }
+diff --git a/wcsmbs/bits/wchar2.h b/wcsmbs/bits/wchar2.h
+index 838ba877ee4b4afe..f82bba481981e4fb 100644
+--- a/wcsmbs/bits/wchar2.h
++++ b/wcsmbs/bits/wchar2.h
+@@ -39,17 +39,9 @@ __fortify_function wchar_t *
+ __NTH (wmemcpy (wchar_t *__restrict __s1, const wchar_t *__restrict __s2,
+ 		size_t __n))
+ {
+-  if (__glibc_objsize0 (__s1) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__n))
+-	return __wmemcpy_chk (__s1, __s2, __n,
+-			      __glibc_objsize0 (__s1) / sizeof (wchar_t));
+-
+-      if (__n > __glibc_objsize0 (__s1) / sizeof (wchar_t))
+-	return __wmemcpy_chk_warn (__s1, __s2, __n,
+-				   __glibc_objsize0 (__s1) / sizeof (wchar_t));
+-    }
+-  return __wmemcpy_alias (__s1, __s2, __n);
++  return __glibc_fortify_n (wmemcpy, __n, sizeof (wchar_t),
++			    __glibc_objsize0 (__s1),
++			    __s1, __s2, __n);
+ }
+ 
+ 
+@@ -67,18 +59,9 @@ extern wchar_t *__REDIRECT_NTH (__wmemmove_chk_warn,
+ __fortify_function wchar_t *
+ __NTH (wmemmove (wchar_t *__s1, const wchar_t *__s2, size_t __n))
+ {
+-  if (__glibc_objsize0 (__s1) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__n))
+-	return __wmemmove_chk (__s1, __s2, __n,
+-			       __glibc_objsize0 (__s1) / sizeof (wchar_t));
+-
+-      if (__n > __glibc_objsize0 (__s1) / sizeof (wchar_t))
+-	return __wmemmove_chk_warn (__s1, __s2, __n,
+-				    (__glibc_objsize0 (__s1)
+-				     / sizeof (wchar_t)));
+-    }
+-  return __wmemmove_alias (__s1, __s2, __n);
++  return __glibc_fortify_n (wmemmove, __n, sizeof (wchar_t),
++			    __glibc_objsize0 (__s1),
++			    __s1, __s2, __n);
+ }
+ 
+ 
+@@ -101,18 +84,9 @@ __fortify_function wchar_t *
+ __NTH (wmempcpy (wchar_t *__restrict __s1, const wchar_t *__restrict __s2,
+ 		 size_t __n))
+ {
+-  if (__glibc_objsize0 (__s1) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__n))
+-	return __wmempcpy_chk (__s1, __s2, __n,
+-			       __glibc_objsize0 (__s1) / sizeof (wchar_t));
+-
+-      if (__n > __glibc_objsize0 (__s1) / sizeof (wchar_t))
+-	return __wmempcpy_chk_warn (__s1, __s2, __n,
+-				    (__glibc_objsize0 (__s1)
+-				     / sizeof (wchar_t)));
+-    }
+-  return __wmempcpy_alias (__s1, __s2, __n);
++  return __glibc_fortify_n (wmempcpy, __n, sizeof (wchar_t),
++			    __glibc_objsize0 (__s1),
++			    __s1, __s2, __n);
+ }
+ #endif
+ 
+@@ -130,17 +104,9 @@ extern wchar_t *__REDIRECT_NTH (__wmemset_chk_warn,
+ __fortify_function wchar_t *
+ __NTH (wmemset (wchar_t *__s, wchar_t __c, size_t __n))
+ {
+-  if (__glibc_objsize0 (__s) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__n))
+-	return __wmemset_chk (__s, __c, __n,
+-			      __glibc_objsize0 (__s) / sizeof (wchar_t));
+-
+-      if (__n > __glibc_objsize0 (__s) / sizeof (wchar_t))
+-	return __wmemset_chk_warn (__s, __c, __n,
+-				   __glibc_objsize0 (__s) / sizeof (wchar_t));
+-    }
+-  return __wmemset_alias (__s, __c, __n);
++  return __glibc_fortify_n (wmemset, __n, sizeof (wchar_t),
++			    __glibc_objsize0 (__s),
++			    __s, __c, __n);
+ }
+ 
+ 
+@@ -154,9 +120,9 @@ extern wchar_t *__REDIRECT_NTH (__wcscpy_alias,
+ __fortify_function wchar_t *
+ __NTH (wcscpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src))
+ {
+-  if (__glibc_objsize (__dest) != (size_t) -1)
+-    return __wcscpy_chk (__dest, __src,
+-			 __glibc_objsize (__dest) / sizeof (wchar_t));
++  size_t sz = __glibc_objsize (__dest);
++  if (sz != (size_t) -1)
++    return __wcscpy_chk (__dest, __src, sz / sizeof (wchar_t));
+   return __wcscpy_alias (__dest, __src);
+ }
+ 
+@@ -171,9 +137,9 @@ extern wchar_t *__REDIRECT_NTH (__wcpcpy_alias,
+ __fortify_function wchar_t *
+ __NTH (wcpcpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src))
+ {
+-  if (__glibc_objsize (__dest) != (size_t) -1)
+-    return __wcpcpy_chk (__dest, __src,
+-			 __glibc_objsize (__dest) / sizeof (wchar_t));
++  size_t sz = __glibc_objsize (__dest);
++  if (sz != (size_t) -1)
++    return __wcpcpy_chk (__dest, __src, sz / sizeof (wchar_t));
+   return __wcpcpy_alias (__dest, __src);
+ }
+ 
+@@ -196,17 +162,9 @@ __fortify_function wchar_t *
+ __NTH (wcsncpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src,
+ 		size_t __n))
+ {
+-  if (__glibc_objsize (__dest) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__n))
+-	return __wcsncpy_chk (__dest, __src, __n,
+-			      __glibc_objsize (__dest) / sizeof (wchar_t));
+-      if (__n > __glibc_objsize (__dest) / sizeof (wchar_t))
+-	return __wcsncpy_chk_warn (__dest, __src, __n,
+-				   (__glibc_objsize (__dest)
+-				    / sizeof (wchar_t)));
+-    }
+-  return __wcsncpy_alias (__dest, __src, __n);
++  return __glibc_fortify_n (wcsncpy, __n, sizeof (wchar_t),
++			    __glibc_objsize (__dest),
++			    __dest, __src, __n);
+ }
+ 
+ 
+@@ -228,17 +186,9 @@ __fortify_function wchar_t *
+ __NTH (wcpncpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src,
+ 		size_t __n))
+ {
+-  if (__glibc_objsize (__dest) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__n))
+-	return __wcpncpy_chk (__dest, __src, __n,
+-			      __glibc_objsize (__dest) / sizeof (wchar_t));
+-      if (__n > __glibc_objsize (__dest) / sizeof (wchar_t))
+-	return __wcpncpy_chk_warn (__dest, __src, __n,
+-				   (__glibc_objsize (__dest)
+-				    / sizeof (wchar_t)));
+-    }
+-  return __wcpncpy_alias (__dest, __src, __n);
++  return __glibc_fortify_n (wcpncpy, __n, sizeof (wchar_t),
++			    __glibc_objsize (__dest),
++			    __dest, __src, __n);
+ }
+ 
+ 
+@@ -252,9 +202,9 @@ extern wchar_t *__REDIRECT_NTH (__wcscat_alias,
+ __fortify_function wchar_t *
+ __NTH (wcscat (wchar_t *__restrict __dest, const wchar_t *__restrict __src))
+ {
+-  if (__glibc_objsize (__dest) != (size_t) -1)
+-    return __wcscat_chk (__dest, __src,
+-			 __glibc_objsize (__dest) / sizeof (wchar_t));
++  size_t sz = __glibc_objsize (__dest);
++  if (sz != (size_t) -1)
++    return __wcscat_chk (__dest, __src, sz / sizeof (wchar_t));
+   return __wcscat_alias (__dest, __src);
+ }
+ 
+@@ -271,9 +221,9 @@ __fortify_function wchar_t *
+ __NTH (wcsncat (wchar_t *__restrict __dest, const wchar_t *__restrict __src,
+ 		size_t __n))
+ {
+-  if (__glibc_objsize (__dest) != (size_t) -1)
+-    return __wcsncat_chk (__dest, __src, __n,
+-			  __glibc_objsize (__dest) / sizeof (wchar_t));
++  size_t sz = __glibc_objsize (__dest);
++  if (sz != (size_t) -1)
++    return __wcsncat_chk (__dest, __src, __n, sz / sizeof (wchar_t));
+   return __wcsncat_alias (__dest, __src, __n);
+ }
+ 
+@@ -293,10 +243,10 @@ __fortify_function int
+ __NTH (swprintf (wchar_t *__restrict __s, size_t __n,
+ 		 const wchar_t *__restrict __fmt, ...))
+ {
+-  if (__glibc_objsize (__s) != (size_t) -1 || __USE_FORTIFY_LEVEL > 1)
++  size_t sz = __glibc_objsize (__s);
++  if (sz != (size_t) -1 || __USE_FORTIFY_LEVEL > 1)
+     return __swprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1,
+-			   __glibc_objsize (__s) / sizeof (wchar_t),
+-			   __fmt, __va_arg_pack ());
++			   sz / sizeof (wchar_t), __fmt, __va_arg_pack ());
+   return __swprintf_alias (__s, __n, __fmt, __va_arg_pack ());
+ }
+ #elif !defined __cplusplus
+@@ -323,10 +273,10 @@ __fortify_function int
+ __NTH (vswprintf (wchar_t *__restrict __s, size_t __n,
+ 		  const wchar_t *__restrict __fmt, __gnuc_va_list __ap))
+ {
+-  if (__glibc_objsize (__s) != (size_t) -1 || __USE_FORTIFY_LEVEL > 1)
++  size_t sz = __glibc_objsize (__s);
++  if (sz != (size_t) -1 || __USE_FORTIFY_LEVEL > 1)
+     return __vswprintf_chk (__s, __n,  __USE_FORTIFY_LEVEL - 1,
+-			    __glibc_objsize (__s) / sizeof (wchar_t), __fmt,
+-			    __ap);
++			    sz / sizeof (wchar_t), __fmt, __ap);
+   return __vswprintf_alias (__s, __n, __fmt, __ap);
+ }
+ 
+@@ -392,18 +342,12 @@ extern wchar_t *__REDIRECT (__fgetws_chk_warn,
+ __fortify_function __wur wchar_t *
+ fgetws (wchar_t *__restrict __s, int __n, __FILE *__restrict __stream)
+ {
+-  if (__glibc_objsize (__s) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__n) || __n <= 0)
+-	return __fgetws_chk (__s, __glibc_objsize (__s) / sizeof (wchar_t),
+-			     __n, __stream);
+-
+-      if ((size_t) __n > __glibc_objsize (__s) / sizeof (wchar_t))
+-	return __fgetws_chk_warn (__s,
+-				  __glibc_objsize (__s) / sizeof (wchar_t),
+-				  __n, __stream);
+-    }
+-  return __fgetws_alias (__s, __n, __stream);
++  size_t sz = __glibc_objsize (__s);
++  if (__glibc_safe_or_unknown_len (__n, sizeof (wchar_t), sz))
++    return __fgetws_alias (__s, __n, __stream);
++  if (__glibc_unsafe_len (__n, sizeof (wchar_t), sz))
++    return __fgetws_chk_warn (__s, sz / sizeof (wchar_t), __n, __stream);
++  return __fgetws_chk (__s, sz / sizeof (wchar_t), __n, __stream);
+ }
+ 
+ #ifdef __USE_GNU
+@@ -424,20 +368,13 @@ extern wchar_t *__REDIRECT (__fgetws_unlocked_chk_warn,
+ __fortify_function __wur wchar_t *
+ fgetws_unlocked (wchar_t *__restrict __s, int __n, __FILE *__restrict __stream)
+ {
+-  if (__glibc_objsize (__s) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__n) || __n <= 0)
+-	return __fgetws_unlocked_chk (__s,
+-				      __glibc_objsize (__s) / sizeof (wchar_t),
+-				      __n, __stream);
+-
+-      if ((size_t) __n > __glibc_objsize (__s) / sizeof (wchar_t))
+-	return __fgetws_unlocked_chk_warn (__s,
+-					   (__glibc_objsize (__s)
+-					    / sizeof (wchar_t)),
+-					   __n, __stream);
+-    }
+-  return __fgetws_unlocked_alias (__s, __n, __stream);
++  size_t sz = __glibc_objsize (__s);
++  if (__glibc_safe_or_unknown_len (__n, sizeof (wchar_t), sz))
++    return __fgetws_unlocked_alias (__s, __n, __stream);
++  if (__glibc_unsafe_len (__n, sizeof (wchar_t), sz))
++    return __fgetws_unlocked_chk_warn (__s, sz / sizeof (wchar_t), __n,
++				       __stream);
++  return __fgetws_unlocked_chk (__s, sz / sizeof (wchar_t), __n, __stream);
+ }
+ #endif
+ 
+@@ -488,18 +425,9 @@ __fortify_function size_t
+ __NTH (mbsrtowcs (wchar_t *__restrict __dst, const char **__restrict __src,
+ 		  size_t __len, mbstate_t *__restrict __ps))
+ {
+-  if (__glibc_objsize (__dst) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__len))
+-	return __mbsrtowcs_chk (__dst, __src, __len, __ps,
+-				__glibc_objsize (__dst) / sizeof (wchar_t));
+-
+-      if (__len > __glibc_objsize (__dst) / sizeof (wchar_t))
+-	return __mbsrtowcs_chk_warn (__dst, __src, __len, __ps,
+-				     (__glibc_objsize (__dst)
+-				      / sizeof (wchar_t)));
+-    }
+-  return __mbsrtowcs_alias (__dst, __src, __len, __ps);
++  return __glibc_fortify_n (mbsrtowcs, __len, sizeof (wchar_t),
++			    __glibc_objsize (__dst),
++			    __dst, __src, __len, __ps);
+ }
+ 
+ 
+@@ -523,17 +451,9 @@ __fortify_function size_t
+ __NTH (wcsrtombs (char *__restrict __dst, const wchar_t **__restrict __src,
+ 		  size_t __len, mbstate_t *__restrict __ps))
+ {
+-  if (__glibc_objsize (__dst) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__len))
+-	return __wcsrtombs_chk (__dst, __src, __len, __ps,
+-				__glibc_objsize (__dst));
+-
+-      if (__len > __glibc_objsize (__dst))
+-	return __wcsrtombs_chk_warn (__dst, __src, __len, __ps,
+-				     __glibc_objsize (__dst));
+-    }
+-  return __wcsrtombs_alias (__dst, __src, __len, __ps);
++  return __glibc_fortify (wcsrtombs, __len, sizeof (char),
++			  __glibc_objsize (__dst),
++			  __dst, __src, __len, __ps);
+ }
+ 
+ 
+@@ -559,18 +479,9 @@ __fortify_function size_t
+ __NTH (mbsnrtowcs (wchar_t *__restrict __dst, const char **__restrict __src,
+ 		   size_t __nmc, size_t __len, mbstate_t *__restrict __ps))
+ {
+-  if (__glibc_objsize (__dst) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__len))
+-	return __mbsnrtowcs_chk (__dst, __src, __nmc, __len, __ps,
+-				 __glibc_objsize (__dst) / sizeof (wchar_t));
+-
+-      if (__len > __glibc_objsize (__dst) / sizeof (wchar_t))
+-	return __mbsnrtowcs_chk_warn (__dst, __src, __nmc, __len, __ps,
+-				      (__glibc_objsize (__dst)
+-				       / sizeof (wchar_t)));
+-    }
+-  return __mbsnrtowcs_alias (__dst, __src, __nmc, __len, __ps);
++  return __glibc_fortify_n (mbsnrtowcs, __len, sizeof (wchar_t),
++			    __glibc_objsize (__dst),
++			    __dst, __src, __nmc, __len, __ps);
+ }
+ 
+ 
+@@ -596,16 +507,8 @@ __fortify_function size_t
+ __NTH (wcsnrtombs (char *__restrict __dst, const wchar_t **__restrict __src,
+ 		   size_t __nwc, size_t __len, mbstate_t *__restrict __ps))
+ {
+-  if (__glibc_objsize (__dst) != (size_t) -1)
+-    {
+-      if (!__builtin_constant_p (__len))
+-	return __wcsnrtombs_chk (__dst, __src, __nwc, __len, __ps,
+-				 __glibc_objsize (__dst));
+-
+-      if (__len > __glibc_objsize (__dst))
+-	return __wcsnrtombs_chk_warn (__dst, __src, __nwc, __len, __ps,
+-				      __glibc_objsize (__dst));
+-    }
+-  return __wcsnrtombs_alias (__dst, __src, __nwc, __len, __ps);
++  return __glibc_fortify (wcsnrtombs, __len, sizeof (char),
++			  __glibc_objsize (__dst),
++			  __dst, __src, __nwc, __len, __ps);
+ }
+ #endif
diff --git a/SOURCES/glibc-rh2033684-7.patch b/SOURCES/glibc-rh2033684-7.patch
new file mode 100644
index 0000000..7cb18a6
--- /dev/null
+++ b/SOURCES/glibc-rh2033684-7.patch
@@ -0,0 +1,43 @@
+commit fadf75c370494da6a02274ebe79e45b2f22ebbd0
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Mon Feb 10 14:37:10 2020 +0100
+
+    debug: Add missing locale dependencies of fortify tests
+    
+    The missing dependencies result in failures like this if make check
+    is invoked with sufficient parallelism for the debug subdirectory:
+    
+    FAIL: debug/tst-chk2
+    FAIL: debug/tst-chk3
+    FAIL: debug/tst-chk4
+    FAIL: debug/tst-chk5
+    FAIL: debug/tst-chk6
+    FAIL: debug/tst-lfschk1
+    FAIL: debug/tst-lfschk2
+    FAIL: debug/tst-lfschk3
+    FAIL: debug/tst-lfschk4
+    FAIL: debug/tst-lfschk5
+    FAIL: debug/tst-lfschk6
+
+diff --git a/debug/Makefile b/debug/Makefile
+index 506cebc3c4ca19ff..5e45c9b41077f2fd 100644
+--- a/debug/Makefile
++++ b/debug/Makefile
+@@ -188,6 +188,17 @@ LOCALES := de_DE.UTF-8
+ include ../gen-locales.mk
+ 
+ $(objpfx)tst-chk1.out: $(gen-locales)
++$(objpfx)tst-chk2.out: $(gen-locales)
++$(objpfx)tst-chk3.out: $(gen-locales)
++$(objpfx)tst-chk4.out: $(gen-locales)
++$(objpfx)tst-chk5.out: $(gen-locales)
++$(objpfx)tst-chk6.out: $(gen-locales)
++$(objpfx)tst-lfschk1.out: $(gen-locales)
++$(objpfx)tst-lfschk2.out: $(gen-locales)
++$(objpfx)tst-lfschk3.out: $(gen-locales)
++$(objpfx)tst-lfschk4.out: $(gen-locales)
++$(objpfx)tst-lfschk5.out: $(gen-locales)
++$(objpfx)tst-lfschk6.out: $(gen-locales)
+ endif
+ 
+ sLIBdir := $(shell echo $(slibdir) | sed 's,lib\(\|64\)$$,\\\\$$LIB,')
diff --git a/SOURCES/glibc-rh2033684-8.patch b/SOURCES/glibc-rh2033684-8.patch
new file mode 100644
index 0000000..5b90b20
--- /dev/null
+++ b/SOURCES/glibc-rh2033684-8.patch
@@ -0,0 +1,357 @@
+commit ad6f2a010c2ce759936de4747f6e0d53991912f8
+Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date:   Wed Oct 20 18:13:05 2021 +0530
+
+    debug: Add tests for _FORTIFY_SOURCE=3
+    
+    Add some testing coverage for _FORTIFY_SOURCE=3.
+    
+    Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+    Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
+
+diff --git a/debug/Makefile b/debug/Makefile
+index 5e45c9b41077f2fd..81361438fc3d2aa9 100644
+--- a/debug/Makefile
++++ b/debug/Makefile
+@@ -120,6 +120,8 @@ CFLAGS-tst-chk3.c += -Wno-format -Wno-deprecated-declarations -Wno-error
+ CFLAGS-tst-chk4.cc += -Wno-format -Wno-deprecated-declarations -Wno-error
+ CFLAGS-tst-chk5.cc += -Wno-format -Wno-deprecated-declarations -Wno-error
+ CFLAGS-tst-chk6.cc += -Wno-format -Wno-deprecated-declarations -Wno-error
++CFLAGS-tst-chk7.c += -Wno-format -Wno-deprecated-declarations -Wno-error
++CFLAGS-tst-chk8.cc += -Wno-format -Wno-deprecated-declarations -Wno-error
+ CFLAGS-tst-lfschk1.c += -Wno-format -Wno-deprecated-declarations -Wno-error
+ CFLAGS-tst-lfschk2.c += -Wno-format -Wno-deprecated-declarations -Wno-error
+ CFLAGS-tst-lfschk3.c += -Wno-format -Wno-deprecated-declarations -Wno-error
+@@ -129,6 +131,7 @@ CFLAGS-tst-lfschk6.cc += -Wno-format -Wno-deprecated-declarations -Wno-error
+ LDLIBS-tst-chk4 = -lstdc++
+ LDLIBS-tst-chk5 = -lstdc++
+ LDLIBS-tst-chk6 = -lstdc++
++LDLIBS-tst-chk8 = -lstdc++
+ LDLIBS-tst-lfschk4 = -lstdc++
+ LDLIBS-tst-lfschk5 = -lstdc++
+ LDLIBS-tst-lfschk6 = -lstdc++
+@@ -150,16 +153,16 @@ CFLAGS-tst-ssp-1.c += -fstack-protector-all
+ 
+ tests = backtrace-tst tst-longjmp_chk tst-chk1 tst-chk2 tst-chk3 \
+ 	tst-lfschk1 tst-lfschk2 tst-lfschk3 test-strcpy_chk test-stpcpy_chk \
+-	tst-chk4 tst-chk5 tst-chk6 tst-lfschk4 tst-lfschk5 tst-lfschk6 \
+-	tst-longjmp_chk2 tst-backtrace2 tst-backtrace3 tst-backtrace4 \
+-	tst-backtrace5 tst-backtrace6
++	tst-chk4 tst-chk5 tst-chk6 tst-chk7 tst-chk8 tst-lfschk4 tst-lfschk5 \
++	tst-lfschk6 tst-longjmp_chk2 tst-backtrace2 tst-backtrace3 \
++	tst-backtrace4 tst-backtrace5 tst-backtrace6
+ 
+ ifeq ($(have-ssp),yes)
+ tests += tst-ssp-1
+ endif
+ 
+ ifeq (,$(CXX))
+-tests-unsupported = tst-chk4 tst-chk5 tst-chk6 \
++tests-unsupported = tst-chk4 tst-chk5 tst-chk6 tst-chk8 \
+ 		    tst-lfschk4 tst-lfschk5 tst-lfschk6
+ endif
+ 
+@@ -193,6 +196,8 @@ $(objpfx)tst-chk3.out: $(gen-locales)
+ $(objpfx)tst-chk4.out: $(gen-locales)
+ $(objpfx)tst-chk5.out: $(gen-locales)
+ $(objpfx)tst-chk6.out: $(gen-locales)
++$(objpfx)tst-chk7.out: $(gen-locales)
++$(objpfx)tst-chk8.out: $(gen-locales)
+ $(objpfx)tst-lfschk1.out: $(gen-locales)
+ $(objpfx)tst-lfschk2.out: $(gen-locales)
+ $(objpfx)tst-lfschk3.out: $(gen-locales)
+diff --git a/debug/tst-chk1.c b/debug/tst-chk1.c
+index ca2b524b2fa6404c..5e76081255316a93 100644
+--- a/debug/tst-chk1.c
++++ b/debug/tst-chk1.c
+@@ -83,8 +83,14 @@ handler (int sig)
+     _exit (127);
+ }
+ 
++#if __USE_FORTIFY_LEVEL == 3
++volatile size_t buf_size = 10;
++#else
+ char buf[10];
+ wchar_t wbuf[10];
++#define buf_size sizeof (buf)
++#endif
++
+ volatile size_t l0;
+ volatile char *p;
+ volatile wchar_t *wp;
+@@ -123,6 +129,10 @@ int num2 = 987654;
+ static int
+ do_test (void)
+ {
++#if __USE_FORTIFY_LEVEL == 3
++  char *buf = (char *) malloc (buf_size);
++  wchar_t *wbuf = (wchar_t *) malloc (buf_size * sizeof (wchar_t));
++#endif
+   set_fortify_handler (handler);
+ 
+   struct A { char buf1[9]; char buf2[1]; } a;
+@@ -947,93 +957,93 @@ do_test (void)
+ 
+   rewind (stdin);
+ 
+-  if (fgets (buf, sizeof (buf), stdin) != buf
++  if (fgets (buf, buf_size, stdin) != buf
+       || memcmp (buf, "abcdefgh\n", 10))
+     FAIL ();
+-  if (fgets (buf, sizeof (buf), stdin) != buf || memcmp (buf, "ABCDEFGHI", 10))
++  if (fgets (buf, buf_size, stdin) != buf || memcmp (buf, "ABCDEFGHI", 10))
+     FAIL ();
+ 
+   rewind (stdin);
+ 
+-  if (fgets (buf, l0 + sizeof (buf), stdin) != buf
++  if (fgets (buf, l0 + buf_size, stdin) != buf
+       || memcmp (buf, "abcdefgh\n", 10))
+     FAIL ();
+ 
+ #if __USE_FORTIFY_LEVEL >= 1
+   CHK_FAIL_START
+-  if (fgets (buf, sizeof (buf) + 1, stdin) != buf)
++  if (fgets (buf, buf_size + 1, stdin) != buf)
+     FAIL ();
+   CHK_FAIL_END
+ 
+   CHK_FAIL_START
+-  if (fgets (buf, l0 + sizeof (buf) + 1, stdin) != buf)
++  if (fgets (buf, l0 + buf_size + 1, stdin) != buf)
+     FAIL ();
+   CHK_FAIL_END
+ #endif
+ 
+   rewind (stdin);
+ 
+-  if (fgets_unlocked (buf, sizeof (buf), stdin) != buf
++  if (fgets_unlocked (buf, buf_size, stdin) != buf
+       || memcmp (buf, "abcdefgh\n", 10))
+     FAIL ();
+-  if (fgets_unlocked (buf, sizeof (buf), stdin) != buf
++  if (fgets_unlocked (buf, buf_size, stdin) != buf
+       || memcmp (buf, "ABCDEFGHI", 10))
+     FAIL ();
+ 
+   rewind (stdin);
+ 
+-  if (fgets_unlocked (buf, l0 + sizeof (buf), stdin) != buf
++  if (fgets_unlocked (buf, l0 + buf_size, stdin) != buf
+       || memcmp (buf, "abcdefgh\n", 10))
+     FAIL ();
+ 
+ #if __USE_FORTIFY_LEVEL >= 1
+   CHK_FAIL_START
+-  if (fgets_unlocked (buf, sizeof (buf) + 1, stdin) != buf)
++  if (fgets_unlocked (buf, buf_size + 1, stdin) != buf)
+     FAIL ();
+   CHK_FAIL_END
+ 
+   CHK_FAIL_START
+-  if (fgets_unlocked (buf, l0 + sizeof (buf) + 1, stdin) != buf)
++  if (fgets_unlocked (buf, l0 + buf_size + 1, stdin) != buf)
+     FAIL ();
+   CHK_FAIL_END
+ #endif
+ 
+   rewind (stdin);
+ 
+-  if (fread (buf, 1, sizeof (buf), stdin) != sizeof (buf)
++  if (fread (buf, 1, buf_size, stdin) != buf_size
+       || memcmp (buf, "abcdefgh\nA", 10))
+     FAIL ();
+-  if (fread (buf, sizeof (buf), 1, stdin) != 1
++  if (fread (buf, buf_size, 1, stdin) != 1
+       || memcmp (buf, "BCDEFGHI\na", 10))
+     FAIL ();
+ 
+   rewind (stdin);
+ 
+-  if (fread (buf, l0 + 1, sizeof (buf), stdin) != sizeof (buf)
++  if (fread (buf, l0 + 1, buf_size, stdin) != buf_size
+       || memcmp (buf, "abcdefgh\nA", 10))
+     FAIL ();
+-  if (fread (buf, sizeof (buf), l0 + 1, stdin) != 1
++  if (fread (buf, buf_size, l0 + 1, stdin) != 1
+       || memcmp (buf, "BCDEFGHI\na", 10))
+     FAIL ();
+ 
+ #if __USE_FORTIFY_LEVEL >= 1
+   CHK_FAIL_START
+-  if (fread (buf, 1, sizeof (buf) + 1, stdin) != sizeof (buf) + 1)
++  if (fread (buf, 1, buf_size + 1, stdin) != buf_size + 1)
+     FAIL ();
+   CHK_FAIL_END
+ 
+   CHK_FAIL_START
+-  if (fread (buf, sizeof (buf) + 1, l0 + 1, stdin) != 1)
++  if (fread (buf, buf_size + 1, l0 + 1, stdin) != 1)
+     FAIL ();
+   CHK_FAIL_END
+ #endif
+ 
+   rewind (stdin);
+ 
+-  if (fread_unlocked (buf, 1, sizeof (buf), stdin) != sizeof (buf)
++  if (fread_unlocked (buf, 1, buf_size, stdin) != buf_size
+       || memcmp (buf, "abcdefgh\nA", 10))
+     FAIL ();
+-  if (fread_unlocked (buf, sizeof (buf), 1, stdin) != 1
++  if (fread_unlocked (buf, buf_size, 1, stdin) != 1
+       || memcmp (buf, "BCDEFGHI\na", 10))
+     FAIL ();
+ 
+@@ -1048,100 +1058,100 @@ do_test (void)
+ 
+   rewind (stdin);
+ 
+-  if (fread_unlocked (buf, l0 + 1, sizeof (buf), stdin) != sizeof (buf)
++  if (fread_unlocked (buf, l0 + 1, buf_size, stdin) != buf_size
+       || memcmp (buf, "abcdefgh\nA", 10))
+     FAIL ();
+-  if (fread_unlocked (buf, sizeof (buf), l0 + 1, stdin) != 1
++  if (fread_unlocked (buf, buf_size, l0 + 1, stdin) != 1
+       || memcmp (buf, "BCDEFGHI\na", 10))
+     FAIL ();
+ 
+ #if __USE_FORTIFY_LEVEL >= 1
+   CHK_FAIL_START
+-  if (fread_unlocked (buf, 1, sizeof (buf) + 1, stdin) != sizeof (buf) + 1)
++  if (fread_unlocked (buf, 1, buf_size + 1, stdin) != buf_size + 1)
+     FAIL ();
+   CHK_FAIL_END
+ 
+   CHK_FAIL_START
+-  if (fread_unlocked (buf, sizeof (buf) + 1, l0 + 1, stdin) != 1)
++  if (fread_unlocked (buf, buf_size + 1, l0 + 1, stdin) != 1)
+     FAIL ();
+   CHK_FAIL_END
+ #endif
+ 
+   lseek (fileno (stdin), 0, SEEK_SET);
+ 
+-  if (read (fileno (stdin), buf, sizeof (buf) - 1) != sizeof (buf) - 1
++  if (read (fileno (stdin), buf, buf_size - 1) != buf_size - 1
+       || memcmp (buf, "abcdefgh\n", 9))
+     FAIL ();
+-  if (read (fileno (stdin), buf, sizeof (buf) - 1) != sizeof (buf) - 1
++  if (read (fileno (stdin), buf, buf_size - 1) != buf_size - 1
+       || memcmp (buf, "ABCDEFGHI", 9))
+     FAIL ();
+ 
+   lseek (fileno (stdin), 0, SEEK_SET);
+ 
+-  if (read (fileno (stdin), buf, l0 + sizeof (buf) - 1) != sizeof (buf) - 1
++  if (read (fileno (stdin), buf, l0 + buf_size - 1) != buf_size - 1
+       || memcmp (buf, "abcdefgh\n", 9))
+     FAIL ();
+ 
+ #if __USE_FORTIFY_LEVEL >= 1
+   CHK_FAIL_START
+-  if (read (fileno (stdin), buf, sizeof (buf) + 1) != sizeof (buf) + 1)
++  if (read (fileno (stdin), buf, buf_size + 1) != buf_size + 1)
+     FAIL ();
+   CHK_FAIL_END
+ 
+   CHK_FAIL_START
+-  if (read (fileno (stdin), buf, l0 + sizeof (buf) + 1) != sizeof (buf) + 1)
++  if (read (fileno (stdin), buf, l0 + buf_size + 1) != buf_size + 1)
+     FAIL ();
+   CHK_FAIL_END
+ #endif
+ 
+-  if (pread (fileno (stdin), buf, sizeof (buf) - 1, sizeof (buf) - 2)
+-      != sizeof (buf) - 1
++  if (pread (fileno (stdin), buf, buf_size - 1, buf_size - 2)
++      != buf_size - 1
+       || memcmp (buf, "\nABCDEFGH", 9))
+     FAIL ();
+-  if (pread (fileno (stdin), buf, sizeof (buf) - 1, 0) != sizeof (buf) - 1
++  if (pread (fileno (stdin), buf, buf_size - 1, 0) != buf_size - 1
+       || memcmp (buf, "abcdefgh\n", 9))
+     FAIL ();
+-  if (pread (fileno (stdin), buf, l0 + sizeof (buf) - 1, sizeof (buf) - 3)
+-      != sizeof (buf) - 1
++  if (pread (fileno (stdin), buf, l0 + buf_size - 1, buf_size - 3)
++      != buf_size - 1
+       || memcmp (buf, "h\nABCDEFG", 9))
+     FAIL ();
+ 
+ #if __USE_FORTIFY_LEVEL >= 1
+   CHK_FAIL_START
+-  if (pread (fileno (stdin), buf, sizeof (buf) + 1, 2 * sizeof (buf))
+-      != sizeof (buf) + 1)
++  if (pread (fileno (stdin), buf, buf_size + 1, 2 * buf_size)
++      != buf_size + 1)
+     FAIL ();
+   CHK_FAIL_END
+ 
+   CHK_FAIL_START
+-  if (pread (fileno (stdin), buf, l0 + sizeof (buf) + 1, 2 * sizeof (buf))
+-      != sizeof (buf) + 1)
++  if (pread (fileno (stdin), buf, l0 + buf_size + 1, 2 * buf_size)
++      != buf_size + 1)
+     FAIL ();
+   CHK_FAIL_END
+ #endif
+ 
+-  if (pread64 (fileno (stdin), buf, sizeof (buf) - 1, sizeof (buf) - 2)
+-      != sizeof (buf) - 1
++  if (pread64 (fileno (stdin), buf, buf_size - 1, buf_size - 2)
++      != buf_size - 1
+       || memcmp (buf, "\nABCDEFGH", 9))
+     FAIL ();
+-  if (pread64 (fileno (stdin), buf, sizeof (buf) - 1, 0) != sizeof (buf) - 1
++  if (pread64 (fileno (stdin), buf, buf_size - 1, 0) != buf_size - 1
+       || memcmp (buf, "abcdefgh\n", 9))
+     FAIL ();
+-  if (pread64 (fileno (stdin), buf, l0 + sizeof (buf) - 1, sizeof (buf) - 3)
+-      != sizeof (buf) - 1
++  if (pread64 (fileno (stdin), buf, l0 + buf_size - 1, buf_size - 3)
++      != buf_size - 1
+       || memcmp (buf, "h\nABCDEFG", 9))
+     FAIL ();
+ 
+ #if __USE_FORTIFY_LEVEL >= 1
+   CHK_FAIL_START
+-  if (pread64 (fileno (stdin), buf, sizeof (buf) + 1, 2 * sizeof (buf))
+-      != sizeof (buf) + 1)
++  if (pread64 (fileno (stdin), buf, buf_size + 1, 2 * buf_size)
++      != buf_size + 1)
+     FAIL ();
+   CHK_FAIL_END
+ 
+   CHK_FAIL_START
+-  if (pread64 (fileno (stdin), buf, l0 + sizeof (buf) + 1, 2 * sizeof (buf))
+-      != sizeof (buf) + 1)
++  if (pread64 (fileno (stdin), buf, l0 + buf_size + 1, 2 * buf_size)
++      != buf_size + 1)
+     FAIL ();
+   CHK_FAIL_END
+ #endif
+@@ -1179,7 +1189,7 @@ do_test (void)
+   CHK_FAIL2_END
+ 
+   CHK_FAIL2_START
+-  snprintf (buf, sizeof (buf), "%3$d\n", 1, 2, 3, 4);
++  snprintf (buf, buf_size, "%3$d\n", 1, 2, 3, 4);
+   CHK_FAIL2_END
+ 
+   int sp[2];
+diff --git a/debug/tst-chk7.c b/debug/tst-chk7.c
+new file mode 100644
+index 0000000000000000..2a7b32381268135c
+--- /dev/null
++++ b/debug/tst-chk7.c
+@@ -0,0 +1,2 @@
++#define _FORTIFY_SOURCE 3
++#include "tst-chk1.c"
+diff --git a/debug/tst-chk8.cc b/debug/tst-chk8.cc
+new file mode 100644
+index 0000000000000000..2a7b32381268135c
+--- /dev/null
++++ b/debug/tst-chk8.cc
+@@ -0,0 +1,2 @@
++#define _FORTIFY_SOURCE 3
++#include "tst-chk1.c"
diff --git a/SOURCES/glibc-rh2033684-9.patch b/SOURCES/glibc-rh2033684-9.patch
new file mode 100644
index 0000000..467ece4
--- /dev/null
+++ b/SOURCES/glibc-rh2033684-9.patch
@@ -0,0 +1,23 @@
+commit ae23fa3e5fe24daf94fc7f8e5268bb8ceeda7477
+Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date:   Thu Dec 16 07:19:14 2021 +0530
+
+    __glibc_unsafe_len: Fix comment
+    
+    We know that the length is *unsafe*.
+    
+    Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+
+diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h
+index 17b84a2e6c69d961..147339957c4ad490 100644
+--- a/misc/sys/cdefs.h
++++ b/misc/sys/cdefs.h
+@@ -150,7 +150,7 @@
+ 						   __s, __osz))		      \
+    && __glibc_safe_len_cond ((__SIZE_TYPE__) (__l), __s, __osz))
+ 
+-/* Conversely, we know at compile time that the length is safe if the
++/* Conversely, we know at compile time that the length is unsafe if the
+    __L * __S <= __OBJSZ condition can be folded to a constant and if it is
+    false.  */
+ #define __glibc_unsafe_len(__l, __s, __osz) \
diff --git a/SOURCES/glibc-rh2037416-1.patch b/SOURCES/glibc-rh2037416-1.patch
new file mode 100644
index 0000000..3fddefe
--- /dev/null
+++ b/SOURCES/glibc-rh2037416-1.patch
@@ -0,0 +1,136 @@
+From 07b427296b8d59f439144029d9a948f6c1ce0a31 Mon Sep 17 00:00:00 2001
+From: Wilco Dijkstra <wdijkstr@arm.com>
+Date: Tue, 10 Aug 2021 13:30:27 +0100
+Subject: [PATCH] [1/5] AArch64: Improve A64FX memset for small sizes
+
+Improve performance of small memsets by reducing instruction counts and
+improving code alignment. Bench-memset shows 35-45% performance gain for
+small sizes.
+
+Reviewed-by: Naohiro Tamura <naohirot@fujitsu.com>
+---
+ sysdeps/aarch64/multiarch/memset_a64fx.S | 96 +++++++++---------------
+ 1 file changed, 36 insertions(+), 60 deletions(-)
+
+diff --git a/sysdeps/aarch64/multiarch/memset_a64fx.S b/sysdeps/aarch64/multiarch/memset_a64fx.S
+index ce54e5418b..cf3d402ef6 100644
+--- a/sysdeps/aarch64/multiarch/memset_a64fx.S
++++ b/sysdeps/aarch64/multiarch/memset_a64fx.S
+@@ -51,78 +51,54 @@
+ 	.endm
+ 
+ 	.macro st1b_unroll first=0, last=7
+-	st1b	z0.b, p0, [dst, #\first, mul vl]
++	st1b	z0.b, p0, [dst, \first, mul vl]
+ 	.if \last-\first
+ 	st1b_unroll "(\first+1)", \last
+ 	.endif
+ 	.endm
+ 
+-	.macro shortcut_for_small_size exit
+-	// if rest <= vector_length * 2
+-	whilelo	p0.b, xzr, count
+-	whilelo	p1.b, vector_length, count
+-	b.last	1f
+-	st1b	z0.b, p0, [dstin, #0, mul vl]
+-	st1b	z0.b, p1, [dstin, #1, mul vl]
+-	ret
+-1:	// if rest > vector_length * 8
+-	cmp	count, vector_length, lsl 3	// vector_length * 8
+-	b.hi	\exit
+-	// if rest <= vector_length * 4
+-	lsl	tmp1, vector_length, 1	// vector_length * 2
+-	whilelo	p2.b, tmp1, count
+-	incb	tmp1
+-	whilelo	p3.b, tmp1, count
+-	b.last	1f
+-	st1b	z0.b, p0, [dstin, #0, mul vl]
+-	st1b	z0.b, p1, [dstin, #1, mul vl]
+-	st1b	z0.b, p2, [dstin, #2, mul vl]
+-	st1b	z0.b, p3, [dstin, #3, mul vl]
+-	ret
+-1:	// if rest <= vector_length * 8
+-	lsl	tmp1, vector_length, 2	// vector_length * 4
+-	whilelo	p4.b, tmp1, count
+-	incb	tmp1
+-	whilelo	p5.b, tmp1, count
+-	b.last	1f
+-	st1b	z0.b, p0, [dstin, #0, mul vl]
+-	st1b	z0.b, p1, [dstin, #1, mul vl]
+-	st1b	z0.b, p2, [dstin, #2, mul vl]
+-	st1b	z0.b, p3, [dstin, #3, mul vl]
+-	st1b	z0.b, p4, [dstin, #4, mul vl]
+-	st1b	z0.b, p5, [dstin, #5, mul vl]
+-	ret
+-1:	lsl	tmp1, vector_length, 2	// vector_length * 4
+-	incb	tmp1			// vector_length * 5
+-	incb	tmp1			// vector_length * 6
+-	whilelo	p6.b, tmp1, count
+-	incb	tmp1
+-	whilelo	p7.b, tmp1, count
+-	st1b	z0.b, p0, [dstin, #0, mul vl]
+-	st1b	z0.b, p1, [dstin, #1, mul vl]
+-	st1b	z0.b, p2, [dstin, #2, mul vl]
+-	st1b	z0.b, p3, [dstin, #3, mul vl]
+-	st1b	z0.b, p4, [dstin, #4, mul vl]
+-	st1b	z0.b, p5, [dstin, #5, mul vl]
+-	st1b	z0.b, p6, [dstin, #6, mul vl]
+-	st1b	z0.b, p7, [dstin, #7, mul vl]
+-	ret
+-	.endm
+ 
+-ENTRY (MEMSET)
++#undef BTI_C
++#define BTI_C
+ 
++ENTRY (MEMSET)
+ 	PTR_ARG (0)
+ 	SIZE_ARG (2)
+ 
+-	cbnz	count, 1f
+-	ret
+-1:	dup	z0.b, valw
+ 	cntb	vector_length
+-	// shortcut for less than vector_length * 8
+-	// gives a free ptrue to p0.b for n >= vector_length
+-	shortcut_for_small_size L(vl_agnostic)
+-	// end of shortcut
++	dup	z0.b, valw
++	whilelo	p0.b, vector_length, count
++	b.last	1f
++	whilelo	p1.b, xzr, count
++	st1b	z0.b, p1, [dstin, 0, mul vl]
++	st1b	z0.b, p0, [dstin, 1, mul vl]
++	ret
++
++	// count >= vector_length * 2
++1:	cmp	count, vector_length, lsl 2
++	add	dstend, dstin, count
++	b.hi	1f
++	st1b	z0.b, p0, [dstin, 0, mul vl]
++	st1b	z0.b, p0, [dstin, 1, mul vl]
++	st1b	z0.b, p0, [dstend, -2, mul vl]
++	st1b	z0.b, p0, [dstend, -1, mul vl]
++	ret
++
++	// count > vector_length * 4
++1:	lsl	tmp1, vector_length, 3
++	cmp	count, tmp1
++	b.hi	L(vl_agnostic)
++	st1b	z0.b, p0, [dstin, 0, mul vl]
++	st1b	z0.b, p0, [dstin, 1, mul vl]
++	st1b	z0.b, p0, [dstin, 2, mul vl]
++	st1b	z0.b, p0, [dstin, 3, mul vl]
++	st1b	z0.b, p0, [dstend, -4, mul vl]
++	st1b	z0.b, p0, [dstend, -3, mul vl]
++	st1b	z0.b, p0, [dstend, -2, mul vl]
++	st1b	z0.b, p0, [dstend, -1, mul vl]
++	ret
+ 
++	.p2align 4
+ L(vl_agnostic): // VL Agnostic
+ 	mov	rest, count
+ 	mov	dst, dstin
+-- 
+2.31.1
+
diff --git a/SOURCES/glibc-rh2037416-2.patch b/SOURCES/glibc-rh2037416-2.patch
new file mode 100644
index 0000000..e991e91
--- /dev/null
+++ b/SOURCES/glibc-rh2037416-2.patch
@@ -0,0 +1,131 @@
+From 9bc2ed8f46d80859a5596789cc9e8cc2de84b0e7 Mon Sep 17 00:00:00 2001
+From: Wilco Dijkstra <wdijkstr@arm.com>
+Date: Tue, 10 Aug 2021 13:39:37 +0100
+Subject: [PATCH] [2/5] AArch64: Improve A64FX memset for large sizes
+
+Improve performance of large memsets. Simplify alignment code. For zero memset
+use DC ZVA, which almost doubles performance. For non-zero memsets use the
+unroll8 loop which is about 10% faster.
+
+Reviewed-by: Naohiro Tamura <naohirot@fujitsu.com>
+---
+ sysdeps/aarch64/multiarch/memset_a64fx.S | 85 +++++++-----------------
+ 1 file changed, 25 insertions(+), 60 deletions(-)
+
+diff --git a/sysdeps/aarch64/multiarch/memset_a64fx.S b/sysdeps/aarch64/multiarch/memset_a64fx.S
+index cf3d402ef6..75cf43ae79 100644
+--- a/sysdeps/aarch64/multiarch/memset_a64fx.S
++++ b/sysdeps/aarch64/multiarch/memset_a64fx.S
+@@ -27,14 +27,11 @@
+  */
+ 
+ #define L1_SIZE		(64*1024)	// L1 64KB
+-#define L2_SIZE         (8*1024*1024)	// L2 8MB - 1MB
++#define L2_SIZE         (8*1024*1024)	// L2 8MB
+ #define CACHE_LINE_SIZE	256
+ #define PF_DIST_L1	(CACHE_LINE_SIZE * 16)	// Prefetch distance L1
+-#define ZF_DIST		(CACHE_LINE_SIZE * 21)	// Zerofill distance
+-#define rest		x8
++#define rest		x2
+ #define vector_length	x9
+-#define vl_remainder	x10	// vector_length remainder
+-#define cl_remainder	x11	// CACHE_LINE_SIZE remainder
+ 
+ #if HAVE_AARCH64_SVE_ASM
+ # if IS_IN (libc)
+@@ -42,14 +39,6 @@
+ 
+ 	.arch armv8.2-a+sve
+ 
+-	.macro dc_zva times
+-	dc	zva, tmp1
+-	add	tmp1, tmp1, CACHE_LINE_SIZE
+-	.if \times-1
+-	dc_zva "(\times-1)"
+-	.endif
+-	.endm
+-
+ 	.macro st1b_unroll first=0, last=7
+ 	st1b	z0.b, p0, [dst, \first, mul vl]
+ 	.if \last-\first
+@@ -188,54 +177,30 @@ L(L1_prefetch): // if rest >= L1_SIZE
+ 	cbnz	rest, L(unroll32)
+ 	ret
+ 
+-L(L2):
+-	// align dst address at vector_length byte boundary
+-	sub	tmp1, vector_length, 1
+-	ands	tmp2, dst, tmp1
+-	// if vl_remainder == 0
+-	b.eq	1f
+-	sub	vl_remainder, vector_length, tmp2
+-	// process remainder until the first vector_length boundary
+-	whilelt	p2.b, xzr, vl_remainder
+-	st1b	z0.b, p2, [dst]
+-	add	dst, dst, vl_remainder
+-	sub	rest, rest, vl_remainder
+-	// align dstin address at CACHE_LINE_SIZE byte boundary
+-1:	mov	tmp1, CACHE_LINE_SIZE
+-	ands	tmp2, dst, CACHE_LINE_SIZE - 1
+-	// if cl_remainder == 0
+-	b.eq	L(L2_dc_zva)
+-	sub	cl_remainder, tmp1, tmp2
+-	// process remainder until the first CACHE_LINE_SIZE boundary
+-	mov	tmp1, xzr       // index
+-2:	whilelt	p2.b, tmp1, cl_remainder
+-	st1b	z0.b, p2, [dst, tmp1]
+-	incb	tmp1
+-	cmp	tmp1, cl_remainder
+-	b.lo	2b
+-	add	dst, dst, cl_remainder
+-	sub	rest, rest, cl_remainder
+-
+-L(L2_dc_zva):
+-	// zero fill
+-	mov	tmp1, dst
+-	dc_zva	(ZF_DIST / CACHE_LINE_SIZE) - 1
+-	mov	zva_len, ZF_DIST
+-	add	tmp1, zva_len, CACHE_LINE_SIZE * 2
+-	// unroll
++	// count >= L2_SIZE
+ 	.p2align 3
+-1:	st1b_unroll 0, 3
+-	add	tmp2, dst, zva_len
+-	dc	 zva, tmp2
+-	st1b_unroll 4, 7
+-	add	tmp2, tmp2, CACHE_LINE_SIZE
+-	dc	zva, tmp2
+-	add	dst, dst, CACHE_LINE_SIZE * 2
+-	sub	rest, rest, CACHE_LINE_SIZE * 2
+-	cmp	rest, tmp1	// ZF_DIST + CACHE_LINE_SIZE * 2
+-	b.ge	1b
+-	cbnz	rest, L(unroll8)
+-	ret
++L(L2):
++	tst	valw, 255
++	b.ne	L(unroll8)
++        // align dst to CACHE_LINE_SIZE byte boundary
++	and	tmp2, dst, CACHE_LINE_SIZE - 1
++	st1b	z0.b, p0, [dst, 0, mul vl]
++	st1b	z0.b, p0, [dst, 1, mul vl]
++	st1b	z0.b, p0, [dst, 2, mul vl]
++	st1b	z0.b, p0, [dst, 3, mul vl]
++	sub	dst, dst, tmp2
++	add	count, count, tmp2
++
++	// clear cachelines using DC ZVA
++	sub	count, count, CACHE_LINE_SIZE * 2
++	.p2align 4
++1:	add	dst, dst, CACHE_LINE_SIZE
++	dc	zva, dst
++	subs	count, count, CACHE_LINE_SIZE
++	b.hi	1b
++	add	count, count, CACHE_LINE_SIZE
++	add	dst, dst, CACHE_LINE_SIZE
++	b	L(last)
+ 
+ END (MEMSET)
+ libc_hidden_builtin_def (MEMSET)
+-- 
+2.31.1
+
diff --git a/SOURCES/glibc-rh2037416-3.patch b/SOURCES/glibc-rh2037416-3.patch
new file mode 100644
index 0000000..3ac7aa2
--- /dev/null
+++ b/SOURCES/glibc-rh2037416-3.patch
@@ -0,0 +1,80 @@
+From 186092c6ba8825598ffdbf15dbf0823c771f560d Mon Sep 17 00:00:00 2001
+From: Wilco Dijkstra <wdijkstr@arm.com>
+Date: Tue, 10 Aug 2021 13:42:07 +0100
+Subject: [PATCH] [3/5] AArch64: Improve A64FX memset for remaining bytes
+
+Simplify handling of remaining bytes. Avoid lots of taken branches and complex
+whilelo computations, instead unconditionally write vectors from the end.
+
+Reviewed-by: Naohiro Tamura <naohirot@fujitsu.com>
+---
+ sysdeps/aarch64/multiarch/memset_a64fx.S | 46 +++++++-----------------
+ 1 file changed, 13 insertions(+), 33 deletions(-)
+
+diff --git a/sysdeps/aarch64/multiarch/memset_a64fx.S b/sysdeps/aarch64/multiarch/memset_a64fx.S
+index 75cf43ae79..337c86be6f 100644
+--- a/sysdeps/aarch64/multiarch/memset_a64fx.S
++++ b/sysdeps/aarch64/multiarch/memset_a64fx.S
+@@ -130,38 +130,19 @@ L(unroll8):
+ 	b	1b
+ 
+ L(last):
+-	whilelo	p0.b, xzr, rest
+-	whilelo	p1.b, vector_length, rest
+-	b.last	1f
+-	st1b	z0.b, p0, [dst, #0, mul vl]
+-	st1b	z0.b, p1, [dst, #1, mul vl]
+-	ret
+-1:	lsl	tmp1, vector_length, 1	// vector_length * 2
+-	whilelo	p2.b, tmp1, rest
+-	incb	tmp1
+-	whilelo	p3.b, tmp1, rest
+-	b.last	1f
+-	st1b	z0.b, p0, [dst, #0, mul vl]
+-	st1b	z0.b, p1, [dst, #1, mul vl]
+-	st1b	z0.b, p2, [dst, #2, mul vl]
+-	st1b	z0.b, p3, [dst, #3, mul vl]
+-	ret
+-1:	lsl	tmp1, vector_length, 2	// vector_length * 4
+-	whilelo	p4.b, tmp1, rest
+-	incb	tmp1
+-	whilelo	p5.b, tmp1, rest
+-	incb	tmp1
+-	whilelo	p6.b, tmp1, rest
+-	incb	tmp1
+-	whilelo	p7.b, tmp1, rest
+-	st1b	z0.b, p0, [dst, #0, mul vl]
+-	st1b	z0.b, p1, [dst, #1, mul vl]
+-	st1b	z0.b, p2, [dst, #2, mul vl]
+-	st1b	z0.b, p3, [dst, #3, mul vl]
+-	st1b	z0.b, p4, [dst, #4, mul vl]
+-	st1b	z0.b, p5, [dst, #5, mul vl]
+-	st1b	z0.b, p6, [dst, #6, mul vl]
+-	st1b	z0.b, p7, [dst, #7, mul vl]
++	cmp	count, vector_length, lsl 1
++	b.ls	2f
++	add	tmp2, vector_length, vector_length, lsl 2
++	cmp	count, tmp2
++	b.ls	5f
++	st1b	z0.b, p0, [dstend, -8, mul vl]
++	st1b	z0.b, p0, [dstend, -7, mul vl]
++	st1b	z0.b, p0, [dstend, -6, mul vl]
++5:	st1b	z0.b, p0, [dstend, -5, mul vl]
++	st1b	z0.b, p0, [dstend, -4, mul vl]
++	st1b	z0.b, p0, [dstend, -3, mul vl]
++2:	st1b	z0.b, p0, [dstend, -2, mul vl]
++	st1b	z0.b, p0, [dstend, -1, mul vl]
+ 	ret
+ 
+ L(L1_prefetch): // if rest >= L1_SIZE
+@@ -199,7 +180,6 @@ L(L2):
+ 	subs	count, count, CACHE_LINE_SIZE
+ 	b.hi	1b
+ 	add	count, count, CACHE_LINE_SIZE
+-	add	dst, dst, CACHE_LINE_SIZE
+ 	b	L(last)
+ 
+ END (MEMSET)
+-- 
+2.31.1
+
diff --git a/SOURCES/glibc-rh2037416-4.patch b/SOURCES/glibc-rh2037416-4.patch
new file mode 100644
index 0000000..e057eeb
--- /dev/null
+++ b/SOURCES/glibc-rh2037416-4.patch
@@ -0,0 +1,51 @@
+From e69d9981f858a38e19304e6ff5ebdf89f2cb0ba0 Mon Sep 17 00:00:00 2001
+From: Wilco Dijkstra <wdijkstr@arm.com>
+Date: Tue, 10 Aug 2021 13:44:27 +0100
+Subject: [PATCH] [4/5] AArch64: Improve A64FX memset by removing unroll32
+
+Remove unroll32 code since it doesn't improve performance.
+
+Reviewed-by: Naohiro Tamura <naohirot@fujitsu.com>
+---
+ sysdeps/aarch64/multiarch/memset_a64fx.S | 18 +-----------------
+ 1 file changed, 1 insertion(+), 17 deletions(-)
+
+diff --git a/sysdeps/aarch64/multiarch/memset_a64fx.S b/sysdeps/aarch64/multiarch/memset_a64fx.S
+index 337c86be6f..ef0315658a 100644
+--- a/sysdeps/aarch64/multiarch/memset_a64fx.S
++++ b/sysdeps/aarch64/multiarch/memset_a64fx.S
+@@ -102,22 +102,6 @@ L(vl_agnostic): // VL Agnostic
+ 	ccmp	vector_length, tmp1, 0, cs
+ 	b.eq	L(L1_prefetch)
+ 
+-L(unroll32):
+-	lsl	tmp1, vector_length, 3	// vector_length * 8
+-	lsl	tmp2, vector_length, 5	// vector_length * 32
+-	.p2align 3
+-1:	cmp	rest, tmp2
+-	b.cc	L(unroll8)
+-	st1b_unroll
+-	add	dst, dst, tmp1
+-	st1b_unroll
+-	add	dst, dst, tmp1
+-	st1b_unroll
+-	add	dst, dst, tmp1
+-	st1b_unroll
+-	add	dst, dst, tmp1
+-	sub	rest, rest, tmp2
+-	b	1b
+ 
+ L(unroll8):
+ 	lsl	tmp1, vector_length, 3
+@@ -155,7 +139,7 @@ L(L1_prefetch): // if rest >= L1_SIZE
+ 	sub	rest, rest, CACHE_LINE_SIZE * 2
+ 	cmp	rest, L1_SIZE
+ 	b.ge	1b
+-	cbnz	rest, L(unroll32)
++	cbnz	rest, L(unroll8)
+ 	ret
+ 
+ 	// count >= L2_SIZE
+-- 
+2.31.1
+
diff --git a/SOURCES/glibc-rh2037416-5.patch b/SOURCES/glibc-rh2037416-5.patch
new file mode 100644
index 0000000..c92c2cf
--- /dev/null
+++ b/SOURCES/glibc-rh2037416-5.patch
@@ -0,0 +1,96 @@
+From a5db6a5cae6a92d1675c013e5c8d972768721576 Mon Sep 17 00:00:00 2001
+From: Wilco Dijkstra <wdijkstr@arm.com>
+Date: Tue, 10 Aug 2021 13:46:20 +0100
+Subject: [PATCH] [5/5] AArch64: Improve A64FX memset medium loops
+
+Simplify the code for memsets smaller than L1. Improve the unroll8 and
+L1_prefetch loops.
+
+Reviewed-by: Naohiro Tamura <naohirot@fujitsu.com>
+---
+ sysdeps/aarch64/multiarch/memset_a64fx.S | 45 ++++++++++--------------
+ 1 file changed, 19 insertions(+), 26 deletions(-)
+
+diff --git a/sysdeps/aarch64/multiarch/memset_a64fx.S b/sysdeps/aarch64/multiarch/memset_a64fx.S
+index ef0315658a..7bf759b6a7 100644
+--- a/sysdeps/aarch64/multiarch/memset_a64fx.S
++++ b/sysdeps/aarch64/multiarch/memset_a64fx.S
+@@ -30,7 +30,6 @@
+ #define L2_SIZE         (8*1024*1024)	// L2 8MB
+ #define CACHE_LINE_SIZE	256
+ #define PF_DIST_L1	(CACHE_LINE_SIZE * 16)	// Prefetch distance L1
+-#define rest		x2
+ #define vector_length	x9
+ 
+ #if HAVE_AARCH64_SVE_ASM
+@@ -89,29 +88,19 @@ ENTRY (MEMSET)
+ 
+ 	.p2align 4
+ L(vl_agnostic): // VL Agnostic
+-	mov	rest, count
+ 	mov	dst, dstin
+-	add	dstend, dstin, count
+-	// if rest >= L2_SIZE && vector_length == 64 then L(L2)
+-	mov	tmp1, 64
+-	cmp	rest, L2_SIZE
+-	ccmp	vector_length, tmp1, 0, cs
+-	b.eq	L(L2)
+-	// if rest >= L1_SIZE && vector_length == 64 then L(L1_prefetch)
+-	cmp	rest, L1_SIZE
+-	ccmp	vector_length, tmp1, 0, cs
+-	b.eq	L(L1_prefetch)
+-
++	cmp	count, L1_SIZE
++	b.hi	L(L1_prefetch)
+ 
++	// count >= 8 * vector_length
+ L(unroll8):
+-	lsl	tmp1, vector_length, 3
+-	.p2align 3
+-1:	cmp	rest, tmp1
+-	b.cc	L(last)
+-	st1b_unroll
++	sub	count, count, tmp1
++	.p2align 4
++1:	st1b_unroll 0, 7
+ 	add	dst, dst, tmp1
+-	sub	rest, rest, tmp1
+-	b	1b
++	subs	count, count, tmp1
++	b.hi	1b
++	add	count, count, tmp1
+ 
+ L(last):
+ 	cmp	count, vector_length, lsl 1
+@@ -129,18 +118,22 @@ L(last):
+ 	st1b	z0.b, p0, [dstend, -1, mul vl]
+ 	ret
+ 
+-L(L1_prefetch): // if rest >= L1_SIZE
++	// count >= L1_SIZE
+ 	.p2align 3
++L(L1_prefetch):
++	cmp	count, L2_SIZE
++	b.hs	L(L2)
++	cmp	vector_length, 64
++	b.ne	L(unroll8)
+ 1:	st1b_unroll 0, 3
+ 	prfm	pstl1keep, [dst, PF_DIST_L1]
+ 	st1b_unroll 4, 7
+ 	prfm	pstl1keep, [dst, PF_DIST_L1 + CACHE_LINE_SIZE]
+ 	add	dst, dst, CACHE_LINE_SIZE * 2
+-	sub	rest, rest, CACHE_LINE_SIZE * 2
+-	cmp	rest, L1_SIZE
+-	b.ge	1b
+-	cbnz	rest, L(unroll8)
+-	ret
++	sub	count, count, CACHE_LINE_SIZE * 2
++	cmp	count, PF_DIST_L1
++	b.hs	1b
++	b	L(unroll8)
+ 
+ 	// count >= L2_SIZE
+ 	.p2align 3
+-- 
+2.31.1
+
diff --git a/SOURCES/glibc-rh2037416-6.patch b/SOURCES/glibc-rh2037416-6.patch
new file mode 100644
index 0000000..b2522ad
--- /dev/null
+++ b/SOURCES/glibc-rh2037416-6.patch
@@ -0,0 +1,39 @@
+From 1d9f99ce1b3788d1897cb53a76d57e973111b8fe Mon Sep 17 00:00:00 2001
+From: Naohiro Tamura <naohirot@fujitsu.com>
+Date: Fri, 27 Aug 2021 05:03:04 +0000
+Subject: [PATCH] AArch64: Update A64FX memset not to degrade at 16KB
+
+This patch updates unroll8 code so as not to degrade at the peak
+performance 16KB for both FX1000 and FX700.
+
+Inserted 2 instructions at the beginning of the unroll8 loop,
+cmp and branch, are a workaround that is found heuristically.
+
+Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
+---
+ sysdeps/aarch64/multiarch/memset_a64fx.S | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/sysdeps/aarch64/multiarch/memset_a64fx.S b/sysdeps/aarch64/multiarch/memset_a64fx.S
+index 7bf759b6a7..f7dfdaace7 100644
+--- a/sysdeps/aarch64/multiarch/memset_a64fx.S
++++ b/sysdeps/aarch64/multiarch/memset_a64fx.S
+@@ -96,7 +96,14 @@ L(vl_agnostic): // VL Agnostic
+ L(unroll8):
+ 	sub	count, count, tmp1
+ 	.p2align 4
+-1:	st1b_unroll 0, 7
++	// The 2 instructions at the beginning of the following loop,
++	// cmp and branch, are a workaround so as not to degrade at
++	// the peak performance 16KB.
++	// It is found heuristically and the branch condition, b.ne,
++	// is chosen intentionally never to jump.
++1:	cmp	xzr, xzr
++	b.ne	1b
++	st1b_unroll 0, 7
+ 	add	dst, dst, tmp1
+ 	subs	count, count, tmp1
+ 	b.hi	1b
+-- 
+2.31.1
+
diff --git a/SOURCES/glibc-rh2037416-7.patch b/SOURCES/glibc-rh2037416-7.patch
new file mode 100644
index 0000000..e57fef7
--- /dev/null
+++ b/SOURCES/glibc-rh2037416-7.patch
@@ -0,0 +1,32 @@
+From 381b29616abb82babc8163bdf516c6da87544b35 Mon Sep 17 00:00:00 2001
+From: Naohiro Tamura <naohirot@fujitsu.com>
+Date: Fri, 24 Sep 2021 07:49:59 +0000
+Subject: [PATCH] aarch64: Disable A64FX memcpy/memmove BTI unconditionally
+
+This patch disables A64FX memcpy/memmove BTI instruction insertion
+unconditionally such as A64FX memset patch [1] for performance.
+
+[1] commit 07b427296b8d59f439144029d9a948f6c1ce0a31
+
+Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
+---
+ sysdeps/aarch64/multiarch/memcpy_a64fx.S | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/sysdeps/aarch64/multiarch/memcpy_a64fx.S b/sysdeps/aarch64/multiarch/memcpy_a64fx.S
+index 65528405bb..ae7464e09f 100644
+--- a/sysdeps/aarch64/multiarch/memcpy_a64fx.S
++++ b/sysdeps/aarch64/multiarch/memcpy_a64fx.S
+@@ -19,6 +19,9 @@
+ 
+ #include <sysdep.h>
+ 
++#undef BTI_C
++#define BTI_C
++
+ /* Assumptions:
+  *
+  * ARMv8.2-a, AArch64, unaligned accesses, sve
+-- 
+2.31.1
+
diff --git a/SOURCES/glibc-rh2037416-8.patch b/SOURCES/glibc-rh2037416-8.patch
new file mode 100644
index 0000000..6a68332
--- /dev/null
+++ b/SOURCES/glibc-rh2037416-8.patch
@@ -0,0 +1,630 @@
+From b31bd11454fade731e5158b1aea40b133ae19926 Mon Sep 17 00:00:00 2001
+From: Wilco Dijkstra <wdijkstr@arm.com>
+Date: Thu, 2 Dec 2021 18:33:26 +0000
+Subject: [PATCH] AArch64: Improve A64FX memcpy
+
+v2 is a complete rewrite of the A64FX memcpy. Performance is improved
+by streamlining the code, aligning all large copies and using a single
+unrolled loop for all sizes. The code size for memcpy and memmove goes
+down from 1796 bytes to 868 bytes. Performance is better in all cases:
+bench-memcpy-random is 2.3% faster overall, bench-memcpy-large is ~33%
+faster for large sizes, bench-memcpy-walk is 25% faster for small sizes
+and 20% for the largest sizes. The geomean of all tests in bench-memcpy
+is 5.1% faster, and total time is reduced by 4%.
+
+Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
+---
+ sysdeps/aarch64/multiarch/memcpy_a64fx.S | 546 ++++++++++-------------
+ 1 file changed, 225 insertions(+), 321 deletions(-)
+
+diff --git a/sysdeps/aarch64/multiarch/memcpy_a64fx.S b/sysdeps/aarch64/multiarch/memcpy_a64fx.S
+index ae7464e09f..0b306925e6 100644
+--- a/sysdeps/aarch64/multiarch/memcpy_a64fx.S
++++ b/sysdeps/aarch64/multiarch/memcpy_a64fx.S
+@@ -28,20 +28,15 @@
+  *
+  */
+ 
+-#define L2_SIZE		(8*1024*1024)/2	// L2 8MB/2
+-#define CACHE_LINE_SIZE	256
+-#define ZF_DIST		(CACHE_LINE_SIZE * 21)	// Zerofill distance
+-#define dest		x0
+-#define src		x1
+-#define n		x2	// size
+-#define tmp1		x3
+-#define tmp2		x4
+-#define tmp3		x5
+-#define rest		x6
+-#define dest_ptr	x7
+-#define src_ptr		x8
+-#define vector_length	x9
+-#define cl_remainder	x10	// CACHE_LINE_SIZE remainder
++#define dstin	x0
++#define src	x1
++#define n	x2
++#define dst	x3
++#define dstend	x4
++#define srcend	x5
++#define tmp	x6
++#define vlen	x7
++#define vlen8	x8
+ 
+ #if HAVE_AARCH64_SVE_ASM
+ # if IS_IN (libc)
+@@ -50,45 +45,37 @@
+ 
+ 	.arch armv8.2-a+sve
+ 
+-	.macro dc_zva times
+-	dc	zva, tmp1
+-	add	tmp1, tmp1, CACHE_LINE_SIZE
+-	.if \times-1
+-	dc_zva "(\times-1)"
+-	.endif
+-	.endm
+-
+ 	.macro ld1b_unroll8
+-	ld1b	z0.b, p0/z, [src_ptr, #0, mul vl]
+-	ld1b	z1.b, p0/z, [src_ptr, #1, mul vl]
+-	ld1b	z2.b, p0/z, [src_ptr, #2, mul vl]
+-	ld1b	z3.b, p0/z, [src_ptr, #3, mul vl]
+-	ld1b	z4.b, p0/z, [src_ptr, #4, mul vl]
+-	ld1b	z5.b, p0/z, [src_ptr, #5, mul vl]
+-	ld1b	z6.b, p0/z, [src_ptr, #6, mul vl]
+-	ld1b	z7.b, p0/z, [src_ptr, #7, mul vl]
++	ld1b	z0.b, p0/z, [src, 0, mul vl]
++	ld1b	z1.b, p0/z, [src, 1, mul vl]
++	ld1b	z2.b, p0/z, [src, 2, mul vl]
++	ld1b	z3.b, p0/z, [src, 3, mul vl]
++	ld1b	z4.b, p0/z, [src, 4, mul vl]
++	ld1b	z5.b, p0/z, [src, 5, mul vl]
++	ld1b	z6.b, p0/z, [src, 6, mul vl]
++	ld1b	z7.b, p0/z, [src, 7, mul vl]
+ 	.endm
+ 
+ 	.macro stld1b_unroll4a
+-	st1b	z0.b, p0,   [dest_ptr, #0, mul vl]
+-	st1b	z1.b, p0,   [dest_ptr, #1, mul vl]
+-	ld1b	z0.b, p0/z, [src_ptr,  #0, mul vl]
+-	ld1b	z1.b, p0/z, [src_ptr,  #1, mul vl]
+-	st1b	z2.b, p0,   [dest_ptr, #2, mul vl]
+-	st1b	z3.b, p0,   [dest_ptr, #3, mul vl]
+-	ld1b	z2.b, p0/z, [src_ptr,  #2, mul vl]
+-	ld1b	z3.b, p0/z, [src_ptr,  #3, mul vl]
++	st1b	z0.b, p0,   [dst, 0, mul vl]
++	st1b	z1.b, p0,   [dst, 1, mul vl]
++	ld1b	z0.b, p0/z, [src, 0, mul vl]
++	ld1b	z1.b, p0/z, [src, 1, mul vl]
++	st1b	z2.b, p0,   [dst, 2, mul vl]
++	st1b	z3.b, p0,   [dst, 3, mul vl]
++	ld1b	z2.b, p0/z, [src, 2, mul vl]
++	ld1b	z3.b, p0/z, [src, 3, mul vl]
+ 	.endm
+ 
+ 	.macro stld1b_unroll4b
+-	st1b	z4.b, p0,   [dest_ptr, #4, mul vl]
+-	st1b	z5.b, p0,   [dest_ptr, #5, mul vl]
+-	ld1b	z4.b, p0/z, [src_ptr,  #4, mul vl]
+-	ld1b	z5.b, p0/z, [src_ptr,  #5, mul vl]
+-	st1b	z6.b, p0,   [dest_ptr, #6, mul vl]
+-	st1b	z7.b, p0,   [dest_ptr, #7, mul vl]
+-	ld1b	z6.b, p0/z, [src_ptr,  #6, mul vl]
+-	ld1b	z7.b, p0/z, [src_ptr,  #7, mul vl]
++	st1b	z4.b, p0,   [dst, 4, mul vl]
++	st1b	z5.b, p0,   [dst, 5, mul vl]
++	ld1b	z4.b, p0/z, [src, 4, mul vl]
++	ld1b	z5.b, p0/z, [src, 5, mul vl]
++	st1b	z6.b, p0,   [dst, 6, mul vl]
++	st1b	z7.b, p0,   [dst, 7, mul vl]
++	ld1b	z6.b, p0/z, [src, 6, mul vl]
++	ld1b	z7.b, p0/z, [src, 7, mul vl]
+ 	.endm
+ 
+ 	.macro stld1b_unroll8
+@@ -97,87 +84,18 @@
+ 	.endm
+ 
+ 	.macro st1b_unroll8
+-	st1b	z0.b, p0, [dest_ptr, #0, mul vl]
+-	st1b	z1.b, p0, [dest_ptr, #1, mul vl]
+-	st1b	z2.b, p0, [dest_ptr, #2, mul vl]
+-	st1b	z3.b, p0, [dest_ptr, #3, mul vl]
+-	st1b	z4.b, p0, [dest_ptr, #4, mul vl]
+-	st1b	z5.b, p0, [dest_ptr, #5, mul vl]
+-	st1b	z6.b, p0, [dest_ptr, #6, mul vl]
+-	st1b	z7.b, p0, [dest_ptr, #7, mul vl]
++	st1b	z0.b, p0, [dst, 0, mul vl]
++	st1b	z1.b, p0, [dst, 1, mul vl]
++	st1b	z2.b, p0, [dst, 2, mul vl]
++	st1b	z3.b, p0, [dst, 3, mul vl]
++	st1b	z4.b, p0, [dst, 4, mul vl]
++	st1b	z5.b, p0, [dst, 5, mul vl]
++	st1b	z6.b, p0, [dst, 6, mul vl]
++	st1b	z7.b, p0, [dst, 7, mul vl]
+ 	.endm
+ 
+-	.macro shortcut_for_small_size exit
+-	// if rest <= vector_length * 2
+-	whilelo	p0.b, xzr, n
+-	whilelo	p1.b, vector_length, n
+-	b.last	1f
+-	ld1b	z0.b, p0/z, [src, #0, mul vl]
+-	ld1b	z1.b, p1/z, [src, #1, mul vl]
+-	st1b	z0.b, p0, [dest, #0, mul vl]
+-	st1b	z1.b, p1, [dest, #1, mul vl]
+-	ret
+-1:	// if rest > vector_length * 8
+-	cmp	n, vector_length, lsl 3 // vector_length * 8
+-	b.hi	\exit
+-	// if rest <= vector_length * 4
+-	lsl	tmp1, vector_length, 1  // vector_length * 2
+-	whilelo	p2.b, tmp1, n
+-	incb	tmp1
+-	whilelo	p3.b, tmp1, n
+-	b.last	1f
+-	ld1b	z0.b, p0/z, [src, #0, mul vl]
+-	ld1b	z1.b, p1/z, [src, #1, mul vl]
+-	ld1b	z2.b, p2/z, [src, #2, mul vl]
+-	ld1b	z3.b, p3/z, [src, #3, mul vl]
+-	st1b	z0.b, p0, [dest, #0, mul vl]
+-	st1b	z1.b, p1, [dest, #1, mul vl]
+-	st1b	z2.b, p2, [dest, #2, mul vl]
+-	st1b	z3.b, p3, [dest, #3, mul vl]
+-	ret
+-1:	// if rest <= vector_length * 8
+-	lsl	tmp1, vector_length, 2  // vector_length * 4
+-	whilelo	p4.b, tmp1, n
+-	incb	tmp1
+-	whilelo	p5.b, tmp1, n
+-	b.last	1f
+-	ld1b	z0.b, p0/z, [src, #0, mul vl]
+-	ld1b	z1.b, p1/z, [src, #1, mul vl]
+-	ld1b	z2.b, p2/z, [src, #2, mul vl]
+-	ld1b	z3.b, p3/z, [src, #3, mul vl]
+-	ld1b	z4.b, p4/z, [src, #4, mul vl]
+-	ld1b	z5.b, p5/z, [src, #5, mul vl]
+-	st1b	z0.b, p0, [dest, #0, mul vl]
+-	st1b	z1.b, p1, [dest, #1, mul vl]
+-	st1b	z2.b, p2, [dest, #2, mul vl]
+-	st1b	z3.b, p3, [dest, #3, mul vl]
+-	st1b	z4.b, p4, [dest, #4, mul vl]
+-	st1b	z5.b, p5, [dest, #5, mul vl]
+-	ret
+-1:	lsl	tmp1, vector_length, 2	// vector_length * 4
+-	incb	tmp1			// vector_length * 5
+-	incb	tmp1			// vector_length * 6
+-	whilelo	p6.b, tmp1, n
+-	incb	tmp1
+-	whilelo	p7.b, tmp1, n
+-	ld1b	z0.b, p0/z, [src, #0, mul vl]
+-	ld1b	z1.b, p1/z, [src, #1, mul vl]
+-	ld1b	z2.b, p2/z, [src, #2, mul vl]
+-	ld1b	z3.b, p3/z, [src, #3, mul vl]
+-	ld1b	z4.b, p4/z, [src, #4, mul vl]
+-	ld1b	z5.b, p5/z, [src, #5, mul vl]
+-	ld1b	z6.b, p6/z, [src, #6, mul vl]
+-	ld1b	z7.b, p7/z, [src, #7, mul vl]
+-	st1b	z0.b, p0, [dest, #0, mul vl]
+-	st1b	z1.b, p1, [dest, #1, mul vl]
+-	st1b	z2.b, p2, [dest, #2, mul vl]
+-	st1b	z3.b, p3, [dest, #3, mul vl]
+-	st1b	z4.b, p4, [dest, #4, mul vl]
+-	st1b	z5.b, p5, [dest, #5, mul vl]
+-	st1b	z6.b, p6, [dest, #6, mul vl]
+-	st1b	z7.b, p7, [dest, #7, mul vl]
+-	ret
+-	.endm
++#undef BTI_C
++#define BTI_C
+ 
+ ENTRY (MEMCPY)
+ 
+@@ -185,223 +103,209 @@ ENTRY (MEMCPY)
+ 	PTR_ARG (1)
+ 	SIZE_ARG (2)
+ 
+-L(memcpy):
+-	cntb	vector_length
+-	// shortcut for less than vector_length * 8
+-	// gives a free ptrue to p0.b for n >= vector_length
+-	shortcut_for_small_size L(vl_agnostic)
+-	// end of shortcut
+-
+-L(vl_agnostic): // VL Agnostic
+-	mov	rest, n
+-	mov	dest_ptr, dest
+-	mov	src_ptr, src
+-	// if rest >= L2_SIZE && vector_length == 64 then L(L2)
+-	mov	tmp1, 64
+-	cmp	rest, L2_SIZE
+-	ccmp	vector_length, tmp1, 0, cs
+-	b.eq	L(L2)
+-
+-L(unroll8): // unrolling and software pipeline
+-	lsl	tmp1, vector_length, 3	// vector_length * 8
+-	.p2align 3
+-	cmp	 rest, tmp1
+-	b.cc	L(last)
++	cntb	vlen
++	cmp	n, vlen, lsl 1
++	b.hi	L(copy_small)
++	whilelo	p1.b, vlen, n
++	whilelo	p0.b, xzr, n
++	ld1b	z0.b, p0/z, [src, 0, mul vl]
++	ld1b	z1.b, p1/z, [src, 1, mul vl]
++	st1b	z0.b, p0, [dstin, 0, mul vl]
++	st1b	z1.b, p1, [dstin, 1, mul vl]
++	ret
++
++	.p2align 4
++
++L(copy_small):
++	cmp	n, vlen, lsl 3
++	b.hi	L(copy_large)
++	add	dstend, dstin, n
++	add	srcend, src, n
++	cmp	n, vlen, lsl 2
++	b.hi	1f
++
++	/* Copy 2-4 vectors.  */
++	ptrue	p0.b
++	ld1b	z0.b, p0/z, [src, 0, mul vl]
++	ld1b	z1.b, p0/z, [src, 1, mul vl]
++	ld1b	z2.b, p0/z, [srcend, -2, mul vl]
++	ld1b	z3.b, p0/z, [srcend, -1, mul vl]
++	st1b	z0.b, p0, [dstin, 0, mul vl]
++	st1b	z1.b, p0, [dstin, 1, mul vl]
++	st1b	z2.b, p0, [dstend, -2, mul vl]
++	st1b	z3.b, p0, [dstend, -1, mul vl]
++	ret
++
++	.p2align 4
++	/* Copy 4-8 vectors.  */
++1:	ptrue	p0.b
++	ld1b	z0.b, p0/z, [src, 0, mul vl]
++	ld1b	z1.b, p0/z, [src, 1, mul vl]
++	ld1b	z2.b, p0/z, [src, 2, mul vl]
++	ld1b	z3.b, p0/z, [src, 3, mul vl]
++	ld1b	z4.b, p0/z, [srcend, -4, mul vl]
++	ld1b	z5.b, p0/z, [srcend, -3, mul vl]
++	ld1b	z6.b, p0/z, [srcend, -2, mul vl]
++	ld1b	z7.b, p0/z, [srcend, -1, mul vl]
++	st1b	z0.b, p0, [dstin, 0, mul vl]
++	st1b	z1.b, p0, [dstin, 1, mul vl]
++	st1b	z2.b, p0, [dstin, 2, mul vl]
++	st1b	z3.b, p0, [dstin, 3, mul vl]
++	st1b	z4.b, p0, [dstend, -4, mul vl]
++	st1b	z5.b, p0, [dstend, -3, mul vl]
++	st1b	z6.b, p0, [dstend, -2, mul vl]
++	st1b	z7.b, p0, [dstend, -1, mul vl]
++	ret
++
++	.p2align 4
++	/* At least 8 vectors - always align to vector length for
++	   higher and consistent write performance.  */
++L(copy_large):
++	sub	tmp, vlen, 1
++	and	tmp, dstin, tmp
++	sub	tmp, vlen, tmp
++	whilelo	p1.b, xzr, tmp
++	ld1b	z1.b, p1/z, [src]
++	st1b	z1.b, p1, [dstin]
++	add	dst, dstin, tmp
++	add	src, src, tmp
++	sub	n, n, tmp
++	ptrue	p0.b
++
++	lsl	vlen8, vlen, 3
++	subs	n, n, vlen8
++	b.ls	3f
+ 	ld1b_unroll8
+-	add	src_ptr, src_ptr, tmp1
+-	sub	rest, rest, tmp1
+-	cmp	rest, tmp1
+-	b.cc	2f
+-	.p2align 3
++	add	src, src, vlen8
++	subs	n, n, vlen8
++	b.ls	2f
++
++	.p2align 4
++	/* 8x unrolled and software pipelined loop.  */
+ 1:	stld1b_unroll8
+-	add	dest_ptr, dest_ptr, tmp1
+-	add	src_ptr, src_ptr, tmp1
+-	sub	rest, rest, tmp1
+-	cmp	rest, tmp1
+-	b.ge	1b
++	add	dst, dst, vlen8
++	add	src, src, vlen8
++	subs	n, n, vlen8
++	b.hi	1b
+ 2:	st1b_unroll8
+-	add	dest_ptr, dest_ptr, tmp1
+-
+-	.p2align 3
+-L(last):
+-	whilelo	p0.b, xzr, rest
+-	whilelo	p1.b, vector_length, rest
+-	b.last	1f
+-	ld1b	z0.b, p0/z, [src_ptr, #0, mul vl]
+-	ld1b	z1.b, p1/z, [src_ptr, #1, mul vl]
+-	st1b	z0.b, p0, [dest_ptr, #0, mul vl]
+-	st1b	z1.b, p1, [dest_ptr, #1, mul vl]
+-	ret
+-1:	lsl	tmp1, vector_length, 1	// vector_length * 2
+-	whilelo	p2.b, tmp1, rest
+-	incb	tmp1
+-	whilelo	p3.b, tmp1, rest
+-	b.last	1f
+-	ld1b	z0.b, p0/z, [src_ptr, #0, mul vl]
+-	ld1b	z1.b, p1/z, [src_ptr, #1, mul vl]
+-	ld1b	z2.b, p2/z, [src_ptr, #2, mul vl]
+-	ld1b	z3.b, p3/z, [src_ptr, #3, mul vl]
+-	st1b	z0.b, p0, [dest_ptr, #0, mul vl]
+-	st1b	z1.b, p1, [dest_ptr, #1, mul vl]
+-	st1b	z2.b, p2, [dest_ptr, #2, mul vl]
+-	st1b	z3.b, p3, [dest_ptr, #3, mul vl]
++	add	dst, dst, vlen8
++3:	add	n, n, vlen8
++
++	/* Move last 0-8 vectors.  */
++L(last_bytes):
++	cmp	n, vlen, lsl 1
++	b.hi	1f
++	whilelo	p0.b, xzr, n
++	whilelo	p1.b, vlen, n
++	ld1b	z0.b, p0/z, [src, 0, mul vl]
++	ld1b	z1.b, p1/z, [src, 1, mul vl]
++	st1b	z0.b, p0, [dst, 0, mul vl]
++	st1b	z1.b, p1, [dst, 1, mul vl]
+ 	ret
+-1:	lsl	tmp1, vector_length, 2	// vector_length * 4
+-	whilelo	p4.b, tmp1, rest
+-	incb	tmp1
+-	whilelo	p5.b, tmp1, rest
+-	incb	tmp1
+-	whilelo	p6.b, tmp1, rest
+-	incb	tmp1
+-	whilelo	p7.b, tmp1, rest
+-	ld1b	z0.b, p0/z, [src_ptr, #0, mul vl]
+-	ld1b	z1.b, p1/z, [src_ptr, #1, mul vl]
+-	ld1b	z2.b, p2/z, [src_ptr, #2, mul vl]
+-	ld1b	z3.b, p3/z, [src_ptr, #3, mul vl]
+-	ld1b	z4.b, p4/z, [src_ptr, #4, mul vl]
+-	ld1b	z5.b, p5/z, [src_ptr, #5, mul vl]
+-	ld1b	z6.b, p6/z, [src_ptr, #6, mul vl]
+-	ld1b	z7.b, p7/z, [src_ptr, #7, mul vl]
+-	st1b	z0.b, p0, [dest_ptr, #0, mul vl]
+-	st1b	z1.b, p1, [dest_ptr, #1, mul vl]
+-	st1b	z2.b, p2, [dest_ptr, #2, mul vl]
+-	st1b	z3.b, p3, [dest_ptr, #3, mul vl]
+-	st1b	z4.b, p4, [dest_ptr, #4, mul vl]
+-	st1b	z5.b, p5, [dest_ptr, #5, mul vl]
+-	st1b	z6.b, p6, [dest_ptr, #6, mul vl]
+-	st1b	z7.b, p7, [dest_ptr, #7, mul vl]
++
++	.p2align 4
++
++1:	add	srcend, src, n
++	add	dstend, dst, n
++	ld1b	z0.b, p0/z, [src, 0, mul vl]
++	ld1b	z1.b, p0/z, [src, 1, mul vl]
++	ld1b	z2.b, p0/z, [srcend, -2, mul vl]
++	ld1b	z3.b, p0/z, [srcend, -1, mul vl]
++	cmp	n, vlen, lsl 2
++	b.hi	1f
++
++	st1b	z0.b, p0, [dst, 0, mul vl]
++	st1b	z1.b, p0, [dst, 1, mul vl]
++	st1b	z2.b, p0, [dstend, -2, mul vl]
++	st1b	z3.b, p0, [dstend, -1, mul vl]
+ 	ret
+ 
+-L(L2):
+-	// align dest address at CACHE_LINE_SIZE byte boundary
+-	mov	tmp1, CACHE_LINE_SIZE
+-	ands	tmp2, dest_ptr, CACHE_LINE_SIZE - 1
+-	// if cl_remainder == 0
+-	b.eq	L(L2_dc_zva)
+-	sub	cl_remainder, tmp1, tmp2
+-	// process remainder until the first CACHE_LINE_SIZE boundary
+-	whilelo	p1.b, xzr, cl_remainder	// keep p0.b all true
+-	whilelo	p2.b, vector_length, cl_remainder
+-	b.last	1f
+-	ld1b	z1.b, p1/z, [src_ptr, #0, mul vl]
+-	ld1b	z2.b, p2/z, [src_ptr, #1, mul vl]
+-	st1b	z1.b, p1, [dest_ptr, #0, mul vl]
+-	st1b	z2.b, p2, [dest_ptr, #1, mul vl]
+-	b	2f
+-1:	lsl	tmp1, vector_length, 1	// vector_length * 2
+-	whilelo	p3.b, tmp1, cl_remainder
+-	incb	tmp1
+-	whilelo	p4.b, tmp1, cl_remainder
+-	ld1b	z1.b, p1/z, [src_ptr, #0, mul vl]
+-	ld1b	z2.b, p2/z, [src_ptr, #1, mul vl]
+-	ld1b	z3.b, p3/z, [src_ptr, #2, mul vl]
+-	ld1b	z4.b, p4/z, [src_ptr, #3, mul vl]
+-	st1b	z1.b, p1, [dest_ptr, #0, mul vl]
+-	st1b	z2.b, p2, [dest_ptr, #1, mul vl]
+-	st1b	z3.b, p3, [dest_ptr, #2, mul vl]
+-	st1b	z4.b, p4, [dest_ptr, #3, mul vl]
+-2:	add	dest_ptr, dest_ptr, cl_remainder
+-	add	src_ptr, src_ptr, cl_remainder
+-	sub	rest, rest, cl_remainder
+-
+-L(L2_dc_zva):
+-	// zero fill
+-	and	tmp1, dest, 0xffffffffffffff
+-	and	tmp2, src, 0xffffffffffffff
+-	subs	tmp1, tmp1, tmp2	// diff
+-	b.ge	1f
+-	neg	tmp1, tmp1
+-1:	mov	tmp3, ZF_DIST + CACHE_LINE_SIZE * 2
+-	cmp	tmp1, tmp3
+-	b.lo	L(unroll8)
+-	mov	tmp1, dest_ptr
+-	dc_zva	(ZF_DIST / CACHE_LINE_SIZE) - 1
+-	// unroll
+-	ld1b_unroll8	// this line has to be after "b.lo L(unroll8)"
+-	add	 src_ptr, src_ptr, CACHE_LINE_SIZE * 2
+-	sub	 rest, rest, CACHE_LINE_SIZE * 2
+-	mov	 tmp1, ZF_DIST
+-	.p2align 3
+-1:	stld1b_unroll4a
+-	add	tmp2, dest_ptr, tmp1	// dest_ptr + ZF_DIST
+-	dc	zva, tmp2
+-	stld1b_unroll4b
+-	add	tmp2, tmp2, CACHE_LINE_SIZE
+-	dc	zva, tmp2
+-	add	dest_ptr, dest_ptr, CACHE_LINE_SIZE * 2
+-	add	src_ptr, src_ptr, CACHE_LINE_SIZE * 2
+-	sub	rest, rest, CACHE_LINE_SIZE * 2
+-	cmp	rest, tmp3	// ZF_DIST + CACHE_LINE_SIZE * 2
+-	b.ge	1b
+-	st1b_unroll8
+-	add	dest_ptr, dest_ptr, CACHE_LINE_SIZE * 2
+-	b	L(unroll8)
++1:	ld1b	z4.b, p0/z, [src, 2, mul vl]
++	ld1b	z5.b, p0/z, [src, 3, mul vl]
++	ld1b	z6.b, p0/z, [srcend, -4, mul vl]
++	ld1b	z7.b, p0/z, [srcend, -3, mul vl]
++	st1b	z0.b, p0, [dst, 0, mul vl]
++	st1b	z1.b, p0, [dst, 1, mul vl]
++	st1b	z4.b, p0, [dst, 2, mul vl]
++	st1b	z5.b, p0, [dst, 3, mul vl]
++	st1b	z6.b, p0, [dstend, -4, mul vl]
++	st1b	z7.b, p0, [dstend, -3, mul vl]
++	st1b	z2.b, p0, [dstend, -2, mul vl]
++	st1b	z3.b, p0, [dstend, -1, mul vl]
++	ret
+ 
+ END (MEMCPY)
+ libc_hidden_builtin_def (MEMCPY)
+ 
+ 
+-ENTRY (MEMMOVE)
++ENTRY_ALIGN (MEMMOVE, 4)
+ 
+ 	PTR_ARG (0)
+ 	PTR_ARG (1)
+ 	SIZE_ARG (2)
+ 
+-	// remove tag address
+-	// dest has to be immutable because it is the return value
+-	// src has to be immutable because it is used in L(bwd_last)
+-	and	tmp2, dest, 0xffffffffffffff	// save dest_notag into tmp2
+-	and	tmp3, src, 0xffffffffffffff	// save src_notag intp tmp3
+-	cmp	n, 0
+-	ccmp	tmp2, tmp3, 4, ne
+-	b.ne	1f
++	/* Fast case for up to 2 vectors.  */
++	cntb	vlen
++	cmp	n, vlen, lsl 1
++	b.hi	1f
++	whilelo	p0.b, xzr, n
++	whilelo	p1.b, vlen, n
++	ld1b	z0.b, p0/z, [src, 0, mul vl]
++	ld1b	z1.b, p1/z, [src, 1, mul vl]
++	st1b	z0.b, p0, [dstin, 0, mul vl]
++	st1b	z1.b, p1, [dstin, 1, mul vl]
++L(full_overlap):
+ 	ret
+-1:	cntb	vector_length
+-	// shortcut for less than vector_length * 8
+-	// gives a free ptrue to p0.b for n >= vector_length
+-	// tmp2 and tmp3 should not be used in this macro to keep
+-	// notag addresses
+-	shortcut_for_small_size L(dispatch)
+-	// end of shortcut
+-
+-L(dispatch):
+-	// tmp2 = dest_notag, tmp3 = src_notag
+-	// diff = dest_notag - src_notag
+-	sub	tmp1, tmp2, tmp3
+-	// if diff <= 0 || diff >= n then memcpy
+-	cmp	tmp1, 0
+-	ccmp	tmp1, n, 2, gt
+-	b.cs	L(vl_agnostic)
+-
+-L(bwd_start):
+-	mov	rest, n
+-	add	dest_ptr, dest, n	// dest_end
+-	add	src_ptr, src, n		// src_end
+-
+-L(bwd_unroll8): // unrolling and software pipeline
+-	lsl	tmp1, vector_length, 3	// vector_length * 8
+-	.p2align 3
+-	cmp	rest, tmp1
+-	b.cc	L(bwd_last)
+-	sub	src_ptr, src_ptr, tmp1
++
++	.p2align 4
++	/* Check for overlapping moves. Return if there is a full overlap.
++	   Small moves up to 8 vectors use the overlap-safe copy_small code.
++	   Non-overlapping or overlapping moves with dst < src use memcpy.
++	   Overlapping moves with dst > src use a backward copy loop.  */
++1:	sub	tmp, dstin, src
++	ands	tmp, tmp, 0xffffffffffffff	/* Clear special tag bits.  */
++	b.eq	L(full_overlap)
++	cmp	n, vlen, lsl 3
++	b.ls	L(copy_small)
++	cmp	tmp, n
++	b.hs	L(copy_large)
++
++	/* Align to vector length.  */
++	add	dst, dstin, n
++	sub	tmp, vlen, 1
++	ands	tmp, dst, tmp
++	csel	tmp, tmp, vlen, ne
++	whilelo	p1.b, xzr, tmp
++	sub	n, n, tmp
++	ld1b	z1.b, p1/z, [src, n]
++	st1b	z1.b, p1, [dstin, n]
++	add	src, src, n
++	add	dst, dstin, n
++
++	ptrue	p0.b
++	lsl	vlen8, vlen, 3
++	subs	n, n, vlen8
++	b.ls	3f
++	sub	src, src, vlen8
+ 	ld1b_unroll8
+-	sub	rest, rest, tmp1
+-	cmp	rest, tmp1
+-	b.cc	2f
+-	.p2align 3
+-1:	sub	src_ptr, src_ptr, tmp1
+-	sub	dest_ptr, dest_ptr, tmp1
++	subs	n, n, vlen8
++	b.ls	2f
++
++	.p2align 4
++	/* 8x unrolled and software pipelined backward copy loop.  */
++1:	sub	src, src, vlen8
++	sub	dst, dst, vlen8
+ 	stld1b_unroll8
+-	sub	rest, rest, tmp1
+-	cmp	rest, tmp1
+-	b.ge	1b
+-2:	sub	dest_ptr, dest_ptr, tmp1
++	subs	n, n, vlen8
++	b.hi	1b
++2:	sub	dst, dst, vlen8
+ 	st1b_unroll8
++3:	add	n, n, vlen8
+ 
+-L(bwd_last):
+-	mov	dest_ptr, dest
+-	mov	src_ptr, src
+-	b	L(last)
++	/* Adjust src/dst for last 0-8 vectors.  */
++	sub	src, src, n
++	mov	dst, dstin
++	b	L(last_bytes)
+ 
+ END (MEMMOVE)
+ libc_hidden_builtin_def (MEMMOVE)
+-- 
+2.31.1
+
diff --git a/SOURCES/glibc-rh2054790.patch b/SOURCES/glibc-rh2054790.patch
new file mode 100644
index 0000000..6af769e
--- /dev/null
+++ b/SOURCES/glibc-rh2054790.patch
@@ -0,0 +1,27 @@
+commit ea89d5bbd9e5e514b606045d909e6ab87d851c88
+Author: Arjun Shankar <arjun@redhat.com>
+Date:   Thu Feb 24 21:43:09 2022 +0100
+
+    localedef: Handle symbolic links when generating locale-archive
+    
+    Whenever locale data for any locale included symbolic links, localedef
+    would throw the error "incomplete set of locale files" and exclude it
+    from the generated locale archive.  This commit fixes that.
+    
+    Co-authored-by: Florian Weimer <fweimer@redhat.com>
+    
+    Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+
+diff --git a/locale/programs/locarchive.c b/locale/programs/locarchive.c
+index dec73264563bc2a0..990f7eb6830d2e57 100644
+--- a/locale/programs/locarchive.c
++++ b/locale/programs/locarchive.c
+@@ -1391,7 +1391,7 @@ add_locales_to_archive (size_t nlist, char *list[], bool replace)
+ 		    {
+ 		      char fullname[fnamelen + 2 * strlen (d->d_name) + 7];
+ 
+-		      if (d_type == DT_UNKNOWN)
++		      if (d_type == DT_UNKNOWN || d_type == DT_LNK)
+ 			{
+ 			  strcpy (stpcpy (stpcpy (fullname, fname), "/"),
+ 				  d->d_name);
diff --git a/SOURCES/glibc-rh2063042.patch b/SOURCES/glibc-rh2063042.patch
new file mode 100644
index 0000000..921add1
--- /dev/null
+++ b/SOURCES/glibc-rh2063042.patch
@@ -0,0 +1,358 @@
+commit fcfc9086815bf0d277ad47a90ee3fda4c37acca8
+Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date:   Wed Jan 12 23:34:48 2022 +0530
+
+    debug: Synchronize feature guards in fortified functions [BZ #28746]
+    
+    Some functions (e.g. stpcpy, pread64, etc.) had moved to POSIX in the
+    main headers as they got incorporated into the standard, but their
+    fortified variants remained under __USE_GNU.  As a result, these
+    functions did not get fortified when _GNU_SOURCE was not defined.
+    
+    Add test wrappers that check all functions tested in tst-chk0 at all
+    levels with _GNU_SOURCE undefined and then use the failures to (1)
+    exclude checks for _GNU_SOURCE functions in these tests and (2) Fix
+    feature macro guards in the fortified function headers so that they're
+    the same as the ones in the main headers.
+    
+    This fixes BZ #28746.
+    
+    Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+    Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
+
+# Conflicts:
+#	debug/tst-fortify.c
+
+diff --git a/debug/Makefile b/debug/Makefile
+index c92fd23dda1a7279..b0f0b7beb6d5cef5 100644
+--- a/debug/Makefile
++++ b/debug/Makefile
+@@ -132,6 +132,12 @@ define cflags-lfs
+ CFLAGS-tst-fortify-$(1)-lfs-$(2).$(1) += -D_FILE_OFFSET_BITS=64
+ endef
+ 
++define cflags-nongnu
++CFLAGS-tst-fortify-$(1)-nongnu-$(2).$(1) += -D_LARGEFILE64_SOURCE=1
++endef
++
++src-chk-nongnu = \#undef _GNU_SOURCE
++
+ # We know these tests have problems with format strings, this is what
+ # we are testing.  Disable that warning.  They are also testing
+ # deprecated functions (notably gets) so disable that warning as well.
+@@ -145,13 +151,13 @@ CFLAGS-tst-fortify-$(1)-$(2)-$(3).$(1) += -D_FORTIFY_SOURCE=$(3) -Wno-format \
+ $(eval $(call cflags-$(2),$(1),$(3)))
+ $(objpfx)tst-fortify-$(1)-$(2)-$(3).$(1): tst-fortify.c Makefile
+ 	( echo "/* Autogenerated from Makefile.  */"; \
+-	  echo ""; \
++	  echo "$(src-chk-$(2))"; \
+ 	  echo "#include \"tst-fortify.c\"" ) > $$@.tmp
+ 	mv $$@.tmp $$@
+ endef
+ 
+ chk-extensions = c cc
+-chk-types = default lfs
++chk-types = default lfs nongnu
+ chk-levels = 1 2 3
+ 
+ $(foreach e,$(chk-extensions), \
+diff --git a/debug/tst-fortify.c b/debug/tst-fortify.c
+index 5e76081255316a93..1668294e48b5c63c 100644
+--- a/debug/tst-fortify.c
++++ b/debug/tst-fortify.c
+@@ -1,4 +1,5 @@
+-/* Copyright (C) 2004-2018 Free Software Foundation, Inc.
++/* Copyright (C) 2004-2022 Free Software Foundation, Inc.
++   Copyright The GNU Toolchain Authors.
+    This file is part of the GNU C Library.
+    Contributed by Jakub Jelinek <jakub@redhat.com>, 2004.
+ 
+@@ -37,6 +38,17 @@
+ #include <sys/socket.h>
+ #include <sys/un.h>
+ 
++#ifndef _GNU_SOURCE
++# define MEMPCPY memcpy
++# define WMEMPCPY wmemcpy
++# define MEMPCPY_RET(x) 0
++# define WMEMPCPY_RET(x) 0
++#else
++# define MEMPCPY mempcpy
++# define WMEMPCPY wmempcpy
++# define MEMPCPY_RET(x) __builtin_strlen (x)
++# define WMEMPCPY_RET(x) wcslen (x)
++#endif
+ 
+ #define obstack_chunk_alloc malloc
+ #define obstack_chunk_free free
+@@ -163,7 +175,7 @@ do_test (void)
+   if (memcmp (buf, "aabcdefghi", 10))
+     FAIL ();
+ 
+-  if (mempcpy (buf + 5, "abcde", 5) != buf + 10
++  if (MEMPCPY (buf + 5, "abcde", 5) != buf + 5 + MEMPCPY_RET ("abcde")
+       || memcmp (buf, "aabcdabcde", 10))
+     FAIL ();
+ 
+@@ -208,7 +220,7 @@ do_test (void)
+   if (memcmp (buf, "aabcdefghi", 10))
+     FAIL ();
+ 
+-  if (mempcpy (buf + 5, "abcde", l0 + 5) != buf + 10
++  if (MEMPCPY (buf + 5, "abcde", l0 + 5) != buf + 5 + MEMPCPY_RET ("abcde")
+       || memcmp (buf, "aabcdabcde", 10))
+     FAIL ();
+ 
+@@ -267,7 +279,8 @@ do_test (void)
+   if (memcmp (a.buf1, "aabcdefghi", 10))
+     FAIL ();
+ 
+-  if (mempcpy (a.buf1 + 5, "abcde", l0 + 5) != a.buf1 + 10
++  if (MEMPCPY (a.buf1 + 5, "abcde", l0 + 5)
++      != a.buf1 + 5 + MEMPCPY_RET ("abcde")
+       || memcmp (a.buf1, "aabcdabcde", 10))
+     FAIL ();
+ 
+@@ -348,6 +361,7 @@ do_test (void)
+   bcopy (buf + 1, buf + 2, l0 + 9);
+   CHK_FAIL_END
+ 
++#ifdef _GNU_SOURCE
+   CHK_FAIL_START
+   p = (char *) mempcpy (buf + 6, "abcde", 5);
+   CHK_FAIL_END
+@@ -355,6 +369,7 @@ do_test (void)
+   CHK_FAIL_START
+   p = (char *) mempcpy (buf + 6, "abcde", l0 + 5);
+   CHK_FAIL_END
++#endif
+ 
+   CHK_FAIL_START
+   memset (buf + 9, 'j', 2);
+@@ -465,6 +480,7 @@ do_test (void)
+   bcopy (a.buf1 + 1, a.buf1 + 2, l0 + 9);
+   CHK_FAIL_END
+ 
++#ifdef _GNU_SOURCE
+   CHK_FAIL_START
+   p = (char *) mempcpy (a.buf1 + 6, "abcde", 5);
+   CHK_FAIL_END
+@@ -472,6 +488,7 @@ do_test (void)
+   CHK_FAIL_START
+   p = (char *) mempcpy (a.buf1 + 6, "abcde", l0 + 5);
+   CHK_FAIL_END
++#endif
+ 
+   CHK_FAIL_START
+   memset (a.buf1 + 9, 'j', 2);
+@@ -551,7 +568,7 @@ do_test (void)
+   if (wmemcmp (wbuf, L"aabcdefghi", 10))
+     FAIL ();
+ 
+-  if (wmempcpy (wbuf + 5, L"abcde", 5) != wbuf + 10
++  if (WMEMPCPY (wbuf + 5, L"abcde", 5) != wbuf + 5 + WMEMPCPY_RET (L"abcde")
+       || wmemcmp (wbuf, L"aabcdabcde", 10))
+     FAIL ();
+ 
+@@ -584,7 +601,8 @@ do_test (void)
+   if (wmemcmp (wbuf, L"aabcdefghi", 10))
+     FAIL ();
+ 
+-  if (wmempcpy (wbuf + 5, L"abcde", l0 + 5) != wbuf + 10
++  if (WMEMPCPY (wbuf + 5, L"abcde", l0 + 5)
++      != wbuf + 5 + WMEMPCPY_RET (L"abcde")
+       || wmemcmp (wbuf, L"aabcdabcde", 10))
+     FAIL ();
+ 
+@@ -626,7 +644,8 @@ do_test (void)
+   if (wmemcmp (wa.buf1, L"aabcdefghi", 10))
+     FAIL ();
+ 
+-  if (wmempcpy (wa.buf1 + 5, L"abcde", l0 + 5) != wa.buf1 + 10
++  if (WMEMPCPY (wa.buf1 + 5, L"abcde", l0 + 5)
++      != wa.buf1 + 5 + WMEMPCPY_RET (L"abcde")
+       || wmemcmp (wa.buf1, L"aabcdabcde", 10))
+     FAIL ();
+ 
+@@ -695,6 +714,7 @@ do_test (void)
+   wmemmove (wbuf + 2, wbuf + 1, l0 + 9);
+   CHK_FAIL_END
+ 
++#ifdef _GNU_SOURCE
+   CHK_FAIL_START
+   wp = wmempcpy (wbuf + 6, L"abcde", 5);
+   CHK_FAIL_END
+@@ -702,6 +722,7 @@ do_test (void)
+   CHK_FAIL_START
+   wp = wmempcpy (wbuf + 6, L"abcde", l0 + 5);
+   CHK_FAIL_END
++#endif
+ 
+   CHK_FAIL_START
+   wmemset (wbuf + 9, L'j', 2);
+@@ -769,6 +790,7 @@ do_test (void)
+   wmemmove (wa.buf1 + 2, wa.buf1 + 1, l0 + 9);
+   CHK_FAIL_END
+ 
++#ifdef _GNU_SOURCE
+   CHK_FAIL_START
+   wp = wmempcpy (wa.buf1 + 6, L"abcde", 5);
+   CHK_FAIL_END
+@@ -776,6 +798,7 @@ do_test (void)
+   CHK_FAIL_START
+   wp = wmempcpy (wa.buf1 + 6, L"abcde", l0 + 5);
+   CHK_FAIL_END
++#endif
+ 
+   CHK_FAIL_START
+   wmemset (wa.buf1 + 9, L'j', 2);
+@@ -907,6 +930,7 @@ do_test (void)
+   if (fprintf (fp, buf2 + 4, str5) != 7)
+     FAIL ();
+ 
++#ifdef _GNU_SOURCE
+   char *my_ptr = NULL;
+   strcpy (buf2 + 2, "%n%s%n");
+   /* When the format string is writable and contains %n,
+@@ -936,6 +960,7 @@ do_test (void)
+   if (obstack_printf (&obs, "%s%n%s%n", str4, &n1, str5, &n1) != 14)
+     FAIL ();
+   obstack_free (&obs, NULL);
++#endif
+ 
+   if (freopen (temp_filename, "r", stdin) == NULL)
+     {
+@@ -983,6 +1008,7 @@ do_test (void)
+ 
+   rewind (stdin);
+ 
++#ifdef _GNU_SOURCE
+   if (fgets_unlocked (buf, buf_size, stdin) != buf
+       || memcmp (buf, "abcdefgh\n", 10))
+     FAIL ();
+@@ -1009,6 +1035,7 @@ do_test (void)
+ #endif
+ 
+   rewind (stdin);
++#endif
+ 
+   if (fread (buf, 1, buf_size, stdin) != buf_size
+       || memcmp (buf, "abcdefgh\nA", 10))
+@@ -1579,7 +1606,10 @@ do_test (void)
+       ret = 1;
+     }
+ 
+-  int fd = posix_openpt (O_RDWR);
++  int fd;
++
++#ifdef _GNU_SOURCE
++  fd = posix_openpt (O_RDWR);
+   if (fd != -1)
+     {
+       char enough[1000];
+@@ -1595,6 +1625,7 @@ do_test (void)
+ #endif
+       close (fd);
+     }
++#endif
+ 
+ #if PATH_MAX > 0
+   confstr (_CS_GNU_LIBC_VERSION, largebuf, sizeof (largebuf));
+@@ -1712,8 +1743,9 @@ do_test (void)
+   poll (fds, l0 + 2, 0);
+   CHK_FAIL_END
+ #endif
++#ifdef _GNU_SOURCE
+   ppoll (fds, 1, NULL, NULL);
+-#if __USE_FORTIFY_LEVEL >= 1
++# if __USE_FORTIFY_LEVEL >= 1
+   CHK_FAIL_START
+   ppoll (fds, 2, NULL, NULL);
+   CHK_FAIL_END
+@@ -1721,6 +1753,7 @@ do_test (void)
+   CHK_FAIL_START
+   ppoll (fds, l0 + 2, NULL, NULL);
+   CHK_FAIL_END
++# endif
+ #endif
+ 
+   return ret;
+diff --git a/posix/bits/unistd.h b/posix/bits/unistd.h
+index a456d1723547db70..ddfaed4dd7574cd2 100644
+--- a/posix/bits/unistd.h
++++ b/posix/bits/unistd.h
+@@ -38,7 +38,7 @@ read (int __fd, void *__buf, size_t __nbytes)
+ 			  __fd, __buf, __nbytes);
+ }
+ 
+-#ifdef __USE_UNIX98
++#if defined __USE_UNIX98 || defined __USE_XOPEN2K8
+ extern ssize_t __pread_chk (int __fd, void *__buf, size_t __nbytes,
+ 			    __off_t __offset, size_t __bufsize) __wur;
+ extern ssize_t __pread64_chk (int __fd, void *__buf, size_t __nbytes,
+diff --git a/string/bits/string_fortified.h b/string/bits/string_fortified.h
+index 27ec273ec41cd81c..3f86629bf8fc51a2 100644
+--- a/string/bits/string_fortified.h
++++ b/string/bits/string_fortified.h
+@@ -94,7 +94,7 @@ __NTH (strcpy (char *__restrict __dest, const char *__restrict __src))
+   return __builtin___strcpy_chk (__dest, __src, __glibc_objsize (__dest));
+ }
+ 
+-#ifdef __USE_GNU
++#ifdef __USE_XOPEN2K8
+ __fortify_function char *
+ __NTH (stpcpy (char *__restrict __dest, const char *__restrict __src))
+ {
+@@ -111,14 +111,15 @@ __NTH (strncpy (char *__restrict __dest, const char *__restrict __src,
+ 				  __glibc_objsize (__dest));
+ }
+ 
+-#if __GNUC_PREREQ (4, 7) || __glibc_clang_prereq (2, 6)
++#ifdef __USE_XOPEN2K8
++# if __GNUC_PREREQ (4, 7) || __glibc_clang_prereq (2, 6)
+ __fortify_function char *
+ __NTH (stpncpy (char *__dest, const char *__src, size_t __n))
+ {
+   return __builtin___stpncpy_chk (__dest, __src, __n,
+ 				  __glibc_objsize (__dest));
+ }
+-#else
++# else
+ extern char *__stpncpy_chk (char *__dest, const char *__src, size_t __n,
+ 			    size_t __destlen) __THROW;
+ extern char *__REDIRECT_NTH (__stpncpy_alias, (char *__dest, const char *__src,
+@@ -132,6 +133,7 @@ __NTH (stpncpy (char *__dest, const char *__src, size_t __n))
+     return __stpncpy_chk (__dest, __src, __n, __bos (__dest));
+   return __stpncpy_alias (__dest, __src, __n);
+ }
++# endif
+ #endif
+ 
+ 
+diff --git a/support/xsignal.h b/support/xsignal.h
+index 9ab8d1bfddf6c598..fae6108a522ae5fe 100644
+--- a/support/xsignal.h
++++ b/support/xsignal.h
+@@ -28,7 +28,9 @@ __BEGIN_DECLS
+    terminate the process on error.  */
+ 
+ void xraise (int sig);
++#ifdef _GNU_SOURCE
+ sighandler_t xsignal (int sig, sighandler_t handler);
++#endif
+ void xsigaction (int sig, const struct sigaction *newact,
+                  struct sigaction *oldact);
+ 
+diff --git a/wcsmbs/bits/wchar2.h b/wcsmbs/bits/wchar2.h
+index f82bba481981e4fb..5c68979e96a504b4 100644
+--- a/wcsmbs/bits/wchar2.h
++++ b/wcsmbs/bits/wchar2.h
+@@ -457,7 +457,7 @@ __NTH (wcsrtombs (char *__restrict __dst, const wchar_t **__restrict __src,
+ }
+ 
+ 
+-#ifdef __USE_GNU
++#ifdef	__USE_XOPEN2K8
+ extern size_t __mbsnrtowcs_chk (wchar_t *__restrict __dst,
+ 				const char **__restrict __src, size_t __nmc,
+ 				size_t __len, mbstate_t *__restrict __ps,
diff --git a/SOURCES/glibc-rh2063712.patch b/SOURCES/glibc-rh2063712.patch
new file mode 100644
index 0000000..b66fce4
--- /dev/null
+++ b/SOURCES/glibc-rh2063712.patch
@@ -0,0 +1,208 @@
+This is a downstream rework of this upstream patch:
+
+  [PATCH v2 2/2] nss: Protect against errno changes in function lookup (bug 28953)
+  <https://sourceware.org/pipermail/libc-alpha/2022-March/137015.html>
+
+The NSS module loading code has been rewritten upstream, which is why
+only the test can be reused.  NSS_DECLARE_MODULE_FUNCTIONS does not yet
+exist downstream, so this part had to be skipped.
+
+diff --git a/nss/Makefile b/nss/Makefile
+index d5c28a6b5ed3661c..e8a7d9c7b3cefcdf 100644
+--- a/nss/Makefile
++++ b/nss/Makefile
+@@ -59,7 +59,8 @@ tests			= test-netdb test-digits-dots tst-nss-getpwent bug17079 \
+ 			  tst-nss-test2 \
+ 			  tst-nss-test3 \
+ 			  tst-nss-test4 \
+-			  tst-nss-test5
++			  tst-nss-test5 \
++			  tst-nss-test_errno
+ xtests			= bug-erange
+ 
+ tests-container = \
+@@ -130,7 +131,7 @@ routines                += $(libnss_files-routines)
+ static-only-routines    += $(libnss_files-routines)
+ tests-static		+= tst-nss-static
+ endif
+-extra-test-objs		+= nss_test1.os nss_test2.os
++extra-test-objs		+= nss_test1.os nss_test2.os nss_test_errno.os
+ 
+ include ../Rules
+ 
+@@ -166,10 +167,13 @@ rtld-tests-LDFLAGS += -Wl,--dynamic-list=nss_test.ver
+ 
+ libof-nss_test1 = extramodules
+ libof-nss_test2 = extramodules
++libof-nss_test_errno = extramodules
+ $(objpfx)/libnss_test1.so: $(objpfx)nss_test1.os $(link-libc-deps)
+ 	$(build-module)
+ $(objpfx)/libnss_test2.so: $(objpfx)nss_test2.os $(link-libc-deps)
+ 	$(build-module)
++$(objpfx)/libnss_test_errno.so: $(objpfx)nss_test_errno.os $(link-libc-deps)
++	$(build-module)
+ $(objpfx)nss_test2.os : nss_test1.c
+ ifdef libnss_test1.so-version
+ $(objpfx)/libnss_test1.so$(libnss_test1.so-version): $(objpfx)/libnss_test1.so
+@@ -179,9 +183,13 @@ ifdef libnss_test2.so-version
+ $(objpfx)/libnss_test2.so$(libnss_test2.so-version): $(objpfx)/libnss_test2.so
+ 	$(make-link)
+ endif
++$(objpfx)/libnss_test_errno.so$(libnss_files.so-version): \
++  $(objpfx)/libnss_test_errno.so
++	$(make-link)
+ $(patsubst %,$(objpfx)%.out,$(tests)) : \
+ 	$(objpfx)/libnss_test1.so$(libnss_test1.so-version) \
+-	$(objpfx)/libnss_test2.so$(libnss_test2.so-version)
++	$(objpfx)/libnss_test2.so$(libnss_test2.so-version) \
++	$(objpfx)/libnss_test_errno.so$(libnss_files.so-version)
+ 
+ ifeq (yes,$(have-thread-library))
+ $(objpfx)tst-cancel-getpwuid_r: $(shared-thread-library)
+diff --git a/nss/nss_test_errno.c b/nss/nss_test_errno.c
+new file mode 100644
+index 0000000000000000..ca75c890aa057869
+--- /dev/null
++++ b/nss/nss_test_errno.c
+@@ -0,0 +1,53 @@
++/* NSS service provider with errno clobber.
++   Copyright (C) 2022 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.h>
++#include <pwd.h>
++#include <stdlib.h>
++
++static void __attribute__ ((constructor))
++init (void)
++{
++  /* An arbitrary error code which is otherwise not used.  */
++  errno = ELIBBAD;
++}
++
++/* Lookup functions for pwd follow that do not return any data.  */
++
++enum nss_status
++_nss_test_errno_setpwent (int stayopen)
++{
++  setenv ("_nss_test_errno_setpwent", "yes", 1);
++  return NSS_STATUS_SUCCESS;
++}
++
++enum nss_status
++_nss_test_errno_getpwent_r (struct passwd *result,
++                            char *buffer, size_t size, int *errnop)
++{
++  setenv ("_nss_test_errno_getpwent_r", "yes", 1);
++  return NSS_STATUS_NOTFOUND;
++}
++
++enum nss_status
++_nss_test_errno_endpwent (void)
++{
++  setenv ("_nss_test_errno_endpwent", "yes", 1);
++  return NSS_STATUS_SUCCESS;
++}
+diff --git a/nss/nsswitch.c b/nss/nsswitch.c
+index 17adf1ef03f93d60..e59ab674e0426b26 100644
+--- a/nss/nsswitch.c
++++ b/nss/nsswitch.c
+@@ -401,6 +401,7 @@ void *
+ __nss_lookup_function (service_user *ni, const char *fct_name)
+ {
+   void **found, *result;
++  int saved_errno = errno;
+ 
+   /* We now modify global data.  Protect it.  */
+   __libc_lock_lock (lock);
+@@ -523,6 +524,8 @@ __nss_lookup_function (service_user *ni, const char *fct_name)
+   /* Remove the lock.  */
+   __libc_lock_unlock (lock);
+ 
++  __set_errno (saved_errno);
++
+   return result;
+ }
+ libc_hidden_def (__nss_lookup_function)
+diff --git a/nss/tst-nss-test_errno.c b/nss/tst-nss-test_errno.c
+new file mode 100644
+index 0000000000000000..d2c42dd363a38b0e
+--- /dev/null
++++ b/nss/tst-nss-test_errno.c
+@@ -0,0 +1,61 @@
++/* getpwent failure when dlopen clobbers errno (bug 28953).
++   Copyright (C) 2022 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.h>
++#include <support/check.h>
++#include <stdlib.h>
++#include <errno.h>
++#include <stdbool.h>
++#include <pwd.h>
++#include <string.h>
++
++static int
++do_test (void)
++{
++  __nss_configure_lookup ("passwd", "files test_errno");
++
++  errno = 0;
++  setpwent ();
++  TEST_COMPARE (errno, 0);
++
++  bool root_seen = false;
++  while (true)
++    {
++      errno = 0;
++      struct passwd *e = getpwent ();
++      if (e == NULL)
++        break;
++      if (strcmp (e->pw_name, "root"))
++        root_seen = true;
++    }
++
++  TEST_COMPARE (errno, 0);
++  TEST_VERIFY (root_seen);
++
++  errno = 0;
++  endpwent ();
++  TEST_COMPARE (errno, 0);
++
++  TEST_COMPARE_STRING (getenv ("_nss_test_errno_setpwent"), "yes");
++  TEST_COMPARE_STRING (getenv ("_nss_test_errno_getpwent_r"), "yes");
++  TEST_COMPARE_STRING (getenv ("_nss_test_errno_endpwent"), "yes");
++
++  return 0;
++}
++
++#include <support/test-driver.c>
diff --git a/SPECS/glibc.spec b/SPECS/glibc.spec
index 446f38d..9a3e247 100644
--- a/SPECS/glibc.spec
+++ b/SPECS/glibc.spec
@@ -1,6 +1,6 @@
 %define glibcsrcdir glibc-2.28
 %define glibcversion 2.28
-%define glibcrelease 189%{?dist}
+%define glibcrelease 196%{?dist}
 # Pre-release tarballs are pulled in from git using a command that is
 # effectively:
 #
@@ -855,6 +855,29 @@ Patch660: glibc-rh2045063-2.patch
 Patch661: glibc-rh2045063-3.patch
 Patch662: glibc-rh2045063-4.patch
 Patch663: glibc-rh2045063-5.patch
+Patch664: glibc-rh2054790.patch
+Patch665: glibc-rh2037416-1.patch
+Patch666: glibc-rh2037416-2.patch
+Patch667: glibc-rh2037416-3.patch
+Patch668: glibc-rh2037416-4.patch
+Patch669: glibc-rh2037416-5.patch
+Patch670: glibc-rh2037416-6.patch
+Patch671: glibc-rh2037416-7.patch
+Patch672: glibc-rh2037416-8.patch
+Patch673: glibc-rh2033684-1.patch
+Patch674: glibc-rh2033684-2.patch
+Patch675: glibc-rh2033684-3.patch
+Patch676: glibc-rh2033684-4.patch
+Patch677: glibc-rh2033684-5.patch
+Patch678: glibc-rh2033684-6.patch
+Patch679: glibc-rh2033684-7.patch
+Patch680: glibc-rh2033684-8.patch
+Patch681: glibc-rh2033684-9.patch
+Patch682: glibc-rh2033684-10.patch
+Patch683: glibc-rh2033684-11.patch
+Patch684: glibc-rh2033684-12.patch
+Patch685: glibc-rh2063712.patch
+Patch686: glibc-rh2063042.patch
 
 ##############################################################################
 # Continued list of core "glibc" package information:
@@ -1746,6 +1769,20 @@ $olddir/build-%{target}/testrun.sh \
 # default locale-archive without modification, and leaving compiled
 # locales as they are (without inclusion into the archive).
 cp locale-archive{,.tmpl}
+
+# Almost half the LC_CTYPE files in langpacks are identical to the C.utf8
+# variant which is installed by default.  When we keep them as hardlinks,
+# each langpack ends up retaining a copy.  If we convert these to symbolic
+# links instead, we save ~350K each when they get installed that way.
+#
+# LC_MEASUREMENT and LC_PAPER also have several duplicates but we don't
+# bother with these because they are only ~30 bytes each.
+pushd %{glibc_sysroot}/usr/lib/locale
+for f in $(find eo *_* -samefile C.utf8/LC_CTYPE); do
+  rm $f && ln -s '../C.utf8/LC_CTYPE' $f
+done
+popd
+
 # Create the file lists for the language specific sub-packages:
 for i in eo *_*
 do
@@ -2054,7 +2091,7 @@ chmod 0444 master.filelist
 # - All the libnss files (we add back the ones we want later).
 # - All bench test binaries.
 # - The aux-cache, since it's handled specially in the files section.
-# - The build-locale-archive binary since it's in the common package.
+# - The build-locale-archive binary since it's in the all-langpacks package.
 # - Extra gconv modules.  We add the required modules later.
 cat master.filelist \
 	| grep -v \
@@ -2179,13 +2216,15 @@ grep '%{_libdir}/lib.*\.a' < master.filelist \
 ###############################################################################
 
 # All of the bin and certain sbin files go into the common package except
-# iconvconfig which needs to go in glibc. Likewise nscd is excluded because
+# iconvconfig which needs to go in glibc, and build-locale-archive which
+# needs to go into glibc-all-langpacks. Likewise nscd is excluded because
 # it goes in nscd. The iconvconfig binary is kept in the main glibc package
 # because we use it in the post-install scriptlet to rebuild the
 # gconv-modules.cache.
 grep '%{_prefix}/bin' master.filelist >> common.filelist
 grep '%{_prefix}/sbin' master.filelist \
 	| grep -v '%{_prefix}/sbin/iconvconfig' \
+	| grep -v '%{_prefix}/sbin/build-locale-archive' \
 	| grep -v 'nscd' >> common.filelist
 # All of the files under share go into the common package since they should be
 # multilib-independent.
@@ -2201,9 +2240,6 @@ grep '%{_prefix}/share' master.filelist \
 	-e '%{_docdir}' \
 	>> common.filelist
 
-# Add the binary to build locales to the common subpackage.
-echo '%{_prefix}/sbin/build-locale-archive' >> common.filelist
-
 ###############################################################################
 # nscd
 ###############################################################################
@@ -2613,6 +2649,8 @@ fi
 %files all-langpacks
 %attr(0644,root,root) %verify(not md5 size mtime) %{_prefix}/lib/locale/locale-archive.tmpl
 %attr(0644,root,root) %verify(not md5 size mtime mode) %ghost %{_prefix}/lib/locale/locale-archive
+# build-locale-archive re-generates locale-archive during install/upgrade/downgrade
+%attr(0700,root,root) %{_prefix}/sbin/build-locale-archive
 
 %files locale-source
 %dir %{_prefix}/share/i18n/locales
@@ -2670,6 +2708,28 @@ fi
 %files -f compat-libpthread-nonshared.filelist -n compat-libpthread-nonshared
 
 %changelog
+* Tue Mar 15 2022 Siddhesh Poyarekar <siddhesh@redhat.com> 2.28-196
+- Synchronize feature guards in fortified functions (#2063042)
+
+* Mon Mar 14 2022 Florian Weimer <fweimer@redhat.com> - 2.28-195
+- nss: Avoid clobbering errno in get*ent via dlopen (#2063712)
+
+* Fri Mar 11 2022 Siddhesh Poyarekar <siddhesh@redhat.com> 2.28-194
+- Enable support for _FORTIFY_SOURCE=3 for gcc 12 and later (#2033684)
+
+* Wed Mar 9 2022 DJ Delorie <dj@redhat.com> - 2.28-193
+- memory operation A64FX SVE performance improvement (#2037416)
+
+* Mon Mar 07 2022 Arjun Shankar <arjun@redhat.com> - 2.28-192
+- Move build-locale-archive to glibc-all-langpacks (#2057513)
+
+* Mon Mar 07 2022 Arjun Shankar <arjun@redhat.com> - 2.28-191
+- Fix build-locale-archive to handle symbolic links (#2054790)
+
+* Fri Mar 04 2022 Arjun Shankar <arjun@redhat.com> - 2.28-190
+- Reduce installed size of some langpacks by de-duplicating LC_CTYPE (#2054790)
+- Fix localedef so it can handle symbolic links when generating locale-archive.
+
 * Thu Jan 27 2022 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.28-189
 - CVE-2021-3999: getcwd: align stack on clone in aarch64 and fix a memory leak
   (#2032281)