This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574]
On Sun, Nov 19, 2017 at 7:39 AM, Florian Weimer <fw@deneb.enyo.de> wrote:
> * H. J. Lu:
>
>> The GCC driver patch has been checked into GCC 8. Here is the updated
>> patch for glibc.
>>
>> Tested with build-many-glibcs.py. Any objections?
>
> Is the entire text below supposed to go into the commit message? What
Yes.
> about the remaining tasks listed in it?
Target maintainers must work with binutils maintainers to resolve them
since static PIE may require linker bug fixes.
>> Dynamic linker, ld.so, is a standalone program which can be loaded at
>> any address. This patch adds a configure option, --enable-static-pie,
>> to embed the part of ld.so in static executable to create static position
>> independent executable (static PIE). A static PIE is similar to static
>> executable, but can be loaded at any address without help from a dynamic
>> linker. When --enable-static-pie is used to configure glibc, libc.a is
>> built as PIE and all static executables, including tests, are built as
>> static PIE. The resulting libc.a can be used together with GCC 8 or
>> above to build static PIE with the compiler option, -static-pie. But
>> GCC 8 isn't required to build glibc with --enable-static-pie. When an
>> older GCC is used to build glibc with --enable-static-pie, proper input
>> files are passed to linker to create static executables as static PIE,
>> together with "-z text" to prevent dynamic relocations in read-only
>> segments, which are allowed in static PIE.
>
> The last sentence is unclear. Is -z text required to use a glibc
> compiled by an earlier GCC? What exactly is the problem with dynamic
> relocations in read-only segments? Are they allowed or disallowed?
ld.so is a special static PIE. ld.so/static PIE can't have dynamic relocations
in read-only segments since static PIE is mapped into memory by KERNEL.
Unless we can want to change memory protection on read-only segments,
we can't have dynamic relocations in read-only segments.
> Can we support .data.relro?
Yes, that is supported since .data.relro section isn't in read-only segment:
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x00000034 0x00000034 0x00140 0x00140 R 0x4
INTERP 0x172494 0x00172494 0x00172494 0x00013 0x00013 R 0x4
[Requesting program interpreter: /lib/ld-linux.so.2]
LOAD 0x000000 0x00000000 0x00000000 0x1b9c24 0x1b9c24 R E 0x1000
LOAD 0x1ba218 0x001bb218 0x001bb218 0x02cdc 0x05804 RW 0x1000
DYNAMIC 0x1bbd70 0x001bcd70 0x001bcd70 0x000f8 0x000f8 RW 0x4
NOTE 0x000174 0x00000174 0x00000174 0x00044 0x00044 R 0x4
TLS 0x1ba218 0x001bb218 0x001bb218 0x00008 0x00054 R 0x4
GNU_EH_FRAME 0x1724a8 0x001724a8 0x001724a8 0x05bc4 0x05bc4 R 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x10
GNU_RELRO 0x1ba218 0x001bb218 0x001bb218 0x01de8 0x01de8 R 0x1
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr
.gnu.version .gnu.version_d .gnu.version_r .rel.dyn .rel.plt .plt
.plt.got .text __libc_freeres_fn __libc_thread_freeres_fn .rodata
.stapsdt.base .interp .eh_frame_hdr .eh_frame .gcc_except_table .hash
03 .tdata .init_array __libc_subfreeres __libc_atexit
__libc_thread_subfreeres __libc_IO_vtables .data.rel.ro .dynamic .got
.got.plt .data .bss
04 .dynamic
05 .note.gnu.build-id .note.ABI-tag
06 .tdata .tbss
07 .eh_frame_hdr
08
09 .tdata .init_array __libc_subfreeres __libc_atexit
__libc_thread_subfreeres __libc_IO_vtables .data.rel.ro .dynamic .got
It is in RELRO segment, which is made read-only AFTER relocation is done.
>> Static PIE can work on all architectures which support PIE, provided:
>>
>> 1. Target must support accessing of local functions without dynamic
>> relocations, which is needed in start.S to call __libc_start_main with
>> function addresses of __libc_csu_init, __libc_csu_fini and main.
>
> Are there really ABI concerns for the statically linked case? It
> should not be necessary to pass these function pointers.
I want to use the same internal function interface for static PIE and
normal binaries.
>> All functions in statice PIE are local functions. If PIE start.S
>> can't
>
> Typo: “statice”
Fixed.
>> 6. __brk works without TLS nor dynamic relocations in read-only section
>> so that it can be used by __libc_setup_tls to initializes TLS in static
>> PIE.
>
> Note that some kernels have strange address space layouts which
> prevent __brk from working reliably.
__brk is used in static binary. If static works, static PIE should be OK.
>
>> NB: When glibc is built with GCC defaulted to PIE, libc.a is compiled
>> with -fPIE, regardless if --enable-static-pie is used to configure glibc.
>> When glibc is configured with --enable-static-pie, libc.a is compiled
>> with -fPIE, regardless wether GCC defaults to PIE or not. The same libc.a
>> can be used to build both static executable and static PIE. There is no
>> need for separate PIE copy of libc.a.
>
> Is there a code size cost to PIE?
On x86-64, the normal static sln:
text data bss dec hex filename
625425 8284 5456 639165 9c0bd elf/sln
the static PIE sln:
text data bss dec hex filename
657626 20636 5392 683654 a6e86 elf/sln
The code size is increased by 5% and the binary size is increased by 7%.
>> Linker requirements to build glibc with --enable-static-pie:
>>
>> 1. Linker supports --no-dynamic-linker to remove PT_INTERP segment from
>> static PIE.
>> 2. Linker can create working static PIE. The x86-64 linker needs the
>> fix for
>>
>> https://sourceware.org/bugzilla/show_bug.cgi?id=21782
>
> So binutils 2.29 is the minimum requirement on x86-64?
Yes.
> Can an earlier binutils version be used to build a static library
> which is usable for PIE with binutils 2.29+?
Only linker is needed to create static PIE. Since we don't need
a linker to create a static library, it should be OK.
>> +'--enable-static-pie'
>> + Build static executables, including tests, as position independent
>> + executable (static PIE) which is similar to static executable, but
>> + can be loaded at any address without help from a dynamic linker.
>> + The resulting libc.a can be used with the GCC option, -static-pie,
>> + which is available with GCC 8 or above, to create static PIE. Only
>> + i686, x86-64 and x32 targets are verified to work.
>
> Drop the last sentence, it will be outdated soon.
>
>> diff --git a/Makeconfig b/Makeconfig
>
> The reason for some of the changes are not obvious at all to me, and
> the ChangeLog doesn't give an explanation either.
Can you list them so that I can address them?
>> new file mode 100644
>> index 0000000000..aa9302602b
>> --- /dev/null
>> +++ b/elf/dl-reloc-static-pie.c
>
> Is there anything which inhibits compilation of this file ith the
> stack protector? I think this is necessary because
> _dl_relocate_static_pie is called so early.
Good point. I will check.
>> +extern struct link_map * _dl_get_dl_main_map (void)
>> + __attribute__ ((visibility ("hidden")));
>
> This should go into a header file somewhere, so that the declaration
> can be checked against the definition.
I will see what I can do.
>> diff --git a/elf/dl-support.c b/elf/dl-support.c
>> index 235d3a7f46..b9fc1a66fe 100644
>> --- a/elf/dl-support.c
>> +++ b/elf/dl-support.c
>> @@ -385,3 +385,14 @@ _dl_non_dynamic_init (void)
>> #ifdef DL_SYSINFO_IMPLEMENTATION
>> DL_SYSINFO_IMPLEMENTATION
>> #endif
>> +
>> +#if ENABLE_STATIC_PIE
>> +/* Since relocation to hidden _dl_main_map causes relocation overflow on
>> + aarch64, a function is used to get the address of _dl_main_map. */
>> +
>> +struct link_map *
>> +_dl_get_dl_main_map (void)
>> +{
>> + return &_dl_main_map;
>> +}
>> +#endif
>
> Is this issue really aarch64-specific, or could it affect other
I think only aarch64 is affected. But I am not 100% sure.
> targets?
Thanks.
--
H.J.