diff options
Diffstat (limited to 'elf')
-rw-r--r-- | elf/dl-load.c | 42 | ||||
-rw-r--r-- | elf/dl-lookup.c | 19 | ||||
-rw-r--r-- | elf/dl-reloc.c | 4 | ||||
-rw-r--r-- | elf/dl-runtime.c | 4 | ||||
-rw-r--r-- | elf/dl-symbol.c | 2 | ||||
-rw-r--r-- | elf/dlsym.c | 2 | ||||
-rw-r--r-- | elf/link.h | 14 | ||||
-rw-r--r-- | elf/rtld.c | 4 |
8 files changed, 58 insertions, 33 deletions
diff --git a/elf/dl-load.c b/elf/dl-load.c index 8ccc838..6fd6a6c 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -70,11 +70,25 @@ int _dl_zerofd = -1; size_t _dl_pagesize; +/* Local version of `strdup' function. */ +static inline char * +local_strdup (const char *s) +{ + size_t len = strlen (s) + 1; + void *new = malloc (len); + + if (new == NULL) + return NULL; + + return (char *) memcpy (new, s, len); +} + + /* Map in the shared object NAME, actually located in REALNAME, and already opened on FD. */ struct link_map * -_dl_map_object_from_fd (const char *name, int fd, char *realname, +_dl_map_object_from_fd (char *name, int fd, char *realname, struct link_map *loader, int l_type) { struct link_map *l = NULL; @@ -96,6 +110,7 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname, l->l_next->l_prev = l->l_prev; free (l); } + free (name); free (realname); _dl_signal_error (code, name, msg); } @@ -142,6 +157,7 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname, /* The object is already loaded. Just bump its reference count and return it. */ __close (fd); + free (name); free (realname); ++l->l_opencount; return l; @@ -524,11 +540,8 @@ _dl_map_object (struct link_map *loader, const char *name, int type) fd = __open (cached, O_RDONLY); if (fd != -1) { - size_t cl = strlen (cached) + 1; - realname = malloc (cl); - if (realname) - memcpy (realname, cached, cl); - else + realname = local_strdup (cached); + if (realname == NULL) { __close (fd); fd = -1; @@ -548,11 +561,8 @@ _dl_map_object (struct link_map *loader, const char *name, int type) fd = __open (name, O_RDONLY); if (fd != -1) { - size_t len = strlen (name) + 1; - realname = malloc (len); - if (realname) - memcpy (realname, name, len); - else + realname = local_strdup (name); + if (realname == NULL) { __close (fd); fd = -1; @@ -560,6 +570,16 @@ _dl_map_object (struct link_map *loader, const char *name, int type) } } + if (fd != -1) + { + name = local_strdup (name); + if (name == NULL) + { + __close (fd); + fd = -1; + } + } + if (fd == -1) _dl_signal_error (errno, name, "cannot open shared object file"); diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c index 44f91fc..e57887b 100644 --- a/elf/dl-lookup.c +++ b/elf/dl-lookup.c @@ -45,16 +45,16 @@ _dl_elf_hash (const char *name) } /* Search loaded objects' symbol tables for a definition of the symbol - UNDEF_NAME. The chosen value can't be RELOC_ADDR. If NOPLT is nonzero, - then a PLT entry cannot satisfy the reference; some different binding - must be found. */ + UNDEF_NAME. FLAGS is a set of flags. If DL_LOOKUP_NOEXEC is set, + then don't search the executable for a definition; this used for + copy relocs. If DL_LOOKUP_NOPLT is set, then a PLT entry cannot + satisfy the reference; some different binding must be found. */ ElfW(Addr) _dl_lookup_symbol (const char *undef_name, const ElfW(Sym) **ref, struct link_map *symbol_scope[], const char *reference_name, - ElfW(Addr) reloc_addr, - int noplt) + int flags) { const unsigned long int hash = _dl_elf_hash (undef_name); struct @@ -75,6 +75,10 @@ _dl_lookup_symbol (const char *undef_name, const ElfW(Sym) **ref, map = (*scope)->l_searchlist[i]; + /* Don't search the executable when resolving a copy reloc. */ + if (flags & DL_LOOKUP_NOEXEC && map->l_type == lt_executable) + continue; + symtab = ((void *) map->l_addr + map->l_info[DT_SYMTAB]->d_un.d_ptr); strtab = ((void *) map->l_addr + map->l_info[DT_STRTAB]->d_un.d_ptr); @@ -87,9 +91,8 @@ _dl_lookup_symbol (const char *undef_name, const ElfW(Sym) **ref, const ElfW(Sym) *sym = &symtab[symidx]; if (sym->st_value == 0 || /* No value. */ - /* Cannot resolve to the location being filled in. */ - reloc_addr == map->l_addr + sym->st_value || - (noplt && sym->st_shndx == SHN_UNDEF)) /* Reject PLT. */ + ((flags & DL_LOOKUP_NOPLT) != 0 /* Reject PLT entry. */ + && sym->st_shndx == SHN_UNDEF)) continue; switch (ELFW(ST_TYPE) (sym->st_info)) diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c index 5adf0f6..fa424a4 100644 --- a/elf/dl-reloc.c +++ b/elf/dl-reloc.c @@ -57,9 +57,9 @@ _dl_relocate_object (struct link_map *l, struct link_map *scope[], int lazy) = ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr); /* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */ -#define RESOLVE(ref, reloc_addr, noplt) \ +#define RESOLVE(ref, flags) \ (_dl_lookup_symbol (strtab + (*ref)->st_name, ref, scope, \ - l->l_name, reloc_addr, noplt)) + l->l_name, flags)) #include "dynamic-link.h" ELF_DYNAMIC_RELOCATE (l, lazy); diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c index 16e0379..4e7b529 100644 --- a/elf/dl-runtime.c +++ b/elf/dl-runtime.c @@ -122,9 +122,9 @@ fixup ( { /* This macro is used as a callback from the elf_machine_relplt code. */ -#define RESOLVE(ref, reloc_addr, noplt) \ +#define RESOLVE(ref, flags) \ (_dl_lookup_symbol (strtab + (*ref)->st_name, ref, scope, \ - l->l_name, reloc_addr, noplt)) + l->l_name, flags)) #include "dynamic-link.h" /* Perform the specified relocation. */ diff --git a/elf/dl-symbol.c b/elf/dl-symbol.c index 7977e69..04dd122 100644 --- a/elf/dl-symbol.c +++ b/elf/dl-symbol.c @@ -28,6 +28,6 @@ _dl_symbol_value (struct link_map *map, const char *name) ElfW(Addr) loadbase; const ElfW(Sym) *ref = NULL; struct link_map *scope[2] = { map, NULL }; - loadbase = _dl_lookup_symbol (name, &ref, scope, map->l_name, 0, 0); + loadbase = _dl_lookup_symbol (name, &ref, scope, map->l_name, 0); return loadbase + ref->st_value; } diff --git a/elf/dlsym.c b/elf/dlsym.c index 256eba8..98e3629 100644 --- a/elf/dlsym.c +++ b/elf/dlsym.c @@ -44,7 +44,7 @@ dlsym (void *handle, const char *name) scope = &(_dl_global_scope ?: _dl_default_scope)[2]; owner = NULL; } - loadbase = _dl_lookup_symbol (name, &ref, scope, owner, 0, 0); + loadbase = _dl_lookup_symbol (name, &ref, scope, owner, 0); } return _dlerror_run (doit) ? NULL : (void *) (loadbase + ref->st_value); @@ -224,16 +224,18 @@ extern void _dl_close (struct link_map *map); null-terminated list of object scopes to search; each object's l_searchlist (i.e. the segment of the dependency tree starting at that object) is searched in turn. REFERENCE_NAME should name the object - containing the reference; it is used in error messages. RELOC_ADDR is - the address being fixed up and the chosen symbol cannot be one with this - value. If NOPLT is nonzero, then the reference must not be resolved to - a PLT entry. */ + containing the reference; it is used in error messages. FLAGS is a + set of flags: */ +#define DL_LOOKUP_NOEXEC 1 /* Don't search the executable for a + definition; this is used for copy + relocs. */ +#define DL_LOOKUP_NOPLT 2 /* The reference must not be resolved + to a PLT entry. */ extern ElfW(Addr) _dl_lookup_symbol (const char *undef, const ElfW(Sym) **sym, struct link_map *symbol_scope[], const char *reference_name, - ElfW(Addr) reloc_addr, - int noplt); + int flags); /* Look up symbol NAME in MAP's scope and return its run-time address. */ extern ElfW(Addr) _dl_symbol_value (struct link_map *map, const char *name); @@ -62,7 +62,7 @@ _dl_start (void *arg) /* This #define produces dynamic linking inline functions for bootstrap relocation instead of general-purpose relocation. */ #define RTLD_BOOTSTRAP -#define RESOLVE(sym, reloc_addr, noplt) bootstrap_map.l_addr +#define RESOLVE(sym, flags) bootstrap_map.l_addr #include "dynamic-link.h" /* Figure out the run-time load address of the dynamic linker itself. */ @@ -369,7 +369,7 @@ of this helper program; chances are you did not intend to run this program.\n", const ElfW(Sym) *ref = NULL; ElfW(Addr) loadbase = _dl_lookup_symbol (_dl_argv[i], &ref, &_dl_default_scope[2], - "argument", 0, 0); + "argument", 0); char buf[20], *bp; buf[sizeof buf - 1] = '\0'; bp = _itoa (ref->st_value, &buf[sizeof buf - 1], 16, 0); |