diff options
Diffstat (limited to 'elf')
-rw-r--r-- | elf/dl-close.c | 24 | ||||
-rw-r--r-- | elf/dl-lookup.c | 6 | ||||
-rw-r--r-- | elf/dl-open.c | 10 | ||||
-rw-r--r-- | elf/dl-runtime.c | 17 | ||||
-rw-r--r-- | elf/dl-sym.c | 7 |
5 files changed, 41 insertions, 23 deletions
diff --git a/elf/dl-close.c b/elf/dl-close.c index 84e57e09d0..bfcceea4bc 100644 --- a/elf/dl-close.c +++ b/elf/dl-close.c @@ -30,6 +30,7 @@ #include <ldsodefs.h> #include <sys/types.h> #include <sys/mman.h> +#include <sysdep-cancel.h> /* Type of the constructor functions. */ @@ -419,16 +420,21 @@ _dl_close (void *_map) struct r_scoperec *old = imap->l_scoperec; - __rtld_mrlock_change (imap->l_scoperec_lock); - imap->l_scoperec = newp; - __rtld_mrlock_done (imap->l_scoperec_lock); - - if (catomic_increment_val (&old->nusers) != 1) + if (SINGLE_THREAD_P) + imap->l_scoperec = newp; + else { - old->remove_after_use = true; - old->notify = true; - if (catomic_decrement_val (&old->nusers) != 0) - __rtld_waitzero (old->nusers); + __rtld_mrlock_change (imap->l_scoperec_lock); + imap->l_scoperec = newp; + __rtld_mrlock_done (imap->l_scoperec_lock); + + if (atomic_increment_val (&old->nusers) != 1) + { + old->remove_after_use = true; + old->notify = true; + if (atomic_decrement_val (&old->nusers) != 0) + __rtld_waitzero (old->nusers); + } } /* No user anymore, we can free it now. */ diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c index 7cfcc620a7..72381698db 100644 --- a/elf/dl-lookup.c +++ b/elf/dl-lookup.c @@ -207,7 +207,11 @@ _dl_debug_bindings (const char *undef_name, struct link_map *undef_map, /* Search loaded objects' symbol tables for a definition of the symbol - UNDEF_NAME, perhaps with a requested version for the symbol. */ + UNDEF_NAME, perhaps with a requested version for the symbol. + + We must never have calls to the audit functions inside this function + or in any function which gets called. If this would happen the audit + code might create a thread which can throw off all the scope locking. */ lookup_t internal_function _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map, diff --git a/elf/dl-open.c b/elf/dl-open.c index 35712b5ac0..85b9637305 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -31,6 +31,7 @@ #include <ldsodefs.h> #include <bp-sym.h> #include <caller.h> +#include <sysdep-cancel.h> #include <dl-dst.h> @@ -423,15 +424,20 @@ dl_open_worker (void *a) if (old == &imap->l_scoperec_mem) imap->l_scoperec = newp; + else if (SINGLE_THREAD_P) + { + imap->l_scoperec = newp; + free (old); + } else { __rtld_mrlock_change (imap->l_scoperec_lock); imap->l_scoperec = newp; __rtld_mrlock_done (imap->l_scoperec_lock); - catomic_increment (&old->nusers); + atomic_increment (&old->nusers); old->remove_after_use = true; - if (catomic_decrement_val (&old->nusers) == 0) + if (atomic_decrement_val (&old->nusers) == 0) /* No user, we can free it here and now. */ free (old); } diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c index 05fd974bf5..8bf5b89eb6 100644 --- a/elf/dl-runtime.c +++ b/elf/dl-runtime.c @@ -24,6 +24,7 @@ #include <unistd.h> #include <sys/param.h> #include <ldsodefs.h> +#include <sysdep-cancel.h> #include "dynamic-link.h" #if (!defined ELF_MACHINE_NO_RELA && !defined ELF_MACHINE_PLT_REL) \ @@ -93,11 +94,11 @@ _dl_fixup ( } struct r_scoperec *scoperec = l->l_scoperec; - if (l->l_type == lt_loaded) + if (l->l_type == lt_loaded && !SINGLE_THREAD_P) { __rtld_mrlock_lock (l->l_scoperec_lock); scoperec = l->l_scoperec; - catomic_increment (&scoperec->nusers); + atomic_increment (&scoperec->nusers); __rtld_mrlock_unlock (l->l_scoperec_lock); } @@ -106,8 +107,8 @@ _dl_fixup ( ELF_RTYPE_CLASS_PLT, DL_LOOKUP_ADD_DEPENDENCY, NULL); - if (l->l_type == lt_loaded - && catomic_decrement_val (&scoperec->nusers) == 0 + if (l->l_type == lt_loaded && !SINGLE_THREAD_P + && atomic_decrement_val (&scoperec->nusers) == 0 && __builtin_expect (scoperec->remove_after_use, 0)) { if (scoperec->notify) @@ -195,11 +196,11 @@ _dl_profile_fixup ( } struct r_scoperec *scoperec = l->l_scoperec; - if (l->l_type == lt_loaded) + if (l->l_type == lt_loaded && !SINGLE_THREAD_P) { __rtld_mrlock_lock (l->l_scoperec_lock); scoperec = l->l_scoperec; - catomic_increment (&scoperec->nusers); + atomic_increment (&scoperec->nusers); __rtld_mrlock_unlock (l->l_scoperec_lock); } @@ -208,8 +209,8 @@ _dl_profile_fixup ( ELF_RTYPE_CLASS_PLT, DL_LOOKUP_ADD_DEPENDENCY, NULL); - if (l->l_type == lt_loaded - && catomic_decrement_val (&scoperec->nusers) == 0 + if (l->l_type == lt_loaded && !SINGLE_THREAD_P + && atomic_decrement_val (&scoperec->nusers) == 0 && __builtin_expect (scoperec->remove_after_use, 0)) { if (scoperec->notify) diff --git a/elf/dl-sym.c b/elf/dl-sym.c index 43933466b4..34d75a1a67 100644 --- a/elf/dl-sym.c +++ b/elf/dl-sym.c @@ -25,6 +25,7 @@ #include <dlfcn.h> #include <ldsodefs.h> #include <dl-hash.h> +#include <sysdep-cancel.h> #ifdef USE_TLS # include <dl-tls.h> #endif @@ -115,7 +116,7 @@ do_sym (void *handle, const char *name, void *who, the initial binary. And then the more complex part where the object is dynamically loaded and the scope array can change. */ - if (match->l_type != lt_loaded) + if (match->l_type != lt_loaded || SINGLE_THREAD_P) result = GLRO(dl_lookup_symbol_x) (name, match, &ref, match->l_scoperec->scope, vers, 0, flags | DL_LOOKUP_ADD_DEPENDENCY, @@ -124,7 +125,7 @@ do_sym (void *handle, const char *name, void *who, { __rtld_mrlock_lock (match->l_scoperec_lock); struct r_scoperec *scoperec = match->l_scoperec; - catomic_increment (&scoperec->nusers); + atomic_increment (&scoperec->nusers); __rtld_mrlock_unlock (match->l_scoperec_lock); struct call_dl_lookup_args args; @@ -141,7 +142,7 @@ do_sym (void *handle, const char *name, void *who, int err = GLRO(dl_catch_error) (&objname, &errstring, &malloced, call_dl_lookup, &args); - if (catomic_decrement_val (&scoperec->nusers) == 0 + if (atomic_decrement_val (&scoperec->nusers) == 0 && __builtin_expect (scoperec->remove_after_use, 0)) { if (scoperec->notify) |