Bug 20995 - Read-only data in ELF libraries may be remapped writable at runtime
Summary: Read-only data in ELF libraries may be remapped writable at runtime
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.28
: P2 normal
Target Milestone: ---
Assignee: Alan Modra
URL:
Keywords:
: 19965 (view as bug list)
Depends on:
Blocks:
 
Reported: 2016-12-26 00:15 UTC by Alan Modra
Modified: 2019-04-10 06:07 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
possible nios2 fix (329 bytes, patch)
2017-02-25 23:10 UTC, Alan Modra
Details | Diff
before/after testcase output (18.72 KB, application/x-compressed-tar)
2017-02-26 00:54 UTC, Sandra Loosemore
Details
hacky patch (298 bytes, patch)
2017-02-26 05:11 UTC, Sandra Loosemore
Details | Diff
Fix for another nios bug (756 bytes, patch)
2017-02-26 05:26 UTC, Alan Modra
Details | Diff
Revised patch (991 bytes, patch)
2017-02-26 05:40 UTC, Alan Modra
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Alan Modra 2016-12-26 00:15:20 UTC
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.
Comment 1 Sourceware Commits 2016-12-26 05:46:48 UTC
The master branch has been updated by Alan Modra <amodra@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=5474d94f03aedba2f832006dc7d680cc15792a7b

commit 5474d94f03aedba2f832006dc7d680cc15792a7b
Author: Alan Modra <amodra@gmail.com>
Date:   Mon Dec 26 00:30:45 2016 +1030

    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.
Comment 2 Sourceware Commits 2016-12-26 07:22:44 UTC
The binutils-2_28-branch branch has been updated by Alan Modra <amodra@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=17026142ef35b62ac88bfe517b4160614902cb28

commit 17026142ef35b62ac88bfe517b4160614902cb28
Author: Alan Modra <amodra@gmail.com>
Date:   Mon Dec 26 00:30:45 2016 +1030

    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.
Comment 3 Sourceware Commits 2016-12-28 04:51:51 UTC
The master branch has been updated by Cary Coutant <ccoutant@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=b733bcb7f58c42e0e0d94a3f266a4193030e5f3a

commit b733bcb7f58c42e0e0d94a3f266a4193030e5f3a
Author: Cary Coutant <ccoutant@gmail.com>
Date:   Tue Dec 27 20:50:47 2016 -0800

    Place copy relocations in .dynbss when target is read-only.
    
    gold/
    	PR ld/20995
    	* copy-relocs.cc (Copy_relocs::make_copy_reloc): Use .dynbss for
    	read-only data when linking with -z relro.
    	* copy-relocs.h (Copy_relocs::dynrelro_): New data member.
    	* testsuite/Makefile.am (copy_test_relro): New test case.
    	* testsuite/Makefile.in: Regenerate.
    	* testsuite/copy_test_relro.cc: New source file.
    	* testsuite/copy_test_relro_1.cc: New source file.
Comment 4 Sourceware Commits 2016-12-28 04:57:39 UTC
The binutils-2_28-branch branch has been updated by Cary Coutant <ccoutant@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=a08db921c967484bbd4fb66ca2648548866cba59

commit a08db921c967484bbd4fb66ca2648548866cba59
Author: Cary Coutant <ccoutant@gmail.com>
Date:   Tue Dec 27 20:50:47 2016 -0800

    Place copy relocations in .dynbss when target is read-only.
    
    gold/
    	PR ld/20995
    	* copy-relocs.cc (Copy_relocs::make_copy_reloc): Use .dynbss for
    	read-only data when linking with -z relro.
    	* copy-relocs.h (Copy_relocs::dynrelro_): New data member.
    	* testsuite/Makefile.am (copy_test_relro): New test case.
    	* testsuite/Makefile.in: Regenerate.
    	* testsuite/copy_test_relro.cc: New source file.
    	* testsuite/copy_test_relro_1.cc: New source file.
Comment 5 Sourceware Commits 2016-12-28 12:13:09 UTC
The master branch has been updated by Alan Modra <amodra@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=9acc85a62eb76c270724bba15c889d2d05567b6a

