1 /* Copyright (C) 1999-2021 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published
6    by the Free Software Foundation; version 2 of the License, or
7    (at your option) any later version.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, see <https://www.gnu.org/licenses/>.  */
16 
17 #include <assert.h>
18 #include <errno.h>
19 #include <error.h>
20 #include <dirent.h>
21 #include <inttypes.h>
22 #include <libgen.h>
23 #include <libintl.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <stdint.h>
29 #include <sys/fcntl.h>
30 #include <sys/mman.h>
31 #include <sys/param.h>
32 #include <sys/stat.h>
33 #include <sys/types.h>
34 
35 #include <ldconfig.h>
36 #include <dl-cache.h>
37 #include <version.h>
38 #include <stringtable.h>
39 
40 /* Used to store library names, paths, and other strings.  */
41 static struct stringtable strings;
42 
43 /* Keeping track of "glibc-hwcaps" subdirectories.  During cache
44    construction, a linear search by name is performed to deduplicate
45    entries.  */
46 struct glibc_hwcaps_subdirectory
47 {
48   struct glibc_hwcaps_subdirectory *next;
49 
50   /* Interned string with the subdirectory name.  */
51   struct stringtable_entry *name;
52 
53   /* Array index in the cache_extension_tag_glibc_hwcaps section in
54      the stored cached file.  This is computed after all the
55      subdirectories have been processed, so that subdirectory names in
56      the extension section can be sorted.  */
57   uint32_t section_index;
58 
59   /* True if the subdirectory is actually used for anything.  */
60   bool used;
61 };
62 
63 const char *
glibc_hwcaps_subdirectory_name(const struct glibc_hwcaps_subdirectory * dir)64 glibc_hwcaps_subdirectory_name (const struct glibc_hwcaps_subdirectory *dir)
65 {
66   return dir->name->string;
67 }
68 
69 /* Linked list of known hwcaps subdirecty names.  */
70 static struct glibc_hwcaps_subdirectory *hwcaps;
71 
72 struct glibc_hwcaps_subdirectory *
new_glibc_hwcaps_subdirectory(const char * name)73 new_glibc_hwcaps_subdirectory (const char *name)
74 {
75   struct stringtable_entry *name_interned = stringtable_add (&strings, name);
76   for (struct glibc_hwcaps_subdirectory *p = hwcaps; p != NULL; p = p->next)
77     if (p->name == name_interned)
78       return p;
79   struct glibc_hwcaps_subdirectory *p = xmalloc (sizeof (*p));
80   p->next = hwcaps;
81   p->name = name_interned;
82   p->section_index = 0;
83   p->used = false;
84   hwcaps = p;
85   return p;
86 }
87 
88 /* Helper for sorting struct glibc_hwcaps_subdirectory elements by
89    name.  */
90 static int
assign_glibc_hwcaps_indices_compare(const void * l,const void * r)91 assign_glibc_hwcaps_indices_compare (const void *l, const void *r)
92 {
93   const struct glibc_hwcaps_subdirectory *left
94     = *(struct glibc_hwcaps_subdirectory **)l;
95   const struct glibc_hwcaps_subdirectory *right
96     = *(struct glibc_hwcaps_subdirectory **)r;
97   return strcmp (glibc_hwcaps_subdirectory_name (left),
98 		 glibc_hwcaps_subdirectory_name (right));
99 }
100 
101 /* Count the number of hwcaps subdirectories which are actually
102    used.  */
103 static size_t
glibc_hwcaps_count(void)104 glibc_hwcaps_count (void)
105 {
106   size_t count = 0;
107   for (struct glibc_hwcaps_subdirectory *p = hwcaps; p != NULL; p = p->next)
108     if (p->used)
109       ++count;
110   return count;
111 }
112 
113 /* Compute the section_index fields for all   */
114 static void
assign_glibc_hwcaps_indices(void)115 assign_glibc_hwcaps_indices (void)
116 {
117   /* Convert the linked list into an array, so that we can use qsort.
118      Only copy the subdirectories which are actually used.  */
119   size_t count = glibc_hwcaps_count ();
120   struct glibc_hwcaps_subdirectory **array
121     = xmalloc (sizeof (*array) * count);
122   {
123     size_t i = 0;
124     for (struct glibc_hwcaps_subdirectory *p = hwcaps; p != NULL; p = p->next)
125       if (p->used)
126 	{
127 	  array[i] = p;
128 	  ++i;
129 	}
130     assert (i == count);
131   }
132 
133   qsort (array, count, sizeof (*array), assign_glibc_hwcaps_indices_compare);
134 
135   /* Assign the array indices.  */
136   for (size_t i = 0; i < count; ++i)
137     array[i]->section_index = i;
138 
139   free (array);
140 }
141 
142 struct cache_entry
143 {
144   struct stringtable_entry *lib; /* Library name.  */
145   struct stringtable_entry *path; /* Path to find library.  */
146   int flags;			/* Flags to indicate kind of library.  */
147   unsigned int osversion;	/* Required OS version.  */
148   unsigned int isa_level;	/* Required ISA level.  */
149   uint64_t hwcap;		/* Important hardware capabilities.  */
150   int bits_hwcap;		/* Number of bits set in hwcap.  */
151 
152   /* glibc-hwcaps subdirectory.  If not NULL, hwcap must be zero.  */
153   struct glibc_hwcaps_subdirectory *hwcaps;
154 
155   struct cache_entry *next;	/* Next entry in list.  */
156 };
157 
158 /* List of all cache entries.  */
159 static struct cache_entry *entries;
160 
161 static const char *flag_descr[] =
162 { "libc4", "ELF", "libc5", "libc6"};
163 
164 /* Print a single entry.  */
165 static void
print_entry(const char * lib,int flag,unsigned int osversion,uint64_t hwcap,const char * hwcap_string,const char * key)166 print_entry (const char *lib, int flag, unsigned int osversion,
167 	     uint64_t hwcap, const char *hwcap_string, const char *key)
168 {
169   printf ("\t%s (", lib);
170   switch (flag & FLAG_TYPE_MASK)
171     {
172     case FLAG_LIBC4:
173     case FLAG_ELF:
174     case FLAG_ELF_LIBC5:
175     case FLAG_ELF_LIBC6:
176       fputs (flag_descr[flag & FLAG_TYPE_MASK], stdout);
177       break;
178     default:
179       fputs (_("unknown"), stdout);
180       break;
181     }
182   switch (flag & FLAG_REQUIRED_MASK)
183     {
184     case FLAG_SPARC_LIB64:
185       fputs (",64bit", stdout);
186       break;
187     case FLAG_IA64_LIB64:
188       fputs (",IA-64", stdout);
189       break;
190     case FLAG_X8664_LIB64:
191       fputs (",x86-64", stdout);
192       break;
193     case FLAG_S390_LIB64:
194       fputs (",64bit", stdout);
195       break;
196     case FLAG_POWERPC_LIB64:
197       fputs (",64bit", stdout);
198       break;
199     case FLAG_MIPS64_LIBN32:
200       fputs (",N32", stdout);
201       break;
202     case FLAG_MIPS64_LIBN64:
203       fputs (",64bit", stdout);
204       break;
205     case FLAG_X8664_LIBX32:
206       fputs (",x32", stdout);
207       break;
208     case FLAG_ARM_LIBHF:
209       fputs (",hard-float", stdout);
210       break;
211     case FLAG_AARCH64_LIB64:
212       fputs (",AArch64", stdout);
213       break;
214     /* Uses the ARM soft-float ABI.  */
215     case FLAG_ARM_LIBSF:
216       fputs (",soft-float", stdout);
217       break;
218     case FLAG_MIPS_LIB32_NAN2008:
219       fputs (",nan2008", stdout);
220       break;
221     case FLAG_MIPS64_LIBN32_NAN2008:
222       fputs (",N32,nan2008", stdout);
223       break;
224     case FLAG_MIPS64_LIBN64_NAN2008:
225       fputs (",64bit,nan2008", stdout);
226       break;
227     case FLAG_RISCV_FLOAT_ABI_SOFT:
228       fputs (",soft-float", stdout);
229       break;
230     case FLAG_RISCV_FLOAT_ABI_DOUBLE:
231       fputs (",double-float", stdout);
232       break;
233     case 0:
234       break;
235     default:
236       printf (",%d", flag & FLAG_REQUIRED_MASK);
237       break;
238     }
239   if (hwcap_string != NULL)
240     printf (", hwcap: \"%s\"", hwcap_string);
241   else if (hwcap != 0)
242     printf (", hwcap: %#.16" PRIx64, hwcap);
243   if (osversion != 0)
244     {
245       static const char *const abi_tag_os[] =
246       {
247 	[0] = "Linux",
248 	[1] = "Hurd",
249 	[2] = "Solaris",
250 	[3] = "FreeBSD",
251 	[4] = "kNetBSD",
252 	[5] = "Syllable",
253 	[6] = N_("Unknown OS")
254       };
255 #define MAXTAG (sizeof abi_tag_os / sizeof abi_tag_os[0] - 1)
256       unsigned int os = osversion >> 24;
257 
258       printf (_(", OS ABI: %s %d.%d.%d"),
259 	      _(abi_tag_os[os > MAXTAG ? MAXTAG : os]),
260 	      (osversion >> 16) & 0xff,
261 	      (osversion >> 8) & 0xff,
262 	      osversion & 0xff);
263     }
264   printf (") => %s\n", key);
265 }
266 
267 /* Returns the string with the name of the glibcs-hwcaps subdirectory
268    associated with ENTRY->hwcap.  file_base must be the base address
269    for string table indices.  */
270 static const char *
glibc_hwcaps_string(struct cache_extension_all_loaded * ext,const void * file_base,size_t file_size,struct file_entry_new * entry)271 glibc_hwcaps_string (struct cache_extension_all_loaded *ext,
272 		     const void *file_base, size_t file_size,
273 		     struct file_entry_new *entry)
274 {
275   const uint32_t *hwcaps_array
276     = ext->sections[cache_extension_tag_glibc_hwcaps].base;
277   if (dl_cache_hwcap_extension (entry) && hwcaps_array != NULL)
278     {
279       uint32_t index = (uint32_t) entry->hwcap;
280       if (index < ext->sections[cache_extension_tag_glibc_hwcaps].size / 4)
281 	{
282 	  uint32_t string_table_index = hwcaps_array[index];
283 	  if (string_table_index < file_size)
284 	    return file_base + string_table_index;
285 	}
286     }
287   return NULL;
288 }
289 
290 /* Print an error and exit if the new-file cache is internally
291    inconsistent.  */
292 static void
check_new_cache(struct cache_file_new * cache)293 check_new_cache (struct cache_file_new *cache)
294 {
295   if (! cache_file_new_matches_endian (cache))
296     error (EXIT_FAILURE, 0, _("Cache file has wrong endianness.\n"));
297 }
298 
299 /* Print the extension information in *EXT.  */
300 static void
print_extensions(struct cache_extension_all_loaded * ext)301 print_extensions (struct cache_extension_all_loaded *ext)
302 {
303   if (ext->sections[cache_extension_tag_generator].base != NULL)
304     {
305       fputs (_("Cache generated by: "), stdout);
306       fwrite (ext->sections[cache_extension_tag_generator].base, 1,
307 	      ext->sections[cache_extension_tag_generator].size, stdout);
308       putchar ('\n');
309     }
310 }
311 
312 /* Print the whole cache file, if a file contains the new cache format
313    hidden in the old one, print the contents of the new format.  */
314 void
print_cache(const char * cache_name)315 print_cache (const char *cache_name)
316 {
317   int fd = open (cache_name, O_RDONLY);
318   if (fd < 0)
319     error (EXIT_FAILURE, errno, _("Can't open cache file %s\n"), cache_name);
320 
321   struct stat64 st;
322   if (__fstat64 (fd, &st) < 0
323       /* No need to map the file if it is empty.  */
324       || st.st_size == 0)
325     {
326       close (fd);
327       return;
328     }
329 
330   struct cache_file *cache
331     = mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
332   if (cache == MAP_FAILED)
333     error (EXIT_FAILURE, errno, _("mmap of cache file failed.\n"));
334 
335   size_t cache_size = st.st_size;
336   if (cache_size < sizeof (struct cache_file))
337     error (EXIT_FAILURE, 0, _("File is not a cache file.\n"));
338 
339   struct cache_file_new *cache_new = NULL;
340   const char *cache_data;
341   int format = 0;
342 
343   if (memcmp (cache->magic, CACHEMAGIC, sizeof CACHEMAGIC - 1))
344     {
345       /* This can only be the new format without the old one.  */
346       cache_new = (struct cache_file_new *) cache;
347 
348       if (memcmp (cache_new->magic, CACHEMAGIC_NEW, sizeof CACHEMAGIC_NEW - 1)
349 	  || memcmp (cache_new->version, CACHE_VERSION,
350 		      sizeof CACHE_VERSION - 1))
351 	error (EXIT_FAILURE, 0, _("File is not a cache file.\n"));
352       check_new_cache (cache_new);
353       format = 1;
354       /* This is where the strings start.  */
355       cache_data = (const char *) cache_new;
356     }
357   else
358     {
359       /* Check for corruption, avoiding overflow.  */
360       if ((cache_size - sizeof (struct cache_file)) / sizeof (struct file_entry)
361 	  < cache->nlibs)
362 	error (EXIT_FAILURE, 0, _("File is not a cache file.\n"));
363 
364       size_t offset = ALIGN_CACHE (sizeof (struct cache_file)
365 				   + (cache->nlibs
366 				      * sizeof (struct file_entry)));
367       /* This is where the strings start.  */
368       cache_data = (const char *) &cache->libs[cache->nlibs];
369 
370       /* Check for a new cache embedded in the old format.  */
371       if (cache_size
372 	  > (offset + sizeof (struct cache_file_new)))
373 	{
374 
375 	  cache_new = (struct cache_file_new *) ((void *)cache + offset);
376 
377 	  if (memcmp (cache_new->magic, CACHEMAGIC_NEW,
378 		      sizeof CACHEMAGIC_NEW - 1) == 0
379 	      && memcmp (cache_new->version, CACHE_VERSION,
380 			 sizeof CACHE_VERSION - 1) == 0)
381 	    {
382 	      check_new_cache (cache_new);
383 	      cache_data = (const char *) cache_new;
384 	      format = 1;
385 	    }
386 	}
387     }
388 
389   if (format == 0)
390     {
391       printf (_("%d libs found in cache `%s'\n"), cache->nlibs, cache_name);
392 
393       /* Print everything.  */
394       for (unsigned int i = 0; i < cache->nlibs; i++)
395 	print_entry (cache_data + cache->libs[i].key,
396 		     cache->libs[i].flags, 0, 0, NULL,
397 		     cache_data + cache->libs[i].value);
398     }
399   else if (format == 1)
400     {
401       struct cache_extension_all_loaded ext;
402       if (!cache_extension_load (cache_new, cache, cache_size, &ext))
403 	error (EXIT_FAILURE, 0,
404 	       _("Malformed extension data in cache file %s\n"), cache_name);
405 
406       printf (_("%d libs found in cache `%s'\n"),
407 	      cache_new->nlibs, cache_name);
408 
409       /* Print everything.  */
410       for (unsigned int i = 0; i < cache_new->nlibs; i++)
411 	{
412 	  const char *hwcaps_string
413 	    = glibc_hwcaps_string (&ext, cache, cache_size,
414 				   &cache_new->libs[i]);
415 	  print_entry (cache_data + cache_new->libs[i].key,
416 		       cache_new->libs[i].flags,
417 		       cache_new->libs[i].osversion,
418 		       cache_new->libs[i].hwcap, hwcaps_string,
419 		       cache_data + cache_new->libs[i].value);
420 	}
421       print_extensions (&ext);
422     }
423   /* Cleanup.  */
424   munmap (cache, cache_size);
425   close (fd);
426 }
427 
428 /* Initialize cache data structures.  */
429 void
init_cache(void)430 init_cache (void)
431 {
432   entries = NULL;
433 }
434 
435 static int
compare(const struct cache_entry * e1,const struct cache_entry * e2)436 compare (const struct cache_entry *e1, const struct cache_entry *e2)
437 {
438   /* We need to swap entries here to get the correct sort order.  */
439   int res = _dl_cache_libcmp (e2->lib->string, e1->lib->string);
440   if (res == 0)
441     {
442       if (e1->flags < e2->flags)
443 	return 1;
444       else if (e1->flags > e2->flags)
445 	return -1;
446       /* Keep the glibc-hwcaps extension entries before the regular
447 	 entries, and sort them by their names.  search_cache in
448 	 dl-cache.c stops searching once the first non-extension entry
449 	 is found, so the extension entries need to come first.  */
450       else if (e1->hwcaps != NULL && e2->hwcaps == NULL)
451 	return -1;
452       else if (e1->hwcaps == NULL && e2->hwcaps != NULL)
453 	return 1;
454       else if (e1->hwcaps != NULL && e2->hwcaps != NULL)
455 	{
456 	  res = strcmp (glibc_hwcaps_subdirectory_name (e1->hwcaps),
457 			glibc_hwcaps_subdirectory_name (e2->hwcaps));
458 	  if (res != 0)
459 	    return res;
460 	}
461       /* Sort by most specific hwcap.  */
462       if (e2->bits_hwcap > e1->bits_hwcap)
463 	return 1;
464       else if (e2->bits_hwcap < e1->bits_hwcap)
465 	return -1;
466       else if (e2->hwcap > e1->hwcap)
467 	return 1;
468       else if (e2->hwcap < e1->hwcap)
469 	return -1;
470       if (e2->osversion > e1->osversion)
471 	return 1;
472       if (e2->osversion < e1->osversion)
473 	return -1;
474     }
475   return res;
476 }
477 
478 /* Size of the cache extension directory.  All tags are assumed to be
479    present.  */
480 enum
481   {
482    cache_extension_size = (offsetof (struct cache_extension, sections)
483 			   + (cache_extension_count
484 			      * sizeof (struct cache_extension_section)))
485   };
486 
487 /* Write the cache extensions to FD.  The string table is shifted by
488    STRING_TABLE_OFFSET.  The extension directory is assumed to be
489    located at CACHE_EXTENSION_OFFSET.  assign_glibc_hwcaps_indices
490    must have been called.  */
491 static void
write_extensions(int fd,uint32_t str_offset,uint32_t cache_extension_offset)492 write_extensions (int fd, uint32_t str_offset,
493 		  uint32_t cache_extension_offset)
494 {
495   assert ((cache_extension_offset % 4) == 0);
496 
497   /* The length and contents of the glibc-hwcaps section.  */
498   uint32_t hwcaps_count = glibc_hwcaps_count ();
499   uint32_t hwcaps_offset = cache_extension_offset + cache_extension_size;
500   uint32_t hwcaps_size = hwcaps_count * sizeof (uint32_t);
501   uint32_t *hwcaps_array = xmalloc (hwcaps_size);
502   for (struct glibc_hwcaps_subdirectory *p = hwcaps; p != NULL; p = p->next)
503     if (p->used)
504       hwcaps_array[p->section_index] = str_offset + p->name->offset;
505 
506   /* This is the offset of the generator string.  */
507   uint32_t generator_offset = hwcaps_offset;
508   if (hwcaps_count == 0)
509     /* There is no section for the hwcaps subdirectories.  */
510     generator_offset -= sizeof (struct cache_extension_section);
511   else
512     /* The string table indices for the hwcaps subdirectories shift
513        the generator string backwards.  */
514     generator_offset += hwcaps_size;
515 
516   struct cache_extension *ext = xmalloc (cache_extension_size);
517   ext->magic = cache_extension_magic;
518 
519   /* Extension index current being filled.  */
520   size_t xid = 0;
521 
522   const char *generator
523     = "ldconfig " PKGVERSION RELEASE " release version " VERSION;
524   ext->sections[xid].tag = cache_extension_tag_generator;
525   ext->sections[xid].flags = 0;
526   ext->sections[xid].offset = generator_offset;
527   ext->sections[xid].size = strlen (generator);
528 
529   if (hwcaps_count > 0)
530     {
531       ++xid;
532       ext->sections[xid].tag = cache_extension_tag_glibc_hwcaps;
533       ext->sections[xid].flags = 0;
534       ext->sections[xid].offset = hwcaps_offset;
535       ext->sections[xid].size = hwcaps_size;
536     }
537 
538   ++xid;
539   ext->count = xid;
540   assert (xid <= cache_extension_count);
541 
542   size_t ext_size = (offsetof (struct cache_extension, sections)
543 		     + xid * sizeof (struct cache_extension_section));
544   if (write (fd, ext, ext_size) != ext_size
545       || write (fd, hwcaps_array, hwcaps_size) != hwcaps_size
546       || write (fd, generator, strlen (generator)) != strlen (generator))
547     error (EXIT_FAILURE, errno, _("Writing of cache extension data failed"));
548 
549   free (hwcaps_array);
550   free (ext);
551 }
552 
553 /* Compute the hwcap value from ENTRY.  */
554 static inline uint64_t
compute_hwcap_value(struct cache_entry * entry)555 compute_hwcap_value (struct cache_entry *entry)
556 {
557   if (entry->isa_level > DL_CACHE_HWCAP_ISA_LEVEL_MASK)
558     error (EXIT_FAILURE, 0, _("%s: ISA level is too high (%d > %d)"),
559 	   entry->path->string, entry->isa_level,
560 	   DL_CACHE_HWCAP_ISA_LEVEL_MASK);
561   return (DL_CACHE_HWCAP_EXTENSION
562 	  | (((uint64_t) entry->isa_level) << 32)
563 	  | entry->hwcaps->section_index);
564 }
565 
566 /* Save the contents of the cache.  */
567 void
save_cache(const char * cache_name)568 save_cache (const char *cache_name)
569 {
570   /* The cache entries are sorted already, save them in this order. */
571 
572   assign_glibc_hwcaps_indices ();
573 
574   struct cache_entry *entry;
575   /* Number of cache entries.  */
576   int cache_entry_count = 0;
577   /* The old format doesn't contain hwcap entries and doesn't contain
578      libraries in subdirectories with hwcaps entries.  Count therefore
579      also all entries with hwcap == 0.  */
580   int cache_entry_old_count = 0;
581 
582   for (entry = entries; entry != NULL; entry = entry->next)
583     {
584       ++cache_entry_count;
585       if (entry->hwcap == 0)
586 	++cache_entry_old_count;
587     }
588 
589   struct stringtable_finalized strings_finalized;
590   stringtable_finalize (&strings, &strings_finalized);
591 
592   /* Create the on disk cache structure.  */
593   struct cache_file *file_entries = NULL;
594   size_t file_entries_size = 0;
595 
596   if (opt_format != opt_format_new)
597     {
598       /* struct cache_file_new is 64-bit aligned on some arches while
599 	 only 32-bit aligned on other arches.  Duplicate last old
600 	 cache entry so that new cache in ld.so.cache can be used by
601 	 both.  */
602       if (opt_format != opt_format_old)
603 	cache_entry_old_count = (cache_entry_old_count + 1) & ~1;
604 
605       /* And the list of all entries in the old format.  */
606       file_entries_size = sizeof (struct cache_file)
607 	+ cache_entry_old_count * sizeof (struct file_entry);
608       file_entries = xmalloc (file_entries_size);
609 
610       /* Fill in the header.  */
611       memset (file_entries, '\0', sizeof (struct cache_file));
612       memcpy (file_entries->magic, CACHEMAGIC, sizeof CACHEMAGIC - 1);
613 
614       file_entries->nlibs = cache_entry_old_count;
615     }
616 
617   struct cache_file_new *file_entries_new = NULL;
618   size_t file_entries_new_size = 0;
619 
620   if (opt_format != opt_format_old)
621     {
622       /* And the list of all entries in the new format.  */
623       file_entries_new_size = sizeof (struct cache_file_new)
624 	+ cache_entry_count * sizeof (struct file_entry_new);
625       file_entries_new = xmalloc (file_entries_new_size);
626 
627       /* Fill in the header.  */
628       memset (file_entries_new, '\0', sizeof (struct cache_file_new));
629       memcpy (file_entries_new->magic, CACHEMAGIC_NEW,
630 	      sizeof CACHEMAGIC_NEW - 1);
631       memcpy (file_entries_new->version, CACHE_VERSION,
632 	      sizeof CACHE_VERSION - 1);
633 
634       file_entries_new->nlibs = cache_entry_count;
635       file_entries_new->len_strings = strings_finalized.size;
636       file_entries_new->flags = cache_file_new_flags_endian_current;
637     }
638 
639   /* Pad for alignment of cache_file_new.  */
640   size_t pad = ALIGN_CACHE (file_entries_size) - file_entries_size;
641 
642   /* If we have both formats, we hide the new format in the strings
643      table, we have to adjust all string indices for this so that
644      old libc5/glibc 2 dynamic linkers just ignore them.  */
645   unsigned int str_offset;
646   if (opt_format != opt_format_old)
647     str_offset = file_entries_new_size;
648   else
649     str_offset = 0;
650 
651   /* An array for all strings.  */
652   int idx_old;
653   int idx_new;
654 
655   for (idx_old = 0, idx_new = 0, entry = entries; entry != NULL;
656        entry = entry->next, ++idx_new)
657     {
658       if (opt_format != opt_format_new && entry->hwcap == 0)
659 	{
660 	  file_entries->libs[idx_old].flags = entry->flags;
661 	  /* XXX: Actually we can optimize here and remove duplicates.  */
662 	  file_entries->libs[idx_old].key = str_offset + pad;
663 	  file_entries->libs[idx_new].key = str_offset + entry->lib->offset;
664 	  file_entries->libs[idx_new].value
665 	    = str_offset + entry->path->offset;
666 	}
667       if (opt_format != opt_format_old)
668 	{
669 	  /* We could subtract file_entries_new_size from str_offset -
670 	     not doing so makes the code easier, the string table
671 	     always begins at the beginning of the new cache
672 	     struct.  */
673 	  file_entries_new->libs[idx_new].flags = entry->flags;
674 	  file_entries_new->libs[idx_new].osversion = entry->osversion;
675 	  if (entry->hwcaps == NULL)
676 	    file_entries_new->libs[idx_new].hwcap = entry->hwcap;
677 	  else
678 	    file_entries_new->libs[idx_new].hwcap
679 	      = compute_hwcap_value (entry);
680 	  file_entries_new->libs[idx_new].key
681 	    = str_offset + entry->lib->offset;
682 	  file_entries_new->libs[idx_new].value
683 	    = str_offset + entry->path->offset;
684 	}
685 
686       /* Ignore entries with hwcap for old format.  */
687       if (entry->hwcap == 0)
688 	++idx_old;
689     }
690 
691   /* Duplicate last old cache entry if needed.  */
692   if (opt_format != opt_format_new
693       && idx_old < cache_entry_old_count)
694     file_entries->libs[idx_old] = file_entries->libs[idx_old - 1];
695 
696   /* Compute the location of the extension directory.  This
697      implementation puts the directory after the string table.  The
698      size computation matches the write calls below.  The extension
699      directory does not exist with format 0, so the value does not
700      matter.  */
701   uint32_t extension_offset = 0;
702   if (opt_format != opt_format_new)
703     extension_offset += file_entries_size;
704   if (opt_format != opt_format_old)
705     {
706       if (opt_format != opt_format_new)
707 	extension_offset += pad;
708       extension_offset += file_entries_new_size;
709     }
710   extension_offset += strings_finalized.size;
711   extension_offset = roundup (extension_offset, 4); /* Provide alignment.  */
712   if (opt_format != opt_format_old)
713     file_entries_new->extension_offset = extension_offset;
714 
715   /* Write out the cache.  */
716 
717   /* Write cache first to a temporary file and rename it later.  */
718   char *temp_name = xmalloc (strlen (cache_name) + 2);
719   sprintf (temp_name, "%s~", cache_name);
720 
721   /* Create file.  */
722   int fd = open (temp_name, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW,
723 		 S_IRUSR|S_IWUSR);
724   if (fd < 0)
725     error (EXIT_FAILURE, errno, _("Can't create temporary cache file %s"),
726 	   temp_name);
727 
728   /* Write contents.  */
729   if (opt_format != opt_format_new)
730     {
731       if (write (fd, file_entries, file_entries_size)
732 	  != (ssize_t) file_entries_size)
733 	error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
734     }
735   if (opt_format != opt_format_old)
736     {
737       /* Align cache.  */
738       if (opt_format != opt_format_new)
739 	{
740 	  char zero[pad];
741 	  memset (zero, '\0', pad);
742 	  if (write (fd, zero, pad) != (ssize_t) pad)
743 	    error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
744 	}
745       if (write (fd, file_entries_new, file_entries_new_size)
746 	  != (ssize_t) file_entries_new_size)
747 	error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
748     }
749 
750   if (write (fd, strings_finalized.strings, strings_finalized.size)
751       != (ssize_t) strings_finalized.size)
752     error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
753 
754   if (opt_format != opt_format_old)
755     {
756       /* Align file position to 4.  */
757       off64_t old_offset = lseek64 (fd, extension_offset, SEEK_SET);
758       assert ((unsigned long long int) (extension_offset - old_offset) < 4);
759       write_extensions (fd, str_offset, extension_offset);
760     }
761 
762   /* Make sure user can always read cache file */
763   if (chmod (temp_name, S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR))
764     error (EXIT_FAILURE, errno,
765 	   _("Changing access rights of %s to %#o failed"), temp_name,
766 	   S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR);
767 
768   /* Make sure that data is written to disk.  */
769   if (fsync (fd) != 0 || close (fd) != 0)
770     error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
771 
772   /* Move temporary to its final location.  */
773   if (rename (temp_name, cache_name))
774     error (EXIT_FAILURE, errno, _("Renaming of %s to %s failed"), temp_name,
775 	   cache_name);
776 
777   /* Free all allocated memory.  */
778   free (file_entries_new);
779   free (file_entries);
780   free (strings_finalized.strings);
781   free (temp_name);
782 
783   while (entries)
784     {
785       entry = entries;
786       entries = entries->next;
787       free (entry);
788     }
789 }
790 
791 
792 /* Add one library to the cache.  */
793 void
add_to_cache(const char * path,const char * filename,const char * soname,int flags,unsigned int osversion,unsigned int isa_level,uint64_t hwcap,struct glibc_hwcaps_subdirectory * hwcaps)794 add_to_cache (const char *path, const char *filename, const char *soname,
795 	      int flags, unsigned int osversion,
796 	      unsigned int isa_level, uint64_t hwcap,
797 	      struct glibc_hwcaps_subdirectory *hwcaps)
798 {
799   struct cache_entry *new_entry = xmalloc (sizeof (*new_entry));
800 
801   struct stringtable_entry *path_interned;
802   {
803     char *p;
804     if (asprintf (&p, "%s/%s", path, filename) < 0)
805       error (EXIT_FAILURE, errno, _("Could not create library path"));
806     path_interned = stringtable_add (&strings, p);
807     free (p);
808   }
809 
810   new_entry->lib = stringtable_add (&strings, soname);
811   new_entry->path = path_interned;
812   new_entry->flags = flags;
813   new_entry->osversion = osversion;
814   new_entry->isa_level = isa_level;
815   new_entry->hwcap = hwcap;
816   new_entry->hwcaps = hwcaps;
817   new_entry->bits_hwcap = 0;
818 
819   if (hwcaps != NULL)
820     {
821       assert (hwcap == 0);
822       hwcaps->used = true;
823     }
824 
825   /* Count the number of bits set in the masked value.  */
826   for (size_t i = 0;
827        (~((1ULL << i) - 1) & hwcap) != 0 && i < 8 * sizeof (hwcap); ++i)
828     if ((hwcap & (1ULL << i)) != 0)
829       ++new_entry->bits_hwcap;
830 
831 
832   /* Keep the list sorted - search for right place to insert.  */
833   struct cache_entry *ptr = entries;
834   struct cache_entry *prev = entries;
835   while (ptr != NULL)
836     {
837       if (compare (ptr, new_entry) > 0)
838 	break;
839       prev = ptr;
840       ptr = ptr->next;
841     }
842   /* Is this the first entry?  */
843   if (ptr == entries)
844     {
845       new_entry->next = entries;
846       entries = new_entry;
847     }
848   else
849     {
850       new_entry->next = prev->next;
851       prev->next = new_entry;
852     }
853 }
854 
855 
856 /* Auxiliary cache.  */
857 
858 struct aux_cache_entry_id
859 {
860   uint64_t ino;
861   uint64_t ctime;
862   uint64_t size;
863   uint64_t dev;
864 };
865 
866 struct aux_cache_entry
867 {
868   struct aux_cache_entry_id id;
869   int flags;
870   unsigned int osversion;
871   unsigned int isa_level;
872   int used;
873   char *soname;
874   struct aux_cache_entry *next;
875 };
876 
877 #define AUX_CACHEMAGIC		"glibc-ld.so.auxcache-1.0"
878 
879 struct aux_cache_file_entry
880 {
881   struct aux_cache_entry_id id;	/* Unique id of entry.  */
882   int32_t flags;		/* This is 1 for an ELF library.  */
883   uint32_t soname;		/* String table indice.  */
884   uint32_t osversion;		/* Required OS version.	 */
885   uint32_t isa_level;		/* Required ISA level.	 */
886 };
887 
888 /* ldconfig maintains an auxiliary cache file that allows
889    only reading those libraries that have changed since the last iteration.
890    For this for each library some information is cached in the auxiliary
891    cache.  */
892 struct aux_cache_file
893 {
894   char magic[sizeof AUX_CACHEMAGIC - 1];
895   uint32_t nlibs;		/* Number of entries.  */
896   uint32_t len_strings;		/* Size of string table. */
897   struct aux_cache_file_entry libs[0]; /* Entries describing libraries.  */
898   /* After this the string table of size len_strings is found.	*/
899 };
900 
901 static const unsigned int primes[] =
902 {
903   1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071, 262139,
904   524287, 1048573, 2097143, 4194301, 8388593, 16777213, 33554393,
905   67108859, 134217689, 268435399, 536870909, 1073741789, 2147483647
906 };
907 
908 static size_t aux_hash_size;
909 static struct aux_cache_entry **aux_hash;
910 
911 /* Simplistic hash function for aux_cache_entry_id.  */
912 static unsigned int
aux_cache_entry_id_hash(struct aux_cache_entry_id * id)913 aux_cache_entry_id_hash (struct aux_cache_entry_id *id)
914 {
915   uint64_t ret = ((id->ino * 11 + id->ctime) * 11 + id->size) * 11 + id->dev;
916   return ret ^ (ret >> 32);
917 }
918 
nextprime(size_t x)919 static size_t nextprime (size_t x)
920 {
921   for (unsigned int i = 0; i < sizeof (primes) / sizeof (primes[0]); ++i)
922     if (primes[i] >= x)
923       return primes[i];
924   return x;
925 }
926 
927 void
init_aux_cache(void)928 init_aux_cache (void)
929 {
930   aux_hash_size = primes[3];
931   aux_hash = xcalloc (aux_hash_size, sizeof (struct aux_cache_entry *));
932 }
933 
934 int
search_aux_cache(struct stat64 * stat_buf,int * flags,unsigned int * osversion,unsigned int * isa_level,char ** soname)935 search_aux_cache (struct stat64 *stat_buf, int *flags,
936 		  unsigned int *osversion, unsigned int *isa_level,
937 		  char **soname)
938 {
939   struct aux_cache_entry_id id;
940   id.ino = (uint64_t) stat_buf->st_ino;
941   id.ctime = (uint64_t) stat_buf->st_ctime;
942   id.size = (uint64_t) stat_buf->st_size;
943   id.dev = (uint64_t) stat_buf->st_dev;
944 
945   unsigned int hash = aux_cache_entry_id_hash (&id);
946   struct aux_cache_entry *entry;
947   for (entry = aux_hash[hash % aux_hash_size]; entry; entry = entry->next)
948     if (id.ino == entry->id.ino
949 	&& id.ctime == entry->id.ctime
950 	&& id.size == entry->id.size
951 	&& id.dev == entry->id.dev)
952       {
953 	*flags = entry->flags;
954 	*osversion = entry->osversion;
955 	*isa_level = entry->isa_level;
956 	if (entry->soname != NULL)
957 	  *soname = xstrdup (entry->soname);
958 	else
959 	  *soname = NULL;
960 	entry->used = 1;
961 	return 1;
962       }
963 
964   return 0;
965 }
966 
967 static void
insert_to_aux_cache(struct aux_cache_entry_id * id,int flags,unsigned int osversion,unsigned int isa_level,const char * soname,int used)968 insert_to_aux_cache (struct aux_cache_entry_id *id, int flags,
969 		     unsigned int osversion, unsigned int isa_level,
970 		     const char *soname, int used)
971 {
972   size_t hash = aux_cache_entry_id_hash (id) % aux_hash_size;
973   struct aux_cache_entry *entry;
974   for (entry = aux_hash[hash]; entry; entry = entry->next)
975     if (id->ino == entry->id.ino
976 	&& id->ctime == entry->id.ctime
977 	&& id->size == entry->id.size
978 	&& id->dev == entry->id.dev)
979       abort ();
980 
981   size_t len = soname ? strlen (soname) + 1 : 0;
982   entry = xmalloc (sizeof (struct aux_cache_entry) + len);
983   entry->id = *id;
984   entry->flags = flags;
985   entry->osversion = osversion;
986   entry->isa_level = isa_level;
987   entry->used = used;
988   if (soname != NULL)
989     entry->soname = memcpy ((char *) (entry + 1), soname, len);
990   else
991     entry->soname = NULL;
992   entry->next = aux_hash[hash];
993   aux_hash[hash] = entry;
994 }
995 
996 void
add_to_aux_cache(struct stat64 * stat_buf,int flags,unsigned int osversion,unsigned int isa_level,const char * soname)997 add_to_aux_cache (struct stat64 *stat_buf, int flags,
998 		  unsigned int osversion, unsigned int isa_level,
999 		  const char *soname)
1000 {
1001   struct aux_cache_entry_id id;
1002   id.ino = (uint64_t) stat_buf->st_ino;
1003   id.ctime = (uint64_t) stat_buf->st_ctime;
1004   id.size = (uint64_t) stat_buf->st_size;
1005   id.dev = (uint64_t) stat_buf->st_dev;
1006   insert_to_aux_cache (&id, flags, osversion, isa_level, soname, 1);
1007 }
1008 
1009 /* Load auxiliary cache to search for unchanged entries.   */
1010 void
load_aux_cache(const char * aux_cache_name)1011 load_aux_cache (const char *aux_cache_name)
1012 {
1013   int fd = open (aux_cache_name, O_RDONLY);
1014   if (fd < 0)
1015     {
1016       init_aux_cache ();
1017       return;
1018     }
1019 
1020   struct stat64 st;
1021   if (__fstat64 (fd, &st) < 0 || st.st_size < sizeof (struct aux_cache_file))
1022     {
1023       close (fd);
1024       init_aux_cache ();
1025       return;
1026     }
1027 
1028   size_t aux_cache_size = st.st_size;
1029   struct aux_cache_file *aux_cache
1030     = mmap (NULL, aux_cache_size, PROT_READ, MAP_PRIVATE, fd, 0);
1031   if (aux_cache == MAP_FAILED
1032       || aux_cache_size < sizeof (struct aux_cache_file)
1033       || memcmp (aux_cache->magic, AUX_CACHEMAGIC, sizeof AUX_CACHEMAGIC - 1)
1034       || aux_cache_size != (sizeof (struct aux_cache_file)
1035 			    + aux_cache->nlibs * sizeof (struct aux_cache_file_entry)
1036 			    + aux_cache->len_strings))
1037     {
1038       if (aux_cache != MAP_FAILED)
1039 	munmap (aux_cache, aux_cache_size);
1040 
1041       close (fd);
1042       init_aux_cache ();
1043       return;
1044     }
1045 
1046   aux_hash_size = nextprime (aux_cache->nlibs);
1047   aux_hash = xcalloc (aux_hash_size, sizeof (struct aux_cache_entry *));
1048 
1049   const char *aux_cache_data
1050     = (const char *) &aux_cache->libs[aux_cache->nlibs];
1051   for (unsigned int i = 0; i < aux_cache->nlibs; ++i)
1052     insert_to_aux_cache (&aux_cache->libs[i].id,
1053 			 aux_cache->libs[i].flags,
1054 			 aux_cache->libs[i].osversion,
1055 			 aux_cache->libs[i].isa_level,
1056 			 aux_cache->libs[i].soname == 0
1057 			 ? NULL : aux_cache_data + aux_cache->libs[i].soname,
1058 			 0);
1059 
1060   munmap (aux_cache, aux_cache_size);
1061   close (fd);
1062 }
1063 
1064 /* Save the contents of the auxiliary cache.  */
1065 void
save_aux_cache(const char * aux_cache_name)1066 save_aux_cache (const char *aux_cache_name)
1067 {
1068   /* Count the length of all sonames.  We start with empty string.  */
1069   size_t total_strlen = 1;
1070   /* Number of cache entries.  */
1071   int cache_entry_count = 0;
1072 
1073   for (size_t i = 0; i < aux_hash_size; ++i)
1074     for (struct aux_cache_entry *entry = aux_hash[i];
1075 	 entry != NULL; entry = entry->next)
1076       if (entry->used)
1077 	{
1078 	  ++cache_entry_count;
1079 	  if (entry->soname != NULL)
1080 	    total_strlen += strlen (entry->soname) + 1;
1081 	}
1082 
1083   /* Auxiliary cache.  */
1084   size_t file_entries_size
1085     = sizeof (struct aux_cache_file)
1086       + cache_entry_count * sizeof (struct aux_cache_file_entry);
1087   struct aux_cache_file *file_entries
1088     = xmalloc (file_entries_size + total_strlen);
1089 
1090   /* Fill in the header of the auxiliary cache.  */
1091   memset (file_entries, '\0', sizeof (struct aux_cache_file));
1092   memcpy (file_entries->magic, AUX_CACHEMAGIC, sizeof AUX_CACHEMAGIC - 1);
1093 
1094   file_entries->nlibs = cache_entry_count;
1095   file_entries->len_strings = total_strlen;
1096 
1097   /* Initial String offset for auxiliary cache is always after the
1098      special empty string.  */
1099   unsigned int str_offset = 1;
1100 
1101   /* An array for all strings.  */
1102   char *str = (char *) file_entries + file_entries_size;
1103   *str++ = '\0';
1104 
1105   size_t idx = 0;
1106   for (size_t i = 0; i < aux_hash_size; ++i)
1107     for (struct aux_cache_entry *entry = aux_hash[i];
1108 	 entry != NULL; entry = entry->next)
1109       if (entry->used)
1110 	{
1111 	  file_entries->libs[idx].id = entry->id;
1112 	  file_entries->libs[idx].flags = entry->flags;
1113 	  if (entry->soname == NULL)
1114 	    file_entries->libs[idx].soname = 0;
1115 	  else
1116 	    {
1117 	      file_entries->libs[idx].soname = str_offset;
1118 
1119 	      size_t len = strlen (entry->soname) + 1;
1120 	      str = mempcpy (str, entry->soname, len);
1121 	      str_offset += len;
1122 	    }
1123 	  file_entries->libs[idx].osversion = entry->osversion;
1124 	  file_entries->libs[idx++].isa_level = entry->isa_level;
1125 	}
1126 
1127   /* Write out auxiliary cache file.  */
1128   /* Write auxiliary cache first to a temporary file and rename it later.  */
1129 
1130   char *temp_name = xmalloc (strlen (aux_cache_name) + 2);
1131   sprintf (temp_name, "%s~", aux_cache_name);
1132 
1133   /* Check that directory exists and create if needed.  */
1134   char *dir = strdupa (aux_cache_name);
1135   dir = dirname (dir);
1136 
1137   struct stat64 st;
1138   if (stat64 (dir, &st) < 0)
1139     {
1140       if (mkdir (dir, 0700) < 0)
1141 	goto out_fail;
1142     }
1143 
1144   /* Create file.  */
1145   int fd = open (temp_name, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW,
1146 		 S_IRUSR|S_IWUSR);
1147   if (fd < 0)
1148     goto out_fail;
1149 
1150   bool fail = ((write (fd, file_entries, file_entries_size + total_strlen)
1151 		!= (ssize_t) (file_entries_size + total_strlen))
1152 	       || fdatasync (fd) != 0);
1153 
1154   fail |= close (fd) != 0;
1155 
1156   if (fail)
1157     {
1158       unlink (temp_name);
1159       goto out_fail;
1160     }
1161 
1162   /* Move temporary to its final location.  */
1163   if (rename (temp_name, aux_cache_name))
1164     unlink (temp_name);
1165 
1166 out_fail:
1167   /* Free allocated memory.  */
1168   free (temp_name);
1169   free (file_entries);
1170 }
1171