[PATCH] elf: Fix 64 time_t support for installed statically binaries

Carlos O'Donell carlos@redhat.com
Fri Jan 14 21:51:02 GMT 2022


On 12/29/21 08:27, Adhemerval Zanella via Libc-alpha wrote:
> The usage of internal static symbol for statically linked binaries
> does not work correctly for objects built with -D_TIME_BITS=64,
> since the internal definition does not provide the expected aliases.
> 
> This patch makes it to use the default stat functions instead (which
> uses the default 64 time_t alias and types).
> 
> Checked on i686-linux-gnu.

LGTM. No CI/CD regressions. Tested on x86_64 and i686 with no regressions.

The associated 64-bit binaries look correct (readelf/objdump), and at 
runtime they all call newfstatat which has a 64-bit kernel structure.

I did not test with -D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64 for i686 because
I couldn't get it to build, and asked you a question about the canonical way
to test this today:
https://sourceware.org/pipermail/libc-alpha/2022-January/135349.html

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Tested-by: Carlos O'Donell <carlos@redhat.com>

> ---
>  elf/cache.c                | 16 +++++++--------
>  elf/chroot_canon.c         |  4 ++--
>  elf/ldconfig.c             | 42 +++++++++++++++++++-------------------
>  elf/readlib.c              |  6 +++---
>  elf/sln.c                  |  4 ++--

elf/Makefile lists ldconfig as using:
* cache.c
* readlib.c
* xmalloc.c
* xstrdup.c
* chroot_canon.c
* static-stubs.c
* stringtable.c

Of those on the following use stat:
* cache.c
* readlib.c
* chroot_canon.c
 
elf/Makefile lists sln as using:
* static-stubs.c

In the end we need to audit:
* ldconfig.c
* sln.c
* cache.c
* chroot_canon.c
* readlib.c

Which matches the 5 files you change above.