commit 9acc85a62eb76c270724bba15c889d2d05567b6a
Author: Alan Modra <amodra@gmail.com>
Date:   Wed Dec 28 17:04:15 2016 +1030

    Use dynrelro for symbols in relro sections too
    
    	PR ld/20995
    bfd/
    	* elflink.c (elf_link_add_object_symbols): Mark relro sections
    	in dynamic objects SEC_READONLY.
    ld/
    	* testsuite/ld-elf/pr20995c.s: New test file.
    	* testsuite/ld-elf/pr20995-2so.r: Likewise.
    	* testsuite/ld-elf/elf.exp: Run it.
Comment 6 Sourceware Commits 2016-12-28 13:37:30 UTC
The binutils-2_28-branch branch has been updated by Alan Modra <amodra@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=b9f351d14e9862d3521c24820671e6531d604364

commit b9f351d14e9862d3521c24820671e6531d604364
Author: Alan Modra <amodra@gmail.com>
Date:   Wed Dec 28 17:04:15 2016 +1030

    Use dynrelro for symbols in relro sections too
    
    	PR ld/20995
    bfd/
    	* elflink.c (elf_link_add_object_symbols): Mark relro sections
    	in dynamic objects SEC_READONLY.
    ld/
    	* testsuite/ld-elf/pr20995c.s: New test file.
    	* testsuite/ld-elf/pr20995-2so.r: Likewise.
    	* testsuite/ld-elf/elf.exp: Run it.
Comment 7 H.J. Lu 2017-01-12 17:33:26 UTC
*** Bug 19965 has been marked as a duplicate of this bug. ***
Comment 8 Sourceware Commits 2017-01-18 23:26:57 UTC
The binutils-2_28-branch branch has been updated by Maciej W. Rozycki <macro@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=13338f4e1bdb2dbee5f767b47d192f68d411d5ab

