diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2017-08-26 19:22:26 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2017-08-26 19:26:21 -0700 |
commit | a5b4ee9451dc9ffb6aa29376fc03943c53c6da0d (patch) | |
tree | 74028cae4c8a9f47eab5faa25aff8a47b0c04e77 /bfd/elf32-i386.c | |
parent | aecbb010f9d74b574ba89a64f45cde2407e53dab (diff) |
Disallow copy relocation against protected data symbol
We shpouldn't generate copy relocation to resolve reference to protected
data symbol defined in shared object with the NO_COPY_ON_PROTECTED
property. This patch adds a bit to elf_obj_tdata as well as
elf_i386_link_hash_entry and elf_x86_64_link_hash_entry to track the bfd
with the NO_COPY_ON_PROTECTED property as well as protected symbol
defined in shared object. extern_protected_data is set to FALSE if any
input relocatable file contains the NO_COPY_ON_PROTECTED property.
bfd/
PR ld/21997
* elf-bfd.h (elf_obj_tdata): Use ENUM_BITFIELD on object_id,
dyn_lib_class and has_gnu_symbols. Change bad_symtab to bitfield.
Add a has_no_copy_on_protected bitfield.
(elf_has_no_copy_on_protected): New.
* elf-properties.c (_bfd_elf_parse_gnu_properties): Set
elf_has_no_copy_on_protected for GNU_PROPERTY_NO_COPY_ON_PROTECTED.
(elf_merge_gnu_property_list): Likewise.
(_bfd_elf_link_setup_gnu_properties): Set extern_protected_data
to FALSE for elf_has_no_copy_on_protected.
* elf32-i386.c (SYMBOL_NO_COPYRELOC): New.
(elf_i386_link_hash_entry): Add def_protected.
(elf_i386_adjust_dynamic_symbol): Also check SYMBOL_NO_COPYRELOC
when checking info->nocopyreloc.
(elf_i386_link_setup_gnu_properties): Don't set
extern_protected_data here.
(elf_i386_merge_symbol_attribute): New function.
(elf_backend_merge_symbol_attribute): New.
* elf64-x86-64.c (SYMBOL_NO_COPYRELOC): New.
(elf_x86_64_link_hash_entry): Add def_protected.
(elf_x86_64_need_pic): Report protected symbol for def_protected.
(elf_x86_64_adjust_dynamic_symbol): Also check SYMBOL_NO_COPYRELOC
when checking info->nocopyreloc.
(elf_x86_64_relocate_section): Also check for R_X86_64_PC32
relocation run-time overflow and unresolvable R_X86_64_32S
relocation against protected data symbol defined in shared object
with GNU_PROPERTY_NO_COPY_ON_PROTECTED.
(elf_x86_64_link_setup_gnu_properties): Don't set
extern_protected_data here.
(elf_x86_64_merge_symbol_attribute): New function.
(elf_backend_merge_symbol_attribute): New.
ld/
PR ld/21997
* testsuite/ld-i386/i386.exp: Run PR ld/21997 tests.
* testsuite/ld-x86-64/x86-64.exp: Likewise.
* testsuite/ld-i386/pr21997-1a.S: New file.
* testsuite/ld-i386/pr21997-1b.c: Likewise.
* testsuite/ld-i386/pr21997-1c.S: Likewise.
* testsuite/ld-x86-64/pr21997-1a.S: Likewise.
* testsuite/ld-x86-64/pr21997-1a.err: Likewise.
* testsuite/ld-x86-64/pr21997-1b.c: Likewise.
* testsuite/ld-x86-64/pr21997-1b.err: Likewise.
* testsuite/ld-x86-64/pr21997-1c.c: Likewise.
Diffstat (limited to 'bfd/elf32-i386.c')
-rw-r--r-- | bfd/elf32-i386.c | 123 |
1 files changed, 64 insertions, 59 deletions
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 179dc434dc..69b41a54f9 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -956,6 +956,18 @@ static const struct elf_i386_backend_data elf_i386_arch_bed = || (EH)->has_non_got_reloc \ || !(INFO)->dynamic_undefined_weak)))) +/* Should copy relocation be generated for a symbol. Don't generate + copy relocation against a protected symbol defined in a shared + object with GNU_PROPERTY_NO_COPY_ON_PROTECTED. */ +#define SYMBOL_NO_COPYRELOC(INFO, EH) \ + ((EH)->def_protected \ + && ((EH)->elf.root.type == bfd_link_hash_defined \ + || (EH)->elf.root.type == bfd_link_hash_defweak) \ + && elf_has_no_copy_on_protected ((EH)->elf.root.u.def.section->owner) \ + && ((EH)->elf.root.u.def.section->owner->flags & DYNAMIC) != 0 \ + && ((EH)->elf.root.u.def.section->flags & SEC_CODE) == 0) + + /* i386 ELF linker hash entry. */ struct elf_i386_link_hash_entry @@ -998,6 +1010,9 @@ struct elf_i386_link_hash_entry /* TRUE if symbol is __tls_get_addr. */ unsigned int tls_get_addr : 1; + /* TRUE if symbol is defined as a protected symbol. */ + unsigned int def_protected : 1; + /* Reference count of C/C++ function pointer relocations in read-write section which can be resolved at run-time. */ bfd_signed_vma func_pointer_refcount; @@ -2590,6 +2605,8 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info, the link may change h->type. So fix it now. */ h->plt.offset = (bfd_vma) -1; + eh = (struct elf_i386_link_hash_entry *) h; + /* If this is a weak symbol, and there is a real definition, the processor independent code will have arranged for us to see the real definition first, and we can just use the same value. */ @@ -2599,7 +2616,9 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info, || h->u.weakdef->root.type == bfd_link_hash_defweak); h->root.u.def.section = h->u.weakdef->root.u.def.section; h->root.u.def.value = h->u.weakdef->root.u.def.value; - if (ELIMINATE_COPY_RELOCS || info->nocopyreloc) + if (ELIMINATE_COPY_RELOCS + || info->nocopyreloc + || SYMBOL_NO_COPYRELOC (info, eh)) h->non_got_ref = h->u.weakdef->non_got_ref; return TRUE; } @@ -2617,12 +2636,11 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info, /* If there are no references to this symbol that do not use the GOT nor R_386_GOTOFF relocation, we don't need to generate a copy reloc. */ - eh = (struct elf_i386_link_hash_entry *) h; if (!h->non_got_ref && !eh->gotoff_ref) return TRUE; /* If -z nocopyreloc was given, we won't generate them either. */ - if (info->nocopyreloc) + if (info->nocopyreloc || SYMBOL_NO_COPYRELOC (info, eh)) { h->non_got_ref = 0; return TRUE; @@ -6802,68 +6820,39 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info) break; } - if (ebfd != NULL) + if (ebfd != NULL && features) { - if (features) + /* If features is set, add GNU_PROPERTY_X86_FEATURE_1_IBT and + GNU_PROPERTY_X86_FEATURE_1_SHSTK. */ + prop = _bfd_elf_get_property (ebfd, + GNU_PROPERTY_X86_FEATURE_1_AND, + 4); + prop->u.number |= features; + prop->pr_kind = property_number; + + /* Create the GNU property note section if needed. */ + if (pbfd == NULL) { - /* If features is set, add GNU_PROPERTY_X86_FEATURE_1_IBT and - GNU_PROPERTY_X86_FEATURE_1_SHSTK. */ - prop = _bfd_elf_get_property (ebfd, - GNU_PROPERTY_X86_FEATURE_1_AND, - 4); - prop->u.number |= features; - prop->pr_kind = property_number; - - /* Create the GNU property note section if needed. */ - if (pbfd == NULL) - { - sec = bfd_make_section_with_flags (ebfd, - NOTE_GNU_PROPERTY_SECTION_NAME, - (SEC_ALLOC - | SEC_LOAD - | SEC_IN_MEMORY - | SEC_READONLY - | SEC_HAS_CONTENTS - | SEC_DATA)); - if (sec == NULL) - info->callbacks->einfo (_("%F: failed to create GNU property section\n")); + sec = bfd_make_section_with_flags (ebfd, + NOTE_GNU_PROPERTY_SECTION_NAME, + (SEC_ALLOC + | SEC_LOAD + | SEC_IN_MEMORY + | SEC_READONLY + | SEC_HAS_CONTENTS + | SEC_DATA)); + if (sec == NULL) + info->callbacks->einfo (_("%F: failed to create GNU property section\n")); - if (!bfd_set_section_alignment (ebfd, sec, 2)) - { + if (!bfd_set_section_alignment (ebfd, sec, 2)) + { error_alignment: - info->callbacks->einfo (_("%F%A: failed to align section\n"), - sec); - } - - elf_section_type (sec) = SHT_NOTE; + info->callbacks->einfo (_("%F%A: failed to align section\n"), + sec); } - } - /* Check GNU_PROPERTY_NO_COPY_ON_PROTECTED. */ - for (; pbfd != NULL; pbfd = pbfd->link.next) - if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour - && (pbfd->flags - & (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0) - { - elf_property_list *p; - - /* The property list is sorted in order of type. */ - for (p = elf_properties (pbfd); p != NULL; p = p->next) - { - if (GNU_PROPERTY_NO_COPY_ON_PROTECTED - == p->property.pr_type) - { - /* Clear extern_protected_data if - GNU_PROPERTY_NO_COPY_ON_PROTECTED is - set on any input relocatable file. */ - info->extern_protected_data = FALSE; - break; - } - else if (GNU_PROPERTY_NO_COPY_ON_PROTECTED - < p->property.pr_type) - break; - } - } + elf_section_type (sec) = SHT_NOTE; + } } pbfd = _bfd_elf_link_setup_gnu_properties (info); @@ -7163,6 +7152,21 @@ elf_i386_link_check_relocs (bfd *abfd, struct bfd_link_info *info) return _bfd_elf_link_check_relocs (abfd, info); } +static void +elf_i386_merge_symbol_attribute (struct elf_link_hash_entry *h, + const Elf_Internal_Sym *isym, + bfd_boolean definition, + bfd_boolean dynamic ATTRIBUTE_UNUSED) +{ + if (definition) + { + struct elf_i386_link_hash_entry *eh + = (struct elf_i386_link_hash_entry *) h; + eh->def_protected = (ELF_ST_VISIBILITY (isym->st_other) + == STV_PROTECTED); + } +} + #define TARGET_LITTLE_SYM i386_elf32_vec #define TARGET_LITTLE_NAME "elf32-i386" #define ELF_ARCH bfd_arch_i386 @@ -7218,6 +7222,7 @@ elf_i386_link_check_relocs (bfd *abfd, struct bfd_link_info *info) #define elf_backend_parse_gnu_properties elf_i386_parse_gnu_properties #define elf_backend_merge_gnu_properties elf_i386_merge_gnu_properties #define elf_backend_setup_gnu_properties elf_i386_link_setup_gnu_properties +#define elf_backend_merge_symbol_attribute elf_i386_merge_symbol_attribute #include "elf32-target.h" |