Implement strlcpy and strlcat [BZ #178]

Message ID 87fsjp7rqz.fsf@oldenburg.str.redhat.com
State Deferred
Headers
Series Implement strlcpy and strlcat [BZ #178] |

Checks

Context Check Description
dj/TryBot-apply_patch success Patch applied to master at the time it was sent
dj/TryBot-32bit fail Patch caused testsuite regressions

Commit Message

Florian Weimer June 27, 2022, 8:53 p.m. UTC
  These functions are about to be added to POSIX, under Austin Group
issue 986.

(not for commit message) Tested on i686-linux-gnu and x86_64-linux-gnu.
Built with build-many-glibcs.py.

Compared to the previously posted version, I adjusted the symbol
version, marked the destination buffer as non-null (based on my
interpretation of the POSIX description), added access attributes, and
removed the custom warnings code (__warndecl had already been removed).
If we want additional compiler warnings, they are likely better placed
in compilers.  The compiler is better placed to issue comprehensible
warnings, I think.

Paul, does your previous objection still stand, given that these
interfaces appear to be heading to an upcoming POSIX version?  I had
nothing to do with the POSIX decision, so I wasn't trying to undermine
the glibc consensus procedures.

Thanks,
Florian
---
 NEWS                                               |  2 +
 debug/Makefile                                     |  1 +
 debug/Versions                                     |  4 +
 debug/strlcat_chk.c                                | 32 ++++++++
 debug/strlcpy_chk.c                                | 32 ++++++++
 debug/tst-fortify.c                                | 22 ++++++
 include/string.h                                   |  2 +
 manual/string.texi                                 | 70 +++++++++++++++++
 string/Makefile                                    |  4 +
 string/Versions                                    |  4 +
 string/bits/string_fortified.h                     | 34 ++++++++
 string/string.h                                    | 13 ++++
 string/strlcat.c                                   | 60 +++++++++++++++
 string/strlcpy.c                                   | 47 +++++++++++
 string/tst-strlcat.c                               | 90 ++++++++++++++++++++++
 string/tst-strlcpy.c                               | 70 +++++++++++++++++
 sysdeps/mach/hurd/i386/libc.abilist                |  4 +
 sysdeps/unix/sysv/linux/aarch64/libc.abilist       |  4 +
 sysdeps/unix/sysv/linux/alpha/libc.abilist         |  4 +
 sysdeps/unix/sysv/linux/arc/libc.abilist           |  4 +
 sysdeps/unix/sysv/linux/arm/be/libc.abilist        |  4 +
 sysdeps/unix/sysv/linux/arm/le/libc.abilist        |  4 +
 sysdeps/unix/sysv/linux/csky/libc.abilist          |  4 +
 sysdeps/unix/sysv/linux/hppa/libc.abilist          |  4 +
 sysdeps/unix/sysv/linux/i386/libc.abilist          |  4 +
 sysdeps/unix/sysv/linux/ia64/libc.abilist          |  4 +
 sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist |  4 +
 sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist   |  4 +
 sysdeps/unix/sysv/linux/microblaze/be/libc.abilist |  4 +
 sysdeps/unix/sysv/linux/microblaze/le/libc.abilist |  4 +
 .../unix/sysv/linux/mips/mips32/fpu/libc.abilist   |  4 +
 .../unix/sysv/linux/mips/mips32/nofpu/libc.abilist |  4 +
 .../unix/sysv/linux/mips/mips64/n32/libc.abilist   |  4 +
 .../unix/sysv/linux/mips/mips64/n64/libc.abilist   |  4 +
 sysdeps/unix/sysv/linux/nios2/libc.abilist         |  4 +
 sysdeps/unix/sysv/linux/or1k/libc.abilist          |  4 +
 .../sysv/linux/powerpc/powerpc32/fpu/libc.abilist  |  4 +
 .../linux/powerpc/powerpc32/nofpu/libc.abilist     |  4 +
 .../sysv/linux/powerpc/powerpc64/be/libc.abilist   |  4 +
 .../sysv/linux/powerpc/powerpc64/le/libc.abilist   |  4 +
 sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist    |  4 +
 sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist    |  4 +
 sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist  |  4 +
 sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist  |  4 +
 sysdeps/unix/sysv/linux/sh/be/libc.abilist         |  4 +
 sysdeps/unix/sysv/linux/sh/le/libc.abilist         |  4 +
 sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist |  4 +
 sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist |  4 +
 sysdeps/unix/sysv/linux/x86_64/64/libc.abilist     |  4 +
 sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist    |  4 +
 50 files changed, 623 insertions(+)
  

Comments

Paul Eggert June 29, 2022, 6:48 p.m. UTC | #1
On 6/27/22 15:53, Florian Weimer wrote:
> Paul, does your previous objection still stand, given that these
> interfaces appear to be heading to an upcoming POSIX version?  I had
> nothing to do with the POSIX decision, so I wasn't trying to undermine
> the glibc consensus procedures.
>
Thanks for bringing this to my attention. If POSIX standardizes strlcpy 
that certainly strengthens the case for glibc supporting it. However, 
strlcpy is not in POSIX yet and even the most recent POSIX draft doesn't 
contain it, and I just now filed an objection 
<https://www.austingroupbugs.net/view.php?id=1591> that may remove or 
alter the proposed spec. Let's wait and see what happens to that before 
committing to any public change to glibc. Of course you're welcome to 
chime in at austingroupbugs if you like.
  
Siddhesh Poyarekar June 29, 2022, 7:30 p.m. UTC | #2
On 28/06/2022 02:23, Florian Weimer via Libc-alpha wrote:
> These functions are about to be added to POSIX, under Austin Group
> issue 986.

Please note the link in the git commit message to the description you're 
referring to so that it's explicit:

https://www.austingroupbugs.net/view.php?id=986#c4967

> 
> (not for commit message) Tested on i686-linux-gnu and x86_64-linux-gnu.
> Built with build-many-glibcs.py.
> 
> Compared to the previously posted version, I adjusted the symbol
> version, marked the destination buffer as non-null (based on my
> interpretation of the POSIX description), added access attributes, and
> removed the custom warnings code (__warndecl had already been removed).
> If we want additional compiler warnings, they are likely better placed
> in compilers.  The compiler is better placed to issue comprehensible
> warnings, I think.
> 
> Paul, does your previous objection still stand, given that these
> interfaces appear to be heading to an upcoming POSIX version?  I had
> nothing to do with the POSIX decision, so I wasn't trying to undermine
> the glibc consensus procedures.

I'll stick to technical review then, hopefully it'll be useful to 
maintain your patch until the standards issues are resolved.

> diff --git a/NEWS b/NEWS
> index b0a3d7e512..74829a30a6 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -46,6 +46,8 @@ Major new features:
>     to more flexibly configure and operate on filesystem mounts.  The new
>     mount APIs are specifically designed to work with namespaces.
>   
> +* The functions strlcpy and strlcat have been added.
> +
>   Deprecated and removed features, and other changes affecting compatibility:
>   
>   * Support for prelink will be removed in the next release; this includes
> diff --git a/debug/Makefile b/debug/Makefile
> index 456b349c4d..abb0a85b03 100644
> --- a/debug/Makefile
> +++ b/debug/Makefile
> @@ -31,6 +31,7 @@ headers	:= execinfo.h
>   routines  = backtrace backtracesyms backtracesymsfd noophooks \
>   	    memcpy_chk memmove_chk mempcpy_chk memset_chk stpcpy_chk \
>   	    strcat_chk strcpy_chk strncat_chk strncpy_chk stpncpy_chk \
> +	    strlcpy_chk strlcat_chk \
>   	    sprintf_chk vsprintf_chk snprintf_chk vsnprintf_chk \
>   	    printf_chk fprintf_chk vprintf_chk vfprintf_chk \
>   	    gets_chk chk_fail readonly-area fgets_chk fgets_u_chk \
> diff --git a/debug/Versions b/debug/Versions
> index a6628db356..a4bfbcfee6 100644
> --- a/debug/Versions
> +++ b/debug/Versions
> @@ -58,6 +58,10 @@ libc {
>     GLIBC_2.25 {
>       __explicit_bzero_chk;
>     }
> +  GLIBC_2.36 {
> +    __strlcpy_chk;
> +    __strlcat_chk;
> +  }
>     GLIBC_PRIVATE {
>       __fortify_fail;
>     }
> diff --git a/debug/strlcat_chk.c b/debug/strlcat_chk.c
> new file mode 100644
> index 0000000000..15e4182229
> --- /dev/null
> +++ b/debug/strlcat_chk.c
> @@ -0,0 +1,32 @@
> +/* Fortified version of strlcat.
> +   Copyright (C) 2017 Free Software Foundation, Inc.

Copyright 2022?  For all files.

> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <string.h>
> +#include <memcopy.h>
> +
> +/* Check that the user-supplied size does not exceed the
> +   compiler-determined size, and then forward to strlcat.  */
> +size_t
> +__strlcat_chk (char *__restrict s1, const char *__restrict s2,
> +	       size_t n, size_t s1len)
> +{
> +  if (__glibc_unlikely (s1len < n))
> +    __chk_fail ();

The manual/string.texi description specifically defines behaviour when n 
 > s1len, so it doesn't make sense to make that case fail for the 
fortified variant.  That or modify the manual to call this usage out as 
problematic (and explicitly specify n as the size of s1) and unsupported 
with fortification.  AFAICT, this hardening then becomes a GNU extension 
since the standard text appears to allow it too.

> +
> +  return strlcat (s1, s2, n);
> +} > diff --git a/debug/strlcpy_chk.c b/debug/strlcpy_chk.c
> new file mode 100644
> index 0000000000..1bcb12b793
> --- /dev/null
> +++ b/debug/strlcpy_chk.c
> @@ -0,0 +1,32 @@
> +/* Fortified version of strlcpy.
> +   Copyright (C) 2017 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <string.h>
> +#include <memcopy.h>
> +
> +/* Check that the user-supplied size does not exceed the
> +   compiler-determined size, and then forward to strlcpy.  */
> +size_t
> +__strlcpy_chk (char *__restrict s1, const char *__restrict s2,
> +	       size_t n, size_t s1len)
> +{
> +  if (__glibc_unlikely (s1len < n))
> +    __chk_fail ();

Likewise.

> +
> +  return strlcpy (s1, s2, n);
> +}
> diff --git a/debug/tst-fortify.c b/debug/tst-fortify.c
> index 8e94643bf2..d4ead37c77 100644
> --- a/debug/tst-fortify.c
> +++ b/debug/tst-fortify.c
> @@ -535,6 +535,16 @@ do_test (void)
>     strncpy (a.buf1 + (O + 6), "X", l0 + 4);
>     CHK_FAIL_END
>   
> +  CHK_FAIL_START
> +  strlcpy (buf, "", sizeof (buf) + 1);
> +  CHK_FAIL_END
> +
> +  {
> +    char *volatile buf2 = buf;
> +    if (strlcpy (buf2, "a", sizeof (buf) + 1) != 1)
> +      FAIL ();
> +  }
> +
>   # if !defined __cplusplus || defined __va_arg_pack
>     CHK_FAIL_START
>     sprintf (a.buf1 + (O + 7), "%d", num1);
> @@ -558,6 +568,18 @@ do_test (void)
>     CHK_FAIL_START
>     strncat (a.buf1, "ZYXWV", l0 + 3);
>     CHK_FAIL_END
> +
> +  buf[0] = '\0';
> +  CHK_FAIL_START
> +  strlcat (buf, "ZYXWV", sizeof (buf) + 1);
> +  CHK_FAIL_END
> +
> +  {
> +    buf[0] = '\0';
> +    char *volatile buf2 = buf;
> +    if (strlcat (buf2, "a", sizeof (buf) + 1) != 1)
> +      FAIL ();
> +  }
>   #endif
>   
>   
> diff --git a/include/string.h b/include/string.h
> index 21f641a413..b01b2fb2b4 100644
> --- a/include/string.h
> +++ b/include/string.h
> @@ -91,6 +91,8 @@ libc_hidden_proto (__stpcpy)
>   # define __stpcpy(dest, src) __builtin_stpcpy (dest, src)
>   #endif
>   libc_hidden_proto (__stpncpy)
> +libc_hidden_proto (strlcpy)
> +libc_hidden_proto (strlcat)
>   libc_hidden_proto (__rawmemchr)
>   libc_hidden_proto (__strcasecmp)
>   libc_hidden_proto (__strcasecmp_l)
> diff --git a/manual/string.texi b/manual/string.texi
> index 0b60b3fbb4..c2f4d3b2de 100644
> --- a/manual/string.texi
> +++ b/manual/string.texi
> @@ -1068,6 +1068,76 @@ processing text.  Also, this function has significant performance
>   issues.  @xref{Concatenating Strings}.
>   @end deftypefun
>   
> +@deftypefun size_t strlcpy (char *restrict @var{to}, const char *restrict @var{from}, size_t @var{size})
> +@standards{BSD, string.h}
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +This function is similar to @code{strcpy}, but copies at most
> +@var{size} bytes from the string @var{from} into the destination
> +array @var{to}, including a terminating null byte.
> +
> +If @var{size} is greater than the length of the string @var{from},
> +this function copies all of the string @var{from} to the destination
> +array @var{to}, including the terminating null byte.  Like other
> +string functions such as @code{strcpy}, but unlike @code{strncpy}, any
> +remaining bytes in the destination array remain unchanged.

The standard wording says copy only up to (but not including) the NUL 
byte.  The NUL byte is added separately:

     The strlcpy() function shall copy not more than dstsize - 1 bytes
     from the string pointed to by src to the array pointed to by dst; a
     NUL byte in src and bytes that follow it shall not be copied.

The difference is only academic I suppose.

> +
> +If @var{size} is nonzero and less than or equal to the the length of the string
> +@var{from}, this function copies only the first @samp{@var{size} - 1}
> +bytes to the destination array @var{to}, and writes a terminating null
> +byte to the last byte of the array.
> +
> +The return value @var{result} of @code{strlcpy} is the length of the
> +string @var{from}.  This means that @samp{@var{result} >= @var{size}} is
> +true whenever truncation occurs.
> +
> +The behavior of @code{strlcpy} is undefined if @var{size} is zero, or if
> +the source string and the first @var{size} bytes of the destination
> +array overlap.
> +
> +As noted below, this function is generally a poor choice for processing
> +text.  Unlike @code{strncpy}, @code{strlcpy} requires @var{size} to be
> +nonzero and the source string to be null-terminated, computes the
> +source string's length, ensures that the destination is
> +null-terminated, and does not fill the remaining part of the destination
> +with null bytes.
> +
> +This function is derived from OpenBSD 2.4.

Given that we're putting it in to comply with a future POSIX version, 
shouldn't that be mentioned instead of OpenBSD?  Or maybe both?

> +@end deftypefun
> +
> +@deftypefun size_t strlcat (char *restrict @var{to}, const char *restrict @var{from}, size_t @var{size})
> +@standards{BSD, string.h}
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +This function appends the string @var{from} to the
> +string @var{to}, limiting the total size of the result string at
> +@var{to} (including the null terminator) to @var{size}.
> +
> +This function copies as much as possible of the string @var{from} into
> +the array at @var{to} of @var{size} bytes, starting at the terminating
> +null byte of the original string @var{to}.  In effect, this appends
> +the string @var{from} to the string @var{to}.  Although the resulting
> +string will contain a null terminator, it can be truncated (not all
> +bytes in @var{from} may be copied).
> +
> +This function returns the sum of the original length of @var{to} and
> +the length of @var{from}.  This means that truncation occurs unless
> +the returned value is less than @var{size}.

Maybe rephrase it in the positive, e.g.:

     This means that if the returned value is greater than or equal to
     size, the result is truncated.

> +
> +The behavior is undefined if the array at @var{to} does not contain a
> +null byte in its first @var{size} bytes, or if the source string and the
> +first @var{size} bytes of @var{to} overlap.
> +
> +As noted below, this function is generally a poor choice for processing
> +text.  Also, this function has significant performance issues;
> +@pxref{Concatenating Strings}.  Unlike @code{strncat}, @var{size}
> +specifies the maximum total size of the result string (including its
> +null terminator), not the number of bytes copied from the source string
> +@var{from}.  Unlike @code{strncat}, this function requires the source
> +and destination to be null-terminated, computes the source string's
> +length, and keeps the destination null-terminated.
> +
> +This function is derived from OpenBSD 2.4.

Likewise.

> +@end deftypefun
> +
>   Because these functions can abruptly truncate strings or wide strings,
>   they are generally poor choices for processing text.  When coping or
>   concatening multibyte strings, they can truncate within a multibyte
> diff --git a/string/Makefile b/string/Makefile
> index 641e062bbb..5ee11c467c 100644
> --- a/string/Makefile
> +++ b/string/Makefile
> @@ -92,6 +92,8 @@ routines := \
>     strerrorname_np \
>     strfry \
>     string-inlines \
> +  strlcat \
> +  strlcpy \
>     strlen \
>     strncase \
>     strncase_l \
> @@ -175,6 +177,8 @@ tests := \
>     tst-inlcall \
>     tst-memmove-overflow \
>     tst-strfry \
> +  tst-strlcat \
> +  tst-strlcpy \
>     tst-strlen \
>     tst-strtok \
>     tst-strtok_r \
> diff --git a/string/Versions b/string/Versions
> index 864c4cf7a4..fbe008c833 100644
> --- a/string/Versions
> +++ b/string/Versions
> @@ -92,4 +92,8 @@ libc {
>     GLIBC_2.35 {
>       __memcmpeq;
>     }
> +  GLIBC_2.36 {
> +    strlcpy;
> +    strlcat;
> +  }
>   }
> diff --git a/string/bits/string_fortified.h b/string/bits/string_fortified.h
> index 149ebbb08b..91240f1d1c 100644
> --- a/string/bits/string_fortified.h
> +++ b/string/bits/string_fortified.h
> @@ -139,4 +139,38 @@ __NTH (strncat (char *__restrict __dest, const char *__restrict __src,
>   				  __glibc_objsize (__dest));
>   }
>   
> +#ifdef __USE_MISC
> +extern size_t __strlcpy_chk (char *__dest, const char *__src, size_t __n,
> +			     size_t __destlen) __THROW;
> +extern size_t __REDIRECT_NTH (__strlcpy_alias,
> +			      (char *__dest, const char *__src, size_t __n),
> +			      strlcpy);
> +
> +__fortify_function size_t
> +__NTH (strlcpy (char *__restrict __dest, const char *__restrict __src,
> +		size_t __len))
> +{
> +  if (__builtin_constant_p (__bos (__dest) == (size_t) -1)
> +      && __bos (__dest) == (size_t) -1)
> +    return __strlcpy_alias (__dest, __src, __len);
> +  return __strlcpy_chk (__dest, __src, __len, __bos (__dest));
> +}
> +
> +extern size_t __strlcat_chk (char *__dest, const char *__src, size_t __n,
> +			     size_t __destlen) __THROW;
> +extern size_t __REDIRECT_NTH (__strlcat_alias,
> +			      (char *__dest, const char *__src, size_t __n),
> +			      strlcat);
> +
> +__fortify_function size_t
> +__NTH (strlcat (char *__restrict __dest, const char *__restrict __src,
> +		size_t __len))
> +{
> +  if (__builtin_constant_p (__bos (__dest) == (size_t) -1)
> +      && __bos (__dest) == (size_t) -1)
> +    return __strlcat_alias (__dest, __src, __len);
> +  return __strlcat_chk (__dest, __src, __len, __bos (__dest));

Maybe use __glibc_fortify?

> +}
> +#endif /* __USE_MISC */
> +
>   #endif /* bits/string_fortified.h */
> diff --git a/string/string.h b/string/string.h
> index 54dd8344de..51241018c3 100644
> --- a/string/string.h
> +++ b/string/string.h
> @@ -501,6 +501,19 @@ extern char *stpncpy (char *__restrict __dest,
>        __THROW __nonnull ((1, 2));
>   #endif
>   
> +#ifdef __USE_MISC
> +/* Copy at most N - 1 characters from SRC to DEST.  */
> +extern size_t strlcpy (char *__restrict __dest,
> +		       const char *__restrict __src, size_t __n)
> +  __THROW __nonnull ((1, 2)) __attr_access ((__write_only__, 1, 3));
> +
> +/* Append SRC to DEST, possibly with truncation to keep the total size
> +   below N.  */
> +extern size_t strlcat (char *__restrict __dest,
> +		       const char *__restrict __src, size_t __n)
> +  __THROW __nonnull ((1, 2))  __attr_access ((__read_write__, 1, 3));
> +#endif
> +

The __attr_access will result in a warning if size of dst is smaller 
than dstsize (i.e. argument 3).  Like the _chk variant case, it doesn't 
match with the manual.

>   #ifdef	__USE_GNU
>   /* Compare S1 and S2 as strings holding name & indices/version numbers.  */
>   extern int strverscmp (const char *__s1, const char *__s2)
> diff --git a/string/strlcat.c b/string/strlcat.c
> new file mode 100644
> index 0000000000..297923ad9b
> --- /dev/null
> +++ b/string/strlcat.c
> @@ -0,0 +1,60 @@
> +/* Append a null-terminated string to another string, with length checking.
> +   Copyright (C) 2017 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <stdint.h>
> +#include <string.h>
> +
> +#undef strlcat
> +
> +size_t
> +strlcat (char *__restrict dest, const char *__restrict src, size_t size)
> +{
> +  size_t src_length = strlen (src);
> +
> +  /* Our implementation strlcat supports dest == NULL if size == 0

Does it though?  The header specifies __nonnull (1, 2), which should 
warn on NUL input.  Maybe this needs test coverage.

> +     (for consistency with snprintf and strlcpy), but strnlen does
> +     not, so we have to cover this case explicitly.  */
> +  if (size == 0)
> +    return src_length;
> +
> +  size_t dest_length = __strnlen (dest, size);

dst is allowed to be a string in strlcat.  OK.

> +  if (dest_length != size)
> +    {
> +      /* Copy at most the remaining number of characters in the
> +	 destination buffer.  Leave for the NUL terminator.  */
> +      size_t to_copy = size - dest_length - 1;

Implicit assumption that size - 1 > dest_length.  I suppose the wording 
allows it.

> +      /* But not more than what is available in the source string.  */
> +      if (to_copy > src_length)
> +	to_copy = src_length;
> +
> +      char *target = dest + dest_length;
> +      memcpy (target, src, to_copy);
> +      target[to_copy] = '\0';

Overwrites the NUL at the end of dest, copies without the NUL and then 
writes the NUL at the end.  OK.

> +    }
> +
> +  /* If the sum wraps around, we have more than SIZE_MAX + 2 bytes in
> +     the two input strings (including both null terminators).  If each
> +     byte in the address space can be assigned a unique size_t value
> +     (which the static_assert checks), then by the pigeonhole
> +     principle, the two input strings must overlap, which is
> +     undefined.  */
> +  _Static_assert (sizeof (uintptr_t) == sizeof (size_t),
> +		  "theoretical maximum object size covers address space");
> +  return dest_length + src_length;
> +}
> +libc_hidden_def (strlcat)
> diff --git a/string/strlcpy.c b/string/strlcpy.c
> new file mode 100644
> index 0000000000..d0764e9b64
> --- /dev/null
> +++ b/string/strlcpy.c
> @@ -0,0 +1,47 @@
> +/* Copy a null-terminated string to a fixed-size buffer, with length checking.
> +   Copyright (C) 2017 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <string.h>
> +
> +#undef strlcpy
> +
> +size_t
> +strlcpy (char *__restrict dest, const char *__restrict src, size_t size)
> +{
> +  size_t src_length = strlen (src);
> +
> +  if (__glibc_unlikely (src_length >= size))
> +    {
> +      if (size > 0)
> +	{
> +	  /* Copy the leading portion of the string.  The last
> +	     character is subsequently overwritten with the NUL
> +	     terminator, but the destination size is usually a
> +	     multiple of a small power of two, so writing it twice
> +	     should be more efficient than copying an odd number of
> +	     bytes.  */

That's not necessary for all arches, but it's too early to talk of 
micro-optimization so whatever you choose is fine I think.

> +	  memcpy (dest, src, size);
> +	  dest[size - 1] = '\0';
> +	}
> +    }
> +  else
> +    /* Copy the string and its terminating NUL character.  */
> +    memcpy (dest, src, src_length + 1);

Going by POSIX wording, it should copy src_length and *write* the last 
NUL, not copy it from src.  Only an academic difference again.  That 
said though, you could just collapse the whole thing to:

if (size > 0)
   {
     size_t n = src_length >= size ? size - 1 : src_length;
     memcpy (dest, src, n);
     dest[n] = '\0';
   }

and then tune it later based on workloads and architectures.

> +  return src_length;
> +}
> +libc_hidden_def (strlcpy)
> diff --git a/string/tst-strlcat.c b/string/tst-strlcat.c
> new file mode 100644
> index 0000000000..805524754a
> --- /dev/null
> +++ b/string/tst-strlcat.c
> @@ -0,0 +1,90 @@
> +/* Test the strlcat function.
> +   Copyright (C) 2017 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <string.h>
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <support/check.h>
> +
> +static int
> +do_test (void)
> +{
> +  struct {
> +    char buf1[16];
> +    char buf2[16];
> +  } s;
> +
> +  /* Nothing is written to the destination if its size is 0.  */
> +  memset (&s, '@', sizeof (s));
> +  TEST_VERIFY (strlcat (s.buf1, "", 0) == 0);
> +  TEST_VERIFY (memcmp (&s, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
> +		       sizeof (s)) == 0);
> +  TEST_VERIFY (strlcat (s.buf1, "Hello!", 0) == 6);
> +  TEST_VERIFY (memcmp (&s, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
> +		       sizeof (s)) == 0);
> +
> +  /* No bytes are are modified in the target buffer if the source
> +     string is short enough.  */
> +  memset (&s, '@', sizeof (s));
> +  strcpy (s.buf1, "He");
> +  TEST_VERIFY (strlcat (s.buf1, "llo!", sizeof (s.buf1)) == 6);
> +  TEST_VERIFY (memcmp (&s, "Hello!\0@@@@@@@@@@@@@@@@@@@@@@@@@",
> +		       sizeof (s)) == 0);
> +
> +  /* A source string which fits exactly into the destination buffer is
> +     not truncated.  */
> +  memset (&s, '@', sizeof (s));
> +  strcpy (s.buf1, "H");
> +  TEST_VERIFY (strlcat (s.buf1, "ello, world!!!", sizeof (s.buf1)) == 15);
> +  TEST_VERIFY (memcmp (&s, "Hello, world!!!\0@@@@@@@@@@@@@@@@@@@@@@@@@",
> +		 sizeof (s)) == 0);
> +
> +  /* A source string one character longer than the destination buffer
> +     is truncated by one character.  The total length is returned.  */
> +  memset (&s, '@', sizeof (s));
> +  strcpy (s.buf1, "Hello");
> +  TEST_VERIFY (strlcat (s.buf1, ", world!!!!", sizeof (s.buf1)) == 16);
> +  TEST_VERIFY (memcmp (&s, "Hello, world!!!\0@@@@@@@@@@@@@@@@@@@@@@@@@",
> +		 sizeof (s)) == 0);
> +
> +  /* An even longer source string is truncated as well, and the total
> +     length is returned.  */
> +  memset (&s, '@', sizeof (s));
> +  strcpy (s.buf1, "Hello,");
> +  TEST_VERIFY (strlcat (s.buf1, " world!!!!!!!!", sizeof (s.buf1)) == 20);
> +  TEST_VERIFY (memcmp (&s, "Hello, world!!!\0@@@@@@@@@@@@@@@@@@@@@@@@@",
> +		 sizeof (s)) == 0);
> +
> +  /* A destination string which is not NUL-terminated does not result
> +     in any changes to the buffer.  */
> +  memset (&s, '@', sizeof (s));
> +  memset (s.buf1, '$', sizeof (s.buf1));
> +  TEST_VERIFY (strlcat (s.buf1, "", sizeof (s.buf1)) == 16);
> +  TEST_VERIFY (memcmp (&s, "$$$$$$$$$$$$$$$$@@@@@@@@@@@@@@@@",
> +		       sizeof (s)) == 0);
> +  TEST_VERIFY (strlcat (s.buf1, "Hello!", sizeof (s.buf1)) == 22);
> +  TEST_VERIFY (memcmp (&s, "$$$$$$$$$$$$$$$$@@@@@@@@@@@@@@@@",
> +		       sizeof (s)) == 0);
> +  TEST_VERIFY (strlcat (s.buf1, "Hello, world!!!!!!!!", sizeof (s.buf1)) == 36);
> +  TEST_VERIFY (memcmp (&s, "$$$$$$$$$$$$$$$$@@@@@@@@@@@@@@@@",
> +		       sizeof (s)) == 0);
> +
> +  return 0;
> +}
> +
> +#include <support/test-driver.c>
> diff --git a/string/tst-strlcpy.c b/string/tst-strlcpy.c
> new file mode 100644
> index 0000000000..16bc75c067
> --- /dev/null
> +++ b/string/tst-strlcpy.c
> @@ -0,0 +1,70 @@
> +/* Test the strlcpy function.
> +   Copyright (C) 2017 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <string.h>
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <support/check.h>
> +
> +static int
> +do_test (void)
> +{
> +  struct {
> +    char buf1[16];
> +    char buf2[16];
> +  } s;
> +
> +  /* Nothing is written to the destination if its size is 0.  */
> +  memset (&s, '@', sizeof (s));
> +  TEST_VERIFY (strlcpy (s.buf1, "Hello!", 0) == 6);
> +  TEST_VERIFY (memcmp (&s, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
> +		       sizeof (s)) == 0);
> +
> +  /* No bytes are are modified in the target buffer if the source
> +     string is short enough.  */
> +  memset (&s, '@', sizeof (s));
> +  TEST_VERIFY (strlcpy (s.buf1, "Hello!", sizeof (s.buf1)) == 6);
> +  TEST_VERIFY (memcmp (&s, "Hello!\0@@@@@@@@@@@@@@@@@@@@@@@@@",
> +		       sizeof (s)) == 0);
> +
> +  /* A source string which fits exactly into the destination buffer is
> +     not truncated.  */
> +  memset (&s, '@', sizeof (s));
> +  TEST_VERIFY (strlcpy (s.buf1, "Hello, world!!!", sizeof (s.buf1)) == 15);
> +  TEST_VERIFY (memcmp (&s, "Hello, world!!!\0@@@@@@@@@@@@@@@@@@@@@@@@@",
> +		       sizeof (s)) == 0);
> +
> +  /* A source string one character longer than the destination buffer
> +     is truncated by one character.  The untruncated source length is
> +     returned.  */
> +  memset (&s, '@', sizeof (s));
> +  TEST_VERIFY (strlcpy (s.buf1, "Hello, world!!!!", sizeof (s.buf1)) == 16);
> +  TEST_VERIFY (memcmp (&s, "Hello, world!!!\0@@@@@@@@@@@@@@@@@@@@@@@@@",
> +		       sizeof (s)) == 0);
> +
> +  /* An even longer source string is truncated as well, and the
> +     original length is returned.  */
> +  memset (&s, '@', sizeof (s));
> +  TEST_VERIFY (strlcpy (s.buf1, "Hello, world!!!!!!!!", sizeof (s.buf1)) == 20);
> +  TEST_VERIFY (memcmp (&s, "Hello, world!!!\0@@@@@@@@@@@@@@@@@@@@@@@@@",
> +		       sizeof (s)) == 0);
> +
> +  return 0;
> +}
> +
> +#include <support/test-driver.c>
> diff --git a/sysdeps/mach/hurd/i386/libc.abilist b/sysdeps/mach/hurd/i386/libc.abilist
> index 4dc87e9061..57ab83842f 100644
> --- a/sysdeps/mach/hurd/i386/libc.abilist
> +++ b/sysdeps/mach/hurd/i386/libc.abilist
> @@ -2289,6 +2289,10 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 close_range F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
>   GLIBC_2.4 __confstr_chk F
>   GLIBC_2.4 __fgets_chk F
>   GLIBC_2.4 __fgets_unlocked_chk F
> diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> index 8dba065b81..79593721f7 100644
> --- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> @@ -2616,6 +2616,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2624,3 +2626,5 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
> diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
> index 08f4750022..8e1588e0a6 100644
> --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
> @@ -2713,6 +2713,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2721,6 +2723,8 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
>   GLIBC_2.4 _IO_fprintf F
>   GLIBC_2.4 _IO_printf F
>   GLIBC_2.4 _IO_sprintf F
> diff --git a/sysdeps/unix/sysv/linux/arc/libc.abilist b/sysdeps/unix/sysv/linux/arc/libc.abilist
> index 75db763023..589f32ef7d 100644
> --- a/sysdeps/unix/sysv/linux/arc/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/arc/libc.abilist
> @@ -2377,6 +2377,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2385,3 +2387,5 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
> diff --git a/sysdeps/unix/sysv/linux/arm/be/libc.abilist b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
> index fa33f317ac..66aad3e945 100644
> --- a/sysdeps/unix/sysv/linux/arm/be/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
> @@ -496,6 +496,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -504,6 +506,8 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
>   GLIBC_2.4 _Exit F
>   GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
>   GLIBC_2.4 _IO_2_1_stdin_ D 0xa0
> diff --git a/sysdeps/unix/sysv/linux/arm/le/libc.abilist b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
> index dba2e4ce42..da3a1bce34 100644
> --- a/sysdeps/unix/sysv/linux/arm/le/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
> @@ -493,6 +493,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -501,6 +503,8 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
>   GLIBC_2.4 _Exit F
>   GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
>   GLIBC_2.4 _IO_2_1_stdin_ D 0xa0
> diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist
> index e6ff921c29..c2ea825539 100644
> --- a/sysdeps/unix/sysv/linux/csky/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/csky/libc.abilist
> @@ -2652,6 +2652,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2660,3 +2662,5 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
> diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
> index 8a40cece83..4859a686a6 100644
> --- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
> @@ -2601,6 +2601,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2609,6 +2611,8 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
>   GLIBC_2.4 __confstr_chk F
>   GLIBC_2.4 __fgets_chk F
>   GLIBC_2.4 __fgets_unlocked_chk F
> diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
> index a89826049f..2547999a77 100644
> --- a/sysdeps/unix/sysv/linux/i386/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
> @@ -2785,6 +2785,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2793,6 +2795,8 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
>   GLIBC_2.4 __confstr_chk F
>   GLIBC_2.4 __fgets_chk F
>   GLIBC_2.4 __fgets_unlocked_chk F
> diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
> index d1d96b7469..a8c73d31f6 100644
> --- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
> @@ -2551,6 +2551,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2559,6 +2561,8 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
>   GLIBC_2.4 __confstr_chk F
>   GLIBC_2.4 __fgets_chk F
>   GLIBC_2.4 __fgets_unlocked_chk F
> diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> index 63a62f267a..0f419bfd22 100644
> --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> @@ -497,6 +497,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -505,6 +507,8 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
>   GLIBC_2.4 _Exit F
>   GLIBC_2.4 _IO_2_1_stderr_ D 0x98
>   GLIBC_2.4 _IO_2_1_stdin_ D 0x98
> diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> index f68325f9bc..aa6332040f 100644
> --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> @@ -2728,6 +2728,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2736,6 +2738,8 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
>   GLIBC_2.4 __confstr_chk F
>   GLIBC_2.4 __fgets_chk F
>   GLIBC_2.4 __fgets_unlocked_chk F
> diff --git a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
> index 247af2075c..ab63dbacd6 100644
> --- a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
> @@ -2701,6 +2701,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2709,3 +2711,5 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
> diff --git a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
> index b0ac3f9009..4f55786882 100644
> --- a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
> @@ -2698,6 +2698,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2706,3 +2708,5 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> index b22cd6bf2f..44d5c4e115 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> @@ -2693,6 +2693,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2701,6 +2703,8 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
>   GLIBC_2.4 __confstr_chk F
>   GLIBC_2.4 __fgets_chk F
>   GLIBC_2.4 __fgets_unlocked_chk F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> index 12fc2cce3e..cf8f7690fd 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> @@ -2691,6 +2691,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2699,6 +2701,8 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
>   GLIBC_2.4 __confstr_chk F
>   GLIBC_2.4 __fgets_chk F
>   GLIBC_2.4 __fgets_unlocked_chk F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> index d3e96dfd43..1ee70f2e2a 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> @@ -2699,6 +2699,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2707,6 +2709,8 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
>   GLIBC_2.4 __confstr_chk F
>   GLIBC_2.4 __fgets_chk F
>   GLIBC_2.4 __fgets_unlocked_chk F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> index cb58ed4db0..99ec7125af 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> @@ -2602,6 +2602,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2610,6 +2612,8 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
>   GLIBC_2.4 __confstr_chk F
>   GLIBC_2.4 __fgets_chk F
>   GLIBC_2.4 __fgets_unlocked_chk F
> diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
> index 61ad58a599..98be295843 100644
> --- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
> @@ -2740,6 +2740,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2748,3 +2750,5 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
> diff --git a/sysdeps/unix/sysv/linux/or1k/libc.abilist b/sysdeps/unix/sysv/linux/or1k/libc.abilist
> index 1260dc4e2e..dc368582af 100644
> --- a/sysdeps/unix/sysv/linux/or1k/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/or1k/libc.abilist
> @@ -2123,6 +2123,8 @@ GLIBC_2.35 wprintf F
>   GLIBC_2.35 write F
>   GLIBC_2.35 writev F
>   GLIBC_2.35 wscanf F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2131,3 +2133,5 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> index 363939762c..f5f8a57079 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> @@ -2755,6 +2755,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2763,6 +2765,8 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
>   GLIBC_2.4 _IO_fprintf F
>   GLIBC_2.4 _IO_printf F
>   GLIBC_2.4 _IO_sprintf F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
> index f512ad8baf..396c5b7ae0 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
> @@ -2788,6 +2788,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2796,6 +2798,8 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
>   GLIBC_2.4 _IO_fprintf F
>   GLIBC_2.4 _IO_printf F
>   GLIBC_2.4 _IO_sprintf F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
> index c9bdc9859c..523e01c0ca 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
> @@ -2510,6 +2510,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2518,6 +2520,8 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
>   GLIBC_2.4 _IO_fprintf F
>   GLIBC_2.4 _IO_printf F
>   GLIBC_2.4 _IO_sprintf F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
> index f091be30bd..0c412e3072 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
> @@ -2812,6 +2812,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2820,3 +2822,5 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
> diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
> index 7ea73f9af8..3703c33c07 100644
> --- a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
> @@ -2379,6 +2379,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2387,3 +2389,5 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
> diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
> index 333fa62714..9a719fdfe3 100644
> --- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
> @@ -2579,6 +2579,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2587,3 +2589,5 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> index a867467b12..5f05b253d5 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> @@ -2753,6 +2753,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2761,6 +2763,8 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
>   GLIBC_2.4 _IO_fprintf F
>   GLIBC_2.4 _IO_printf F
>   GLIBC_2.4 _IO_sprintf F
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> index dbad5b3163..36e78d7cb2 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> @@ -2547,6 +2547,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2555,6 +2557,8 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
>   GLIBC_2.4 _IO_fprintf F
>   GLIBC_2.4 _IO_printf F
>   GLIBC_2.4 _IO_sprintf F
> diff --git a/sysdeps/unix/sysv/linux/sh/be/libc.abilist b/sysdeps/unix/sysv/linux/sh/be/libc.abilist
> index 6f755cc173..6ccdc54d27 100644
> --- a/sysdeps/unix/sysv/linux/sh/be/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sh/be/libc.abilist
> @@ -2608,6 +2608,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2616,6 +2618,8 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
>   GLIBC_2.4 __confstr_chk F
>   GLIBC_2.4 __fgets_chk F
>   GLIBC_2.4 __fgets_unlocked_chk F
> diff --git a/sysdeps/unix/sysv/linux/sh/le/libc.abilist b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
> index 77d936aa3c..647834425f 100644
> --- a/sysdeps/unix/sysv/linux/sh/le/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
> @@ -2605,6 +2605,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2613,6 +2615,8 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
>   GLIBC_2.4 __confstr_chk F
>   GLIBC_2.4 __fgets_chk F
>   GLIBC_2.4 __fgets_unlocked_chk F
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> index 09bb4363e1..fe16974926 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> @@ -2748,6 +2748,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2756,6 +2758,8 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
>   GLIBC_2.4 _IO_fprintf F
>   GLIBC_2.4 _IO_printf F
>   GLIBC_2.4 _IO_sprintf F
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> index 9df9cb6adb..f661ba5b4a 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> @@ -2574,6 +2574,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2582,6 +2584,8 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
>   GLIBC_2.4 __confstr_chk F
>   GLIBC_2.4 __fgets_chk F
>   GLIBC_2.4 __fgets_unlocked_chk F
> diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> index 4829450ad0..e170c64b77 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> @@ -2525,6 +2525,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2533,6 +2535,8 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
>   GLIBC_2.4 __confstr_chk F
>   GLIBC_2.4 __fgets_chk F
>   GLIBC_2.4 __fgets_unlocked_chk F
> diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> index caea228bcb..8c4cefcb09 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> @@ -2631,6 +2631,8 @@ GLIBC_2.35 __memcmpeq F
>   GLIBC_2.35 _dl_find_object F
>   GLIBC_2.35 epoll_pwait2 F
>   GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
> +GLIBC_2.36 __strlcat_chk F
> +GLIBC_2.36 __strlcpy_chk F
>   GLIBC_2.36 fsmount F
>   GLIBC_2.36 fsopen F
>   GLIBC_2.36 move_mount F
> @@ -2639,3 +2641,5 @@ GLIBC_2.36 pidfd_open F
>   GLIBC_2.36 pidfd_send_signal F
>   GLIBC_2.36 process_madvise F
>   GLIBC_2.36 process_mrelease F
> +GLIBC_2.36 strlcat F
> +GLIBC_2.36 strlcpy F
>
  

