From 561774ab86f8722cd0020809251febc09cf3d99c Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 12 Jul 2007 15:34:58 +0000 Subject: 2007-06-19 Ulrich Drepper * sysdeps/generic/ldsodefs.h (rtld_global): Reorder some elements to fill in holes (rtld_global_ro): Likewise. 2007-06-18 Jakub Jelinek * elf/dl-addr.c (_dl_addr): Skip PT_LOAD checking if l_contiguous. Move PT_LOAD checking to... (_dl_addr_inside_object): ... here, new function. * elf/dl-sym.c (do_sym): If not l_contiguous, call _dl_addr_inside_object. * elf/dl-iteratephdr.c (__dl_iterate_phdr): Likewise. * dlfcn/dlinfo.c (dlinfo_doit): Likewise. * elf/dl-open.c (dl_open_worker): Likewise. (_dl_addr_inside_object): New function if IS_IN_rtld. * elf/dl-load.c (_dl_map_object_from_fd): Set l_contiguous if no holes are present or are PROT_NONE protected. * include/link.h (struct link_map): Add l_contiguous field. * sysdeps/generic/ldsodefs.h (_dl_addr_inside_object): New prototype. --- ChangeLog | 22 ++++++++++++++++++++++ dlfcn/dlinfo.c | 5 ++--- elf/dl-addr.c | 36 +++++++++++++++++++++--------------- elf/dl-iteratephdr.c | 6 +++--- elf/dl-load.c | 3 +++ elf/dl-open.c | 24 +++++++++++++++++++++--- elf/dl-sym.c | 5 ++--- include/link.h | 3 +++ sysdeps/generic/ldsodefs.h | 24 +++++++++++++----------- 9 files changed, 90 insertions(+), 38 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6e635e6e95..1278a92bf4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2007-06-19 Ulrich Drepper + + * sysdeps/generic/ldsodefs.h (rtld_global): Reorder some elements + to fill in holes + (rtld_global_ro): Likewise. + +2007-06-18 Jakub Jelinek + + * elf/dl-addr.c (_dl_addr): Skip PT_LOAD checking if l_contiguous. + Move PT_LOAD checking to... + (_dl_addr_inside_object): ... here, new function. + * elf/dl-sym.c (do_sym): If not l_contiguous, + call _dl_addr_inside_object. + * elf/dl-iteratephdr.c (__dl_iterate_phdr): Likewise. + * dlfcn/dlinfo.c (dlinfo_doit): Likewise. + * elf/dl-open.c (dl_open_worker): Likewise. + (_dl_addr_inside_object): New function if IS_IN_rtld. + * elf/dl-load.c (_dl_map_object_from_fd): Set l_contiguous if no + holes are present or are PROT_NONE protected. + * include/link.h (struct link_map): Add l_contiguous field. + * sysdeps/generic/ldsodefs.h (_dl_addr_inside_object): New prototype. + 2007-06-18 Jakub Jelinek * elf/rtld.c (dl_main): Don't call init_tls more than once. diff --git a/dlfcn/dlinfo.c b/dlfcn/dlinfo.c index b1e2b009a5..e931b40b01 100644 --- a/dlfcn/dlinfo.c +++ b/dlfcn/dlinfo.c @@ -58,9 +58,8 @@ dlinfo_doit (void *argsblock) /* Find the highest-addressed object that CALLER is not below. */ for (nsid = 0; nsid < DL_NNS; ++nsid) for (l = GL(dl_ns)[nsid]._ns_loaded; l != NULL; l = l->l_next) - if (caller >= l->l_map_start && caller < l->l_map_end) - /* There must be exactly one DSO for the range of the virtual - memory. Otherwise something is really broken. */ + if (caller >= l->l_map_start && caller < l->l_map_end + && (l->l_contiguous || _dl_addr_inside_object (l, caller))) break; if (l == NULL) diff --git a/elf/dl-addr.c b/elf/dl-addr.c index 17b73be724..e8620e686f 100644 --- a/elf/dl-addr.c +++ b/elf/dl-addr.c @@ -138,22 +138,12 @@ _dl_addr (const void *address, Dl_info *info, /* Find the highest-addressed object that ADDRESS is not below. */ for (Lmid_t ns = 0; ns < DL_NNS; ++ns) for (struct link_map *l = GL(dl_ns)[ns]._ns_loaded; l; l = l->l_next) - if (addr >= l->l_map_start && addr < l->l_map_end) + if (addr >= l->l_map_start && addr < l->l_map_end + && (l->l_contiguous || _dl_addr_inside_object (l, addr))) { - /* Make sure it lies within one of L's segments. */ - int n = l->l_phnum; - const ElfW(Addr) reladdr = addr - l->l_addr; - while (--n >= 0) - if (l->l_phdr[n].p_type == PT_LOAD) - { - if (reladdr - l->l_phdr[n].p_vaddr >= 0 - && reladdr - l->l_phdr[n].p_vaddr < l->l_phdr[n].p_memsz) - { - determine_info (addr, l, info, mapp, symbolp); - result = 1; - goto out; - } - } + determine_info (addr, l, info, mapp, symbolp); + result = 1; + goto out; } out: @@ -162,3 +152,19 @@ _dl_addr (const void *address, Dl_info *info, return result; } libc_hidden_def (_dl_addr) + +/* Return non-zero if ADDR lies within one of L's segments. */ +int +internal_function +_dl_addr_inside_object (struct link_map *l, const ElfW(Addr) addr) +{ + int n = l->l_phnum; + const ElfW(Addr) reladdr = addr - l->l_addr; + + while (--n >= 0) + if (l->l_phdr[n].p_type == PT_LOAD + && reladdr - l->l_phdr[n].p_vaddr >= 0 + && reladdr - l->l_phdr[n].p_vaddr < l->l_phdr[n].p_memsz) + return 1; + return 0; +} diff --git a/elf/dl-iteratephdr.c b/elf/dl-iteratephdr.c index 52a114421d..7cd4d3e2b8 100644 --- a/elf/dl-iteratephdr.c +++ b/elf/dl-iteratephdr.c @@ -54,9 +54,9 @@ __dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info, nloaded += GL(dl_ns)[cnt]._ns_nloaded; if (caller >= (const void *) l->l_map_start - && caller < (const void *) l->l_map_end) - /* There must be exactly one DSO for the range of the virtual - memory. Otherwise something is really broken. */ + && caller < (const void *) l->l_map_end + && (l->l_contiguous + || _dl_addr_inside_object (l, (ElfW(Addr)) caller))) ns = cnt; } diff --git a/elf/dl-load.c b/elf/dl-load.c index 0bb58129c5..175cf89dbf 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -1225,6 +1225,8 @@ cannot allocate TLS data structures for initial thread"); loadcmds[nloadcmds - 1].mapstart - c->mapend, PROT_NONE); + l->l_contiguous = 1; + goto postmap; } @@ -1244,6 +1246,7 @@ cannot allocate TLS data structures for initial thread"); /* Remember which part of the address space this object uses. */ l->l_map_start = c->mapstart + l->l_addr; l->l_map_end = l->l_map_start + maplength; + l->l_contiguous = !has_holes; while (c < &loadcmds[nloadcmds]) { diff --git a/elf/dl-open.c b/elf/dl-open.c index e10b421b8a..69d48a622e 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -237,10 +237,10 @@ dl_open_worker (void *a) for (Lmid_t ns = 0; ns < DL_NNS; ++ns) for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next) if (caller_dlopen >= (const void *) l->l_map_start - && caller_dlopen < (const void *) l->l_map_end) + && caller_dlopen < (const void *) l->l_map_end + && (l->l_contiguous + || _dl_addr_inside_object (l, (ElfW(Addr)) caller_dlopen))) { - /* There must be exactly one DSO for the range of the virtual - memory. Otherwise something is really broken. */ assert (ns == l->l_ns); call_map = l; goto found_caller; @@ -697,3 +697,21 @@ show_scope (struct link_map *new) } } #endif + +#ifdef IS_IN_rtld +/* Return non-zero if ADDR lies within one of L's segments. */ +int +internal_function +_dl_addr_inside_object (struct link_map *l, const ElfW(Addr) addr) +{ + int n = l->l_phnum; + const ElfW(Addr) reladdr = addr - l->l_addr; + + while (--n >= 0) + if (l->l_phdr[n].p_type == PT_LOAD + && reladdr - l->l_phdr[n].p_vaddr >= 0 + && reladdr - l->l_phdr[n].p_vaddr < l->l_phdr[n].p_memsz) + return 1; + return 0; +} +#endif diff --git a/elf/dl-sym.c b/elf/dl-sym.c index 7066566bed..cedd8def80 100644 --- a/elf/dl-sym.c +++ b/elf/dl-sym.c @@ -100,10 +100,9 @@ do_sym (void *handle, const char *name, void *who, for (Lmid_t ns = 0; ns < DL_NNS; ++ns) for (struct link_map *l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next) - if (caller >= l->l_map_start && caller < l->l_map_end) + if (caller >= l->l_map_start && caller < l->l_map_end + && (l->l_contiguous || _dl_addr_inside_object (l, caller))) { - /* There must be exactly one DSO for the range of the virtual - memory. Otherwise something is really broken. */ match = l; break; } diff --git a/include/link.h b/include/link.h index 37602345de..438ec013b2 100644 --- a/include/link.h +++ b/include/link.h @@ -182,6 +182,9 @@ struct link_map is interested in the PLT interception.*/ unsigned int l_removed:1; /* Nozero if the object cannot be used anymore since it is removed. */ + unsigned int l_contiguous:1; /* Nonzero if inter-segment holes are + mprotected or if no holes are present at + all. */ /* Array with version names. */ unsigned int l_nversions; diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index 4c836e24ee..7989e221e8 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -438,23 +438,23 @@ struct rtld_global EXTERN void (*_dl_rtld_unlock_recursive) (void *); #endif - /* Prevailing state of the stack, PF_X indicating it's executable. */ - EXTERN ElfW(Word) _dl_stack_flags; - /* If loading a shared object requires that we make the stack executable when it was not, we do it by calling this function. It returns an errno code or zero on success. */ EXTERN int (*_dl_make_stack_executable_hook) (void **) internal_function; + /* Prevailing state of the stack, PF_X indicating it's executable. */ + EXTERN ElfW(Word) _dl_stack_flags; + /* Keep the conditional TLS members at the end so the layout of the structure used by !USE_TLS code matches the prefix of the layout in the USE_TLS rtld. Note that `struct link_map' is conditionally defined as well, so _dl_rtld_map needs to be last before this. */ #ifdef USE_TLS - /* Highest dtv index currently needed. */ - EXTERN size_t _dl_tls_max_dtv_idx; /* Flag signalling whether there are gaps in the module ID allocation. */ EXTERN bool _dl_tls_dtv_gaps; + /* Highest dtv index currently needed. */ + EXTERN size_t _dl_tls_max_dtv_idx; /* Information about the dtv slots. */ EXTERN struct dtv_slotinfo_list { @@ -549,15 +549,15 @@ struct rtld_global_ro #define DL_DEBUG_HELP (1 << 9) #define DL_DEBUG_PRELINK (1 << 10) - /* Cached value of `getpagesize ()'. */ - EXTERN size_t _dl_pagesize; - /* OS version. */ EXTERN unsigned int _dl_osversion; /* Platform name. */ EXTERN const char *_dl_platform; EXTERN size_t _dl_platformlen; + /* Cached value of `getpagesize ()'. */ + EXTERN size_t _dl_pagesize; + /* Copy of the content of `_dl_main_searchlist' at startup time. */ EXTERN struct r_scope_elem _dl_initial_searchlist; @@ -586,9 +586,6 @@ struct rtld_global_ro /* Expected cache ID. */ EXTERN int _dl_correct_cache_id; - /* 0 if internal pointer values should not be guarded, 1 if they should. */ - EXTERN int _dl_pointer_guard; - /* Mask for hardware capabilities that are available. */ EXTERN uint64_t _dl_hwcap; @@ -672,6 +669,9 @@ struct rtld_global_ro /* List of auditing interfaces. */ struct audit_ifaces *_dl_audit; unsigned int _dl_naudit; + + /* 0 if internal pointer values should not be guarded, 1 if they should. */ + EXTERN int _dl_pointer_guard; }; # define __rtld_global_attribute__ # ifdef IS_IN_rtld @@ -1085,6 +1085,8 @@ extern struct link_map *_dl_update_slotinfo (unsigned long int req_modid); but never touch anything. Return null if it's not allocated yet. */ extern void *_dl_tls_get_addr_soft (struct link_map *l) internal_function; +extern int _dl_addr_inside_object (struct link_map *l, const ElfW(Addr) addr) + internal_function attribute_hidden; __END_DECLS -- cgit 1.4.1