Add a test for longjmp from user context
[glibc.git] / sysdeps / generic / dl-cache.h
blobbd39ff7fb7f7b34774096d73684476ac18ba6fd6
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.
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.
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.
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/>. */
19 #ifndef _DL_CACHE_H
20 #define _DL_CACHE_H
22 #include <endian.h>
23 #include <stdbool.h>
24 #include <stddef.h>
25 #include <stdint.h>
26 #include <string.h>
28 #ifndef _DL_CACHE_DEFAULT_ID
29 # define _DL_CACHE_DEFAULT_ID 3
30 #endif
32 #ifndef _dl_cache_check_flags
33 # define _dl_cache_check_flags(flags) \
34 ((flags) == 1 || (flags) == _DL_CACHE_DEFAULT_ID)
35 #endif
37 #ifndef LD_SO_CACHE
38 # define LD_SO_CACHE SYSCONFDIR "/ld.so.cache"
39 #endif
41 #ifndef add_system_dir
42 # define add_system_dir(dir) add_dir (dir)
43 #endif
45 #define CACHEMAGIC "ld.so-1.7.0"
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 ...
67 struct file_entry
69 int32_t flags; /* This is 1 for an ELF library. */
70 uint32_t key, value; /* String table indices. */
73 struct cache_file
75 char magic[sizeof CACHEMAGIC - 1];
76 unsigned int nlibs;
77 struct file_entry libs[0];
80 #define CACHEMAGIC_NEW "glibc-ld.so.cache"
81 #define CACHE_VERSION "1.1"
82 #define CACHEMAGIC_VERSION_NEW CACHEMAGIC_NEW CACHE_VERSION
85 struct file_entry_new
87 union
89 /* Fields shared with struct file_entry. */
90 struct file_entry entry;
91 /* Also expose these fields directly. */
92 struct
94 int32_t flags; /* This is 1 for an ELF library. */
95 uint32_t key, value; /* String table indices. */
98 uint32_t osversion_unused; /* Required OS version (unused). */
99 uint64_t hwcap; /* Hwcap entry. */
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)
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
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)
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)
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));
129 /* See flags member of struct cache_file_new below. */
130 enum
132 /* No endianness information available. An old ldconfig version
133 without endianness support wrote the file. */
134 cache_file_new_flags_endian_unset = 0,
136 /* Cache is invalid and should be ignored. */
137 cache_file_new_flags_endian_invalid = 1,
139 /* Cache format is little endian. */
140 cache_file_new_flags_endian_little = 2,
142 /* Cache format is big endian. */
143 cache_file_new_flags_endian_big = 3,
145 /* Bit mask to extract the cache_file_new_flags_endian_*
146 values. */
147 cache_file_new_flags_endian_mask = 3,
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),
157 struct cache_file_new
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. */
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.
168 The remaining bits are unused and should be generated as zero and
169 ignored by readers. */
170 uint8_t flags;
172 uint8_t padding_unsed[3]; /* Not used, for future extensions. */
174 /* File offset of the extension directory. See struct
175 cache_extension below. Must be a multiple of four. */
176 uint32_t extension_offset;
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. */
183 _Static_assert (sizeof (struct cache_file_new) == 48,
184 "size of struct cache_file_new");
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)
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);
200 /* Randomly chosen magic value, which allows for additional
201 consistency verification. */
202 enum { cache_extension_magic = (uint32_t) -358342284 };
204 /* Tag values for different kinds of extension sections. Similar to
205 SHT_* constants. */
206 enum cache_extension_tag
208 /* Array of bytes containing the glibc version that generated this
209 cache file. */
210 cache_extension_tag_generator,
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.
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,
223 /* Total number of known cache extension tags. */
224 cache_extension_count
227 /* Element in the array following struct cache_extension. Similar to
228 an ELF section header. */
229 struct cache_extension_section
231 /* Type of the extension section. A enum cache_extension_tag value. */
232 uint32_t tag;
234 /* Extension-specific flags. Currently generated as zero. */
235 uint32_t flags;
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;
241 /* Length in bytes of the extension data. Specific extensions may
242 have size requirements. */
243 uint32_t size;
246 /* The extension directory in the cache. An array of struct
247 cache_extension_section entries. */
248 struct cache_extension
250 uint32_t magic; /* Always cache_extension_magic. */
251 uint32_t count; /* Number of following entries. */
253 /* count section descriptors of type struct cache_extension_section
254 follow. */
255 struct cache_extension_section sections[];
258 /* A relocated version of struct cache_extension_section. */
259 struct cache_extension_loaded
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;
266 /* Flags from struct cache_extension_section. */
267 uint32_t flags;
270 /* All supported extension sections, relocated. Filled in by
271 cache_extension_load below. */
272 struct cache_extension_all_loaded
274 struct cache_extension_loaded sections[cache_extension_count];
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)
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)
291 hwcaps->base = NULL;
292 hwcaps->size = 0;
293 hwcaps->flags = 0;
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)
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)
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;
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;
344 cache_extension_verify (loaded);
345 return true;
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)))
353 extern int _dl_cache_libcmp (const char *p1, const char *p2) attribute_hidden;
355 #endif /* _DL_CACHE_H */