This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug libc/1346] New: _dl_map_object_from_fd removes data segment execute permission


With HAVE_Z_RELRO defined, if _dl_map_object_from_fd decides that it needs to
make the stack executable, and therefore modify __stack_prot, it unconditionally
changes the protection on the page containing __stack_prot, without checking
that that page is entirely contained within the .rel.ro region.

I hit this when using a ppc64 kernel with a 64kB page size (which the ppc32 and
ppc64 ABIs allow).  The symptom is that getty segfaults after the user enters
the username.

The linker tries to ensure that there is nothing else in the same 4k page as the
.rel.ro sections, but with 64k pages, we ended up with __stack_prot in the same
page as the GOT.  Since the ppc32 ABI currently uses a bl to GOT-4 to get the
address of the GOT (and has a blrl instruction at GOT-4), the __mprotect call in
_dl_map_object_from_fd meant that the process segfaulted as soon as a function
tried to get the GOT address.  This meant that getty segfaulted inside
ld-2.3.5.so when trying to load libcap.so.1, with pc == GOT-4 and lr ==
_dl_check_caller + 12.

Here is the output from readelf -Sl /lib/ld-2.3.5.so:

There are 22 section headers, starting at offset 0x18c3c:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .hash             HASH            000000f4 0000f4 0000dc 04   A  2   0  4
  [ 2] .dynsym           DYNSYM          000001d0 0001d0 000240 10   A  3  10  4
  [ 3] .dynstr           STRTAB          00000410 000410 00017f 00   A  0   0  1
  [ 4] .gnu.version      VERSYM          00000590 000590 000048 02   A  2   0  2
  [ 5] .gnu.version_d    VERDEF          000005d8 0005d8 0000a4 00   A  3   5  4
  [ 6] .rela.dyn         RELA            0000067c 00067c 00165c 0c   A  2   0  4
  [ 7] .rela.plt         RELA            00001cd8 001cd8 00003c 0c   A  2  18  4
  [ 8] .text             PROGBITS        00001d20 001d20 012430 00  AX  0   0 32
  [ 9] .rodata           PROGBITS        00014150 014150 003288 00   A  0   0  4
  [10] .eh_frame_hdr     PROGBITS        000173d8 0173d8 00004c 00   A  0   0  4
  [11] .eh_frame         PROGBITS        00017424 017424 000150 00   A  0   0  4
  [12] .data.rel.ro      PROGBITS        00027e5c 017e5c 0000f4 00  WA  0   0  4
  [13] .dynamic          DYNAMIC         00027f50 017f50 0000b0 08  WA  3   0  4
  [14] .data             PROGBITS        00028000 018000 000000 00  WA  0   0  1
  [15] .got              PROGBITS        00028000 018000 00073c 04 WAX  0   0  4
  [16] .sdata            PROGBITS        00028740 018740 000430 00  WA  0   0  8
  [17] .sbss             NOBITS          00028b70 018b70 00007c 00  WA  0   0  4
  [18] .plt              NOBITS          00028bec 018b70 000084 00 WAX  0   0  4
  [19] .bss              NOBITS          00028c70 018b70 000030 00  WA  0   0  4
  [20] .gnu_debuglink    PROGBITS        00000000 018b70 000010 00      0   0  1
  [21] .shstrtab         STRTAB          00000000 018b80 0000b9 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

Elf file type is DYN (Shared object file)
Entry point 0x1046c
There are 6 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x00000000 0x00000000 0x17574 0x17574 R E 0x10000
  LOAD           0x017e5c 0x00027e5c 0x00027e5c 0x00d14 0x00e44 RWE 0x10000
  DYNAMIC        0x017f50 0x00027f50 0x00027f50 0x000b0 0x000b0 RW  0x4
  GNU_EH_FRAME   0x0173d8 0x000173d8 0x000173d8 0x0004c 0x0004c R   0x4
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x4
  GNU_RELRO      0x017e5c 0x00027e5c 0x00027e5c 0x001a4 0x001a4 R E 0x4

 Section to Segment mapping:
  Segment Sections...
   00     .hash .dynsym .dynstr .gnu.version .gnu.version_d .rela.dyn .rela.plt
.text .rodata .eh_frame_hdr .eh_frame 
   01     .data.rel.ro .dynamic .got .sdata .sbss .plt .bss 
   02     .dynamic 
   03     .eh_frame_hdr 
   04     
   05     .data.rel.ro .dynamic 

The address of __stack_prot in the process image is 0xf7ff7f24 when ld-2.3.5.so
is loaded at 0xf7fd0000, i.e. offset 0x27f24, in the .data.rel.ro region.  The
last thing in an strace before the segfault is:

mprotect(0xf7ff0000, 32552, PROT_READ|PROT_WRITE) = 0

-- 
           Summary: _dl_map_object_from_fd removes data segment execute
                    permission
           Product: glibc
           Version: 2.3.5
            Status: NEW
          Severity: normal
          Priority: P2
         Component: libc
        AssignedTo: gotom at debian dot or dot jp
        ReportedBy: paulus at samba dot org
                CC: glibc-bugs at sources dot redhat dot com
 GCC build triplet: powerpc-unknown-linux-gnu
  GCC host triplet: powerpc-unknown-linux-gnu
GCC target triplet: powerpc-unknown-linux-gnu


http://sourceware.org/bugzilla/show_bug.cgi?id=1346

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]