Patch

diff --git a/NEWS b/NEWS
index b0a3d7e512..74829a30a6 100644
--- a/NEWS
+++ b/NEWS
@@ -46,6 +46,8 @@  Major new features:
   to more flexibly configure and operate on filesystem mounts.  The new
   mount APIs are specifically designed to work with namespaces.
 
+* The functions strlcpy and strlcat have been added.
+
 Deprecated and removed features, and other changes affecting compatibility:
 
 * Support for prelink will be removed in the next release; this includes
diff --git a/debug/Makefile b/debug/Makefile
index 456b349c4d..abb0a85b03 100644
--- a/debug/Makefile
+++ b/debug/Makefile
@@ -31,6 +31,7 @@  headers	:= execinfo.h
 routines  = backtrace backtracesyms backtracesymsfd noophooks \
 	    memcpy_chk memmove_chk mempcpy_chk memset_chk stpcpy_chk \
 	    strcat_chk strcpy_chk strncat_chk strncpy_chk stpncpy_chk \
+	    strlcpy_chk strlcat_chk \
 	    sprintf_chk vsprintf_chk snprintf_chk vsnprintf_chk \
 	    printf_chk fprintf_chk vprintf_chk vfprintf_chk \
 	    gets_chk chk_fail readonly-area fgets_chk fgets_u_chk \
