diff mbox series

[v2,07/32] elf: Disambiguate some failures in _dl_load_cache_lookup

Message ID fdb8756d7c233510d77038d84a38b65107d1246c.1688741159.git.fweimer@redhat.com
State New
Headers show
Series RELRO link maps | expand

Commit Message

Florian Weimer July 7, 2023, 6:48 p.m. UTC
Failure to allocate a copy of the string is now distinct from
a cache lookup failure.  Some infrastructure failures in
_dl_sysdep_read_whole_file are still treated as cache lookup
failures, though.
---
 elf/dl-cache.c             | 22 ++++++++++++++++------
 elf/dl-load.c              |  5 ++++-
 sysdeps/generic/ldsodefs.h | 10 +++++++---
 3 files changed, 27 insertions(+), 10 deletions(-)
diff mbox series

Patch

diff --git a/elf/dl-cache.c b/elf/dl-cache.c
index 804bf23222..a3eb960dac 100644
--- a/elf/dl-cache.c
+++ b/elf/dl-cache.c
@@ -398,8 +398,8 @@  _dl_cache_libcmp (const char *p1, const char *p2)
    may be unmapped at any time by a completing recursive dlopen and
    this function must take care that it does not return references to
    any data in the mapping.  */
-char *
-_dl_load_cache_lookup (const char *name)
+bool
+_dl_load_cache_lookup (const char *name, char **realname)
 {
   /* Print a message if the loading of libs is traced.  */
   if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS))
@@ -475,8 +475,11 @@  _dl_load_cache_lookup (const char *name)
     }
 
   if (cache == (void *) -1)
-    /* Previously looked for the cache file and didn't find it.  */
-    return NULL;
+    {
+      /* Previously looked for the cache file and didn't find it.  */
+      *realname = NULL;
+      return true;
+    }
 
   const char *best;
   if (cache_new != (void *) -1)
@@ -502,7 +505,10 @@  _dl_load_cache_lookup (const char *name)
     _dl_debug_printf ("  trying file=%s\n", best);
 
   if (best == NULL)
-    return NULL;
+    {
+      *realname = NULL;
+      return true;
+    }
 
   /* The double copy is *required* since malloc may be interposed
      and call dlopen itself whose completion would unmap the data
@@ -512,7 +518,11 @@  _dl_load_cache_lookup (const char *name)
   size_t best_len = strlen (best) + 1;
   temp = alloca (best_len);
   memcpy (temp, best, best_len);
-  return __strdup (temp);
+  char *copy = __strdup (temp);
+  if (copy == NULL)
+    return false;
+  *realname = copy;
+  return true;
 }
 
 #ifndef MAP_COPY
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 9a9cee599d..ff721fe5d2 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -2079,7 +2079,10 @@  _dl_map_object (struct link_map *loader, const char *name,
 	{
 	  /* Check the list of libraries in the file /etc/ld.so.cache,
 	     for compatibility with Linux's ldconfig program.  */
-	  char *cached = _dl_load_cache_lookup (name);
+	  char *cached;
+	  if (!_dl_load_cache_lookup (name, &cached))
+	    _dl_signal_error (ENOMEM, NULL, NULL,
+			      N_("cannot allocate library name"));
 
 	  if (cached != NULL)
 	    {
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 8b7e603c87..5941da3ec1 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1111,9 +1111,13 @@  const struct r_strlenpair *_dl_important_hwcaps (const char *prepend,
 						 size_t *max_capstrlen)
   attribute_hidden;
 
-/* Look up NAME in ld.so.cache and return the file name stored there,
-   or null if none is found.  Caller must free returned string.  */
-extern char *_dl_load_cache_lookup (const char *name) attribute_hidden;
+/* Look up NAME in ld.so.cache.  Return false on memory allocation
+   failure and do not change *REALNAME.  If lookup fails, return true
+   and write a null pointer to *REALNAME.  If lookup suceeds, write a
+   copy of the full name to *REALNAME (which has to be freed by the
+   caller).  */
+bool _dl_load_cache_lookup (const char *name, char **realname)
+  attribute_hidden __nonnull ((1, 2)) __attribute__ ((warn_unused_result));
 
 /* If the system does not support MAP_COPY we cannot leave the file open
    all the time since this would create problems when the file is replaced.