[PATCH v6 0/3] Fix opendir regression on some FS
Adhemerval Zanella
adhemerval.zanella@linaro.org
Thu Mar 2 14:57:29 GMT 2023
Some filesystem might return a non-representable d_off on getdents
call, even if there are few entries in the directories (for instance
ext4, which returns an internal FS hash). This trigger issues with
non-LFS readdir when it finds the first non representable entry, and
also for LFS interface when used along with telldir (which return a
'long int', while d_off is potentially off64_t).
For instance, arm32 dirent and io tests running on qemu-user show the
following failures:
FAIL: dirent/list
FAIL: dirent/tst-scandir
FAIL: io/tst-fts
FAIL: io/tst-fts-lfs
FAIL: io/tst-fts-time64
This patch changes non-LFS readdir so it clamps the d_off value if
it overflows. It now uses getdents64 and maintains an internal map
between d_off that can not be represented by 'long int' (telldir
returned value). seekdir will then set the correct offset by
using the input argument as a key to the internal list.
I have checked on x86_64-linux-gnu, i686-linux-gnu, and
arm-linux-gnueabihf.
Changes from v5:
* Use non-LFS getdents logic on non-LFS readdir.
* Clamp overflow d_off values.
* Removed unrequired readdir64 refactor.
Changes from v4:
* Allocate the telldir map an readdir, thus avoid telldir failure.
* The translation buffer now uses a fixed size struct.
* Fixed the condition to use the long to off64_t map.
Changes from v3:
* Rebase against master.
* Fixed a missing lock unlock on telldir.
* Renamed tst-seekdir2 to tst-opendir-nolfs and check the opendir
result against getdents64.
Adhemerval Zanella (3):
linux: Use getdents64 on non-LFS readdir
support: Add xreallocarray
linux: Set internal DIR filepos as off64_t (BZ #23960, BZ #24050)
include/dirent.h | 2 +-
support/Makefile | 1 +
support/support.h | 2 +
support/xreallocarray.c | 29 ++++
sysdeps/unix/sysv/linux/Makefile | 2 +
sysdeps/unix/sysv/linux/alpha/bits/dirent.h | 3 +
sysdeps/unix/sysv/linux/bits/dirent.h | 4 +
sysdeps/unix/sysv/linux/closedir.c | 4 +
sysdeps/unix/sysv/linux/dirstream.h | 9 +-
sysdeps/unix/sysv/linux/opendir.c | 3 +
sysdeps/unix/sysv/linux/readdir.c | 107 +++++++++++----
sysdeps/unix/sysv/linux/readdir64.c | 11 ++
sysdeps/unix/sysv/linux/rewinddir.c | 5 +
sysdeps/unix/sysv/linux/seekdir.c | 30 +++-
sysdeps/unix/sysv/linux/telldir.c | 36 +++++
sysdeps/unix/sysv/linux/telldir.h | 67 +++++++++
sysdeps/unix/sysv/linux/tst-opendir-lfs.c | 2 +
sysdeps/unix/sysv/linux/tst-opendir.c | 145 ++++++++++++++++++++
18 files changed, 432 insertions(+), 30 deletions(-)
create mode 100644 support/xreallocarray.c
create mode 100644 sysdeps/unix/sysv/linux/telldir.h
create mode 100644 sysdeps/unix/sysv/linux/tst-opendir-lfs.c
create mode 100644 sysdeps/unix/sysv/linux/tst-opendir.c
--
2.34.1
More information about the Libc-alpha
mailing list