projects/guix·blob python-team · refs

141 lines · 4.9 KiB

1Read the shared library cache relative to $ORIGIN instead of reading
2from /etc/ld.so.cache. Also arrange so that this cache takes
3precedence over RUNPATH.
4
5diff --git a/elf/dl-cache.c b/elf/dl-cache.c
6index 93d185e788..e0760a1f40 100644
7--- a/elf/dl-cache.c
8+++ b/elf/dl-cache.c
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:
80diff --git a/elf/dl-load.c b/elf/dl-load.c
81index f3201e7c14..a69aec3428 100644
82--- a/elf/dl-load.c
83+++ b/elf/dl-load.c
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