>  sysdeps/generic/ldconfig.h |  6 +++---
>  6 files changed, 39 insertions(+), 39 deletions(-)
> 
> diff --git a/elf/cache.c b/elf/cache.c
> index 1c0dc5ee87..86b6896cca 100644
> --- a/elf/cache.c
> +++ b/elf/cache.c
> @@ -318,8 +318,8 @@ print_cache (const char *cache_name)
>    if (fd < 0)
>      error (EXIT_FAILURE, errno, _("Can't open cache file %s\n"), cache_name);
>  
> -  struct stat64 st;
> -  if (__fstat64 (fd, &st) < 0
> +  struct stat st;
> +  if (fstat (fd, &st) < 0

OK. 1/5

>        /* No need to map the file if it is empty.  */
>        || st.st_size == 0)
>      {
> @@ -932,7 +932,7 @@ init_aux_cache (void)
>  }
>  
>  int
> -search_aux_cache (struct stat64 *stat_buf, int *flags,
> +search_aux_cache (struct stat *stat_buf, int *flags,

OK. 2/5

>  		  unsigned int *osversion, unsigned int *isa_level,
>  		  char **soname)
>  {
> @@ -994,7 +994,7 @@ insert_to_aux_cache (struct aux_cache_entry_id *id, int flags,
>  }
>  
>  void
> -add_to_aux_cache (struct stat64 *stat_buf, int flags,
> +add_to_aux_cache (struct stat *stat_buf, int flags,

OK. 3/5

>  		  unsigned int osversion, unsigned int isa_level,
>  		  const char *soname)
>  {
> @@ -1017,8 +1017,8 @@ load_aux_cache (const char *aux_cache_name)
>        return;
>      }
>  
> -  struct stat64 st;
> -  if (__fstat64 (fd, &st) < 0 || st.st_size < sizeof (struct aux_cache_file))
> +  struct stat st;
> +  if (fstat (fd, &st) < 0 || st.st_size < sizeof (struct aux_cache_file))

OK. 4/5

>      {
>        close (fd);
>        init_aux_cache ();
> @@ -1134,8 +1134,8 @@ save_aux_cache (const char *aux_cache_name)
>    char *dir = strdupa (aux_cache_name);
>    dir = dirname (dir);
>  
> -  struct stat64 st;
> -  if (stat64 (dir, &st) < 0)
> +  struct stat st;
> +  if (stat (dir, &st) < 0)

OK. 5/5

>      {
>        if (mkdir (dir, 0700) < 0)
>  	goto out_fail;
> diff --git a/elf/chroot_canon.c b/elf/chroot_canon.c
> index 045611e730..a70fd25046 100644
> --- a/elf/chroot_canon.c
> +++ b/elf/chroot_canon.c
> @@ -67,7 +67,7 @@ chroot_canon (const char *chroot, const char *name)
>  
>    for (start = end = name; *start; start = end)
>      {
> -      struct stat64 st;
> +      struct stat st;

OK. 1/2.

>  
>        /* Skip sequence of multiple path-separators.  */
>        while (*start == '/')
> @@ -114,7 +114,7 @@ chroot_canon (const char *chroot, const char *name)
>  	  dest = mempcpy (dest, start, end - start);
>  	  *dest = '\0';
>  
> -	  if (lstat64 (rpath, &st) < 0)
> +	  if (lstat (rpath, &st) < 0)

OK. 2/2.

>  	    {
>  	      if (*end == '\0')
>  		goto done;
> diff --git a/elf/ldconfig.c b/elf/ldconfig.c
> index 101d56ac8e..40f76d0ffd 100644
> --- a/elf/ldconfig.c
> +++ b/elf/ldconfig.c
> @@ -337,7 +337,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
>     inode data from *ST.  */
>  static struct dir_entry *
>  new_sub_entry (const struct dir_entry *entry, const char *path,
> -	       const struct stat64 *st)
> +	       const struct stat *st)

OK. 1/19.

>  {
>    struct dir_entry *new_entry = xmalloc (sizeof (struct dir_entry));
>    new_entry->from_file = entry->from_file;
> @@ -427,8 +427,8 @@ add_glibc_hwcaps_subdirectories (struct dir_entry *entry, const char *path)
>  	    continue;
>  
>  	  /* See if this entry eventually resolves to a directory.  */
> -	  struct stat64 st;
> -	  if (fstatat64 (dirfd (dir), e->d_name, &st, 0) < 0)
> +	  struct stat st;
> +	  if (fstatat (dirfd (dir), e->d_name, &st, 0) < 0)

OK. 2/19.

>  	    /* Ignore unreadable entries.  */
>  	    continue;
>  
> @@ -512,8 +512,8 @@ add_dir_1 (const char *line, const char *from_file, int from_line)
>    if (opt_chroot != NULL)
>      path = chroot_canon (opt_chroot, path);
>  
> -  struct stat64 stat_buf;
> -  if (path == NULL || stat64 (path, &stat_buf))
> +  struct stat stat_buf;
> +  if (path == NULL || stat (path, &stat_buf))

OK. 3/19

>      {
>        if (opt_verbose)
>  	error (0, errno, _("Can't stat %s"), entry->path);
> @@ -541,15 +541,15 @@ add_dir (const char *line)
>  }
>  
>  static int
> -chroot_stat (const char *real_path, const char *path, struct stat64 *st)
> +chroot_stat (const char *real_path, const char *path, struct stat *st)

OK. 4/19

>  {
>    int ret;
>    char *canon_path;
>  
>    if (!opt_chroot)
> -    return stat64 (real_path, st);
> +    return stat (real_path, st);

OK. 5/19

>  
> -  ret = lstat64 (real_path, st);
> +  ret = lstat (real_path, st);

OK. 6/19

>    if (ret || !S_ISLNK (st->st_mode))
>      return ret;
>  
> @@ -557,7 +557,7 @@ chroot_stat (const char *real_path, const char *path, struct stat64 *st)
>    if (canon_path == NULL)
>      return -1;
>  
> -  ret = stat64 (canon_path, st);
> +  ret = stat (canon_path, st);

OK. 7/19

>    free (canon_path);
>    return ret;
>  }
> @@ -569,7 +569,7 @@ create_links (const char *real_path, const char *path, const char *libname,
>  {
>    char *full_libname, *full_soname;
>    char *real_full_libname, *real_full_soname;
> -  struct stat64 stat_lib, stat_so, lstat_so;
> +  struct stat stat_lib, stat_so, lstat_so;

OK. 8/19

>    int do_link = 1;
>    int do_remove = 1;
>    /* XXX: The logics in this function should be simplified.  */
> @@ -604,7 +604,7 @@ create_links (const char *real_path, const char *path, const char *libname,
>  	  && stat_lib.st_ino == stat_so.st_ino)
>  	/* Link is already correct.  */
>  	do_link = 0;
> -      else if (lstat64 (full_soname, &lstat_so) == 0
> +      else if (lstat (full_soname, &lstat_so) == 0

OK. 9/19

>  	       && !S_ISLNK (lstat_so.st_mode))
>  	{
>  	  error (0, 0, _("%s is not a symbolic link\n"), full_soname);
> @@ -612,7 +612,7 @@ create_links (const char *real_path, const char *path, const char *libname,
>  	  do_remove = 0;
>  	}
>      }
> -  else if (lstat64 (real_full_soname, &lstat_so) != 0
> +  else if (lstat (real_full_soname, &lstat_so) != 0

OK. 10/19

>  	   || !S_ISLNK (lstat_so.st_mode))
>      /* Unless it is a stale symlink, there is no need to remove.  */
>      do_remove = 0;
> @@ -656,7 +656,7 @@ manual_link (char *library)
>    char *real_library;
>    char *libname;
>    char *soname;
> -  struct stat64 stat_buf;
> +  struct stat stat_buf;

OK. 11/19

>    int flag;
>    unsigned int osversion;
>    unsigned int isa_level;
> @@ -710,7 +710,7 @@ manual_link (char *library)
>      }
>  
>    /* Do some sanity checks first.  */
> -  if (lstat64 (real_library, &stat_buf))
> +  if (lstat (real_library, &stat_buf))

OK. 12/19

>      {
>        error (0, errno, _("Cannot lstat %s"), library);
>        goto out;
> @@ -885,18 +885,18 @@ search_dir (const struct dir_entry *entry)
>  	  sprintf (real_file_name, "%s/%s", dir_name, direntry->d_name);
>  	}
>  
> -      struct stat64 lstat_buf;
> +      struct stat lstat_buf;

OK. 13/19

>        /* We optimize and try to do the lstat call only if needed.  */
>        if (direntry->d_type != DT_UNKNOWN)
>  	lstat_buf.st_mode = DTTOIF (direntry->d_type);
>        else
> -	if (__glibc_unlikely (lstat64 (real_file_name, &lstat_buf)))
> +	if (__glibc_unlikely (lstat (real_file_name, &lstat_buf)))

OK. 14/19

>  	  {
>  	    error (0, errno, _("Cannot lstat %s"), file_name);
>  	    continue;
>  	  }
>  
> -      struct stat64 stat_buf;
> +      struct stat stat_buf;

OK. 15/19

>        bool is_dir;
>        int is_link = S_ISLNK (lstat_buf.st_mode);
>        if (is_link)
> @@ -914,7 +914,7 @@ search_dir (const struct dir_entry *entry)
>  		  continue;
>  		}
>  	    }
> -	  if (__glibc_unlikely (stat64 (target_name, &stat_buf)))
> +	  if (__glibc_unlikely (stat (target_name, &stat_buf)))

OK. 16/19

>  	    {
>  	      if (opt_verbose)
>  		error (0, errno, _("Cannot stat %s"), file_name);
> @@ -950,7 +950,7 @@ search_dir (const struct dir_entry *entry)
>  	{
>  	  if (!is_link
>  	      && direntry->d_type != DT_UNKNOWN
> -	      && __builtin_expect (lstat64 (real_file_name, &lstat_buf), 0))
> +	      && __builtin_expect (lstat (real_file_name, &lstat_buf), 0))

OK. 17/19

>  	    {
>  	      error (0, errno, _("Cannot lstat %s"), file_name);
>  	      continue;
> @@ -979,10 +979,10 @@ search_dir (const struct dir_entry *entry)
>        else
>  	real_name = real_file_name;
>  
> -      /* Call lstat64 if not done yet.  */
> +      /* Call lstat if not done yet.  */

OK. 18/19

>        if (!is_link
>  	  && direntry->d_type != DT_UNKNOWN
> -	  && __builtin_expect (lstat64 (real_file_name, &lstat_buf), 0))
> +	  && __builtin_expect (lstat (real_file_name, &lstat_buf), 0))

OK. 19/19

>  	{
>  	  error (0, errno, _("Cannot lstat %s"), file_name);
>  	  continue;
> diff --git a/elf/readlib.c b/elf/readlib.c
> index 64b20d7804..3e2c6383c1 100644
> --- a/elf/readlib.c
> +++ b/elf/readlib.c
> @@ -74,10 +74,10 @@ int
>  process_file (const char *real_file_name, const char *file_name,
>  	      const char *lib, int *flag, unsigned int *osversion,
>  	      unsigned int *isa_level, char **soname, int is_link,
> -	      struct stat64 *stat_buf)
> +	      struct stat *stat_buf)

OK. 1/3

>  {
>    FILE *file;
> -  struct stat64 statbuf;
> +  struct stat statbuf;

OK. 2/3

>    void *file_contents;
>    int ret;
>    ElfW(Ehdr) *elf_header;
> @@ -97,7 +97,7 @@ process_file (const char *real_file_name, const char *file_name,
>        return 1;
>      }
>  
> -  if (fstat64 (fileno (file), &statbuf) < 0)
> +  if (fstat (fileno (file), &statbuf) < 0)

OK. 3/3

>      {
>        error (0, 0, _("Cannot fstat file %s.\n"), file_name);
>        fclose (file);
> diff --git a/elf/sln.c b/elf/sln.c
> index 26f371a493..f71321d565 100644
> --- a/elf/sln.c
> +++ b/elf/sln.c
> @@ -153,11 +153,11 @@ makesymlinks (const char *file)
>  static int
>  makesymlink (const char *src, const char *dest)
>  {
> -  struct stat64 stats;
> +  struct stat stats;

OK. 1/2

>    const char *error;
>  
>    /* Destination must not be a directory. */
> -  if (lstat64 (dest, &stats) == 0)
> +  if (lstat (dest, &stats) == 0)

OK. 2/2

>      {
>        if (S_ISDIR (stats.st_mode))
>  	{
> diff --git a/sysdeps/generic/ldconfig.h b/sysdeps/generic/ldconfig.h
> index 371d97eca2..b99a92654b 100644
> --- a/sysdeps/generic/ldconfig.h
> +++ b/sysdeps/generic/ldconfig.h
> @@ -78,11 +78,11 @@ extern void init_aux_cache (void);
>  
>  extern void load_aux_cache (const char *aux_cache_name);
>  
> -extern int search_aux_cache (struct stat64 *stat_buf, int *flags,
> +extern int search_aux_cache (struct stat *stat_buf, int *flags,

OK.

>  			     unsigned int *osversion,
>  			     unsigned int *isa_level, char **soname);
>  
> -extern void add_to_aux_cache (struct stat64 *stat_buf, int flags,
> +extern void add_to_aux_cache (struct stat *stat_buf, int flags,

OK.

>  			      unsigned int osversion,
>  			      unsigned int isa_level, const char *soname);
>  
> @@ -93,7 +93,7 @@ extern int process_file (const char *real_file_name, const char *file_name,
>  			 const char *lib, int *flag,
>  			 unsigned int *osversion, unsigned int *isa_level,
>  			 char **soname, int is_link,
> -			 struct stat64 *stat_buf);
> +			 struct stat *stat_buf);

OK.

>  
>  extern char *implicit_soname (const char *lib, int flag);
>  


-- 
Cheers,
Carlos.



More information about the Libc-alpha mailing list