This is the mail archive of the
glibc-bugs@sourceware.org
mailing list for the glibc project.
[Bug libc/1346] New: _dl_map_object_from_fd removes data segment execute permission
- From: "paulus at samba dot org" <sourceware-bugzilla at sourceware dot org>
- To: glibc-bugs at sources dot redhat dot com
- Date: 16 Sep 2005 01:58:46 -0000
- Subject: [Bug libc/1346] New: _dl_map_object_from_fd removes data segment execute permission
- Reply-to: sourceware-bugzilla at sourceware dot org
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.