diff options
author | Alan Modra <amodra@gmail.com> | 2016-12-26 00:30:45 +1030 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2016-12-26 13:47:51 +1030 |
commit | 5474d94f03aedba2f832006dc7d680cc15792a7b (patch) | |
tree | 8fdd2bb1d2a32f1f35ef76199f9d92da95c0ec27 /bfd/elf32-nios2.c | |
parent | 9d19e4fdb7c684329c8b1b72796a0071708dabc7 (diff) | |
download | binutils-gdb-5474d94f03aedba2f832006dc7d680cc15792a7b.tar.gz |
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/elf32-nios2.c')
-rw-r--r-- | bfd/elf32-nios2.c | 41 |
1 files changed, 26 insertions, 15 deletions
diff --git a/bfd/elf32-nios2.c b/bfd/elf32-nios2.c index a4ce99c7cd3..541eb6f3489 100644 --- a/bfd/elf32-nios2.c +++ b/bfd/elf32-nios2.c @@ -5275,14 +5275,16 @@ nios2_elf32_finish_dynamic_symbol (bfd *output_bfd, && (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak)); - s = htab->root.srelbss; - BFD_ASSERT (s != NULL); - rela.r_offset = (h->root.u.def.value + h->root.u.def.section->output_section->vma + h->root.u.def.section->output_offset); rela.r_info = ELF32_R_INFO (h->dynindx, R_NIOS2_COPY); rela.r_addend = 0; + if ((h->root.u.def.section->flags & SEC_READONLY) != 0) + s = htab->root.sreldynrelro; + else + s = htab->root.srelbss; + BFD_ASSERT (s != NULL); loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela); bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); } @@ -5441,7 +5443,7 @@ nios2_elf32_adjust_dynamic_symbol (struct bfd_link_info *info, { struct elf32_nios2_link_hash_table *htab; bfd *dynobj; - asection *s; + asection *s, *srel; unsigned align2; htab = elf32_nios2_hash_table (info); @@ -5523,19 +5525,22 @@ nios2_elf32_adjust_dynamic_symbol (struct bfd_link_info *info, determine the address it must put in the global offset table, so both the dynamic object and the regular object will refer to the same memory location for the variable. */ - s = htab->root.sdynbss; - BFD_ASSERT (s != NULL); - /* We must generate a R_NIOS2_COPY reloc to tell the dynamic linker to copy the initial value out of the dynamic object and into the runtime process image. We need to remember the offset into the .rela.bss section we are going to use. */ - if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) + if ((h->root.u.def.section->flags & SEC_READONLY) != 0) { - asection *srel; - + s = htab->root.sdynrelro; + srel = htab->root.sreldynrelro; + } + else + { + s = htab->root.sdynbss; srel = htab->root.srelbss; - BFD_ASSERT (srel != NULL); + } + if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) + { srel->size += sizeof (Elf32_External_Rela); h->needs_copy = 1; } @@ -5975,7 +5980,7 @@ nios2_elf32_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, of the dynobj section names depend upon the input files. */ name = bfd_get_section_name (dynobj, s); - if (strcmp (name, ".plt") == 0) + if (s == htab->root.splt) { /* Remember whether there is a PLT. */ plt = s->size != 0; @@ -5998,9 +6003,14 @@ nios2_elf32_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, s->reloc_count = 0; } } - else if (CONST_STRNEQ (name, ".got")) - got = s->size != 0; - else if (strcmp (name, ".dynbss") != 0) + else if (s == htab->root.sgot + || s == htab->root.sgotplt) + { + if (s->size != 0) + got = TRUE; + } + else if (s != htab->root.sdynbss + && s != htab->root.sdynrelro) /* It's not one of our sections, so don't allocate space. */ continue; @@ -6249,6 +6259,7 @@ const struct bfd_elf_special_section elf32_nios2_special_sections[] = #define elf_backend_can_refcount 1 #define elf_backend_plt_readonly 1 #define elf_backend_want_got_plt 1 +#define elf_backend_want_dynrelro 1 #define elf_backend_rela_normal 1 #define elf_backend_dtrel_excludes_plt 1 |