RFC: strategies to provide y2038 support for stat functions

Adhemerval Zanella adhemerval.zanella@linaro.org
Tue Jul 14 16:49:52 GMT 2020


Hi all

The current implementation for stat family functions (stat, stat64,
lstat, lstat64, fstat, fstat64, fstatat, fstatat64) poses some
challenges on how to provide the y2038 support.

Its implementation uses scheme where the stat.h header (io/sys/stat.h) 
provides inline versions for the exported extensible version (__xstat for
instance).  A libc_nonshared wrappers is also provided if the inline
could not be satisfied (if __USE_EXTERN_INLINES could not defined).
The extended implementation receives as first argument the expected
'version' of the stat structure and thus either uses it directly on
the syscall or apply some conversion.

This mechanism was devised prior symbol versioning and besides the code
complexity it also has some other issues: the non-shared wrappers, exports 
non-default symbols, it fails at runtime instead of load time for different
support stat version between application and libc.

So to support a y2038 interface using this mechanism the straightforward
way would to add a new _STAT_* version, the stat{64}_time64 definitions,
and adjust each *xstat*.c implementation to handle the new type:

  int
  __xstat (int vers, const char *name, struct stat *buf)
  {
    [...]
    if (vers == _STAT_VER_LINUX_TIME64)
      {
        // Call statx
        // Convert from statx to struct __stat_time64 and return
      }
    [...]
  }

And on header once the time64 support is enabled we would do

  [...]
  #if __TIMESIZE == 64
  __extern_inline int
  __NTH (stat (const char *__path, struct stat_time64 *__statbuf))
  {
    return __xstat (_STAT_LINUX_TIME64, __path, __statbuf);
  }
  #else
  [...]
  #endif

We will need to add the libc_nonshared wrapper as well.

Two additional issues on this approach are:

  1. There are multiple implementations of extended stat version (with 
     and without LFS support) and we will need to adjust each of them.

  2. Testing won't be easy as for current way to add time64 support, where
     the time32 version call the time64 one.


Another possibility which would also require some plumbing is to:

  1. Move the extensible stat function to compat symbols

  2. Implement the stat family function as proper versioned symbols
     2.1. Add the required libc_hidden_def and call the internal calls to
          avoid internal plts.

  3. Implement the y2038 support as other symbols:
     3.1. Add struct __stat_time64 and __stat64_time64
     3.2. Add __stat_time64 and __stat64_time64
     3.3. Implement stat by calling __stat_time64 and covert the output.

A drawback is add new glibc symbols for stat, stat64, lstat, lstat64, 
fstat, fstat64, fstatat, fstatat64.  In the other hand we can cleanup the 
stat struct and use a default one for all architectures and also cleanup 
the implementation to just use statx or fstatat64 syscall.

I am more inclined on second way, so we could move away from the stat
non_shared wrapper.

Thoughts?


More information about the Libc-alpha mailing list