Bug 207631 - rtld requires the first PT_LOAD segment to be .text and is incompatible with output produced by lld
Summary: rtld requires the first PT_LOAD segment to be .text and is incompatible with ...
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: misc (show other bugs)
Version: CURRENT
Hardware: Any Any
: --- Affects Only Me
Assignee: freebsd-bugs (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-03-01 23:50 UTC by Ed Maste
Modified: 2016-03-21 17:45 UTC (History)
1 user (show)

See Also:
emaste: mfc-stable10+
emaste: mfc-stable9-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ed Maste freebsd_committer freebsd_triage 2016-03-01 23:50:45 UTC
The first PT_LOAD segment is traditionally mapped with R+X permission and contains the .text section. rtld assumes this is the case and the temporarily maps this segment RWX while applying non-plt relocations.

The LLVM linker lld currently puts .rodata in the first PT_LOAD with only R permission and .text in the second PT_LOAD with RX.

rtld then segfaults while trying to apply relocations to .text which has not been updated with write permission.
Comment 1 Ed Maste freebsd_committer freebsd_triage 2016-03-02 03:58:05 UTC
For reference here is the segment layout currently produced by lld:

% readelf -l bin/sh

Elf file type is EXEC (Executable file)
Entry point 0x19000
There are 10 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000010040 0x0000000000010040
                 0x0000000000000230 0x0000000000000230  R      8
  INTERP         0x0000000000000270 0x0000000000010270 0x0000000000010270
                 0x0000000000000015 0x0000000000000015  R      1
      [Requesting program interpreter: /libexec/ld-elf.so.1]
  LOAD           0x0000000000000000 0x0000000000010000 0x0000000000010000
                 0x000000000000875c 0x000000000000875c  R      1000
  LOAD           0x0000000000009000 0x0000000000019000 0x0000000000019000
                 0x000000000001b220 0x000000000001b220  R E    1000
  LOAD           0x0000000000025000 0x0000000000035000 0x0000000000035000
                 0x0000000000001500 0x0000000000003a50  RW     1000
  DYNAMIC        0x0000000000025028 0x0000000000035028 0x0000000000035028
                 0x0000000000000130 0x0000000000000130  RW     8
  GNU_RELRO      0x0000000000025000 0x0000000000035000 0x0000000000035000
                 0x0000000000000160 0x0000000000000160  R      1
  GNU_EH_FRAME   0x0000000000007f18 0x0000000000017f18 0x0000000000017f18
                 0x0000000000000844 0x0000000000000844  R      1
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0
  NOTE           0x0000000000000288 0x0000000000010288 0x0000000000010288
                 0x0000000000000030 0x0000000000000030  R      4

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .interp 
   02     .interp .note.tag .rodata .eh_frame .rodata .rodata .rodata .dynsym .gnu.hash .hash .dynstr .rela.dyn .rela.plt .eh_frame_hdr 
   03     .text .init .fini .plt 
   04     .ctors .dtors .jcr .dynamic .got .data .got.plt .bss 
   05     .dynamic 
   06     .ctors .dtors .jcr .dynamic .got 
   07     .eh_frame_hdr 
   08     
   09     .note.tag
Comment 2 Ed Maste freebsd_committer freebsd_triage 2016-03-02 15:39:37 UTC
See also https://llvm.org/pr26813 for the llvm issue that results in the .text relocations in the first place.
Comment 3 Shawn Webb 2016-03-02 15:41:53 UTC
(In reply to Ed Maste from comment #2)

That link 404's for me.

By the way, if you need/want help in developing or testing a patch, let me know.
Comment 4 Ed Maste freebsd_committer freebsd_triage 2016-03-02 15:44:23 UTC
Sorry correct link is http://llvm.org/pr26813
Comment 5 commit-hook freebsd_committer freebsd_triage 2016-03-02 16:37:17 UTC
A commit references this bug:

Author: kib
Date: Wed Mar  2 16:36:25 UTC 2016
New revision: 296319
URL: https://svnweb.freebsd.org/changeset/base/296319

Log:
  Fix handling of DT_TEXTREL for an object with more than one read-only
  segment.  According to gABI spec, presence of the tag indicates that
  dynamic linker must be prepared to handle relocations against any
  read-only segment, not only the segment which we, somewhat arbitrary,
  declared the text.

  For each read-only segment, add write permission before relocs are
  processed, and return to the mapping mode requested by the phdr, after
  relocs are done.

  Reported, tested, and reviewed by:	emaste
  PR:	207631
  Sponsored by:	The FreeBSD Foundation
  MFC after:	2 weeks

Changes:
  head/libexec/rtld-elf/map_object.c
  head/libexec/rtld-elf/rtld.c
  head/libexec/rtld-elf/rtld.h
Comment 6 Ed Maste freebsd_committer freebsd_triage 2016-03-02 16:49:34 UTC
> By the way, if you need/want help in developing or testing a patch, let me know.

Thanks for the offer; kib@ had a patch ready pretty quickly to test out.
Comment 7 commit-hook freebsd_committer freebsd_triage 2016-03-16 15:35:15 UTC
A commit references this bug:

Author: kib
Date: Wed Mar 16 15:34:16 UTC 2016
New revision: 296939
URL: https://svnweb.freebsd.org/changeset/base/296939

Log:
  MFC r296319:
  Fix handling of DT_TEXTREL for an object with more than one read-only
  segment.

  PR:	207631

Changes:
_U  stable/10/
  stable/10/libexec/rtld-elf/map_object.c
  stable/10/libexec/rtld-elf/rtld.c
  stable/10/libexec/rtld-elf/rtld.h
Comment 8 Ed Maste freebsd_committer freebsd_triage 2016-03-21 17:45:13 UTC
No need to merge to stable/9 as new toolchain experiments that prompted this are not relevant there.