Bug 22393 - Add read-only segment
Summary: Add read-only segment
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.30
: P2 normal
Target Milestone: 2.30
Assignee: Not yet assigned to anyone
URL:
Keywords:
: 16685 (view as bug list)
Depends on:
Blocks:
 
Reported: 2017-11-03 23:19 UTC by H.J. Lu
Modified: 2018-11-09 16:00 UTC (History)
2 users (show)

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


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description H.J. Lu 2017-11-03 23:19:28 UTC
We currently put read-only sections in read-execute segment:

[hjl@gnu-ivb-1 gcc]$ readelf -lW /bin/ls

Elf file type is DYN (Shared object file)
Entry point 0x51c0
There are 9 program headers, starting at offset 64

Program Headers:
  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
  PHDR           0x000040 0x0000000000000040 0x0000000000000040 0x0001f8 0x0001f8 R E 0x8
  INTERP         0x000238 0x0000000000000238 0x0000000000000238 0x00001c 0x00001c R   0x1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x000000 0x0000000000000000 0x0000000000000000 0x01d84c 0x01d84c R E 0x200000
  LOAD           0x01dfd0 0x000000000021dfd0 0x000000000021dfd0 0x001278 0x002418 RW  0x200000
  DYNAMIC        0x01ea18 0x000000000021ea18 0x000000000021ea18 0x0001e0 0x0001e0 RW  0x8
  NOTE           0x000254 0x0000000000000254 0x0000000000000254 0x000044 0x000044 R   0x4
  GNU_EH_FRAME   0x01a1f4 0x000000000001a1f4 0x000000000001a1f4 0x000824 0x000824 R   0x4
  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x10
  GNU_RELRO      0x01dfd0 0x000000000021dfd0 0x000000000021dfd0 0x001030 0x001030 R   0x1

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .interp 
   02     .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame 
   03     .init_array .fini_array .data.rel.ro .dynamic .got .data .bss 
   04     .dynamic 
   05     .note.ABI-tag .note.gnu.build-id 
   06     .eh_frame_hdr 
   07     
   08     .init_array .fini_array .data.rel.ro .dynamic .got 
[hjl@gnu-ivb-1 gcc]$ 

I'd like to add a read-only segment for read-only sections to prevent
executing data in read-only sections as instructions.
Comment 1 cvs-commit@gcc.gnu.org 2018-01-12 03:04:57 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=47acac12c83f173481debc64618626b50ecf7498

commit 47acac12c83f173481debc64618626b50ecf7498
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Thu Jan 11 19:01:39 2018 -0800

    ld: Add "-z separate-code" option to ELF linker
    
    The new "-z separate-code" option will generate separate code LOAD
    segment which must be in wholly disjoint pages from any other data.
    
    include/
    
    	PR ld/22393
    	* bfdlink.h (bfd_link_info): Add separate_code.
    
    ld/
    
    	PR ld/22393
    	* NEWS: Mention "-z separate-code".
    	* emultempl/elf32.em (gld${EMULATION_NAME}_get_script): Get
    	builtin linker scripts and return linker scripts from disk for
    	"-z separate-code".
    	(gld${EMULATION_NAME}_handle_option): Handle "-z separate-code"
    	and "-z noseparate-code".
    	* genscripts.sh: Generate linker scripts for "-z separate-code".
    	(LD_FLAG): Set to *textonly for "-z separate-code".
    	* ld.texinfo: Document "-z separate-code".
    	* lexsup.c (elf_shlib_list_options): Add linker help messsages
    	for "-z separate-code" and "-z noseparate-code".
    	* scripttempl/elf.sc (SEPARATE_TEXT): New
    	(TEXT_SEGMENT_ALIGN): Likewise.
    	Use ${TEXT_SEGMENT_ALIGN} to align and pad text segment to
    	${MAXPAGESIZE}.
Comment 2 cvs-commit@gcc.gnu.org 2018-01-12 03:17:25 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=2888249fc9eb38b6d6e4bd969ce63c26e3753d5e

