| 1 | Read the shared library cache relative to $ORIGIN instead of reading
|
| 2 | from /etc/ld.so.cache. Also arrange so that this cache takes
|
| 3 | precedence over RUNPATH.
|
| 4 |
|
| 5 | diff --git a/elf/dl-cache.c b/elf/dl-cache.c
|
| 6 | index 93d185e788..e0760a1f40 100644
|
| 7 | |
| 8 | |
| 9 | @@ -171,6 +171,52 @@ _dl_cache_libcmp (const char *p1, const char *p2)
|
| 10 | return *p1 - *p2;
|
| 11 | }
|
| 12 |
|
| 13 | +/* Special value representing the lack of an ld.so cache. */
|
| 14 | +static const char ld_so_cache_lacking[] = "/ld.so cache is lacking";
|
| 15 | +
|
| 16 | +/* Return the per-application ld.so cache, relative to $ORIGIN, or NULL if
|
| 17 | + that fails for some reason. Do not return the system-wide LD_SO_CACHE
|
| 18 | + since on a foreign distro it would contain invalid information. */
|
| 19 | +static const char *
|
| 20 | +ld_so_cache (void)
|
| 21 | +{
|
| 22 | + static const char *loader_cache;
|
| 23 | +
|
| 24 | + if (loader_cache == NULL)
|
| 25 | + {
|
| 26 | + static const char store[] = @STORE_DIRECTORY@;
|
| 27 | + const char *origin = _dl_get_origin ();
|
| 28 | +
|
| 29 | + /* Check whether ORIGIN is something like "/gnu/store/…-foo/bin". */
|
| 30 | + if (origin != (char *) -1 /* _dl_get_origin reported failure */
|
| 31 | + && strncmp (store, origin, strlen (store)) == 0
|
| 32 | + && origin[sizeof store - 1] == '/')
|
| 33 | + {
|
| 34 | + char *store_item_end = strchr (origin + sizeof store, '/');
|
| 35 | +
|
| 36 | + if (store_item_end != NULL)
|
| 37 | + {
|
| 38 | + static const char suffix[] = "/etc/ld.so.cache";
|
| 39 | + size_t store_item_len = store_item_end - origin;
|
| 40 | +
|
| 41 | + /* Note: We can't use 'malloc' because it can be interposed.
|
| 42 | + Likewise, 'strncpy' is not available. */
|
| 43 | + char *cache = alloca (strlen (origin) + sizeof suffix);
|
| 44 | +
|
| 45 | + strcpy (cache, origin);
|
| 46 | + strcpy (cache + store_item_len, suffix);
|
| 47 | +
|
| 48 | + loader_cache = __strdup (cache) ?: ld_so_cache_lacking;
|
| 49 | + }
|
| 50 | + else
|
| 51 | + loader_cache = ld_so_cache_lacking;
|
| 52 | + }
|
| 53 | + else
|
| 54 | + loader_cache = ld_so_cache_lacking;
|
| 55 | + }
|
| 56 | +
|
| 57 | + return loader_cache;
|
| 58 | +}
|
| 59 |
|
| 60 | /* Look up NAME in ld.so.cache and return the file name stored there, or null
|
| 61 | if none is found. The cache is loaded if it was not already. If loading
|
| 62 | @@ -190,12 +235,15 @@ _dl_load_cache_lookup (const char *name)
|
| 63 |
|
| 64 | /* Print a message if the loading of libs is traced. */
|
| 65 | if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS))
|
| 66 | - _dl_debug_printf (" search cache=%s\n", LD_SO_CACHE);
|
| 67 | + _dl_debug_printf (" search cache=%s\n", ld_so_cache ());
|
| 68 | +
|
| 69 | + if (__glibc_unlikely (ld_so_cache () == ld_so_cache_lacking))
|
| 70 | + return NULL;
|
| 71 |
|
| 72 | if (cache == NULL)
|
| 73 | {
|
| 74 | /* Read the contents of the file. */
|
| 75 | - void *file = _dl_sysdep_read_whole_file (LD_SO_CACHE, &cachesize,
|
| 76 | + void *file = _dl_sysdep_read_whole_file (ld_so_cache (), &cachesize,
|
| 77 | PROT_READ);
|
| 78 |
|
| 79 | /* We can handle three different cache file formats here:
|
| 80 | diff --git a/elf/dl-load.c b/elf/dl-load.c
|
| 81 | index f3201e7c14..a69aec3428 100644
|
| 82 | |
| 83 | |
| 84 | @@ -2152,28 +2152,6 @@ _dl_map_object (struct link_map *loader, const char *name,
|
| 85 | loader ?: GL(dl_ns)[LM_ID_BASE]._ns_loaded,
|
| 86 | LA_SER_LIBPATH, &found_other_class);
|
| 87 |
|
| 88 | - /* Look at the RUNPATH information for this binary. */
|
| 89 | - if (fd == -1 && loader != NULL
|
| 90 | - && cache_rpath (loader, &loader->l_runpath_dirs,
|
| 91 | - DT_RUNPATH, "RUNPATH"))
|
| 92 | - fd = open_path (name, namelen, mode,
|
| 93 | - &loader->l_runpath_dirs, &realname, &fb, loader,
|
| 94 | - LA_SER_RUNPATH, &found_other_class);
|
| 95 | -
|
| 96 | - if (fd == -1)
|
| 97 | - {
|
| 98 | - realname = _dl_sysdep_open_object (name, namelen, &fd);
|
| 99 | - if (realname != NULL)
|
| 100 | - {
|
| 101 | - fd = open_verify (realname, fd,
|
| 102 | - &fb, loader ?: GL(dl_ns)[nsid]._ns_loaded,
|
| 103 | - LA_SER_CONFIG, mode, &found_other_class,
|
| 104 | - false);
|
| 105 | - if (fd == -1)
|
| 106 | - free (realname);
|
| 107 | - }
|
| 108 | - }
|
| 109 | -
|
| 110 | #ifdef USE_LDCONFIG
|
| 111 | if (fd == -1
|
| 112 | && (__glibc_likely ((mode & __RTLD_SECURE) == 0)
|
| 113 | @@ -2232,6 +2210,28 @@ _dl_map_object (struct link_map *loader, const char *name,
|
| 114 | }
|
| 115 | #endif
|
| 116 |
|
| 117 | + /* Look at the RUNPATH information for this binary. */
|
| 118 | + if (fd == -1 && loader != NULL
|
| 119 | + && cache_rpath (loader, &loader->l_runpath_dirs,
|
| 120 | + DT_RUNPATH, "RUNPATH"))
|
| 121 | + fd = open_path (name, namelen, mode,
|
| 122 | + &loader->l_runpath_dirs, &realname, &fb, loader,
|
| 123 | + LA_SER_RUNPATH, &found_other_class);
|
| 124 | +
|
| 125 | + if (fd == -1)
|
| 126 | + {
|
| 127 | + realname = _dl_sysdep_open_object (name, namelen, &fd);
|
| 128 | + if (realname != NULL)
|
| 129 | + {
|
| 130 | + fd = open_verify (realname, fd,
|
| 131 | + &fb, loader ?: GL(dl_ns)[nsid]._ns_loaded,
|
| 132 | + LA_SER_CONFIG, mode, &found_other_class,
|
| 133 | + false);
|
| 134 | + if (fd == -1)
|
| 135 | + free (realname);
|
| 136 | + }
|
| 137 | + }
|
| 138 | +
|
| 139 | /* Finally, try the default path. */
|
| 140 | if (fd == -1
|
| 141 | && ((l = loader ?: GL(dl_ns)[nsid]._ns_loaded) == NULL
|