diff options
author | Ulrich Drepper <drepper@redhat.com> | 2009-12-15 12:32:27 -0800 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2009-12-15 12:32:27 -0800 |
commit | 2af6396817fb9df98e63de75dd59fd999ee9f1d0 (patch) | |
tree | d66827c66d770f1f3d697dbb027b59064e6ab0e0 | |
parent | 2510d01ddba195f8cfaa3c2349f75e0612719d82 (diff) | |
download | glibc-2af6396817fb9df98e63de75dd59fd999ee9f1d0.tar glibc-2af6396817fb9df98e63de75dd59fd999ee9f1d0.tar.gz glibc-2af6396817fb9df98e63de75dd59fd999ee9f1d0.tar.bz2 glibc-2af6396817fb9df98e63de75dd59fd999ee9f1d0.zip |
Avoid ELF lookup race.
On some architectures the update of the l_used field in the lookup
functions races with setting the other bits in the bitfield. Simply
avoid this and optimize use of l_used in general.
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | elf/dl-lookup.c | 7 | ||||
-rw-r--r-- | elf/dl-object.c | 8 | ||||
-rw-r--r-- | include/link.h | 8 |
4 files changed, 23 insertions, 8 deletions
@@ -1,3 +1,11 @@ +2009-12-15 Ulrich Drepper <drepper@redhat.com> + + * include/link.h (struct link_map): Move l_used into its own word. + * elf/dl-lookup.c (_dl_lookup_symbol_x): Only update l_used when it is + still zero. + * elf/dl-object.c (_dl_new_object): Set dl_used if we know it is + never really used. + 2009-12-13 H.J. Lu <hongjiu.lu@intel.com> * sysdeps/i386/i686/multiarch/strcspn.S Include <init-arch.h> diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c index c1a1366d6f..763ec16fa4 100644 --- a/elf/dl-lookup.c +++ b/elf/dl-lookup.c @@ -777,7 +777,7 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map, if (__builtin_expect (protected != 0, 0)) { /* It is very tricky. We need to figure out what value to - return for the protected symbol. */ + return for the protected symbol. */ if (type_class == ELF_RTYPE_CLASS_PLT) { if (current_value.s != NULL && current_value.m != undef_map) @@ -822,7 +822,8 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map, version, type_class, flags, skip_map); /* The object is used. */ - current_value.m->l_used = 1; + if (__builtin_expect (current_value.m->l_used == 0, 0)) + current_value.m->l_used = 1; if (__builtin_expect (GLRO(dl_debug_mask) & (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0)) @@ -844,7 +845,7 @@ _dl_setup_hash (struct link_map *map) Elf_Symndx nchain; if (__builtin_expect (map->l_info[DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM - + DT_THISPROCNUM + DT_VERSIONTAGNUM + + DT_THISPROCNUM + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM] != NULL, 1)) { Elf32_Word *hash32 diff --git a/elf/dl-object.c b/elf/dl-object.c index be4ea38f9f..788e2c07b9 100644 --- a/elf/dl-object.c +++ b/elf/dl-object.c @@ -1,5 +1,5 @@ /* Storage management for the chain of loaded shared objects. - Copyright (C) 1995-2002,2004,2006,2007,2008 Free Software Foundation, Inc. + Copyright (C) 1995-2002,2004,2006-2008,2009 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -67,6 +67,10 @@ _dl_new_object (char *realname, const char *libname, int type, new->l_name = realname; new->l_type = type; + /* If we set the bit now since we know it is never used we avoid + dirtying the cache line later. */ + if ((GLRO(dl_debug_mask) & DL_DEBUG_UNUSED) == 0) + new->l_used = 1; new->l_loader = loader; #if NO_TLS_OFFSET != 0 new->l_tls_offset = NO_TLS_OFFSET; @@ -174,7 +178,7 @@ _dl_new_object (char *realname, const char *libname, int type, if (result == NULL) { /* We were not able to determine the current directory. - Note that free(origin) is OK if origin == NULL. */ + Note that free(origin) is OK if origin == NULL. */ free (origin); origin = (char *) -1; goto out; diff --git a/include/link.h b/include/link.h index 4b9978ad61..26c67438f0 100644 --- a/include/link.h +++ b/include/link.h @@ -1,6 +1,6 @@ /* Data structure for communication from the run-time dynamic linker for loaded ELF shared objects. - Copyright (C) 1995-2006, 2007 Free Software Foundation, Inc. + Copyright (C) 1995-2006, 2007, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -180,7 +180,6 @@ struct link_map unsigned int l_need_tls_init:1; /* Nonzero if GL(dl_init_static_tls) should be called on this link map when relocation finishes. */ - unsigned int l_used:1; /* Nonzero if the DSO is used. */ unsigned int l_auditing:1; /* Nonzero if the DSO is used in auditing. */ unsigned int l_audit_any_plt:1; /* Nonzero if at least one audit module is interested in the PLT interception.*/ @@ -239,12 +238,15 @@ struct link_map struct link_map **l_initfini; /* List of the dependencies introduced through symbol binding. */ - unsigned int l_reldepsmax; struct link_map_reldeps { unsigned int act; struct link_map *list[]; } *l_reldeps; + unsigned int l_reldepsmax; + + /* Nonzero if the DSO is used. */ + unsigned int l_used; /* Various flag words. */ ElfW(Word) l_feature_1; |