commit 2888249fc9eb38b6d6e4bd969ce63c26e3753d5e
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Thu Jan 11 19:04:55 2018 -0800

    ld: Create a new LOAD segment for separate code segment
    
    When generating separate code LOAD segment, create a new LOAD segment
    if the previous section contains text and the current section doesn't
    or vice versa:
    
    Elf file type is DYN (Shared object file)
    Entry point 0x200020
    There are 7 program headers, starting at offset 52
    
    Program Headers:
      Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
      LOAD           0x000000 0x00000000 0x00000000 0x00200 0x00200 R   0x200000
      LOAD           0x200000 0x00200000 0x00200000 0x00036 0x00036 R E 0x200000
      LOAD           0x400000 0x00400000 0x00400000 0x00064 0x00064 R   0x200000
      LOAD           0x400f80 0x00600f80 0x00600f80 0x000a0 0x000a0 RW  0x200000
      DYNAMIC        0x400f80 0x00600f80 0x00600f80 0x00080 0x00080 RW  0x4
      GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x10
      GNU_RELRO      0x400f80 0x00600f80 0x00600f80 0x00080 0x00080 R   0x1
    
     Section to Segment mapping:
      Segment Sections...
       00     .hash .gnu.hash .dynsym .dynstr .rela.plt
       01     .plt .text
       02     .rodata .eh_frame
       03     .dynamic .got.plt
       04     .dynamic
       05
       06     .dynamic
    
    to prevent fetching or executing data in code pages as instructions.
    
    Also don't put a writable section in a read-only segment if there is a
    RELRO segment.
    
    Since code segment is aligned and padded to the maximum page size on
    disk, the minimum file size is bigger than the maximum page size which
    is 2MB (0x200000):
    
    -rwxr-xr-x 1 hjl hjl 4201932 Jan 10 10:41 libfoo.so
    
    "-z max-page-size=0x1000" can be used to reduce the maximum page size to
    4KB (0x1000):
    
    -rwxr-xr-x 1 hjl hjl   15820 Jan 10 10:44 libfoo.so
    
    	PR ld/22393
    	* elf.c (_bfd_elf_map_sections_to_segments): When generating
    	separate code and read-only data LOAD segments, create a new
    	LOAD segment if the previous section contains text and the
    	current section doesn't or vice versa.  Don't put a writable
    	section in a read-only segment if there is a RELRO segment.
Comment 3 cvs-commit@gcc.gnu.org 2018-01-12 03:19:27 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=d346bb277c7f194ece73a7200d1ed6417b1194e5

commit d346bb277c7f194ece73a7200d1ed6417b1194e5
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Thu Jan 11 19:17:46 2018 -0800

    ld: Add tests for -z separate-code and -z noseparate-code
    
    Verify that -z separate-code works and -z noseparate-code doesn't disable
    -z relro.
    
    	PR ld/22393
    	* testsuite/ld-elf/pr16322.d: Add -z noseparate-code.
    	* testsuite/ld-elf/pr22393-1.s: New file.
    	* testsuite/ld-elf/pr22393-1a.d: Likewise.
    	* testsuite/ld-elf/pr22393-1b.d: Likewise.
    	* testsuite/ld-elf/pr22393-1c.d: Likewise.
    	* testsuite/ld-elf/pr22393-1d.d: Likewise.
    	* testsuite/ld-elf/pr22393-1e.d: Likewise.
    	* testsuite/ld-elf/pr22393-1f.d: Likewise.
    	* testsuite/ld-elf/pr22393-2a.c: Likewise.
    	* testsuite/ld-elf/pr22393-2a.rd: Likewise.
    	* testsuite/ld-elf/pr22393-2b.c: Likewise.
    	* testsuite/ld-elf/pr22393-2b.rd: Likewise.
    	* testsuite/ld-elf/shared.exp: Run tests for -z separate-code.
Comment 4 cvs-commit@gcc.gnu.org 2018-01-12 03:21:46 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=cf9e7f1f07efa2ce6846d8a29015dd8fb70197b0

commit cf9e7f1f07efa2ce6846d8a29015dd8fb70197b0
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Thu Jan 11 19:19:22 2018 -0800

    x86-64: Add tests for -z separate-code -z max-page-size=0x1000
    
    	PR ld/22393
    	* testsuite/ld-x86-64/pr22393-3a.c: New file.
    	* testsuite/ld-x86-64/pr22393-3a.rd: Likewise.
    	* testsuite/ld-x86-64/pr22393-3b.c: Likewise.
    	* testsuite/ld-x86-64/pr22393-3b.rd: Likewise.
    	* testsuite/ld-x86-64/x86-64.exp: Run tests for -z separate-code
    	-z max-page-size=0x1000.
Comment 5 H.J. Lu 2018-01-12 03:59:38 UTC
Fixed for 2.30.
Comment 6 H.J. Lu 2018-11-09 14:10:54 UTC
*** Bug 16685 has been marked as a duplicate of this bug. ***
Comment 7 Zack Weinberg 2018-11-09 15:42:26 UTC
Thanks for doing this, H.J.

I'm confused - is -z separate-code the new default or not?  The patch reads like it's not the default, but the demo you posted in #16685 makes it look like it is the default.
Comment 8 H.J. Lu 2018-11-09 15:52:57 UTC
(In reply to Zack Weinberg from comment #7)
> Thanks for doing this, H.J.
> 
> I'm confused - is -z separate-code the new default or not?  The patch reads
> like it's not the default, but the demo you posted in #16685 makes it look
> like it is the default.

It is the default for Linux/x86:

commit f6aec96dce1ddbd8961a3aa8a2925db2021719bb
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Tue Feb 27 11:34:20 2018 -0800

    ld: Add --enable-separate-code
    
    This patch adds --enable-separate-code to ld configure to turn on
    -z separate-code by default and enables it by default for Linux/x86.
    This avoids mixing code pages with data to improve cache performance
    as well as security.
Comment 9 Zack Weinberg 2018-11-09 16:00:50 UTC
OK, thanks for the clarification.