(root)/
glibc-2.38/
sysdeps/
generic/
dl-cache.h
       1  /* Support for reading /etc/ld.so.cache files written by Linux ldconfig.
       2     Copyright (C) 1999-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #ifndef _DL_CACHE_H
      20  #define _DL_CACHE_H
      21  
      22  #include <endian.h>
      23  #include <stdbool.h>
      24  #include <stddef.h>
      25  #include <stdint.h>
      26  #include <string.h>
      27  
      28  #ifndef _DL_CACHE_DEFAULT_ID
      29  # define _DL_CACHE_DEFAULT_ID	3
      30  #endif
      31  
      32  #ifndef _dl_cache_check_flags
      33  # define _dl_cache_check_flags(flags)			\
      34    ((flags) == 1 || (flags) == _DL_CACHE_DEFAULT_ID)
      35  #endif
      36  
      37  #ifndef LD_SO_CACHE
      38  # define LD_SO_CACHE SYSCONFDIR "/ld.so.cache"
      39  #endif
      40  
      41  #ifndef add_system_dir
      42  # define add_system_dir(dir) add_dir (dir)
      43  #endif
      44  
      45  #define CACHEMAGIC "ld.so-1.7.0"
      46  
      47  /* libc5 and glibc 2.0/2.1 use the same format.  For glibc 2.2 another
      48     format has been added in a compatible way:
      49     The beginning of the string table is used for the new table:
      50  	old_magic
      51  	nlibs
      52  	libs[0]
      53  	...
      54  	libs[nlibs-1]
      55  	pad, new magic needs to be aligned
      56  	     - this is string[0] for the old format
      57  	new magic - this is string[0] for the new format
      58  	newnlibs
      59  	...
      60  	newlibs[0]
      61  	...
      62  	newlibs[newnlibs-1]
      63  	string 1
      64  	string 2
      65  	...
      66  */
      67  struct file_entry
      68  {
      69    int32_t flags;		/* This is 1 for an ELF library.  */
      70    uint32_t key, value;		/* String table indices.  */
      71  };
      72  
      73  struct cache_file
      74  {
      75    char magic[sizeof CACHEMAGIC - 1];
      76    unsigned int nlibs;
      77    struct file_entry libs[0];
      78  };
      79  
      80  #define CACHEMAGIC_NEW "glibc-ld.so.cache"
      81  #define CACHE_VERSION "1.1"
      82  #define CACHEMAGIC_VERSION_NEW CACHEMAGIC_NEW CACHE_VERSION
      83  
      84  
      85  struct file_entry_new
      86  {
      87    union
      88    {
      89      /* Fields shared with struct file_entry.  */
      90      struct file_entry entry;
      91      /* Also expose these fields directly.  */
      92      struct
      93      {
      94        int32_t flags;		/* This is 1 for an ELF library.  */
      95        uint32_t key, value;	/* String table indices.  */
      96      };
      97    };
      98    uint32_t osversion_unused;	/* Required OS version (unused).  */
      99    uint64_t hwcap;		/* Hwcap entry.	 */
     100  };
     101  
     102  /* This bit in the hwcap field of struct file_entry_new indicates that
     103     the lower 32 bits contain an index into the
     104     cache_extension_tag_glibc_hwcaps section.  Older glibc versions do
     105     not know about this HWCAP bit, so they will ignore these
     106     entries.  */
     107  #define DL_CACHE_HWCAP_EXTENSION (1ULL << 62)
     108  
     109  /* The number of the ISA level bits in the upper 32 bits of the hwcap
     110     field.  */
     111  #define DL_CACHE_HWCAP_ISA_LEVEL_COUNT 10
     112  
     113  /* The mask of the ISA level bits in the hwcap field.  */
     114  #define DL_CACHE_HWCAP_ISA_LEVEL_MASK \
     115    ((1 << DL_CACHE_HWCAP_ISA_LEVEL_COUNT) -1)
     116  
     117  /* Return true if the ENTRY->hwcap value indicates that
     118     DL_CACHE_HWCAP_EXTENSION is used.  */
     119  static inline bool
     120  dl_cache_hwcap_extension (struct file_entry_new *entry)
     121  {
     122    /* This is an hwcap extension if only the DL_CACHE_HWCAP_EXTENSION bit
     123       is set, ignoring the lower 32 bits as well as the ISA level bits in
     124       the upper 32 bits.  */
     125    return (((entry->hwcap >> 32) & ~DL_CACHE_HWCAP_ISA_LEVEL_MASK)
     126  	  == (DL_CACHE_HWCAP_EXTENSION >> 32));
     127  }
     128  
     129  /* See flags member of struct cache_file_new below.  */
     130  enum
     131    {
     132      /* No endianness information available.  An old ldconfig version
     133         without endianness support wrote the file.  */
     134      cache_file_new_flags_endian_unset = 0,
     135  
     136      /* Cache is invalid and should be ignored.  */
     137      cache_file_new_flags_endian_invalid = 1,
     138  
     139      /* Cache format is little endian.  */
     140      cache_file_new_flags_endian_little = 2,
     141  
     142      /* Cache format is big endian.  */
     143      cache_file_new_flags_endian_big = 3,
     144  
     145      /* Bit mask to extract the cache_file_new_flags_endian_*
     146         values.  */
     147      cache_file_new_flags_endian_mask = 3,
     148  
     149      /* Expected value of the endian bits in the flags member for the
     150         current architecture.  */
     151      cache_file_new_flags_endian_current
     152        = (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
     153  	 ? cache_file_new_flags_endian_little
     154  	 : cache_file_new_flags_endian_big),
     155    };
     156  
     157  struct cache_file_new
     158  {
     159    char magic[sizeof CACHEMAGIC_NEW - 1];
     160    char version[sizeof CACHE_VERSION - 1];
     161    uint32_t nlibs;		/* Number of entries.  */
     162    uint32_t len_strings;		/* Size of string table. */
     163  
     164    /* flags & cache_file_new_flags_endian_mask is one of the values
     165       cache_file_new_flags_endian_unset, cache_file_new_flags_endian_invalid,
     166       cache_file_new_flags_endian_little, cache_file_new_flags_endian_big.
     167  
     168       The remaining bits are unused and should be generated as zero and
     169       ignored by readers.  */
     170    uint8_t flags;
     171  
     172    uint8_t padding_unsed[3];	/* Not used, for future extensions.  */
     173  
     174    /* File offset of the extension directory.  See struct
     175       cache_extension below.  Must be a multiple of four.  */
     176    uint32_t extension_offset;
     177  
     178    uint32_t unused[3];		/* Leave space for future extensions
     179  				   and align to 8 byte boundary.  */
     180    struct file_entry_new libs[0]; /* Entries describing libraries.  */
     181    /* After this the string table of size len_strings is found.	*/
     182  };
     183  _Static_assert (sizeof (struct cache_file_new) == 48,
     184  		"size of struct cache_file_new");
     185  
     186  /* Returns false if *CACHE has the wrong endianness for this
     187     architecture, and true if the endianness matches (or is
     188     unknown).  */
     189  static inline bool
     190  cache_file_new_matches_endian (const struct cache_file_new *cache)
     191  {
     192    /* A zero value for cache->flags means that no endianness
     193       information is available.  */
     194    return cache->flags == 0
     195      || ((cache->flags & cache_file_new_flags_endian_big)
     196  	== cache_file_new_flags_endian_current);
     197  }
     198  
     199  
     200  /* Randomly chosen magic value, which allows for additional
     201     consistency verification.  */
     202  enum { cache_extension_magic = (uint32_t) -358342284 };
     203  
     204  /* Tag values for different kinds of extension sections.  Similar to
     205     SHT_* constants.  */
     206  enum cache_extension_tag
     207    {
     208     /* Array of bytes containing the glibc version that generated this
     209        cache file.  */
     210     cache_extension_tag_generator,
     211  
     212     /* glibc-hwcaps subdirectory information.  An array of uint32_t
     213        values, which are indices into the string table.  The strings
     214        are sorted lexicographically (according to strcmp).  The extra
     215        level of indirection (instead of using string table indices
     216        directly) allows the dynamic loader to compute the preference
     217        order of the hwcaps names more efficiently.
     218  
     219        For this section, 4-byte alignment is required, and the section
     220        size must be a multiple of 4.  */
     221     cache_extension_tag_glibc_hwcaps,
     222  
     223     /* Total number of known cache extension tags.  */
     224     cache_extension_count
     225    };
     226  
     227  /* Element in the array following struct cache_extension.  Similar to
     228     an ELF section header.  */
     229  struct cache_extension_section
     230  {
     231    /* Type of the extension section.  A enum cache_extension_tag value.  */
     232    uint32_t tag;
     233  
     234    /* Extension-specific flags.  Currently generated as zero.  */
     235    uint32_t flags;
     236  
     237    /* Offset from the start of the file for the data in this extension
     238       section.  Specific extensions can have alignment constraints.  */
     239    uint32_t offset;
     240  
     241    /* Length in bytes of the extension data.  Specific extensions may
     242       have size requirements.  */
     243    uint32_t size;
     244  };
     245  
     246  /* The extension directory in the cache.  An array of struct
     247     cache_extension_section entries.  */
     248  struct cache_extension
     249  {
     250    uint32_t magic;		/* Always cache_extension_magic.  */
     251    uint32_t count;		/* Number of following entries.  */
     252  
     253    /* count section descriptors of type struct cache_extension_section
     254       follow.  */
     255    struct cache_extension_section sections[];
     256  };
     257  
     258  /* A relocated version of struct cache_extension_section.  */
     259  struct cache_extension_loaded
     260  {
     261    /* Address and size of this extension section.  base is NULL if the
     262       section is missing from the file.  */
     263    const void *base;
     264    size_t size;
     265  
     266    /* Flags from struct cache_extension_section.  */
     267    uint32_t flags;
     268  };
     269  
     270  /* All supported extension sections, relocated.  Filled in by
     271     cache_extension_load below.  */
     272  struct cache_extension_all_loaded
     273  {
     274    struct cache_extension_loaded sections[cache_extension_count];
     275  };
     276  
     277  /* Performs basic data validation based on section tag, and removes
     278     the sections which are invalid.  */
     279  static void
     280  cache_extension_verify (struct cache_extension_all_loaded *loaded)
     281  {
     282    {
     283      /* Section must not be empty, it must be aligned at 4 bytes, and
     284         the size must be a multiple of 4.  */
     285      struct cache_extension_loaded *hwcaps
     286        = &loaded->sections[cache_extension_tag_glibc_hwcaps];
     287      if (hwcaps->size == 0
     288  	|| ((uintptr_t) hwcaps->base % 4) != 0
     289  	|| (hwcaps->size % 4) != 0)
     290        {
     291  	hwcaps->base = NULL;
     292  	hwcaps->size = 0;
     293  	hwcaps->flags = 0;
     294        }
     295    }
     296  }
     297  
     298  static bool __attribute__ ((unused))
     299  cache_extension_load (const struct cache_file_new *cache,
     300  		      const void *file_base, size_t file_size,
     301  		      struct cache_extension_all_loaded *loaded)
     302  {
     303    memset (loaded, 0, sizeof (*loaded));
     304    if (cache->extension_offset == 0)
     305      /* No extensions present.  This is not a format error.  */
     306      return true;
     307    if ((cache->extension_offset % 4) != 0)
     308      /* Extension offset is misaligned.  */
     309      return false;
     310    size_t size_tmp;
     311    if (__builtin_add_overflow (cache->extension_offset,
     312  			      sizeof (struct cache_extension), &size_tmp)
     313        || size_tmp > file_size)
     314      /* Extension extends beyond the end of the file.  */
     315      return false;
     316    const struct cache_extension *ext = file_base + cache->extension_offset;
     317    if (ext->magic != cache_extension_magic)
     318      return false;
     319    if (__builtin_mul_overflow (ext->count,
     320  			      sizeof (struct cache_extension_section),
     321  			      &size_tmp)
     322        || __builtin_add_overflow (cache->extension_offset
     323  				 + sizeof (struct cache_extension), size_tmp,
     324  				 &size_tmp)
     325        || size_tmp > file_size)
     326      /* Extension array extends beyond the end of the file.  */
     327      return false;
     328    for (uint32_t i = 0; i < ext->count; ++i)
     329      {
     330        if (__builtin_add_overflow (ext->sections[i].offset,
     331  				  ext->sections[i].size, &size_tmp)
     332  	  || size_tmp > file_size)
     333  	/* Extension data extends beyond the end of the file.  */
     334  	return false;
     335  
     336        uint32_t tag = ext->sections[i].tag;
     337        if (tag >= cache_extension_count)
     338  	/* Tag is out of range and unrecognized.  */
     339  	continue;
     340        loaded->sections[tag].base = file_base + ext->sections[i].offset;
     341        loaded->sections[tag].size = ext->sections[i].size;
     342        loaded->sections[tag].flags = ext->sections[i].flags;
     343      }
     344    cache_extension_verify (loaded);
     345    return true;
     346  }
     347  
     348  /* Used to align cache_file_new.  */
     349  #define ALIGN_CACHE(addr)				\
     350  (((addr) + __alignof__ (struct cache_file_new) -1)	\
     351   & (~(__alignof__ (struct cache_file_new) - 1)))
     352  
     353  extern int _dl_cache_libcmp (const char *p1, const char *p2) attribute_hidden;
     354  
     355  #endif /* _DL_CACHE_H */