1 /* Support for reading /etc/ld.so.cache files written by Linux ldconfig.
2    Copyright (C) 1999-2022 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
dl_cache_hwcap_extension(struct file_entry_new * entry)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
cache_file_new_matches_endian(const struct cache_file_new * cache)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
cache_extension_verify(struct cache_extension_all_loaded * loaded)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))
cache_extension_load(const struct cache_file_new * cache,const void * file_base,size_t file_size,struct cache_extension_all_loaded * loaded)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 */
356