diff --git a/debug/Versions b/debug/Versions
index a6628db356..a4bfbcfee6 100644
--- a/debug/Versions
+++ b/debug/Versions
@@ -58,6 +58,10 @@  libc {
   GLIBC_2.25 {
     __explicit_bzero_chk;
   }
+  GLIBC_2.36 {
+    __strlcpy_chk;
+    __strlcat_chk;
+  }
   GLIBC_PRIVATE {
     __fortify_fail;
   }
diff --git a/debug/strlcat_chk.c b/debug/strlcat_chk.c
new file mode 100644
index 0000000000..15e4182229
--- /dev/null
+++ b/debug/strlcat_chk.c
@@ -0,0 +1,32 @@ 
+/* Fortified version of strlcat.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+#include <memcopy.h>
+
+/* Check that the user-supplied size does not exceed the
+   compiler-determined size, and then forward to strlcat.  */
+size_t
+__strlcat_chk (char *__restrict s1, const char *__restrict s2,
+	       size_t n, size_t s1len)
+{
+  if (__glibc_unlikely (s1len < n))
+    __chk_fail ();
+
+  return strlcat (s1, s2, n);
+}
diff --git a/debug/strlcpy_chk.c b/debug/strlcpy_chk.c
new file mode 100644
index 0000000000..1bcb12b793
--- /dev/null
+++ b/debug/strlcpy_chk.c
@@ -0,0 +1,32 @@ 
+/* Fortified version of strlcpy.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+#include <memcopy.h>
+
+/* Check that the user-supplied size does not exceed the
+   compiler-determined size, and then forward to strlcpy.  */
+size_t
+__strlcpy_chk (char *__restrict s1, const char *__restrict s2,
+	       size_t n, size_t s1len)
+{
+  if (__glibc_unlikely (s1len < n))
+    __chk_fail ();
+
+  return strlcpy (s1, s2, n);
+}
diff --git a/debug/tst-fortify.c b/debug/tst-fortify.c
index 8e94643bf2..d4ead37c77 100644
--- a/debug/tst-fortify.c
+++ b/debug/tst-fortify.c
@@ -535,6 +535,16 @@  do_test (void)
   strncpy (a.buf1 + (O + 6), "X", l0 + 4);
   CHK_FAIL_END
 
+  CHK_FAIL_START
+  strlcpy (buf, "", sizeof (buf) + 1);
+  CHK_FAIL_END
+
+  {
+    char *volatile buf2 = buf;
+    if (strlcpy (buf2, "a", sizeof (buf) + 1) != 1)
+      FAIL ();
+  }
+
 # if !defined __cplusplus || defined __va_arg_pack
   CHK_FAIL_START
   sprintf (a.buf1 + (O + 7), "%d", num1);
@@ -558,6 +568,18 @@  do_test (void)
   CHK_FAIL_START
   strncat (a.buf1, "ZYXWV", l0 + 3);
   CHK_FAIL_END
+
+  buf[0] = '\0';
+  CHK_FAIL_START
+  strlcat (buf, "ZYXWV", sizeof (buf) + 1);
+  CHK_FAIL_END
+
+  {
+    buf[0] = '\0';
+    char *volatile buf2 = buf;
+    if (strlcat (buf2, "a", sizeof (buf) + 1) != 1)
+      FAIL ();
+  }
 #endif
 
 
diff --git a/include/string.h b/include/string.h
index 21f641a413..b01b2fb2b4 100644
--- a/include/string.h
+++ b/include/string.h
@@ -91,6 +91,8 @@  libc_hidden_proto (__stpcpy)
 # define __stpcpy(dest, src) __builtin_stpcpy (dest, src)
 #endif
 libc_hidden_proto (__stpncpy)
+libc_hidden_proto (strlcpy)
+libc_hidden_proto (strlcat)
 libc_hidden_proto (__rawmemchr)
 libc_hidden_proto (__strcasecmp)
 libc_hidden_proto (__strcasecmp_l)
diff --git a/manual/string.texi b/manual/string.texi
index 0b60b3fbb4..c2f4d3b2de 100644
--- a/manual/string.texi
+++ b/manual/string.texi
@@ -1068,6 +1068,76 @@  processing text.  Also, this function has significant performance
 issues.  @xref{Concatenating Strings}.
 @end deftypefun
 
+@deftypefun size_t strlcpy (char *restrict @var{to}, const char *restrict @var{from}, size_t @var{size})
+@standards{BSD, string.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+This function is similar to @code{strcpy}, but copies at most
+@var{size} bytes from the string @var{from} into the destination
+array @var{to}, including a terminating null byte.
+
+If @var{size} is greater than the length of the string @var{from},
+this function copies all of the string @var{from} to the destination
+array @var{to}, including the terminating null byte.  Like other
+string functions such as @code{strcpy}, but unlike @code{strncpy}, any
+remaining bytes in the destination array remain unchanged.
+
+If @var{size} is nonzero and less than or equal to the the length of the string
+@var{from}, this function copies only the first @samp{@var{size} - 1}
+bytes to the destination array @var{to}, and writes a terminating null
+byte to the last byte of the array.
+
+The return value @var{result} of @code{strlcpy} is the length of the
+string @var{from}.  This means that @samp{@var{result} >= @var{size}} is
+true whenever truncation occurs.
+
+The behavior of @code{strlcpy} is undefined if @var{size} is zero, or if
+the source string and the first @var{size} bytes of the destination
+array overlap.
+
+As noted below, this function is generally a poor choice for processing
+text.  Unlike @code{strncpy}, @code{strlcpy} requires @var{size} to be
+nonzero and the source string to be null-terminated, computes the
+source string's length, ensures that the destination is
+null-terminated, and does not fill the remaining part of the destination
+with null bytes.
+
+This function is derived from OpenBSD 2.4.
+@end deftypefun
+
+@deftypefun size_t strlcat (char *restrict @var{to}, const char *restrict @var{from}, size_t @var{size})
+@standards{BSD, string.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+This function appends the string @var{from} to the
+string @var{to}, limiting the total size of the result string at
+@var{to} (including the null terminator) to @var{size}.
+
+This function copies as much as possible of the string @var{from} into
+the array at @var{to} of @var{size} bytes, starting at the terminating
+null byte of the original string @var{to}.  In effect, this appends
+the string @var{from} to the string @var{to}.  Although the resulting
+string will contain a null terminator, it can be truncated (not all
+bytes in @var{from} may be copied).
+
+This function returns the sum of the original length of @var{to} and
+the length of @var{from}.  This means that truncation occurs unless
+the returned value is less than @var{size}.
+
+The behavior is undefined if the array at @var{to} does not contain a
+null byte in its first @var{size} bytes, or if the source string and the
+first @var{size} bytes of @var{to} overlap.
+
+As noted below, this function is generally a poor choice for processing
+text.  Also, this function has significant performance issues;
+@pxref{Concatenating Strings}.  Unlike @code{strncat}, @var{size}
+specifies the maximum total size of the result string (including its
+null terminator), not the number of bytes copied from the source string
+@var{from}.  Unlike @code{strncat}, this function requires the source
+and destination to be null-terminated, computes the source string's
+length, and keeps the destination null-terminated.
+
+This function is derived from OpenBSD 2.4.
+@end deftypefun
+
 Because these functions can abruptly truncate strings or wide strings,
 they are generally poor choices for processing text.  When coping or
 concatening multibyte strings, they can truncate within a multibyte
diff --git a/string/Makefile b/string/Makefile
index 641e062bbb..5ee11c467c 100644
--- a/string/Makefile
+++ b/string/Makefile
@@ -92,6 +92,8 @@  routines := \
   strerrorname_np \
   strfry \
   string-inlines \
+  strlcat \
+  strlcpy \
   strlen \
   strncase \
   strncase_l \
@@ -175,6 +177,8 @@  tests := \
   tst-inlcall \
   tst-memmove-overflow \
   tst-strfry \
+  tst-strlcat \
+  tst-strlcpy \
   tst-strlen \
   tst-strtok \
   tst-strtok_r \
diff --git a/string/Versions b/string/Versions
index 864c4cf7a4..fbe008c833 100644
--- a/string/Versions
+++ b/string/Versions
@@ -92,4 +92,8 @@  libc {
   GLIBC_2.35 {
     __memcmpeq;
   }
+  GLIBC_2.36 {
+    strlcpy;
+    strlcat;
+  }
 }
diff --git a/string/bits/string_fortified.h b/string/bits/string_fortified.h
index 149ebbb08b..91240f1d1c 100644
--- a/string/bits/string_fortified.h
+++ b/string/bits/string_fortified.h
@@ -139,4 +139,38 @@  __NTH (strncat (char *__restrict __dest, const char *__restrict __src,
 				  __glibc_objsize (__dest));
 }
 
+#ifdef __USE_MISC
+extern size_t __strlcpy_chk (char *__dest, const char *__src, size_t __n,
+			     size_t __destlen) __THROW;
+extern size_t __REDIRECT_NTH (__strlcpy_alias,
+			      (char *__dest, const char *__src, size_t __n),
+			      strlcpy);
+
+__fortify_function size_t
+__NTH (strlcpy (char *__restrict __dest, const char *__restrict __src,
+		size_t __len))
+{
+  if (__builtin_constant_p (__bos (__dest) == (size_t) -1)
+      && __bos (__dest) == (size_t) -1)
+    return __strlcpy_alias (__dest, __src, __len);
+  return __strlcpy_chk (__dest, __src, __len, __bos (__dest));
+}
+
+extern size_t __strlcat_chk (char *__dest, const char *__src, size_t __n,
+			     size_t __destlen) __THROW;
+extern size_t __REDIRECT_NTH (__strlcat_alias,
+			      (char *__dest, const char *__src, size_t __n),
+			      strlcat);
+
+__fortify_function size_t
+__NTH (strlcat (char *__restrict __dest, const char *__restrict __src,
+		size_t __len))
+{
+  if (__builtin_constant_p (__bos (__dest) == (size_t) -1)
+      && __bos (__dest) == (size_t) -1)
+    return __strlcat_alias (__dest, __src, __len);
+  return __strlcat_chk (__dest, __src, __len, __bos (__dest));
+}
+#endif /* __USE_MISC */
+
 #endif /* bits/string_fortified.h */
diff --git a/string/string.h b/string/string.h
index 54dd8344de..51241018c3 100644
--- a/string/string.h
+++ b/string/string.h
@@ -501,6 +501,19 @@  extern char *stpncpy (char *__restrict __dest,
      __THROW __nonnull ((1, 2));
 #endif
 
+#ifdef __USE_MISC
+/* Copy at most N - 1 characters from SRC to DEST.  */
+extern size_t strlcpy (char *__restrict __dest,
+		       const char *__restrict __src, size_t __n)
+  __THROW __nonnull ((1, 2)) __attr_access ((__write_only__, 1, 3));
+
+/* Append SRC to DEST, possibly with truncation to keep the total size
+   below N.  */
+extern size_t strlcat (char *__restrict __dest,
+		       const char *__restrict __src, size_t __n)
+  __THROW __nonnull ((1, 2))  __attr_access ((__read_write__, 1, 3));
+#endif
+
 #ifdef	__USE_GNU
 /* Compare S1 and S2 as strings holding name & indices/version numbers.  */
 extern int strverscmp (const char *__s1, const char *__s2)
diff --git a/string/strlcat.c b/string/strlcat.c
new file mode 100644
index 0000000000..297923ad9b
--- /dev/null
+++ b/string/strlcat.c
@@ -0,0 +1,60 @@ 
+/* Append a null-terminated string to another string, with length checking.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdint.h>
+#include <string.h>
+
+#undef strlcat
+
+size_t
+strlcat (char *__restrict dest, const char *__restrict src, size_t size)
+{
+  size_t src_length = strlen (src);
+
+  /* Our implementation strlcat supports dest == NULL if size == 0
+     (for consistency with snprintf and strlcpy), but strnlen does
+     not, so we have to cover this case explicitly.  */
+  if (size == 0)
+    return src_length;
+
+  size_t dest_length = __strnlen (dest, size);
+  if (dest_length != size)
+    {
+      /* Copy at most the remaining number of characters in the
+	 destination buffer.  Leave for the NUL terminator.  */
+      size_t to_copy = size - dest_length - 1;
+      /* But not more than what is available in the source string.  */
+      if (to_copy > src_length)
+	to_copy = src_length;
+
+      char *target = dest + dest_length;
+      memcpy (target, src, to_copy);
+      target[to_copy] = '\0';
+    }
+
+  /* If the sum wraps around, we have more than SIZE_MAX + 2 bytes in
+     the two input strings (including both null terminators).  If each
+     byte in the address space can be assigned a unique size_t value
+     (which the static_assert checks), then by the pigeonhole
+     principle, the two input strings must overlap, which is
+     undefined.  */
+  _Static_assert (sizeof (uintptr_t) == sizeof (size_t),
+		  "theoretical maximum object size covers address space");
+  return dest_length + src_length;
+}
+libc_hidden_def (strlcat)
diff --git a/string/strlcpy.c b/string/strlcpy.c
new file mode 100644
index 0000000000..d0764e9b64
--- /dev/null
+++ b/string/strlcpy.c
@@ -0,0 +1,47 @@ 
+/* Copy a null-terminated string to a fixed-size buffer, with length checking.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+
+#undef strlcpy
+
+size_t
+strlcpy (char *__restrict dest, const char *__restrict src, size_t size)
+{
+  size_t src_length = strlen (src);
+
+  if (__glibc_unlikely (src_length >= size))
+    {
+      if (size > 0)
+	{
+	  /* Copy the leading portion of the string.  The last
+	     character is subsequently overwritten with the NUL
+	     terminator, but the destination size is usually a
+	     multiple of a small power of two, so writing it twice
+	     should be more efficient than copying an odd number of
+	     bytes.  */
+	  memcpy (dest, src, size);
+	  dest[size - 1] = '\0';
+	}
+    }
+  else
+    /* Copy the string and its terminating NUL character.  */
+    memcpy (dest, src, src_length + 1);
+  return src_length;
+}
+libc_hidden_def (strlcpy)
diff --git a/string/tst-strlcat.c b/string/tst-strlcat.c
new file mode 100644
index 0000000000..805524754a
--- /dev/null
+++ b/string/tst-strlcat.c
@@ -0,0 +1,90 @@ 
+/* Test the strlcat function.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <support/check.h>
+
+static int
+do_test (void)
+{
+  struct {
+    char buf1[16];
+    char buf2[16];
+  } s;
+
+  /* Nothing is written to the destination if its size is 0.  */
+  memset (&s, '@', sizeof (s));
+  TEST_VERIFY (strlcat (s.buf1, "", 0) == 0);
+  TEST_VERIFY (memcmp (&s, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
+		       sizeof (s)) == 0);
+  TEST_VERIFY (strlcat (s.buf1, "Hello!", 0) == 6);
+  TEST_VERIFY (memcmp (&s, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
+		       sizeof (s)) == 0);
+
+  /* No bytes are are modified in the target buffer if the source
+     string is short enough.  */
+  memset (&s, '@', sizeof (s));
+  strcpy (s.buf1, "He");
+  TEST_VERIFY (strlcat (s.buf1, "llo!", sizeof (s.buf1)) == 6);
+  TEST_VERIFY (memcmp (&s, "Hello!\0@@@@@@@@@@@@@@@@@@@@@@@@@",
+		       sizeof (s)) == 0);
+
+  /* A source string which fits exactly into the destination buffer is
+     not truncated.  */
+  memset (&s, '@', sizeof (s));
+  strcpy (s.buf1, "H");
+  TEST_VERIFY (strlcat (s.buf1, "ello, world!!!", sizeof (s.buf1)) == 15);
+  TEST_VERIFY (memcmp (&s, "Hello, world!!!\0@@@@@@@@@@@@@@@@@@@@@@@@@",
+		 sizeof (s)) == 0);
+
+  /* A source string one character longer than the destination buffer
+     is truncated by one character.  The total length is returned.  */
+  memset (&s, '@', sizeof (s));
+  strcpy (s.buf1, "Hello");
+  TEST_VERIFY (strlcat (s.buf1, ", world!!!!", sizeof (s.buf1)) == 16);
+  TEST_VERIFY (memcmp (&s, "Hello, world!!!\0@@@@@@@@@@@@@@@@@@@@@@@@@",
+		 sizeof (s)) == 0);
+
+  /* An even longer source string is truncated as well, and the total
+     length is returned.  */
+  memset (&s, '@', sizeof (s));
+  strcpy (s.buf1, "Hello,");
+  TEST_VERIFY (strlcat (s.buf1, " world!!!!!!!!", sizeof (s.buf1)) == 20);
+  TEST_VERIFY (memcmp (&s, "Hello, world!!!\0@@@@@@@@@@@@@@@@@@@@@@@@@",
+		 sizeof (s)) == 0);
+
+  /* A destination string which is not NUL-terminated does not result
+     in any changes to the buffer.  */
+  memset (&s, '@', sizeof (s));
+  memset (s.buf1, '$', sizeof (s.buf1));
+  TEST_VERIFY (strlcat (s.buf1, "", sizeof (s.buf1)) == 16);
+  TEST_VERIFY (memcmp (&s, "$$$$$$$$$$$$$$$$@@@@@@@@@@@@@@@@",
+		       sizeof (s)) == 0);
+  TEST_VERIFY (strlcat (s.buf1, "Hello!", sizeof (s.buf1)) == 22);
+  TEST_VERIFY (memcmp (&s, "$$$$$$$$$$$$$$$$@@@@@@@@@@@@@@@@",
+		       sizeof (s)) == 0);
+  TEST_VERIFY (strlcat (s.buf1, "Hello, world!!!!!!!!", sizeof (s.buf1)) == 36);
+  TEST_VERIFY (memcmp (&s, "$$$$$$$$$$$$$$$$@@@@@@@@@@@@@@@@",
+		       sizeof (s)) == 0);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/string/tst-strlcpy.c b/string/tst-strlcpy.c
new file mode 100644
index 0000000000..16bc75c067
--- /dev/null
+++ b/string/tst-strlcpy.c
@@ -0,0 +1,70 @@ 
+/* Test the strlcpy function.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <support/check.h>
+
+static int
+do_test (void)
+{
+  struct {
+    char buf1[16];
+    char buf2[16];
+  } s;
+
+  /* Nothing is written to the destination if its size is 0.  */
+  memset (&s, '@', sizeof (s));
+  TEST_VERIFY (strlcpy (s.buf1, "Hello!", 0) == 6);
+  TEST_VERIFY (memcmp (&s, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
+		       sizeof (s)) == 0);
+
+  /* No bytes are are modified in the target buffer if the source
+     string is short enough.  */
+  memset (&s, '@', sizeof (s));
+  TEST_VERIFY (strlcpy (s.buf1, "Hello!", sizeof (s.buf1)) == 6);
+  TEST_VERIFY (memcmp (&s, "Hello!\0@@@@@@@@@@@@@@@@@@@@@@@@@",
+		       sizeof (s)) == 0);
+
+  /* A source string which fits exactly into the destination buffer is
+     not truncated.  */
+  memset (&s, '@', sizeof (s));
+  TEST_VERIFY (strlcpy (s.buf1, "Hello, world!!!", sizeof (s.buf1)) == 15);
+  TEST_VERIFY (memcmp (&s, "Hello, world!!!\0@@@@@@@@@@@@@@@@@@@@@@@@@",
+		       sizeof (s)) == 0);
+
+  /* A source string one character longer than the destination buffer
+     is truncated by one character.  The untruncated source length is
+     returned.  */
+  memset (&s, '@', sizeof (s));
+  TEST_VERIFY (strlcpy (s.buf1, "Hello, world!!!!", sizeof (s.buf1)) == 16);
+  TEST_VERIFY (memcmp (&s, "Hello, world!!!\0@@@@@@@@@@@@@@@@@@@@@@@@@",
+		       sizeof (s)) == 0);
+
+  /* An even longer source string is truncated as well, and the
+     original length is returned.  */
+  memset (&s, '@', sizeof (s));
+  TEST_VERIFY (strlcpy (s.buf1, "Hello, world!!!!!!!!", sizeof (s.buf1)) == 20);
+  TEST_VERIFY (memcmp (&s, "Hello, world!!!\0@@@@@@@@@@@@@@@@@@@@@@@@@",
+		       sizeof (s)) == 0);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/mach/hurd/i386/libc.abilist b/sysdeps/mach/hurd/i386/libc.abilist
index 4dc87e9061..57ab83842f 100644
--- a/sysdeps/mach/hurd/i386/libc.abilist
+++ b/sysdeps/mach/hurd/i386/libc.abilist
@@ -2289,6 +2289,10 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 close_range F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 8dba065b81..79593721f7 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2616,6 +2616,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2624,3 +2626,5 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 08f4750022..8e1588e0a6 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2713,6 +2713,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2721,6 +2723,8 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/arc/libc.abilist b/sysdeps/unix/sysv/linux/arc/libc.abilist
index 75db763023..589f32ef7d 100644
--- a/sysdeps/unix/sysv/linux/arc/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arc/libc.abilist
@@ -2377,6 +2377,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2385,3 +2387,5 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
diff --git a/sysdeps/unix/sysv/linux/arm/be/libc.abilist b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
index fa33f317ac..66aad3e945 100644
--- a/sysdeps/unix/sysv/linux/arm/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
@@ -496,6 +496,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -504,6 +506,8 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
 GLIBC_2.4 _IO_2_1_stdin_ D 0xa0
