aboutsummaryrefslogtreecommitdiff
path: root/bfd/elfxx-mips.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2016-12-26 00:30:45 +1030
committerAlan Modra <amodra@gmail.com>2016-12-26 13:47:51 +1030
commit5474d94f03aedba2f832006dc7d680cc15792a7b (patch)
tree8fdd2bb1d2a32f1f35ef76199f9d92da95c0ec27 /bfd/elfxx-mips.c
parent9d19e4fdb7c684329c8b1b72796a0071708dabc7 (diff)
downloadgdb-5474d94f03aedba2f832006dc7d680cc15792a7b.zip
gdb-5474d94f03aedba2f832006dc7d680cc15792a7b.tar.gz
gdb-5474d94f03aedba2f832006dc7d680cc15792a7b.tar.bz2
dynrelro section for read-only dynamic symbols copied into executable
Variables defined in shared libraries are copied into an executable's .bss section when code in the executable is non-PIC and thus would require dynamic text relocations to access the variable directly in the shared library. Recent x86 toolchains also copy variables into the executable to gain a small speed improvement. The problem is that if the variable was originally read-only, the copy in .bss is writable, potentially opening a security hole. This patch cures that problem by putting the copy in a section that becomes read-only after ld.so relocation, provided -z relro is in force. The patch also fixes a microblaze linker segfault on attempting to use dynamic bss variables. bfd/ PR ld/20995 * elf-bfd.h (struct elf_link_hash_table): Add sdynrelro and sreldynrelro. (struct elf_backend_data): Add want_dynrelro. * elfxx-target.h (elf_backend_want_dynrelro): Define. (elfNN_bed): Update initializer. * elflink.c (_bfd_elf_create_dynamic_sections): Create sdynrelro and sreldynrelro sections. * elf32-arm.c (elf32_arm_adjust_dynamic_symbol): Place variables copied into the executable from read-only sections into sdynrelro. (elf32_arm_size_dynamic_sections): Handle sdynrelro. (elf32_arm_finish_dynamic_symbol): Select sreldynrelro for dynamic relocs in sdynrelro. (elf_backend_want_dynrelro): Define. * elf32-hppa.c (elf32_hppa_adjust_dynamic_symbol) (elf32_hppa_size_dynamic_sections, elf32_hppa_finish_dynamic_symbol) (elf_backend_want_dynrelro): As above. * elf32-i386.c (elf_i386_adjust_dynamic_symbol) (elf_i386_size_dynamic_sections, elf_i386_finish_dynamic_symbol) (elf_backend_want_dynrelro): As above. * elf32-metag.c (elf_metag_adjust_dynamic_symbol) (elf_metag_size_dynamic_sections, elf_metag_finish_dynamic_symbol) (elf_backend_want_dynrelro): As above. * elf32-microblaze.c (microblaze_elf_adjust_dynamic_symbol) (microblaze_elf_size_dynamic_sections) (microblaze_elf_finish_dynamic_symbol) (elf_backend_want_dynrelro): As above. * elf32-nios2.c (nios2_elf32_finish_dynamic_symbol) (nios2_elf32_adjust_dynamic_symbol) (nios2_elf32_size_dynamic_sections) (elf_backend_want_dynrelro): As above. * elf32-or1k.c (or1k_elf_finish_dynamic_symbol) (or1k_elf_adjust_dynamic_symbol, or1k_elf_size_dynamic_sections) (elf_backend_want_dynrelro): As above. * elf32-ppc.c (ppc_elf_adjust_dynamic_symbol) (ppc_elf_size_dynamic_sections, ppc_elf_finish_dynamic_symbol) (elf_backend_want_dynrelro): As above. * elf32-s390.c (elf_s390_adjust_dynamic_symbol) (elf_s390_size_dynamic_sections, elf_s390_finish_dynamic_symbol) (elf_backend_want_dynrelro): As above. * elf32-tic6x.c (elf32_tic6x_adjust_dynamic_symbol) (elf32_tic6x_size_dynamic_sections) (elf32_tic6x_finish_dynamic_symbol) (elf_backend_want_dynrelro): As above. * elf32-tilepro.c (tilepro_elf_adjust_dynamic_symbol) (tilepro_elf_size_dynamic_sections) (tilepro_elf_finish_dynamic_symbol) (elf_backend_want_dynrelro): As above. * elf64-ppc.c (ppc64_elf_adjust_dynamic_symbol) (ppc64_elf_size_dynamic_sections, ppc64_elf_finish_dynamic_symbol) (elf_backend_want_dynrelro): As above. * elf64-s390.c (elf_s390_adjust_dynamic_symbol) (elf_s390_size_dynamic_sections, elf_s390_finish_dynamic_symbol) (elf_backend_want_dynrelro): As above. * elf64-x86-64.c (elf_x86_64_adjust_dynamic_symbol) (elf_x86_64_size_dynamic_sections) (elf_x86_64_finish_dynamic_symbol) (elf_backend_want_dynrelro): As above. * elfnn-aarch64.c (elfNN_aarch64_adjust_dynamic_symbol) (elfNN_aarch64_size_dynamic_sections) (elfNN_aarch64_finish_dynamic_symbol) (elf_backend_want_dynrelro): As above. * elfnn-riscv.c (riscv_elf_adjust_dynamic_symbol) (riscv_elf_size_dynamic_sections, riscv_elf_finish_dynamic_symbol) (elf_backend_want_dynrelro): As above. * elfxx-mips.c (_bfd_mips_elf_adjust_dynamic_symbol) (_bfd_mips_elf_size_dynamic_sections) (_bfd_mips_vxworks_finish_dynamic_symbol): As above. * elfxx-sparc.c (_bfd_sparc_elf_adjust_dynamic_symbol) (_bfd_sparc_elf_size_dynamic_sections) (_bfd_sparc_elf_finish_dynamic_symbol): As above. * elfxx-tilegx.c (tilegx_elf_adjust_dynamic_symbol) (tilegx_elf_size_dynamic_sections) (tilegx_elf_finish_dynamic_symbol): As above. * elf32-mips.c (elf_backend_want_dynrelro): Define. * elf64-mips.c (elf_backend_want_dynrelro): Define. * elf32-sparc.c (elf_backend_want_dynrelro): Define. * elf64-sparc.c (elf_backend_want_dynrelro): Define. * elf32-tilegx.c (elf_backend_want_dynrelro): Define. * elf64-tilegx.c (elf_backend_want_dynrelro): Define. * elf32-microblaze.c (microblaze_elf_adjust_dynamic_symbol): Tidy. (microblaze_elf_size_dynamic_sections): Handle sdynbss. * elf32-nios2.c (nios2_elf32_size_dynamic_sections): Make use of linker shortcuts to dynamic sections rather than comparing names. Correctly set "got" flag. ld/ PR ld/20995 * testsuite/ld-arm/farcall-mixed-app-v5.d: Update to suit changed stub hash table traversal caused by section id increment. Accept the previous output too. * testsuite/ld-arm/farcall-mixed-app.d: Likewise. * testsuite/ld-arm/farcall-mixed-lib-v4t.d: Likewise. * testsuite/ld-arm/farcall-mixed-lib.d: Likewise. * testsuite/ld-elf/pr20995a.s, * testsuite/ld-elf/pr20995b.s, * testsuite/ld-elf/pr20995.r: New test. * testsuite/ld-elf/elf.exp: Run it.
Diffstat (limited to 'bfd/elfxx-mips.c')
-rw-r--r--bfd/elfxx-mips.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index 086d537..7c7cd38 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -9129,6 +9129,7 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
bfd *dynobj;
struct mips_elf_link_hash_entry *hmips;
struct mips_elf_link_hash_table *htab;
+ asection *s, *srel;
htab = mips_elf_hash_table (info);
BFD_ASSERT (htab != NULL);
@@ -9371,10 +9372,20 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
both the dynamic object and the regular object will refer to the
same memory location for the variable. */
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->root.sdynrelro;
+ srel = htab->root.sreldynrelro;
+ }
+ else
+ {
+ s = htab->root.sdynbss;
+ srel = htab->root.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
{
if (htab->is_vxworks)
- htab->root.srelbss->size += sizeof (Elf32_External_Rela);
+ srel->size += sizeof (Elf32_External_Rela);
else
mips_elf_allocate_dynamic_relocations (dynobj, info, 1);
h->needs_copy = 1;
@@ -9384,7 +9395,7 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
dynamic will now refer to the local copy instead. */
hmips->possibly_dynamic_relocs = 0;
- return _bfd_elf_adjust_dynamic_copy (info, h, htab->root.sdynbss);
+ return _bfd_elf_adjust_dynamic_copy (info, h, s);
}
/* This function is called after all the input files have been read,
@@ -9906,7 +9917,8 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
&& s != htab->root.sgot
&& s != htab->root.sgotplt
&& s != htab->sstubs
- && s != htab->root.sdynbss)
+ && s != htab->root.sdynbss
+ && s != htab->root.sdynrelro)
{
/* It's not one of our sections, so don't allocate space. */
continue;
@@ -11296,6 +11308,8 @@ _bfd_mips_vxworks_finish_dynamic_symbol (bfd *output_bfd,
if (h->needs_copy)
{
Elf_Internal_Rela rel;
+ asection *srel;
+ bfd_byte *loc;
BFD_ASSERT (h->dynindx != -1);
@@ -11304,11 +11318,13 @@ _bfd_mips_vxworks_finish_dynamic_symbol (bfd *output_bfd,
+ h->root.u.def.value);
rel.r_info = ELF32_R_INFO (h->dynindx, R_MIPS_COPY);
rel.r_addend = 0;
- bfd_elf32_swap_reloca_out (output_bfd, &rel,
- htab->root.srelbss->contents
- + (htab->root.srelbss->reloc_count
- * sizeof (Elf32_External_Rela)));
- ++htab->root.srelbss->reloc_count;
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ srel = htab->root.sreldynrelro;
+ else
+ srel = htab->root.srelbss;
+ loc = srel->contents + srel->reloc_count * sizeof (Elf32_External_Rela);
+ bfd_elf32_swap_reloca_out (output_bfd, &rel, loc);
+ ++srel->reloc_count;
}
/* If this is a mips16/microMIPS symbol, force the value to be even. */