Linux: Add fortify wrapper for getdents64

Message ID 87tvcn9nba.fsf@oldenburg2.str.redhat.com
State New, archived
Headers

Commit Message

Florian Weimer June 18, 2019, 10:53 a.m. UTC
  2019-06-18  Florian Weimer  <fweimer@redhat.com>

	* sysdeps/unix/sysv/linux/Makefile
	[$(subdir) == dirent] (sysdep_routines): Add getdents64_chk.
	[$(subdir) == dirent] (tests): Add tst-getdents64_chk,
	tst-getdents64_chk-fail.
	* sysdeps/unix/sysv/linux/Versions (GLIBC_2.30): Export
	__getdents64_chk.
	* sysdeps/unix/sysv/linux/bits/unistd_ext.h
	[__USE_FORTIFY_LEVEL > 0] (__getdents64_chk): Declare.
	[__USE_FORTIFY_LEVEL > 0] (getdents64): Define inline.
	* sysdeps/unix/sysv/linux/getdents64_chk.c: New file.
	* sysdeps/unix/sysv/linux/tst-getdents64_chk.c: Likewise.
	* sysdeps/unix/sysv/linux/tst-getdents64_chk-fail.c: Likewise.
	* sysdeps/unix/sysv/linux/aarch64/libc.abilist (GLIBC_2.30): Add
	getdents64.
	* sysdeps/unix/sysv/linux/alpha/libc.abilist (GLIBC_2.30):
	Likewise.
	* sysdeps/unix/sysv/linux/arm/libc.abilist (GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/csky/libc.abilist (GLIBC_2.30):
	Likewise.
	* sysdeps/unix/sysv/linux/hppa/libc.abilist (GLIBC_2.30):
	Likewise.
	* sysdeps/unix/sysv/linux/i386/libc.abilist (GLIBC_2.30):
	Likewise.
	* sysdeps/unix/sysv/linux/ia64/libc.abilist (GLIBC_2.30):
	Likewise.
	* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist (GLIBC_2.30):
	Likewise.
	* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist (GLIBC_2.30):
	Likewise.
	* sysdeps/unix/sysv/linux/microblaze/libc.abilist (GLIBC_2.30):
	Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/nios2/libc.abilist (GLIBC_2.30):
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist (GLIBC_2.30):
	Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist (GLIBC_2.30):
	Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist (GLIBC_2.30):
	Likewise.
	* sysdeps/unix/sysv/linux/sh/libc.abilist (GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist (GLIBC_2.30):
	Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist (GLIBC_2.30):
	Likewise.
	* sysdeps/unix/sysv/linux/x86_64/64/libc.abilist (GLIBC_2.30):
	Likewise.
	* sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist (GLIBC_2.30):
	Likewise.
  

Comments

Adhemerval Zanella June 18, 2019, 2:33 p.m. UTC | #1
On 18/06/2019 07:53, Florian Weimer wrote:
> 2019-06-18  Florian Weimer  <fweimer@redhat.com>
> diff --git a/sysdeps/unix/sysv/linux/getdents64_chk.c b/sysdeps/unix/sysv/linux/getdents64_chk.c
> new file mode 100644
> index 0000000000..dddbececd5
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/getdents64_chk.c
> @@ -0,0 +1,28 @@
> +/* Get directory entries, with fortificiation.
> +   Copyright (C) 2019 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library.  If not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <unistd.h>
> +#include <dirent.h>
> +
> +ssize_t
> +__getdents64_chk (int fd, void *dst, size_t len, size_t dstlen)
> +{
> +  if (__glibc_unlikely (dstlen < len))
> +    __chk_fail ();
> +  return __getdents64 (fd, dst, len);
> +}

__chk_fail is exported in libc ABI, wouldn't be better to just inline it
and avoid a new symbol?
  
Florian Weimer June 18, 2019, 2:38 p.m. UTC | #2
* Adhemerval Zanella:

>> +ssize_t
>> +__getdents64_chk (int fd, void *dst, size_t len, size_t dstlen)
>> +{
>> +  if (__glibc_unlikely (dstlen < len))
>> +    __chk_fail ();
>> +  return __getdents64 (fd, dst, len);
>> +}
>
> __chk_fail is exported in libc ABI, wouldn't be better to just inline it
> and avoid a new symbol?

None of the existing wrappers do this.  The advantage of not inling is
that you can look at a coredump and see __getdents64_chk in libc.so.6 in
the stack trace, even with (application) debugging symbols available.

Thanks,
Florian
  
Adhemerval Zanella June 19, 2019, 7:25 p.m. UTC | #3
On 18/06/2019 11:38, Florian Weimer wrote:
> * Adhemerval Zanella:
> 
>>> +ssize_t
>>> +__getdents64_chk (int fd, void *dst, size_t len, size_t dstlen)
>>> +{
>>> +  if (__glibc_unlikely (dstlen < len))
>>> +    __chk_fail ();
>>> +  return __getdents64 (fd, dst, len);
>>> +}
>>
>> __chk_fail is exported in libc ABI, wouldn't be better to just inline it
>> and avoid a new symbol?
> 
> None of the existing wrappers do this.  The advantage of not inling is
> that you can look at a coredump and see __getdents64_chk in libc.so.6 in
> the stack trace, even with (application) debugging symbols available.
> 
> Thanks,
> Florian
> 

I am not sure why the __chk_fail was exported in first place, so I don't
have a strong opinion whether we should use directly or not.  Either option
should be fine. 

As a side note, do you foresee this symbol being used extensively so we
do need to add a fortify symbol? I noted some code tries to optimize directory
listing by calling it directly instead of copying the buffer contents multiple
times using readdir.
  
Florian Weimer June 21, 2019, 11 a.m. UTC | #4
* Adhemerval Zanella:

> On 18/06/2019 11:38, Florian Weimer wrote:
>> * Adhemerval Zanella:
>> 
>>>> +ssize_t
>>>> +__getdents64_chk (int fd, void *dst, size_t len, size_t dstlen)
>>>> +{
>>>> +  if (__glibc_unlikely (dstlen < len))
>>>> +    __chk_fail ();
>>>> +  return __getdents64 (fd, dst, len);
>>>> +}
>>>
>>> __chk_fail is exported in libc ABI, wouldn't be better to just inline it
>>> and avoid a new symbol?
>> 
>> None of the existing wrappers do this.  The advantage of not inling is
>> that you can look at a coredump and see __getdents64_chk in libc.so.6 in
>> the stack trace, even with (application) debugging symbols available.
>> 
>> Thanks,
>> Florian
>> 
>
> I am not sure why the __chk_fail was exported in first place, so I don't
> have a strong opinion whether we should use directly or not.  Either option
> should be fine.

It's hard to tell from the sources.  Historically, there are some
exports which should have been GLIBC_PRIVATE, but __chk_fail is probably
not one of those.

> As a side note, do you foresee this symbol being used extensively so
> we do need to add a fortify symbol? I noted some code tries to
> optimize directory listing by calling it directly instead of copying
> the buffer contents multiple times using readdir.

I think that we should add fortified versions for new functions where
this makes sense.  This function takes a variable-sized buffer, so I
think it qualifies purely on formal grounds.

The other question is whether we want to add fortification to all the
buffer-based NSS functions …

Thanks,
Florian
  
Florian Weimer July 8, 2019, 11:08 a.m. UTC | #5
How can we proceed here?

I had hoped that the same release that got getdents64 would also receive
the fortify wrapper.

Thanks,
Florian
  
Adhemerval Zanella July 8, 2019, 12:51 p.m. UTC | #6
On 08/07/2019 08:08, Florian Weimer wrote:
> How can we proceed here?
> 
> I had hoped that the same release that got getdents64 would also receive
> the fortify wrapper.
> 
> Thanks,
> Florian
> 

Wilco, I see that both you and Florian sees there is limitations in fortify
handlers, however do you think that we should not pursuit any longer on glibc
side?

Do we have a gcc bug report of the issues you have raised [1] or at least
some example where compiler does not have enough information to handle it
correctly?

[1] https://sourceware.org/ml/libc-alpha/2019-06/msg00517.html
  
Dmitry V. Levin July 10, 2019, 3:58 p.m. UTC | #7
On Mon, Jul 08, 2019 at 09:51:21AM -0300, Adhemerval Zanella wrote:
> On 08/07/2019 08:08, Florian Weimer wrote:
> > How can we proceed here?
> > 
> > I had hoped that the same release that got getdents64 would also receive
> > the fortify wrapper.

I agree.

> > Thanks,
> > Florian
> 
> Wilco, I see that both you and Florian sees there is limitations in fortify
> handlers, however do you think that we should not pursuit any longer on glibc
> side?

I don't see why these limitations should stop us from adding fortify
wrappers.  They are useful despite of these limitations, and I think
we should proceed with adding the fortify wrapper for getdents64.
  

Patch

diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index afcdc658b5..a0b53c2821 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -187,8 +187,8 @@  endif
 inhibit-glue = yes
 
 ifeq ($(subdir),dirent)
-sysdep_routines += getdirentries getdirentries64
-tests += tst-getdents64
+sysdep_routines += getdirentries getdirentries64 getdents64_chk
+tests += tst-getdents64 tst-getdents64_chk tst-getdents64_chk-fail
 tests-internal += tst-readdir64-compat
 endif
 
diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions
index 1ca102a9e2..90548e9b2e 100644
--- a/sysdeps/unix/sysv/linux/Versions
+++ b/sysdeps/unix/sysv/linux/Versions
@@ -175,7 +175,7 @@  libc {
     getcpu;
   }
   GLIBC_2.30 {
-    getdents64; gettid; tgkill;
+    getdents64; __getdents64_chk; gettid; tgkill;
   }
   GLIBC_PRIVATE {
     # functions used in other libraries
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index a4c31932cb..605085aa7c 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2141,6 +2141,7 @@  GLIBC_2.28 thrd_yield F
 GLIBC_2.29 getcpu F
 GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
 GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
+GLIBC_2.30 __getdents64_chk F
 GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index fe85a35620..222c3797c1 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2204,6 +2204,7 @@  GLIBC_2.3.4 setipv4sourcefilter F
 GLIBC_2.3.4 setsourcefilter F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 __getdents64_chk F
 GLIBC_2.30 __nldbl_argp_error F
 GLIBC_2.30 __nldbl_argp_failure F
 GLIBC_2.30 __nldbl_err F
diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
index bc3df8dcea..79e8a879bd 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -126,6 +126,7 @@  GLIBC_2.28 thrd_yield F
 GLIBC_2.29 getcpu F
 GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
 GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
+GLIBC_2.30 __getdents64_chk F
 GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
diff --git a/sysdeps/unix/sysv/linux/bits/unistd_ext.h b/sysdeps/unix/sysv/linux/bits/unistd_ext.h
index 6e7b2bb83d..5f77365b2b 100644
--- a/sysdeps/unix/sysv/linux/bits/unistd_ext.h
+++ b/sysdeps/unix/sysv/linux/bits/unistd_ext.h
@@ -39,4 +39,19 @@  extern ssize_t getdents64 (int __fd, void *__buffer, size_t __length)
    not detached and has not been joined.  */
 extern __pid_t gettid (void) __THROW;
 
-#endif
+
+/* Fortified versions of the functions above.  */
+
+# if __GNUC_PREREQ (3,4)
+#  if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function
+ssize_t __getdents64_chk (int __fd, void *__buffer, size_t __length,
+                          size_t __bufferlength) __THROW __nonnull ((2));
+
+__fortify_function ssize_t
+__NTH (getdents64 (int __fd, void *__buffer, size_t __length))
+{
+  return __getdents64_chk (__fd, __buffer, __length, __bos0 (__buffer));
+}
+#  endif /* __USE_FORTIFY_LEVEL */
+# endif /* __GNUC_PREREQ (3,4) */
+#endif /* __USE_GNU */
diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist
index 9b3cee65bb..804fe703d4 100644
--- a/sysdeps/unix/sysv/linux/csky/libc.abilist
+++ b/sysdeps/unix/sysv/linux/csky/libc.abilist
@@ -2085,6 +2085,7 @@  GLIBC_2.29 xdrstdio_create F
 GLIBC_2.29 xencrypt F
 GLIBC_2.29 xprt_register F
 GLIBC_2.29 xprt_unregister F
+GLIBC_2.30 __getdents64_chk F
 GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
diff --git a/sysdeps/unix/sysv/linux/getdents64_chk.c b/sysdeps/unix/sysv/linux/getdents64_chk.c
new file mode 100644
index 0000000000..dddbececd5
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/getdents64_chk.c
@@ -0,0 +1,28 @@ 
+/* Get directory entries, with fortificiation.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <unistd.h>
+#include <dirent.h>
+
+ssize_t
+__getdents64_chk (int fd, void *dst, size_t len, size_t dstlen)
+{
+  if (__glibc_unlikely (dstlen < len))
+    __chk_fail ();
+  return __getdents64 (fd, dst, len);
+}
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 75edece94a..c5d64fd550 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -2037,6 +2037,7 @@  GLIBC_2.3.4 setipv4sourcefilter F
 GLIBC_2.3.4 setsourcefilter F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 __getdents64_chk F
 GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index edeaf8e722..5efc980c31 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2203,6 +2203,7 @@  GLIBC_2.3.4 setsourcefilter F
 GLIBC_2.3.4 vm86 F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 __getdents64_chk F
 GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index b5d460eeb2..739bc85ba9 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -2069,6 +2069,7 @@  GLIBC_2.3.4 setipv4sourcefilter F
 GLIBC_2.3.4 setsourcefilter F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 __getdents64_chk F
 GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 05633b3cb8..bfab7b3c7f 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -127,6 +127,7 @@  GLIBC_2.28 thrd_yield F
 GLIBC_2.29 getcpu F
 GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
 GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
+GLIBC_2.30 __getdents64_chk F
 GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 47eb7b4608..2b360d9a89 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -2146,6 +2146,7 @@  GLIBC_2.3.4 setipv4sourcefilter F
 GLIBC_2.3.4 setsourcefilter F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 __getdents64_chk F
 GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
index f7ced487f7..2f088707dc 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
@@ -2133,6 +2133,7 @@  GLIBC_2.28 thrd_yield F
 GLIBC_2.29 getcpu F
 GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
 GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
+GLIBC_2.30 __getdents64_chk F
 GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index e49dc4272e..3d3fa61d4b 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -2120,6 +2120,7 @@  GLIBC_2.3.4 setipv4sourcefilter F
 GLIBC_2.3.4 setsourcefilter F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 __getdents64_chk F
 GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index daa3b60c5b..5df4bb12eb 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -2118,6 +2118,7 @@  GLIBC_2.3.4 setipv4sourcefilter F
 GLIBC_2.3.4 setsourcefilter F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 __getdents64_chk F
 GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index 457ce0b6f2..a7c94947c3 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -2126,6 +2126,7 @@  GLIBC_2.3.4 setipv4sourcefilter F
 GLIBC_2.3.4 setsourcefilter F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 __getdents64_chk F
 GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index 63d5c03bfb..7abb65b0d4 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -2120,6 +2120,7 @@  GLIBC_2.3.4 setipv4sourcefilter F
 GLIBC_2.3.4 setsourcefilter F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 __getdents64_chk F
 GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index 7fec0c9670..3e69da189d 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2174,6 +2174,7 @@  GLIBC_2.28 thrd_yield F
 GLIBC_2.29 getcpu F
 GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
 GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
+GLIBC_2.30 __getdents64_chk F
 GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index 9200a54309..a8711b4bad 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -2164,6 +2164,7 @@  GLIBC_2.3.4 siglongjmp F
 GLIBC_2.3.4 swapcontext F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 __getdents64_chk F
 GLIBC_2.30 __nldbl_argp_error F
 GLIBC_2.30 __nldbl_argp_failure F
 GLIBC_2.30 __nldbl_err F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index ef7779905f..729aa21b7b 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -2197,6 +2197,7 @@  GLIBC_2.3.4 siglongjmp F
 GLIBC_2.3.4 swapcontext F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 __getdents64_chk F
 GLIBC_2.30 __nldbl_argp_error F
 GLIBC_2.30 __nldbl_argp_failure F
 GLIBC_2.30 __nldbl_err F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
index 2860df8ebc..234343228c 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
@@ -2027,6 +2027,7 @@  GLIBC_2.3.4 siglongjmp F
 GLIBC_2.3.4 swapcontext F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 __getdents64_chk F
 GLIBC_2.30 __nldbl_argp_error F
 GLIBC_2.30 __nldbl_argp_failure F
 GLIBC_2.30 __nldbl_err F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
index 2229a1dcc0..6687047d25 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
@@ -2231,6 +2231,7 @@  GLIBC_2.28 thrd_yield F
 GLIBC_2.29 getcpu F
 GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
 GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
+GLIBC_2.30 __getdents64_chk F
 GLIBC_2.30 __nldbl_argp_error F
 GLIBC_2.30 __nldbl_argp_failure F
 GLIBC_2.30 __nldbl_err F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
index 31010e6cf7..adff5a1d92 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
@@ -2103,6 +2103,7 @@  GLIBC_2.28 thrd_yield F
 GLIBC_2.29 getcpu F
 GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
 GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
+GLIBC_2.30 __getdents64_chk F
 GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index 576295deff..46894e36b7 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -2159,6 +2159,7 @@  GLIBC_2.3.4 setipv4sourcefilter F
 GLIBC_2.3.4 setsourcefilter F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 __getdents64_chk F
 GLIBC_2.30 __nldbl_argp_error F
 GLIBC_2.30 __nldbl_argp_failure F
 GLIBC_2.30 __nldbl_err F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index abf0473683..6e9c9af03f 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -2063,6 +2063,7 @@  GLIBC_2.3.4 setipv4sourcefilter F
 GLIBC_2.3.4 setsourcefilter F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 __getdents64_chk F
 GLIBC_2.30 __nldbl_argp_error F
 GLIBC_2.30 __nldbl_argp_failure F
 GLIBC_2.30 __nldbl_err F
diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
index 41977f6e9c..9b8d75c8be 100644
--- a/sysdeps/unix/sysv/linux/sh/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
@@ -2041,6 +2041,7 @@  GLIBC_2.3.4 setipv4sourcefilter F
 GLIBC_2.3.4 setsourcefilter F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 __getdents64_chk F
 GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 3d2f00ca52..35d97f6697 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -2153,6 +2153,7 @@  GLIBC_2.3.4 setipv4sourcefilter F
 GLIBC_2.3.4 setsourcefilter F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 __getdents64_chk F
 GLIBC_2.30 __nldbl_argp_error F
 GLIBC_2.30 __nldbl_argp_failure F
 GLIBC_2.30 __nldbl_err F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index 2f20643e8e..eb35cf0168 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -2092,6 +2092,7 @@  GLIBC_2.3.4 setipv4sourcefilter F
 GLIBC_2.3.4 setsourcefilter F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 __getdents64_chk F
 GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
diff --git a/sysdeps/unix/sysv/linux/tst-getdents64_chk-fail.c b/sysdeps/unix/sysv/linux/tst-getdents64_chk-fail.c
new file mode 100644
index 0000000000..108814be81
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-getdents64_chk-fail.c
@@ -0,0 +1,54 @@ 
+/* Test for fortification failure with getdents64.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define _FORTIFY_SOURCE 2
+#include <unistd.h>
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/capture_subprocess.h>
+#include <support/check.h>
+
+static void
+subprocess (void *closure)
+{
+  char buf[1024];
+  /* Artificial buffer overflow.  This does not need a working file
+     descriptor, so use standard input.  */
+  printf ("error: getdents64 returned: %zd\n", getdents64 (0, buf, 2048));
+}
+
+static int
+do_test (void)
+{
+  setenv ("LIBC_FATAL_STDERR_", "1", 1);
+
+  struct support_capture_subprocess proc
+    = support_capture_subprocess (subprocess, NULL);
+  support_capture_subprocess_check (&proc, "getdents64",
+                                    -SIGABRT, sc_allow_stderr);
+  const char *prefix = "*** buffer overflow detected ***: ";
+  TEST_COMPARE (strncmp (prefix, proc.err.buffer, strlen (prefix)), 0);
+  printf ("info: output from subprocess follows\n%s", proc.err.buffer);
+  support_capture_subprocess_free (&proc);
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/unix/sysv/linux/tst-getdents64_chk.c b/sysdeps/unix/sysv/linux/tst-getdents64_chk.c
new file mode 100644
index 0000000000..6ae8fd0482
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-getdents64_chk.c
@@ -0,0 +1,20 @@ 
+/* Test for reading directories with getdents64.  Fortified version.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define _FORTIFY_SOURCE 2
+#include "tst-getdents64.c"
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index 59f85d9373..2665a0019d 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -2050,6 +2050,7 @@  GLIBC_2.3.4 setipv4sourcefilter F
 GLIBC_2.3.4 setsourcefilter F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 __getdents64_chk F
 GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 67a4e238d6..05d0a735f3 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2149,6 +2149,7 @@  GLIBC_2.28 thrd_yield F
 GLIBC_2.29 getcpu F
 GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
 GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
+GLIBC_2.30 __getdents64_chk F
 GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F