From 0c7690f6a5d6e073052ee6487f768289db3a58f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Mon, 7 Nov 2011 18:08:33 +0100 Subject: ldso: support RTLD_NOLOAD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So application query if specified module is loaded or not with dlopen. Signed-off-by: Timo Teräs Signed-off-by: Bernhard Reutner-Fischer --- ldso/include/dl-elf.h | 6 ++++-- ldso/ldso/dl-elf.c | 30 +++++++++++++++++------------- ldso/ldso/ldso.c | 4 +++- ldso/libdl/libdl.c | 11 +++++++---- 4 files changed, 31 insertions(+), 20 deletions(-) (limited to 'ldso') diff --git a/ldso/include/dl-elf.h b/ldso/include/dl-elf.h index 495bd2bca..29d1a007f 100644 --- a/ldso/include/dl-elf.h +++ b/ldso/include/dl-elf.h @@ -26,16 +26,18 @@ static __inline__ void _dl_map_cache(void) { } static __inline__ void _dl_unmap_cache(void) { } #endif +#define DL_RESOLVE_SECURE 0x0001 +#define DL_RESOLVE_NOLOAD 0x0002 /* Function prototypes for non-static stuff in readelflib1.c */ extern void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size); extern int _dl_parse_relocation_information(struct dyn_elf *rpnt, struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size); -extern struct elf_resolve * _dl_load_shared_library(int secure, +extern struct elf_resolve * _dl_load_shared_library(unsigned rflags, struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname, int trace_loaded_objects); -extern struct elf_resolve * _dl_load_elf_shared_library(int secure, +extern struct elf_resolve * _dl_load_elf_shared_library(unsigned rflags, struct dyn_elf **rpnt, const char *libname); extern struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full_libname, int trace_loaded_objects); diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c index 308a66c63..b9de19910 100644 --- a/ldso/ldso/dl-elf.c +++ b/ldso/ldso/dl-elf.c @@ -132,7 +132,7 @@ _dl_protect_relro (struct elf_resolve *l) /* This function's behavior must exactly match that * in uClibc/ldso/util/ldd.c */ static struct elf_resolve * -search_for_named_library(const char *name, int secure, const char *path_list, +search_for_named_library(const char *name, unsigned rflags, const char *path_list, struct dyn_elf **rpnt) { char *path, *path_n, *mylibname; @@ -174,7 +174,7 @@ search_for_named_library(const char *name, int secure, const char *path_list, _dl_strcpy(mylibname, "."); /* Assume current dir if empty path */ _dl_strcat(mylibname, "/"); _dl_strcat(mylibname, name); - if ((tpnt = _dl_load_elf_shared_library(secure, rpnt, mylibname)) != NULL) + if ((tpnt = _dl_load_elf_shared_library(rflags, rpnt, mylibname)) != NULL) return tpnt; path_n = path+1; } @@ -187,7 +187,7 @@ search_for_named_library(const char *name, int secure, const char *path_list, unsigned long _dl_error_number; unsigned long _dl_internal_error_number; -struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, +struct elf_resolve *_dl_load_shared_library(unsigned rflags, struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname, int attribute_unused trace_loaded_objects) { char *pnt; @@ -216,7 +216,7 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, if (libname != full_libname) { _dl_if_debug_dprint("\ttrying file='%s'\n", full_libname); - tpnt1 = _dl_load_elf_shared_library(secure, rpnt, full_libname); + tpnt1 = _dl_load_elf_shared_library(rflags, rpnt, full_libname); if (tpnt1) { return tpnt1; } @@ -231,7 +231,7 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, if (pnt) { pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB]; _dl_if_debug_dprint("\tsearching RPATH='%s'\n", pnt); - if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL) + if ((tpnt1 = search_for_named_library(libname, rflags, pnt, rpnt)) != NULL) return tpnt1; } #endif @@ -240,7 +240,7 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, /* Check in LD_{ELF_}LIBRARY_PATH, if specified and allowed */ if (_dl_library_path) { _dl_if_debug_dprint("\tsearching LD_LIBRARY_PATH='%s'\n", _dl_library_path); - if ((tpnt1 = search_for_named_library(libname, secure, _dl_library_path, rpnt)) != NULL) + if ((tpnt1 = search_for_named_library(libname, rflags, _dl_library_path, rpnt)) != NULL) { return tpnt1; } @@ -254,7 +254,7 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, if (pnt) { pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB]; _dl_if_debug_dprint("\tsearching RUNPATH='%s'\n", pnt); - if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL) + if ((tpnt1 = search_for_named_library(libname, rflags, pnt, rpnt)) != NULL) return tpnt1; } #endif @@ -277,7 +277,7 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, || libent[i].flags == LIB_ELF_LIBC0 || libent[i].flags == LIB_ELF_LIBC5) && _dl_strcmp(libname, strs + libent[i].sooffset) == 0 - && (tpnt1 = _dl_load_elf_shared_library(secure, rpnt, strs + libent[i].liboffset)) + && (tpnt1 = _dl_load_elf_shared_library(rflags, rpnt, strs + libent[i].liboffset)) ) { return tpnt1; } @@ -288,14 +288,14 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, /* Look for libraries wherever the shared library loader * was installed */ _dl_if_debug_dprint("\tsearching ldso dir='%s'\n", _dl_ldsopath); - tpnt1 = search_for_named_library(libname, secure, _dl_ldsopath, rpnt); + tpnt1 = search_for_named_library(libname, rflags, _dl_ldsopath, rpnt); if (tpnt1 != NULL) return tpnt1; #endif /* Lastly, search the standard list of paths for the library. This list must exactly match the list in uClibc/ldso/util/ldd.c */ _dl_if_debug_dprint("\tsearching full lib path list\n"); - tpnt1 = search_for_named_library(libname, secure, + tpnt1 = search_for_named_library(libname, rflags, UCLIBC_RUNTIME_PREFIX "lib:" UCLIBC_RUNTIME_PREFIX "usr/lib" #ifndef __LDSO_CACHE_SUPPORT__ @@ -437,7 +437,7 @@ map_writeable (int infile, ElfW(Phdr) *ppnt, int piclib, int flags, * are required. */ -struct elf_resolve *_dl_load_elf_shared_library(int secure, +struct elf_resolve *_dl_load_elf_shared_library(unsigned rflags, struct dyn_elf **rpnt, const char *libname) { ElfW(Ehdr) *epnt; @@ -474,9 +474,9 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, _dl_close(infile); return NULL; } - /* If we are in secure mode (i.e. a setu/gid binary using LD_PRELOAD), + /* If we are in secure mode (i.e. a setuid/gid binary using LD_PRELOAD), we don't load the library if it isn't setuid. */ - if (secure) { + if (rflags & DL_RESOLVE_SECURE) { if (!(st.st_mode & S_ISUID)) { _dl_close(infile); return NULL; @@ -492,6 +492,10 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, return tpnt; } } + if (rflags & DL_RESOLVE_NOLOAD) { + _dl_close(infile); + return NULL; + } header = _dl_mmap((void *) 0, _dl_pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_UNINITIALIZE, -1, 0); if (_dl_mmap_check_error(header)) { diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index fe463b75d..0dff9781f 100644 --- a/ldso/ldso/ldso.c +++ b/ldso/ldso/ldso.c @@ -858,7 +858,9 @@ of this helper program; chances are you did not intend to run this program.\n\ if (!_dl_secure || _dl_strchr(str, '/') == NULL) { _dl_if_debug_dprint("\tfile='%s'; needed by '%s'\n", str, _dl_progname); - tpnt1 = _dl_load_shared_library(_dl_secure, &rpnt, NULL, str, trace_loaded_objects); + tpnt1 = _dl_load_shared_library( + _dl_secure ? DL_RESOLVE_SECURE : 0, + &rpnt, NULL, str, trace_loaded_objects); if (!tpnt1) { #ifdef __LDSO_LDD_SUPPORT__ if (trace_loaded_objects || _dl_trace_prelink) diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c index c164ffbee..cbbbcd49e 100644 --- a/ldso/libdl/libdl.c +++ b/ldso/libdl/libdl.c @@ -52,11 +52,13 @@ extern struct link_map *_dl_update_slotinfo(unsigned long int req_modid); /* When libdl is loaded as a shared library, we need to load in * and use a pile of symbols from ldso... */ - -extern struct elf_resolve * _dl_load_shared_library(int, struct dyn_elf **, +#include +#if 0 +extern struct elf_resolve * _dl_load_shared_library(unsigned, struct dyn_elf **, struct elf_resolve *, char *, int); extern int _dl_fixup(struct dyn_elf *rpnt, struct r_scope_elem *scope, int lazy); extern void _dl_protect_relro(struct elf_resolve * tpnt); +#endif extern int _dl_errno; extern struct dyn_elf *_dl_symbol_tables; extern struct dyn_elf *_dl_handles; @@ -308,7 +310,7 @@ void *dlopen(const char *libname, int flag) #endif /* A bit of sanity checking... */ - if (!(flag & (RTLD_LAZY|RTLD_NOW))) { + if (!(flag & (RTLD_LAZY|RTLD_NOW|RTLD_NOLOAD))) { _dl_error_number = LD_BAD_HANDLE; return NULL; } @@ -378,8 +380,9 @@ void *dlopen(const char *libname, int flag) /* Try to load the specified library */ _dl_if_debug_print("Trying to dlopen '%s', RTLD_GLOBAL:%d RTLD_NOW:%d\n", (char*)libname, (flag & RTLD_GLOBAL ? 1:0), (now_flag & RTLD_NOW ? 1:0)); - tpnt = _dl_load_shared_library(0, &rpnt, tfrom, (char*)libname, 0); + tpnt = _dl_load_shared_library((flag & RTLD_NOLOAD) ? DL_RESOLVE_NOLOAD : 0, + &rpnt, tfrom, (char*)libname, 0); if (tpnt == NULL) { _dl_unmap_cache(); return NULL; -- cgit v1.2.3