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