diff --git a/sysdeps/unix/sysv/linux/arm/le/libc.abilist b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
index dba2e4ce42..da3a1bce34 100644
--- a/sysdeps/unix/sysv/linux/arm/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
@@ -493,6 +493,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -501,6 +503,8 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
 GLIBC_2.4 _IO_2_1_stdin_ D 0xa0
diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist
index e6ff921c29..c2ea825539 100644
--- a/sysdeps/unix/sysv/linux/csky/libc.abilist
+++ b/sysdeps/unix/sysv/linux/csky/libc.abilist
@@ -2652,6 +2652,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2660,3 +2662,5 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 8a40cece83..4859a686a6 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -2601,6 +2601,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2609,6 +2611,8 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index a89826049f..2547999a77 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2785,6 +2785,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2793,6 +2795,8 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index d1d96b7469..a8c73d31f6 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -2551,6 +2551,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2559,6 +2561,8 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 63a62f267a..0f419bfd22 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -497,6 +497,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -505,6 +507,8 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0x98
 GLIBC_2.4 _IO_2_1_stdin_ D 0x98
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index f68325f9bc..aa6332040f 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -2728,6 +2728,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2736,6 +2738,8 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
index 247af2075c..ab63dbacd6 100644
--- a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
@@ -2701,6 +2701,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2709,3 +2711,5 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
diff --git a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
index b0ac3f9009..4f55786882 100644
--- a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
@@ -2698,6 +2698,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2706,3 +2708,5 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index b22cd6bf2f..44d5c4e115 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -2693,6 +2693,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2701,6 +2703,8 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index 12fc2cce3e..cf8f7690fd 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -2691,6 +2691,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2699,6 +2701,8 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index d3e96dfd43..1ee70f2e2a 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -2699,6 +2699,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2707,6 +2709,8 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index cb58ed4db0..99ec7125af 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -2602,6 +2602,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2610,6 +2612,8 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index 61ad58a599..98be295843 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2740,6 +2740,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2748,3 +2750,5 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
diff --git a/sysdeps/unix/sysv/linux/or1k/libc.abilist b/sysdeps/unix/sysv/linux/or1k/libc.abilist
index 1260dc4e2e..dc368582af 100644
--- a/sysdeps/unix/sysv/linux/or1k/libc.abilist
+++ b/sysdeps/unix/sysv/linux/or1k/libc.abilist
@@ -2123,6 +2123,8 @@  GLIBC_2.35 wprintf F
 GLIBC_2.35 write F
 GLIBC_2.35 writev F
 GLIBC_2.35 wscanf F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2131,3 +2133,5 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index 363939762c..f5f8a57079 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -2755,6 +2755,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2763,6 +2765,8 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index f512ad8baf..396c5b7ae0 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -2788,6 +2788,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2796,6 +2798,8 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