commit 13338f4e1bdb2dbee5f767b47d192f68d411d5ab
Author: Maciej W. Rozycki <macro@imgtec.com>
Date:   Wed Jan 18 18:07:58 2017 +0000

    PR ld/20995: MIPS: Set GAS flags correctly for tests
    
    Complement commit 9acc85a62eb7 ("Use dynrelro for symbols in relro
    sections too").
    
    	ld/
    	PR ld/20995
    	* testsuite/ld-elf/elf.exp: Set GAS flags correctly for the
    	`mips*-*-*' target and `pr20995' and `pr20995-2' tests.
    
    (cherry picked from commit 6984613a53528c818482c3a531e17a86bac6e7dc)
Comment 9 Sourceware Commits 2017-01-18 23:43:03 UTC
The master branch has been updated by Maciej W. Rozycki <macro@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=6984613a53528c818482c3a531e17a86bac6e7dc

commit 6984613a53528c818482c3a531e17a86bac6e7dc
Author: Maciej W. Rozycki <macro@imgtec.com>
Date:   Wed Jan 18 18:07:58 2017 +0000

    PR ld/20995: MIPS: Set GAS flags correctly for tests
    
    Complement commit 9acc85a62eb7 ("Use dynrelro for symbols in relro
    sections too").
    
    	ld/
    	PR ld/20995
    	* testsuite/ld-elf/elf.exp: Set GAS flags correctly for the
    	`mips*-*-*' target and `pr20995' and `pr20995-2' tests.
Comment 10 Christophe Lyon 2017-01-23 09:24:16 UTC
As I reported on the mailing-list, 2 of the new tests fail on arm-netbsdelf and arm-none-eabi:
FAIL: Build pr20995-2.so
FAIL: pr20995-2
Comment 11 Alan Modra 2017-01-24 02:45:46 UTC
I deliberately left the arm FAILs showing.  They are telling you that -z relro does not wotk on those target variants.  That should probably be fixed.
Comment 12 Jiong Wang 2017-01-25 14:45:20 UTC
(In reply to Alan Modra from comment #11)
> I deliberately left the arm FAILs showing.  They are telling you that -z
> relro does not wotk on those target variants.  That should probably be fixed.

Reading the comment at https://sourceware.org/ml/binutils/2017-01/msg00094.html, I feel we should define COMMONPAGESIZE for arm-none-eabi, searching src/bfd and src/ld, the only usage of it is to initialize config.commonpagesize which is later used to expand "CONSTANT (COMMONPAGESIZE)" when COMMONPAGESIZE is used in linker script which only play a role when calculating relro_end.

If the runtime doesn't support GNU_RELRO, then I looks to me the user is responsible to make sure don't pass -z relro to the linker.
Comment 13 Jiong Wang 2017-01-25 16:52:20 UTC
(In reply to Jiong Wang from comment #12)
> (In reply to Alan Modra from comment #11)
> > I deliberately left the arm FAILs showing.  They are telling you that -z
> > relro does not wotk on those target variants.  That should probably be fixed.
> 
> Reading the comment at
> https://sourceware.org/ml/binutils/2017-01/msg00094.html, I feel we should
> define COMMONPAGESIZE for arm-none-eabi, searching src/bfd and src/ld, the
> only usage of it is to initialize config.commonpagesize which is later used
> to expand "CONSTANT (COMMONPAGESIZE)" when COMMONPAGESIZE is used in linker
> script which only play a role when calculating relro_end.
> 
> If the runtime doesn't support GNU_RELRO, then I looks to me the user is
> responsible to make sure don't pass -z relro to the linker.

Hmm, but my testing shows define this will waste disk and mem size.... as there will be ". = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));" after data segment.
Comment 14 Alan Modra 2017-01-26 13:21:02 UTC
If you define COMMONPAGESIZE, yes, you may waste up to COMMONPAGESIZE extra on disk in order to *save* memory pages.

To see this, imagine a system where memory pages are 16k and disk pages are 4k.  Consider a binary with 15k of text and 5k of data.  The classic layout puts data adjacent to text on disk, thus taking 20k of disk.  In memory text occupies one page covering base address b to b+15k, while data starts at b+15k+16k.  This means data takes two 16k memory pages.  If we add a gap of 1k between text and data, then data only takes one 16k memory page but we now have 21k on disk, or one extra disk page.
Comment 15 Jiong Wang 2017-01-26 14:32:44 UTC
(In reply to Alan Modra from comment #14)
> If you define COMMONPAGESIZE, yes, you may waste up to COMMONPAGESIZE extra
> on disk in order to *save* memory pages.
> 
> To see this, imagine a system where memory pages are 16k and disk pages are
> 4k.  Consider a binary with 15k of text and 5k of data.  The classic layout
> puts data adjacent to text on disk, thus taking 20k of disk.  In memory text
> occupies one page covering base address b to b+15k, while data starts at
> b+15k+16k.  This means data takes two 16k memory pages.  If we add a gap of
> 1k between text and data, then data only takes one 16k memory page but we
> now have 21k on disk, or one extra disk page.

Thanks for the explanation. I kind of understanding this as caused by remapping of the page which cross text and data twice for different permission.
Comment 16 Sourceware Commits 2017-01-27 00:51:06 UTC
The master branch has been updated by Hans-Peter Nilsson <hp@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=1fbd05e16ebde966e44c1108dc77871f3fba329a

commit 1fbd05e16ebde966e44c1108dc77871f3fba329a
Author: Hans-Peter Nilsson <hp@bitrange.com>
Date:   Fri Jan 27 01:50:06 2017 +0100

    Fix PR ld/20995 for cris-linux
    
    	PR ld/20995
    	* elf32-cris.c (elf_cris_size_dynamic_sections): Handle sdynrelro.
    	(elf_cris_adjust_dynamic_symbol): Place variables copied into the
    	executable from read-only sections into sdynrelro.
    	(elf_cris_finish_dynamic_symbol): Select sreldynrelro for
    	dynamic relocs in sdynrelro.
    	(elf_backend_want_dynrelro): Define.
Comment 17 Sourceware Commits 2017-02-03 01:01:21 UTC
The binutils-2_28-branch branch has been updated by Hans-Peter Nilsson <hp@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=4f73293264a46b8bd15c49ed86044b57f2531d8e

commit 4f73293264a46b8bd15c49ed86044b57f2531d8e
Author: Hans-Peter Nilsson <hp@bitrange.com>
Date:   Fri Feb 3 01:23:16 2017 +0100

    Fix PR ld/20995 for cris-linux
    
    	* elf32-cris.c (elf_cris_finish_dynamic_symbol): Remove now unused
    	local variable dynobj.
    
    	PR ld/20995
    	* elf32-cris.c (elf_cris_size_dynamic_sections): Handle sdynrelro.
    	(elf_cris_adjust_dynamic_symbol): Place variables copied into the
    	executable from read-only sections into sdynrelro.
    	(elf_cris_finish_dynamic_symbol): Select sreldynrelro for
    	dynamic relocs in sdynrelro.
    	(elf_backend_want_dynrelro): Define.
Comment 18 Sandra Loosemore 2017-02-25 17:47:56 UTC
Just a heads up: I'm seeing the dynamic linker crashing with a SEGV on nios2-linux-gnu on binaries linked with commit 5474d94f03aedba2f832006dc7d680cc15792a7b and later.  I'm still investigating to see if the problem is in binutils or glibc.
Comment 19 Alan Modra 2017-02-25 23:10:52 UTC
Created attachment 9855 [details]
possible nios2 fix

Sandra, looking over my patch again, I think it is most likely this hunk.

-      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)

The CONST_STRNEQ matches both .got and .got.plt and I thought it was a bug that the "got" flag could be set on finding a non-zero size .got section present then cleared the next time around the loop on finding a zero size .got.plt.  Or vice versa.  My guess at the time was that you wanted "got" set (results in DT_PLTGOT) for either section, but it's possible you only want it set for .got.plt.  If so then it was indeed a bug that the name compare matched both .got and .got.plt, but I fixed it the wrong way..
Comment 20 Sandra Loosemore 2017-02-26 00:54:25 UTC
Created attachment 9856 [details]
before/after testcase output
Comment 21 Sandra Loosemore 2017-02-26 01:01:55 UTC
Nope, that's not it.  I've attached a tarball with good/bad executables (from commits 9d19e4fdb7c684329c8b1b72796a0071708dabc7 and 5474d94f03aedba2f832006dc7d680cc15792a7b, respectively) and corresponding readelf -a and objdump -x output.

And, here is some more information on the dynamic linker crash.

Program received signal SIGSEGV, Segmentation fault.
_dl_relocate_object (scope=0x2aac85b0, reloc_mode=<optimized out>, 
    consider_profiling=consider_profiling@entry=0) at dl-reloc.c:232
232	    const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
(gdb) bt
#0  _dl_relocate_object (scope=0x2aac85b0, reloc_mode=<optimized out>, 
    consider_profiling=consider_profiling@entry=0) at dl-reloc.c:232
#1  0x2aaaaee0 in dl_main (phdr=<optimized out>, phnum=<optimized out>, 
    user_entry=<optimized out>, auxv=<optimized out>) at rtld.c:2051
#2  0x2aabcb6c in _dl_sysdep_start (
    start_argptr=start_argptr@entry=0x7ffefa70, 
    dl_main=dl_main@entry=0x2aaa9280 <dl_main>) at ../elf/dl-sysdep.c:253
#3  0x2aaac148 in _dl_start_final (arg=arg@entry=0x7ffefa70, 
    info=info@entry=0x7ffef7f0) at rtld.c:305
#4  0x2aaac448 in _dl_start (arg=0x7ffefa70) at rtld.c:413
#5  0x2aaa8bf0 in _start ()
   from target:/scratch/sandra/nios2-linux-upstream/install/nios2-linux-gnu/libc/lib/ld-linux-nios2.so.1
(gdb) frame 1
#1  0x2aaaaee0 in dl_main (phdr=<optimized out>, phnum=<optimized out>, 
    user_entry=<optimized out>, auxv=<optimized out>) at rtld.c:2051
