[v4,0/5] Fix opendir regression on some FS

Message ID 20230126192953.2990973-1-adhemerval.zanella@linaro.org
Headers
Series Fix opendir regression on some FS |

Message

Adhemerval Zanella Netto Jan. 26, 2023, 7:29 p.m. UTC
  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 a 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).

This patch changes non-LFS readdir so it ignore non representable
entries.  The opendir now uses getdents64, even for non-LFS and uses
a translation buffer to return the getdents entry from the getdents64
buffer.

The second part fixes the broken telldir on non LP64 ABIs, where
returning d_off as stream position might overflow.  For these ABIs,
telldir mantains an internal list that maps the DIR object off64_t
offsets to the returned long int (the function return value).  The
seekdir will then set the correct offset from the internal list using
the telldir as the list key.

One drawback of such strategy is now telldir might silent fail if
seekdir fails to allocate the off64_t map entry, however non-LFS is a
compat interface and overflowed entries currently also does not fully
work even for LFS interface.

I have checked on x86_64-linux-gnu, i686-linux-gnu, and
arm-linux-gnueabihf.

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 (5):
  linux: Use getdents64 on non-LFS readdir
  linux: Set internal DIR filepos as off64_t (BZ #23960, BZ #24050)
  linux: Add __readdir64_unlocked
  linux: Add __old_readdir64_unlocked
  linux: Use getdents64 on readdir64 compat implementation

 dirent/tst-scandir.c                        |   6 +-
 dirent/tst-seekdir.c                        |   8 +
 include/dirent.h                            |   1 +
 sysdeps/unix/sysv/linux/Makefile            |   1 +
 sysdeps/unix/sysv/linux/closedir.c          |   7 +
 sysdeps/unix/sysv/linux/dirstream.h         |  11 +-
 sysdeps/unix/sysv/linux/getdents64.c        |  93 ------------
 sysdeps/unix/sysv/linux/olddirent.h         |   4 +-
 sysdeps/unix/sysv/linux/opendir.c           |  37 +++++
 sysdeps/unix/sysv/linux/readdir.c           |  90 +++++++----
 sysdeps/unix/sysv/linux/readdir64.c         | 104 ++++++++++---
 sysdeps/unix/sysv/linux/readdir64_r.c       | 159 +++++---------------
 sysdeps/unix/sysv/linux/rewinddir.c         |   5 +
 sysdeps/unix/sysv/linux/seekdir.c           |  36 ++++-
 sysdeps/unix/sysv/linux/telldir.c           |  45 +++++-
 sysdeps/unix/sysv/linux/telldir.h           |  65 ++++++++
 sysdeps/unix/sysv/linux/tst-opendir-nolfs.c | 146 ++++++++++++++++++
 17 files changed, 539 insertions(+), 279 deletions(-)
 create mode 100644 sysdeps/unix/sysv/linux/telldir.h
 create mode 100644 sysdeps/unix/sysv/linux/tst-opendir-nolfs.c
  

Comments

Florian Weimer Jan. 26, 2023, 10:42 p.m. UTC | #1
* Adhemerval Zanella via Libc-alpha:

> One drawback of such strategy is now telldir might silent fail if
> seekdir fails to allocate the off64_t map entry, however non-LFS is a
> compat interface and overflowed entries currently also does not fully
> work even for LFS interface.

Could we please fix this by allocating an entry ahead of time, in
readdir?

Thanks,
Florian
  
Adhemerval Zanella Netto Jan. 27, 2023, 2:09 p.m. UTC | #2
On 26/01/23 19:42, Florian Weimer wrote:
> * Adhemerval Zanella via Libc-alpha:
> 
>> One drawback of such strategy is now telldir might silent fail if
>> seekdir fails to allocate the off64_t map entry, however non-LFS is a
>> compat interface and overflowed entries currently also does not fully
>> work even for LFS interface.
> 
> Could we please fix this by allocating an entry ahead of time, in
> readdir?

Right, I forgot to add this change you require in last iteration. I will
send a new version.