index c9bdc9859c..523e01c0ca 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
@@ -2510,6 +2510,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2518,6 +2520,8 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
index f091be30bd..0c412e3072 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
@@ -2812,6 +2812,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2820,3 +2822,5 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
index 7ea73f9af8..3703c33c07 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
@@ -2379,6 +2379,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2387,3 +2389,5 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
index 333fa62714..9a719fdfe3 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
@@ -2579,6 +2579,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2587,3 +2589,5 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index a867467b12..5f05b253d5 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -2753,6 +2753,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2761,6 +2763,8 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index dbad5b3163..36e78d7cb2 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -2547,6 +2547,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2555,6 +2557,8 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/sh/be/libc.abilist b/sysdeps/unix/sysv/linux/sh/be/libc.abilist
index 6f755cc173..6ccdc54d27 100644
--- a/sysdeps/unix/sysv/linux/sh/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/be/libc.abilist
@@ -2608,6 +2608,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2616,6 +2618,8 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/sh/le/libc.abilist b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
index 77d936aa3c..647834425f 100644
--- a/sysdeps/unix/sysv/linux/sh/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
@@ -2605,6 +2605,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2613,6 +2615,8 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 09bb4363e1..fe16974926 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -2748,6 +2748,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2756,6 +2758,8 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index 9df9cb6adb..f661ba5b4a 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -2574,6 +2574,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2582,6 +2584,8 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index 4829450ad0..e170c64b77 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -2525,6 +2525,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2533,6 +2535,8 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index caea228bcb..8c4cefcb09 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2631,6 +2631,8 @@  GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
 GLIBC_2.35 posix_spawn_file_actions_addtcsetpgrp_np F
+GLIBC_2.36 __strlcat_chk F
+GLIBC_2.36 __strlcpy_chk F
 GLIBC_2.36 fsmount F
 GLIBC_2.36 fsopen F
 GLIBC_2.36 move_mount F
@@ -2639,3 +2641,5 @@  GLIBC_2.36 pidfd_open F
 GLIBC_2.36 pidfd_send_signal F
 GLIBC_2.36 process_madvise F
 GLIBC_2.36 process_mrelease F
+GLIBC_2.36 strlcat F
+GLIBC_2.36 strlcpy F