2051		    _dl_relocate_object (l, l->l_scope, GLRO(dl_lazy) ? RTLD_LAZY : 0,
(gdb) print *l
$1 = {l_addr = 0, l_name = 0x2aac86d8 "", l_ld = 0x3f20, l_next = 0x0, 
  l_prev = 0x0, l_real = 0x2aac83f8, l_ns = 0, l_libname = 0x2aac86cc, 
  l_info = {0x0 <repeats 76 times>}, l_phdr = 0x2034, l_entry = 9612, 
  l_phnum = 9, l_ldnum = 0, l_searchlist = {r_list = 0x2aac8990, r_nlist = 1}, 
  l_symbolic_searchlist = {r_list = 0x2aac86c8, r_nlist = 0}, l_loader = 0x0, 
  l_versions = 0x0, l_nversions = 0, l_nbuckets = 0, 
  l_gnu_bitmask_idxbits = 0, l_gnu_shift = 0, l_gnu_bitmask = 0x0, {
    l_gnu_buckets = 0x0, l_chain = 0x0}, {l_gnu_chain_zero = 0x0, 
    l_buckets = 0x0}, l_direct_opencount = 1, l_type = lt_executable, 
  l_relocated = 0, l_init_called = 0, l_global = 1, l_reserved = 0, 
  l_phdr_allocated = 0, l_soname_added = 0, l_faked = 0, l_need_tls_init = 0, 
  l_auditing = 0, l_audit_any_plt = 0, l_removed = 0, l_contiguous = 0, 
  l_symbolic_in_local_scope = 0, l_free_initfini = 0, l_rpath_dirs = {
    dirs = 0xffffffff, malloced = 0}, l_reloc_result = 0x0, l_versyms = 0x0, 
  l_origin = 0x0, l_map_start = 8192, l_map_end = 16476, l_text_end = 10488, 
  l_scope_mem = {0x2aac8554, 0x0, 0x0, 0x0}, l_scope_max = 4, 
  l_scope = 0x2aac85b0, l_local_scope = {0x2aac8554, 0x0}, l_file_id = {
    dev = 0, ino = 0}, l_runpath_dirs = {dirs = 0xffffffff, malloced = 0}, 
  l_initfini = 0x2aac8988, l_reldeps = 0x0, l_reldepsmax = 0, l_used = 1, 
  l_feature_1 = 0, l_flags_1 = 0, l_flags = 0, l_idx = 0, 
  l_mach = {<No data fields>}, l_lookup_cache = {sym = 0x0, type_class = 0, 
    value = 0x0, ret = 0x0}, l_tls_initimage = 0x0, l_tls_initimage_size = 0, 
  l_tls_blocksize = 0, l_tls_align = 0, l_tls_firstbyte_offset = 0, 
  l_tls_offset = -1, l_tls_modid = 0, l_tls_dtor_count = 0, 
  l_relro_addr = 16144, l_relro_size = 240, l_serial = 0, l_audit = 0x2aac8648}
(gdb) print *(l->l_ld)
$2 = {d_tag = 0, d_un = {d_val = 0, d_ptr = 0}}
(gdb) 

So, the dynamic linker has only an empty entry in the dynamic section l->l_ld, the contents of l->l_info are all zeros because it's not finding anything to initialize them with, and it's getting the SEGV trying to dereference a null pointer out of this array.  I'm still working backwards trying to find where l->ld is supposed to be getting its contents.
Comment 22 Alan Modra 2017-02-26 03:40:54 UTC
This is weird.
  LOAD           0x001f20 0x00003f20 0x00003f20 0x00000 0x00000 RW  0x1000

A zero length PT_LOAD?

Corresponds to
[18] .data.rel.ro      PROGBITS        00003f20 001f20 000000 00  WA  0   0  1

So why didn't that get removed by strip_excluded_output_sections?
Comment 23 Sandra Loosemore 2017-02-26 05:11:48 UTC
Created attachment 9857 [details]
hacky patch

Hmmm.  I get a working program with the attached patch.  No clue whether this is a correct general solution, though.

It's curious that a zero-length section causes such an apparently unrelated failure in the dynamic linker.  Something is probably not as robust as it should be there.
Comment 24 Alan Modra 2017-02-26 05:18:22 UTC
No, that patch doesn't look good.  SEC_EXCLUDE ought to be set for htab->root.sdynrelro in nios2_elf32_size_dynamic_sections!
Comment 25 Alan Modra 2017-02-26 05:26:57 UTC
Created attachment 9858 [details]
Fix for another nios bug

At a guess, you're getting dynamic sections attached to different input bfds, due to a bug in check_relocs.
Comment 26 Alan Modra 2017-02-26 05:40:23 UTC
Created attachment 9859 [details]
Revised patch

I missed another place where htab->root.dynobj needs to be set.
Comment 27 Alan Modra 2017-02-26 05:43:55 UTC
I'm also a little curious as to why nios2_elf32_create_dynamic_sections is called in check_relocs when the comment says "Create the .got section".  Why not just create_got_section?
Comment 28 Sandra Loosemore 2017-02-26 20:54:08 UTC
The revised patch produces a failing executable identical to the bad one.  I haven't had time to dig further yet.
Comment 29 Alan Modra 2017-02-26 21:15:21 UTC
Please attach the object files necessary to build your testcase and I'll find out where the linker is going wrong.
Comment 30 Sourceware Commits 2017-02-28 02:54:02 UTC
The master branch has been updated by Alan Modra <amodra@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=4ef97a1b459849ad190244c36b36d45bdd078030

commit 4ef97a1b459849ad190244c36b36d45bdd078030
Author: Alan Modra <amodra@gmail.com>
Date:   Tue Feb 28 10:38:51 2017 +1030

    Nios2 dynobj handling fixes
    
    A number of places in elf32-nios.c created dynamic sections but didn't
    set the hash table dynobj.  That meant we could have duplicate dynamic
    sections connected to a number of bfds, so size_dynamic_sections
    didn't properly discard or allocate contents.
    
    Also, the entire set of dynamic sections was created in check_relocs
    on seeing GOT relocs, when only .got related sections are needed,
    probably done to hide segfaults later in finish_dynamic_sections.
    
    The patch fixes these issues and makes the assembler emit errors when
    nios2 lacks the necessary pc-relative relocs for subtraction
    expressions, rather than silently generating bad code.
    eg. ld-elf/merge.  I've also tidied uses of elf32_nios2_hash_table and
    elf_hash_table.
    
    bfd/
    	PR 20995
    	* elf32-nios2.c (nios2_elf32_relocate_section): Use htab
    	rather than elf32_nios2_hash_table or elf_hash_table.
    	(create_got_section): Likewise.
    	(nios2_elf32_finish_dynamic_symbol): Likewise.
    	(nios2_elf32_adjust_dynamic_symbol): Likewise.
    	(nios2_elf32_size_dynamic_sections): Likewise.
    	(nios2_elf32_check_relocs): Delete dynobj, sgot, and srelgot
    	vars.  Use htab equivalents directly instead.  Don't create
    	all dynamic sections on needing just the GOT.  Use a goto
    	rather than a fall-through with reloc test.  Ensure
    	htab->dynobj is set when making dynamic sreloc section.
    	(nios2_elf32_finish_dynamic_sections): Delete dynobj, use htab
    	equivalent directly instead.  Don't segfault on looking for
    	.dynamic when dynamic sections have not been created.  Don't
    	segfault on .got.plt being discarded.
    	(nios2_elf32_size_dynamic_sections): Delete plt and got vars.
    	Don't set "relocs" on .rela.plt.  Do handle .sbss.  Delete
    	fixme and another not so relevant comment.
    	(nios2_elf_add_symbol_hook): Delete dynobj var.  If not
    	already set, set hash table dynobj on creating .sbss.
    gas/
    	* config/tc-nios2.h (TC_FORCE_RELOCATION_SUB_LOCAL): Define.
    ld/
    	* testsuite/ld-elf/merge.d: xfail for nios.
Comment 31 Sourceware Commits 2017-02-28 20:53:50 UTC
The binutils-2_28-branch branch has been updated by Alan Modra <amodra@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=cc6b110b92572318bd32acf914b0fce9c4bb0a6f

commit cc6b110b92572318bd32acf914b0fce9c4bb0a6f
Author: Alan Modra <amodra@gmail.com>
Date:   Tue Feb 28 10:38:51 2017 +1030

    Nios2 dynobj handling fixes
    
    A number of places in elf32-nios.c created dynamic sections but didn't
    set the hash table dynobj.  That meant we could have duplicate dynamic
    sections connected to a number of bfds, so size_dynamic_sections
    didn't properly discard or allocate contents.
    
    Also, the entire set of dynamic sections was created in check_relocs
    on seeing GOT relocs, when only .got related sections are needed,
    probably done to hide segfaults later in finish_dynamic_sections.
    
    The patch fixes these issues and makes the assembler emit errors when
    nios2 lacks the necessary pc-relative relocs for subtraction
    expressions, rather than silently generating bad code.
    eg. ld-elf/merge.  I've also tidied uses of elf32_nios2_hash_table and
    elf_hash_table.
    
    bfd/
    	PR 20995
    	* elf32-nios2.c (nios2_elf32_relocate_section): Use htab
    	rather than elf32_nios2_hash_table or elf_hash_table.
    	(create_got_section): Likewise.
    	(nios2_elf32_finish_dynamic_symbol): Likewise.
    	(nios2_elf32_adjust_dynamic_symbol): Likewise.
    	(nios2_elf32_size_dynamic_sections): Likewise.
    	(nios2_elf32_check_relocs): Delete dynobj, sgot, and srelgot
    	vars.  Use htab equivalents directly instead.  Don't create
    	all dynamic sections on needing just the GOT.  Use a goto
    	rather than a fall-through with reloc test.  Ensure
    	htab->dynobj is set when making dynamic sreloc section.
    	(nios2_elf32_finish_dynamic_sections): Delete dynobj, use htab
    	equivalent directly instead.  Don't segfault on looking for
    	.dynamic when dynamic sections have not been created.  Don't
    	segfault on .got.plt being discarded.
    	(nios2_elf32_size_dynamic_sections): Delete plt and got vars.
    	Don't set "relocs" on .rela.plt.  Do handle .sbss.  Delete
    	fixme and another not so relevant comment.
    	(nios2_elf_add_symbol_hook): Delete dynobj var.  If not
    	already set, set hash table dynobj on creating .sbss.
    gas/
    	* config/tc-nios2.h (TC_FORCE_RELOCATION_SUB_LOCAL): Define.
    ld/
    	* testsuite/ld-elf/merge.d: xfail for nios.
Comment 32 Sourceware Commits 2019-04-08 20:56:17 UTC
The master branch has been updated by H.J. Lu <hjl@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=c93c0e7f3f21f809d9390e2e7096f7e2cb8334e2

commit c93c0e7f3f21f809d9390e2e7096f7e2cb8334e2
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Mon Apr 8 13:54:20 2019 -0700

    XFAIL PR ld/20995 tests for lynxos and nto targets
    
    lynxos and nto targets don't support RELRO.
    
    	* testsuite/ld-elf/shared.exp: XFAIL PR ld/20995 tests for
    	lynxos and nto targets.
Comment 33 Sourceware Commits 2019-04-10 06:07:10 UTC
The master branch has been updated by Alan Modra <amodra@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=e6aded7c34054a2eea55ec56ca3b997ddd0197cf

commit e6aded7c34054a2eea55ec56ca3b997ddd0197cf
Author: Alan Modra <amodra@gmail.com>
Date:   Wed Apr 10 15:30:37 2019 +0930

    Re: XFAIL PR ld/20995 tests for lynxos and nto targets
    
    	* testsuite/ld-elf/shared.exp: Don't xfail PR ld/20995 for
    	powerpc-nto.