summaryrefslogtreecommitdiff
path: root/elf/rtld.c
diff options
context:
space:
mode:
Diffstat (limited to 'elf/rtld.c')
-rw-r--r--elf/rtld.c47
1 files changed, 45 insertions, 2 deletions
diff --git a/elf/rtld.c b/elf/rtld.c
index 6baa7a868a..2e23d9cb38 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -21,6 +21,7 @@ Cambridge, MA 02139, USA. */
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
+#include <sys/mman.h> /* Check if MAP_ANON is defined. */
#include "../stdio-common/_itoa.h"
@@ -124,6 +125,8 @@ dl_main (const ElfW(Phdr) *phdr,
struct link_map *l;
int lazy;
int list_only = 0;
+ struct link_map **preloads;
+ unsigned int npreloads;
if (*user_entry == (ElfW(Addr)) &_start)
{
@@ -247,12 +250,52 @@ of this helper program; chances are you did not intend to run this program.\n",
l->l_next = &_dl_rtld_map;
_dl_rtld_map.l_prev = l;
- /* Load all the libraries specified by DT_NEEDED entries. */
- _dl_map_object_deps (l);
+ preloads = NULL;
+ npreloads = 0;
+ if (! _dl_secure)
+ {
+ const char *preloadlist = getenv ("LD_PRELOAD");
+ if (preloadlist)
+ {
+ /* The LD_PRELOAD environment variable gives a colon-separated
+ list of libraries that are loaded before the executable's
+ dependencies and prepended to the global scope list. */
+ char *list = strdupa (preloadlist);
+ char *p;
+ while ((p = strsep (&list, ":")) != NULL)
+ {
+ (void) _dl_map_object (NULL, p, lt_library);
+ ++npreloads;
+ }
+
+ if (npreloads != 0)
+ {
+ /* Set up PRELOADS with a vector of the preloaded libraries. */
+ struct link_map *l;
+ unsigned int i;
+ preloads = __alloca (npreloads * sizeof preloads[0]);
+ l = _dl_rtld_map.l_next; /* End of the chain before preloads. */
+ i = 0;
+ do
+ {
+ preloads[i++] = l;
+ l = l->l_next;
+ } while (l);
+ assert (i == npreloads);
+ }
+ }
+ }
+
+ /* Load all the libraries specified by DT_NEEDED entries. If LD_PRELOAD
+ specified some libraries to load, these are inserted before the actual
+ dependencies in the executable's searchlist for symbol resolution. */
+ _dl_map_object_deps (l, preloads, npreloads);
+#ifndef MAP_ANON
/* We are done mapping things, so close the zero-fill descriptor. */
__close (_dl_zerofd);
_dl_zerofd = -1;
+#endif
/* Remove _dl_rtld_map from the chain. */
_dl_rtld_map.l_prev->l_next = _dl_rtld_map.l_next;