* PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] @ 2017-11-01 12:46 H.J. Lu 2017-11-01 16:04 ` Joseph Myers 0 siblings, 1 reply; 37+ messages in thread From: H.J. Lu @ 2017-11-01 12:46 UTC (permalink / raw) To: GNU C Library I'd like to get static PIE: https://sourceware.org/ml/libc-alpha/2017-10/msg00587.html Static PIE is simply an extension of ld.so. The following changes are made for static PIE: 1. Add a new function, _dl_relocate_static_pie, to: a. Get the run-time load address. b. Read the dynamic section. c. Perform dynamic relocations. Dynamic linker also performs these steps. But static PIE doesn't load any shared objects. 2. Call _dl_relocate_static_pie at entrance of LIBC_START_MAIN in libc.a. crt1.o, which is used to create dynamic and non-PIE static executables, is updated to include a dummy _dl_relocate_static_pie. Pcrt1.o is added to create static PIE, which will link in the real _dl_relocate_static_pie. gPcrt1.o is also added to create static PIE with -pg. The main issues with static PIE are 1. Many binutils targets don't handle PIE properly. I opened a few binutils bugs for PIE. 2. Many assembly codes assumes PIC == SHARED. I opened a glibc bug for it. 3. Some dl-machine.h files may not handle undefined weak symbols in PIE properly. But we will never know for sure unless we build static PIE. I'd like to add static PIE support into glibc 2.27, which works on i686 and x86-64. I will help other target developers get static PIE working for his/her target. -- H.J. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-11-01 12:46 PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] H.J. Lu @ 2017-11-01 16:04 ` Joseph Myers 2017-11-01 16:06 ` H.J. Lu 0 siblings, 1 reply; 37+ messages in thread From: Joseph Myers @ 2017-11-01 16:04 UTC (permalink / raw) To: H.J. Lu; +Cc: GNU C Library On Wed, 1 Nov 2017, H.J. Lu wrote: > _dl_relocate_static_pie. gPcrt1.o is also added to create static PIE > with -pg. Does that require extra GCC support, or do the specs already in GCC handle using gPcrt1.o? -- Joseph S. Myers joseph@codesourcery.com ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-11-01 16:04 ` Joseph Myers @ 2017-11-01 16:06 ` H.J. Lu 2017-11-03 17:57 ` H.J. Lu 0 siblings, 1 reply; 37+ messages in thread From: H.J. Lu @ 2017-11-01 16:06 UTC (permalink / raw) To: Joseph Myers; +Cc: GNU C Library On Wed, Nov 1, 2017 at 9:03 AM, Joseph Myers <joseph@codesourcery.com> wrote: > On Wed, 1 Nov 2017, H.J. Lu wrote: > >> _dl_relocate_static_pie. gPcrt1.o is also added to create static PIE >> with -pg. > > Does that require extra GCC support, or do the specs already in GCC handle > using gPcrt1.o? Yes, this GCC driver patch: https://gcc.gnu.org/ml/gcc-patches/2017-10/msg00954.html is needed. -- H.J. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-11-01 16:06 ` H.J. Lu @ 2017-11-03 17:57 ` H.J. Lu 2017-11-19 2:40 ` H.J. Lu 0 siblings, 1 reply; 37+ messages in thread From: H.J. Lu @ 2017-11-03 17:57 UTC (permalink / raw) To: Joseph Myers; +Cc: GNU C Library [-- Attachment #1: Type: text/plain, Size: 609 bytes --] On Wed, Nov 1, 2017 at 9:06 AM, H.J. Lu <hjl.tools@gmail.com> wrote: > On Wed, Nov 1, 2017 at 9:03 AM, Joseph Myers <joseph@codesourcery.com> wrote: >> On Wed, 1 Nov 2017, H.J. Lu wrote: >> >>> _dl_relocate_static_pie. gPcrt1.o is also added to create static PIE >>> with -pg. >> >> Does that require extra GCC support, or do the specs already in GCC handle >> using gPcrt1.o? > > Yes, this GCC driver patch: > > https://gcc.gnu.org/ml/gcc-patches/2017-10/msg00954.html > > is needed. Here is the updated patch to rename Pcrt1.o/gPcrt1.o to rcrt1.o/grcrt1.o. Any comments or objections? Thanks. -- H.J. [-- Attachment #2: 0001-Add-enable-static-pie-configure-option-to-build-stat.patch --] [-- Type: text/x-patch, Size: 41742 bytes --] From b2aa8907043bdd8048647be22ab9a339f1934b49 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <hjl.tools@gmail.com> Date: Mon, 17 Jul 2017 08:17:32 -0700 Subject: [PATCH 1/8] Add --enable-static-pie configure option to build static PIE [BZ #19574] 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 following changes are made for static PIE: 1. Add a new function, _dl_relocate_static_pie, to: a. Get the run-time load address. b. Read the dynamic section. c. Perform dynamic relocations. Dynamic linker also performs these steps. But static PIE doesn't load any shared objects. 2. Call _dl_relocate_static_pie at entrance of LIBC_START_MAIN in libc.a. crt1.o, which is used to create dynamic and non-PIE static executables, is updated to include a dummy _dl_relocate_static_pie. rcrt1.o is added to create static PIE, which will link in the real _dl_relocate_static_pie. grcrt1.o is also added to create static PIE with -pg. The names of rcrt1.o/grcrt1.o are chosen to be consistent with musl libc and OpenBSD: https://gcc.gnu.org/ml/gcc/2015-06/msg00008.html The corresponding patch for GCC 8 is at https://gcc.gnu.org/ml/gcc-patches/2017-11/msg00247.html 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. All functions in statice PIE are local functions. If PIE start.S can't reach main () defined in a shared object, the code sequence: pass addess of local_main to __libc_start_main ... local_main: tail call to main via PLT can be used. 2. start.S is updated to check PIC instead SHARED for PIC code path and avoid dynamic relocation, when PIC is defined and SHARED isn't defined, to support static PIE. Patches are submitted for aarch64, hppa, m68k, microblaze and sparc. 3. All assembly codes are updated check PIC instead SHARED for PIC code path to avoid dynamic relocations in read-only sections. 4. All assembly codes are updated check SHARED instead PIC for static symbol name. A patch is submitted for tile. 5. elf_machine_load_address in dl-machine.h are updated to support static PIE. Patches are submitted for aarch64, s390 and sh. 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. 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. 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 The i386 linker needs to be able to convert "movl main@GOT(%ebx), %eax" to "leal main@GOTOFF(%ebx), %eax" if main is defined locally. Binutils 2.29 or above are OK for i686 and x86-64. But linker status for other targets need to be verified. 3. Linker should resolve undefined weak symbols to 0 in static PIE: https://sourceware.org/bugzilla/show_bug.cgi?id=22269 4. Many ELF backend linkers incorrectly check bfd_link_pic for TLS relocations, which should check bfd_link_executable instead: https://sourceware.org/bugzilla/show_bug.cgi?id=22263 Tested on i686 and x86-64. Build results of build-many-glibcs.py with --enable-static-pie with all patches for static PIE applied are PASS: glibcs-aarch64_be-linux-gnu build PASS: glibcs-aarch64-linux-gnu build PASS: glibcs-armeb-linux-gnueabi build PASS: glibcs-armeb-linux-gnueabi-be8 build PASS: glibcs-armeb-linux-gnueabihf build PASS: glibcs-armeb-linux-gnueabihf-be8 build PASS: glibcs-arm-linux-gnueabi build PASS: glibcs-arm-linux-gnueabihf build PASS: glibcs-hppa-linux-gnu build PASS: glibcs-i486-linux-gnu build PASS: glibcs-i586-linux-gnu build PASS: glibcs-i686-linux-gnu build PASS: glibcs-i686-linux-gnu-disable-multi-arch build PASS: glibcs-m68k-linux-gnu build PASS: glibcs-microblazeel-linux-gnu build PASS: glibcs-microblaze-linux-gnu build PASS: glibcs-mips64el-linux-gnu-n64 build PASS: glibcs-mips64el-linux-gnu-n64-nan2008 build PASS: glibcs-mips64el-linux-gnu-n64-nan2008-soft build PASS: glibcs-mips64el-linux-gnu-n64-soft build PASS: glibcs-mips64-linux-gnu-n64 build PASS: glibcs-mips64-linux-gnu-n64-nan2008 build PASS: glibcs-mips64-linux-gnu-n64-nan2008-soft build PASS: glibcs-mips64-linux-gnu-n64-soft build PASS: glibcs-nios2-linux-gnu build PASS: glibcs-powerpc64le-linux-gnu build PASS: glibcs-powerpc64-linux-gnu build PASS: glibcs-s390x-linux-gnu build PASS: glibcs-x86_64-linux-gnu build PASS: glibcs-x86_64-linux-gnu-disable-multi-arch build PASS: glibcs-x86_64-linux-gnu-x32 build FAIL: glibcs-alpha-linux-gnu build elf/sln is failed to link due to: assertion fail bfd/elf64-alpha.c:4125 This is caused by linker bug and/or non-PIC code in PIE libc.a. FAIL: glibcs-ia64-linux-gnu build elf/sln is failed to link due to: libc.a(sched_yield.o): non-pic code with imm relocation against dynamic symbol `_dl_sysinfo' This is caused by non-PIC version of DO_CALL macro in ia64 sysdep.h. PIE libc.a should use PIC version of DO_CALL, except during startup in static PIE. An ia64 startup.h, similar to i386 startup.h, is needed to handle this. FAIL: glibcs-mips64el-linux-gnu-n32 build FAIL: glibcs-mips64el-linux-gnu-n32-nan2008 build FAIL: glibcs-mips64el-linux-gnu-n32-nan2008-soft build FAIL: glibcs-mips64el-linux-gnu-n32-soft build FAIL: glibcs-mips64-linux-gnu-n32 build FAIL: glibcs-mips64-linux-gnu-n32-nan2008 build FAIL: glibcs-mips64-linux-gnu-n32-nan2008-soft build FAIL: glibcs-mips64-linux-gnu-n32-soft build FAIL: glibcs-mipsel-linux-gnu build FAIL: glibcs-mipsel-linux-gnu-nan2008 build FAIL: glibcs-mipsel-linux-gnu-nan2008-soft build FAIL: glibcs-mipsel-linux-gnu-soft build FAIL: glibcs-mips-linux-gnu build FAIL: glibcs-mips-linux-gnu-nan2008 build FAIL: glibcs-mips-linux-gnu-nan2008-soft build FAIL: glibcs-mips-linux-gnu-soft build elf/sln is failed to link due to: crt1.o: relocation R_MIPS_HI16 against `_gp' can not be used when making a shared object; recompile with -fPIC This is caused by linker bug and/or non-PIC code in crt1.o. FAIL: glibcs-powerpc-linux-gnu build FAIL: glibcs-powerpc-linux-gnu-soft build FAIL: glibcs-powerpc-linux-gnuspe build FAIL: glibcs-powerpc-linux-gnuspe-e500v1 build elf/sln is failed to link due to: ld: read-only segment has dynamic relocations. This is caused by linker bug and/or non-PIC code in PIE libc.a. See: https://sourceware.org/bugzilla/show_bug.cgi?id=22264 FAIL: glibcs-powerpc-linux-gnu-power4 build elf/sln is failed to link due to: findlocale.c:96:(.text+0x22c): @local call to ifunc memchr This is caused by linker bug and/or non-PIC code in PIE libc.a. FAIL: glibcs-s390-linux-gnu build elf/sln is failed to link due to: collect2: fatal error: ld terminated with signal 11 [Segmentation fault], core dumped assertion fail bfd/elflink.c:14242 This is caused by linker bug and/or non-PIC code in PIE libc.a. FAIL: glibcs-sh3eb-linux-gnu build FAIL: glibcs-sh3-linux-gnu build FAIL: glibcs-sh4eb-linux-gnu build FAIL: glibcs-sh4eb-linux-gnu-soft build FAIL: glibcs-sh4-linux-gnu build FAIL: glibcs-sh4-linux-gnu-soft build elf/sln is failed to link due to: ld: read-only segment has dynamic relocations. This is caused by linker bug and/or non-PIC code in PIE libc.a. See: https://sourceware.org/bugzilla/show_bug.cgi?id=22263 Also TLS code sequence in SH assembly syscalls in glibc doesn't match TLS code sequence expected by ld: https://sourceware.org/bugzilla/show_bug.cgi?id=22270 FAIL: glibcs-sparc64-linux-gnu build FAIL: glibcs-sparcv9-linux-gnu build FAIL: glibcs-tilegxbe-linux-gnu build FAIL: glibcs-tilegxbe-linux-gnu-32 build FAIL: glibcs-tilegx-linux-gnu build FAIL: glibcs-tilegx-linux-gnu-32 build FAIL: glibcs-tilepro-linux-gnu build elf/sln is failed to link due to: ld: read-only segment has dynamic relocations. This is caused by linker bug and/or non-PIC code in PIE libc.a. See: https://sourceware.org/bugzilla/show_bug.cgi?id=22263 [BZ #19574] * INSTALL: Regenerated. * Makeconfig (static-start-installed-name): Add the `r' prefix for --enable-static-pie. (pic-default): Updated for --enable-static-pie. (pie-default): New for --enable-static-pie. (default-pie-ldflag): Likewise. (+link-static-before-libc): Use the first of $(DEFAULT-LDFLAGS-$(@F)) and $(default-pie-ldflag). (+prectorT): Updated for --enable-static-pie. (+postctorT): Likewise. (CFLAGS-.o): Add $(pie-default). (CFLAGS-.op): Likewise. * NEWS: Mention --enable-static-pie. * config.h.in (ENABLE_STATIC_PIE): New. * configure.ac (--enable-static-pie): New configure option. (have-no-dynamic-linker): New LIBC_CONFIG_VAR. (have-static-pie): Likewise. Enable static PIE if linker supports --no-dynamic-linker. (ENABLE_STATIC_PIE): New AC_DEFINE. (enable-static-pie): New LIBC_CONFIG_VAR. * configure: Regenerated. * csu/Makefile (omit-deps): Add r$(start-installed-name) for --enable-static-pie. (extra-objs): Likewise. (install-lib): Likewise. (extra-objs): Add static-reloc.o and static-reloc.os ($(objpfx)$(start-installed-name)): Also depend on $(objpfx)static-reloc.o. ($(objpfx)r$(start-installed-name)): New. ($(objpfx)g$(start-installed-name)): Also depend on $(objpfx)static-reloc.os. * csu/libc-start.c (LIBC_START_MAIN): Call _dl_relocate_static_pie in libc.a. * csu/libc-tls.c (__libc_setup_tls): Add main_map->l_addr to initimage. * csu/static-reloc.c: New file. * elf/Makefile (routines): Add dl-reloc-static-pie. (elide-routines.os): Likewise. * elf/dl-reloc-static-pie.c: New file. * elf/dl-support.c (_dl_get_dl_main_map): New function. * elf/dynamic-link.h (ELF_DURING_STARTUP): Also check STATIC_PIE_BOOTSTRAP. * elf/get-dynamic-info.h (elf_get_dynamic_info): Likewise. * gmon/Makefile (tests): Add tst-gmon-static-pie. (tests-static): Likewise. (CFLAGS-tst-gmon-static-pie.c): New. (CRT-tst-gmon-static-pie): Likewise. (tst-gmon-static-pie-ENV): Likewise. (tests-special): Likewise. ($(objpfx)tst-gmon-static-pie.out): Likewise. (clean-tst-gmon-static-pie-data): Likewise. ($(objpfx)tst-gmon-static-pie-gprof.out): Likewise. * gmon/tst-gmon-static-pie.c: New file. * manual/install.texi: Document --enable-static-pie. * sysdeps/generic/ldsodefs.h (_dl_relocate_static_pie): New. * sysdeps/i386/configure.ac: Check if linker supports static PIE. * sysdeps/x86_64/configure.ac: Likewise. * sysdeps/i386/configure: Regenerated. * sysdeps/x86_64/configure: Likewise. --- INSTALL | 8 +++++ Makeconfig | 25 +++++++++++++-- NEWS | 6 ++++ config.h.in | 3 ++ configure | 78 +++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 29 +++++++++++++++++ csu/Makefile | 17 ++++++++-- csu/libc-start.c | 2 ++ csu/libc-tls.c | 6 ++-- csu/static-reloc.c | 26 +++++++++++++++ elf/Makefile | 5 +-- elf/dl-reloc-static-pie.c | 55 ++++++++++++++++++++++++++++++++ elf/dl-support.c | 11 +++++++ elf/dynamic-link.h | 2 +- elf/get-dynamic-info.h | 6 ++-- gmon/Makefile | 23 +++++++++++++ gmon/tst-gmon-static-pie.c | 1 + manual/install.texi | 8 +++++ sysdeps/generic/ldsodefs.h | 7 ++++ sysdeps/i386/configure | 33 +++++++++++++++++++ sysdeps/i386/configure.ac | 23 +++++++++++++ sysdeps/x86_64/configure | 33 +++++++++++++++++++ sysdeps/x86_64/configure.ac | 25 +++++++++++++++ 23 files changed, 418 insertions(+), 14 deletions(-) create mode 100644 csu/static-reloc.c create mode 100644 elf/dl-reloc-static-pie.c create mode 100644 gmon/tst-gmon-static-pie.c diff --git a/INSTALL b/INSTALL index bc972b2ffa..b58ae890a3 100644 --- a/INSTALL +++ b/INSTALL @@ -89,6 +89,14 @@ will be used, and CFLAGS sets optimization options for the compiler. systems support shared libraries; you need ELF support and (currently) the GNU linker. +'--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. + '--disable-profile' Don't build libraries with profiling information. You may want to use this option if you don't plan to do profiling. diff --git a/Makeconfig b/Makeconfig index 1346109ac0..3712e8a2ed 100644 --- a/Makeconfig +++ b/Makeconfig @@ -352,6 +352,10 @@ ifndef static-start-installed-name static-start-installed-name = $(start-installed-name) endif +ifeq (yes,$(enable-static-pie)) +static-start-installed-name := r$(static-start-installed-name) +endif + ifeq (yesyes,$(build-shared)$(have-z-combreloc)) combreloc-LDFLAGS = -Wl,-z,combreloc LDFLAGS.so += $(combreloc-LDFLAGS) @@ -371,6 +375,16 @@ LDFLAGS.so += $(hashstyle-LDFLAGS) LDFLAGS-rtld += $(hashstyle-LDFLAGS) endif +ifeq (yes,$(enable-static-pie)) +pic-default = -DPIC +pie-default = $(pie-ccflag) +ifeq (yes,$(have-static-pie)) +default-pie-ldflag = -static-pie +else +default-pie-ldflag = -Wl,-pie,--no-dynamic-linker,--eh-frame-hdr,-z,text +endif +endif + # If lazy relocations are disabled, add the -z now flag. Use # LDFLAGS-lib.so instead of LDFLAGS.so, to avoid adding the flag to # test modules. @@ -420,7 +434,7 @@ endif # Command for statically linking programs with the C library. ifndef +link-static +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \ - $(DEFAULT-LDFLAGS-$(@F)) \ + $(firstword $(DEFAULT-LDFLAGS-$(@F)) $(default-pie-ldflag)) \ $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \ $(firstword $(CRT-$(@F)) $(csu-objpfx)$(static-start-installed-name)) \ $(+preinit) $(+prectorT) \ @@ -637,8 +651,13 @@ endif +prectorS = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtbeginS.o` +postctorS = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtendS.o` # Variants of the two previous definitions for statically linking programs. +ifeq (yes,$(enable-static-pie)) ++prectorT = $(+prectorS) ++postctorT = $(+postctorS) +else +prectorT = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtbeginT.o` +postctorT = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtend.o` +endif csu-objpfx = $(common-objpfx)csu/ elf-objpfx = $(common-objpfx)elf/ @@ -959,7 +978,7 @@ libtypes = $(foreach o,$(object-suffixes-for-libc),$(libtype$o)) all-object-suffixes := .o .os .oS object-suffixes := CPPFLAGS-.o = $(pic-default) -CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) +CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) $(pie-default) libtype.o := lib%.a object-suffixes += .o ifeq (yes,$(build-shared)) @@ -984,7 +1003,7 @@ ifeq (yes,$(build-profile)) all-object-suffixes += .op object-suffixes += .op CPPFLAGS-.op = -DPROF $(pic-default) -CFLAGS-.op = -pg +CFLAGS-.op = -pg $(pie-default) libtype.op = lib%_p.a endif diff --git a/NEWS b/NEWS index 8e040f1f3b..0b4ba380af 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,12 @@ Version 2.27 Major new features: +* Add --enable-static-pie configure option to build static PIE. The + resulting libc.a can be used with the GCC option, -static-pie, which + is available with GCC 8 or above, to create static position independent + executable (static PIE). Only i686, x86-64 and x32 targets are verified + to work. + * Optimized x86-64 asin, atan2, exp, expf, log, pow, atan, sin and tan with FMA, contributed by Arjan van de Ven and H.J. Lu from Intel. diff --git a/config.h.in b/config.h.in index c140ff3ecb..f7db916711 100644 --- a/config.h.in +++ b/config.h.in @@ -244,6 +244,9 @@ /* Build glibc with tunables support. */ #define HAVE_TUNABLES 0 +/* Define if static PIE is enabled. */ +#define ENABLE_STATIC_PIE 0 + /* Some compiler options may now allow to use ebp in __asm__ (used mainly in i386 6 argument syscall issue). */ #define CAN_USE_REGISTER_ASM_EBP 0 diff --git a/configure b/configure index 6010977c58..9aaf654477 100755 --- a/configure +++ b/configure @@ -764,6 +764,7 @@ with_default_link enable_sanity_checks enable_shared enable_profile +enable_static_pie enable_timezone_tools enable_hardcoded_path_in_tests enable_stackguard_randomization @@ -1419,6 +1420,7 @@ Optional Features: in special situations) [default=yes] --enable-shared build shared library [default=yes if GNU ld] --enable-profile build profiled library [default=no] + --enable-static-pie build static executables as PIE [default=no] --disable-timezone-tools do not install timezone tools [default=install] --enable-hardcoded-path-in-tests @@ -3364,6 +3366,13 @@ else profile=no fi +# Check whether --enable-static-pie was given. +if test "${enable_static_pie+set}" = set; then : + enableval=$enable_static_pie; static_pie=$enableval +else + static_pie=no +fi + # Check whether --enable-timezone-tools was given. if test "${enable_timezone_tools+set}" = set; then : enableval=$enable_timezone_tools; enable_timezone_tools=$enableval @@ -5804,6 +5813,62 @@ fi $as_echo "$libc_linker_feature" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker that supports --no-dynamic-linker" >&5 +$as_echo_n "checking for linker that supports --no-dynamic-linker... " >&6; } +libc_linker_feature=no +if test x"$gnu_ld" = x"yes"; then + libc_linker_check=`$LD -v --help 2>/dev/null | grep "\--no-dynamic-linker"` + if test -n "$libc_linker_check"; then + cat > conftest.c <<EOF +int _start (void) { return 42; } +EOF + if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp + -Wl,--no-dynamic-linker -nostdlib -nostartfiles + -fPIC -shared -o conftest.so conftest.c + 1>&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } + then + libc_linker_feature=yes + fi + rm -f conftest* + fi +fi +if test $libc_linker_feature = yes; then + libc_cv_no_dynamic_linker=yes +else + libc_cv_no_dynamic_linker=no +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5 +$as_echo "$libc_linker_feature" >&6; } +config_vars="$config_vars +have-no-dynamic-linker = $libc_cv_no_dynamic_linker" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -static-pie" >&5 +$as_echo_n "checking for -static-pie... " >&6; } +if ${libc_cv_static_pie+:} false; then : + $as_echo_n "(cached) " >&6 +else + if { ac_try='${CC-cc} -static-pie -xc /dev/null -S -o /dev/null' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + libc_cv_static_pie=yes +else + libc_cv_static_pie=no +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_static_pie" >&5 +$as_echo "$libc_cv_static_pie" >&6; } +config_vars="$config_vars +have-static-pie = $libc_cv_static_pie" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -fpie" >&5 $as_echo_n "checking for -fpie... " >&6; } if ${libc_cv_fpie+:} false; then : @@ -6698,6 +6763,19 @@ fi $as_echo "$libc_cv_pie_default" >&6; } +if test "$static_pie" = yes; then + # The linker must support --no-dynamic-linker. + if test "$libc_cv_no_dynamic_linker" != yes; then + as_fn_error $? "linker support for --no-dynamic-linker needed" "$LINENO" 5 + fi + # Default to PIE. + libc_cv_pie_default=yes + $as_echo "#define ENABLE_STATIC_PIE 1" >>confdefs.h + +fi +config_vars="$config_vars +enable-static-pie = $static_pie" + diff --git a/configure.ac b/configure.ac index 148f7d1682..28a51b6efb 100644 --- a/configure.ac +++ b/configure.ac @@ -176,6 +176,11 @@ AC_ARG_ENABLE([profile], [build profiled library @<:@default=no@:>@]), [profile=$enableval], [profile=no]) +AC_ARG_ENABLE([static-pie], + AC_HELP_STRING([--enable-static-pie], + [build static executables as PIE @<:@default=no@:>@]), + [static_pie=$enableval], + [static_pie=no]) AC_ARG_ENABLE([timezone-tools], AC_HELP_STRING([--disable-timezone-tools], [do not install timezone tools @<:@default=install@:>@]), @@ -1281,6 +1286,19 @@ LIBC_LINKER_FEATURE([-z execstack], [-Wl,-z,execstack], [libc_cv_z_execstack=yes], [libc_cv_z_execstack=no]) AC_SUBST(libc_cv_z_execstack) +LIBC_LINKER_FEATURE([--no-dynamic-linker], + [-Wl,--no-dynamic-linker], + [libc_cv_no_dynamic_linker=yes], + [libc_cv_no_dynamic_linker=no]) +LIBC_CONFIG_VAR([have-no-dynamic-linker], [$libc_cv_no_dynamic_linker]) + +AC_CACHE_CHECK(for -static-pie, libc_cv_static_pie, [dnl +LIBC_TRY_CC_OPTION([-static-pie], + [libc_cv_static_pie=yes], + [libc_cv_static_pie=no]) +]) +LIBC_CONFIG_VAR([have-static-pie], [$libc_cv_static_pie]) + AC_CACHE_CHECK(for -fpie, libc_cv_fpie, [dnl LIBC_TRY_CC_OPTION([-fpie], [libc_cv_fpie=yes], [libc_cv_fpie=no]) ]) @@ -1783,6 +1801,17 @@ fi rm -f conftest.*]) AC_SUBST(libc_cv_pie_default) +if test "$static_pie" = yes; then + # The linker must support --no-dynamic-linker. + if test "$libc_cv_no_dynamic_linker" != yes; then + AC_MSG_ERROR([linker support for --no-dynamic-linker needed]) + fi + # Default to PIE. + libc_cv_pie_default=yes + AC_DEFINE(ENABLE_STATIC_PIE) +fi +LIBC_CONFIG_VAR([enable-static-pie], [$static_pie]) + AC_SUBST(profile) AC_SUBST(static_nss) diff --git a/csu/Makefile b/csu/Makefile index fd668a5d00..2770efe612 100644 --- a/csu/Makefile +++ b/csu/Makefile @@ -37,7 +37,8 @@ extra-objs = start.o \ S$(start-installed-name) omit-deps = $(patsubst %.o,%,$(start-installed-name) g$(start-installed-name) \ b$(start-installed-name) $(csu-dummies) \ - S$(start-installed-name)) + S$(start-installed-name) \ + r$(start-installed-name)) install-lib = $(start-installed-name) g$(start-installed-name) $(csu-dummies) # No tests are allowed in the csu/ subdirectory because the startup @@ -55,6 +56,10 @@ extra-objs += gmon-start.o endif install-lib += S$(start-installed-name) generated += start.os +ifeq (yes,$(enable-static-pie)) +extra-objs += r$(start-installed-name) +install-lib += r$(start-installed-name) +endif else extra-objs += gmon-start.o endif @@ -77,7 +82,10 @@ crtstuff = crti crtn install-lib += $(crtstuff:=.o) extra-objs += $(crtstuff:=.o) -extra-objs += abi-note.o init.o +extra-objs += abi-note.o init.o static-reloc.o +ifeq (yes,$(build-shared)) +extra-objs += static-reloc.os +endif asm-CPPFLAGS += -I$(objpfx). # Enable unwinding so backtrace unwinds to __libc_start_main @@ -96,6 +104,9 @@ ifndef start-installed-name-rule # We link the ELF startfile along with a SHT_NOTE section indicating # the kernel ABI the binaries linked with this library will require. $(objpfx)$(start-installed-name): $(objpfx)start.o $(objpfx)abi-note.o \ + $(objpfx)init.o $(objpfx)static-reloc.o + $(link-relocatable) +$(objpfx)r$(start-installed-name): $(objpfx)start.o $(objpfx)abi-note.o \ $(objpfx)init.o $(link-relocatable) $(objpfx)S$(start-installed-name): $(objpfx)start.os $(objpfx)abi-note.o \ @@ -108,7 +119,7 @@ endif # to turn on profiling code at startup. ifeq (yes,$(build-shared)) $(objpfx)g$(start-installed-name): \ - $(objpfx)g%: $(objpfx)S% $(objpfx)gmon-start.os + $(objpfx)g%: $(objpfx)S% $(objpfx)gmon-start.os $(objpfx)static-reloc.os $(link-relocatable) ifneq ($(start-installed-name),$(static-start-installed-name)) $(objpfx)g$(static-start-installed-name): \ diff --git a/csu/libc-start.c b/csu/libc-start.c index 24c63be02f..34dd125260 100644 --- a/csu/libc-start.c +++ b/csu/libc-start.c @@ -141,6 +141,8 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), __libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up; #ifndef SHARED + _dl_relocate_static_pie (); + char **ev = &argv[argc + 1]; __environ = ev; diff --git a/csu/libc-tls.c b/csu/libc-tls.c index 00138eb43a..1f8ddaf543 100644 --- a/csu/libc-tls.c +++ b/csu/libc-tls.c @@ -114,6 +114,8 @@ __libc_setup_tls (void) size_t tcb_offset; const ElfW(Phdr) *phdr; + struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded; + /* Look through the TLS segment if there is any. */ if (_dl_phdr != NULL) for (phdr = _dl_phdr; phdr < &_dl_phdr[_dl_phnum]; ++phdr) @@ -122,7 +124,7 @@ __libc_setup_tls (void) /* Remember the values we need. */ memsz = phdr->p_memsz; filesz = phdr->p_filesz; - initimage = (void *) phdr->p_vaddr; + initimage = (void *) phdr->p_vaddr + main_map->l_addr; align = phdr->p_align; if (phdr->p_align > max_align) max_align = phdr->p_align; @@ -163,8 +165,6 @@ __libc_setup_tls (void) _dl_static_dtv[0].counter = (sizeof (_dl_static_dtv) / sizeof (_dl_static_dtv[0])) - 2; // _dl_static_dtv[1].counter = 0; would be needed if not already done - struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded; - /* Initialize the TLS block. */ #if TLS_TCB_AT_TP _dl_static_dtv[2].pointer.val = ((char *) tlsblock + tcb_offset diff --git a/csu/static-reloc.c b/csu/static-reloc.c new file mode 100644 index 0000000000..37be72c8ea --- /dev/null +++ b/csu/static-reloc.c @@ -0,0 +1,26 @@ +/* Special startup support for non-PIE static executables. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#if ENABLE_STATIC_PIE +#include <ldsodefs.h> + +void +_dl_relocate_static_pie (void) +{ +} +#endif diff --git a/elf/Makefile b/elf/Makefile index a31fb72498..cb035e63aa 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -24,7 +24,8 @@ include ../Makeconfig headers = elf.h bits/elfclass.h link.h bits/link.h routines = $(all-dl-routines) dl-support dl-iteratephdr \ dl-addr dl-addr-obj enbl-secure dl-profstub \ - dl-origin dl-libc dl-sym dl-sysdep dl-error + dl-origin dl-libc dl-sym dl-sysdep dl-error \ + dl-reloc-static-pie # The core dynamic linking functions are in libc for the static and # profiled libraries. @@ -52,7 +53,7 @@ endif all-dl-routines = $(dl-routines) $(sysdep-dl-routines) # But they are absent from the shared libc, because that code is in ld.so. elide-routines.os = $(all-dl-routines) dl-support enbl-secure dl-origin \ - dl-sysdep dl-exception + dl-sysdep dl-exception dl-reloc-static-pie shared-only-routines += dl-caller # ld.so uses those routines, plus some special stuff for being the program diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c new file mode 100644 index 0000000000..aa9302602b --- /dev/null +++ b/elf/dl-reloc-static-pie.c @@ -0,0 +1,55 @@ +/* Support for relocating static PIE. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#if ENABLE_STATIC_PIE +#include <unistd.h> +#include <ldsodefs.h> +#include "dynamic-link.h" + +extern struct link_map * _dl_get_dl_main_map (void) + __attribute__ ((visibility ("hidden"))); + +/* Relocate static executable with PIE. */ + +void +_dl_relocate_static_pie (void) +{ + struct link_map *main_map = _dl_get_dl_main_map (); + +# define STATIC_PIE_BOOTSTRAP +# define BOOTSTRAP_MAP (main_map) +# define RESOLVE_MAP(sym, version, flags) BOOTSTRAP_MAP +# include "dynamic-link.h" + + /* Figure out the run-time load address of static PIE. */ + main_map->l_addr = elf_machine_load_address (); + + /* Read our own dynamic section and fill in the info array. */ + main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ()); + elf_get_dynamic_info (main_map, NULL); + +# ifdef ELF_MACHINE_BEFORE_RTLD_RELOC + ELF_MACHINE_BEFORE_RTLD_RELOC (main_map->l_info); +# endif + + /* Relocate ourselves so we can do normal function calls and + data access using the global offset table. */ + ELF_DYNAMIC_RELOCATE (main_map, 0, 0, 0); + main_map->l_relocated = 1; +} +#endif diff --git a/elf/dl-support.c b/elf/dl-support.c index 5e3de90598..282e99d5e9 100644 --- a/elf/dl-support.c +++ b/elf/dl-support.c @@ -384,3 +384,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 diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h index ebea7567cd..6278649711 100644 --- a/elf/dynamic-link.h +++ b/elf/dynamic-link.h @@ -94,7 +94,7 @@ elf_machine_lazy_rel (struct link_map *map, #ifdef RESOLVE_MAP -# ifdef RTLD_BOOTSTRAP +# if defined RTLD_BOOTSTRAP || defined STATIC_PIE_BOOTSTRAP # define ELF_DURING_STARTUP (1) # else # define ELF_DURING_STARTUP (0) diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h index 7525c3a5b2..eb26d23649 100644 --- a/elf/get-dynamic-info.h +++ b/elf/get-dynamic-info.h @@ -38,7 +38,7 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) typedef Elf64_Xword d_tag_utype; #endif -#ifndef RTLD_BOOTSTRAP +#if !defined RTLD_BOOTSTRAP && !defined STATIC_PIE_BOOTSTRAP if (dyn == NULL) return; #endif @@ -139,9 +139,11 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) /* Only the bind now flags are allowed. */ assert (info[VERSYMIDX (DT_FLAGS_1)] == NULL || (info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val & ~DF_1_NOW) == 0); + /* Flags must not be set for ld.so. */ assert (info[DT_FLAGS] == NULL || (info[DT_FLAGS]->d_un.d_val & ~DF_BIND_NOW) == 0); - /* Flags must not be set for ld.so. */ +#endif +#if defined RTLD_BOOTSTRAP || defined STATIC_PIE_BOOTSTRAP assert (info[DT_RUNPATH] == NULL); assert (info[DT_RPATH] == NULL); #else diff --git a/gmon/Makefile b/gmon/Makefile index 89ab3fc7da..f83fcc9d71 100644 --- a/gmon/Makefile +++ b/gmon/Makefile @@ -39,6 +39,10 @@ tests-static += tst-gmon-static ifeq (yesyes,$(have-fpie)$(build-shared)) tests += tst-gmon-pie tests-pie += tst-gmon-pie +ifeq (yes,$(enable-static-pie)) +tests += tst-gmon-static-pie +tests-static += tst-gmon-static-pie +endif endif # The mcount code won't work without a frame pointer. @@ -67,6 +71,15 @@ ifeq ($(run-built-tests),yes) tests-special += $(objpfx)tst-gmon-pie-gprof.out endif +ifeq (yes,$(enable-static-pie)) +CFLAGS-tst-gmon-static-pie.c := $(PIE-ccflag) -fno-omit-frame-pointer -pg +CRT-tst-gmon-static-pie := $(csu-objpfx)grcrt1.o +tst-gmon-static-pie-ENV := GMON_OUT_PREFIX=$(objpfx)tst-gmon-static-pie.data +ifeq ($(run-built-tests),yes) +tests-special += $(objpfx)tst-gmon-static-pie-gprof.out +endif +endif + include ../Rules @@ -111,3 +124,13 @@ clean-tst-gmon-pie-data: $(objpfx)tst-gmon-pie-gprof.out: tst-gmon-gprof.sh $(objpfx)tst-gmon-pie.out $(SHELL) $< $(GPROF) $(objpfx)tst-gmon-pie $(objpfx)tst-gmon-pie.data.* > $@; \ $(evaluate-test) + +$(objpfx)tst-gmon-static-pie.out: clean-tst-gmon-static-pie-data +clean-tst-gmon-static-pie-data: + rm -f $(objpfx)tst-gmon-static-pie.data.* + +$(objpfx)tst-gmon-static-pie-gprof.out: tst-gmon-static-gprof.sh \ + $(objpfx)tst-gmon-static-pie.out + $(SHELL) $< $(GPROF) $(objpfx)tst-gmon-static-pie \ + $(objpfx)tst-gmon-static-pie.data.* > $@; \ + $(evaluate-test) diff --git a/gmon/tst-gmon-static-pie.c b/gmon/tst-gmon-static-pie.c new file mode 100644 index 0000000000..1eef2583b6 --- /dev/null +++ b/gmon/tst-gmon-static-pie.c @@ -0,0 +1 @@ +#include "tst-gmon.c" diff --git a/manual/install.texi b/manual/install.texi index 96b988e829..67bf48e1ea 100644 --- a/manual/install.texi +++ b/manual/install.texi @@ -120,6 +120,14 @@ Don't build shared libraries even if it is possible. Not all systems support shared libraries; you need ELF support and (currently) the GNU linker. +@item --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. + @item --disable-profile Don't build libraries with profiling information. You may want to use this option if you don't plan to do profiling. diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index 5efae2d96d..dbcc1ec766 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -1048,6 +1048,13 @@ extern void _dl_determine_tlsoffset (void) attribute_hidden; stack protector, among other things). */ void __libc_setup_tls (void); +# if ENABLE_STATIC_PIE +/* Relocate static executable with PIE. */ +void _dl_relocate_static_pie (void) attribute_hidden; +# else +# define _dl_relocate_static_pie() +# endif + /* Initialization of libpthread for statically linked applications. If libpthread is not linked in, this is an empty function. */ void __pthread_initialize_minimal (void) weak_function; diff --git a/sysdeps/i386/configure b/sysdeps/i386/configure index 4cf968d8bc..90c63caf35 100644 --- a/sysdeps/i386/configure +++ b/sysdeps/i386/configure @@ -50,6 +50,39 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_compiler_builtin_inlined" >&5 $as_echo "$libc_compiler_builtin_inlined" >&6; } +if test "$static_pie" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker static PIE support" >&5 +$as_echo_n "checking for linker static PIE support... " >&6; } +if ${libc_cv_ld_static_pie+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat > conftest.s <<\EOF + .text + .global _start +_start: + movl _start@GOT(%ebx), %eax +EOF + libc_cv_pie_option="-Wl,-pie" + libc_cv_ld_static_pie=no + if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + if $READELF -r conftest | grep 'There are no relocations in this file.' > /dev/null; then + libc_cv_ld_static_pie=yes + fi + fi +rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_ld_static_pie" >&5 +$as_echo "$libc_cv_ld_static_pie" >&6; } + if test "$libc_cv_ld_static_pie" != yes; then + as_fn_error $? "linker support for static PIE needed" "$LINENO" 5 + fi +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Intel MPX support" >&5 $as_echo_n "checking for Intel MPX support... " >&6; } if ${libc_cv_asm_mpx+:} false; then : diff --git a/sysdeps/i386/configure.ac b/sysdeps/i386/configure.ac index b598b120bc..6d2068d2b3 100644 --- a/sysdeps/i386/configure.ac +++ b/sysdeps/i386/configure.ac @@ -30,6 +30,29 @@ LIBC_COMPILER_BUILTIN_INLINED( *** Please use host i786, i686, i586, or i486. *** For example: /source/glibc/configure CFLAGS='-O2 -march=i686' ...])]) +dnl Check if linker can convert "movl main@GOT(%ebx), %eax" to +dnl "leal main@GOTOFF(%ebx), %eax" for static PIE. +if test "$static_pie" = yes; then + AC_CACHE_CHECK(for linker static PIE support, libc_cv_ld_static_pie, [dnl +cat > conftest.s <<\EOF + .text + .global _start +_start: + movl _start@GOT(%ebx), %eax +EOF + libc_cv_pie_option="-Wl,-pie" + libc_cv_ld_static_pie=no + if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&AS_MESSAGE_LOG_FD); then + if $READELF -r conftest | grep 'There are no relocations in this file.' > /dev/null; then + libc_cv_ld_static_pie=yes + fi + fi +rm -f conftest*]) + if test "$libc_cv_ld_static_pie" != yes; then + AC_MSG_ERROR([linker support for static PIE needed]) + fi +fi + dnl Check whether asm supports Intel MPX AC_CACHE_CHECK(for Intel MPX support, libc_cv_asm_mpx, [dnl cat > conftest.s <<\EOF diff --git a/sysdeps/x86_64/configure b/sysdeps/x86_64/configure index efef46b1b7..8674d14569 100644 --- a/sysdeps/x86_64/configure +++ b/sysdeps/x86_64/configure @@ -85,6 +85,39 @@ if test x"$build_mathvec" = xnotset; then build_mathvec=yes fi +if test "$static_pie" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker static PIE support" >&5 +$as_echo_n "checking for linker static PIE support... " >&6; } +if ${libc_cv_ld_static_pie+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat > conftest.s <<\EOF + .text + .global _start + .weak foo +_start: + leaq foo(%rip), %rax +EOF + libc_cv_pie_option="-Wl,-pie" + if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + libc_cv_ld_static_pie=yes + else + libc_cv_ld_static_pie=no + fi +rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_ld_static_pie" >&5 +$as_echo "$libc_cv_ld_static_pie" >&6; } + if test "$libc_cv_ld_static_pie" != yes; then + as_fn_error $? "linker support for static PIE needed" "$LINENO" 5 + fi +fi + $as_echo "#define PI_STATIC_AND_HIDDEN 1" >>confdefs.h diff --git a/sysdeps/x86_64/configure.ac b/sysdeps/x86_64/configure.ac index fa86e953ee..b7d2c0124f 100644 --- a/sysdeps/x86_64/configure.ac +++ b/sysdeps/x86_64/configure.ac @@ -44,6 +44,31 @@ if test x"$build_mathvec" = xnotset; then build_mathvec=yes fi +dnl Check if linker supports static PIE with the fix for +dnl +dnl https://sourceware.org/bugzilla/show_bug.cgi?id=21782 +dnl +if test "$static_pie" = yes; then + AC_CACHE_CHECK(for linker static PIE support, libc_cv_ld_static_pie, [dnl +cat > conftest.s <<\EOF + .text + .global _start + .weak foo +_start: + leaq foo(%rip), %rax +EOF + libc_cv_pie_option="-Wl,-pie" + if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&AS_MESSAGE_LOG_FD); then + libc_cv_ld_static_pie=yes + else + libc_cv_ld_static_pie=no + fi +rm -f conftest*]) + if test "$libc_cv_ld_static_pie" != yes; then + AC_MSG_ERROR([linker support for static PIE needed]) + fi +fi + dnl It is always possible to access static and hidden symbols in an dnl position independent way. AC_DEFINE(PI_STATIC_AND_HIDDEN) -- 2.13.6 ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-11-03 17:57 ` H.J. Lu @ 2017-11-19 2:40 ` H.J. Lu 2017-11-19 15:39 ` Florian Weimer 2017-11-20 12:16 ` Szabolcs Nagy 0 siblings, 2 replies; 37+ messages in thread From: H.J. Lu @ 2017-11-19 2:40 UTC (permalink / raw) To: Joseph Myers; +Cc: GNU C Library [-- Attachment #1: Type: text/plain, Size: 838 bytes --] On Fri, Nov 3, 2017 at 10:57 AM, H.J. Lu <hjl.tools@gmail.com> wrote: > On Wed, Nov 1, 2017 at 9:06 AM, H.J. Lu <hjl.tools@gmail.com> wrote: >> On Wed, Nov 1, 2017 at 9:03 AM, Joseph Myers <joseph@codesourcery.com> wrote: >>> On Wed, 1 Nov 2017, H.J. Lu wrote: >>> >>>> _dl_relocate_static_pie. gPcrt1.o is also added to create static PIE >>>> with -pg. >>> >>> Does that require extra GCC support, or do the specs already in GCC handle >>> using gPcrt1.o? >> >> Yes, this GCC driver patch: >> >> https://gcc.gnu.org/ml/gcc-patches/2017-10/msg00954.html >> >> is needed. > > Here is the updated patch to rename Pcrt1.o/gPcrt1.o to rcrt1.o/grcrt1.o. > Any comments or objections? > 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? -- H.J. [-- Attachment #2: 0001-Add-enable-static-pie-configure-option-to-build-stat.patch --] [-- Type: text/x-patch, Size: 41739 bytes --] From 11337bccdf52ff2dfcf652f46097895d2c65a76e Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <hjl.tools@gmail.com> Date: Mon, 17 Jul 2017 08:17:32 -0700 Subject: [PATCH] Add --enable-static-pie configure option to build static PIE [BZ #19574] 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 following changes are made for static PIE: 1. Add a new function, _dl_relocate_static_pie, to: a. Get the run-time load address. b. Read the dynamic section. c. Perform dynamic relocations. Dynamic linker also performs these steps. But static PIE doesn't load any shared objects. 2. Call _dl_relocate_static_pie at entrance of LIBC_START_MAIN in libc.a. crt1.o, which is used to create dynamic and non-PIE static executables, is updated to include a dummy _dl_relocate_static_pie. rcrt1.o is added to create static PIE, which will link in the real _dl_relocate_static_pie. grcrt1.o is also added to create static PIE with -pg. GCC 8 has been updated to support rcrt1.o and grcrt1.o for static PIE. 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. All functions in statice PIE are local functions. If PIE start.S can't reach main () defined in a shared object, the code sequence: pass addess of local_main to __libc_start_main ... local_main: tail call to main via PLT can be used. 2. start.S is updated to check PIC instead SHARED for PIC code path and avoid dynamic relocation, when PIC is defined and SHARED isn't defined, to support static PIE. Patches are submitted for aarch64, hppa, m68k, microblaze and sparc. 3. All assembly codes are updated check PIC instead SHARED for PIC code path to avoid dynamic relocations in read-only sections. 4. All assembly codes are updated check SHARED instead PIC for static symbol name. A patch is submitted for tile. 5. elf_machine_load_address in dl-machine.h are updated to support static PIE. Patches are submitted for aarch64, s390 and sh. 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. 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. 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 The i386 linker needs to be able to convert "movl main@GOT(%ebx), %eax" to "leal main@GOTOFF(%ebx), %eax" if main is defined locally. Binutils 2.29 or above are OK for i686 and x86-64. But linker status for other targets need to be verified. 3. Linker should resolve undefined weak symbols to 0 in static PIE: https://sourceware.org/bugzilla/show_bug.cgi?id=22269 4. Many ELF backend linkers incorrectly check bfd_link_pic for TLS relocations, which should check bfd_link_executable instead: https://sourceware.org/bugzilla/show_bug.cgi?id=22263 Tested on i686 and x86-64. Build results of build-many-glibcs.py with --enable-static-pie with all patches for static PIE applied are PASS: glibcs-aarch64_be-linux-gnu build PASS: glibcs-aarch64-linux-gnu build PASS: glibcs-armeb-linux-gnueabi build PASS: glibcs-armeb-linux-gnueabi-be8 build PASS: glibcs-armeb-linux-gnueabihf build PASS: glibcs-armeb-linux-gnueabihf-be8 build PASS: glibcs-arm-linux-gnueabi build PASS: glibcs-arm-linux-gnueabihf build PASS: glibcs-hppa-linux-gnu build PASS: glibcs-i486-linux-gnu build PASS: glibcs-i586-linux-gnu build PASS: glibcs-i686-linux-gnu build PASS: glibcs-i686-linux-gnu-disable-multi-arch build PASS: glibcs-m68k-linux-gnu build PASS: glibcs-microblazeel-linux-gnu build PASS: glibcs-microblaze-linux-gnu build PASS: glibcs-mips64el-linux-gnu-n64 build PASS: glibcs-mips64el-linux-gnu-n64-nan2008 build PASS: glibcs-mips64el-linux-gnu-n64-nan2008-soft build PASS: glibcs-mips64el-linux-gnu-n64-soft build PASS: glibcs-mips64-linux-gnu-n64 build PASS: glibcs-mips64-linux-gnu-n64-nan2008 build PASS: glibcs-mips64-linux-gnu-n64-nan2008-soft build PASS: glibcs-mips64-linux-gnu-n64-soft build PASS: glibcs-nios2-linux-gnu build PASS: glibcs-powerpc64le-linux-gnu build PASS: glibcs-powerpc64-linux-gnu build PASS: glibcs-s390x-linux-gnu build PASS: glibcs-x86_64-linux-gnu build PASS: glibcs-x86_64-linux-gnu-disable-multi-arch build PASS: glibcs-x86_64-linux-gnu-x32 build FAIL: glibcs-alpha-linux-gnu build elf/sln is failed to link due to: assertion fail bfd/elf64-alpha.c:4125 This is caused by linker bug and/or non-PIC code in PIE libc.a. FAIL: glibcs-ia64-linux-gnu build elf/sln is failed to link due to: libc.a(sched_yield.o): non-pic code with imm relocation against dynamic symbol `_dl_sysinfo' This is caused by non-PIC version of DO_CALL macro in ia64 sysdep.h. PIE libc.a should use PIC version of DO_CALL, except during startup in static PIE. An ia64 startup.h, similar to i386 startup.h, is needed to handle this. FAIL: glibcs-mips64el-linux-gnu-n32 build FAIL: glibcs-mips64el-linux-gnu-n32-nan2008 build FAIL: glibcs-mips64el-linux-gnu-n32-nan2008-soft build FAIL: glibcs-mips64el-linux-gnu-n32-soft build FAIL: glibcs-mips64-linux-gnu-n32 build FAIL: glibcs-mips64-linux-gnu-n32-nan2008 build FAIL: glibcs-mips64-linux-gnu-n32-nan2008-soft build FAIL: glibcs-mips64-linux-gnu-n32-soft build FAIL: glibcs-mipsel-linux-gnu build FAIL: glibcs-mipsel-linux-gnu-nan2008 build FAIL: glibcs-mipsel-linux-gnu-nan2008-soft build FAIL: glibcs-mipsel-linux-gnu-soft build FAIL: glibcs-mips-linux-gnu build FAIL: glibcs-mips-linux-gnu-nan2008 build FAIL: glibcs-mips-linux-gnu-nan2008-soft build FAIL: glibcs-mips-linux-gnu-soft build elf/sln is failed to link due to: crt1.o: relocation R_MIPS_HI16 against `_gp' can not be used when making a shared object; recompile with -fPIC This is caused by linker bug and/or non-PIC code in crt1.o. FAIL: glibcs-powerpc-linux-gnu build FAIL: glibcs-powerpc-linux-gnu-soft build FAIL: glibcs-powerpc-linux-gnuspe build FAIL: glibcs-powerpc-linux-gnuspe-e500v1 build elf/sln is failed to link due to: ld: read-only segment has dynamic relocations. This is caused by linker bug and/or non-PIC code in PIE libc.a. See: https://sourceware.org/bugzilla/show_bug.cgi?id=22264 FAIL: glibcs-powerpc-linux-gnu-power4 build elf/sln is failed to link due to: findlocale.c:96:(.text+0x22c): @local call to ifunc memchr This is caused by linker bug and/or non-PIC code in PIE libc.a. FAIL: glibcs-s390-linux-gnu build elf/sln is failed to link due to: collect2: fatal error: ld terminated with signal 11 [Segmentation fault], core dumped assertion fail bfd/elflink.c:14242 This is caused by linker bug and/or non-PIC code in PIE libc.a. FAIL: glibcs-sh3eb-linux-gnu build FAIL: glibcs-sh3-linux-gnu build FAIL: glibcs-sh4eb-linux-gnu build FAIL: glibcs-sh4eb-linux-gnu-soft build FAIL: glibcs-sh4-linux-gnu build FAIL: glibcs-sh4-linux-gnu-soft build elf/sln is failed to link due to: ld: read-only segment has dynamic relocations. This is caused by linker bug and/or non-PIC code in PIE libc.a. See: https://sourceware.org/bugzilla/show_bug.cgi?id=22263 Also TLS code sequence in SH assembly syscalls in glibc doesn't match TLS code sequence expected by ld: https://sourceware.org/bugzilla/show_bug.cgi?id=22270 FAIL: glibcs-sparc64-linux-gnu build FAIL: glibcs-sparcv9-linux-gnu build FAIL: glibcs-tilegxbe-linux-gnu build FAIL: glibcs-tilegxbe-linux-gnu-32 build FAIL: glibcs-tilegx-linux-gnu build FAIL: glibcs-tilegx-linux-gnu-32 build FAIL: glibcs-tilepro-linux-gnu build elf/sln is failed to link due to: ld: read-only segment has dynamic relocations. This is caused by linker bug and/or non-PIC code in PIE libc.a. See: https://sourceware.org/bugzilla/show_bug.cgi?id=22263 [BZ #19574] * INSTALL: Regenerated. * Makeconfig (static-start-installed-name): Add the `r' prefix for --enable-static-pie. (pic-default): Updated for --enable-static-pie. (pie-default): New for --enable-static-pie. (default-pie-ldflag): Likewise. (+link-static-before-libc): Use the first of $(DEFAULT-LDFLAGS-$(@F)) and $(default-pie-ldflag). (+prectorT): Updated for --enable-static-pie. (+postctorT): Likewise. (CFLAGS-.o): Add $(pie-default). (CFLAGS-.op): Likewise. * NEWS: Mention --enable-static-pie. * config.h.in (ENABLE_STATIC_PIE): New. * configure.ac (--enable-static-pie): New configure option. (have-no-dynamic-linker): New LIBC_CONFIG_VAR. (have-static-pie): Likewise. Enable static PIE if linker supports --no-dynamic-linker. (ENABLE_STATIC_PIE): New AC_DEFINE. (enable-static-pie): New LIBC_CONFIG_VAR. * configure: Regenerated. * csu/Makefile (omit-deps): Add r$(start-installed-name) for --enable-static-pie. (extra-objs): Likewise. (install-lib): Likewise. (extra-objs): Add static-reloc.o and static-reloc.os ($(objpfx)$(start-installed-name)): Also depend on $(objpfx)static-reloc.o. ($(objpfx)r$(start-installed-name)): New. ($(objpfx)g$(start-installed-name)): Also depend on $(objpfx)static-reloc.os. * csu/libc-start.c (LIBC_START_MAIN): Call _dl_relocate_static_pie in libc.a. * csu/libc-tls.c (__libc_setup_tls): Add main_map->l_addr to initimage. * csu/static-reloc.c: New file. * elf/Makefile (routines): Add dl-reloc-static-pie. (elide-routines.os): Likewise. * elf/dl-reloc-static-pie.c: New file. * elf/dl-support.c (_dl_get_dl_main_map): New function. * elf/dynamic-link.h (ELF_DURING_STARTUP): Also check STATIC_PIE_BOOTSTRAP. * elf/get-dynamic-info.h (elf_get_dynamic_info): Likewise. * gmon/Makefile (tests): Add tst-gmon-static-pie. (tests-static): Likewise. (CFLAGS-tst-gmon-static-pie.c): New. (CRT-tst-gmon-static-pie): Likewise. (tst-gmon-static-pie-ENV): Likewise. (tests-special): Likewise. ($(objpfx)tst-gmon-static-pie.out): Likewise. (clean-tst-gmon-static-pie-data): Likewise. ($(objpfx)tst-gmon-static-pie-gprof.out): Likewise. * gmon/tst-gmon-static-pie.c: New file. * manual/install.texi: Document --enable-static-pie. * sysdeps/generic/ldsodefs.h (_dl_relocate_static_pie): New. * sysdeps/i386/configure.ac: Check if linker supports static PIE. * sysdeps/x86_64/configure.ac: Likewise. * sysdeps/i386/configure: Regenerated. * sysdeps/x86_64/configure: Likewise. --- INSTALL | 8 +++++ Makeconfig | 25 +++++++++++++-- NEWS | 6 ++++ config.h.in | 3 ++ configure | 78 +++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 29 +++++++++++++++++ csu/Makefile | 17 ++++++++-- csu/libc-start.c | 2 ++ csu/libc-tls.c | 6 ++-- csu/static-reloc.c | 26 +++++++++++++++ elf/Makefile | 5 +-- elf/dl-reloc-static-pie.c | 55 ++++++++++++++++++++++++++++++++ elf/dl-support.c | 11 +++++++ elf/dynamic-link.h | 2 +- elf/get-dynamic-info.h | 6 ++-- gmon/Makefile | 23 +++++++++++++ gmon/tst-gmon-static-pie.c | 1 + manual/install.texi | 8 +++++ sysdeps/generic/ldsodefs.h | 7 ++++ sysdeps/i386/configure | 33 +++++++++++++++++++ sysdeps/i386/configure.ac | 23 +++++++++++++ sysdeps/x86_64/configure | 33 +++++++++++++++++++ sysdeps/x86_64/configure.ac | 25 +++++++++++++++ 23 files changed, 418 insertions(+), 14 deletions(-) create mode 100644 csu/static-reloc.c create mode 100644 elf/dl-reloc-static-pie.c create mode 100644 gmon/tst-gmon-static-pie.c diff --git a/INSTALL b/INSTALL index ac8db74a0f..4d2f2fa08b 100644 --- a/INSTALL +++ b/INSTALL @@ -90,6 +90,14 @@ will be used, and CFLAGS sets optimization options for the compiler. systems support shared libraries; you need ELF support and (currently) the GNU linker. +'--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. + '--disable-profile' Don't build libraries with profiling information. You may want to use this option if you don't plan to do profiling. diff --git a/Makeconfig b/Makeconfig index 1346109ac0..3712e8a2ed 100644 --- a/Makeconfig +++ b/Makeconfig @@ -352,6 +352,10 @@ ifndef static-start-installed-name static-start-installed-name = $(start-installed-name) endif +ifeq (yes,$(enable-static-pie)) +static-start-installed-name := r$(static-start-installed-name) +endif + ifeq (yesyes,$(build-shared)$(have-z-combreloc)) combreloc-LDFLAGS = -Wl,-z,combreloc LDFLAGS.so += $(combreloc-LDFLAGS) @@ -371,6 +375,16 @@ LDFLAGS.so += $(hashstyle-LDFLAGS) LDFLAGS-rtld += $(hashstyle-LDFLAGS) endif +ifeq (yes,$(enable-static-pie)) +pic-default = -DPIC +pie-default = $(pie-ccflag) +ifeq (yes,$(have-static-pie)) +default-pie-ldflag = -static-pie +else +default-pie-ldflag = -Wl,-pie,--no-dynamic-linker,--eh-frame-hdr,-z,text +endif +endif + # If lazy relocations are disabled, add the -z now flag. Use # LDFLAGS-lib.so instead of LDFLAGS.so, to avoid adding the flag to # test modules. @@ -420,7 +434,7 @@ endif # Command for statically linking programs with the C library. ifndef +link-static +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \ - $(DEFAULT-LDFLAGS-$(@F)) \ + $(firstword $(DEFAULT-LDFLAGS-$(@F)) $(default-pie-ldflag)) \ $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \ $(firstword $(CRT-$(@F)) $(csu-objpfx)$(static-start-installed-name)) \ $(+preinit) $(+prectorT) \ @@ -637,8 +651,13 @@ endif +prectorS = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtbeginS.o` +postctorS = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtendS.o` # Variants of the two previous definitions for statically linking programs. +ifeq (yes,$(enable-static-pie)) ++prectorT = $(+prectorS) ++postctorT = $(+postctorS) +else +prectorT = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtbeginT.o` +postctorT = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtend.o` +endif csu-objpfx = $(common-objpfx)csu/ elf-objpfx = $(common-objpfx)elf/ @@ -959,7 +978,7 @@ libtypes = $(foreach o,$(object-suffixes-for-libc),$(libtype$o)) all-object-suffixes := .o .os .oS object-suffixes := CPPFLAGS-.o = $(pic-default) -CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) +CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) $(pie-default) libtype.o := lib%.a object-suffixes += .o ifeq (yes,$(build-shared)) @@ -984,7 +1003,7 @@ ifeq (yes,$(build-profile)) all-object-suffixes += .op object-suffixes += .op CPPFLAGS-.op = -DPROF $(pic-default) -CFLAGS-.op = -pg +CFLAGS-.op = -pg $(pie-default) libtype.op = lib%_p.a endif diff --git a/NEWS b/NEWS index 1c5da21327..016aa172f2 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,12 @@ Version 2.27 Major new features: +* Add --enable-static-pie configure option to build static PIE. The + resulting libc.a can be used with the GCC option, -static-pie, which + is available with GCC 8 or above, to create static position independent + executable (static PIE). Only i686, x86-64 and x32 targets are verified + to work. + * Optimized x86-64 asin, atan2, exp, expf, log, pow, atan, sin and tan with FMA, contributed by Arjan van de Ven and H.J. Lu from Intel. diff --git a/config.h.in b/config.h.in index c140ff3ecb..f7db916711 100644 --- a/config.h.in +++ b/config.h.in @@ -244,6 +244,9 @@ /* Build glibc with tunables support. */ #define HAVE_TUNABLES 0 +/* Define if static PIE is enabled. */ +#define ENABLE_STATIC_PIE 0 + /* Some compiler options may now allow to use ebp in __asm__ (used mainly in i386 6 argument syscall issue). */ #define CAN_USE_REGISTER_ASM_EBP 0 diff --git a/configure b/configure index d9d9243238..eb3c4225e3 100755 --- a/configure +++ b/configure @@ -765,6 +765,7 @@ with_default_link enable_sanity_checks enable_shared enable_profile +enable_static_pie enable_timezone_tools enable_hardcoded_path_in_tests enable_stackguard_randomization @@ -1420,6 +1421,7 @@ Optional Features: in special situations) [default=yes] --enable-shared build shared library [default=yes if GNU ld] --enable-profile build profiled library [default=no] + --enable-static-pie build static executables as PIE [default=no] --disable-timezone-tools do not install timezone tools [default=install] --enable-hardcoded-path-in-tests @@ -3365,6 +3367,13 @@ else profile=no fi +# Check whether --enable-static-pie was given. +if test "${enable_static_pie+set}" = set; then : + enableval=$enable_static_pie; static_pie=$enableval +else + static_pie=no +fi + # Check whether --enable-timezone-tools was given. if test "${enable_timezone_tools+set}" = set; then : enableval=$enable_timezone_tools; enable_timezone_tools=$enableval @@ -5805,6 +5814,62 @@ fi $as_echo "$libc_linker_feature" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker that supports --no-dynamic-linker" >&5 +$as_echo_n "checking for linker that supports --no-dynamic-linker... " >&6; } +libc_linker_feature=no +if test x"$gnu_ld" = x"yes"; then + libc_linker_check=`$LD -v --help 2>/dev/null | grep "\--no-dynamic-linker"` + if test -n "$libc_linker_check"; then + cat > conftest.c <<EOF +int _start (void) { return 42; } +EOF + if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp + -Wl,--no-dynamic-linker -nostdlib -nostartfiles + -fPIC -shared -o conftest.so conftest.c + 1>&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } + then + libc_linker_feature=yes + fi + rm -f conftest* + fi +fi +if test $libc_linker_feature = yes; then + libc_cv_no_dynamic_linker=yes +else + libc_cv_no_dynamic_linker=no +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5 +$as_echo "$libc_linker_feature" >&6; } +config_vars="$config_vars +have-no-dynamic-linker = $libc_cv_no_dynamic_linker" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -static-pie" >&5 +$as_echo_n "checking for -static-pie... " >&6; } +if ${libc_cv_static_pie+:} false; then : + $as_echo_n "(cached) " >&6 +else + if { ac_try='${CC-cc} -static-pie -xc /dev/null -S -o /dev/null' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + libc_cv_static_pie=yes +else + libc_cv_static_pie=no +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_static_pie" >&5 +$as_echo "$libc_cv_static_pie" >&6; } +config_vars="$config_vars +have-static-pie = $libc_cv_static_pie" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -fpie" >&5 $as_echo_n "checking for -fpie... " >&6; } if ${libc_cv_fpie+:} false; then : @@ -6704,6 +6769,19 @@ $as_echo "$libc_cv_pie_default" >&6; } libc_cv_multidir=`${CC-cc} $CFLAGS $CPPFLAGS -print-multi-directory` +if test "$static_pie" = yes; then + # The linker must support --no-dynamic-linker. + if test "$libc_cv_no_dynamic_linker" != yes; then + as_fn_error $? "linker support for --no-dynamic-linker needed" "$LINENO" 5 + fi + # Default to PIE. + libc_cv_pie_default=yes + $as_echo "#define ENABLE_STATIC_PIE 1" >>confdefs.h + +fi +config_vars="$config_vars +enable-static-pie = $static_pie" + diff --git a/configure.ac b/configure.ac index 8ebc490a55..ae219f8fe0 100644 --- a/configure.ac +++ b/configure.ac @@ -176,6 +176,11 @@ AC_ARG_ENABLE([profile], [build profiled library @<:@default=no@:>@]), [profile=$enableval], [profile=no]) +AC_ARG_ENABLE([static-pie], + AC_HELP_STRING([--enable-static-pie], + [build static executables as PIE @<:@default=no@:>@]), + [static_pie=$enableval], + [static_pie=no]) AC_ARG_ENABLE([timezone-tools], AC_HELP_STRING([--disable-timezone-tools], [do not install timezone tools @<:@default=install@:>@]), @@ -1281,6 +1286,19 @@ LIBC_LINKER_FEATURE([-z execstack], [-Wl,-z,execstack], [libc_cv_z_execstack=yes], [libc_cv_z_execstack=no]) AC_SUBST(libc_cv_z_execstack) +LIBC_LINKER_FEATURE([--no-dynamic-linker], + [-Wl,--no-dynamic-linker], + [libc_cv_no_dynamic_linker=yes], + [libc_cv_no_dynamic_linker=no]) +LIBC_CONFIG_VAR([have-no-dynamic-linker], [$libc_cv_no_dynamic_linker]) + +AC_CACHE_CHECK(for -static-pie, libc_cv_static_pie, [dnl +LIBC_TRY_CC_OPTION([-static-pie], + [libc_cv_static_pie=yes], + [libc_cv_static_pie=no]) +]) +LIBC_CONFIG_VAR([have-static-pie], [$libc_cv_static_pie]) + AC_CACHE_CHECK(for -fpie, libc_cv_fpie, [dnl LIBC_TRY_CC_OPTION([-fpie], [libc_cv_fpie=yes], [libc_cv_fpie=no]) ]) @@ -1788,6 +1806,17 @@ AC_SUBST(libc_cv_pie_default) libc_cv_multidir=`${CC-cc} $CFLAGS $CPPFLAGS -print-multi-directory` AC_SUBST(libc_cv_multidir) +if test "$static_pie" = yes; then + # The linker must support --no-dynamic-linker. + if test "$libc_cv_no_dynamic_linker" != yes; then + AC_MSG_ERROR([linker support for --no-dynamic-linker needed]) + fi + # Default to PIE. + libc_cv_pie_default=yes + AC_DEFINE(ENABLE_STATIC_PIE) +fi +LIBC_CONFIG_VAR([enable-static-pie], [$static_pie]) + AC_SUBST(profile) AC_SUBST(static_nss) diff --git a/csu/Makefile b/csu/Makefile index e42a32b3eb..e8ff1ec257 100644 --- a/csu/Makefile +++ b/csu/Makefile @@ -37,7 +37,8 @@ extra-objs = start.o \ S$(start-installed-name) omit-deps = $(patsubst %.o,%,$(start-installed-name) g$(start-installed-name) \ b$(start-installed-name) $(csu-dummies) \ - S$(start-installed-name)) + S$(start-installed-name) \ + r$(start-installed-name)) install-lib = $(start-installed-name) g$(start-installed-name) $(csu-dummies) # No tests are allowed in the csu/ subdirectory because the startup @@ -55,6 +56,10 @@ extra-objs += gmon-start.o endif install-lib += S$(start-installed-name) generated += start.os +ifeq (yes,$(enable-static-pie)) +extra-objs += r$(start-installed-name) +install-lib += r$(start-installed-name) +endif else extra-objs += gmon-start.o endif @@ -82,7 +87,10 @@ multilib-extra-objs = $(addprefix $(multidir)/, $(install-lib)) extra-objs += $(multilib-extra-objs) endif -extra-objs += abi-note.o init.o +extra-objs += abi-note.o init.o static-reloc.o +ifeq (yes,$(build-shared)) +extra-objs += static-reloc.os +endif asm-CPPFLAGS += -I$(objpfx). # Enable unwinding so backtrace unwinds to __libc_start_main @@ -101,6 +109,9 @@ ifndef start-installed-name-rule # We link the ELF startfile along with a SHT_NOTE section indicating # the kernel ABI the binaries linked with this library will require. $(objpfx)$(start-installed-name): $(objpfx)start.o $(objpfx)abi-note.o \ + $(objpfx)init.o $(objpfx)static-reloc.o + $(link-relocatable) +$(objpfx)r$(start-installed-name): $(objpfx)start.o $(objpfx)abi-note.o \ $(objpfx)init.o $(link-relocatable) $(objpfx)S$(start-installed-name): $(objpfx)start.os $(objpfx)abi-note.o \ @@ -113,7 +124,7 @@ endif # to turn on profiling code at startup. ifeq (yes,$(build-shared)) $(objpfx)g$(start-installed-name): \ - $(objpfx)g%: $(objpfx)S% $(objpfx)gmon-start.os + $(objpfx)g%: $(objpfx)S% $(objpfx)gmon-start.os $(objpfx)static-reloc.os $(link-relocatable) ifneq ($(start-installed-name),$(static-start-installed-name)) $(objpfx)g$(static-start-installed-name): \ diff --git a/csu/libc-start.c b/csu/libc-start.c index 24c63be02f..34dd125260 100644 --- a/csu/libc-start.c +++ b/csu/libc-start.c @@ -141,6 +141,8 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), __libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up; #ifndef SHARED + _dl_relocate_static_pie (); + char **ev = &argv[argc + 1]; __environ = ev; diff --git a/csu/libc-tls.c b/csu/libc-tls.c index 00138eb43a..1f8ddaf543 100644 --- a/csu/libc-tls.c +++ b/csu/libc-tls.c @@ -114,6 +114,8 @@ __libc_setup_tls (void) size_t tcb_offset; const ElfW(Phdr) *phdr; + struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded; + /* Look through the TLS segment if there is any. */ if (_dl_phdr != NULL) for (phdr = _dl_phdr; phdr < &_dl_phdr[_dl_phnum]; ++phdr) @@ -122,7 +124,7 @@ __libc_setup_tls (void) /* Remember the values we need. */ memsz = phdr->p_memsz; filesz = phdr->p_filesz; - initimage = (void *) phdr->p_vaddr; + initimage = (void *) phdr->p_vaddr + main_map->l_addr; align = phdr->p_align; if (phdr->p_align > max_align) max_align = phdr->p_align; @@ -163,8 +165,6 @@ __libc_setup_tls (void) _dl_static_dtv[0].counter = (sizeof (_dl_static_dtv) / sizeof (_dl_static_dtv[0])) - 2; // _dl_static_dtv[1].counter = 0; would be needed if not already done - struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded; - /* Initialize the TLS block. */ #if TLS_TCB_AT_TP _dl_static_dtv[2].pointer.val = ((char *) tlsblock + tcb_offset diff --git a/csu/static-reloc.c b/csu/static-reloc.c new file mode 100644 index 0000000000..37be72c8ea --- /dev/null +++ b/csu/static-reloc.c @@ -0,0 +1,26 @@ +/* Special startup support for non-PIE static executables. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#if ENABLE_STATIC_PIE +#include <ldsodefs.h> + +void +_dl_relocate_static_pie (void) +{ +} +#endif diff --git a/elf/Makefile b/elf/Makefile index a31fb72498..cb035e63aa 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -24,7 +24,8 @@ include ../Makeconfig headers = elf.h bits/elfclass.h link.h bits/link.h routines = $(all-dl-routines) dl-support dl-iteratephdr \ dl-addr dl-addr-obj enbl-secure dl-profstub \ - dl-origin dl-libc dl-sym dl-sysdep dl-error + dl-origin dl-libc dl-sym dl-sysdep dl-error \ + dl-reloc-static-pie # The core dynamic linking functions are in libc for the static and # profiled libraries. @@ -52,7 +53,7 @@ endif all-dl-routines = $(dl-routines) $(sysdep-dl-routines) # But they are absent from the shared libc, because that code is in ld.so. elide-routines.os = $(all-dl-routines) dl-support enbl-secure dl-origin \ - dl-sysdep dl-exception + dl-sysdep dl-exception dl-reloc-static-pie shared-only-routines += dl-caller # ld.so uses those routines, plus some special stuff for being the program diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c new file mode 100644 index 0000000000..aa9302602b --- /dev/null +++ b/elf/dl-reloc-static-pie.c @@ -0,0 +1,55 @@ +/* Support for relocating static PIE. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#if ENABLE_STATIC_PIE +#include <unistd.h> +#include <ldsodefs.h> +#include "dynamic-link.h" + +extern struct link_map * _dl_get_dl_main_map (void) + __attribute__ ((visibility ("hidden"))); + +/* Relocate static executable with PIE. */ + +void +_dl_relocate_static_pie (void) +{ + struct link_map *main_map = _dl_get_dl_main_map (); + +# define STATIC_PIE_BOOTSTRAP +# define BOOTSTRAP_MAP (main_map) +# define RESOLVE_MAP(sym, version, flags) BOOTSTRAP_MAP +# include "dynamic-link.h" + + /* Figure out the run-time load address of static PIE. */ + main_map->l_addr = elf_machine_load_address (); + + /* Read our own dynamic section and fill in the info array. */ + main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ()); + elf_get_dynamic_info (main_map, NULL); + +# ifdef ELF_MACHINE_BEFORE_RTLD_RELOC + ELF_MACHINE_BEFORE_RTLD_RELOC (main_map->l_info); +# endif + + /* Relocate ourselves so we can do normal function calls and + data access using the global offset table. */ + ELF_DYNAMIC_RELOCATE (main_map, 0, 0, 0); + main_map->l_relocated = 1; +} +#endif 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 diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h index ebea7567cd..6278649711 100644 --- a/elf/dynamic-link.h +++ b/elf/dynamic-link.h @@ -94,7 +94,7 @@ elf_machine_lazy_rel (struct link_map *map, #ifdef RESOLVE_MAP -# ifdef RTLD_BOOTSTRAP +# if defined RTLD_BOOTSTRAP || defined STATIC_PIE_BOOTSTRAP # define ELF_DURING_STARTUP (1) # else # define ELF_DURING_STARTUP (0) diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h index 7525c3a5b2..eb26d23649 100644 --- a/elf/get-dynamic-info.h +++ b/elf/get-dynamic-info.h @@ -38,7 +38,7 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) typedef Elf64_Xword d_tag_utype; #endif -#ifndef RTLD_BOOTSTRAP +#if !defined RTLD_BOOTSTRAP && !defined STATIC_PIE_BOOTSTRAP if (dyn == NULL) return; #endif @@ -139,9 +139,11 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) /* Only the bind now flags are allowed. */ assert (info[VERSYMIDX (DT_FLAGS_1)] == NULL || (info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val & ~DF_1_NOW) == 0); + /* Flags must not be set for ld.so. */ assert (info[DT_FLAGS] == NULL || (info[DT_FLAGS]->d_un.d_val & ~DF_BIND_NOW) == 0); - /* Flags must not be set for ld.so. */ +#endif +#if defined RTLD_BOOTSTRAP || defined STATIC_PIE_BOOTSTRAP assert (info[DT_RUNPATH] == NULL); assert (info[DT_RPATH] == NULL); #else diff --git a/gmon/Makefile b/gmon/Makefile index 89ab3fc7da..f83fcc9d71 100644 --- a/gmon/Makefile +++ b/gmon/Makefile @@ -39,6 +39,10 @@ tests-static += tst-gmon-static ifeq (yesyes,$(have-fpie)$(build-shared)) tests += tst-gmon-pie tests-pie += tst-gmon-pie +ifeq (yes,$(enable-static-pie)) +tests += tst-gmon-static-pie +tests-static += tst-gmon-static-pie +endif endif # The mcount code won't work without a frame pointer. @@ -67,6 +71,15 @@ ifeq ($(run-built-tests),yes) tests-special += $(objpfx)tst-gmon-pie-gprof.out endif +ifeq (yes,$(enable-static-pie)) +CFLAGS-tst-gmon-static-pie.c := $(PIE-ccflag) -fno-omit-frame-pointer -pg +CRT-tst-gmon-static-pie := $(csu-objpfx)grcrt1.o +tst-gmon-static-pie-ENV := GMON_OUT_PREFIX=$(objpfx)tst-gmon-static-pie.data +ifeq ($(run-built-tests),yes) +tests-special += $(objpfx)tst-gmon-static-pie-gprof.out +endif +endif + include ../Rules @@ -111,3 +124,13 @@ clean-tst-gmon-pie-data: $(objpfx)tst-gmon-pie-gprof.out: tst-gmon-gprof.sh $(objpfx)tst-gmon-pie.out $(SHELL) $< $(GPROF) $(objpfx)tst-gmon-pie $(objpfx)tst-gmon-pie.data.* > $@; \ $(evaluate-test) + +$(objpfx)tst-gmon-static-pie.out: clean-tst-gmon-static-pie-data +clean-tst-gmon-static-pie-data: + rm -f $(objpfx)tst-gmon-static-pie.data.* + +$(objpfx)tst-gmon-static-pie-gprof.out: tst-gmon-static-gprof.sh \ + $(objpfx)tst-gmon-static-pie.out + $(SHELL) $< $(GPROF) $(objpfx)tst-gmon-static-pie \ + $(objpfx)tst-gmon-static-pie.data.* > $@; \ + $(evaluate-test) diff --git a/gmon/tst-gmon-static-pie.c b/gmon/tst-gmon-static-pie.c new file mode 100644 index 0000000000..1eef2583b6 --- /dev/null +++ b/gmon/tst-gmon-static-pie.c @@ -0,0 +1 @@ +#include "tst-gmon.c" diff --git a/manual/install.texi b/manual/install.texi index f1fa28c937..f81196baaf 100644 --- a/manual/install.texi +++ b/manual/install.texi @@ -120,6 +120,14 @@ Don't build shared libraries even if it is possible. Not all systems support shared libraries; you need ELF support and (currently) the GNU linker. +@item --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. + @item --disable-profile Don't build libraries with profiling information. You may want to use this option if you don't plan to do profiling. diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index 52a792a597..19606492eb 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -1051,6 +1051,13 @@ extern void _dl_determine_tlsoffset (void) attribute_hidden; stack protector, among other things). */ void __libc_setup_tls (void); +# if ENABLE_STATIC_PIE +/* Relocate static executable with PIE. */ +void _dl_relocate_static_pie (void) attribute_hidden; +# else +# define _dl_relocate_static_pie() +# endif + /* Initialization of libpthread for statically linked applications. If libpthread is not linked in, this is an empty function. */ void __pthread_initialize_minimal (void) weak_function; diff --git a/sysdeps/i386/configure b/sysdeps/i386/configure index 4cf968d8bc..90c63caf35 100644 --- a/sysdeps/i386/configure +++ b/sysdeps/i386/configure @@ -50,6 +50,39 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_compiler_builtin_inlined" >&5 $as_echo "$libc_compiler_builtin_inlined" >&6; } +if test "$static_pie" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker static PIE support" >&5 +$as_echo_n "checking for linker static PIE support... " >&6; } +if ${libc_cv_ld_static_pie+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat > conftest.s <<\EOF + .text + .global _start +_start: + movl _start@GOT(%ebx), %eax +EOF + libc_cv_pie_option="-Wl,-pie" + libc_cv_ld_static_pie=no + if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + if $READELF -r conftest | grep 'There are no relocations in this file.' > /dev/null; then + libc_cv_ld_static_pie=yes + fi + fi +rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_ld_static_pie" >&5 +$as_echo "$libc_cv_ld_static_pie" >&6; } + if test "$libc_cv_ld_static_pie" != yes; then + as_fn_error $? "linker support for static PIE needed" "$LINENO" 5 + fi +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Intel MPX support" >&5 $as_echo_n "checking for Intel MPX support... " >&6; } if ${libc_cv_asm_mpx+:} false; then : diff --git a/sysdeps/i386/configure.ac b/sysdeps/i386/configure.ac index b598b120bc..6d2068d2b3 100644 --- a/sysdeps/i386/configure.ac +++ b/sysdeps/i386/configure.ac @@ -30,6 +30,29 @@ LIBC_COMPILER_BUILTIN_INLINED( *** Please use host i786, i686, i586, or i486. *** For example: /source/glibc/configure CFLAGS='-O2 -march=i686' ...])]) +dnl Check if linker can convert "movl main@GOT(%ebx), %eax" to +dnl "leal main@GOTOFF(%ebx), %eax" for static PIE. +if test "$static_pie" = yes; then + AC_CACHE_CHECK(for linker static PIE support, libc_cv_ld_static_pie, [dnl +cat > conftest.s <<\EOF + .text + .global _start +_start: + movl _start@GOT(%ebx), %eax +EOF + libc_cv_pie_option="-Wl,-pie" + libc_cv_ld_static_pie=no + if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&AS_MESSAGE_LOG_FD); then + if $READELF -r conftest | grep 'There are no relocations in this file.' > /dev/null; then + libc_cv_ld_static_pie=yes + fi + fi +rm -f conftest*]) + if test "$libc_cv_ld_static_pie" != yes; then + AC_MSG_ERROR([linker support for static PIE needed]) + fi +fi + dnl Check whether asm supports Intel MPX AC_CACHE_CHECK(for Intel MPX support, libc_cv_asm_mpx, [dnl cat > conftest.s <<\EOF diff --git a/sysdeps/x86_64/configure b/sysdeps/x86_64/configure index efef46b1b7..8674d14569 100644 --- a/sysdeps/x86_64/configure +++ b/sysdeps/x86_64/configure @@ -85,6 +85,39 @@ if test x"$build_mathvec" = xnotset; then build_mathvec=yes fi +if test "$static_pie" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker static PIE support" >&5 +$as_echo_n "checking for linker static PIE support... " >&6; } +if ${libc_cv_ld_static_pie+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat > conftest.s <<\EOF + .text + .global _start + .weak foo +_start: + leaq foo(%rip), %rax +EOF + libc_cv_pie_option="-Wl,-pie" + if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + libc_cv_ld_static_pie=yes + else + libc_cv_ld_static_pie=no + fi +rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_ld_static_pie" >&5 +$as_echo "$libc_cv_ld_static_pie" >&6; } + if test "$libc_cv_ld_static_pie" != yes; then + as_fn_error $? "linker support for static PIE needed" "$LINENO" 5 + fi +fi + $as_echo "#define PI_STATIC_AND_HIDDEN 1" >>confdefs.h diff --git a/sysdeps/x86_64/configure.ac b/sysdeps/x86_64/configure.ac index fa86e953ee..b7d2c0124f 100644 --- a/sysdeps/x86_64/configure.ac +++ b/sysdeps/x86_64/configure.ac @@ -44,6 +44,31 @@ if test x"$build_mathvec" = xnotset; then build_mathvec=yes fi +dnl Check if linker supports static PIE with the fix for +dnl +dnl https://sourceware.org/bugzilla/show_bug.cgi?id=21782 +dnl +if test "$static_pie" = yes; then + AC_CACHE_CHECK(for linker static PIE support, libc_cv_ld_static_pie, [dnl +cat > conftest.s <<\EOF + .text + .global _start + .weak foo +_start: + leaq foo(%rip), %rax +EOF + libc_cv_pie_option="-Wl,-pie" + if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&AS_MESSAGE_LOG_FD); then + libc_cv_ld_static_pie=yes + else + libc_cv_ld_static_pie=no + fi +rm -f conftest*]) + if test "$libc_cv_ld_static_pie" != yes; then + AC_MSG_ERROR([linker support for static PIE needed]) + fi +fi + dnl It is always possible to access static and hidden symbols in an dnl position independent way. AC_DEFINE(PI_STATIC_AND_HIDDEN) -- 2.14.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-11-19 2:40 ` H.J. Lu @ 2017-11-19 15:39 ` Florian Weimer 2017-11-19 16:17 ` H.J. Lu 2017-11-20 12:16 ` Szabolcs Nagy 1 sibling, 1 reply; 37+ messages in thread From: Florian Weimer @ 2017-11-19 15:39 UTC (permalink / raw) To: H.J. Lu; +Cc: Joseph Myers, GNU C Library * 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 about the remaining tasks listed in it? > 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? Can we support .data.relro? > 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. > All functions in statice PIE are local functions. If PIE start.S > can't Typo: “statice” > 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. > 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? > 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? Can an earlier binutils version be used to build a static library which is usable for PIE with binutils 2.29+? > +'--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. > 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. > +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. > 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 targets? ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-11-19 15:39 ` Florian Weimer @ 2017-11-19 16:17 ` H.J. Lu 2017-11-19 19:52 ` H.J. Lu 2017-11-20 14:17 ` Joseph Myers 0 siblings, 2 replies; 37+ messages in thread From: H.J. Lu @ 2017-11-19 16:17 UTC (permalink / raw) To: Florian Weimer; +Cc: Joseph Myers, GNU C Library 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. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-11-19 16:17 ` H.J. Lu @ 2017-11-19 19:52 ` H.J. Lu 2017-11-20 14:17 ` Joseph Myers 1 sibling, 0 replies; 37+ messages in thread From: H.J. Lu @ 2017-11-19 19:52 UTC (permalink / raw) To: Florian Weimer; +Cc: Joseph Myers, GNU C Library [-- Attachment #1: Type: text/plain, Size: 1731 bytes --] On Sun, Nov 19, 2017 at 8:17 AM, H.J. Lu <hjl.tools@gmail.com> wrote: > >>> +'--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. Fixed. >>> 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? I added some comments to Makeconfig. Do they answer your questions? >>> 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. _dl_relocate_static_pie must be compiled without stack protector. Since dl-reloc-static-pie.c is in elf, it is compiled with -fno-stack-protector. >>> +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. I moved it to sysdeps/generic/ldsodefs.h. Here is the updated patch. Any more comments? Thanks. -- H.J. [-- Attachment #2: 0001-Add-enable-static-pie-configure-option-to-build-stat.patch --] [-- Type: text/x-patch, Size: 42469 bytes --] From 0379d68b6128b8d87c9c00cff4b824052c8db968 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <hjl.tools@gmail.com> Date: Mon, 17 Jul 2017 08:17:32 -0700 Subject: [PATCH] Add --enable-static-pie configure option to build static PIE [BZ #19574] 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 following changes are made for static PIE: 1. Add a new function, _dl_relocate_static_pie, to: a. Get the run-time load address. b. Read the dynamic section. c. Perform dynamic relocations. Dynamic linker also performs these steps. But static PIE doesn't load any shared objects. 2. Call _dl_relocate_static_pie at entrance of LIBC_START_MAIN in libc.a. crt1.o, which is used to create dynamic and non-PIE static executables, is updated to include a dummy _dl_relocate_static_pie. rcrt1.o is added to create static PIE, which will link in the real _dl_relocate_static_pie. grcrt1.o is also added to create static PIE with -pg. GCC 8 has been updated to support rcrt1.o and grcrt1.o for static PIE. 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. All functions in static PIE are local functions. If PIE start.S can't reach main () defined in a shared object, the code sequence: pass addess of local_main to __libc_start_main ... local_main: tail call to main via PLT can be used. 2. start.S is updated to check PIC instead SHARED for PIC code path and avoid dynamic relocation, when PIC is defined and SHARED isn't defined, to support static PIE. Patches are submitted for aarch64, hppa, m68k, microblaze and sparc. 3. All assembly codes are updated check PIC instead SHARED for PIC code path to avoid dynamic relocations in read-only sections. 4. All assembly codes are updated check SHARED instead PIC for static symbol name. A patch is submitted for tile. 5. elf_machine_load_address in dl-machine.h are updated to support static PIE. Patches are submitted for aarch64, s390 and sh. 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. 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. 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 The i386 linker needs to be able to convert "movl main@GOT(%ebx), %eax" to "leal main@GOTOFF(%ebx), %eax" if main is defined locally. Binutils 2.29 or above are OK for i686 and x86-64. But linker status for other targets need to be verified. 3. Linker should resolve undefined weak symbols to 0 in static PIE: https://sourceware.org/bugzilla/show_bug.cgi?id=22269 4. Many ELF backend linkers incorrectly check bfd_link_pic for TLS relocations, which should check bfd_link_executable instead: https://sourceware.org/bugzilla/show_bug.cgi?id=22263 Tested on i686 and x86-64. Build results of build-many-glibcs.py with --enable-static-pie with all patches for static PIE applied are PASS: glibcs-aarch64_be-linux-gnu build PASS: glibcs-aarch64-linux-gnu build PASS: glibcs-armeb-linux-gnueabi build PASS: glibcs-armeb-linux-gnueabi-be8 build PASS: glibcs-armeb-linux-gnueabihf build PASS: glibcs-armeb-linux-gnueabihf-be8 build PASS: glibcs-arm-linux-gnueabi build PASS: glibcs-arm-linux-gnueabihf build PASS: glibcs-hppa-linux-gnu build PASS: glibcs-i486-linux-gnu build PASS: glibcs-i586-linux-gnu build PASS: glibcs-i686-linux-gnu build PASS: glibcs-i686-linux-gnu-disable-multi-arch build PASS: glibcs-m68k-linux-gnu build PASS: glibcs-microblazeel-linux-gnu build PASS: glibcs-microblaze-linux-gnu build PASS: glibcs-mips64el-linux-gnu-n64 build PASS: glibcs-mips64el-linux-gnu-n64-nan2008 build PASS: glibcs-mips64el-linux-gnu-n64-nan2008-soft build PASS: glibcs-mips64el-linux-gnu-n64-soft build PASS: glibcs-mips64-linux-gnu-n64 build PASS: glibcs-mips64-linux-gnu-n64-nan2008 build PASS: glibcs-mips64-linux-gnu-n64-nan2008-soft build PASS: glibcs-mips64-linux-gnu-n64-soft build PASS: glibcs-nios2-linux-gnu build PASS: glibcs-powerpc64le-linux-gnu build PASS: glibcs-powerpc64-linux-gnu build PASS: glibcs-s390x-linux-gnu build PASS: glibcs-x86_64-linux-gnu build PASS: glibcs-x86_64-linux-gnu-disable-multi-arch build PASS: glibcs-x86_64-linux-gnu-x32 build FAIL: glibcs-alpha-linux-gnu build elf/sln is failed to link due to: assertion fail bfd/elf64-alpha.c:4125 This is caused by linker bug and/or non-PIC code in PIE libc.a. FAIL: glibcs-ia64-linux-gnu build elf/sln is failed to link due to: libc.a(sched_yield.o): non-pic code with imm relocation against dynamic symbol `_dl_sysinfo' This is caused by non-PIC version of DO_CALL macro in ia64 sysdep.h. PIE libc.a should use PIC version of DO_CALL, except during startup in static PIE. An ia64 startup.h, similar to i386 startup.h, is needed to handle this. FAIL: glibcs-mips64el-linux-gnu-n32 build FAIL: glibcs-mips64el-linux-gnu-n32-nan2008 build FAIL: glibcs-mips64el-linux-gnu-n32-nan2008-soft build FAIL: glibcs-mips64el-linux-gnu-n32-soft build FAIL: glibcs-mips64-linux-gnu-n32 build FAIL: glibcs-mips64-linux-gnu-n32-nan2008 build FAIL: glibcs-mips64-linux-gnu-n32-nan2008-soft build FAIL: glibcs-mips64-linux-gnu-n32-soft build FAIL: glibcs-mipsel-linux-gnu build FAIL: glibcs-mipsel-linux-gnu-nan2008 build FAIL: glibcs-mipsel-linux-gnu-nan2008-soft build FAIL: glibcs-mipsel-linux-gnu-soft build FAIL: glibcs-mips-linux-gnu build FAIL: glibcs-mips-linux-gnu-nan2008 build FAIL: glibcs-mips-linux-gnu-nan2008-soft build FAIL: glibcs-mips-linux-gnu-soft build elf/sln is failed to link due to: crt1.o: relocation R_MIPS_HI16 against `_gp' can not be used when making a shared object; recompile with -fPIC This is caused by linker bug and/or non-PIC code in crt1.o. FAIL: glibcs-powerpc-linux-gnu build FAIL: glibcs-powerpc-linux-gnu-soft build FAIL: glibcs-powerpc-linux-gnuspe build FAIL: glibcs-powerpc-linux-gnuspe-e500v1 build elf/sln is failed to link due to: ld: read-only segment has dynamic relocations. This is caused by linker bug and/or non-PIC code in PIE libc.a. See: https://sourceware.org/bugzilla/show_bug.cgi?id=22264 FAIL: glibcs-powerpc-linux-gnu-power4 build elf/sln is failed to link due to: findlocale.c:96:(.text+0x22c): @local call to ifunc memchr This is caused by linker bug and/or non-PIC code in PIE libc.a. FAIL: glibcs-s390-linux-gnu build elf/sln is failed to link due to: collect2: fatal error: ld terminated with signal 11 [Segmentation fault], core dumped assertion fail bfd/elflink.c:14242 This is caused by linker bug and/or non-PIC code in PIE libc.a. FAIL: glibcs-sh3eb-linux-gnu build FAIL: glibcs-sh3-linux-gnu build FAIL: glibcs-sh4eb-linux-gnu build FAIL: glibcs-sh4eb-linux-gnu-soft build FAIL: glibcs-sh4-linux-gnu build FAIL: glibcs-sh4-linux-gnu-soft build elf/sln is failed to link due to: ld: read-only segment has dynamic relocations. This is caused by linker bug and/or non-PIC code in PIE libc.a. See: https://sourceware.org/bugzilla/show_bug.cgi?id=22263 Also TLS code sequence in SH assembly syscalls in glibc doesn't match TLS code sequence expected by ld: https://sourceware.org/bugzilla/show_bug.cgi?id=22270 FAIL: glibcs-sparc64-linux-gnu build FAIL: glibcs-sparcv9-linux-gnu build FAIL: glibcs-tilegxbe-linux-gnu build FAIL: glibcs-tilegxbe-linux-gnu-32 build FAIL: glibcs-tilegx-linux-gnu build FAIL: glibcs-tilegx-linux-gnu-32 build FAIL: glibcs-tilepro-linux-gnu build elf/sln is failed to link due to: ld: read-only segment has dynamic relocations. This is caused by linker bug and/or non-PIC code in PIE libc.a. See: https://sourceware.org/bugzilla/show_bug.cgi?id=22263 [BZ #19574] * INSTALL: Regenerated. * Makeconfig (static-start-installed-name): Add the `r' prefix for --enable-static-pie. (pic-default): Updated for --enable-static-pie. (pie-default): New for --enable-static-pie. (default-pie-ldflag): Likewise. (+link-static-before-libc): Use the first of $(DEFAULT-LDFLAGS-$(@F)) and $(default-pie-ldflag). (+prectorT): Updated for --enable-static-pie. (+postctorT): Likewise. (CFLAGS-.o): Add $(pie-default). (CFLAGS-.op): Likewise. * NEWS: Mention --enable-static-pie. * config.h.in (ENABLE_STATIC_PIE): New. * configure.ac (--enable-static-pie): New configure option. (have-no-dynamic-linker): New LIBC_CONFIG_VAR. (have-static-pie): Likewise. Enable static PIE if linker supports --no-dynamic-linker. (ENABLE_STATIC_PIE): New AC_DEFINE. (enable-static-pie): New LIBC_CONFIG_VAR. * configure: Regenerated. * csu/Makefile (omit-deps): Add r$(start-installed-name) for --enable-static-pie. (extra-objs): Likewise. (install-lib): Likewise. (extra-objs): Add static-reloc.o and static-reloc.os ($(objpfx)$(start-installed-name)): Also depend on $(objpfx)static-reloc.o. ($(objpfx)r$(start-installed-name)): New. ($(objpfx)g$(start-installed-name)): Also depend on $(objpfx)static-reloc.os. * csu/libc-start.c (LIBC_START_MAIN): Call _dl_relocate_static_pie in libc.a. * csu/libc-tls.c (__libc_setup_tls): Add main_map->l_addr to initimage. * csu/static-reloc.c: New file. * elf/Makefile (routines): Add dl-reloc-static-pie. (elide-routines.os): Likewise. * elf/dl-reloc-static-pie.c: New file. * elf/dl-support.c (_dl_get_dl_main_map): New function. * elf/dynamic-link.h (ELF_DURING_STARTUP): Also check STATIC_PIE_BOOTSTRAP. * elf/get-dynamic-info.h (elf_get_dynamic_info): Likewise. * gmon/Makefile (tests): Add tst-gmon-static-pie. (tests-static): Likewise. (CFLAGS-tst-gmon-static-pie.c): New. (CRT-tst-gmon-static-pie): Likewise. (tst-gmon-static-pie-ENV): Likewise. (tests-special): Likewise. ($(objpfx)tst-gmon-static-pie.out): Likewise. (clean-tst-gmon-static-pie-data): Likewise. ($(objpfx)tst-gmon-static-pie-gprof.out): Likewise. * gmon/tst-gmon-static-pie.c: New file. * manual/install.texi: Document --enable-static-pie. * sysdeps/generic/ldsodefs.h (_dl_relocate_static_pie): New. (_dl_get_dl_main_map): Likewise. * sysdeps/i386/configure.ac: Check if linker supports static PIE. * sysdeps/x86_64/configure.ac: Likewise. * sysdeps/i386/configure: Regenerated. * sysdeps/x86_64/configure: Likewise. --- INSTALL | 7 ++++ Makeconfig | 34 ++++++++++++++++++-- NEWS | 5 +++ config.h.in | 3 ++ configure | 78 +++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 29 +++++++++++++++++ csu/Makefile | 17 ++++++++-- csu/libc-start.c | 2 ++ csu/libc-tls.c | 6 ++-- csu/static-reloc.c | 26 +++++++++++++++ elf/Makefile | 5 +-- elf/dl-reloc-static-pie.c | 52 ++++++++++++++++++++++++++++++ elf/dl-support.c | 11 +++++++ elf/dynamic-link.h | 2 +- elf/get-dynamic-info.h | 6 ++-- gmon/Makefile | 23 +++++++++++++ gmon/tst-gmon-static-pie.c | 1 + manual/install.texi | 7 ++++ sysdeps/generic/ldsodefs.h | 11 +++++++ sysdeps/i386/configure | 33 +++++++++++++++++++ sysdeps/i386/configure.ac | 23 +++++++++++++ sysdeps/x86_64/configure | 33 +++++++++++++++++++ sysdeps/x86_64/configure.ac | 25 +++++++++++++++ 23 files changed, 425 insertions(+), 14 deletions(-) create mode 100644 csu/static-reloc.c create mode 100644 elf/dl-reloc-static-pie.c create mode 100644 gmon/tst-gmon-static-pie.c diff --git a/INSTALL b/INSTALL index ac8db74a0f..1beede7bae 100644 --- a/INSTALL +++ b/INSTALL @@ -90,6 +90,13 @@ will be used, and CFLAGS sets optimization options for the compiler. systems support shared libraries; you need ELF support and (currently) the GNU linker. +'--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. + '--disable-profile' Don't build libraries with profiling information. You may want to use this option if you don't plan to do profiling. diff --git a/Makeconfig b/Makeconfig index 1346109ac0..62a0c30498 100644 --- a/Makeconfig +++ b/Makeconfig @@ -352,6 +352,12 @@ ifndef static-start-installed-name static-start-installed-name = $(start-installed-name) endif +ifeq (yes,$(enable-static-pie)) +# Link with rcrt1.o, instead of crt1.o, to call _dl_relocate_static_pie +# to relocate static PIE. +static-start-installed-name := r$(static-start-installed-name) +endif + ifeq (yesyes,$(build-shared)$(have-z-combreloc)) combreloc-LDFLAGS = -Wl,-z,combreloc LDFLAGS.so += $(combreloc-LDFLAGS) @@ -371,6 +377,20 @@ LDFLAGS.so += $(hashstyle-LDFLAGS) LDFLAGS-rtld += $(hashstyle-LDFLAGS) endif +ifeq (yes,$(enable-static-pie)) +pic-default = -DPIC +# Compile libc.a and libc_p.a with -fPIE/-fpie for static PIE. +pie-default = $(pie-ccflag) +ifeq (yes,$(have-static-pie)) +default-pie-ldflag = -static-pie +else +# Static PIE can't have dynamic relocations in read-only segments since +# static PIE is mapped into memory by kernel. --eh-frame-hdr is needed +# for PIE to support exception. +default-pie-ldflag = -Wl,-pie,--no-dynamic-linker,--eh-frame-hdr,-z,text +endif +endif + # If lazy relocations are disabled, add the -z now flag. Use # LDFLAGS-lib.so instead of LDFLAGS.so, to avoid adding the flag to # test modules. @@ -420,7 +440,7 @@ endif # Command for statically linking programs with the C library. ifndef +link-static +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \ - $(DEFAULT-LDFLAGS-$(@F)) \ + $(firstword $(DEFAULT-LDFLAGS-$(@F)) $(default-pie-ldflag)) \ $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \ $(firstword $(CRT-$(@F)) $(csu-objpfx)$(static-start-installed-name)) \ $(+preinit) $(+prectorT) \ @@ -637,8 +657,14 @@ endif +prectorS = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtbeginS.o` +postctorS = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtendS.o` # Variants of the two previous definitions for statically linking programs. +ifeq (yes,$(enable-static-pie)) +# Static PIE must use PIE variants. ++prectorT = $(+prectorS) ++postctorT = $(+postctorS) +else +prectorT = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtbeginT.o` +postctorT = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtend.o` +endif csu-objpfx = $(common-objpfx)csu/ elf-objpfx = $(common-objpfx)elf/ @@ -959,7 +985,8 @@ libtypes = $(foreach o,$(object-suffixes-for-libc),$(libtype$o)) all-object-suffixes := .o .os .oS object-suffixes := CPPFLAGS-.o = $(pic-default) -CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) +# libc.a must be compiled with -fPIE/-fpie for static PIE. +CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) $(pie-default) libtype.o := lib%.a object-suffixes += .o ifeq (yes,$(build-shared)) @@ -984,7 +1011,8 @@ ifeq (yes,$(build-profile)) all-object-suffixes += .op object-suffixes += .op CPPFLAGS-.op = -DPROF $(pic-default) -CFLAGS-.op = -pg +# libc_p.a must be compiled with -fPIE/-fpie for static PIE. +CFLAGS-.op = -pg $(pie-default) libtype.op = lib%_p.a endif diff --git a/NEWS b/NEWS index 1c5da21327..9212ef444d 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,11 @@ Version 2.27 Major new features: +* Add --enable-static-pie configure option to build static PIE. The + resulting libc.a can be used with the GCC option, -static-pie, which + is available with GCC 8 or above, to create static position independent + executable (static PIE). + * Optimized x86-64 asin, atan2, exp, expf, log, pow, atan, sin and tan with FMA, contributed by Arjan van de Ven and H.J. Lu from Intel. diff --git a/config.h.in b/config.h.in index c140ff3ecb..f7db916711 100644 --- a/config.h.in +++ b/config.h.in @@ -244,6 +244,9 @@ /* Build glibc with tunables support. */ #define HAVE_TUNABLES 0 +/* Define if static PIE is enabled. */ +#define ENABLE_STATIC_PIE 0 + /* Some compiler options may now allow to use ebp in __asm__ (used mainly in i386 6 argument syscall issue). */ #define CAN_USE_REGISTER_ASM_EBP 0 diff --git a/configure b/configure index d9d9243238..eb3c4225e3 100755 --- a/configure +++ b/configure @@ -765,6 +765,7 @@ with_default_link enable_sanity_checks enable_shared enable_profile +enable_static_pie enable_timezone_tools enable_hardcoded_path_in_tests enable_stackguard_randomization @@ -1420,6 +1421,7 @@ Optional Features: in special situations) [default=yes] --enable-shared build shared library [default=yes if GNU ld] --enable-profile build profiled library [default=no] + --enable-static-pie build static executables as PIE [default=no] --disable-timezone-tools do not install timezone tools [default=install] --enable-hardcoded-path-in-tests @@ -3365,6 +3367,13 @@ else profile=no fi +# Check whether --enable-static-pie was given. +if test "${enable_static_pie+set}" = set; then : + enableval=$enable_static_pie; static_pie=$enableval +else + static_pie=no +fi + # Check whether --enable-timezone-tools was given. if test "${enable_timezone_tools+set}" = set; then : enableval=$enable_timezone_tools; enable_timezone_tools=$enableval @@ -5805,6 +5814,62 @@ fi $as_echo "$libc_linker_feature" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker that supports --no-dynamic-linker" >&5 +$as_echo_n "checking for linker that supports --no-dynamic-linker... " >&6; } +libc_linker_feature=no +if test x"$gnu_ld" = x"yes"; then + libc_linker_check=`$LD -v --help 2>/dev/null | grep "\--no-dynamic-linker"` + if test -n "$libc_linker_check"; then + cat > conftest.c <<EOF +int _start (void) { return 42; } +EOF + if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp + -Wl,--no-dynamic-linker -nostdlib -nostartfiles + -fPIC -shared -o conftest.so conftest.c + 1>&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } + then + libc_linker_feature=yes + fi + rm -f conftest* + fi +fi +if test $libc_linker_feature = yes; then + libc_cv_no_dynamic_linker=yes +else + libc_cv_no_dynamic_linker=no +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5 +$as_echo "$libc_linker_feature" >&6; } +config_vars="$config_vars +have-no-dynamic-linker = $libc_cv_no_dynamic_linker" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -static-pie" >&5 +$as_echo_n "checking for -static-pie... " >&6; } +if ${libc_cv_static_pie+:} false; then : + $as_echo_n "(cached) " >&6 +else + if { ac_try='${CC-cc} -static-pie -xc /dev/null -S -o /dev/null' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + libc_cv_static_pie=yes +else + libc_cv_static_pie=no +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_static_pie" >&5 +$as_echo "$libc_cv_static_pie" >&6; } +config_vars="$config_vars +have-static-pie = $libc_cv_static_pie" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -fpie" >&5 $as_echo_n "checking for -fpie... " >&6; } if ${libc_cv_fpie+:} false; then : @@ -6704,6 +6769,19 @@ $as_echo "$libc_cv_pie_default" >&6; } libc_cv_multidir=`${CC-cc} $CFLAGS $CPPFLAGS -print-multi-directory` +if test "$static_pie" = yes; then + # The linker must support --no-dynamic-linker. + if test "$libc_cv_no_dynamic_linker" != yes; then + as_fn_error $? "linker support for --no-dynamic-linker needed" "$LINENO" 5 + fi + # Default to PIE. + libc_cv_pie_default=yes + $as_echo "#define ENABLE_STATIC_PIE 1" >>confdefs.h + +fi +config_vars="$config_vars +enable-static-pie = $static_pie" + diff --git a/configure.ac b/configure.ac index 8ebc490a55..ae219f8fe0 100644 --- a/configure.ac +++ b/configure.ac @@ -176,6 +176,11 @@ AC_ARG_ENABLE([profile], [build profiled library @<:@default=no@:>@]), [profile=$enableval], [profile=no]) +AC_ARG_ENABLE([static-pie], + AC_HELP_STRING([--enable-static-pie], + [build static executables as PIE @<:@default=no@:>@]), + [static_pie=$enableval], + [static_pie=no]) AC_ARG_ENABLE([timezone-tools], AC_HELP_STRING([--disable-timezone-tools], [do not install timezone tools @<:@default=install@:>@]), @@ -1281,6 +1286,19 @@ LIBC_LINKER_FEATURE([-z execstack], [-Wl,-z,execstack], [libc_cv_z_execstack=yes], [libc_cv_z_execstack=no]) AC_SUBST(libc_cv_z_execstack) +LIBC_LINKER_FEATURE([--no-dynamic-linker], + [-Wl,--no-dynamic-linker], + [libc_cv_no_dynamic_linker=yes], + [libc_cv_no_dynamic_linker=no]) +LIBC_CONFIG_VAR([have-no-dynamic-linker], [$libc_cv_no_dynamic_linker]) + +AC_CACHE_CHECK(for -static-pie, libc_cv_static_pie, [dnl +LIBC_TRY_CC_OPTION([-static-pie], + [libc_cv_static_pie=yes], + [libc_cv_static_pie=no]) +]) +LIBC_CONFIG_VAR([have-static-pie], [$libc_cv_static_pie]) + AC_CACHE_CHECK(for -fpie, libc_cv_fpie, [dnl LIBC_TRY_CC_OPTION([-fpie], [libc_cv_fpie=yes], [libc_cv_fpie=no]) ]) @@ -1788,6 +1806,17 @@ AC_SUBST(libc_cv_pie_default) libc_cv_multidir=`${CC-cc} $CFLAGS $CPPFLAGS -print-multi-directory` AC_SUBST(libc_cv_multidir) +if test "$static_pie" = yes; then + # The linker must support --no-dynamic-linker. + if test "$libc_cv_no_dynamic_linker" != yes; then + AC_MSG_ERROR([linker support for --no-dynamic-linker needed]) + fi + # Default to PIE. + libc_cv_pie_default=yes + AC_DEFINE(ENABLE_STATIC_PIE) +fi +LIBC_CONFIG_VAR([enable-static-pie], [$static_pie]) + AC_SUBST(profile) AC_SUBST(static_nss) diff --git a/csu/Makefile b/csu/Makefile index e42a32b3eb..e8ff1ec257 100644 --- a/csu/Makefile +++ b/csu/Makefile @@ -37,7 +37,8 @@ extra-objs = start.o \ S$(start-installed-name) omit-deps = $(patsubst %.o,%,$(start-installed-name) g$(start-installed-name) \ b$(start-installed-name) $(csu-dummies) \ - S$(start-installed-name)) + S$(start-installed-name) \ + r$(start-installed-name)) install-lib = $(start-installed-name) g$(start-installed-name) $(csu-dummies) # No tests are allowed in the csu/ subdirectory because the startup @@ -55,6 +56,10 @@ extra-objs += gmon-start.o endif install-lib += S$(start-installed-name) generated += start.os +ifeq (yes,$(enable-static-pie)) +extra-objs += r$(start-installed-name) +install-lib += r$(start-installed-name) +endif else extra-objs += gmon-start.o endif @@ -82,7 +87,10 @@ multilib-extra-objs = $(addprefix $(multidir)/, $(install-lib)) extra-objs += $(multilib-extra-objs) endif -extra-objs += abi-note.o init.o +extra-objs += abi-note.o init.o static-reloc.o +ifeq (yes,$(build-shared)) +extra-objs += static-reloc.os +endif asm-CPPFLAGS += -I$(objpfx). # Enable unwinding so backtrace unwinds to __libc_start_main @@ -101,6 +109,9 @@ ifndef start-installed-name-rule # We link the ELF startfile along with a SHT_NOTE section indicating # the kernel ABI the binaries linked with this library will require. $(objpfx)$(start-installed-name): $(objpfx)start.o $(objpfx)abi-note.o \ + $(objpfx)init.o $(objpfx)static-reloc.o + $(link-relocatable) +$(objpfx)r$(start-installed-name): $(objpfx)start.o $(objpfx)abi-note.o \ $(objpfx)init.o $(link-relocatable) $(objpfx)S$(start-installed-name): $(objpfx)start.os $(objpfx)abi-note.o \ @@ -113,7 +124,7 @@ endif # to turn on profiling code at startup. ifeq (yes,$(build-shared)) $(objpfx)g$(start-installed-name): \ - $(objpfx)g%: $(objpfx)S% $(objpfx)gmon-start.os + $(objpfx)g%: $(objpfx)S% $(objpfx)gmon-start.os $(objpfx)static-reloc.os $(link-relocatable) ifneq ($(start-installed-name),$(static-start-installed-name)) $(objpfx)g$(static-start-installed-name): \ diff --git a/csu/libc-start.c b/csu/libc-start.c index 24c63be02f..34dd125260 100644 --- a/csu/libc-start.c +++ b/csu/libc-start.c @@ -141,6 +141,8 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), __libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up; #ifndef SHARED + _dl_relocate_static_pie (); + char **ev = &argv[argc + 1]; __environ = ev; diff --git a/csu/libc-tls.c b/csu/libc-tls.c index 00138eb43a..1f8ddaf543 100644 --- a/csu/libc-tls.c +++ b/csu/libc-tls.c @@ -114,6 +114,8 @@ __libc_setup_tls (void) size_t tcb_offset; const ElfW(Phdr) *phdr; + struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded; + /* Look through the TLS segment if there is any. */ if (_dl_phdr != NULL) for (phdr = _dl_phdr; phdr < &_dl_phdr[_dl_phnum]; ++phdr) @@ -122,7 +124,7 @@ __libc_setup_tls (void) /* Remember the values we need. */ memsz = phdr->p_memsz; filesz = phdr->p_filesz; - initimage = (void *) phdr->p_vaddr; + initimage = (void *) phdr->p_vaddr + main_map->l_addr; align = phdr->p_align; if (phdr->p_align > max_align) max_align = phdr->p_align; @@ -163,8 +165,6 @@ __libc_setup_tls (void) _dl_static_dtv[0].counter = (sizeof (_dl_static_dtv) / sizeof (_dl_static_dtv[0])) - 2; // _dl_static_dtv[1].counter = 0; would be needed if not already done - struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded; - /* Initialize the TLS block. */ #if TLS_TCB_AT_TP _dl_static_dtv[2].pointer.val = ((char *) tlsblock + tcb_offset diff --git a/csu/static-reloc.c b/csu/static-reloc.c new file mode 100644 index 0000000000..37be72c8ea --- /dev/null +++ b/csu/static-reloc.c @@ -0,0 +1,26 @@ +/* Special startup support for non-PIE static executables. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#if ENABLE_STATIC_PIE +#include <ldsodefs.h> + +void +_dl_relocate_static_pie (void) +{ +} +#endif diff --git a/elf/Makefile b/elf/Makefile index a31fb72498..cb035e63aa 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -24,7 +24,8 @@ include ../Makeconfig headers = elf.h bits/elfclass.h link.h bits/link.h routines = $(all-dl-routines) dl-support dl-iteratephdr \ dl-addr dl-addr-obj enbl-secure dl-profstub \ - dl-origin dl-libc dl-sym dl-sysdep dl-error + dl-origin dl-libc dl-sym dl-sysdep dl-error \ + dl-reloc-static-pie # The core dynamic linking functions are in libc for the static and # profiled libraries. @@ -52,7 +53,7 @@ endif all-dl-routines = $(dl-routines) $(sysdep-dl-routines) # But they are absent from the shared libc, because that code is in ld.so. elide-routines.os = $(all-dl-routines) dl-support enbl-secure dl-origin \ - dl-sysdep dl-exception + dl-sysdep dl-exception dl-reloc-static-pie shared-only-routines += dl-caller # ld.so uses those routines, plus some special stuff for being the program diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c new file mode 100644 index 0000000000..6e43aea76a --- /dev/null +++ b/elf/dl-reloc-static-pie.c @@ -0,0 +1,52 @@ +/* Support for relocating static PIE. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#if ENABLE_STATIC_PIE +#include <unistd.h> +#include <ldsodefs.h> +#include "dynamic-link.h" + +/* Relocate static executable with PIE. */ + +void +_dl_relocate_static_pie (void) +{ + struct link_map *main_map = _dl_get_dl_main_map (); + +# define STATIC_PIE_BOOTSTRAP +# define BOOTSTRAP_MAP (main_map) +# define RESOLVE_MAP(sym, version, flags) BOOTSTRAP_MAP +# include "dynamic-link.h" + + /* Figure out the run-time load address of static PIE. */ + main_map->l_addr = elf_machine_load_address (); + + /* Read our own dynamic section and fill in the info array. */ + main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ()); + elf_get_dynamic_info (main_map, NULL); + +# ifdef ELF_MACHINE_BEFORE_RTLD_RELOC + ELF_MACHINE_BEFORE_RTLD_RELOC (main_map->l_info); +# endif + + /* Relocate ourselves so we can do normal function calls and + data access using the global offset table. */ + ELF_DYNAMIC_RELOCATE (main_map, 0, 0, 0); + main_map->l_relocated = 1; +} +#endif 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 diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h index ebea7567cd..6278649711 100644 --- a/elf/dynamic-link.h +++ b/elf/dynamic-link.h @@ -94,7 +94,7 @@ elf_machine_lazy_rel (struct link_map *map, #ifdef RESOLVE_MAP -# ifdef RTLD_BOOTSTRAP +# if defined RTLD_BOOTSTRAP || defined STATIC_PIE_BOOTSTRAP # define ELF_DURING_STARTUP (1) # else # define ELF_DURING_STARTUP (0) diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h index 7525c3a5b2..eb26d23649 100644 --- a/elf/get-dynamic-info.h +++ b/elf/get-dynamic-info.h @@ -38,7 +38,7 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) typedef Elf64_Xword d_tag_utype; #endif -#ifndef RTLD_BOOTSTRAP +#if !defined RTLD_BOOTSTRAP && !defined STATIC_PIE_BOOTSTRAP if (dyn == NULL) return; #endif @@ -139,9 +139,11 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) /* Only the bind now flags are allowed. */ assert (info[VERSYMIDX (DT_FLAGS_1)] == NULL || (info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val & ~DF_1_NOW) == 0); + /* Flags must not be set for ld.so. */ assert (info[DT_FLAGS] == NULL || (info[DT_FLAGS]->d_un.d_val & ~DF_BIND_NOW) == 0); - /* Flags must not be set for ld.so. */ +#endif +#if defined RTLD_BOOTSTRAP || defined STATIC_PIE_BOOTSTRAP assert (info[DT_RUNPATH] == NULL); assert (info[DT_RPATH] == NULL); #else diff --git a/gmon/Makefile b/gmon/Makefile index 89ab3fc7da..f83fcc9d71 100644 --- a/gmon/Makefile +++ b/gmon/Makefile @@ -39,6 +39,10 @@ tests-static += tst-gmon-static ifeq (yesyes,$(have-fpie)$(build-shared)) tests += tst-gmon-pie tests-pie += tst-gmon-pie +ifeq (yes,$(enable-static-pie)) +tests += tst-gmon-static-pie +tests-static += tst-gmon-static-pie +endif endif # The mcount code won't work without a frame pointer. @@ -67,6 +71,15 @@ ifeq ($(run-built-tests),yes) tests-special += $(objpfx)tst-gmon-pie-gprof.out endif +ifeq (yes,$(enable-static-pie)) +CFLAGS-tst-gmon-static-pie.c := $(PIE-ccflag) -fno-omit-frame-pointer -pg +CRT-tst-gmon-static-pie := $(csu-objpfx)grcrt1.o +tst-gmon-static-pie-ENV := GMON_OUT_PREFIX=$(objpfx)tst-gmon-static-pie.data +ifeq ($(run-built-tests),yes) +tests-special += $(objpfx)tst-gmon-static-pie-gprof.out +endif +endif + include ../Rules @@ -111,3 +124,13 @@ clean-tst-gmon-pie-data: $(objpfx)tst-gmon-pie-gprof.out: tst-gmon-gprof.sh $(objpfx)tst-gmon-pie.out $(SHELL) $< $(GPROF) $(objpfx)tst-gmon-pie $(objpfx)tst-gmon-pie.data.* > $@; \ $(evaluate-test) + +$(objpfx)tst-gmon-static-pie.out: clean-tst-gmon-static-pie-data +clean-tst-gmon-static-pie-data: + rm -f $(objpfx)tst-gmon-static-pie.data.* + +$(objpfx)tst-gmon-static-pie-gprof.out: tst-gmon-static-gprof.sh \ + $(objpfx)tst-gmon-static-pie.out + $(SHELL) $< $(GPROF) $(objpfx)tst-gmon-static-pie \ + $(objpfx)tst-gmon-static-pie.data.* > $@; \ + $(evaluate-test) diff --git a/gmon/tst-gmon-static-pie.c b/gmon/tst-gmon-static-pie.c new file mode 100644 index 0000000000..1eef2583b6 --- /dev/null +++ b/gmon/tst-gmon-static-pie.c @@ -0,0 +1 @@ +#include "tst-gmon.c" diff --git a/manual/install.texi b/manual/install.texi index f1fa28c937..86193ade3f 100644 --- a/manual/install.texi +++ b/manual/install.texi @@ -120,6 +120,13 @@ Don't build shared libraries even if it is possible. Not all systems support shared libraries; you need ELF support and (currently) the GNU linker. +@item --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. + @item --disable-profile Don't build libraries with profiling information. You may want to use this option if you don't plan to do profiling. diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index 52a792a597..af89f5eeb4 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -1051,6 +1051,17 @@ extern void _dl_determine_tlsoffset (void) attribute_hidden; stack protector, among other things). */ void __libc_setup_tls (void); +# if ENABLE_STATIC_PIE +/* Relocate static executable with PIE. */ +extern void _dl_relocate_static_pie (void) attribute_hidden; + +/* Get a pointer to _dl_main_map. */ +extern struct link_map * _dl_get_dl_main_map (void) + __attribute__ ((visibility ("hidden"))); +# else +# define _dl_relocate_static_pie() +# endif + /* Initialization of libpthread for statically linked applications. If libpthread is not linked in, this is an empty function. */ void __pthread_initialize_minimal (void) weak_function; diff --git a/sysdeps/i386/configure b/sysdeps/i386/configure index 4cf968d8bc..90c63caf35 100644 --- a/sysdeps/i386/configure +++ b/sysdeps/i386/configure @@ -50,6 +50,39 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_compiler_builtin_inlined" >&5 $as_echo "$libc_compiler_builtin_inlined" >&6; } +if test "$static_pie" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker static PIE support" >&5 +$as_echo_n "checking for linker static PIE support... " >&6; } +if ${libc_cv_ld_static_pie+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat > conftest.s <<\EOF + .text + .global _start +_start: + movl _start@GOT(%ebx), %eax +EOF + libc_cv_pie_option="-Wl,-pie" + libc_cv_ld_static_pie=no + if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + if $READELF -r conftest | grep 'There are no relocations in this file.' > /dev/null; then + libc_cv_ld_static_pie=yes + fi + fi +rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_ld_static_pie" >&5 +$as_echo "$libc_cv_ld_static_pie" >&6; } + if test "$libc_cv_ld_static_pie" != yes; then + as_fn_error $? "linker support for static PIE needed" "$LINENO" 5 + fi +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Intel MPX support" >&5 $as_echo_n "checking for Intel MPX support... " >&6; } if ${libc_cv_asm_mpx+:} false; then : diff --git a/sysdeps/i386/configure.ac b/sysdeps/i386/configure.ac index b598b120bc..6d2068d2b3 100644 --- a/sysdeps/i386/configure.ac +++ b/sysdeps/i386/configure.ac @@ -30,6 +30,29 @@ LIBC_COMPILER_BUILTIN_INLINED( *** Please use host i786, i686, i586, or i486. *** For example: /source/glibc/configure CFLAGS='-O2 -march=i686' ...])]) +dnl Check if linker can convert "movl main@GOT(%ebx), %eax" to +dnl "leal main@GOTOFF(%ebx), %eax" for static PIE. +if test "$static_pie" = yes; then + AC_CACHE_CHECK(for linker static PIE support, libc_cv_ld_static_pie, [dnl +cat > conftest.s <<\EOF + .text + .global _start +_start: + movl _start@GOT(%ebx), %eax +EOF + libc_cv_pie_option="-Wl,-pie" + libc_cv_ld_static_pie=no + if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&AS_MESSAGE_LOG_FD); then + if $READELF -r conftest | grep 'There are no relocations in this file.' > /dev/null; then + libc_cv_ld_static_pie=yes + fi + fi +rm -f conftest*]) + if test "$libc_cv_ld_static_pie" != yes; then + AC_MSG_ERROR([linker support for static PIE needed]) + fi +fi + dnl Check whether asm supports Intel MPX AC_CACHE_CHECK(for Intel MPX support, libc_cv_asm_mpx, [dnl cat > conftest.s <<\EOF diff --git a/sysdeps/x86_64/configure b/sysdeps/x86_64/configure index efef46b1b7..8674d14569 100644 --- a/sysdeps/x86_64/configure +++ b/sysdeps/x86_64/configure @@ -85,6 +85,39 @@ if test x"$build_mathvec" = xnotset; then build_mathvec=yes fi +if test "$static_pie" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker static PIE support" >&5 +$as_echo_n "checking for linker static PIE support... " >&6; } +if ${libc_cv_ld_static_pie+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat > conftest.s <<\EOF + .text + .global _start + .weak foo +_start: + leaq foo(%rip), %rax +EOF + libc_cv_pie_option="-Wl,-pie" + if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + libc_cv_ld_static_pie=yes + else + libc_cv_ld_static_pie=no + fi +rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_ld_static_pie" >&5 +$as_echo "$libc_cv_ld_static_pie" >&6; } + if test "$libc_cv_ld_static_pie" != yes; then + as_fn_error $? "linker support for static PIE needed" "$LINENO" 5 + fi +fi + $as_echo "#define PI_STATIC_AND_HIDDEN 1" >>confdefs.h diff --git a/sysdeps/x86_64/configure.ac b/sysdeps/x86_64/configure.ac index fa86e953ee..b7d2c0124f 100644 --- a/sysdeps/x86_64/configure.ac +++ b/sysdeps/x86_64/configure.ac @@ -44,6 +44,31 @@ if test x"$build_mathvec" = xnotset; then build_mathvec=yes fi +dnl Check if linker supports static PIE with the fix for +dnl +dnl https://sourceware.org/bugzilla/show_bug.cgi?id=21782 +dnl +if test "$static_pie" = yes; then + AC_CACHE_CHECK(for linker static PIE support, libc_cv_ld_static_pie, [dnl +cat > conftest.s <<\EOF + .text + .global _start + .weak foo +_start: + leaq foo(%rip), %rax +EOF + libc_cv_pie_option="-Wl,-pie" + if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&AS_MESSAGE_LOG_FD); then + libc_cv_ld_static_pie=yes + else + libc_cv_ld_static_pie=no + fi +rm -f conftest*]) + if test "$libc_cv_ld_static_pie" != yes; then + AC_MSG_ERROR([linker support for static PIE needed]) + fi +fi + dnl It is always possible to access static and hidden symbols in an dnl position independent way. AC_DEFINE(PI_STATIC_AND_HIDDEN) -- 2.14.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-11-19 16:17 ` H.J. Lu 2017-11-19 19:52 ` H.J. Lu @ 2017-11-20 14:17 ` Joseph Myers 2017-11-23 14:09 ` H.J. Lu 1 sibling, 1 reply; 37+ messages in thread From: Joseph Myers @ 2017-11-20 14:17 UTC (permalink / raw) To: H.J. Lu; +Cc: Florian Weimer, GNU C Library On Sun, 19 Nov 2017, H.J. Lu wrote: > > 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. A binutils segfault / BFD internal error is always a bug, even on invalid input. Those should all have binutils bugs filed (if present with current binutils master) and those bugs referenced in the commit message. If this patch reaches consensus for commit, the status information for architectures that don't build, or that build but have not been verified to have execution tests work in this configuration, will need to go on a wiki page linked from https://sourceware.org/glibc/wiki/PortStatus (or on that page itself), describing how to verify if the feature works (given that it builds) and what's needed to fix things if there is a build problem. Then that architecture information can be removed as and when someone gets things working, and verifies that they are working, on particular architectures. -- Joseph S. Myers joseph@codesourcery.com ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-11-20 14:17 ` Joseph Myers @ 2017-11-23 14:09 ` H.J. Lu 0 siblings, 0 replies; 37+ messages in thread From: H.J. Lu @ 2017-11-23 14:09 UTC (permalink / raw) To: Joseph Myers; +Cc: Florian Weimer, GNU C Library On Mon, Nov 20, 2017 at 6:17 AM, Joseph Myers <joseph@codesourcery.com> wrote: > On Sun, 19 Nov 2017, H.J. Lu wrote: > >> > 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. > > A binutils segfault / BFD internal error is always a bug, even on invalid > input. Those should all have binutils bugs filed (if present with current > binutils master) and those bugs referenced in the commit message. I have filed and listed 2 of linker bugs in my commit message. There may be more once target maintainers start working on static PIE. > If this patch reaches consensus for commit, the status information for > architectures that don't build, or that build but have not been verified > to have execution tests work in this configuration, will need to go on a > wiki page linked from https://sourceware.org/glibc/wiki/PortStatus (or on > that page itself), describing how to verify if the feature works (given > that it builds) and what's needed to fix things if there is a build > problem. Then that architecture information can be removed as and when > someone gets things working, and verifies that they are working, on > particular architectures. I will do that once we have reached consensus for commit. It is very unlikely that non-x86 targets will have working static PIE before glibc 2.27 is branched. I'd like to get my patch in and developers can work on it. Are there any objections to enable static PIE in glibc 2.27 even if it is only verified to work on x86? Thanks. -- H.J. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-11-19 2:40 ` H.J. Lu 2017-11-19 15:39 ` Florian Weimer @ 2017-11-20 12:16 ` Szabolcs Nagy 2017-11-23 13:59 ` H.J. Lu 1 sibling, 1 reply; 37+ messages in thread From: Szabolcs Nagy @ 2017-11-20 12:16 UTC (permalink / raw) To: H.J. Lu, Joseph Myers; +Cc: nd, GNU C Library On 19/11/17 02:40, H.J. Lu wrote: > 3. Linker should resolve undefined weak symbols to 0 in static PIE: > > https://sourceware.org/bugzilla/show_bug.cgi?id=22269 > > 4. Many ELF backend linkers incorrectly check bfd_link_pic for TLS > relocations, which should check bfd_link_executable instead: > > https://sourceware.org/bugzilla/show_bug.cgi?id=22263 > > Tested on i686 and x86-64. > > Build results of build-many-glibcs.py with --enable-static-pie with all > patches for static PIE applied are > > PASS: glibcs-aarch64_be-linux-gnu build > PASS: glibcs-aarch64-linux-gnu build i'd expect these to fail on current binutils master (linking with undefweak symbol fails now because of the issues listed above, i'll try to prepare a binutils patch) ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-11-20 12:16 ` Szabolcs Nagy @ 2017-11-23 13:59 ` H.J. Lu 2017-11-24 13:07 ` Szabolcs Nagy 0 siblings, 1 reply; 37+ messages in thread From: H.J. Lu @ 2017-11-23 13:59 UTC (permalink / raw) To: Szabolcs Nagy; +Cc: Joseph Myers, nd, GNU C Library On Mon, Nov 20, 2017 at 4:16 AM, Szabolcs Nagy <szabolcs.nagy@arm.com> wrote: > On 19/11/17 02:40, H.J. Lu wrote: >> 3. Linker should resolve undefined weak symbols to 0 in static PIE: >> >> https://sourceware.org/bugzilla/show_bug.cgi?id=22269 >> >> 4. Many ELF backend linkers incorrectly check bfd_link_pic for TLS >> relocations, which should check bfd_link_executable instead: >> >> https://sourceware.org/bugzilla/show_bug.cgi?id=22263 >> >> Tested on i686 and x86-64. >> >> Build results of build-many-glibcs.py with --enable-static-pie with all >> patches for static PIE applied are >> >> PASS: glibcs-aarch64_be-linux-gnu build >> PASS: glibcs-aarch64-linux-gnu build > > i'd expect these to fail on current binutils master > > (linking with undefweak symbol fails now because of the issues > listed above, i'll try to prepare a binutils patch) > Do you think you can fix arm64 for glibc 2.27? -- H.J. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-11-23 13:59 ` H.J. Lu @ 2017-11-24 13:07 ` Szabolcs Nagy 2017-11-24 15:03 ` H.J. Lu 0 siblings, 1 reply; 37+ messages in thread From: Szabolcs Nagy @ 2017-11-24 13:07 UTC (permalink / raw) To: H.J. Lu; +Cc: nd, Joseph Myers, GNU C Library On 23/11/17 13:59, H.J. Lu wrote: > On Mon, Nov 20, 2017 at 4:16 AM, Szabolcs Nagy <szabolcs.nagy@arm.com> wrote: >> On 19/11/17 02:40, H.J. Lu wrote: >>> 3. Linker should resolve undefined weak symbols to 0 in static PIE: >>> >>> https://sourceware.org/bugzilla/show_bug.cgi?id=22269 >>> >>> 4. Many ELF backend linkers incorrectly check bfd_link_pic for TLS >>> relocations, which should check bfd_link_executable instead: >>> >>> https://sourceware.org/bugzilla/show_bug.cgi?id=22263 >>> >>> Tested on i686 and x86-64. >>> >>> Build results of build-many-glibcs.py with --enable-static-pie with all >>> patches for static PIE applied are >>> >>> PASS: glibcs-aarch64_be-linux-gnu build >>> PASS: glibcs-aarch64-linux-gnu build >> >> i'd expect these to fail on current binutils master >> >> (linking with undefweak symbol fails now because of the issues >> listed above, i'll try to prepare a binutils patch) >> > > Do you think you can fix arm64 for glibc 2.27? > the aarch64 glibc tests pass with the pie patches and the start code fix i posted (and with a fixed bfd linker). the bfd linker cannot turn GOT load into pc relative address computation when the symbol is defined in the same module, so 3 variant of the start asm is needed (in principle the linker could do it if the pie code is smaller than 4G). this might affect other targets too. i find the dummy _dl_relocate_static_pie in crt1.o a bit ugly, such symbol is not reserved for extern linkage, but it is added to every static linked executable, and apart from the namespace issue it is new internal abi between libc and crt code, fortunately only the abi between Scrt1.o and libc.so needs to be fixed across libc versions and that is not affected, so this design is probably ok for now. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-11-24 13:07 ` Szabolcs Nagy @ 2017-11-24 15:03 ` H.J. Lu 2017-11-24 22:24 ` H.J. Lu 0 siblings, 1 reply; 37+ messages in thread From: H.J. Lu @ 2017-11-24 15:03 UTC (permalink / raw) To: Szabolcs Nagy; +Cc: nd, Joseph Myers, GNU C Library On Fri, Nov 24, 2017 at 5:06 AM, Szabolcs Nagy <szabolcs.nagy@arm.com> wrote: > On 23/11/17 13:59, H.J. Lu wrote: >> On Mon, Nov 20, 2017 at 4:16 AM, Szabolcs Nagy <szabolcs.nagy@arm.com> wrote: >>> On 19/11/17 02:40, H.J. Lu wrote: >>>> 3. Linker should resolve undefined weak symbols to 0 in static PIE: >>>> >>>> https://sourceware.org/bugzilla/show_bug.cgi?id=22269 >>>> >>>> 4. Many ELF backend linkers incorrectly check bfd_link_pic for TLS >>>> relocations, which should check bfd_link_executable instead: >>>> >>>> https://sourceware.org/bugzilla/show_bug.cgi?id=22263 >>>> >>>> Tested on i686 and x86-64. >>>> >>>> Build results of build-many-glibcs.py with --enable-static-pie with all >>>> patches for static PIE applied are >>>> >>>> PASS: glibcs-aarch64_be-linux-gnu build >>>> PASS: glibcs-aarch64-linux-gnu build >>> >>> i'd expect these to fail on current binutils master >>> >>> (linking with undefweak symbol fails now because of the issues >>> listed above, i'll try to prepare a binutils patch) >>> >> >> Do you think you can fix arm64 for glibc 2.27? >> > > the aarch64 glibc tests pass with the pie patches and > the start code fix i posted (and with a fixed bfd linker). Great. Linker changes look quite straight forward. I will update my commit message. > the bfd linker cannot turn GOT load into pc relative address > computation when the symbol is defined in the same module, > so 3 variant of the start asm is needed (in principle the > linker could do it if the pie code is smaller than 4G). > this might affect other targets too. I don't think the default glibc build supports large model on x86-64 either. > i find the dummy _dl_relocate_static_pie in crt1.o a bit > ugly, such symbol is not reserved for extern linkage, > but it is added to every static linked executable, and > apart from the namespace issue it is new internal abi > between libc and crt code, fortunately only the abi > between Scrt1.o and libc.so needs to be fixed across > libc versions and that is not affected, so this > design is probably ok for now. > We can revisit it later when we find a better approach. -- H.J. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-11-24 15:03 ` H.J. Lu @ 2017-11-24 22:24 ` H.J. Lu 2017-11-30 14:00 ` H.J. Lu 2017-11-30 21:45 ` Carlos O'Donell 0 siblings, 2 replies; 37+ messages in thread From: H.J. Lu @ 2017-11-24 22:24 UTC (permalink / raw) To: Szabolcs Nagy; +Cc: nd, Joseph Myers, GNU C Library [-- Attachment #1: Type: text/plain, Size: 1461 bytes --] On Fri, Nov 24, 2017 at 7:03 AM, H.J. Lu <hjl.tools@gmail.com> wrote: > On Fri, Nov 24, 2017 at 5:06 AM, Szabolcs Nagy <szabolcs.nagy@arm.com> wrote: >> On 23/11/17 13:59, H.J. Lu wrote: >>> On Mon, Nov 20, 2017 at 4:16 AM, Szabolcs Nagy <szabolcs.nagy@arm.com> wrote: >>>> On 19/11/17 02:40, H.J. Lu wrote: >>>>> 3. Linker should resolve undefined weak symbols to 0 in static PIE: >>>>> >>>>> https://sourceware.org/bugzilla/show_bug.cgi?id=22269 >>>>> >>>>> 4. Many ELF backend linkers incorrectly check bfd_link_pic for TLS >>>>> relocations, which should check bfd_link_executable instead: >>>>> >>>>> https://sourceware.org/bugzilla/show_bug.cgi?id=22263 >>>>> >>>>> Tested on i686 and x86-64. >>>>> >>>>> Build results of build-many-glibcs.py with --enable-static-pie with all >>>>> patches for static PIE applied are >>>>> >>>>> PASS: glibcs-aarch64_be-linux-gnu build >>>>> PASS: glibcs-aarch64-linux-gnu build >>>> >>>> i'd expect these to fail on current binutils master >>>> >>>> (linking with undefweak symbol fails now because of the issues >>>> listed above, i'll try to prepare a binutils patch) >>>> >>> >>> Do you think you can fix arm64 for glibc 2.27? >>> >> >> the aarch64 glibc tests pass with the pie patches and >> the start code fix i posted (and with a fixed bfd linker). > > Great. Linker changes look quite straight forward. I will > update my commit message. Here is the patch with the updated commit message. Thanks. -- H.J. [-- Attachment #2: 0001-Add-enable-static-pie-configure-option-to-build-stat.patch --] [-- Type: text/x-patch, Size: 41379 bytes --] From 7026a79c1f71f5decd135208503fd4186193ffb8 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <hjl.tools@gmail.com> Date: Mon, 17 Jul 2017 08:17:32 -0700 Subject: [PATCH] Add --enable-static-pie configure option to build static PIE [BZ #19574] 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 following changes are made for static PIE: 1. Add a new function, _dl_relocate_static_pie, to: a. Get the run-time load address. b. Read the dynamic section. c. Perform dynamic relocations. Dynamic linker also performs these steps. But static PIE doesn't load any shared objects. 2. Call _dl_relocate_static_pie at entrance of LIBC_START_MAIN in libc.a. crt1.o, which is used to create dynamic and non-PIE static executables, is updated to include a dummy _dl_relocate_static_pie. rcrt1.o is added to create static PIE, which will link in the real _dl_relocate_static_pie. grcrt1.o is also added to create static PIE with -pg. GCC 8 has been updated to support rcrt1.o and grcrt1.o for static PIE. 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. All functions in static PIE are local functions. If PIE start.S can't reach main () defined in a shared object, the code sequence: pass addess of local_main to __libc_start_main ... local_main: tail call to main via PLT can be used. 2. start.S is updated to check PIC instead SHARED for PIC code path and avoid dynamic relocation, when PIC is defined and SHARED isn't defined, to support static PIE. Patches are submitted for aarch64, hppa, m68k, microblaze and sparc. 3. All assembly codes are updated check PIC instead SHARED for PIC code path to avoid dynamic relocations in read-only sections. 4. All assembly codes are updated check SHARED instead PIC for static symbol name. A patch is submitted for tile. 5. elf_machine_load_address in dl-machine.h are updated to support static PIE. Patches are submitted for aarch64, s390 and sh. 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. 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. 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 The i386 linker needs to be able to convert "movl main@GOT(%ebx), %eax" to "leal main@GOTOFF(%ebx), %eax" if main is defined locally. Binutils 2.29 or above are OK for i686 and x86-64. But linker status for other targets need to be verified. 3. Linker should resolve undefined weak symbols to 0 in static PIE: https://sourceware.org/bugzilla/show_bug.cgi?id=22269 4. Many ELF backend linkers incorrectly check bfd_link_pic for TLS relocations, which should check bfd_link_executable instead: https://sourceware.org/bugzilla/show_bug.cgi?id=22263 Tested on aarch64, i686 and x86-64. On aarch64, binutils master branch with 2 patches: https://sourceware.org/ml/binutils/2017-11/msg00455.html https://sourceware.org/ml/binutils/2017-11/msg00456.html applied is required. build-many-glibcs.py with --enable-static-pie with all patches for static PIE applied have many failures: FAIL: glibcs-alpha-linux-gnu build elf/sln is failed to link due to: assertion fail bfd/elf64-alpha.c:4125 This is caused by linker bug and/or non-PIC code in PIE libc.a. FAIL: glibcs-ia64-linux-gnu build elf/sln is failed to link due to: libc.a(sched_yield.o): non-pic code with imm relocation against dynamic symbol `_dl_sysinfo' This is caused by non-PIC version of DO_CALL macro in ia64 sysdep.h. PIE libc.a should use PIC version of DO_CALL, except during startup in static PIE. An ia64 startup.h, similar to i386 startup.h, is needed to handle this. FAIL: glibcs-mips64el-linux-gnu-n32 build FAIL: glibcs-mips64el-linux-gnu-n32-nan2008 build FAIL: glibcs-mips64el-linux-gnu-n32-nan2008-soft build FAIL: glibcs-mips64el-linux-gnu-n32-soft build FAIL: glibcs-mips64-linux-gnu-n32 build FAIL: glibcs-mips64-linux-gnu-n32-nan2008 build FAIL: glibcs-mips64-linux-gnu-n32-nan2008-soft build FAIL: glibcs-mips64-linux-gnu-n32-soft build FAIL: glibcs-mipsel-linux-gnu build FAIL: glibcs-mipsel-linux-gnu-nan2008 build FAIL: glibcs-mipsel-linux-gnu-nan2008-soft build FAIL: glibcs-mipsel-linux-gnu-soft build FAIL: glibcs-mips-linux-gnu build FAIL: glibcs-mips-linux-gnu-nan2008 build FAIL: glibcs-mips-linux-gnu-nan2008-soft build FAIL: glibcs-mips-linux-gnu-soft build elf/sln is failed to link due to: crt1.o: relocation R_MIPS_HI16 against `_gp' can not be used when making a shared object; recompile with -fPIC This is caused by linker bug and/or non-PIC code in crt1.o. FAIL: glibcs-powerpc-linux-gnu build FAIL: glibcs-powerpc-linux-gnu-soft build FAIL: glibcs-powerpc-linux-gnuspe build FAIL: glibcs-powerpc-linux-gnuspe-e500v1 build elf/sln is failed to link due to: ld: read-only segment has dynamic relocations. This is caused by linker bug and/or non-PIC code in PIE libc.a. See: https://sourceware.org/bugzilla/show_bug.cgi?id=22264 FAIL: glibcs-powerpc-linux-gnu-power4 build elf/sln is failed to link due to: findlocale.c:96:(.text+0x22c): @local call to ifunc memchr This is caused by linker bug and/or non-PIC code in PIE libc.a. FAIL: glibcs-s390-linux-gnu build elf/sln is failed to link due to: collect2: fatal error: ld terminated with signal 11 [Segmentation fault], core dumped assertion fail bfd/elflink.c:14242 This is caused by linker bug and/or non-PIC code in PIE libc.a. FAIL: glibcs-sh3eb-linux-gnu build FAIL: glibcs-sh3-linux-gnu build FAIL: glibcs-sh4eb-linux-gnu build FAIL: glibcs-sh4eb-linux-gnu-soft build FAIL: glibcs-sh4-linux-gnu build FAIL: glibcs-sh4-linux-gnu-soft build elf/sln is failed to link due to: ld: read-only segment has dynamic relocations. This is caused by linker bug and/or non-PIC code in PIE libc.a. See: https://sourceware.org/bugzilla/show_bug.cgi?id=22263 Also TLS code sequence in SH assembly syscalls in glibc doesn't match TLS code sequence expected by ld: https://sourceware.org/bugzilla/show_bug.cgi?id=22270 FAIL: glibcs-sparc64-linux-gnu build FAIL: glibcs-sparcv9-linux-gnu build FAIL: glibcs-tilegxbe-linux-gnu build FAIL: glibcs-tilegxbe-linux-gnu-32 build FAIL: glibcs-tilegx-linux-gnu build FAIL: glibcs-tilegx-linux-gnu-32 build FAIL: glibcs-tilepro-linux-gnu build elf/sln is failed to link due to: ld: read-only segment has dynamic relocations. This is caused by linker bug and/or non-PIC code in PIE libc.a. See: https://sourceware.org/bugzilla/show_bug.cgi?id=22263 [BZ #19574] * INSTALL: Regenerated. * Makeconfig (static-start-installed-name): Add the `r' prefix for --enable-static-pie. (pic-default): Updated for --enable-static-pie. (pie-default): New for --enable-static-pie. (default-pie-ldflag): Likewise. (+link-static-before-libc): Use the first of $(DEFAULT-LDFLAGS-$(@F)) and $(default-pie-ldflag). (+prectorT): Updated for --enable-static-pie. (+postctorT): Likewise. (CFLAGS-.o): Add $(pie-default). (CFLAGS-.op): Likewise. * NEWS: Mention --enable-static-pie. * config.h.in (ENABLE_STATIC_PIE): New. * configure.ac (--enable-static-pie): New configure option. (have-no-dynamic-linker): New LIBC_CONFIG_VAR. (have-static-pie): Likewise. Enable static PIE if linker supports --no-dynamic-linker. (ENABLE_STATIC_PIE): New AC_DEFINE. (enable-static-pie): New LIBC_CONFIG_VAR. * configure: Regenerated. * csu/Makefile (omit-deps): Add r$(start-installed-name) for --enable-static-pie. (extra-objs): Likewise. (install-lib): Likewise. (extra-objs): Add static-reloc.o and static-reloc.os ($(objpfx)$(start-installed-name)): Also depend on $(objpfx)static-reloc.o. ($(objpfx)r$(start-installed-name)): New. ($(objpfx)g$(start-installed-name)): Also depend on $(objpfx)static-reloc.os. * csu/libc-start.c (LIBC_START_MAIN): Call _dl_relocate_static_pie in libc.a. * csu/libc-tls.c (__libc_setup_tls): Add main_map->l_addr to initimage. * csu/static-reloc.c: New file. * elf/Makefile (routines): Add dl-reloc-static-pie. (elide-routines.os): Likewise. * elf/dl-reloc-static-pie.c: New file. * elf/dl-support.c (_dl_get_dl_main_map): New function. * elf/dynamic-link.h (ELF_DURING_STARTUP): Also check STATIC_PIE_BOOTSTRAP. * elf/get-dynamic-info.h (elf_get_dynamic_info): Likewise. * gmon/Makefile (tests): Add tst-gmon-static-pie. (tests-static): Likewise. (CFLAGS-tst-gmon-static-pie.c): New. (CRT-tst-gmon-static-pie): Likewise. (tst-gmon-static-pie-ENV): Likewise. (tests-special): Likewise. ($(objpfx)tst-gmon-static-pie.out): Likewise. (clean-tst-gmon-static-pie-data): Likewise. ($(objpfx)tst-gmon-static-pie-gprof.out): Likewise. * gmon/tst-gmon-static-pie.c: New file. * manual/install.texi: Document --enable-static-pie. * sysdeps/generic/ldsodefs.h (_dl_relocate_static_pie): New. (_dl_get_dl_main_map): Likewise. * sysdeps/i386/configure.ac: Check if linker supports static PIE. * sysdeps/x86_64/configure.ac: Likewise. * sysdeps/i386/configure: Regenerated. * sysdeps/x86_64/configure: Likewise. --- INSTALL | 7 ++++ Makeconfig | 34 ++++++++++++++++++-- NEWS | 5 +++ config.h.in | 3 ++ configure | 78 +++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 29 +++++++++++++++++ csu/Makefile | 17 ++++++++-- csu/libc-start.c | 2 ++ csu/libc-tls.c | 6 ++-- csu/static-reloc.c | 26 +++++++++++++++ elf/Makefile | 5 +-- elf/dl-reloc-static-pie.c | 52 ++++++++++++++++++++++++++++++ elf/dl-support.c | 11 +++++++ elf/dynamic-link.h | 2 +- elf/get-dynamic-info.h | 6 ++-- gmon/Makefile | 23 +++++++++++++ gmon/tst-gmon-static-pie.c | 1 + manual/install.texi | 7 ++++ sysdeps/generic/ldsodefs.h | 11 +++++++ sysdeps/i386/configure | 33 +++++++++++++++++++ sysdeps/i386/configure.ac | 23 +++++++++++++ sysdeps/x86_64/configure | 33 +++++++++++++++++++ sysdeps/x86_64/configure.ac | 25 +++++++++++++++ 23 files changed, 425 insertions(+), 14 deletions(-) create mode 100644 csu/static-reloc.c create mode 100644 elf/dl-reloc-static-pie.c create mode 100644 gmon/tst-gmon-static-pie.c diff --git a/INSTALL b/INSTALL index ac8db74a0f..1beede7bae 100644 --- a/INSTALL +++ b/INSTALL @@ -90,6 +90,13 @@ will be used, and CFLAGS sets optimization options for the compiler. systems support shared libraries; you need ELF support and (currently) the GNU linker. +'--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. + '--disable-profile' Don't build libraries with profiling information. You may want to use this option if you don't plan to do profiling. diff --git a/Makeconfig b/Makeconfig index 1346109ac0..62a0c30498 100644 --- a/Makeconfig +++ b/Makeconfig @@ -352,6 +352,12 @@ ifndef static-start-installed-name static-start-installed-name = $(start-installed-name) endif +ifeq (yes,$(enable-static-pie)) +# Link with rcrt1.o, instead of crt1.o, to call _dl_relocate_static_pie +# to relocate static PIE. +static-start-installed-name := r$(static-start-installed-name) +endif + ifeq (yesyes,$(build-shared)$(have-z-combreloc)) combreloc-LDFLAGS = -Wl,-z,combreloc LDFLAGS.so += $(combreloc-LDFLAGS) @@ -371,6 +377,20 @@ LDFLAGS.so += $(hashstyle-LDFLAGS) LDFLAGS-rtld += $(hashstyle-LDFLAGS) endif +ifeq (yes,$(enable-static-pie)) +pic-default = -DPIC +# Compile libc.a and libc_p.a with -fPIE/-fpie for static PIE. +pie-default = $(pie-ccflag) +ifeq (yes,$(have-static-pie)) +default-pie-ldflag = -static-pie +else +# Static PIE can't have dynamic relocations in read-only segments since +# static PIE is mapped into memory by kernel. --eh-frame-hdr is needed +# for PIE to support exception. +default-pie-ldflag = -Wl,-pie,--no-dynamic-linker,--eh-frame-hdr,-z,text +endif +endif + # If lazy relocations are disabled, add the -z now flag. Use # LDFLAGS-lib.so instead of LDFLAGS.so, to avoid adding the flag to # test modules. @@ -420,7 +440,7 @@ endif # Command for statically linking programs with the C library. ifndef +link-static +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \ - $(DEFAULT-LDFLAGS-$(@F)) \ + $(firstword $(DEFAULT-LDFLAGS-$(@F)) $(default-pie-ldflag)) \ $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \ $(firstword $(CRT-$(@F)) $(csu-objpfx)$(static-start-installed-name)) \ $(+preinit) $(+prectorT) \ @@ -637,8 +657,14 @@ endif +prectorS = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtbeginS.o` +postctorS = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtendS.o` # Variants of the two previous definitions for statically linking programs. +ifeq (yes,$(enable-static-pie)) +# Static PIE must use PIE variants. ++prectorT = $(+prectorS) ++postctorT = $(+postctorS) +else +prectorT = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtbeginT.o` +postctorT = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtend.o` +endif csu-objpfx = $(common-objpfx)csu/ elf-objpfx = $(common-objpfx)elf/ @@ -959,7 +985,8 @@ libtypes = $(foreach o,$(object-suffixes-for-libc),$(libtype$o)) all-object-suffixes := .o .os .oS object-suffixes := CPPFLAGS-.o = $(pic-default) -CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) +# libc.a must be compiled with -fPIE/-fpie for static PIE. +CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) $(pie-default) libtype.o := lib%.a object-suffixes += .o ifeq (yes,$(build-shared)) @@ -984,7 +1011,8 @@ ifeq (yes,$(build-profile)) all-object-suffixes += .op object-suffixes += .op CPPFLAGS-.op = -DPROF $(pic-default) -CFLAGS-.op = -pg +# libc_p.a must be compiled with -fPIE/-fpie for static PIE. +CFLAGS-.op = -pg $(pie-default) libtype.op = lib%_p.a endif diff --git a/NEWS b/NEWS index ab14d1eb1b..61598be94d 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,11 @@ Version 2.27 Major new features: +* Add --enable-static-pie configure option to build static PIE. The + resulting libc.a can be used with the GCC option, -static-pie, which + is available with GCC 8 or above, to create static position independent + executable (static PIE). + * Optimized x86-64 asin, atan2, exp, expf, log, pow, atan, sin and tan with FMA, contributed by Arjan van de Ven and H.J. Lu from Intel. diff --git a/config.h.in b/config.h.in index c140ff3ecb..f7db916711 100644 --- a/config.h.in +++ b/config.h.in @@ -244,6 +244,9 @@ /* Build glibc with tunables support. */ #define HAVE_TUNABLES 0 +/* Define if static PIE is enabled. */ +#define ENABLE_STATIC_PIE 0 + /* Some compiler options may now allow to use ebp in __asm__ (used mainly in i386 6 argument syscall issue). */ #define CAN_USE_REGISTER_ASM_EBP 0 diff --git a/configure b/configure index d9d9243238..eb3c4225e3 100755 --- a/configure +++ b/configure @@ -765,6 +765,7 @@ with_default_link enable_sanity_checks enable_shared enable_profile +enable_static_pie enable_timezone_tools enable_hardcoded_path_in_tests enable_stackguard_randomization @@ -1420,6 +1421,7 @@ Optional Features: in special situations) [default=yes] --enable-shared build shared library [default=yes if GNU ld] --enable-profile build profiled library [default=no] + --enable-static-pie build static executables as PIE [default=no] --disable-timezone-tools do not install timezone tools [default=install] --enable-hardcoded-path-in-tests @@ -3365,6 +3367,13 @@ else profile=no fi +# Check whether --enable-static-pie was given. +if test "${enable_static_pie+set}" = set; then : + enableval=$enable_static_pie; static_pie=$enableval +else + static_pie=no +fi + # Check whether --enable-timezone-tools was given. if test "${enable_timezone_tools+set}" = set; then : enableval=$enable_timezone_tools; enable_timezone_tools=$enableval @@ -5805,6 +5814,62 @@ fi $as_echo "$libc_linker_feature" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker that supports --no-dynamic-linker" >&5 +$as_echo_n "checking for linker that supports --no-dynamic-linker... " >&6; } +libc_linker_feature=no +if test x"$gnu_ld" = x"yes"; then + libc_linker_check=`$LD -v --help 2>/dev/null | grep "\--no-dynamic-linker"` + if test -n "$libc_linker_check"; then + cat > conftest.c <<EOF +int _start (void) { return 42; } +EOF + if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp + -Wl,--no-dynamic-linker -nostdlib -nostartfiles + -fPIC -shared -o conftest.so conftest.c + 1>&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } + then + libc_linker_feature=yes + fi + rm -f conftest* + fi +fi +if test $libc_linker_feature = yes; then + libc_cv_no_dynamic_linker=yes +else + libc_cv_no_dynamic_linker=no +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5 +$as_echo "$libc_linker_feature" >&6; } +config_vars="$config_vars +have-no-dynamic-linker = $libc_cv_no_dynamic_linker" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -static-pie" >&5 +$as_echo_n "checking for -static-pie... " >&6; } +if ${libc_cv_static_pie+:} false; then : + $as_echo_n "(cached) " >&6 +else + if { ac_try='${CC-cc} -static-pie -xc /dev/null -S -o /dev/null' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + libc_cv_static_pie=yes +else + libc_cv_static_pie=no +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_static_pie" >&5 +$as_echo "$libc_cv_static_pie" >&6; } +config_vars="$config_vars +have-static-pie = $libc_cv_static_pie" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -fpie" >&5 $as_echo_n "checking for -fpie... " >&6; } if ${libc_cv_fpie+:} false; then : @@ -6704,6 +6769,19 @@ $as_echo "$libc_cv_pie_default" >&6; } libc_cv_multidir=`${CC-cc} $CFLAGS $CPPFLAGS -print-multi-directory` +if test "$static_pie" = yes; then + # The linker must support --no-dynamic-linker. + if test "$libc_cv_no_dynamic_linker" != yes; then + as_fn_error $? "linker support for --no-dynamic-linker needed" "$LINENO" 5 + fi + # Default to PIE. + libc_cv_pie_default=yes + $as_echo "#define ENABLE_STATIC_PIE 1" >>confdefs.h + +fi +config_vars="$config_vars +enable-static-pie = $static_pie" + diff --git a/configure.ac b/configure.ac index 8ebc490a55..ae219f8fe0 100644 --- a/configure.ac +++ b/configure.ac @@ -176,6 +176,11 @@ AC_ARG_ENABLE([profile], [build profiled library @<:@default=no@:>@]), [profile=$enableval], [profile=no]) +AC_ARG_ENABLE([static-pie], + AC_HELP_STRING([--enable-static-pie], + [build static executables as PIE @<:@default=no@:>@]), + [static_pie=$enableval], + [static_pie=no]) AC_ARG_ENABLE([timezone-tools], AC_HELP_STRING([--disable-timezone-tools], [do not install timezone tools @<:@default=install@:>@]), @@ -1281,6 +1286,19 @@ LIBC_LINKER_FEATURE([-z execstack], [-Wl,-z,execstack], [libc_cv_z_execstack=yes], [libc_cv_z_execstack=no]) AC_SUBST(libc_cv_z_execstack) +LIBC_LINKER_FEATURE([--no-dynamic-linker], + [-Wl,--no-dynamic-linker], + [libc_cv_no_dynamic_linker=yes], + [libc_cv_no_dynamic_linker=no]) +LIBC_CONFIG_VAR([have-no-dynamic-linker], [$libc_cv_no_dynamic_linker]) + +AC_CACHE_CHECK(for -static-pie, libc_cv_static_pie, [dnl +LIBC_TRY_CC_OPTION([-static-pie], + [libc_cv_static_pie=yes], + [libc_cv_static_pie=no]) +]) +LIBC_CONFIG_VAR([have-static-pie], [$libc_cv_static_pie]) + AC_CACHE_CHECK(for -fpie, libc_cv_fpie, [dnl LIBC_TRY_CC_OPTION([-fpie], [libc_cv_fpie=yes], [libc_cv_fpie=no]) ]) @@ -1788,6 +1806,17 @@ AC_SUBST(libc_cv_pie_default) libc_cv_multidir=`${CC-cc} $CFLAGS $CPPFLAGS -print-multi-directory` AC_SUBST(libc_cv_multidir) +if test "$static_pie" = yes; then + # The linker must support --no-dynamic-linker. + if test "$libc_cv_no_dynamic_linker" != yes; then + AC_MSG_ERROR([linker support for --no-dynamic-linker needed]) + fi + # Default to PIE. + libc_cv_pie_default=yes + AC_DEFINE(ENABLE_STATIC_PIE) +fi +LIBC_CONFIG_VAR([enable-static-pie], [$static_pie]) + AC_SUBST(profile) AC_SUBST(static_nss) diff --git a/csu/Makefile b/csu/Makefile index e42a32b3eb..e8ff1ec257 100644 --- a/csu/Makefile +++ b/csu/Makefile @@ -37,7 +37,8 @@ extra-objs = start.o \ S$(start-installed-name) omit-deps = $(patsubst %.o,%,$(start-installed-name) g$(start-installed-name) \ b$(start-installed-name) $(csu-dummies) \ - S$(start-installed-name)) + S$(start-installed-name) \ + r$(start-installed-name)) install-lib = $(start-installed-name) g$(start-installed-name) $(csu-dummies) # No tests are allowed in the csu/ subdirectory because the startup @@ -55,6 +56,10 @@ extra-objs += gmon-start.o endif install-lib += S$(start-installed-name) generated += start.os +ifeq (yes,$(enable-static-pie)) +extra-objs += r$(start-installed-name) +install-lib += r$(start-installed-name) +endif else extra-objs += gmon-start.o endif @@ -82,7 +87,10 @@ multilib-extra-objs = $(addprefix $(multidir)/, $(install-lib)) extra-objs += $(multilib-extra-objs) endif -extra-objs += abi-note.o init.o +extra-objs += abi-note.o init.o static-reloc.o +ifeq (yes,$(build-shared)) +extra-objs += static-reloc.os +endif asm-CPPFLAGS += -I$(objpfx). # Enable unwinding so backtrace unwinds to __libc_start_main @@ -101,6 +109,9 @@ ifndef start-installed-name-rule # We link the ELF startfile along with a SHT_NOTE section indicating # the kernel ABI the binaries linked with this library will require. $(objpfx)$(start-installed-name): $(objpfx)start.o $(objpfx)abi-note.o \ + $(objpfx)init.o $(objpfx)static-reloc.o + $(link-relocatable) +$(objpfx)r$(start-installed-name): $(objpfx)start.o $(objpfx)abi-note.o \ $(objpfx)init.o $(link-relocatable) $(objpfx)S$(start-installed-name): $(objpfx)start.os $(objpfx)abi-note.o \ @@ -113,7 +124,7 @@ endif # to turn on profiling code at startup. ifeq (yes,$(build-shared)) $(objpfx)g$(start-installed-name): \ - $(objpfx)g%: $(objpfx)S% $(objpfx)gmon-start.os + $(objpfx)g%: $(objpfx)S% $(objpfx)gmon-start.os $(objpfx)static-reloc.os $(link-relocatable) ifneq ($(start-installed-name),$(static-start-installed-name)) $(objpfx)g$(static-start-installed-name): \ diff --git a/csu/libc-start.c b/csu/libc-start.c index 24c63be02f..34dd125260 100644 --- a/csu/libc-start.c +++ b/csu/libc-start.c @@ -141,6 +141,8 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), __libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up; #ifndef SHARED + _dl_relocate_static_pie (); + char **ev = &argv[argc + 1]; __environ = ev; diff --git a/csu/libc-tls.c b/csu/libc-tls.c index 00138eb43a..1f8ddaf543 100644 --- a/csu/libc-tls.c +++ b/csu/libc-tls.c @@ -114,6 +114,8 @@ __libc_setup_tls (void) size_t tcb_offset; const ElfW(Phdr) *phdr; + struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded; + /* Look through the TLS segment if there is any. */ if (_dl_phdr != NULL) for (phdr = _dl_phdr; phdr < &_dl_phdr[_dl_phnum]; ++phdr) @@ -122,7 +124,7 @@ __libc_setup_tls (void) /* Remember the values we need. */ memsz = phdr->p_memsz; filesz = phdr->p_filesz; - initimage = (void *) phdr->p_vaddr; + initimage = (void *) phdr->p_vaddr + main_map->l_addr; align = phdr->p_align; if (phdr->p_align > max_align) max_align = phdr->p_align; @@ -163,8 +165,6 @@ __libc_setup_tls (void) _dl_static_dtv[0].counter = (sizeof (_dl_static_dtv) / sizeof (_dl_static_dtv[0])) - 2; // _dl_static_dtv[1].counter = 0; would be needed if not already done - struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded; - /* Initialize the TLS block. */ #if TLS_TCB_AT_TP _dl_static_dtv[2].pointer.val = ((char *) tlsblock + tcb_offset diff --git a/csu/static-reloc.c b/csu/static-reloc.c new file mode 100644 index 0000000000..37be72c8ea --- /dev/null +++ b/csu/static-reloc.c @@ -0,0 +1,26 @@ +/* Special startup support for non-PIE static executables. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#if ENABLE_STATIC_PIE +#include <ldsodefs.h> + +void +_dl_relocate_static_pie (void) +{ +} +#endif diff --git a/elf/Makefile b/elf/Makefile index a31fb72498..cb035e63aa 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -24,7 +24,8 @@ include ../Makeconfig headers = elf.h bits/elfclass.h link.h bits/link.h routines = $(all-dl-routines) dl-support dl-iteratephdr \ dl-addr dl-addr-obj enbl-secure dl-profstub \ - dl-origin dl-libc dl-sym dl-sysdep dl-error + dl-origin dl-libc dl-sym dl-sysdep dl-error \ + dl-reloc-static-pie # The core dynamic linking functions are in libc for the static and # profiled libraries. @@ -52,7 +53,7 @@ endif all-dl-routines = $(dl-routines) $(sysdep-dl-routines) # But they are absent from the shared libc, because that code is in ld.so. elide-routines.os = $(all-dl-routines) dl-support enbl-secure dl-origin \ - dl-sysdep dl-exception + dl-sysdep dl-exception dl-reloc-static-pie shared-only-routines += dl-caller # ld.so uses those routines, plus some special stuff for being the program diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c new file mode 100644 index 0000000000..6e43aea76a --- /dev/null +++ b/elf/dl-reloc-static-pie.c @@ -0,0 +1,52 @@ +/* Support for relocating static PIE. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#if ENABLE_STATIC_PIE +#include <unistd.h> +#include <ldsodefs.h> +#include "dynamic-link.h" + +/* Relocate static executable with PIE. */ + +void +_dl_relocate_static_pie (void) +{ + struct link_map *main_map = _dl_get_dl_main_map (); + +# define STATIC_PIE_BOOTSTRAP +# define BOOTSTRAP_MAP (main_map) +# define RESOLVE_MAP(sym, version, flags) BOOTSTRAP_MAP +# include "dynamic-link.h" + + /* Figure out the run-time load address of static PIE. */ + main_map->l_addr = elf_machine_load_address (); + + /* Read our own dynamic section and fill in the info array. */ + main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ()); + elf_get_dynamic_info (main_map, NULL); + +# ifdef ELF_MACHINE_BEFORE_RTLD_RELOC + ELF_MACHINE_BEFORE_RTLD_RELOC (main_map->l_info); +# endif + + /* Relocate ourselves so we can do normal function calls and + data access using the global offset table. */ + ELF_DYNAMIC_RELOCATE (main_map, 0, 0, 0); + main_map->l_relocated = 1; +} +#endif 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 diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h index ebea7567cd..6278649711 100644 --- a/elf/dynamic-link.h +++ b/elf/dynamic-link.h @@ -94,7 +94,7 @@ elf_machine_lazy_rel (struct link_map *map, #ifdef RESOLVE_MAP -# ifdef RTLD_BOOTSTRAP +# if defined RTLD_BOOTSTRAP || defined STATIC_PIE_BOOTSTRAP # define ELF_DURING_STARTUP (1) # else # define ELF_DURING_STARTUP (0) diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h index 7525c3a5b2..eb26d23649 100644 --- a/elf/get-dynamic-info.h +++ b/elf/get-dynamic-info.h @@ -38,7 +38,7 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) typedef Elf64_Xword d_tag_utype; #endif -#ifndef RTLD_BOOTSTRAP +#if !defined RTLD_BOOTSTRAP && !defined STATIC_PIE_BOOTSTRAP if (dyn == NULL) return; #endif @@ -139,9 +139,11 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) /* Only the bind now flags are allowed. */ assert (info[VERSYMIDX (DT_FLAGS_1)] == NULL || (info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val & ~DF_1_NOW) == 0); + /* Flags must not be set for ld.so. */ assert (info[DT_FLAGS] == NULL || (info[DT_FLAGS]->d_un.d_val & ~DF_BIND_NOW) == 0); - /* Flags must not be set for ld.so. */ +#endif +#if defined RTLD_BOOTSTRAP || defined STATIC_PIE_BOOTSTRAP assert (info[DT_RUNPATH] == NULL); assert (info[DT_RPATH] == NULL); #else diff --git a/gmon/Makefile b/gmon/Makefile index 89ab3fc7da..f83fcc9d71 100644 --- a/gmon/Makefile +++ b/gmon/Makefile @@ -39,6 +39,10 @@ tests-static += tst-gmon-static ifeq (yesyes,$(have-fpie)$(build-shared)) tests += tst-gmon-pie tests-pie += tst-gmon-pie +ifeq (yes,$(enable-static-pie)) +tests += tst-gmon-static-pie +tests-static += tst-gmon-static-pie +endif endif # The mcount code won't work without a frame pointer. @@ -67,6 +71,15 @@ ifeq ($(run-built-tests),yes) tests-special += $(objpfx)tst-gmon-pie-gprof.out endif +ifeq (yes,$(enable-static-pie)) +CFLAGS-tst-gmon-static-pie.c := $(PIE-ccflag) -fno-omit-frame-pointer -pg +CRT-tst-gmon-static-pie := $(csu-objpfx)grcrt1.o +tst-gmon-static-pie-ENV := GMON_OUT_PREFIX=$(objpfx)tst-gmon-static-pie.data +ifeq ($(run-built-tests),yes) +tests-special += $(objpfx)tst-gmon-static-pie-gprof.out +endif +endif + include ../Rules @@ -111,3 +124,13 @@ clean-tst-gmon-pie-data: $(objpfx)tst-gmon-pie-gprof.out: tst-gmon-gprof.sh $(objpfx)tst-gmon-pie.out $(SHELL) $< $(GPROF) $(objpfx)tst-gmon-pie $(objpfx)tst-gmon-pie.data.* > $@; \ $(evaluate-test) + +$(objpfx)tst-gmon-static-pie.out: clean-tst-gmon-static-pie-data +clean-tst-gmon-static-pie-data: + rm -f $(objpfx)tst-gmon-static-pie.data.* + +$(objpfx)tst-gmon-static-pie-gprof.out: tst-gmon-static-gprof.sh \ + $(objpfx)tst-gmon-static-pie.out + $(SHELL) $< $(GPROF) $(objpfx)tst-gmon-static-pie \ + $(objpfx)tst-gmon-static-pie.data.* > $@; \ + $(evaluate-test) diff --git a/gmon/tst-gmon-static-pie.c b/gmon/tst-gmon-static-pie.c new file mode 100644 index 0000000000..1eef2583b6 --- /dev/null +++ b/gmon/tst-gmon-static-pie.c @@ -0,0 +1 @@ +#include "tst-gmon.c" diff --git a/manual/install.texi b/manual/install.texi index f1fa28c937..86193ade3f 100644 --- a/manual/install.texi +++ b/manual/install.texi @@ -120,6 +120,13 @@ Don't build shared libraries even if it is possible. Not all systems support shared libraries; you need ELF support and (currently) the GNU linker. +@item --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. + @item --disable-profile Don't build libraries with profiling information. You may want to use this option if you don't plan to do profiling. diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index 52a792a597..af89f5eeb4 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -1051,6 +1051,17 @@ extern void _dl_determine_tlsoffset (void) attribute_hidden; stack protector, among other things). */ void __libc_setup_tls (void); +# if ENABLE_STATIC_PIE +/* Relocate static executable with PIE. */ +extern void _dl_relocate_static_pie (void) attribute_hidden; + +/* Get a pointer to _dl_main_map. */ +extern struct link_map * _dl_get_dl_main_map (void) + __attribute__ ((visibility ("hidden"))); +# else +# define _dl_relocate_static_pie() +# endif + /* Initialization of libpthread for statically linked applications. If libpthread is not linked in, this is an empty function. */ void __pthread_initialize_minimal (void) weak_function; diff --git a/sysdeps/i386/configure b/sysdeps/i386/configure index 4cf968d8bc..90c63caf35 100644 --- a/sysdeps/i386/configure +++ b/sysdeps/i386/configure @@ -50,6 +50,39 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_compiler_builtin_inlined" >&5 $as_echo "$libc_compiler_builtin_inlined" >&6; } +if test "$static_pie" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker static PIE support" >&5 +$as_echo_n "checking for linker static PIE support... " >&6; } +if ${libc_cv_ld_static_pie+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat > conftest.s <<\EOF + .text + .global _start +_start: + movl _start@GOT(%ebx), %eax +EOF + libc_cv_pie_option="-Wl,-pie" + libc_cv_ld_static_pie=no + if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + if $READELF -r conftest | grep 'There are no relocations in this file.' > /dev/null; then + libc_cv_ld_static_pie=yes + fi + fi +rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_ld_static_pie" >&5 +$as_echo "$libc_cv_ld_static_pie" >&6; } + if test "$libc_cv_ld_static_pie" != yes; then + as_fn_error $? "linker support for static PIE needed" "$LINENO" 5 + fi +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Intel MPX support" >&5 $as_echo_n "checking for Intel MPX support... " >&6; } if ${libc_cv_asm_mpx+:} false; then : diff --git a/sysdeps/i386/configure.ac b/sysdeps/i386/configure.ac index b598b120bc..6d2068d2b3 100644 --- a/sysdeps/i386/configure.ac +++ b/sysdeps/i386/configure.ac @@ -30,6 +30,29 @@ LIBC_COMPILER_BUILTIN_INLINED( *** Please use host i786, i686, i586, or i486. *** For example: /source/glibc/configure CFLAGS='-O2 -march=i686' ...])]) +dnl Check if linker can convert "movl main@GOT(%ebx), %eax" to +dnl "leal main@GOTOFF(%ebx), %eax" for static PIE. +if test "$static_pie" = yes; then + AC_CACHE_CHECK(for linker static PIE support, libc_cv_ld_static_pie, [dnl +cat > conftest.s <<\EOF + .text + .global _start +_start: + movl _start@GOT(%ebx), %eax +EOF + libc_cv_pie_option="-Wl,-pie" + libc_cv_ld_static_pie=no + if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&AS_MESSAGE_LOG_FD); then + if $READELF -r conftest | grep 'There are no relocations in this file.' > /dev/null; then + libc_cv_ld_static_pie=yes + fi + fi +rm -f conftest*]) + if test "$libc_cv_ld_static_pie" != yes; then + AC_MSG_ERROR([linker support for static PIE needed]) + fi +fi + dnl Check whether asm supports Intel MPX AC_CACHE_CHECK(for Intel MPX support, libc_cv_asm_mpx, [dnl cat > conftest.s <<\EOF diff --git a/sysdeps/x86_64/configure b/sysdeps/x86_64/configure index efef46b1b7..8674d14569 100644 --- a/sysdeps/x86_64/configure +++ b/sysdeps/x86_64/configure @@ -85,6 +85,39 @@ if test x"$build_mathvec" = xnotset; then build_mathvec=yes fi +if test "$static_pie" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker static PIE support" >&5 +$as_echo_n "checking for linker static PIE support... " >&6; } +if ${libc_cv_ld_static_pie+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat > conftest.s <<\EOF + .text + .global _start + .weak foo +_start: + leaq foo(%rip), %rax +EOF + libc_cv_pie_option="-Wl,-pie" + if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + libc_cv_ld_static_pie=yes + else + libc_cv_ld_static_pie=no + fi +rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_ld_static_pie" >&5 +$as_echo "$libc_cv_ld_static_pie" >&6; } + if test "$libc_cv_ld_static_pie" != yes; then + as_fn_error $? "linker support for static PIE needed" "$LINENO" 5 + fi +fi + $as_echo "#define PI_STATIC_AND_HIDDEN 1" >>confdefs.h diff --git a/sysdeps/x86_64/configure.ac b/sysdeps/x86_64/configure.ac index fa86e953ee..b7d2c0124f 100644 --- a/sysdeps/x86_64/configure.ac +++ b/sysdeps/x86_64/configure.ac @@ -44,6 +44,31 @@ if test x"$build_mathvec" = xnotset; then build_mathvec=yes fi +dnl Check if linker supports static PIE with the fix for +dnl +dnl https://sourceware.org/bugzilla/show_bug.cgi?id=21782 +dnl +if test "$static_pie" = yes; then + AC_CACHE_CHECK(for linker static PIE support, libc_cv_ld_static_pie, [dnl +cat > conftest.s <<\EOF + .text + .global _start + .weak foo +_start: + leaq foo(%rip), %rax +EOF + libc_cv_pie_option="-Wl,-pie" + if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&AS_MESSAGE_LOG_FD); then + libc_cv_ld_static_pie=yes + else + libc_cv_ld_static_pie=no + fi +rm -f conftest*]) + if test "$libc_cv_ld_static_pie" != yes; then + AC_MSG_ERROR([linker support for static PIE needed]) + fi +fi + dnl It is always possible to access static and hidden symbols in an dnl position independent way. AC_DEFINE(PI_STATIC_AND_HIDDEN) -- 2.14.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-11-24 22:24 ` H.J. Lu @ 2017-11-30 14:00 ` H.J. Lu 2017-11-30 15:28 ` Joseph Myers 2017-11-30 21:45 ` Carlos O'Donell 1 sibling, 1 reply; 37+ messages in thread From: H.J. Lu @ 2017-11-30 14:00 UTC (permalink / raw) To: Szabolcs Nagy; +Cc: nd, Joseph Myers, GNU C Library On Fri, Nov 24, 2017 at 2:24 PM, H.J. Lu <hjl.tools@gmail.com> wrote: > On Fri, Nov 24, 2017 at 7:03 AM, H.J. Lu <hjl.tools@gmail.com> wrote: >> On Fri, Nov 24, 2017 at 5:06 AM, Szabolcs Nagy <szabolcs.nagy@arm.com> wrote: >>> On 23/11/17 13:59, H.J. Lu wrote: >>>> On Mon, Nov 20, 2017 at 4:16 AM, Szabolcs Nagy <szabolcs.nagy@arm.com> wrote: >>>>> On 19/11/17 02:40, H.J. Lu wrote: >>>>>> 3. Linker should resolve undefined weak symbols to 0 in static PIE: >>>>>> >>>>>> https://sourceware.org/bugzilla/show_bug.cgi?id=22269 >>>>>> >>>>>> 4. Many ELF backend linkers incorrectly check bfd_link_pic for TLS >>>>>> relocations, which should check bfd_link_executable instead: >>>>>> >>>>>> https://sourceware.org/bugzilla/show_bug.cgi?id=22263 >>>>>> >>>>>> Tested on i686 and x86-64. >>>>>> >>>>>> Build results of build-many-glibcs.py with --enable-static-pie with all >>>>>> patches for static PIE applied are >>>>>> >>>>>> PASS: glibcs-aarch64_be-linux-gnu build >>>>>> PASS: glibcs-aarch64-linux-gnu build >>>>> >>>>> i'd expect these to fail on current binutils master >>>>> >>>>> (linking with undefweak symbol fails now because of the issues >>>>> listed above, i'll try to prepare a binutils patch) >>>>> >>>> >>>> Do you think you can fix arm64 for glibc 2.27? >>>> >>> >>> the aarch64 glibc tests pass with the pie patches and >>> the start code fix i posted (and with a fixed bfd linker). >> >> Great. Linker changes look quite straight forward. I will >> update my commit message. > > Here is the patch with the updated commit message. > > Thanks. Static PIE works on i686, x32 and x86-64 as well as aarch64 with a patch. I will check in my patch and update https://sourceware.org/glibc/wiki/PortStatus next week if there no objection. -- H.J. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-11-30 14:00 ` H.J. Lu @ 2017-11-30 15:28 ` Joseph Myers 2017-11-30 16:24 ` H.J. Lu 0 siblings, 1 reply; 37+ messages in thread From: Joseph Myers @ 2017-11-30 15:28 UTC (permalink / raw) To: H.J. Lu; +Cc: Szabolcs Nagy, nd, GNU C Library On Thu, 30 Nov 2017, H.J. Lu wrote: > Static PIE works on i686, x32 and x86-64 as well as aarch64 > with a patch. I will check in my patch and update > > https://sourceware.org/glibc/wiki/PortStatus > > next week if there no objection. I object to it being checked in without proper review achieving a consensus. This is a major new feature, not in anyone's subsystem maintainership area; it's not possibly something that could be considered borderline obvious. -- Joseph S. Myers joseph@codesourcery.com ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-11-30 15:28 ` Joseph Myers @ 2017-11-30 16:24 ` H.J. Lu 2017-11-30 16:37 ` Joseph Myers 0 siblings, 1 reply; 37+ messages in thread From: H.J. Lu @ 2017-11-30 16:24 UTC (permalink / raw) To: Joseph Myers; +Cc: Szabolcs Nagy, nd, GNU C Library On Thu, Nov 30, 2017 at 7:28 AM, Joseph Myers <joseph@codesourcery.com> wrote: > On Thu, 30 Nov 2017, H.J. Lu wrote: > >> Static PIE works on i686, x32 and x86-64 as well as aarch64 >> with a patch. I will check in my patch and update >> >> https://sourceware.org/glibc/wiki/PortStatus >> >> next week if there no objection. > > I object to it being checked in without proper review achieving a > consensus. This is a major new feature, not in anyone's subsystem > maintainership area; it's not possibly something that could be considered > borderline obvious. Can you help me achieve consensus on this issue? I'd like to get static PIE into glibc 2.27. Thanks. -- H.J. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-11-30 16:24 ` H.J. Lu @ 2017-11-30 16:37 ` Joseph Myers 2017-11-30 16:56 ` H.J. Lu 0 siblings, 1 reply; 37+ messages in thread From: Joseph Myers @ 2017-11-30 16:37 UTC (permalink / raw) To: H.J. Lu; +Cc: Szabolcs Nagy, nd, GNU C Library On Thu, 30 Nov 2017, H.J. Lu wrote: > Can you help me achieve consensus on this issue? I'd like to get static PIE > into glibc 2.27. The closest component to this work is dynamic-link, where Carlos is listed as interested reviewer. -- Joseph S. Myers joseph@codesourcery.com ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-11-30 16:37 ` Joseph Myers @ 2017-11-30 16:56 ` H.J. Lu 2017-11-30 18:45 ` Carlos O'Donell 0 siblings, 1 reply; 37+ messages in thread From: H.J. Lu @ 2017-11-30 16:56 UTC (permalink / raw) To: Joseph Myers, Carlos O'Donell, Florian Weimer Cc: Szabolcs Nagy, nd, GNU C Library On Thu, Nov 30, 2017 at 8:37 AM, Joseph Myers <joseph@codesourcery.com> wrote: > On Thu, 30 Nov 2017, H.J. Lu wrote: > >> Can you help me achieve consensus on this issue? I'd like to get static PIE >> into glibc 2.27. > > The closest component to this work is dynamic-link, where Carlos is listed > as interested reviewer. > Hi Carlos, Here is my patch to enable static PIE: https://sourceware.org/git/?p=glibc.git;a=commit;h=b3c9432386edbd2f57098daa6a2a63780c9d9d63 It fixed: https://sourceware.org/bugzilla/show_bug.cgi?id=19574 I also created hjl/pie/static branch in glibc git repo. Can you take a look at my patch? Thanks. -- H.J. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-11-30 16:56 ` H.J. Lu @ 2017-11-30 18:45 ` Carlos O'Donell 0 siblings, 0 replies; 37+ messages in thread From: Carlos O'Donell @ 2017-11-30 18:45 UTC (permalink / raw) To: H.J. Lu, Joseph Myers, Florian Weimer; +Cc: Szabolcs Nagy, nd, GNU C Library On 11/30/2017 08:56 AM, H.J. Lu wrote: > On Thu, Nov 30, 2017 at 8:37 AM, Joseph Myers <joseph@codesourcery.com> wrote: >> On Thu, 30 Nov 2017, H.J. Lu wrote: >> >>> Can you help me achieve consensus on this issue? I'd like to get static PIE >>> into glibc 2.27. >> >> The closest component to this work is dynamic-link, where Carlos is listed >> as interested reviewer. >> > > Hi Carlos, > > Here is my patch to enable static PIE: > > https://sourceware.org/git/?p=glibc.git;a=commit;h=b3c9432386edbd2f57098daa6a2a63780c9d9d63 > > It fixed: > > https://sourceware.org/bugzilla/show_bug.cgi?id=19574 > > I also created hjl/pie/static branch in glibc git repo. Can you take > a look at my patch? Yes, I'm reviewing this patch now: https://www.sourceware.org/ml/libc-alpha/2017-11/msg00896.html Thank you for your patience. -- Cheers, Carlos. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-11-24 22:24 ` H.J. Lu 2017-11-30 14:00 ` H.J. Lu @ 2017-11-30 21:45 ` Carlos O'Donell 2017-11-30 22:37 ` Maciej W. Rozycki 2017-12-01 18:24 ` H.J. Lu 1 sibling, 2 replies; 37+ messages in thread From: Carlos O'Donell @ 2017-11-30 21:45 UTC (permalink / raw) To: H.J. Lu, Szabolcs Nagy; +Cc: nd, Joseph Myers, GNU C Library H.J., High Level: At a high level I have no objection with the idea of static PIE executables, it makes sense to support such things. My only nit is that we need to do a better job of explaining to users why they would use them and under what circumstances. To that end you have a bit more work to do in the commit message, install.texit, and NEWS entry. Design: I have one design question below which around testing static non-PIE executables in a --enable-static-pie build. See below. Implementation: Everything looks good except the use of firstword in +link-static-before-libc, which I describe below. I think this is a hack and should be changed to better represent the expected semantics and structure you are looking to support. Thank you for your work in this area. Look forward to a v2. > From 7026a79c1f71f5decd135208503fd4186193ffb8 Mon Sep 17 00:00:00 2001 > From: "H.J. Lu" <hjl.tools@gmail.com> > Date: Mon, 17 Jul 2017 08:17:32 -0700 > Subject: [PATCH] Add --enable-static-pie configure option to build static PIE > [BZ #19574] > > 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. You write "which are allowed", shouldn't that be "which are not allowed"? The commit message must explain the following: * Why would a user use this feature? - What does it provide over and beyond existing static executables * How does a user decide to use this feature? - Should everyone use it? - Should you use it if you care about security, and what does it cost? Please include the answers to these questions in a the next versions commit message. > > The following changes are made for static PIE: > > 1. Add a new function, _dl_relocate_static_pie, to: > a. Get the run-time load address. > b. Read the dynamic section. > c. Perform dynamic relocations. OK. > Dynamic linker also performs these steps. But static PIE doesn't load > any shared objects. OK. > 2. Call _dl_relocate_static_pie at entrance of LIBC_START_MAIN in > libc.a. crt1.o, which is used to create dynamic and non-PIE static > executables, is updated to include a dummy _dl_relocate_static_pie. > rcrt1.o is added to create static PIE, which will link in the real > _dl_relocate_static_pie. grcrt1.o is also added to create static PIE > with -pg. GCC 8 has been updated to support rcrt1.o and grcrt1.o for > static PIE. > > 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. All > functions in static PIE are local functions. If PIE start.S can't reach > main () defined in a shared object, the code sequence: > > pass addess of local_main to __libc_start_main > ... > > local_main: > tail call to main via PLT > > can be used. > 2. start.S is updated to check PIC instead SHARED for PIC code path and > avoid dynamic relocation, when PIC is defined and SHARED isn't defined, > to support static PIE. Patches are submitted for aarch64, hppa, m68k, > microblaze and sparc. > 3. All assembly codes are updated check PIC instead SHARED for PIC code > path to avoid dynamic relocations in read-only sections. > 4. All assembly codes are updated check SHARED instead PIC for static > symbol name. A patch is submitted for tile. > 5. elf_machine_load_address in dl-machine.h are updated to support static > PIE. Patches are submitted for aarch64, s390 and sh. > 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. > > 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. > > 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 > > The i386 linker needs to be able to convert "movl main@GOT(%ebx), %eax" > to "leal main@GOTOFF(%ebx), %eax" if main is defined locally. > > Binutils 2.29 or above are OK for i686 and x86-64. But linker status for > other targets need to be verified. > > 3. Linker should resolve undefined weak symbols to 0 in static PIE: > > https://sourceware.org/bugzilla/show_bug.cgi?id=22269 > > 4. Many ELF backend linkers incorrectly check bfd_link_pic for TLS > relocations, which should check bfd_link_executable instead: > > https://sourceware.org/bugzilla/show_bug.cgi?id=22263 > > Tested on aarch64, i686 and x86-64. > > On aarch64, binutils master branch with 2 patches: > > https://sourceware.org/ml/binutils/2017-11/msg00455.html > https://sourceware.org/ml/binutils/2017-11/msg00456.html > > applied is required. > > build-many-glibcs.py with --enable-static-pie with all patches for static > PIE applied have many failures: > > FAIL: glibcs-alpha-linux-gnu build > > elf/sln is failed to link due to: > > assertion fail bfd/elf64-alpha.c:4125 > > This is caused by linker bug and/or non-PIC code in PIE libc.a. > > FAIL: glibcs-ia64-linux-gnu build > > elf/sln is failed to link due to: > > libc.a(sched_yield.o): non-pic code with imm relocation against dynamic symbol `_dl_sysinfo' > > This is caused by non-PIC version of DO_CALL macro in ia64 sysdep.h. PIE > libc.a should use PIC version of DO_CALL, except during startup in static > PIE. An ia64 startup.h, similar to i386 startup.h, is needed to handle > this. > > FAIL: glibcs-mips64el-linux-gnu-n32 build > FAIL: glibcs-mips64el-linux-gnu-n32-nan2008 build > FAIL: glibcs-mips64el-linux-gnu-n32-nan2008-soft build > FAIL: glibcs-mips64el-linux-gnu-n32-soft build > FAIL: glibcs-mips64-linux-gnu-n32 build > FAIL: glibcs-mips64-linux-gnu-n32-nan2008 build > FAIL: glibcs-mips64-linux-gnu-n32-nan2008-soft build > FAIL: glibcs-mips64-linux-gnu-n32-soft build > FAIL: glibcs-mipsel-linux-gnu build > FAIL: glibcs-mipsel-linux-gnu-nan2008 build > FAIL: glibcs-mipsel-linux-gnu-nan2008-soft build > FAIL: glibcs-mipsel-linux-gnu-soft build > FAIL: glibcs-mips-linux-gnu build > FAIL: glibcs-mips-linux-gnu-nan2008 build > FAIL: glibcs-mips-linux-gnu-nan2008-soft build > FAIL: glibcs-mips-linux-gnu-soft build > > elf/sln is failed to link due to: > > crt1.o: relocation R_MIPS_HI16 against `_gp' can not be used when making a shared object; recompile with -fPIC > > This is caused by linker bug and/or non-PIC code in crt1.o. > > FAIL: glibcs-powerpc-linux-gnu build > FAIL: glibcs-powerpc-linux-gnu-soft build > FAIL: glibcs-powerpc-linux-gnuspe build > FAIL: glibcs-powerpc-linux-gnuspe-e500v1 build > > elf/sln is failed to link due to: > > ld: read-only segment has dynamic relocations. > > This is caused by linker bug and/or non-PIC code in PIE libc.a. See: > > https://sourceware.org/bugzilla/show_bug.cgi?id=22264 > > FAIL: glibcs-powerpc-linux-gnu-power4 build > > elf/sln is failed to link due to: > > findlocale.c:96:(.text+0x22c): @local call to ifunc memchr > > This is caused by linker bug and/or non-PIC code in PIE libc.a. > > FAIL: glibcs-s390-linux-gnu build > > elf/sln is failed to link due to: > > collect2: fatal error: ld terminated with signal 11 [Segmentation fault], core dumped > > assertion fail bfd/elflink.c:14242 > > This is caused by linker bug and/or non-PIC code in PIE libc.a. > > FAIL: glibcs-sh3eb-linux-gnu build > FAIL: glibcs-sh3-linux-gnu build > FAIL: glibcs-sh4eb-linux-gnu build > FAIL: glibcs-sh4eb-linux-gnu-soft build > FAIL: glibcs-sh4-linux-gnu build > FAIL: glibcs-sh4-linux-gnu-soft build > > elf/sln is failed to link due to: > > ld: read-only segment has dynamic relocations. > > This is caused by linker bug and/or non-PIC code in PIE libc.a. See: > > https://sourceware.org/bugzilla/show_bug.cgi?id=22263 > > Also TLS code sequence in SH assembly syscalls in glibc doesn't match TLS > code sequence expected by ld: > > https://sourceware.org/bugzilla/show_bug.cgi?id=22270 > > FAIL: glibcs-sparc64-linux-gnu build > FAIL: glibcs-sparcv9-linux-gnu build > FAIL: glibcs-tilegxbe-linux-gnu build > FAIL: glibcs-tilegxbe-linux-gnu-32 build > FAIL: glibcs-tilegx-linux-gnu build > FAIL: glibcs-tilegx-linux-gnu-32 build > FAIL: glibcs-tilepro-linux-gnu build > > elf/sln is failed to link due to: > > ld: read-only segment has dynamic relocations. > > This is caused by linker bug and/or non-PIC code in PIE libc.a. See: > > https://sourceware.org/bugzilla/show_bug.cgi?id=22263 > > [BZ #19574] > * INSTALL: Regenerated. > * Makeconfig (static-start-installed-name): Add the `r' prefix > for --enable-static-pie. > (pic-default): Updated for --enable-static-pie. > (pie-default): New for --enable-static-pie. > (default-pie-ldflag): Likewise. > (+link-static-before-libc): Use the first of $(DEFAULT-LDFLAGS-$(@F)) > and $(default-pie-ldflag). > (+prectorT): Updated for --enable-static-pie. > (+postctorT): Likewise. > (CFLAGS-.o): Add $(pie-default). > (CFLAGS-.op): Likewise. > * NEWS: Mention --enable-static-pie. > * config.h.in (ENABLE_STATIC_PIE): New. > * configure.ac (--enable-static-pie): New configure option. > (have-no-dynamic-linker): New LIBC_CONFIG_VAR. > (have-static-pie): Likewise. > Enable static PIE if linker supports --no-dynamic-linker. > (ENABLE_STATIC_PIE): New AC_DEFINE. > (enable-static-pie): New LIBC_CONFIG_VAR. > * configure: Regenerated. > * csu/Makefile (omit-deps): Add r$(start-installed-name) for > --enable-static-pie. > (extra-objs): Likewise. > (install-lib): Likewise. > (extra-objs): Add static-reloc.o and static-reloc.os > ($(objpfx)$(start-installed-name)): Also depend on > $(objpfx)static-reloc.o. > ($(objpfx)r$(start-installed-name)): New. > ($(objpfx)g$(start-installed-name)): Also depend on > $(objpfx)static-reloc.os. > * csu/libc-start.c (LIBC_START_MAIN): Call _dl_relocate_static_pie > in libc.a. > * csu/libc-tls.c (__libc_setup_tls): Add main_map->l_addr to > initimage. > * csu/static-reloc.c: New file. > * elf/Makefile (routines): Add dl-reloc-static-pie. > (elide-routines.os): Likewise. > * elf/dl-reloc-static-pie.c: New file. > * elf/dl-support.c (_dl_get_dl_main_map): New function. > * elf/dynamic-link.h (ELF_DURING_STARTUP): Also check > STATIC_PIE_BOOTSTRAP. > * elf/get-dynamic-info.h (elf_get_dynamic_info): Likewise. > * gmon/Makefile (tests): Add tst-gmon-static-pie. > (tests-static): Likewise. > (CFLAGS-tst-gmon-static-pie.c): New. > (CRT-tst-gmon-static-pie): Likewise. > (tst-gmon-static-pie-ENV): Likewise. > (tests-special): Likewise. > ($(objpfx)tst-gmon-static-pie.out): Likewise. > (clean-tst-gmon-static-pie-data): Likewise. > ($(objpfx)tst-gmon-static-pie-gprof.out): Likewise. > * gmon/tst-gmon-static-pie.c: New file. > * manual/install.texi: Document --enable-static-pie. > * sysdeps/generic/ldsodefs.h (_dl_relocate_static_pie): New. > (_dl_get_dl_main_map): Likewise. > * sysdeps/i386/configure.ac: Check if linker supports static PIE. > * sysdeps/x86_64/configure.ac: Likewise. > * sysdeps/i386/configure: Regenerated. > * sysdeps/x86_64/configure: Likewise. > --- > INSTALL | 7 ++++ > Makeconfig | 34 ++++++++++++++++++-- > NEWS | 5 +++ > config.h.in | 3 ++ > configure | 78 +++++++++++++++++++++++++++++++++++++++++++++ > configure.ac | 29 +++++++++++++++++ > csu/Makefile | 17 ++++++++-- > csu/libc-start.c | 2 ++ > csu/libc-tls.c | 6 ++-- > csu/static-reloc.c | 26 +++++++++++++++ > elf/Makefile | 5 +-- > elf/dl-reloc-static-pie.c | 52 ++++++++++++++++++++++++++++++ > elf/dl-support.c | 11 +++++++ > elf/dynamic-link.h | 2 +- > elf/get-dynamic-info.h | 6 ++-- > gmon/Makefile | 23 +++++++++++++ > gmon/tst-gmon-static-pie.c | 1 + > manual/install.texi | 7 ++++ > sysdeps/generic/ldsodefs.h | 11 +++++++ > sysdeps/i386/configure | 33 +++++++++++++++++++ > sysdeps/i386/configure.ac | 23 +++++++++++++ > sysdeps/x86_64/configure | 33 +++++++++++++++++++ > sysdeps/x86_64/configure.ac | 25 +++++++++++++++ > 23 files changed, 425 insertions(+), 14 deletions(-) > create mode 100644 csu/static-reloc.c > create mode 100644 elf/dl-reloc-static-pie.c > create mode 100644 gmon/tst-gmon-static-pie.c > > diff --git a/INSTALL b/INSTALL > index ac8db74a0f..1beede7bae 100644 > --- a/INSTALL > +++ b/INSTALL > @@ -90,6 +90,13 @@ will be used, and CFLAGS sets optimization options for the compiler. > systems support shared libraries; you need ELF support and > (currently) the GNU linker. > > +'--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. OK. > + > '--disable-profile' > Don't build libraries with profiling information. You may want to > use this option if you don't plan to do profiling. > diff --git a/Makeconfig b/Makeconfig > index 1346109ac0..62a0c30498 100644 > --- a/Makeconfig > +++ b/Makeconfig > @@ -352,6 +352,12 @@ ifndef static-start-installed-name > static-start-installed-name = $(start-installed-name) > endif > > +ifeq (yes,$(enable-static-pie)) > +# Link with rcrt1.o, instead of crt1.o, to call _dl_relocate_static_pie > +# to relocate static PIE. > +static-start-installed-name := r$(static-start-installed-name) > +endif OK. > + > ifeq (yesyes,$(build-shared)$(have-z-combreloc)) > combreloc-LDFLAGS = -Wl,-z,combreloc > LDFLAGS.so += $(combreloc-LDFLAGS) > @@ -371,6 +377,20 @@ LDFLAGS.so += $(hashstyle-LDFLAGS) > LDFLAGS-rtld += $(hashstyle-LDFLAGS) > endif > > +ifeq (yes,$(enable-static-pie)) > +pic-default = -DPIC > +# Compile libc.a and libc_p.a with -fPIE/-fpie for static PIE. > +pie-default = $(pie-ccflag) > +ifeq (yes,$(have-static-pie)) > +default-pie-ldflag = -static-pie > +else > +# Static PIE can't have dynamic relocations in read-only segments since > +# static PIE is mapped into memory by kernel. --eh-frame-hdr is needed > +# for PIE to support exception. > +default-pie-ldflag = -Wl,-pie,--no-dynamic-linker,--eh-frame-hdr,-z,text OK. > +endif > +endif > + > # If lazy relocations are disabled, add the -z now flag. Use > # LDFLAGS-lib.so instead of LDFLAGS.so, to avoid adding the flag to > # test modules. > @@ -420,7 +440,7 @@ endif > # Command for statically linking programs with the C library. > ifndef +link-static > +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \ > - $(DEFAULT-LDFLAGS-$(@F)) \ > + $(firstword $(DEFAULT-LDFLAGS-$(@F)) $(default-pie-ldflag)) \ Is the use of firstword here just a hack to put $(no-pie-ldflag) first so you can override it with the subsequent $(default-pie-ldflag)? It is not a robust design to use firstword here because it implies that the DEFAUTL-LDFLAGS-$(@F) has some structure that we are not documenting. I would like to see this done some other way. My preference would be for a new value other than DEFAULT-LDFLAGS to control the PIE-ness of the built progarm. > $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \ > $(firstword $(CRT-$(@F)) $(csu-objpfx)$(static-start-installed-name)) \ > $(+preinit) $(+prectorT) \ > @@ -637,8 +657,14 @@ endif > +prectorS = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtbeginS.o` > +postctorS = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtendS.o` > # Variants of the two previous definitions for statically linking programs. > +ifeq (yes,$(enable-static-pie)) > +# Static PIE must use PIE variants. > ++prectorT = $(+prectorS) > ++postctorT = $(+postctorS) OK. > +else > +prectorT = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtbeginT.o` > +postctorT = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtend.o` > +endif OK. > csu-objpfx = $(common-objpfx)csu/ > elf-objpfx = $(common-objpfx)elf/ > > @@ -959,7 +985,8 @@ libtypes = $(foreach o,$(object-suffixes-for-libc),$(libtype$o)) > all-object-suffixes := .o .os .oS > object-suffixes := > CPPFLAGS-.o = $(pic-default) > -CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) > +# libc.a must be compiled with -fPIE/-fpie for static PIE. > +CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) $(pie-default) OK. > libtype.o := lib%.a > object-suffixes += .o > ifeq (yes,$(build-shared)) > @@ -984,7 +1011,8 @@ ifeq (yes,$(build-profile)) > all-object-suffixes += .op > object-suffixes += .op > CPPFLAGS-.op = -DPROF $(pic-default) > -CFLAGS-.op = -pg > +# libc_p.a must be compiled with -fPIE/-fpie for static PIE. > +CFLAGS-.op = -pg $(pie-default) OK. > libtype.op = lib%_p.a > endif > > diff --git a/NEWS b/NEWS > index ab14d1eb1b..61598be94d 100644 > --- a/NEWS > +++ b/NEWS > @@ -9,6 +9,11 @@ Version 2.27 > > Major new features: > > +* Add --enable-static-pie configure option to build static PIE. The > + resulting libc.a can be used with the GCC option, -static-pie, which > + is available with GCC 8 or above, to create static position independent > + executable (static PIE). > + The description of a new configure option is relevant only to INSTALL. We must explain when users would use this feature and why. NEWS entries are user facing and must explain the function of the new feature. Does it improve security for static binaries? Should users switch to using them instead of normal static binaries? Lastly, we must explain which machines are supported in this initial release of the feature. Only x86_64? You need not check all machines, other maintainers can check and adjust the NEWS entry, but we have to commit to at least one machine supporting this feature, which I assume is x86_64. For example: * The GNU C Library can now be compiled with support for building static PIE executables (See --enable-static-pie in INSTALL). These static PIE exectuables are like static executables but can be loaded at any address and provide additional security hardening benefits at the cost of some memory and performance. When the library is built with --enable-static-pie the resulting libc.a is usable with GCC 8 and above to create static PIE executables using the GCC option '-static-pie'. This feature is currently supported on x86_64. > * Optimized x86-64 asin, atan2, exp, expf, log, pow, atan, sin and tan > with FMA, contributed by Arjan van de Ven and H.J. Lu from Intel. > > diff --git a/config.h.in b/config.h.in > index c140ff3ecb..f7db916711 100644 > --- a/config.h.in > +++ b/config.h.in > @@ -244,6 +244,9 @@ > /* Build glibc with tunables support. */ > #define HAVE_TUNABLES 0 > > +/* Define if static PIE is enabled. */ > +#define ENABLE_STATIC_PIE 0 > + OK. Architecture independent feature, which is OK to go in config.h (we're trying to get rid of any architecture specific entries). > /* Some compiler options may now allow to use ebp in __asm__ (used mainly > in i386 6 argument syscall issue). */ > #define CAN_USE_REGISTER_ASM_EBP 0 [snip configure] > diff --git a/configure.ac b/configure.ac > index 8ebc490a55..ae219f8fe0 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -176,6 +176,11 @@ AC_ARG_ENABLE([profile], > [build profiled library @<:@default=no@:>@]), > [profile=$enableval], > [profile=no]) > +AC_ARG_ENABLE([static-pie], > + AC_HELP_STRING([--enable-static-pie], > + [build static executables as PIE @<:@default=no@:>@]), This does 2 things: * It enables support for building static PIE executables. * It builds all static binaries and tests in the testsuite as static PIE executables. It should say that e.g. "Enable static PIE executable support and use it in the testsuite." I understand the desire to use such a functionality to test static PIE executables by converting the entire testsuite to use them, but we still need to test non-PIE static executables? How are we still doing that after this change? How are we testing non-PIE static executables after this change? > + [static_pie=$enableval], > + [static_pie=no]) OK. > AC_ARG_ENABLE([timezone-tools], > AC_HELP_STRING([--disable-timezone-tools], > [do not install timezone tools @<:@default=install@:>@]), > @@ -1281,6 +1286,19 @@ LIBC_LINKER_FEATURE([-z execstack], [-Wl,-z,execstack], > [libc_cv_z_execstack=yes], [libc_cv_z_execstack=no]) > AC_SUBST(libc_cv_z_execstack) > > +LIBC_LINKER_FEATURE([--no-dynamic-linker], > + [-Wl,--no-dynamic-linker], > + [libc_cv_no_dynamic_linker=yes], > + [libc_cv_no_dynamic_linker=no]) > +LIBC_CONFIG_VAR([have-no-dynamic-linker], [$libc_cv_no_dynamic_linker]) OK. > + > +AC_CACHE_CHECK(for -static-pie, libc_cv_static_pie, [dnl > +LIBC_TRY_CC_OPTION([-static-pie], > + [libc_cv_static_pie=yes], > + [libc_cv_static_pie=no]) > +]) > +LIBC_CONFIG_VAR([have-static-pie], [$libc_cv_static_pie]) OK. > + > AC_CACHE_CHECK(for -fpie, libc_cv_fpie, [dnl > LIBC_TRY_CC_OPTION([-fpie], [libc_cv_fpie=yes], [libc_cv_fpie=no]) > ]) > @@ -1788,6 +1806,17 @@ AC_SUBST(libc_cv_pie_default) > libc_cv_multidir=`${CC-cc} $CFLAGS $CPPFLAGS -print-multi-directory` > AC_SUBST(libc_cv_multidir) > > +if test "$static_pie" = yes; then > + # The linker must support --no-dynamic-linker. > + if test "$libc_cv_no_dynamic_linker" != yes; then > + AC_MSG_ERROR([linker support for --no-dynamic-linker needed]) > + fi > + # Default to PIE. > + libc_cv_pie_default=yes > + AC_DEFINE(ENABLE_STATIC_PIE) > +fi > +LIBC_CONFIG_VAR([enable-static-pie], [$static_pie]) OK. > + > AC_SUBST(profile) > AC_SUBST(static_nss) > > diff --git a/csu/Makefile b/csu/Makefile > index e42a32b3eb..e8ff1ec257 100644 > --- a/csu/Makefile > +++ b/csu/Makefile > @@ -37,7 +37,8 @@ extra-objs = start.o \ > S$(start-installed-name) > omit-deps = $(patsubst %.o,%,$(start-installed-name) g$(start-installed-name) \ > b$(start-installed-name) $(csu-dummies) \ > - S$(start-installed-name)) > + S$(start-installed-name) \ > + r$(start-installed-name)) OK. > install-lib = $(start-installed-name) g$(start-installed-name) $(csu-dummies) > > # No tests are allowed in the csu/ subdirectory because the startup > @@ -55,6 +56,10 @@ extra-objs += gmon-start.o > endif > install-lib += S$(start-installed-name) > generated += start.os > +ifeq (yes,$(enable-static-pie)) > +extra-objs += r$(start-installed-name) > +install-lib += r$(start-installed-name) > +endif OK. > else > extra-objs += gmon-start.o > endif > @@ -82,7 +87,10 @@ multilib-extra-objs = $(addprefix $(multidir)/, $(install-lib)) > extra-objs += $(multilib-extra-objs) > endif > > -extra-objs += abi-note.o init.o > +extra-objs += abi-note.o init.o static-reloc.o > +ifeq (yes,$(build-shared)) > +extra-objs += static-reloc.os > +endif OK. > asm-CPPFLAGS += -I$(objpfx). > > # Enable unwinding so backtrace unwinds to __libc_start_main > @@ -101,6 +109,9 @@ ifndef start-installed-name-rule > # We link the ELF startfile along with a SHT_NOTE section indicating > # the kernel ABI the binaries linked with this library will require. > $(objpfx)$(start-installed-name): $(objpfx)start.o $(objpfx)abi-note.o \ > + $(objpfx)init.o $(objpfx)static-reloc.o > + $(link-relocatable) > +$(objpfx)r$(start-installed-name): $(objpfx)start.o $(objpfx)abi-note.o \ OK. > $(objpfx)init.o > $(link-relocatable) > $(objpfx)S$(start-installed-name): $(objpfx)start.os $(objpfx)abi-note.o \ > @@ -113,7 +124,7 @@ endif > # to turn on profiling code at startup. > ifeq (yes,$(build-shared)) > $(objpfx)g$(start-installed-name): \ > - $(objpfx)g%: $(objpfx)S% $(objpfx)gmon-start.os > + $(objpfx)g%: $(objpfx)S% $(objpfx)gmon-start.os $(objpfx)static-reloc.os OK. > $(link-relocatable) > ifneq ($(start-installed-name),$(static-start-installed-name)) > $(objpfx)g$(static-start-installed-name): \ > diff --git a/csu/libc-start.c b/csu/libc-start.c > index 24c63be02f..34dd125260 100644 > --- a/csu/libc-start.c > +++ b/csu/libc-start.c > @@ -141,6 +141,8 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), > __libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up; > > #ifndef SHARED > + _dl_relocate_static_pie (); OK. > + > char **ev = &argv[argc + 1]; > > __environ = ev; > diff --git a/csu/libc-tls.c b/csu/libc-tls.c > index 00138eb43a..1f8ddaf543 100644 > --- a/csu/libc-tls.c > +++ b/csu/libc-tls.c > @@ -114,6 +114,8 @@ __libc_setup_tls (void) > size_t tcb_offset; > const ElfW(Phdr) *phdr; > > + struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded; OK. > + > /* Look through the TLS segment if there is any. */ > if (_dl_phdr != NULL) > for (phdr = _dl_phdr; phdr < &_dl_phdr[_dl_phnum]; ++phdr) > @@ -122,7 +124,7 @@ __libc_setup_tls (void) > /* Remember the values we need. */ > memsz = phdr->p_memsz; > filesz = phdr->p_filesz; > - initimage = (void *) phdr->p_vaddr; > + initimage = (void *) phdr->p_vaddr + main_map->l_addr; OK. > align = phdr->p_align; > if (phdr->p_align > max_align) > max_align = phdr->p_align; > @@ -163,8 +165,6 @@ __libc_setup_tls (void) > _dl_static_dtv[0].counter = (sizeof (_dl_static_dtv) / sizeof (_dl_static_dtv[0])) - 2; > // _dl_static_dtv[1].counter = 0; would be needed if not already done > > - struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded; > - > /* Initialize the TLS block. */ > #if TLS_TCB_AT_TP > _dl_static_dtv[2].pointer.val = ((char *) tlsblock + tcb_offset > diff --git a/csu/static-reloc.c b/csu/static-reloc.c > new file mode 100644 > index 0000000000..37be72c8ea > --- /dev/null > +++ b/csu/static-reloc.c > @@ -0,0 +1,26 @@ > +/* Special startup support for non-PIE static executables. > + Copyright (C) 2017 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <http://www.gnu.org/licenses/>. */ > + > +#if ENABLE_STATIC_PIE > +#include <ldsodefs.h> > + > +void > +_dl_relocate_static_pie (void) > +{ > +} > +#endif OK. > diff --git a/elf/Makefile b/elf/Makefile > index a31fb72498..cb035e63aa 100644 > --- a/elf/Makefile > +++ b/elf/Makefile > @@ -24,7 +24,8 @@ include ../Makeconfig > headers = elf.h bits/elfclass.h link.h bits/link.h > routines = $(all-dl-routines) dl-support dl-iteratephdr \ > dl-addr dl-addr-obj enbl-secure dl-profstub \ > - dl-origin dl-libc dl-sym dl-sysdep dl-error > + dl-origin dl-libc dl-sym dl-sysdep dl-error \ > + dl-reloc-static-pie OK. > > # The core dynamic linking functions are in libc for the static and > # profiled libraries. > @@ -52,7 +53,7 @@ endif > all-dl-routines = $(dl-routines) $(sysdep-dl-routines) > # But they are absent from the shared libc, because that code is in ld.so. > elide-routines.os = $(all-dl-routines) dl-support enbl-secure dl-origin \ > - dl-sysdep dl-exception > + dl-sysdep dl-exception dl-reloc-static-pie OK. > shared-only-routines += dl-caller > > # ld.so uses those routines, plus some special stuff for being the program > diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c > new file mode 100644 > index 0000000000..6e43aea76a > --- /dev/null > +++ b/elf/dl-reloc-static-pie.c > @@ -0,0 +1,52 @@ > +/* Support for relocating static PIE. > + Copyright (C) 2017 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <http://www.gnu.org/licenses/>. */ > + > +#if ENABLE_STATIC_PIE > +#include <unistd.h> > +#include <ldsodefs.h> > +#include "dynamic-link.h" > + > +/* Relocate static executable with PIE. */ > + > +void > +_dl_relocate_static_pie (void) > +{ > + struct link_map *main_map = _dl_get_dl_main_map (); > + > +# define STATIC_PIE_BOOTSTRAP > +# define BOOTSTRAP_MAP (main_map) > +# define RESOLVE_MAP(sym, version, flags) BOOTSTRAP_MAP > +# include "dynamic-link.h" > + > + /* Figure out the run-time load address of static PIE. */ > + main_map->l_addr = elf_machine_load_address (); OK. > + > + /* Read our own dynamic section and fill in the info array. */ > + main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ()); > + elf_get_dynamic_info (main_map, NULL); OK. > + > +# ifdef ELF_MACHINE_BEFORE_RTLD_RELOC > + ELF_MACHINE_BEFORE_RTLD_RELOC (main_map->l_info); > +# endif > + > + /* Relocate ourselves so we can do normal function calls and > + data access using the global offset table. */ > + ELF_DYNAMIC_RELOCATE (main_map, 0, 0, 0); > + main_map->l_relocated = 1; OK. > +} > +#endif > 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; > +} OK. > +#endif > diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h > index ebea7567cd..6278649711 100644 > --- a/elf/dynamic-link.h > +++ b/elf/dynamic-link.h > @@ -94,7 +94,7 @@ elf_machine_lazy_rel (struct link_map *map, > > #ifdef RESOLVE_MAP > > -# ifdef RTLD_BOOTSTRAP > +# if defined RTLD_BOOTSTRAP || defined STATIC_PIE_BOOTSTRAP OK. > # define ELF_DURING_STARTUP (1) > # else > # define ELF_DURING_STARTUP (0) > diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h > index 7525c3a5b2..eb26d23649 100644 > --- a/elf/get-dynamic-info.h > +++ b/elf/get-dynamic-info.h > @@ -38,7 +38,7 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) > typedef Elf64_Xword d_tag_utype; > #endif > > -#ifndef RTLD_BOOTSTRAP > +#if !defined RTLD_BOOTSTRAP && !defined STATIC_PIE_BOOTSTRAP OK. > if (dyn == NULL) > return; > #endif > @@ -139,9 +139,11 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) > /* Only the bind now flags are allowed. */ > assert (info[VERSYMIDX (DT_FLAGS_1)] == NULL > || (info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val & ~DF_1_NOW) == 0); > + /* Flags must not be set for ld.so. */ > assert (info[DT_FLAGS] == NULL > || (info[DT_FLAGS]->d_un.d_val & ~DF_BIND_NOW) == 0); OK. > - /* Flags must not be set for ld.so. */ > +#endif > +#if defined RTLD_BOOTSTRAP || defined STATIC_PIE_BOOTSTRAP > assert (info[DT_RUNPATH] == NULL); > assert (info[DT_RPATH] == NULL); > #else > diff --git a/gmon/Makefile b/gmon/Makefile > index 89ab3fc7da..f83fcc9d71 100644 > --- a/gmon/Makefile > +++ b/gmon/Makefile > @@ -39,6 +39,10 @@ tests-static += tst-gmon-static > ifeq (yesyes,$(have-fpie)$(build-shared)) > tests += tst-gmon-pie > tests-pie += tst-gmon-pie > +ifeq (yes,$(enable-static-pie)) > +tests += tst-gmon-static-pie > +tests-static += tst-gmon-static-pie OK. > +endif > endif > > # The mcount code won't work without a frame pointer. > @@ -67,6 +71,15 @@ ifeq ($(run-built-tests),yes) > tests-special += $(objpfx)tst-gmon-pie-gprof.out > endif > > +ifeq (yes,$(enable-static-pie)) > +CFLAGS-tst-gmon-static-pie.c := $(PIE-ccflag) -fno-omit-frame-pointer -pg > +CRT-tst-gmon-static-pie := $(csu-objpfx)grcrt1.o > +tst-gmon-static-pie-ENV := GMON_OUT_PREFIX=$(objpfx)tst-gmon-static-pie.data > +ifeq ($(run-built-tests),yes) > +tests-special += $(objpfx)tst-gmon-static-pie-gprof.out > +endif > +endif OK. > + > > include ../Rules > > @@ -111,3 +124,13 @@ clean-tst-gmon-pie-data: > $(objpfx)tst-gmon-pie-gprof.out: tst-gmon-gprof.sh $(objpfx)tst-gmon-pie.out > $(SHELL) $< $(GPROF) $(objpfx)tst-gmon-pie $(objpfx)tst-gmon-pie.data.* > $@; \ > $(evaluate-test) > + > +$(objpfx)tst-gmon-static-pie.out: clean-tst-gmon-static-pie-data > +clean-tst-gmon-static-pie-data: > + rm -f $(objpfx)tst-gmon-static-pie.data.* > + > +$(objpfx)tst-gmon-static-pie-gprof.out: tst-gmon-static-gprof.sh \ > + $(objpfx)tst-gmon-static-pie.out > + $(SHELL) $< $(GPROF) $(objpfx)tst-gmon-static-pie \ > + $(objpfx)tst-gmon-static-pie.data.* > $@; \ > + $(evaluate-test) OK. > diff --git a/gmon/tst-gmon-static-pie.c b/gmon/tst-gmon-static-pie.c > new file mode 100644 > index 0000000000..1eef2583b6 > --- /dev/null > +++ b/gmon/tst-gmon-static-pie.c > @@ -0,0 +1 @@ > +#include "tst-gmon.c" > diff --git a/manual/install.texi b/manual/install.texi > index f1fa28c937..86193ade3f 100644 > --- a/manual/install.texi > +++ b/manual/install.texi > @@ -120,6 +120,13 @@ Don't build shared libraries even if it is possible. Not all systems > support shared libraries; you need ELF support and (currently) the GNU > linker. > > +@item --enable-static-pie This should be rewritten to explain the feature that it enables first, and then the ancilliary benefits like turning it on in the testsuite. > +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. > + > @item --disable-profile > Don't build libraries with profiling information. You may want to use > this option if you don't plan to do profiling. > diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h > index 52a792a597..af89f5eeb4 100644 > --- a/sysdeps/generic/ldsodefs.h > +++ b/sysdeps/generic/ldsodefs.h > @@ -1051,6 +1051,17 @@ extern void _dl_determine_tlsoffset (void) attribute_hidden; > stack protector, among other things). */ > void __libc_setup_tls (void); > > +# if ENABLE_STATIC_PIE > +/* Relocate static executable with PIE. */ > +extern void _dl_relocate_static_pie (void) attribute_hidden; > + > +/* Get a pointer to _dl_main_map. */ > +extern struct link_map * _dl_get_dl_main_map (void) > + __attribute__ ((visibility ("hidden"))); > +# else > +# define _dl_relocate_static_pie() > +# endif > + > /* Initialization of libpthread for statically linked applications. > If libpthread is not linked in, this is an empty function. */ > void __pthread_initialize_minimal (void) weak_function; > diff --git a/sysdeps/i386/configure b/sysdeps/i386/configure > index 4cf968d8bc..90c63caf35 100644 [snip regenerated sysdeps/i386/configure] > diff --git a/sysdeps/i386/configure.ac b/sysdeps/i386/configure.ac > index b598b120bc..6d2068d2b3 100644 > --- a/sysdeps/i386/configure.ac > +++ b/sysdeps/i386/configure.ac > @@ -30,6 +30,29 @@ LIBC_COMPILER_BUILTIN_INLINED( > *** Please use host i786, i686, i586, or i486. > *** For example: /source/glibc/configure CFLAGS='-O2 -march=i686' ...])]) > > +dnl Check if linker can convert "movl main@GOT(%ebx), %eax" to > +dnl "leal main@GOTOFF(%ebx), %eax" for static PIE. > +if test "$static_pie" = yes; then > + AC_CACHE_CHECK(for linker static PIE support, libc_cv_ld_static_pie, [dnl > +cat > conftest.s <<\EOF > + .text > + .global _start > +_start: > + movl _start@GOT(%ebx), %eax > +EOF > + libc_cv_pie_option="-Wl,-pie" > + libc_cv_ld_static_pie=no > + if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&AS_MESSAGE_LOG_FD); then > + if $READELF -r conftest | grep 'There are no relocations in this file.' > /dev/null; then > + libc_cv_ld_static_pie=yes > + fi > + fi > +rm -f conftest*]) > + if test "$libc_cv_ld_static_pie" != yes; then > + AC_MSG_ERROR([linker support for static PIE needed]) OK. > + fi > +fi > + > dnl Check whether asm supports Intel MPX > AC_CACHE_CHECK(for Intel MPX support, libc_cv_asm_mpx, [dnl > cat > conftest.s <<\EOF [snip regenerated sysdeps/x86_64/configure] -- Cheers, Carlos. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-11-30 21:45 ` Carlos O'Donell @ 2017-11-30 22:37 ` Maciej W. Rozycki [not found] ` <CAMe9rOpDRknZANuSvXAqU_qaXzGRjt=uY5BZLJoE_o9Ke+9yfw@mail.gmail.com> 2017-12-01 18:24 ` H.J. Lu 1 sibling, 1 reply; 37+ messages in thread From: Maciej W. Rozycki @ 2017-11-30 22:37 UTC (permalink / raw) To: Carlos O'Donell Cc: H.J. Lu, Szabolcs Nagy, nd, Joseph Myers, GNU C Library On Thu, 30 Nov 2017, Carlos O'Donell wrote: > > FAIL: glibcs-mips64el-linux-gnu-n32 build > > FAIL: glibcs-mips64el-linux-gnu-n32-nan2008 build > > FAIL: glibcs-mips64el-linux-gnu-n32-nan2008-soft build > > FAIL: glibcs-mips64el-linux-gnu-n32-soft build > > FAIL: glibcs-mips64-linux-gnu-n32 build > > FAIL: glibcs-mips64-linux-gnu-n32-nan2008 build > > FAIL: glibcs-mips64-linux-gnu-n32-nan2008-soft build > > FAIL: glibcs-mips64-linux-gnu-n32-soft build > > FAIL: glibcs-mipsel-linux-gnu build > > FAIL: glibcs-mipsel-linux-gnu-nan2008 build > > FAIL: glibcs-mipsel-linux-gnu-nan2008-soft build > > FAIL: glibcs-mipsel-linux-gnu-soft build > > FAIL: glibcs-mips-linux-gnu build > > FAIL: glibcs-mips-linux-gnu-nan2008 build > > FAIL: glibcs-mips-linux-gnu-nan2008-soft build > > FAIL: glibcs-mips-linux-gnu-soft build > > > > elf/sln is failed to link due to: > > > > crt1.o: relocation R_MIPS_HI16 against `_gp' can not be used when making a shared object; recompile with -fPIC > > > > This is caused by linker bug and/or non-PIC code in crt1.o. Or likely a bug in the `make' recipe used to link `sln' -- Scrt1.o has to be chosen instead for PIE links and the GCC driver gets it right, however we use `-nostartfiles' and link in the bits by hand. Maciej ^ permalink raw reply [flat|nested] 37+ messages in thread
[parent not found: <CAMe9rOpDRknZANuSvXAqU_qaXzGRjt=uY5BZLJoE_o9Ke+9yfw@mail.gmail.com>]
[parent not found: <alpine.DEB.2.00.1711302308170.31156@tp.orcam.me.uk>]
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] [not found] ` <alpine.DEB.2.00.1711302308170.31156@tp.orcam.me.uk> @ 2017-12-01 1:08 ` H.J. Lu 2017-12-01 1:58 ` Maciej W. Rozycki 0 siblings, 1 reply; 37+ messages in thread From: H.J. Lu @ 2017-12-01 1:08 UTC (permalink / raw) To: Maciej W. Rozycki, GNU C Library On Thu, Nov 30, 2017 at 3:31 PM, Maciej W. Rozycki <macro@mips.com> wrote: > On Thu, 30 Nov 2017, H.J. Lu wrote: > >> > Or likely a bug in the `make' recipe used to link `sln' -- Scrt1.o has to >> > be chosen instead for PIE links and the GCC driver gets it right, however >> > we use `-nostartfiles' and link in the bits by hand. >> >> My current patch links rcrt1.o for static PIE. I got >> >> mips64-glibc-linux-gnu-gcc -mabi=32 -nostdlib -nostartfiles -static -o >> /export/gnu/import/git/toolchain/build/glibcs/mips-linux-gnu/glibc/elf/sln >> -Wl,-pie,--no-dynamic-linker,--eh-frame-hdr,-z,text >> /export/gnu/import/git/toolchain/build/glibcs/mips-linux-gnu/glibc/csu/rcrt1.o >> /export/gnu/import/git/toolchain/build/glibcs/mips-linux-gnu/glibc/csu/crti.o >> `mips64-glibc-linux-gnu-gcc -mabi=32 --print-file-name=crtbeginS.o` >> /export/gnu/import/git/toolchain/build/glibcs/mips-linux-gnu/glibc/elf/sln.o >> /export/gnu/import/git/toolchain/build/glibcs/mips-linux-gnu/glibc/elf/static-stubs.o >> -Wl,--start-group >> /export/gnu/import/git/toolchain/build/glibcs/mips-linux-gnu/glibc/libc.a >> -lgcc -Wl,--end-group `mips64-glibc-linux-gnu-gcc -mabi=32 >> --print-file-name=crtendS.o` >> /export/gnu/import/git/toolchain/build/glibcs/mips-linux-gnu/glibc/csu/crtn.o >> /export/ssd/git/toolchain/install/compilers/mips64-linux-gnu/bin/../lib/gcc/mips64-glibc-linux-gnu/7.2.1/../../../../mips64-glibc-linux-gnu/bin/ld: >> /export/gnu/import/git/toolchain/build/glibcs/mips-linux-gnu/glibc/csu/rcrt1.o: >> relocation R_MIPS_HI16 against `_gp' can not be used when making a >> shared object; recompile with -fPIC >> /export/ssd/git/toolchain/install/compilers/mips64-linux-gnu/bin/../lib/gcc/mips64-glibc-linux-gnu/7.2.1/../../../../mips64-glibc-linux-gnu/bin/ld: >> /export/gnu/import/git/toolchain/build/glibcs/mips-linux-gnu/glibc/libc.a(bsd-_setjmp.o): >> relocation R_MIPS_26 against `__sigsetjmp' can not be used when making >> a shared object; recompile with -fPIC >> /export/ssd/git/toolchain/install/compilers/mips64-linux-gnu/bin/../lib/gcc/mips64-glibc-linux-gnu/7.2.1/../../../../mips64-glibc-linux-gnu/bin/ld: >> /export/gnu/import/git/toolchain/build/glibcs/mips-linux-gnu/glibc/libc.a(sched_yield.o): >> relocation R_MIPS_26 against `__syscall_error' can not be used when >> making a shared object; recompile with -fPIC >> /export/ssd/git/toolchain/install/compilers/mips64-linux-gnu/bin/../lib/gcc/mips64-glibc-linux-gnu/7.2.1/../../../../mips64-glibc-linux-gnu/bin/ld: >> /export/gnu/import/git/toolchain/build/glibcs/mips-linux-gnu/glibc/libc.a(symlink.o): >> relocation R_MIPS_26 against `__syscall_error' can not be used when >> making a shared object; recompile with -fPIC >> /export/ssd/git/toolchain/install/compilers/mips64-linux-gnu/bin/../lib/gcc/mips64-glibc-linux-gnu/7.2.1/../../../../mips64-glibc-linux-gnu/bin/ld: >> /export/gnu/import/git/toolchain/build/glibcs/mips-linux-gnu/glibc/libc.a(unlink.o): >> relocation R_MIPS_26 against `__syscall_error' can not be used when >> making a shared object; recompile with -fPIC >> /export/ssd/git/toolchain/install/compilers/mips64-linux-gnu/bin/../lib/gcc/mips64-glibc-linux-gnu/7.2.1/../../../../mips64-glibc-linux-gnu/bin/ld: >> /export/gnu/import/git/toolchain/build/glibcs/mips-linux-gnu/glibc/libc.a(munmap.o): >> relocation R_MIPS_26 against `__syscall_error' can not be used when >> making a shared object; recompile with -fPIC >> /export/ssd/git/toolchain/install/compilers/mips64-linux-gnu/bin/../lib/gcc/mips64-glibc-linux-gnu/7.2.1/../../../../mips64-glibc-linux-gnu/bin/ld: >> /export/gnu/import/git/toolchain/build/glibcs/mips-linux-gnu/glibc/libc.a(mprotect.o): >> relocation R_MIPS_26 against `__syscall_error' can not be used when >> making a shared object; recompile with -fPIC >> /export/ssd/git/toolchain/install/compilers/mips64-linux-gnu/bin/../lib/gcc/mips64-glibc-linux-gnu/7.2.1/../../../../mips64-glibc-linux-gnu/bin/ld: >> /export/gnu/import/git/toolchain/build/glibcs/mips-linux-gnu/glibc/libc.a(madvise.o): >> relocation R_MIPS_26 against `__syscall_error' can not be used when >> making a shared object; recompile with -fPIC >> /export/ssd/git/toolchain/install/compilers/mips64-linux-gnu/bin/../lib/gcc/mips64-glibc-linux-gnu/7.2.1/../../../../mips64-glibc-linux-gnu/bin/ld: >> /export/gnu/import/git/toolchain/build/glibcs/mips-linux-gnu/glibc/libc.a(mremap.o): >> relocation R_MIPS_26 against `__syscall_error' can not be used when >> making a shared object; recompile with -fPIC >> /export/ssd/git/toolchain/install/compilers/mips64-linux-gnu/bin/../lib/gcc/mips64-glibc-linux-gnu/7.2.1/../../../../mips64-glibc-linux-gnu/bin/ld: >> /export/gnu/import/git/toolchain/build/glibcs/mips-linux-gnu/glibc/libc.a(sysinfo.o): >> relocation R_MIPS_26 against `__syscall_error' can not be used when >> making a shared object; recompile with -fPIC >> /export/ssd/git/toolchain/install/compilers/mips64-linux-gnu/bin/../lib/gcc/mips64-glibc-linux-gnu/7.2.1/../../../../mips64-glibc-linux-gnu/bin/ld: >> /export/gnu/import/git/toolchain/build/glibcs/mips-linux-gnu/glibc/libc.a(sysdep.o): >> relocation R_MIPS_26 against `__errno_location' can not be used when >> making a shared object; recompile with -fPIC >> /export/ssd/git/toolchain/install/compilers/mips64-linux-gnu/bin/../lib/gcc/mips64-glibc-linux-gnu/7.2.1/../../../../mips64-glibc-linux-gnu/bin/ld: >> /export/gnu/import/git/toolchain/build/glibcs/mips-linux-gnu/glibc/libc.a(setjmp.o): >> relocation R_MIPS_26 against `__sigsetjmp_aux' can not be used when >> making a shared object; recompile with -fPIC >> /export/ssd/git/toolchain/install/compilers/mips64-linux-gnu/bin/../lib/gcc/mips64-glibc-linux-gnu/7.2.1/../../../../mips64-glibc-linux-gnu/bin/ld: >> /export/gnu/import/git/toolchain/build/glibcs/mips-linux-gnu/glibc/libc.a(uname.o): >> relocation R_MIPS_26 against `__syscall_error' can not be used when >> making a shared object; recompile with -fPIC >> /export/ssd/git/toolchain/install/compilers/mips64-linux-gnu/bin/../lib/gcc/mips64-glibc-linux-gnu/7.2.1/../../../../mips64-glibc-linux-gnu/bin/ld: >> /export/gnu/import/git/toolchain/build/glibcs/mips-linux-gnu/glibc/libc.a(prctl.o): >> relocation R_MIPS_26 against `__syscall_error' can not be used when >> making a shared object; recompile with -fPIC >> /export/ssd/git/toolchain/install/compilers/mips64-linux-gnu/bin/../lib/gcc/mips64-glibc-linux-gnu/7.2.1/../../../../mips64-glibc-linux-gnu/bin/ld: >> /export/gnu/import/git/toolchain/build/glibcs/mips-linux-gnu/glibc/libc.a(setitimer.o): >> relocation R_MIPS_26 against `__syscall_error' can not be used when >> making a shared object; recompile with -fPIC >> collect2: error: ld returned 1 exit status > > I don't know what rcrt1.o is, this is the first time I see it mentioned. See: https://gcc.gnu.org/ml/gcc-patches/2017-11/msg00247.html > However overall all these MIPS relocations are strictly non-PIC ones, so > clearly this code has not been correctly built. That is MIPS specific issue. It could be bfd_link_pic vs bfd_link_executable in MIPS linker backend. > AFAICT you need to pass -DPIC to GCC when assembling sysdeps/mips/start.S > to get a position-independent intermediate object. The same applies to > our other MIPS assembly sources. Everything is compiled with -fPIE -DPIC: +ifeq (yes,$(enable-static-pie)) +pic-default = -DPIC +pie-default = $(pie-ccflag) +ifeq (yes,$(have-static-pie)) +default-pie-ldflag = -static-pie +else +default-pie-ldflag = -Wl,-pie,--no-dynamic-linker,--eh-frame-hdr,-z,text +endif +endif -- H.J. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-12-01 1:08 ` H.J. Lu @ 2017-12-01 1:58 ` Maciej W. Rozycki 2017-12-01 4:18 ` H.J. Lu 0 siblings, 1 reply; 37+ messages in thread From: Maciej W. Rozycki @ 2017-12-01 1:58 UTC (permalink / raw) To: H.J. Lu; +Cc: GNU C Library On Thu, 30 Nov 2017, H.J. Lu wrote: > > However overall all these MIPS relocations are strictly non-PIC ones, so > > clearly this code has not been correctly built. > > That is MIPS specific issue. It could be bfd_link_pic vs bfd_link_executable > in MIPS linker backend. Well, these relocations are produced by GAS, which obviously has nothing to do with linking. You need to find a way for them not to be produced in the first place, as they are not valid in a PIE executable link. > > AFAICT you need to pass -DPIC to GCC when assembling sysdeps/mips/start.S > > to get a position-independent intermediate object. The same applies to > > our other MIPS assembly sources. > > Everything is compiled with -fPIE -DPIC: > > +ifeq (yes,$(enable-static-pie)) > +pic-default = -DPIC > +pie-default = $(pie-ccflag) > +ifeq (yes,$(have-static-pie)) > +default-pie-ldflag = -static-pie > +else > +default-pie-ldflag = -Wl,-pie,--no-dynamic-linker,--eh-frame-hdr,-z,text > +endif > +endif Well, that doesn't prove that these options actually make it to the GCC invocation line for say rcrt1.o. Quoting the actual line for rcrt1.o from a build log would be more useful. Maciej ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-12-01 1:58 ` Maciej W. Rozycki @ 2017-12-01 4:18 ` H.J. Lu 2017-12-01 9:59 ` Maciej W. Rozycki 0 siblings, 1 reply; 37+ messages in thread From: H.J. Lu @ 2017-12-01 4:18 UTC (permalink / raw) To: Maciej W. Rozycki; +Cc: GNU C Library On Thu, Nov 30, 2017 at 5:57 PM, Maciej W. Rozycki <macro@mips.com> wrote: > On Thu, 30 Nov 2017, H.J. Lu wrote: > >> > However overall all these MIPS relocations are strictly non-PIC ones, so >> > clearly this code has not been correctly built. >> >> That is MIPS specific issue. It could be bfd_link_pic vs bfd_link_executable >> in MIPS linker backend. > > Well, these relocations are produced by GAS, which obviously has nothing > to do with linking. You need to find a way for them not to be produced in > the first place, as they are not valid in a PIE executable link. > >> > AFAICT you need to pass -DPIC to GCC when assembling sysdeps/mips/start.S >> > to get a position-independent intermediate object. The same applies to >> > our other MIPS assembly sources. >> >> Everything is compiled with -fPIE -DPIC: >> >> +ifeq (yes,$(enable-static-pie)) >> +pic-default = -DPIC >> +pie-default = $(pie-ccflag) >> +ifeq (yes,$(have-static-pie)) >> +default-pie-ldflag = -static-pie >> +else >> +default-pie-ldflag = -Wl,-pie,--no-dynamic-linker,--eh-frame-hdr,-z,text >> +endif >> +endif > > Well, that doesn't prove that these options actually make it to the GCC > invocation line for say rcrt1.o. Quoting the actual line for rcrt1.o from > a build log would be more useful. > This patch fixes mips build with --enable-static-pie: diff --git a/sysdeps/mips/Makefile b/sysdeps/mips/Makefile index fd891ddf09..7ac6fa5031 100644 --- a/sysdeps/mips/Makefile +++ b/sysdeps/mips/Makefile @@ -23,6 +23,9 @@ CPPFLAGS-crtn.S += $(pic-ccflag) endif ASFLAGS-.os += $(pic-ccflag) +# libc.a and libc_p.a must be compiled with -fPIE/-fpie for static PIE. +ASFLAGS-.o += $(pie-default) +ASFLAGS-.op += $(pie-default) ifeq ($(subdir),elf) ifneq ($(o32-fpabi),) Can you try native mips build with --enable-static-pie using hjl/pie/static branch? Thanks. -- H.J. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-12-01 4:18 ` H.J. Lu @ 2017-12-01 9:59 ` Maciej W. Rozycki 2017-12-01 12:27 ` Joseph Myers 0 siblings, 1 reply; 37+ messages in thread From: Maciej W. Rozycki @ 2017-12-01 9:59 UTC (permalink / raw) To: H.J. Lu, Joseph S. Myers; +Cc: GNU C Library On Thu, 30 Nov 2017, H.J. Lu wrote: > This patch fixes mips build with --enable-static-pie: > > diff --git a/sysdeps/mips/Makefile b/sysdeps/mips/Makefile > index fd891ddf09..7ac6fa5031 100644 > --- a/sysdeps/mips/Makefile > +++ b/sysdeps/mips/Makefile > @@ -23,6 +23,9 @@ CPPFLAGS-crtn.S += $(pic-ccflag) > endif > > ASFLAGS-.os += $(pic-ccflag) > +# libc.a and libc_p.a must be compiled with -fPIE/-fpie for static PIE. > +ASFLAGS-.o += $(pie-default) > +ASFLAGS-.op += $(pie-default) > > ifeq ($(subdir),elf) > ifneq ($(o32-fpabi),) > > Can you try native mips build with --enable-static-pie using hjl/pie/static > branch? I'm not sure if I'm set up for a native glibc build right now, I haven't done one for a while now. I could try a cross build right away, however I am too loaded with other stuff to commit to do testing for you at the moment. Perhaps Joseph would be kind enough, as the MIPS port maintainer -- Joseph? Maciej ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-12-01 9:59 ` Maciej W. Rozycki @ 2017-12-01 12:27 ` Joseph Myers 2017-12-01 13:35 ` H.J. Lu 0 siblings, 1 reply; 37+ messages in thread From: Joseph Myers @ 2017-12-01 12:27 UTC (permalink / raw) To: Maciej W. Rozycki; +Cc: H.J. Lu, GNU C Library On Fri, 1 Dec 2017, Maciej W. Rozycki wrote: > > Can you try native mips build with --enable-static-pie using hjl/pie/static > > branch? > > I'm not sure if I'm set up for a native glibc build right now, I haven't > done one for a while now. I could try a cross build right away, however I > am too loaded with other stuff to commit to do testing for you at the > moment. I've not done native MIPS builds at all, but I don't think native versus cross is relevant here. The main thing is that the wiki instructions, if and when this feature reaches consensus for inclusion on master, give sufficient information on what testing is needed of whether the feature works on a given architecture before that architecture can be removed from the list of those that haven't had execution testing (whether or not the build completes OK for them). For example, are any special GCC configure options needed, or just the glibc configure option --enable-static-pie? Does GCC need to be a version (i.e. GCC 8 or later) that supports the -static-pie option in order to test this glibc feature? -- Joseph S. Myers joseph@codesourcery.com ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-12-01 12:27 ` Joseph Myers @ 2017-12-01 13:35 ` H.J. Lu 0 siblings, 0 replies; 37+ messages in thread From: H.J. Lu @ 2017-12-01 13:35 UTC (permalink / raw) To: Joseph Myers; +Cc: Maciej W. Rozycki, GNU C Library On Fri, Dec 1, 2017 at 4:27 AM, Joseph Myers <joseph@codesourcery.com> wrote: > On Fri, 1 Dec 2017, Maciej W. Rozycki wrote: > >> > Can you try native mips build with --enable-static-pie using hjl/pie/static >> > branch? >> >> I'm not sure if I'm set up for a native glibc build right now, I haven't >> done one for a while now. I could try a cross build right away, however I >> am too loaded with other stuff to commit to do testing for you at the >> moment. > > I've not done native MIPS builds at all, but I don't think native versus > cross is relevant here. The main thing is that the wiki instructions, if > and when this feature reaches consensus for inclusion on master, give > sufficient information on what testing is needed of whether the feature > works on a given architecture before that architecture can be removed from > the list of those that haven't had execution testing (whether or not the > build completes OK for them). For example, are any special GCC configure > options needed, or just the glibc configure option --enable-static-pie? > Does GCC need to be a version (i.e. GCC 8 or later) that supports the > -static-pie option in order to test this glibc feature? > GCC must support PIE to build static PIE glibc. The main issue is linker. Many ELF linker backends have various issues with PIE, especially static PIE. Other than those, there are no special requirements. To use static PIE glibc to create static PIE with "gcc -static-pie", GCC 8 is needed. I also have backported it to GCC 7 on hjl/pie/gcc-7-branch branch in gcc git repo. -- H.J. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-11-30 21:45 ` Carlos O'Donell 2017-11-30 22:37 ` Maciej W. Rozycki @ 2017-12-01 18:24 ` H.J. Lu 2017-12-08 13:14 ` H.J. Lu 2017-12-15 21:19 ` Carlos O'Donell 1 sibling, 2 replies; 37+ messages in thread From: H.J. Lu @ 2017-12-01 18:24 UTC (permalink / raw) To: Carlos O'Donell; +Cc: Szabolcs Nagy, nd, Joseph Myers, GNU C Library [-- Attachment #1: Type: text/plain, Size: 10894 bytes --] On Thu, Nov 30, 2017 at 1:44 PM, Carlos O'Donell <carlos@redhat.com> wrote: > H.J., > > High Level: > > At a high level I have no objection with the idea of static PIE executables, > it makes sense to support such things. Thanks for your feedbacks. > My only nit is that we need to do a better job of explaining to users why > they would use them and under what circumstances. To that end you have a bit > more work to do in the commit message, install.texit, and NEWS entry. > > Design: > > I have one design question below which around testing static non-PIE executables > in a --enable-static-pie build. See below. > > Implementation: > > Everything looks good except the use of firstword in +link-static-before-libc, > which I describe below. I think this is a hack and should be changed to better > represent the expected semantics and structure you are looking to support. Fixed. > Thank you for your work in this area. > > Look forward to a v2. > >> From 7026a79c1f71f5decd135208503fd4186193ffb8 Mon Sep 17 00:00:00 2001 >> From: "H.J. Lu" <hjl.tools@gmail.com> >> Date: Mon, 17 Jul 2017 08:17:32 -0700 >> Subject: [PATCH] Add --enable-static-pie configure option to build static PIE >> [BZ #19574] >> >> 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. > > You write "which are allowed", shouldn't that be "which are not allowed"? Fixed. > The commit message must explain the following: > > * Why would a user use this feature? > - What does it provide over and beyond existing static executables > > * How does a user decide to use this feature? > - Should everyone use it? > - Should you use it if you care about security, and what does it cost? > > Please include the answers to these questions in a the next versions > commit message. I added : Static PIE extends address space layout randomization to static executables. It provides additional security hardening benefits at the cost of some memory and performance. Is this OK? >> @@ -420,7 +440,7 @@ endif >> # Command for statically linking programs with the C library. >> ifndef +link-static >> +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \ >> - $(DEFAULT-LDFLAGS-$(@F)) \ >> + $(firstword $(DEFAULT-LDFLAGS-$(@F)) $(default-pie-ldflag)) \ > > Is the use of firstword here just a hack to put $(no-pie-ldflag) first so > you can override it with the subsequent $(default-pie-ldflag)? > > It is not a robust design to use firstword here because it implies that the > DEFAUTL-LDFLAGS-$(@F) has some structure that we are not documenting. > > I would like to see this done some other way. My preference would be for a new > value other than DEFAULT-LDFLAGS to control the PIE-ness of the built progarm. > I replaced DEFAUTL-LDFLAGS-$(@F) with $($(@F)-no-pie). Now I have # Command for statically linking programs with the C library. ifndef +link-static +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \ - $(DEFAULT-LDFLAGS-$(@F)) \ + $(if $($(@F)-no-pie),$(no-pie-ldflag),$(default-pie-ldflag)) \ $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \ >> >> diff --git a/NEWS b/NEWS >> index ab14d1eb1b..61598be94d 100644 >> --- a/NEWS >> +++ b/NEWS >> @@ -9,6 +9,11 @@ Version 2.27 >> >> Major new features: >> >> +* Add --enable-static-pie configure option to build static PIE. The >> + resulting libc.a can be used with the GCC option, -static-pie, which >> + is available with GCC 8 or above, to create static position independent >> + executable (static PIE). >> + > > The description of a new configure option is relevant only to INSTALL. > > We must explain when users would use this feature and why. NEWS entries are > user facing and must explain the function of the new feature. Does it improve > security for static binaries? Should users switch to using them instead of > normal static binaries? > > Lastly, we must explain which machines are supported in this initial release > of the feature. Only x86_64? You need not check all machines, other maintainers > can check and adjust the NEWS entry, but we have to commit to at least one > machine supporting this feature, which I assume is x86_64. > > For example: > > * The GNU C Library can now be compiled with support for building static > PIE executables (See --enable-static-pie in INSTALL). These static PIE > exectuables are like static executables but can be loaded at any address > and provide additional security hardening benefits at the cost of some > memory and performance. When the library is built with --enable-static-pie > the resulting libc.a is usable with GCC 8 and above to create static PIE > executables using the GCC option '-static-pie'. This feature is currently > supported on x86_64. > I took your example. Thanks. > >> diff --git a/configure.ac b/configure.ac >> index 8ebc490a55..ae219f8fe0 100644 >> --- a/configure.ac >> +++ b/configure.ac >> @@ -176,6 +176,11 @@ AC_ARG_ENABLE([profile], >> [build profiled library @<:@default=no@:>@]), >> [profile=$enableval], >> [profile=no]) >> +AC_ARG_ENABLE([static-pie], >> + AC_HELP_STRING([--enable-static-pie], >> + [build static executables as PIE @<:@default=no@:>@]), > > This does 2 things: > * It enables support for building static PIE executables. > * It builds all static binaries and tests in the testsuite as static PIE executables. > > It should say that e.g. > > "Enable static PIE executable support and use it in the testsuite." > > I understand the desire to use such a functionality to test static PIE executables > by converting the entire testsuite to use them, but we still need to test non-PIE > static executables? How are we still doing that after this change? > > How are we testing non-PIE static executables after this change? This is similar to PIE vs non-PIE. When you build glibc with GCC defaulting to PIE, most of dynamic tests are built as PIE, except for a couple of them linked with $(no-pie-ldflag). I added elf/tst-tls1-static-non-pie.c which is always built as non-PIE static executable, regardless if --enable-static-pie is used to configure glibc. To get better coverage for non-PIE, we need to build glibc with GCC defaulting to non-PIE and configure glibc without --enable-static-pie. >> diff --git a/manual/install.texi b/manual/install.texi >> index f1fa28c937..86193ade3f 100644 >> --- a/manual/install.texi >> +++ b/manual/install.texi >> @@ -120,6 +120,13 @@ Don't build shared libraries even if it is possible. Not all systems >> support shared libraries; you need ELF support and (currently) the GNU >> linker. >> >> +@item --enable-static-pie > > This should be rewritten to explain the feature that it enables first, > and then the ancilliary benefits like turning it on in the testsuite. > >> +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. >> + I changed it to '--enable-static-pie' Enable static position independent executable (static PIE) support. Static PIE is similar to static executable, but can be loaded at any address without help from a dynamic linker. All static programs as well as static tests are built as static PIE, except for those marked with no-pie. The resulting glibc can be used with the GCC option, -static-pie, which is available with GCC 8 or above, to create static PIE. Here is the updated patch. Using GCC 7 and binutils master branch, build-many-glibcs.py with --enable-static-pie with all patches for static PIE applied have the following build successes: PASS: glibcs-aarch64_be-linux-gnu build PASS: glibcs-aarch64-linux-gnu build PASS: glibcs-armeb-linux-gnueabi-be8 build PASS: glibcs-armeb-linux-gnueabi build PASS: glibcs-armeb-linux-gnueabihf-be8 build PASS: glibcs-armeb-linux-gnueabihf build PASS: glibcs-arm-linux-gnueabi build PASS: glibcs-arm-linux-gnueabihf build PASS: glibcs-arm-linux-gnueabihf-v7a build PASS: glibcs-arm-linux-gnueabihf-v7a-disable-multi-arch build PASS: glibcs-m68k-linux-gnu build PASS: glibcs-microblazeel-linux-gnu build PASS: glibcs-microblaze-linux-gnu build PASS: glibcs-mips64el-linux-gnu-n32 build PASS: glibcs-mips64el-linux-gnu-n32-nan2008 build PASS: glibcs-mips64el-linux-gnu-n32-nan2008-soft build PASS: glibcs-mips64el-linux-gnu-n32-soft build PASS: glibcs-mips64el-linux-gnu-n64 build PASS: glibcs-mips64el-linux-gnu-n64-nan2008 build PASS: glibcs-mips64el-linux-gnu-n64-nan2008-soft build PASS: glibcs-mips64el-linux-gnu-n64-soft build PASS: glibcs-mips64-linux-gnu-n32 build PASS: glibcs-mips64-linux-gnu-n32-nan2008 build PASS: glibcs-mips64-linux-gnu-n32-nan2008-soft build PASS: glibcs-mips64-linux-gnu-n32-soft build PASS: glibcs-mips64-linux-gnu-n64 build PASS: glibcs-mips64-linux-gnu-n64-nan2008 build PASS: glibcs-mips64-linux-gnu-n64-nan2008-soft build PASS: glibcs-mips64-linux-gnu-n64-soft build PASS: glibcs-mipsel-linux-gnu build PASS: glibcs-mipsel-linux-gnu-nan2008 build PASS: glibcs-mipsel-linux-gnu-nan2008-soft build PASS: glibcs-mipsel-linux-gnu-soft build PASS: glibcs-mips-linux-gnu build PASS: glibcs-mips-linux-gnu-nan2008 build PASS: glibcs-mips-linux-gnu-nan2008-soft build PASS: glibcs-mips-linux-gnu-soft build PASS: glibcs-nios2-linux-gnu build PASS: glibcs-powerpc64le-linux-gnu build PASS: glibcs-powerpc64-linux-gnu build PASS: glibcs-tilegxbe-linux-gnu-32 build PASS: glibcs-tilegxbe-linux-gnu build PASS: glibcs-tilegx-linux-gnu-32 build PASS: glibcs-tilegx-linux-gnu build PASS: glibcs-tilepro-linux-gnu build I don't know how many of them actually work, except for aarch64. Thanks. -- H.J. [-- Attachment #2: 0001-Add-enable-static-pie-configure-option-to-build-stat.patch --] [-- Type: text/x-patch, Size: 45534 bytes --] From 86d8013ccc24e4c07fdc6da04dac0448c4f5fc29 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <hjl.tools@gmail.com> Date: Mon, 17 Jul 2017 08:17:32 -0700 Subject: [PATCH] Add --enable-static-pie configure option to build static PIE [BZ #19574] 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. Only GCC with PIE support is needed. 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 not allowed in static PIE. Static PIE extends address space layout randomization to static executables. It provides additional security hardening benefits at the cost of some memory and performance. The following changes are made for static PIE: 1. Add a new function, _dl_relocate_static_pie, to: a. Get the run-time load address. b. Read the dynamic section. c. Perform dynamic relocations. Dynamic linker also performs these steps. But static PIE doesn't load any shared objects. 2. Call _dl_relocate_static_pie at entrance of LIBC_START_MAIN in libc.a. crt1.o, which is used to create dynamic and non-PIE static executables, is updated to include a dummy _dl_relocate_static_pie. rcrt1.o is added to create static PIE, which will link in the real _dl_relocate_static_pie. grcrt1.o is also added to create static PIE with -pg. GCC 8 has been updated to support rcrt1.o and grcrt1.o for static PIE. 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. All functions in static PIE are local functions. If PIE start.S can't reach main () defined in a shared object, the code sequence: pass addess of local_main to __libc_start_main ... local_main: tail call to main via PLT can be used. 2. start.S is updated to check PIC instead SHARED for PIC code path and avoid dynamic relocation, when PIC is defined and SHARED isn't defined, to support static PIE. Patches are submitted for aarch64, hppa, m68k, microblaze and sparc. 3. All assembly codes are updated check PIC instead SHARED for PIC code path to avoid dynamic relocations in read-only sections. 4. All assembly codes are updated check SHARED instead PIC for static symbol name. A patch is submitted for tile. 5. elf_machine_load_address in dl-machine.h are updated to support static PIE. Patches are submitted for aarch64, s390 and sh. 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. 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. 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 The i386 linker needs to be able to convert "movl main@GOT(%ebx), %eax" to "leal main@GOTOFF(%ebx), %eax" if main is defined locally. Binutils 2.29 or above are OK for i686 and x86-64. But linker status for other targets need to be verified. 3. Linker should resolve undefined weak symbols to 0 in static PIE: https://sourceware.org/bugzilla/show_bug.cgi?id=22269 4. Many ELF backend linkers incorrectly check bfd_link_pic for TLS relocations, which should check bfd_link_executable instead: https://sourceware.org/bugzilla/show_bug.cgi?id=22263 Tested on aarch64, i686 and x86-64. Using GCC 7 and binutils master branch, build-many-glibcs.py with --enable-static-pie with all patches for static PIE applied have the following build successes: PASS: glibcs-aarch64_be-linux-gnu build PASS: glibcs-aarch64-linux-gnu build PASS: glibcs-armeb-linux-gnueabi-be8 build PASS: glibcs-armeb-linux-gnueabi build PASS: glibcs-armeb-linux-gnueabihf-be8 build PASS: glibcs-armeb-linux-gnueabihf build PASS: glibcs-arm-linux-gnueabi build PASS: glibcs-arm-linux-gnueabihf build PASS: glibcs-arm-linux-gnueabihf-v7a build PASS: glibcs-arm-linux-gnueabihf-v7a-disable-multi-arch build PASS: glibcs-m68k-linux-gnu build PASS: glibcs-microblazeel-linux-gnu build PASS: glibcs-microblaze-linux-gnu build PASS: glibcs-mips64el-linux-gnu-n32 build PASS: glibcs-mips64el-linux-gnu-n32-nan2008 build PASS: glibcs-mips64el-linux-gnu-n32-nan2008-soft build PASS: glibcs-mips64el-linux-gnu-n32-soft build PASS: glibcs-mips64el-linux-gnu-n64 build PASS: glibcs-mips64el-linux-gnu-n64-nan2008 build PASS: glibcs-mips64el-linux-gnu-n64-nan2008-soft build PASS: glibcs-mips64el-linux-gnu-n64-soft build PASS: glibcs-mips64-linux-gnu-n32 build PASS: glibcs-mips64-linux-gnu-n32-nan2008 build PASS: glibcs-mips64-linux-gnu-n32-nan2008-soft build PASS: glibcs-mips64-linux-gnu-n32-soft build PASS: glibcs-mips64-linux-gnu-n64 build PASS: glibcs-mips64-linux-gnu-n64-nan2008 build PASS: glibcs-mips64-linux-gnu-n64-nan2008-soft build PASS: glibcs-mips64-linux-gnu-n64-soft build PASS: glibcs-mipsel-linux-gnu build PASS: glibcs-mipsel-linux-gnu-nan2008 build PASS: glibcs-mipsel-linux-gnu-nan2008-soft build PASS: glibcs-mipsel-linux-gnu-soft build PASS: glibcs-mips-linux-gnu build PASS: glibcs-mips-linux-gnu-nan2008 build PASS: glibcs-mips-linux-gnu-nan2008-soft build PASS: glibcs-mips-linux-gnu-soft build PASS: glibcs-nios2-linux-gnu build PASS: glibcs-powerpc64le-linux-gnu build PASS: glibcs-powerpc64-linux-gnu build PASS: glibcs-tilegxbe-linux-gnu-32 build PASS: glibcs-tilegxbe-linux-gnu build PASS: glibcs-tilegx-linux-gnu-32 build PASS: glibcs-tilegx-linux-gnu build PASS: glibcs-tilepro-linux-gnu build and the following build failures: FAIL: glibcs-alpha-linux-gnu build elf/sln is failed to link due to: assertion fail bfd/elf64-alpha.c:4125 This is caused by linker bug and/or non-PIC code in PIE libc.a. FAIL: glibcs-hppa-linux-gnu build elf/sln is failed to link due to: collect2: fatal error: ld terminated with signal 11 [Segmentation fault] https://sourceware.org/bugzilla/show_bug.cgi?id=22537 FAIL: glibcs-ia64-linux-gnu build elf/sln is failed to link due to: collect2: fatal error: ld terminated with signal 11 [Segmentation fault] FAIL: glibcs-powerpc-linux-gnu build FAIL: glibcs-powerpc-linux-gnu-soft build FAIL: glibcs-powerpc-linux-gnuspe build FAIL: glibcs-powerpc-linux-gnuspe-e500v1 build elf/sln is failed to link due to: ld: read-only segment has dynamic relocations. This is caused by linker bug and/or non-PIC code in PIE libc.a. See: https://sourceware.org/bugzilla/show_bug.cgi?id=22264 FAIL: glibcs-powerpc-linux-gnu-power4 build elf/sln is failed to link due to: findlocale.c:96:(.text+0x22c): @local call to ifunc memchr This is caused by linker bug and/or non-PIC code in PIE libc.a. FAIL: glibcs-s390-linux-gnu build elf/sln is failed to link due to: collect2: fatal error: ld terminated with signal 11 [Segmentation fault], core dumped assertion fail bfd/elflink.c:14299 This is caused by linker bug and/or non-PIC code in PIE libc.a. FAIL: glibcs-sh3eb-linux-gnu build FAIL: glibcs-sh3-linux-gnu build FAIL: glibcs-sh4eb-linux-gnu build FAIL: glibcs-sh4eb-linux-gnu-soft build FAIL: glibcs-sh4-linux-gnu build FAIL: glibcs-sh4-linux-gnu-soft build elf/sln is failed to link due to: ld: read-only segment has dynamic relocations. This is caused by linker bug and/or non-PIC code in PIE libc.a. See: https://sourceware.org/bugzilla/show_bug.cgi?id=22263 Also TLS code sequence in SH assembly syscalls in glibc doesn't match TLS code sequence expected by ld: https://sourceware.org/bugzilla/show_bug.cgi?id=22270 FAIL: glibcs-sparc64-linux-gnu build FAIL: glibcs-sparcv9-linux-gnu build FAIL: glibcs-tilegxbe-linux-gnu build FAIL: glibcs-tilegxbe-linux-gnu-32 build FAIL: glibcs-tilegx-linux-gnu build FAIL: glibcs-tilegx-linux-gnu-32 build FAIL: glibcs-tilepro-linux-gnu build elf/sln is failed to link due to: ld: read-only segment has dynamic relocations. This is caused by linker bug and/or non-PIC code in PIE libc.a. See: https://sourceware.org/bugzilla/show_bug.cgi?id=22263 [BZ #19574] * INSTALL: Regenerated. * Makeconfig (real-static-start-installed-name): New. (pic-default): Updated for --enable-static-pie. (pie-default): New for --enable-static-pie. (default-pie-ldflag): Likewise. (+link-static-before-libc): Replace $(DEFAULT-LDFLAGS-$(@F)) with $(if $($(@F)-no-pie),$(no-pie-ldflag),$(default-pie-ldflag)). Replace $(static-start-installed-name) with $(real-static-start-installed-name). (+prectorT): Updated for --enable-static-pie. (+postctorT): Likewise. (CFLAGS-.o): Add $(pie-default). (CFLAGS-.op): Likewise. * NEWS: Mention --enable-static-pie. * config.h.in (ENABLE_STATIC_PIE): New. * configure.ac (--enable-static-pie): New configure option. (have-no-dynamic-linker): New LIBC_CONFIG_VAR. (have-static-pie): Likewise. Enable static PIE if linker supports --no-dynamic-linker. (ENABLE_STATIC_PIE): New AC_DEFINE. (enable-static-pie): New LIBC_CONFIG_VAR. * configure: Regenerated. * csu/Makefile (omit-deps): Add r$(start-installed-name) and gr$(start-installed-name) for --enable-static-pie. (extra-objs): Likewise. (install-lib): Likewise. (extra-objs): Add static-reloc.o and static-reloc.os ($(objpfx)$(start-installed-name)): Also depend on $(objpfx)static-reloc.o. ($(objpfx)r$(start-installed-name)): New. ($(objpfx)g$(start-installed-name)): Also depend on $(objpfx)static-reloc.os. ($(objpfx)gr$(start-installed-name)): New. * csu/libc-start.c (LIBC_START_MAIN): Call _dl_relocate_static_pie in libc.a. * csu/libc-tls.c (__libc_setup_tls): Add main_map->l_addr to initimage. * csu/static-reloc.c: New file. * elf/Makefile (routines): Add dl-reloc-static-pie. (elide-routines.os): Likewise. (DEFAULT-LDFLAGS-tst-tls1-static-non-pie): Removed. (tst-tls1-static-non-pie-no-pie): New. * elf/dl-reloc-static-pie.c: New file. * elf/dl-support.c (_dl_get_dl_main_map): New function. * elf/dynamic-link.h (ELF_DURING_STARTUP): Also check STATIC_PIE_BOOTSTRAP. * elf/get-dynamic-info.h (elf_get_dynamic_info): Likewise. * gmon/Makefile (tests): Add tst-gmon-static-pie. (tests-static): Likewise. (DEFAULT-LDFLAGS-tst-gmon-static): Removed. (tst-gmon-static-no-pie): New. (CFLAGS-tst-gmon-static-pie.c): Likewise. (CRT-tst-gmon-static-pie): Likewise. (tst-gmon-static-pie-ENV): Likewise. (tests-special): Likewise. ($(objpfx)tst-gmon-static-pie.out): Likewise. (clean-tst-gmon-static-pie-data): Likewise. ($(objpfx)tst-gmon-static-pie-gprof.out): Likewise. * gmon/tst-gmon-static-pie.c: New file. * manual/install.texi: Document --enable-static-pie. * sysdeps/generic/ldsodefs.h (_dl_relocate_static_pie): New. (_dl_get_dl_main_map): Likewise. * sysdeps/i386/configure.ac: Check if linker supports static PIE. * sysdeps/x86_64/configure.ac: Likewise. * sysdeps/i386/configure: Regenerated. * sysdeps/x86_64/configure: Likewise. * sysdeps/mips/Makefile (ASFLAGS-.o): Add $(pie-default). (ASFLAGS-.op): Likewise. --- INSTALL | 9 ++++++ Makeconfig | 38 +++++++++++++++++++--- NEWS | 9 ++++++ config.h.in | 3 ++ configure | 79 +++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 29 +++++++++++++++++ csu/Makefile | 24 ++++++++++++-- csu/libc-start.c | 2 ++ csu/libc-tls.c | 6 ++-- csu/static-reloc.c | 26 +++++++++++++++ elf/Makefile | 7 ++-- elf/dl-reloc-static-pie.c | 52 +++++++++++++++++++++++++++++ elf/dl-support.c | 11 +++++++ elf/dynamic-link.h | 2 +- elf/get-dynamic-info.h | 6 ++-- gmon/Makefile | 25 +++++++++++++- gmon/tst-gmon-static-pie.c | 1 + manual/install.texi | 9 ++++++ sysdeps/generic/ldsodefs.h | 11 +++++++ sysdeps/i386/configure | 33 +++++++++++++++++++ sysdeps/i386/configure.ac | 23 +++++++++++++ sysdeps/mips/Makefile | 3 ++ sysdeps/x86_64/configure | 33 +++++++++++++++++++ sysdeps/x86_64/configure.ac | 25 ++++++++++++++ 24 files changed, 449 insertions(+), 17 deletions(-) create mode 100644 csu/static-reloc.c create mode 100644 elf/dl-reloc-static-pie.c create mode 100644 gmon/tst-gmon-static-pie.c diff --git a/INSTALL b/INSTALL index d1a34c2a90..30804eca38 100644 --- a/INSTALL +++ b/INSTALL @@ -90,6 +90,15 @@ will be used, and CFLAGS sets optimization options for the compiler. systems support shared libraries; you need ELF support and (currently) the GNU linker. +'--enable-static-pie' + Enable static position independent executable (static PIE) support. + Static PIE is similar to static executable, but can be loaded at + any address without help from a dynamic linker. All static + programs as well as static tests are built as static PIE, except + for those marked with no-pie. The resulting glibc can be used with + the GCC option, -static-pie, which is available with GCC 8 or + above, to create static PIE. + '--disable-profile' Don't build libraries with profiling information. You may want to use this option if you don't plan to do profiling. diff --git a/Makeconfig b/Makeconfig index 1346109ac0..99cc136bfa 100644 --- a/Makeconfig +++ b/Makeconfig @@ -352,6 +352,14 @@ ifndef static-start-installed-name static-start-installed-name = $(start-installed-name) endif +ifeq (yes,$(enable-static-pie)) +# Link with rcrt1.o, instead of crt1.o, to call _dl_relocate_static_pie +# to relocate static PIE. +real-static-start-installed-name = r$(static-start-installed-name) +else +real-static-start-installed-name = $(static-start-installed-name) +endif + ifeq (yesyes,$(build-shared)$(have-z-combreloc)) combreloc-LDFLAGS = -Wl,-z,combreloc LDFLAGS.so += $(combreloc-LDFLAGS) @@ -371,6 +379,20 @@ LDFLAGS.so += $(hashstyle-LDFLAGS) LDFLAGS-rtld += $(hashstyle-LDFLAGS) endif +ifeq (yes,$(enable-static-pie)) +pic-default = -DPIC +# Compile libc.a and libc_p.a with -fPIE/-fpie for static PIE. +pie-default = $(pie-ccflag) +ifeq (yes,$(have-static-pie)) +default-pie-ldflag = -static-pie +else +# Static PIE can't have dynamic relocations in read-only segments since +# static PIE is mapped into memory by kernel. --eh-frame-hdr is needed +# for PIE to support exception. +default-pie-ldflag = -Wl,-pie,--no-dynamic-linker,--eh-frame-hdr,-z,text +endif +endif + # If lazy relocations are disabled, add the -z now flag. Use # LDFLAGS-lib.so instead of LDFLAGS.so, to avoid adding the flag to # test modules. @@ -420,9 +442,9 @@ endif # Command for statically linking programs with the C library. ifndef +link-static +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \ - $(DEFAULT-LDFLAGS-$(@F)) \ + $(if $($(@F)-no-pie),$(no-pie-ldflag),$(default-pie-ldflag)) \ $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \ - $(firstword $(CRT-$(@F)) $(csu-objpfx)$(static-start-installed-name)) \ + $(firstword $(CRT-$(@F)) $(csu-objpfx)$(real-static-start-installed-name)) \ $(+preinit) $(+prectorT) \ $(filter-out $(addprefix $(csu-objpfx),start.o \ $(start-installed-name))\ @@ -637,8 +659,14 @@ endif +prectorS = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtbeginS.o` +postctorS = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtendS.o` # Variants of the two previous definitions for statically linking programs. +ifeq (yes,$(enable-static-pie)) +# Static PIE must use PIE variants. ++prectorT = $(+prectorS) ++postctorT = $(+postctorS) +else +prectorT = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtbeginT.o` +postctorT = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtend.o` +endif csu-objpfx = $(common-objpfx)csu/ elf-objpfx = $(common-objpfx)elf/ @@ -959,7 +987,8 @@ libtypes = $(foreach o,$(object-suffixes-for-libc),$(libtype$o)) all-object-suffixes := .o .os .oS object-suffixes := CPPFLAGS-.o = $(pic-default) -CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) +# libc.a must be compiled with -fPIE/-fpie for static PIE. +CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) $(pie-default) libtype.o := lib%.a object-suffixes += .o ifeq (yes,$(build-shared)) @@ -984,7 +1013,8 @@ ifeq (yes,$(build-profile)) all-object-suffixes += .op object-suffixes += .op CPPFLAGS-.op = -DPROF $(pic-default) -CFLAGS-.op = -pg +# libc_p.a must be compiled with -fPIE/-fpie for static PIE. +CFLAGS-.op = -pg $(pie-default) libtype.op = lib%_p.a endif diff --git a/NEWS b/NEWS index 48af4acaea..5b09359f2c 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,15 @@ Version 2.27 Major new features: +* The GNU C Library can now be compiled with support for building static + PIE executables (See --enable-static-pie in INSTALL). These static PIE + exectuables are like static executables but can be loaded at any address + and provide additional security hardening benefits at the cost of some + memory and performance. When the library is built with --enable-static-pie + the resulting libc.a is usable with GCC 8 and above to create static PIE + executables using the GCC option '-static-pie'. This feature is currently + supported on i386, x86_64 and x32. + * Optimized x86-64 asin, atan2, exp, expf, log, pow, atan, sin and tan with FMA, contributed by Arjan van de Ven and H.J. Lu from Intel. diff --git a/config.h.in b/config.h.in index 8d76dadca2..0ecb10939f 100644 --- a/config.h.in +++ b/config.h.in @@ -241,6 +241,9 @@ /* Build glibc with tunables support. */ #define HAVE_TUNABLES 0 +/* Define if static PIE is enabled. */ +#define ENABLE_STATIC_PIE 0 + /* Some compiler options may now allow to use ebp in __asm__ (used mainly in i386 6 argument syscall issue). */ #define CAN_USE_REGISTER_ASM_EBP 0 diff --git a/configure b/configure index caba102846..d4dfb90a38 100755 --- a/configure +++ b/configure @@ -765,6 +765,7 @@ with_default_link enable_sanity_checks enable_shared enable_profile +enable_static_pie enable_timezone_tools enable_hardcoded_path_in_tests enable_stackguard_randomization @@ -1420,6 +1421,8 @@ Optional Features: in special situations) [default=yes] --enable-shared build shared library [default=yes if GNU ld] --enable-profile build profiled library [default=no] + --enable-static-pie enable static PIE support and use it in the + testsuite [default=no] --disable-timezone-tools do not install timezone tools [default=install] --enable-hardcoded-path-in-tests @@ -3365,6 +3368,13 @@ else profile=no fi +# Check whether --enable-static-pie was given. +if test "${enable_static_pie+set}" = set; then : + enableval=$enable_static_pie; static_pie=$enableval +else + static_pie=no +fi + # Check whether --enable-timezone-tools was given. if test "${enable_timezone_tools+set}" = set; then : enableval=$enable_timezone_tools; enable_timezone_tools=$enableval @@ -5805,6 +5815,62 @@ fi $as_echo "$libc_linker_feature" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker that supports --no-dynamic-linker" >&5 +$as_echo_n "checking for linker that supports --no-dynamic-linker... " >&6; } +libc_linker_feature=no +if test x"$gnu_ld" = x"yes"; then + libc_linker_check=`$LD -v --help 2>/dev/null | grep "\--no-dynamic-linker"` + if test -n "$libc_linker_check"; then + cat > conftest.c <<EOF +int _start (void) { return 42; } +EOF + if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp + -Wl,--no-dynamic-linker -nostdlib -nostartfiles + -fPIC -shared -o conftest.so conftest.c + 1>&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } + then + libc_linker_feature=yes + fi + rm -f conftest* + fi +fi +if test $libc_linker_feature = yes; then + libc_cv_no_dynamic_linker=yes +else + libc_cv_no_dynamic_linker=no +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5 +$as_echo "$libc_linker_feature" >&6; } +config_vars="$config_vars +have-no-dynamic-linker = $libc_cv_no_dynamic_linker" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -static-pie" >&5 +$as_echo_n "checking for -static-pie... " >&6; } +if ${libc_cv_static_pie+:} false; then : + $as_echo_n "(cached) " >&6 +else + if { ac_try='${CC-cc} -static-pie -xc /dev/null -S -o /dev/null' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + libc_cv_static_pie=yes +else + libc_cv_static_pie=no +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_static_pie" >&5 +$as_echo "$libc_cv_static_pie" >&6; } +config_vars="$config_vars +have-static-pie = $libc_cv_static_pie" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -fpie" >&5 $as_echo_n "checking for -fpie... " >&6; } if ${libc_cv_fpie+:} false; then : @@ -6704,6 +6770,19 @@ $as_echo "$libc_cv_pie_default" >&6; } libc_cv_multidir=`${CC-cc} $CFLAGS $CPPFLAGS -print-multi-directory` +if test "$static_pie" = yes; then + # The linker must support --no-dynamic-linker. + if test "$libc_cv_no_dynamic_linker" != yes; then + as_fn_error $? "linker support for --no-dynamic-linker needed" "$LINENO" 5 + fi + # Default to PIE. + libc_cv_pie_default=yes + $as_echo "#define ENABLE_STATIC_PIE 1" >>confdefs.h + +fi +config_vars="$config_vars +enable-static-pie = $static_pie" + diff --git a/configure.ac b/configure.ac index 9707ae4d8e..78564f3746 100644 --- a/configure.ac +++ b/configure.ac @@ -176,6 +176,11 @@ AC_ARG_ENABLE([profile], [build profiled library @<:@default=no@:>@]), [profile=$enableval], [profile=no]) +AC_ARG_ENABLE([static-pie], + AC_HELP_STRING([--enable-static-pie], + [enable static PIE support and use it in the testsuite @<:@default=no@:>@]), + [static_pie=$enableval], + [static_pie=no]) AC_ARG_ENABLE([timezone-tools], AC_HELP_STRING([--disable-timezone-tools], [do not install timezone tools @<:@default=install@:>@]), @@ -1280,6 +1285,19 @@ LIBC_LINKER_FEATURE([-z execstack], [-Wl,-z,execstack], [libc_cv_z_execstack=yes], [libc_cv_z_execstack=no]) AC_SUBST(libc_cv_z_execstack) +LIBC_LINKER_FEATURE([--no-dynamic-linker], + [-Wl,--no-dynamic-linker], + [libc_cv_no_dynamic_linker=yes], + [libc_cv_no_dynamic_linker=no]) +LIBC_CONFIG_VAR([have-no-dynamic-linker], [$libc_cv_no_dynamic_linker]) + +AC_CACHE_CHECK(for -static-pie, libc_cv_static_pie, [dnl +LIBC_TRY_CC_OPTION([-static-pie], + [libc_cv_static_pie=yes], + [libc_cv_static_pie=no]) +]) +LIBC_CONFIG_VAR([have-static-pie], [$libc_cv_static_pie]) + AC_CACHE_CHECK(for -fpie, libc_cv_fpie, [dnl LIBC_TRY_CC_OPTION([-fpie], [libc_cv_fpie=yes], [libc_cv_fpie=no]) ]) @@ -1787,6 +1805,17 @@ AC_SUBST(libc_cv_pie_default) libc_cv_multidir=`${CC-cc} $CFLAGS $CPPFLAGS -print-multi-directory` AC_SUBST(libc_cv_multidir) +if test "$static_pie" = yes; then + # The linker must support --no-dynamic-linker. + if test "$libc_cv_no_dynamic_linker" != yes; then + AC_MSG_ERROR([linker support for --no-dynamic-linker needed]) + fi + # Default to PIE. + libc_cv_pie_default=yes + AC_DEFINE(ENABLE_STATIC_PIE) +fi +LIBC_CONFIG_VAR([enable-static-pie], [$static_pie]) + AC_SUBST(profile) AC_SUBST(static_nss) diff --git a/csu/Makefile b/csu/Makefile index e42a32b3eb..86b95a9759 100644 --- a/csu/Makefile +++ b/csu/Makefile @@ -37,7 +37,9 @@ extra-objs = start.o \ S$(start-installed-name) omit-deps = $(patsubst %.o,%,$(start-installed-name) g$(start-installed-name) \ b$(start-installed-name) $(csu-dummies) \ - S$(start-installed-name)) + S$(start-installed-name) \ + r$(start-installed-name) \ + gr$(start-installed-name)) install-lib = $(start-installed-name) g$(start-installed-name) $(csu-dummies) # No tests are allowed in the csu/ subdirectory because the startup @@ -60,10 +62,17 @@ extra-objs += gmon-start.o endif ifneq ($(start-installed-name),$(static-start-installed-name)) +# FIXME: Only Hurd defines static-start-installed-name. Hurd needs to +# provide special rules to support static PIE. extra-objs += $(static-start-installed-name) g$(static-start-installed-name) omit-deps += $(patsubst %.o,%,$(static-start-installed-name) \ g$(static-start-installed-name)) install-lib += $(static-start-installed-name) g$(static-start-installed-name) +else +ifeq (yes,$(enable-static-pie)) +extra-objs += r$(start-installed-name) gr$(start-installed-name) +install-lib += r$(start-installed-name) gr$(start-installed-name) +endif endif before-compile += $(objpfx)abi-tag.h @@ -82,7 +91,10 @@ multilib-extra-objs = $(addprefix $(multidir)/, $(install-lib)) extra-objs += $(multilib-extra-objs) endif -extra-objs += abi-note.o init.o +extra-objs += abi-note.o init.o static-reloc.o +ifeq (yes,$(build-shared)) +extra-objs += static-reloc.os +endif asm-CPPFLAGS += -I$(objpfx). # Enable unwinding so backtrace unwinds to __libc_start_main @@ -101,6 +113,9 @@ ifndef start-installed-name-rule # We link the ELF startfile along with a SHT_NOTE section indicating # the kernel ABI the binaries linked with this library will require. $(objpfx)$(start-installed-name): $(objpfx)start.o $(objpfx)abi-note.o \ + $(objpfx)init.o $(objpfx)static-reloc.o + $(link-relocatable) +$(objpfx)r$(start-installed-name): $(objpfx)start.o $(objpfx)abi-note.o \ $(objpfx)init.o $(link-relocatable) $(objpfx)S$(start-installed-name): $(objpfx)start.os $(objpfx)abi-note.o \ @@ -113,7 +128,10 @@ endif # to turn on profiling code at startup. ifeq (yes,$(build-shared)) $(objpfx)g$(start-installed-name): \ - $(objpfx)g%: $(objpfx)S% $(objpfx)gmon-start.os + $(objpfx)g%: $(objpfx)S% $(objpfx)gmon-start.os $(objpfx)static-reloc.os + $(link-relocatable) +$(objpfx)gr$(start-installed-name): \ + $(objpfx)gr%: $(objpfx)r% $(objpfx)gmon-start.o $(link-relocatable) ifneq ($(start-installed-name),$(static-start-installed-name)) $(objpfx)g$(static-start-installed-name): \ diff --git a/csu/libc-start.c b/csu/libc-start.c index 24c63be02f..34dd125260 100644 --- a/csu/libc-start.c +++ b/csu/libc-start.c @@ -141,6 +141,8 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), __libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up; #ifndef SHARED + _dl_relocate_static_pie (); + char **ev = &argv[argc + 1]; __environ = ev; diff --git a/csu/libc-tls.c b/csu/libc-tls.c index 00138eb43a..1f8ddaf543 100644 --- a/csu/libc-tls.c +++ b/csu/libc-tls.c @@ -114,6 +114,8 @@ __libc_setup_tls (void) size_t tcb_offset; const ElfW(Phdr) *phdr; + struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded; + /* Look through the TLS segment if there is any. */ if (_dl_phdr != NULL) for (phdr = _dl_phdr; phdr < &_dl_phdr[_dl_phnum]; ++phdr) @@ -122,7 +124,7 @@ __libc_setup_tls (void) /* Remember the values we need. */ memsz = phdr->p_memsz; filesz = phdr->p_filesz; - initimage = (void *) phdr->p_vaddr; + initimage = (void *) phdr->p_vaddr + main_map->l_addr; align = phdr->p_align; if (phdr->p_align > max_align) max_align = phdr->p_align; @@ -163,8 +165,6 @@ __libc_setup_tls (void) _dl_static_dtv[0].counter = (sizeof (_dl_static_dtv) / sizeof (_dl_static_dtv[0])) - 2; // _dl_static_dtv[1].counter = 0; would be needed if not already done - struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded; - /* Initialize the TLS block. */ #if TLS_TCB_AT_TP _dl_static_dtv[2].pointer.val = ((char *) tlsblock + tcb_offset diff --git a/csu/static-reloc.c b/csu/static-reloc.c new file mode 100644 index 0000000000..37be72c8ea --- /dev/null +++ b/csu/static-reloc.c @@ -0,0 +1,26 @@ +/* Special startup support for non-PIE static executables. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#if ENABLE_STATIC_PIE +#include <ldsodefs.h> + +void +_dl_relocate_static_pie (void) +{ +} +#endif diff --git a/elf/Makefile b/elf/Makefile index d49fd4673d..4c6f9e0a49 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -24,7 +24,8 @@ include ../Makeconfig headers = elf.h bits/elfclass.h link.h bits/link.h routines = $(all-dl-routines) dl-support dl-iteratephdr \ dl-addr dl-addr-obj enbl-secure dl-profstub \ - dl-origin dl-libc dl-sym dl-sysdep dl-error + dl-origin dl-libc dl-sym dl-sysdep dl-error \ + dl-reloc-static-pie # The core dynamic linking functions are in libc for the static and # profiled libraries. @@ -52,7 +53,7 @@ endif all-dl-routines = $(dl-routines) $(sysdep-dl-routines) # But they are absent from the shared libc, because that code is in ld.so. elide-routines.os = $(all-dl-routines) dl-support enbl-secure dl-origin \ - dl-sysdep dl-exception + dl-sysdep dl-exception dl-reloc-static-pie shared-only-routines += dl-caller # ld.so uses those routines, plus some special stuff for being the program @@ -153,7 +154,7 @@ tests-static-internal := tst-tls1-static tst-tls2-static \ tst-tls1-static-non-pie CRT-tst-tls1-static-non-pie := $(csu-objpfx)crt1.o -DEFAULT-LDFLAGS-tst-tls1-static-non-pie = $(no-pie-ldflag) +tst-tls1-static-non-pie-no-pie = yes tests := tst-tls9 tst-leaks1 \ tst-array1 tst-array2 tst-array3 tst-array4 tst-array5 \ diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c new file mode 100644 index 0000000000..6e43aea76a --- /dev/null +++ b/elf/dl-reloc-static-pie.c @@ -0,0 +1,52 @@ +/* Support for relocating static PIE. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#if ENABLE_STATIC_PIE +#include <unistd.h> +#include <ldsodefs.h> +#include "dynamic-link.h" + +/* Relocate static executable with PIE. */ + +void +_dl_relocate_static_pie (void) +{ + struct link_map *main_map = _dl_get_dl_main_map (); + +# define STATIC_PIE_BOOTSTRAP +# define BOOTSTRAP_MAP (main_map) +# define RESOLVE_MAP(sym, version, flags) BOOTSTRAP_MAP +# include "dynamic-link.h" + + /* Figure out the run-time load address of static PIE. */ + main_map->l_addr = elf_machine_load_address (); + + /* Read our own dynamic section and fill in the info array. */ + main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ()); + elf_get_dynamic_info (main_map, NULL); + +# ifdef ELF_MACHINE_BEFORE_RTLD_RELOC + ELF_MACHINE_BEFORE_RTLD_RELOC (main_map->l_info); +# endif + + /* Relocate ourselves so we can do normal function calls and + data access using the global offset table. */ + ELF_DYNAMIC_RELOCATE (main_map, 0, 0, 0); + main_map->l_relocated = 1; +} +#endif 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 diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h index ebea7567cd..6278649711 100644 --- a/elf/dynamic-link.h +++ b/elf/dynamic-link.h @@ -94,7 +94,7 @@ elf_machine_lazy_rel (struct link_map *map, #ifdef RESOLVE_MAP -# ifdef RTLD_BOOTSTRAP +# if defined RTLD_BOOTSTRAP || defined STATIC_PIE_BOOTSTRAP # define ELF_DURING_STARTUP (1) # else # define ELF_DURING_STARTUP (0) diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h index 7525c3a5b2..eb26d23649 100644 --- a/elf/get-dynamic-info.h +++ b/elf/get-dynamic-info.h @@ -38,7 +38,7 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) typedef Elf64_Xword d_tag_utype; #endif -#ifndef RTLD_BOOTSTRAP +#if !defined RTLD_BOOTSTRAP && !defined STATIC_PIE_BOOTSTRAP if (dyn == NULL) return; #endif @@ -139,9 +139,11 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) /* Only the bind now flags are allowed. */ assert (info[VERSYMIDX (DT_FLAGS_1)] == NULL || (info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val & ~DF_1_NOW) == 0); + /* Flags must not be set for ld.so. */ assert (info[DT_FLAGS] == NULL || (info[DT_FLAGS]->d_un.d_val & ~DF_BIND_NOW) == 0); - /* Flags must not be set for ld.so. */ +#endif +#if defined RTLD_BOOTSTRAP || defined STATIC_PIE_BOOTSTRAP assert (info[DT_RUNPATH] == NULL); assert (info[DT_RPATH] == NULL); #else diff --git a/gmon/Makefile b/gmon/Makefile index 89ab3fc7da..29e746723e 100644 --- a/gmon/Makefile +++ b/gmon/Makefile @@ -39,6 +39,10 @@ tests-static += tst-gmon-static ifeq (yesyes,$(have-fpie)$(build-shared)) tests += tst-gmon-pie tests-pie += tst-gmon-pie +ifeq (yes,$(enable-static-pie)) +tests += tst-gmon-static-pie +tests-static += tst-gmon-static-pie +endif endif # The mcount code won't work without a frame pointer. @@ -54,7 +58,7 @@ endif CFLAGS-tst-gmon-static.c := $(PIE-ccflag) -fno-omit-frame-pointer -pg CRT-tst-gmon-static := $(csu-objpfx)gcrt1.o -DEFAULT-LDFLAGS-tst-gmon-static = $(no-pie-ldflag) +tst-gmon-static-no-pie = yes tst-gmon-static-ENV := GMON_OUT_PREFIX=$(objpfx)tst-gmon-static.data ifeq ($(run-built-tests),yes) tests-special += $(objpfx)tst-gmon-static-gprof.out @@ -67,6 +71,15 @@ ifeq ($(run-built-tests),yes) tests-special += $(objpfx)tst-gmon-pie-gprof.out endif +ifeq (yes,$(enable-static-pie)) +CFLAGS-tst-gmon-static-pie.c := $(PIE-ccflag) -fno-omit-frame-pointer -pg +CRT-tst-gmon-static-pie := $(csu-objpfx)grcrt1.o +tst-gmon-static-pie-ENV := GMON_OUT_PREFIX=$(objpfx)tst-gmon-static-pie.data +ifeq ($(run-built-tests),yes) +tests-special += $(objpfx)tst-gmon-static-pie-gprof.out +endif +endif + include ../Rules @@ -111,3 +124,13 @@ clean-tst-gmon-pie-data: $(objpfx)tst-gmon-pie-gprof.out: tst-gmon-gprof.sh $(objpfx)tst-gmon-pie.out $(SHELL) $< $(GPROF) $(objpfx)tst-gmon-pie $(objpfx)tst-gmon-pie.data.* > $@; \ $(evaluate-test) + +$(objpfx)tst-gmon-static-pie.out: clean-tst-gmon-static-pie-data +clean-tst-gmon-static-pie-data: + rm -f $(objpfx)tst-gmon-static-pie.data.* + +$(objpfx)tst-gmon-static-pie-gprof.out: tst-gmon-static-gprof.sh \ + $(objpfx)tst-gmon-static-pie.out + $(SHELL) $< $(GPROF) $(objpfx)tst-gmon-static-pie \ + $(objpfx)tst-gmon-static-pie.data.* > $@; \ + $(evaluate-test) diff --git a/gmon/tst-gmon-static-pie.c b/gmon/tst-gmon-static-pie.c new file mode 100644 index 0000000000..1eef2583b6 --- /dev/null +++ b/gmon/tst-gmon-static-pie.c @@ -0,0 +1 @@ +#include "tst-gmon.c" diff --git a/manual/install.texi b/manual/install.texi index ea559e4e72..0efa8572df 100644 --- a/manual/install.texi +++ b/manual/install.texi @@ -120,6 +120,15 @@ Don't build shared libraries even if it is possible. Not all systems support shared libraries; you need ELF support and (currently) the GNU linker. +@item --enable-static-pie +Enable static position independent executable (static PIE) support. +Static PIE is similar to static executable, but can be loaded at any +address without help from a dynamic linker. All static programs as +well as static tests are built as static PIE, except for those marked +with no-pie. The resulting glibc can be used with the GCC option, +-static-pie, which is available with GCC 8 or above, to create static +PIE. + @item --disable-profile Don't build libraries with profiling information. You may want to use this option if you don't plan to do profiling. diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index 7a65dc641c..196513851f 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -1051,6 +1051,17 @@ extern void _dl_determine_tlsoffset (void) attribute_hidden; stack protector, among other things). */ void __libc_setup_tls (void); +# if ENABLE_STATIC_PIE +/* Relocate static executable with PIE. */ +extern void _dl_relocate_static_pie (void) attribute_hidden; + +/* Get a pointer to _dl_main_map. */ +extern struct link_map * _dl_get_dl_main_map (void) + __attribute__ ((visibility ("hidden"))); +# else +# define _dl_relocate_static_pie() +# endif + /* Initialization of libpthread for statically linked applications. If libpthread is not linked in, this is an empty function. */ void __pthread_initialize_minimal (void) weak_function; diff --git a/sysdeps/i386/configure b/sysdeps/i386/configure index 4cf968d8bc..90c63caf35 100644 --- a/sysdeps/i386/configure +++ b/sysdeps/i386/configure @@ -50,6 +50,39 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_compiler_builtin_inlined" >&5 $as_echo "$libc_compiler_builtin_inlined" >&6; } +if test "$static_pie" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker static PIE support" >&5 +$as_echo_n "checking for linker static PIE support... " >&6; } +if ${libc_cv_ld_static_pie+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat > conftest.s <<\EOF + .text + .global _start +_start: + movl _start@GOT(%ebx), %eax +EOF + libc_cv_pie_option="-Wl,-pie" + libc_cv_ld_static_pie=no + if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + if $READELF -r conftest | grep 'There are no relocations in this file.' > /dev/null; then + libc_cv_ld_static_pie=yes + fi + fi +rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_ld_static_pie" >&5 +$as_echo "$libc_cv_ld_static_pie" >&6; } + if test "$libc_cv_ld_static_pie" != yes; then + as_fn_error $? "linker support for static PIE needed" "$LINENO" 5 + fi +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Intel MPX support" >&5 $as_echo_n "checking for Intel MPX support... " >&6; } if ${libc_cv_asm_mpx+:} false; then : diff --git a/sysdeps/i386/configure.ac b/sysdeps/i386/configure.ac index b598b120bc..6d2068d2b3 100644 --- a/sysdeps/i386/configure.ac +++ b/sysdeps/i386/configure.ac @@ -30,6 +30,29 @@ LIBC_COMPILER_BUILTIN_INLINED( *** Please use host i786, i686, i586, or i486. *** For example: /source/glibc/configure CFLAGS='-O2 -march=i686' ...])]) +dnl Check if linker can convert "movl main@GOT(%ebx), %eax" to +dnl "leal main@GOTOFF(%ebx), %eax" for static PIE. +if test "$static_pie" = yes; then + AC_CACHE_CHECK(for linker static PIE support, libc_cv_ld_static_pie, [dnl +cat > conftest.s <<\EOF + .text + .global _start +_start: + movl _start@GOT(%ebx), %eax +EOF + libc_cv_pie_option="-Wl,-pie" + libc_cv_ld_static_pie=no + if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&AS_MESSAGE_LOG_FD); then + if $READELF -r conftest | grep 'There are no relocations in this file.' > /dev/null; then + libc_cv_ld_static_pie=yes + fi + fi +rm -f conftest*]) + if test "$libc_cv_ld_static_pie" != yes; then + AC_MSG_ERROR([linker support for static PIE needed]) + fi +fi + dnl Check whether asm supports Intel MPX AC_CACHE_CHECK(for Intel MPX support, libc_cv_asm_mpx, [dnl cat > conftest.s <<\EOF diff --git a/sysdeps/mips/Makefile b/sysdeps/mips/Makefile index fd891ddf09..7ac6fa5031 100644 --- a/sysdeps/mips/Makefile +++ b/sysdeps/mips/Makefile @@ -23,6 +23,9 @@ CPPFLAGS-crtn.S += $(pic-ccflag) endif ASFLAGS-.os += $(pic-ccflag) +# libc.a and libc_p.a must be compiled with -fPIE/-fpie for static PIE. +ASFLAGS-.o += $(pie-default) +ASFLAGS-.op += $(pie-default) ifeq ($(subdir),elf) ifneq ($(o32-fpabi),) diff --git a/sysdeps/x86_64/configure b/sysdeps/x86_64/configure index efef46b1b7..8674d14569 100644 --- a/sysdeps/x86_64/configure +++ b/sysdeps/x86_64/configure @@ -85,6 +85,39 @@ if test x"$build_mathvec" = xnotset; then build_mathvec=yes fi +if test "$static_pie" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker static PIE support" >&5 +$as_echo_n "checking for linker static PIE support... " >&6; } +if ${libc_cv_ld_static_pie+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat > conftest.s <<\EOF + .text + .global _start + .weak foo +_start: + leaq foo(%rip), %rax +EOF + libc_cv_pie_option="-Wl,-pie" + if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + libc_cv_ld_static_pie=yes + else + libc_cv_ld_static_pie=no + fi +rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_ld_static_pie" >&5 +$as_echo "$libc_cv_ld_static_pie" >&6; } + if test "$libc_cv_ld_static_pie" != yes; then + as_fn_error $? "linker support for static PIE needed" "$LINENO" 5 + fi +fi + $as_echo "#define PI_STATIC_AND_HIDDEN 1" >>confdefs.h diff --git a/sysdeps/x86_64/configure.ac b/sysdeps/x86_64/configure.ac index fa86e953ee..b7d2c0124f 100644 --- a/sysdeps/x86_64/configure.ac +++ b/sysdeps/x86_64/configure.ac @@ -44,6 +44,31 @@ if test x"$build_mathvec" = xnotset; then build_mathvec=yes fi +dnl Check if linker supports static PIE with the fix for +dnl +dnl https://sourceware.org/bugzilla/show_bug.cgi?id=21782 +dnl +if test "$static_pie" = yes; then + AC_CACHE_CHECK(for linker static PIE support, libc_cv_ld_static_pie, [dnl +cat > conftest.s <<\EOF + .text + .global _start + .weak foo +_start: + leaq foo(%rip), %rax +EOF + libc_cv_pie_option="-Wl,-pie" + if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&AS_MESSAGE_LOG_FD); then + libc_cv_ld_static_pie=yes + else + libc_cv_ld_static_pie=no + fi +rm -f conftest*]) + if test "$libc_cv_ld_static_pie" != yes; then + AC_MSG_ERROR([linker support for static PIE needed]) + fi +fi + dnl It is always possible to access static and hidden symbols in an dnl position independent way. AC_DEFINE(PI_STATIC_AND_HIDDEN) -- 2.14.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-12-01 18:24 ` H.J. Lu @ 2017-12-08 13:14 ` H.J. Lu 2017-12-15 21:19 ` Carlos O'Donell 1 sibling, 0 replies; 37+ messages in thread From: H.J. Lu @ 2017-12-08 13:14 UTC (permalink / raw) To: Carlos O'Donell; +Cc: Szabolcs Nagy, nd, Joseph Myers, GNU C Library On Fri, Dec 1, 2017 at 10:24 AM, H.J. Lu <hjl.tools@gmail.com> wrote: > On Thu, Nov 30, 2017 at 1:44 PM, Carlos O'Donell <carlos@redhat.com> wrote: >> H.J., >> >> High Level: >> >> At a high level I have no objection with the idea of static PIE executables, >> it makes sense to support such things. > > Thanks for your feedbacks. > >> My only nit is that we need to do a better job of explaining to users why >> they would use them and under what circumstances. To that end you have a bit >> more work to do in the commit message, install.texit, and NEWS entry. >> >> Design: >> >> I have one design question below which around testing static non-PIE executables >> in a --enable-static-pie build. See below. >> >> Implementation: >> >> Everything looks good except the use of firstword in +link-static-before-libc, >> which I describe below. I think this is a hack and should be changed to better >> represent the expected semantics and structure you are looking to support. > > Fixed. > >> Thank you for your work in this area. >> >> Look forward to a v2. >> >>> From 7026a79c1f71f5decd135208503fd4186193ffb8 Mon Sep 17 00:00:00 2001 >>> From: "H.J. Lu" <hjl.tools@gmail.com> >>> Date: Mon, 17 Jul 2017 08:17:32 -0700 >>> Subject: [PATCH] Add --enable-static-pie configure option to build static PIE >>> [BZ #19574] >>> >>> 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. >> >> You write "which are allowed", shouldn't that be "which are not allowed"? > > Fixed. > >> The commit message must explain the following: >> >> * Why would a user use this feature? >> - What does it provide over and beyond existing static executables >> >> * How does a user decide to use this feature? >> - Should everyone use it? >> - Should you use it if you care about security, and what does it cost? >> >> Please include the answers to these questions in a the next versions >> commit message. > > I added : > > Static PIE extends address space layout randomization to static > executables. It provides additional security hardening benefits at > the cost of some memory and performance. > > Is this OK? > >>> @@ -420,7 +440,7 @@ endif >>> # Command for statically linking programs with the C library. >>> ifndef +link-static >>> +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \ >>> - $(DEFAULT-LDFLAGS-$(@F)) \ >>> + $(firstword $(DEFAULT-LDFLAGS-$(@F)) $(default-pie-ldflag)) \ >> >> Is the use of firstword here just a hack to put $(no-pie-ldflag) first so >> you can override it with the subsequent $(default-pie-ldflag)? >> >> It is not a robust design to use firstword here because it implies that the >> DEFAUTL-LDFLAGS-$(@F) has some structure that we are not documenting. >> >> I would like to see this done some other way. My preference would be for a new >> value other than DEFAULT-LDFLAGS to control the PIE-ness of the built progarm. >> > > I replaced DEFAUTL-LDFLAGS-$(@F) with $($(@F)-no-pie). Now I have > > # Command for statically linking programs with the C library. > ifndef +link-static > +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \ > - $(DEFAULT-LDFLAGS-$(@F)) \ > + $(if $($(@F)-no-pie),$(no-pie-ldflag),$(default-pie-ldflag)) \ > $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \ > >>> >>> diff --git a/NEWS b/NEWS >>> index ab14d1eb1b..61598be94d 100644 >>> --- a/NEWS >>> +++ b/NEWS >>> @@ -9,6 +9,11 @@ Version 2.27 >>> >>> Major new features: >>> >>> +* Add --enable-static-pie configure option to build static PIE. The >>> + resulting libc.a can be used with the GCC option, -static-pie, which >>> + is available with GCC 8 or above, to create static position independent >>> + executable (static PIE). >>> + >> >> The description of a new configure option is relevant only to INSTALL. >> >> We must explain when users would use this feature and why. NEWS entries are >> user facing and must explain the function of the new feature. Does it improve >> security for static binaries? Should users switch to using them instead of >> normal static binaries? >> >> Lastly, we must explain which machines are supported in this initial release >> of the feature. Only x86_64? You need not check all machines, other maintainers >> can check and adjust the NEWS entry, but we have to commit to at least one >> machine supporting this feature, which I assume is x86_64. >> >> For example: >> >> * The GNU C Library can now be compiled with support for building static >> PIE executables (See --enable-static-pie in INSTALL). These static PIE >> exectuables are like static executables but can be loaded at any address >> and provide additional security hardening benefits at the cost of some >> memory and performance. When the library is built with --enable-static-pie >> the resulting libc.a is usable with GCC 8 and above to create static PIE >> executables using the GCC option '-static-pie'. This feature is currently >> supported on x86_64. >> > > I took your example. Thanks. > >> >>> diff --git a/configure.ac b/configure.ac >>> index 8ebc490a55..ae219f8fe0 100644 >>> --- a/configure.ac >>> +++ b/configure.ac >>> @@ -176,6 +176,11 @@ AC_ARG_ENABLE([profile], >>> [build profiled library @<:@default=no@:>@]), >>> [profile=$enableval], >>> [profile=no]) >>> +AC_ARG_ENABLE([static-pie], >>> + AC_HELP_STRING([--enable-static-pie], >>> + [build static executables as PIE @<:@default=no@:>@]), >> >> This does 2 things: >> * It enables support for building static PIE executables. >> * It builds all static binaries and tests in the testsuite as static PIE executables. >> >> It should say that e.g. >> >> "Enable static PIE executable support and use it in the testsuite." >> >> I understand the desire to use such a functionality to test static PIE executables >> by converting the entire testsuite to use them, but we still need to test non-PIE >> static executables? How are we still doing that after this change? >> >> How are we testing non-PIE static executables after this change? > > This is similar to PIE vs non-PIE. When you build glibc with GCC > defaulting to PIE, most of dynamic tests are built as PIE, except for > a couple of them linked with $(no-pie-ldflag). I added > > elf/tst-tls1-static-non-pie.c > > which is always built as non-PIE static executable, regardless if > --enable-static-pie is used to configure glibc. > > To get better coverage for non-PIE, we need to build glibc with GCC > defaulting to non-PIE and configure glibc without --enable-static-pie. > >>> diff --git a/manual/install.texi b/manual/install.texi >>> index f1fa28c937..86193ade3f 100644 >>> --- a/manual/install.texi >>> +++ b/manual/install.texi >>> @@ -120,6 +120,13 @@ Don't build shared libraries even if it is possible. Not all systems >>> support shared libraries; you need ELF support and (currently) the GNU >>> linker. >>> >>> +@item --enable-static-pie >> >> This should be rewritten to explain the feature that it enables first, >> and then the ancilliary benefits like turning it on in the testsuite. >> >>> +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. >>> + > > I changed it to > > '--enable-static-pie' > Enable static position independent executable (static PIE) support. > Static PIE is similar to static executable, but can be loaded at > any address without help from a dynamic linker. All static > programs as well as static tests are built as static PIE, except > for those marked with no-pie. The resulting glibc can be used with > the GCC option, -static-pie, which is available with GCC 8 or > above, to create static PIE. > > Here is the updated patch. > > Using GCC 7 and binutils master branch, build-many-glibcs.py with > --enable-static-pie with all patches for static PIE applied have the > following build successes: > > PASS: glibcs-aarch64_be-linux-gnu build > PASS: glibcs-aarch64-linux-gnu build > PASS: glibcs-armeb-linux-gnueabi-be8 build > PASS: glibcs-armeb-linux-gnueabi build > PASS: glibcs-armeb-linux-gnueabihf-be8 build > PASS: glibcs-armeb-linux-gnueabihf build > PASS: glibcs-arm-linux-gnueabi build > PASS: glibcs-arm-linux-gnueabihf build > PASS: glibcs-arm-linux-gnueabihf-v7a build > PASS: glibcs-arm-linux-gnueabihf-v7a-disable-multi-arch build > PASS: glibcs-m68k-linux-gnu build > PASS: glibcs-microblazeel-linux-gnu build > PASS: glibcs-microblaze-linux-gnu build > PASS: glibcs-mips64el-linux-gnu-n32 build > PASS: glibcs-mips64el-linux-gnu-n32-nan2008 build > PASS: glibcs-mips64el-linux-gnu-n32-nan2008-soft build > PASS: glibcs-mips64el-linux-gnu-n32-soft build > PASS: glibcs-mips64el-linux-gnu-n64 build > PASS: glibcs-mips64el-linux-gnu-n64-nan2008 build > PASS: glibcs-mips64el-linux-gnu-n64-nan2008-soft build > PASS: glibcs-mips64el-linux-gnu-n64-soft build > PASS: glibcs-mips64-linux-gnu-n32 build > PASS: glibcs-mips64-linux-gnu-n32-nan2008 build > PASS: glibcs-mips64-linux-gnu-n32-nan2008-soft build > PASS: glibcs-mips64-linux-gnu-n32-soft build > PASS: glibcs-mips64-linux-gnu-n64 build > PASS: glibcs-mips64-linux-gnu-n64-nan2008 build > PASS: glibcs-mips64-linux-gnu-n64-nan2008-soft build > PASS: glibcs-mips64-linux-gnu-n64-soft build > PASS: glibcs-mipsel-linux-gnu build > PASS: glibcs-mipsel-linux-gnu-nan2008 build > PASS: glibcs-mipsel-linux-gnu-nan2008-soft build > PASS: glibcs-mipsel-linux-gnu-soft build > PASS: glibcs-mips-linux-gnu build > PASS: glibcs-mips-linux-gnu-nan2008 build > PASS: glibcs-mips-linux-gnu-nan2008-soft build > PASS: glibcs-mips-linux-gnu-soft build > PASS: glibcs-nios2-linux-gnu build > PASS: glibcs-powerpc64le-linux-gnu build > PASS: glibcs-powerpc64-linux-gnu build > PASS: glibcs-tilegxbe-linux-gnu-32 build > PASS: glibcs-tilegxbe-linux-gnu build > PASS: glibcs-tilegx-linux-gnu-32 build > PASS: glibcs-tilegx-linux-gnu build > PASS: glibcs-tilepro-linux-gnu build > > I don't know how many of them actually work, except for aarch64. > > Thanks. > Hi Carlos, Do you get a chance to take a look https://sourceware.org/ml/libc-alpha/2017-12/msg00033.html Thanks. -- H.J. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-12-01 18:24 ` H.J. Lu 2017-12-08 13:14 ` H.J. Lu @ 2017-12-15 21:19 ` Carlos O'Donell 2017-12-16 2:04 ` H.J. Lu 1 sibling, 1 reply; 37+ messages in thread From: Carlos O'Donell @ 2017-12-15 21:19 UTC (permalink / raw) To: H.J. Lu; +Cc: Szabolcs Nagy, nd, Joseph Myers, GNU C Library On 12/01/2017 10:24 AM, H.J. Lu wrote: > On Thu, Nov 30, 2017 at 1:44 PM, Carlos O'Donell <carlos@redhat.com> wrote: >> H.J., >> >> High Level: >> >> At a high level I have no objection with the idea of static PIE executables, >> it makes sense to support such things. > Thanks for your feedbacks. Thank you for putting together a v2, sorry it took me a while to review. This version looks good to me, it cleans up the outstanding issues with the implementation, and you have answered my questions about testing in the design. The firstword hack is removed in the implementation and that was the only thing that needed cleanup. Looks good to me. Please feel free to commit. >> My only nit is that we need to do a better job of explaining to users why >> they would use them and under what circumstances. To that end you have a bit >> more work to do in the commit message, install.texit, and NEWS entry. >> >> Design: >> >> I have one design question below which around testing static non-PIE executables >> in a --enable-static-pie build. See below. >> >> Implementation: >> >> Everything looks good except the use of firstword in +link-static-before-libc, >> which I describe below. I think this is a hack and should be changed to better >> represent the expected semantics and structure you are looking to support. > Fixed. > >> Thank you for your work in this area. >> >> Look forward to a v2. >> >>> From 7026a79c1f71f5decd135208503fd4186193ffb8 Mon Sep 17 00:00:00 2001 >>> From: "H.J. Lu" <hjl.tools@gmail.com> >>> Date: Mon, 17 Jul 2017 08:17:32 -0700 >>> Subject: [PATCH] Add --enable-static-pie configure option to build static PIE >>> [BZ #19574] >>> >>> 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. >> You write "which are allowed", shouldn't that be "which are not allowed"? > Fixed. > >> The commit message must explain the following: >> >> * Why would a user use this feature? >> - What does it provide over and beyond existing static executables >> >> * How does a user decide to use this feature? >> - Should everyone use it? >> - Should you use it if you care about security, and what does it cost? >> >> Please include the answers to these questions in a the next versions >> commit message. > I added : > > Static PIE extends address space layout randomization to static > executables. It provides additional security hardening benefits at > the cost of some memory and performance. > > Is this OK? Perfect. >>> @@ -420,7 +440,7 @@ endif >>> # Command for statically linking programs with the C library. >>> ifndef +link-static >>> +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \ >>> - $(DEFAULT-LDFLAGS-$(@F)) \ >>> + $(firstword $(DEFAULT-LDFLAGS-$(@F)) $(default-pie-ldflag)) \ >> Is the use of firstword here just a hack to put $(no-pie-ldflag) first so >> you can override it with the subsequent $(default-pie-ldflag)? >> >> It is not a robust design to use firstword here because it implies that the >> DEFAUTL-LDFLAGS-$(@F) has some structure that we are not documenting. >> >> I would like to see this done some other way. My preference would be for a new >> value other than DEFAULT-LDFLAGS to control the PIE-ness of the built progarm. >> > I replaced DEFAUTL-LDFLAGS-$(@F) with $($(@F)-no-pie). Now I have > > # Command for statically linking programs with the C library. > ifndef +link-static > +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \ > - $(DEFAULT-LDFLAGS-$(@F)) \ > + $(if $($(@F)-no-pie),$(no-pie-ldflag),$(default-pie-ldflag)) \ > $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \ > This is much better. Thanks. >>> diff --git a/NEWS b/NEWS >>> index ab14d1eb1b..61598be94d 100644 >>> --- a/NEWS >>> +++ b/NEWS >>> @@ -9,6 +9,11 @@ Version 2.27 >>> >>> Major new features: >>> >>> +* Add --enable-static-pie configure option to build static PIE. The >>> + resulting libc.a can be used with the GCC option, -static-pie, which >>> + is available with GCC 8 or above, to create static position independent >>> + executable (static PIE). >>> + >> The description of a new configure option is relevant only to INSTALL. >> >> We must explain when users would use this feature and why. NEWS entries are >> user facing and must explain the function of the new feature. Does it improve >> security for static binaries? Should users switch to using them instead of >> normal static binaries? >> >> Lastly, we must explain which machines are supported in this initial release >> of the feature. Only x86_64? You need not check all machines, other maintainers >> can check and adjust the NEWS entry, but we have to commit to at least one >> machine supporting this feature, which I assume is x86_64. >> >> For example: >> >> * The GNU C Library can now be compiled with support for building static >> PIE executables (See --enable-static-pie in INSTALL). These static PIE >> exectuables are like static executables but can be loaded at any address >> and provide additional security hardening benefits at the cost of some >> memory and performance. When the library is built with --enable-static-pie >> the resulting libc.a is usable with GCC 8 and above to create static PIE >> executables using the GCC option '-static-pie'. This feature is currently >> supported on x86_64. >> > I took your example. Thanks. You are welcome. I hope you fixed my spelling mistakes ;-) I tried to provide at least some examples of what I was looking for. I appreciate your patience. >>> diff --git a/configure.ac b/configure.ac >>> index 8ebc490a55..ae219f8fe0 100644 >>> --- a/configure.ac >>> +++ b/configure.ac >>> @@ -176,6 +176,11 @@ AC_ARG_ENABLE([profile], >>> [build profiled library @<:@default=no@:>@]), >>> [profile=$enableval], >>> [profile=no]) >>> +AC_ARG_ENABLE([static-pie], >>> + AC_HELP_STRING([--enable-static-pie], >>> + [build static executables as PIE @<:@default=no@:>@]), >> This does 2 things: >> * It enables support for building static PIE executables. >> * It builds all static binaries and tests in the testsuite as static PIE executables. >> >> It should say that e.g. >> >> "Enable static PIE executable support and use it in the testsuite." >> >> I understand the desire to use such a functionality to test static PIE executables >> by converting the entire testsuite to use them, but we still need to test non-PIE >> static executables? How are we still doing that after this change? >> >> How are we testing non-PIE static executables after this change? > This is similar to PIE vs non-PIE. When you build glibc with GCC > defaulting to PIE, most of dynamic tests are built as PIE, except for > a couple of them linked with $(no-pie-ldflag). I added > > elf/tst-tls1-static-non-pie.c > > which is always built as non-PIE static executable, regardless if > --enable-static-pie is used to configure glibc. OK, this is better than nothing. Thank you for checking. > To get better coverage for non-PIE, we need to build glibc with GCC > defaulting to non-PIE and configure glibc without --enable-static-pie. > >>> diff --git a/manual/install.texi b/manual/install.texi >>> index f1fa28c937..86193ade3f 100644 >>> --- a/manual/install.texi >>> +++ b/manual/install.texi >>> @@ -120,6 +120,13 @@ Don't build shared libraries even if it is possible. Not all systems >>> support shared libraries; you need ELF support and (currently) the GNU >>> linker. >>> >>> +@item --enable-static-pie >> This should be rewritten to explain the feature that it enables first, >> and then the ancilliary benefits like turning it on in the testsuite. >> >>> +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. >>> + > I changed it to > > '--enable-static-pie' > Enable static position independent executable (static PIE) support. > Static PIE is similar to static executable, but can be loaded at > any address without help from a dynamic linker. All static > programs as well as static tests are built as static PIE, except > for those marked with no-pie. The resulting glibc can be used with > the GCC option, -static-pie, which is available with GCC 8 or > above, to create static PIE. OK. > Here is the updated patch. > > Using GCC 7 and binutils master branch, build-many-glibcs.py with > --enable-static-pie with all patches for static PIE applied have the > following build successes: > > PASS: glibcs-aarch64_be-linux-gnu build > PASS: glibcs-aarch64-linux-gnu build > PASS: glibcs-armeb-linux-gnueabi-be8 build > PASS: glibcs-armeb-linux-gnueabi build > PASS: glibcs-armeb-linux-gnueabihf-be8 build > PASS: glibcs-armeb-linux-gnueabihf build > PASS: glibcs-arm-linux-gnueabi build > PASS: glibcs-arm-linux-gnueabihf build > PASS: glibcs-arm-linux-gnueabihf-v7a build > PASS: glibcs-arm-linux-gnueabihf-v7a-disable-multi-arch build > PASS: glibcs-m68k-linux-gnu build > PASS: glibcs-microblazeel-linux-gnu build > PASS: glibcs-microblaze-linux-gnu build > PASS: glibcs-mips64el-linux-gnu-n32 build > PASS: glibcs-mips64el-linux-gnu-n32-nan2008 build > PASS: glibcs-mips64el-linux-gnu-n32-nan2008-soft build > PASS: glibcs-mips64el-linux-gnu-n32-soft build > PASS: glibcs-mips64el-linux-gnu-n64 build > PASS: glibcs-mips64el-linux-gnu-n64-nan2008 build > PASS: glibcs-mips64el-linux-gnu-n64-nan2008-soft build > PASS: glibcs-mips64el-linux-gnu-n64-soft build > PASS: glibcs-mips64-linux-gnu-n32 build > PASS: glibcs-mips64-linux-gnu-n32-nan2008 build > PASS: glibcs-mips64-linux-gnu-n32-nan2008-soft build > PASS: glibcs-mips64-linux-gnu-n32-soft build > PASS: glibcs-mips64-linux-gnu-n64 build > PASS: glibcs-mips64-linux-gnu-n64-nan2008 build > PASS: glibcs-mips64-linux-gnu-n64-nan2008-soft build > PASS: glibcs-mips64-linux-gnu-n64-soft build > PASS: glibcs-mipsel-linux-gnu build > PASS: glibcs-mipsel-linux-gnu-nan2008 build > PASS: glibcs-mipsel-linux-gnu-nan2008-soft build > PASS: glibcs-mipsel-linux-gnu-soft build > PASS: glibcs-mips-linux-gnu build > PASS: glibcs-mips-linux-gnu-nan2008 build > PASS: glibcs-mips-linux-gnu-nan2008-soft build > PASS: glibcs-mips-linux-gnu-soft build > PASS: glibcs-nios2-linux-gnu build > PASS: glibcs-powerpc64le-linux-gnu build > PASS: glibcs-powerpc64-linux-gnu build > PASS: glibcs-tilegxbe-linux-gnu-32 build > PASS: glibcs-tilegxbe-linux-gnu build > PASS: glibcs-tilegx-linux-gnu-32 build > PASS: glibcs-tilegx-linux-gnu build > PASS: glibcs-tilepro-linux-gnu build > > I don't know how many of them actually work, except for aarch64. Right, the real test is that they work. However, making sure they compilation passes is the first real step allowing the machine maintainers to look into runtime issues. > Thanks. > > -- H.J. > > > 0001-Add-enable-static-pie-configure-option-to-build-stat.patch > > > From 86d8013ccc24e4c07fdc6da04dac0448c4f5fc29 Mon Sep 17 00:00:00 2001 > From: "H.J. Lu" <hjl.tools@gmail.com> > Date: Mon, 17 Jul 2017 08:17:32 -0700 > Subject: [PATCH] Add --enable-static-pie configure option to build static PIE > [BZ #19574] > > 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. Only GCC > with PIE support is needed. 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 not allowed > in static PIE. > > Static PIE extends address space layout randomization to static > executables. It provides additional security hardening benefits at > the cost of some memory and performance. Put this paragraph first in your commit message please. It's they key purpose of this entire patch. > The following changes are made for static PIE: > > 1. Add a new function, _dl_relocate_static_pie, to: > a. Get the run-time load address. > b. Read the dynamic section. > c. Perform dynamic relocations. > Dynamic linker also performs these steps. But static PIE doesn't load > any shared objects. > 2. Call _dl_relocate_static_pie at entrance of LIBC_START_MAIN in > libc.a. crt1.o, which is used to create dynamic and non-PIE static > executables, is updated to include a dummy _dl_relocate_static_pie. > rcrt1.o is added to create static PIE, which will link in the real > _dl_relocate_static_pie. grcrt1.o is also added to create static PIE > with -pg. GCC 8 has been updated to support rcrt1.o and grcrt1.o for > static PIE. > > 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. All > functions in static PIE are local functions. If PIE start.S can't reach > main () defined in a shared object, the code sequence: > > pass addess of local_main to __libc_start_main s/addess/address/g > ... > > local_main: > tail call to main via PLT > > can be used. > 2. start.S is updated to check PIC instead SHARED for PIC code path and > avoid dynamic relocation, when PIC is defined and SHARED isn't defined, > to support static PIE. Patches are submitted for aarch64, hppa, m68k, > microblaze and sparc. > 3. All assembly codes are updated check PIC instead SHARED for PIC code > path to avoid dynamic relocations in read-only sections. > 4. All assembly codes are updated check SHARED instead PIC for static > symbol name. A patch is submitted for tile. > 5. elf_machine_load_address in dl-machine.h are updated to support static > PIE. Patches are submitted for aarch64, s390 and sh. > 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. > > 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 s/wether/whether/g > can be used to build both static executable and static PIE. There is no > need for separate PIE copy of libc.a. > > 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 > > The i386 linker needs to be able to convert "movl main@GOT(%ebx), %eax" > to "leal main@GOTOFF(%ebx), %eax" if main is defined locally. > > Binutils 2.29 or above are OK for i686 and x86-64. But linker status for > other targets need to be verified. > > 3. Linker should resolve undefined weak symbols to 0 in static PIE: > > https://sourceware.org/bugzilla/show_bug.cgi?id=22269 > > 4. Many ELF backend linkers incorrectly check bfd_link_pic for TLS > relocations, which should check bfd_link_executable instead: > > https://sourceware.org/bugzilla/show_bug.cgi?id=22263 > > Tested on aarch64, i686 and x86-64. > > Using GCC 7 and binutils master branch, build-many-glibcs.py with > --enable-static-pie with all patches for static PIE applied have the > following build successes: > > PASS: glibcs-aarch64_be-linux-gnu build > PASS: glibcs-aarch64-linux-gnu build > PASS: glibcs-armeb-linux-gnueabi-be8 build > PASS: glibcs-armeb-linux-gnueabi build > PASS: glibcs-armeb-linux-gnueabihf-be8 build > PASS: glibcs-armeb-linux-gnueabihf build > PASS: glibcs-arm-linux-gnueabi build > PASS: glibcs-arm-linux-gnueabihf build > PASS: glibcs-arm-linux-gnueabihf-v7a build > PASS: glibcs-arm-linux-gnueabihf-v7a-disable-multi-arch build > PASS: glibcs-m68k-linux-gnu build > PASS: glibcs-microblazeel-linux-gnu build > PASS: glibcs-microblaze-linux-gnu build > PASS: glibcs-mips64el-linux-gnu-n32 build > PASS: glibcs-mips64el-linux-gnu-n32-nan2008 build > PASS: glibcs-mips64el-linux-gnu-n32-nan2008-soft build > PASS: glibcs-mips64el-linux-gnu-n32-soft build > PASS: glibcs-mips64el-linux-gnu-n64 build > PASS: glibcs-mips64el-linux-gnu-n64-nan2008 build > PASS: glibcs-mips64el-linux-gnu-n64-nan2008-soft build > PASS: glibcs-mips64el-linux-gnu-n64-soft build > PASS: glibcs-mips64-linux-gnu-n32 build > PASS: glibcs-mips64-linux-gnu-n32-nan2008 build > PASS: glibcs-mips64-linux-gnu-n32-nan2008-soft build > PASS: glibcs-mips64-linux-gnu-n32-soft build > PASS: glibcs-mips64-linux-gnu-n64 build > PASS: glibcs-mips64-linux-gnu-n64-nan2008 build > PASS: glibcs-mips64-linux-gnu-n64-nan2008-soft build > PASS: glibcs-mips64-linux-gnu-n64-soft build > PASS: glibcs-mipsel-linux-gnu build > PASS: glibcs-mipsel-linux-gnu-nan2008 build > PASS: glibcs-mipsel-linux-gnu-nan2008-soft build > PASS: glibcs-mipsel-linux-gnu-soft build > PASS: glibcs-mips-linux-gnu build > PASS: glibcs-mips-linux-gnu-nan2008 build > PASS: glibcs-mips-linux-gnu-nan2008-soft build > PASS: glibcs-mips-linux-gnu-soft build > PASS: glibcs-nios2-linux-gnu build > PASS: glibcs-powerpc64le-linux-gnu build > PASS: glibcs-powerpc64-linux-gnu build > PASS: glibcs-tilegxbe-linux-gnu-32 build > PASS: glibcs-tilegxbe-linux-gnu build > PASS: glibcs-tilegx-linux-gnu-32 build > PASS: glibcs-tilegx-linux-gnu build > PASS: glibcs-tilepro-linux-gnu build > > and the following build failures: > > FAIL: glibcs-alpha-linux-gnu build > > elf/sln is failed to link due to: > > assertion fail bfd/elf64-alpha.c:4125 > > This is caused by linker bug and/or non-PIC code in PIE libc.a. > > FAIL: glibcs-hppa-linux-gnu build > > elf/sln is failed to link due to: > > collect2: fatal error: ld terminated with signal 11 [Segmentation fault] > > https://sourceware.org/bugzilla/show_bug.cgi?id=22537 > > FAIL: glibcs-ia64-linux-gnu build > > elf/sln is failed to link due to: > > collect2: fatal error: ld terminated with signal 11 [Segmentation fault] > > FAIL: glibcs-powerpc-linux-gnu build > FAIL: glibcs-powerpc-linux-gnu-soft build > FAIL: glibcs-powerpc-linux-gnuspe build > FAIL: glibcs-powerpc-linux-gnuspe-e500v1 build > > elf/sln is failed to link due to: > > ld: read-only segment has dynamic relocations. > > This is caused by linker bug and/or non-PIC code in PIE libc.a. See: > > https://sourceware.org/bugzilla/show_bug.cgi?id=22264 > > FAIL: glibcs-powerpc-linux-gnu-power4 build > > elf/sln is failed to link due to: > > findlocale.c:96:(.text+0x22c): @local call to ifunc memchr > > This is caused by linker bug and/or non-PIC code in PIE libc.a. > > FAIL: glibcs-s390-linux-gnu build > > elf/sln is failed to link due to: > > collect2: fatal error: ld terminated with signal 11 [Segmentation fault], core dumped > > assertion fail bfd/elflink.c:14299 > > This is caused by linker bug and/or non-PIC code in PIE libc.a. > > FAIL: glibcs-sh3eb-linux-gnu build > FAIL: glibcs-sh3-linux-gnu build > FAIL: glibcs-sh4eb-linux-gnu build > FAIL: glibcs-sh4eb-linux-gnu-soft build > FAIL: glibcs-sh4-linux-gnu build > FAIL: glibcs-sh4-linux-gnu-soft build > > elf/sln is failed to link due to: > > ld: read-only segment has dynamic relocations. > > This is caused by linker bug and/or non-PIC code in PIE libc.a. See: > > https://sourceware.org/bugzilla/show_bug.cgi?id=22263 > > Also TLS code sequence in SH assembly syscalls in glibc doesn't match TLS > code sequence expected by ld: > > https://sourceware.org/bugzilla/show_bug.cgi?id=22270 > > FAIL: glibcs-sparc64-linux-gnu build > FAIL: glibcs-sparcv9-linux-gnu build > FAIL: glibcs-tilegxbe-linux-gnu build > FAIL: glibcs-tilegxbe-linux-gnu-32 build > FAIL: glibcs-tilegx-linux-gnu build > FAIL: glibcs-tilegx-linux-gnu-32 build > FAIL: glibcs-tilepro-linux-gnu build > > elf/sln is failed to link due to: > > ld: read-only segment has dynamic relocations. > > This is caused by linker bug and/or non-PIC code in PIE libc.a. See: > > https://sourceware.org/bugzilla/show_bug.cgi?id=22263 > > [BZ #19574] > * INSTALL: Regenerated. > * Makeconfig (real-static-start-installed-name): New. > (pic-default): Updated for --enable-static-pie. > (pie-default): New for --enable-static-pie. > (default-pie-ldflag): Likewise. > (+link-static-before-libc): Replace $(DEFAULT-LDFLAGS-$(@F)) > with $(if $($(@F)-no-pie),$(no-pie-ldflag),$(default-pie-ldflag)). > Replace $(static-start-installed-name) with > $(real-static-start-installed-name). > (+prectorT): Updated for --enable-static-pie. > (+postctorT): Likewise. > (CFLAGS-.o): Add $(pie-default). > (CFLAGS-.op): Likewise. > * NEWS: Mention --enable-static-pie. > * config.h.in (ENABLE_STATIC_PIE): New. > * configure.ac (--enable-static-pie): New configure option. > (have-no-dynamic-linker): New LIBC_CONFIG_VAR. > (have-static-pie): Likewise. > Enable static PIE if linker supports --no-dynamic-linker. > (ENABLE_STATIC_PIE): New AC_DEFINE. > (enable-static-pie): New LIBC_CONFIG_VAR. > * configure: Regenerated. > * csu/Makefile (omit-deps): Add r$(start-installed-name) and > gr$(start-installed-name) for --enable-static-pie. > (extra-objs): Likewise. > (install-lib): Likewise. > (extra-objs): Add static-reloc.o and static-reloc.os > ($(objpfx)$(start-installed-name)): Also depend on > $(objpfx)static-reloc.o. > ($(objpfx)r$(start-installed-name)): New. > ($(objpfx)g$(start-installed-name)): Also depend on > $(objpfx)static-reloc.os. > ($(objpfx)gr$(start-installed-name)): New. > * csu/libc-start.c (LIBC_START_MAIN): Call _dl_relocate_static_pie > in libc.a. > * csu/libc-tls.c (__libc_setup_tls): Add main_map->l_addr to > initimage. > * csu/static-reloc.c: New file. > * elf/Makefile (routines): Add dl-reloc-static-pie. > (elide-routines.os): Likewise. > (DEFAULT-LDFLAGS-tst-tls1-static-non-pie): Removed. > (tst-tls1-static-non-pie-no-pie): New. > * elf/dl-reloc-static-pie.c: New file. > * elf/dl-support.c (_dl_get_dl_main_map): New function. > * elf/dynamic-link.h (ELF_DURING_STARTUP): Also check > STATIC_PIE_BOOTSTRAP. > * elf/get-dynamic-info.h (elf_get_dynamic_info): Likewise. > * gmon/Makefile (tests): Add tst-gmon-static-pie. > (tests-static): Likewise. > (DEFAULT-LDFLAGS-tst-gmon-static): Removed. > (tst-gmon-static-no-pie): New. > (CFLAGS-tst-gmon-static-pie.c): Likewise. > (CRT-tst-gmon-static-pie): Likewise. > (tst-gmon-static-pie-ENV): Likewise. > (tests-special): Likewise. > ($(objpfx)tst-gmon-static-pie.out): Likewise. > (clean-tst-gmon-static-pie-data): Likewise. > ($(objpfx)tst-gmon-static-pie-gprof.out): Likewise. > * gmon/tst-gmon-static-pie.c: New file. > * manual/install.texi: Document --enable-static-pie. > * sysdeps/generic/ldsodefs.h (_dl_relocate_static_pie): New. > (_dl_get_dl_main_map): Likewise. > * sysdeps/i386/configure.ac: Check if linker supports static PIE. > * sysdeps/x86_64/configure.ac: Likewise. > * sysdeps/i386/configure: Regenerated. > * sysdeps/x86_64/configure: Likewise. > * sysdeps/mips/Makefile (ASFLAGS-.o): Add $(pie-default). > (ASFLAGS-.op): Likewise. > --- > INSTALL | 9 ++++++ > Makeconfig | 38 +++++++++++++++++++--- > NEWS | 9 ++++++ > config.h.in | 3 ++ > configure | 79 +++++++++++++++++++++++++++++++++++++++++++++ > configure.ac | 29 +++++++++++++++++ > csu/Makefile | 24 ++++++++++++-- > csu/libc-start.c | 2 ++ > csu/libc-tls.c | 6 ++-- > csu/static-reloc.c | 26 +++++++++++++++ > elf/Makefile | 7 ++-- > elf/dl-reloc-static-pie.c | 52 +++++++++++++++++++++++++++++ > elf/dl-support.c | 11 +++++++ > elf/dynamic-link.h | 2 +- > elf/get-dynamic-info.h | 6 ++-- > gmon/Makefile | 25 +++++++++++++- > gmon/tst-gmon-static-pie.c | 1 + > manual/install.texi | 9 ++++++ > sysdeps/generic/ldsodefs.h | 11 +++++++ > sysdeps/i386/configure | 33 +++++++++++++++++++ > sysdeps/i386/configure.ac | 23 +++++++++++++ > sysdeps/mips/Makefile | 3 ++ > sysdeps/x86_64/configure | 33 +++++++++++++++++++ > sysdeps/x86_64/configure.ac | 25 ++++++++++++++ > 24 files changed, 449 insertions(+), 17 deletions(-) > create mode 100644 csu/static-reloc.c > create mode 100644 elf/dl-reloc-static-pie.c > create mode 100644 gmon/tst-gmon-static-pie.c > > diff --git a/INSTALL b/INSTALL > index d1a34c2a90..30804eca38 100644 > --- a/INSTALL > +++ b/INSTALL > @@ -90,6 +90,15 @@ will be used, and CFLAGS sets optimization options for the compiler. > systems support shared libraries; you need ELF support and > (currently) the GNU linker. > > +'--enable-static-pie' > + Enable static position independent executable (static PIE) support. > + Static PIE is similar to static executable, but can be loaded at > + any address without help from a dynamic linker. All static > + programs as well as static tests are built as static PIE, except > + for those marked with no-pie. The resulting glibc can be used with > + the GCC option, -static-pie, which is available with GCC 8 or > + above, to create static PIE. > + OK. > '--disable-profile' > Don't build libraries with profiling information. You may want to > use this option if you don't plan to do profiling. > diff --git a/Makeconfig b/Makeconfig > index 1346109ac0..99cc136bfa 100644 > --- a/Makeconfig > +++ b/Makeconfig > @@ -352,6 +352,14 @@ ifndef static-start-installed-name > static-start-installed-name = $(start-installed-name) > endif > > +ifeq (yes,$(enable-static-pie)) > +# Link with rcrt1.o, instead of crt1.o, to call _dl_relocate_static_pie > +# to relocate static PIE. > +real-static-start-installed-name = r$(static-start-installed-name) > +else > +real-static-start-installed-name = $(static-start-installed-name) > +endif > + OK. > ifeq (yesyes,$(build-shared)$(have-z-combreloc)) > combreloc-LDFLAGS = -Wl,-z,combreloc > LDFLAGS.so += $(combreloc-LDFLAGS) > @@ -371,6 +379,20 @@ LDFLAGS.so += $(hashstyle-LDFLAGS) > LDFLAGS-rtld += $(hashstyle-LDFLAGS) > endif > > +ifeq (yes,$(enable-static-pie)) > +pic-default = -DPIC > +# Compile libc.a and libc_p.a with -fPIE/-fpie for static PIE. > +pie-default = $(pie-ccflag) > +ifeq (yes,$(have-static-pie)) > +default-pie-ldflag = -static-pie > +else > +# Static PIE can't have dynamic relocations in read-only segments since > +# static PIE is mapped into memory by kernel. --eh-frame-hdr is needed > +# for PIE to support exception. > +default-pie-ldflag = -Wl,-pie,--no-dynamic-linker,--eh-frame-hdr,-z,text > +endif > +endif OK. > + > # If lazy relocations are disabled, add the -z now flag. Use > # LDFLAGS-lib.so instead of LDFLAGS.so, to avoid adding the flag to > # test modules. > @@ -420,9 +442,9 @@ endif > # Command for statically linking programs with the C library. > ifndef +link-static > +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \ > - $(DEFAULT-LDFLAGS-$(@F)) \ > + $(if $($(@F)-no-pie),$(no-pie-ldflag),$(default-pie-ldflag)) \ OK. > $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \ > - $(firstword $(CRT-$(@F)) $(csu-objpfx)$(static-start-installed-name)) \ > + $(firstword $(CRT-$(@F)) $(csu-objpfx)$(real-static-start-installed-name)) \ OK. > $(+preinit) $(+prectorT) \ > $(filter-out $(addprefix $(csu-objpfx),start.o \ > $(start-installed-name))\ > @@ -637,8 +659,14 @@ endif > +prectorS = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtbeginS.o` > +postctorS = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtendS.o` > # Variants of the two previous definitions for statically linking programs. > +ifeq (yes,$(enable-static-pie)) > +# Static PIE must use PIE variants. > ++prectorT = $(+prectorS) > ++postctorT = $(+postctorS) > +else > +prectorT = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtbeginT.o` > +postctorT = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtend.o` > +endif OK. > csu-objpfx = $(common-objpfx)csu/ > elf-objpfx = $(common-objpfx)elf/ > > @@ -959,7 +987,8 @@ libtypes = $(foreach o,$(object-suffixes-for-libc),$(libtype$o)) > all-object-suffixes := .o .os .oS > object-suffixes := > CPPFLAGS-.o = $(pic-default) > -CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) > +# libc.a must be compiled with -fPIE/-fpie for static PIE. > +CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) $(pie-default) OK. > libtype.o := lib%.a > object-suffixes += .o > ifeq (yes,$(build-shared)) > @@ -984,7 +1013,8 @@ ifeq (yes,$(build-profile)) > all-object-suffixes += .op > object-suffixes += .op > CPPFLAGS-.op = -DPROF $(pic-default) > -CFLAGS-.op = -pg > +# libc_p.a must be compiled with -fPIE/-fpie for static PIE. > +CFLAGS-.op = -pg $(pie-default) OK. > libtype.op = lib%_p.a > endif > > diff --git a/NEWS b/NEWS > index 48af4acaea..5b09359f2c 100644 > --- a/NEWS > +++ b/NEWS > @@ -9,6 +9,15 @@ Version 2.27 > > Major new features: > > +* The GNU C Library can now be compiled with support for building static > + PIE executables (See --enable-static-pie in INSTALL). These static PIE > + exectuables are like static executables but can be loaded at any address > + and provide additional security hardening benefits at the cost of some > + memory and performance. When the library is built with --enable-static-pie > + the resulting libc.a is usable with GCC 8 and above to create static PIE > + executables using the GCC option '-static-pie'. This feature is currently > + supported on i386, x86_64 and x32. OK. > + > * Optimized x86-64 asin, atan2, exp, expf, log, pow, atan, sin and tan > with FMA, contributed by Arjan van de Ven and H.J. Lu from Intel. > > diff --git a/config.h.in b/config.h.in > index 8d76dadca2..0ecb10939f 100644 > --- a/config.h.in > +++ b/config.h.in > @@ -241,6 +241,9 @@ > /* Build glibc with tunables support. */ > #define HAVE_TUNABLES 0 > > +/* Define if static PIE is enabled. */ > +#define ENABLE_STATIC_PIE 0 OK. > + > /* Some compiler options may now allow to use ebp in __asm__ (used mainly > in i386 6 argument syscall issue). */ > #define CAN_USE_REGISTER_ASM_EBP 0 [snip configure] > diff --git a/configure.ac b/configure.ac > index 9707ae4d8e..78564f3746 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -176,6 +176,11 @@ AC_ARG_ENABLE([profile], > [build profiled library @<:@default=no@:>@]), > [profile=$enableval], > [profile=no]) > +AC_ARG_ENABLE([static-pie], > + AC_HELP_STRING([--enable-static-pie], > + [enable static PIE support and use it in the testsuite @<:@default=no@:>@]), > + [static_pie=$enableval], > + [static_pie=no]) > AC_ARG_ENABLE([timezone-tools], OK. > AC_HELP_STRING([--disable-timezone-tools], > [do not install timezone tools @<:@default=install@:>@]), > @@ -1280,6 +1285,19 @@ LIBC_LINKER_FEATURE([-z execstack], [-Wl,-z,execstack], > [libc_cv_z_execstack=yes], [libc_cv_z_execstack=no]) > AC_SUBST(libc_cv_z_execstack) > > +LIBC_LINKER_FEATURE([--no-dynamic-linker], > + [-Wl,--no-dynamic-linker], > + [libc_cv_no_dynamic_linker=yes], > + [libc_cv_no_dynamic_linker=no]) > +LIBC_CONFIG_VAR([have-no-dynamic-linker], [$libc_cv_no_dynamic_linker]) > + > +AC_CACHE_CHECK(for -static-pie, libc_cv_static_pie, [dnl > +LIBC_TRY_CC_OPTION([-static-pie], > + [libc_cv_static_pie=yes], > + [libc_cv_static_pie=no]) > +]) > +LIBC_CONFIG_VAR([have-static-pie], [$libc_cv_static_pie]) > + OK. > AC_CACHE_CHECK(for -fpie, libc_cv_fpie, [dnl > LIBC_TRY_CC_OPTION([-fpie], [libc_cv_fpie=yes], [libc_cv_fpie=no]) > ]) > @@ -1787,6 +1805,17 @@ AC_SUBST(libc_cv_pie_default) > libc_cv_multidir=`${CC-cc} $CFLAGS $CPPFLAGS -print-multi-directory` > AC_SUBST(libc_cv_multidir) > > +if test "$static_pie" = yes; then > + # The linker must support --no-dynamic-linker. > + if test "$libc_cv_no_dynamic_linker" != yes; then > + AC_MSG_ERROR([linker support for --no-dynamic-linker needed]) > + fi > + # Default to PIE. > + libc_cv_pie_default=yes > + AC_DEFINE(ENABLE_STATIC_PIE) > +fi > +LIBC_CONFIG_VAR([enable-static-pie], [$static_pie]) > + OK. > AC_SUBST(profile) > AC_SUBST(static_nss) > > diff --git a/csu/Makefile b/csu/Makefile > index e42a32b3eb..86b95a9759 100644 > --- a/csu/Makefile > +++ b/csu/Makefile > @@ -37,7 +37,9 @@ extra-objs = start.o \ > S$(start-installed-name) > omit-deps = $(patsubst %.o,%,$(start-installed-name) g$(start-installed-name) \ > b$(start-installed-name) $(csu-dummies) \ > - S$(start-installed-name)) > + S$(start-installed-name) \ > + r$(start-installed-name) \ > + gr$(start-installed-name)) OK. > install-lib = $(start-installed-name) g$(start-installed-name) $(csu-dummies) > > # No tests are allowed in the csu/ subdirectory because the startup > @@ -60,10 +62,17 @@ extra-objs += gmon-start.o > endif > > ifneq ($(start-installed-name),$(static-start-installed-name)) > +# FIXME: Only Hurd defines static-start-installed-name. Hurd needs to > +# provide special rules to support static PIE. OK. Thanks for the FIXME comment. > extra-objs += $(static-start-installed-name) g$(static-start-installed-name) > omit-deps += $(patsubst %.o,%,$(static-start-installed-name) \ > g$(static-start-installed-name)) > install-lib += $(static-start-installed-name) g$(static-start-installed-name) > +else > +ifeq (yes,$(enable-static-pie)) > +extra-objs += r$(start-installed-name) gr$(start-installed-name) > +install-lib += r$(start-installed-name) gr$(start-installed-name) > +endif OK. > endif > > before-compile += $(objpfx)abi-tag.h > @@ -82,7 +91,10 @@ multilib-extra-objs = $(addprefix $(multidir)/, $(install-lib)) > extra-objs += $(multilib-extra-objs) > endif > > -extra-objs += abi-note.o init.o > +extra-objs += abi-note.o init.o static-reloc.o > +ifeq (yes,$(build-shared)) > +extra-objs += static-reloc.os > +endif > asm-CPPFLAGS += -I$(objpfx). > > # Enable unwinding so backtrace unwinds to __libc_start_main > @@ -101,6 +113,9 @@ ifndef start-installed-name-rule > # We link the ELF startfile along with a SHT_NOTE section indicating > # the kernel ABI the binaries linked with this library will require. > $(objpfx)$(start-installed-name): $(objpfx)start.o $(objpfx)abi-note.o \ > + $(objpfx)init.o $(objpfx)static-reloc.o > + $(link-relocatable) > +$(objpfx)r$(start-installed-name): $(objpfx)start.o $(objpfx)abi-note.o \ > $(objpfx)init.o OK. > $(link-relocatable) > $(objpfx)S$(start-installed-name): $(objpfx)start.os $(objpfx)abi-note.o \ > @@ -113,7 +128,10 @@ endif > # to turn on profiling code at startup. > ifeq (yes,$(build-shared)) > $(objpfx)g$(start-installed-name): \ > - $(objpfx)g%: $(objpfx)S% $(objpfx)gmon-start.os > + $(objpfx)g%: $(objpfx)S% $(objpfx)gmon-start.os $(objpfx)static-reloc.os > + $(link-relocatable) > +$(objpfx)gr$(start-installed-name): \ > + $(objpfx)gr%: $(objpfx)r% $(objpfx)gmon-start.o OK. > $(link-relocatable) > ifneq ($(start-installed-name),$(static-start-installed-name)) > $(objpfx)g$(static-start-installed-name): \ > diff --git a/csu/libc-start.c b/csu/libc-start.c > index 24c63be02f..34dd125260 100644 > --- a/csu/libc-start.c > +++ b/csu/libc-start.c > @@ -141,6 +141,8 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), > __libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up; > > #ifndef SHARED > + _dl_relocate_static_pie (); > + OK. > char **ev = &argv[argc + 1]; > > __environ = ev; > diff --git a/csu/libc-tls.c b/csu/libc-tls.c > index 00138eb43a..1f8ddaf543 100644 > --- a/csu/libc-tls.c > +++ b/csu/libc-tls.c > @@ -114,6 +114,8 @@ __libc_setup_tls (void) > size_t tcb_offset; > const ElfW(Phdr) *phdr; > > + struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded; > + OK. > /* Look through the TLS segment if there is any. */ > if (_dl_phdr != NULL) > for (phdr = _dl_phdr; phdr < &_dl_phdr[_dl_phnum]; ++phdr) > @@ -122,7 +124,7 @@ __libc_setup_tls (void) > /* Remember the values we need. */ > memsz = phdr->p_memsz; > filesz = phdr->p_filesz; > - initimage = (void *) phdr->p_vaddr; > + initimage = (void *) phdr->p_vaddr + main_map->l_addr; > align = phdr->p_align; OK. > if (phdr->p_align > max_align) > max_align = phdr->p_align; > @@ -163,8 +165,6 @@ __libc_setup_tls (void) > _dl_static_dtv[0].counter = (sizeof (_dl_static_dtv) / sizeof (_dl_static_dtv[0])) - 2; > // _dl_static_dtv[1].counter = 0; would be needed if not already done > > - struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded; > - OK. > /* Initialize the TLS block. */ > #if TLS_TCB_AT_TP > _dl_static_dtv[2].pointer.val = ((char *) tlsblock + tcb_offset > diff --git a/csu/static-reloc.c b/csu/static-reloc.c > new file mode 100644 > index 0000000000..37be72c8ea > --- /dev/null > +++ b/csu/static-reloc.c > @@ -0,0 +1,26 @@ > +/* Special startup support for non-PIE static executables. > + Copyright (C) 2017 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <http://www.gnu.org/licenses/>. */ > + > +#if ENABLE_STATIC_PIE > +#include <ldsodefs.h> > + > +void > +_dl_relocate_static_pie (void) > +{ > +} > +#endif OK. > diff --git a/elf/Makefile b/elf/Makefile > index d49fd4673d..4c6f9e0a49 100644 > --- a/elf/Makefile > +++ b/elf/Makefile > @@ -24,7 +24,8 @@ include ../Makeconfig > headers = elf.h bits/elfclass.h link.h bits/link.h > routines = $(all-dl-routines) dl-support dl-iteratephdr \ > dl-addr dl-addr-obj enbl-secure dl-profstub \ > - dl-origin dl-libc dl-sym dl-sysdep dl-error > + dl-origin dl-libc dl-sym dl-sysdep dl-error \ > + dl-reloc-static-pie OK. > > # The core dynamic linking functions are in libc for the static and > # profiled libraries. > @@ -52,7 +53,7 @@ endif > all-dl-routines = $(dl-routines) $(sysdep-dl-routines) > # But they are absent from the shared libc, because that code is in ld.so. > elide-routines.os = $(all-dl-routines) dl-support enbl-secure dl-origin \ > - dl-sysdep dl-exception > + dl-sysdep dl-exception dl-reloc-static-pie > shared-only-routines += dl-caller > > # ld.so uses those routines, plus some special stuff for being the program > @@ -153,7 +154,7 @@ tests-static-internal := tst-tls1-static tst-tls2-static \ > tst-tls1-static-non-pie > > CRT-tst-tls1-static-non-pie := $(csu-objpfx)crt1.o > -DEFAULT-LDFLAGS-tst-tls1-static-non-pie = $(no-pie-ldflag) > +tst-tls1-static-non-pie-no-pie = yes > > tests := tst-tls9 tst-leaks1 \ > tst-array1 tst-array2 tst-array3 tst-array4 tst-array5 \ > diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c > new file mode 100644 > index 0000000000..6e43aea76a > --- /dev/null > +++ b/elf/dl-reloc-static-pie.c > @@ -0,0 +1,52 @@ > +/* Support for relocating static PIE. > + Copyright (C) 2017 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <http://www.gnu.org/licenses/>. */ > + > +#if ENABLE_STATIC_PIE > +#include <unistd.h> > +#include <ldsodefs.h> > +#include "dynamic-link.h" > + > +/* Relocate static executable with PIE. */ > + > +void > +_dl_relocate_static_pie (void) > +{ > + struct link_map *main_map = _dl_get_dl_main_map (); > + > +# define STATIC_PIE_BOOTSTRAP > +# define BOOTSTRAP_MAP (main_map) > +# define RESOLVE_MAP(sym, version, flags) BOOTSTRAP_MAP > +# include "dynamic-link.h" > + > + /* Figure out the run-time load address of static PIE. */ > + main_map->l_addr = elf_machine_load_address (); > + > + /* Read our own dynamic section and fill in the info array. */ > + main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ()); > + elf_get_dynamic_info (main_map, NULL); > + > +# ifdef ELF_MACHINE_BEFORE_RTLD_RELOC > + ELF_MACHINE_BEFORE_RTLD_RELOC (main_map->l_info); > +# endif > + > + /* Relocate ourselves so we can do normal function calls and > + data access using the global offset table. */ > + ELF_DYNAMIC_RELOCATE (main_map, 0, 0, 0); > + main_map->l_relocated = 1; OK. > +} > +#endif > 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; > +} OK. > +#endif > diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h > index ebea7567cd..6278649711 100644 > --- a/elf/dynamic-link.h > +++ b/elf/dynamic-link.h > @@ -94,7 +94,7 @@ elf_machine_lazy_rel (struct link_map *map, > > #ifdef RESOLVE_MAP > > -# ifdef RTLD_BOOTSTRAP > +# if defined RTLD_BOOTSTRAP || defined STATIC_PIE_BOOTSTRAP > # define ELF_DURING_STARTUP (1) > # else > # define ELF_DURING_STARTUP (0) > diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h > index 7525c3a5b2..eb26d23649 100644 > --- a/elf/get-dynamic-info.h > +++ b/elf/get-dynamic-info.h > @@ -38,7 +38,7 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) > typedef Elf64_Xword d_tag_utype; > #endif > > -#ifndef RTLD_BOOTSTRAP > +#if !defined RTLD_BOOTSTRAP && !defined STATIC_PIE_BOOTSTRAP > if (dyn == NULL) > return; > #endif > @@ -139,9 +139,11 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) > /* Only the bind now flags are allowed. */ > assert (info[VERSYMIDX (DT_FLAGS_1)] == NULL > || (info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val & ~DF_1_NOW) == 0); > + /* Flags must not be set for ld.so. */ > assert (info[DT_FLAGS] == NULL > || (info[DT_FLAGS]->d_un.d_val & ~DF_BIND_NOW) == 0); > - /* Flags must not be set for ld.so. */ > +#endif > +#if defined RTLD_BOOTSTRAP || defined STATIC_PIE_BOOTSTRAP > assert (info[DT_RUNPATH] == NULL); > assert (info[DT_RPATH] == NULL); > #else > diff --git a/gmon/Makefile b/gmon/Makefile > index 89ab3fc7da..29e746723e 100644 > --- a/gmon/Makefile > +++ b/gmon/Makefile > @@ -39,6 +39,10 @@ tests-static += tst-gmon-static > ifeq (yesyes,$(have-fpie)$(build-shared)) > tests += tst-gmon-pie > tests-pie += tst-gmon-pie > +ifeq (yes,$(enable-static-pie)) > +tests += tst-gmon-static-pie > +tests-static += tst-gmon-static-pie OK. > +endif > endif > > # The mcount code won't work without a frame pointer. > @@ -54,7 +58,7 @@ endif > > CFLAGS-tst-gmon-static.c := $(PIE-ccflag) -fno-omit-frame-pointer -pg > CRT-tst-gmon-static := $(csu-objpfx)gcrt1.o > -DEFAULT-LDFLAGS-tst-gmon-static = $(no-pie-ldflag) > +tst-gmon-static-no-pie = yes > tst-gmon-static-ENV := GMON_OUT_PREFIX=$(objpfx)tst-gmon-static.data > ifeq ($(run-built-tests),yes) > tests-special += $(objpfx)tst-gmon-static-gprof.out > @@ -67,6 +71,15 @@ ifeq ($(run-built-tests),yes) > tests-special += $(objpfx)tst-gmon-pie-gprof.out > endif > > +ifeq (yes,$(enable-static-pie)) > +CFLAGS-tst-gmon-static-pie.c := $(PIE-ccflag) -fno-omit-frame-pointer -pg > +CRT-tst-gmon-static-pie := $(csu-objpfx)grcrt1.o > +tst-gmon-static-pie-ENV := GMON_OUT_PREFIX=$(objpfx)tst-gmon-static-pie.data > +ifeq ($(run-built-tests),yes) > +tests-special += $(objpfx)tst-gmon-static-pie-gprof.out > +endif > +endif OK. > + > > include ../Rules > > @@ -111,3 +124,13 @@ clean-tst-gmon-pie-data: > $(objpfx)tst-gmon-pie-gprof.out: tst-gmon-gprof.sh $(objpfx)tst-gmon-pie.out > $(SHELL) $< $(GPROF) $(objpfx)tst-gmon-pie $(objpfx)tst-gmon-pie.data.* > $@; \ > $(evaluate-test) > + > +$(objpfx)tst-gmon-static-pie.out: clean-tst-gmon-static-pie-data > +clean-tst-gmon-static-pie-data: > + rm -f $(objpfx)tst-gmon-static-pie.data.* > + > +$(objpfx)tst-gmon-static-pie-gprof.out: tst-gmon-static-gprof.sh \ > + $(objpfx)tst-gmon-static-pie.out > + $(SHELL) $< $(GPROF) $(objpfx)tst-gmon-static-pie \ > + $(objpfx)tst-gmon-static-pie.data.* > $@; \ > + $(evaluate-test) OK. > diff --git a/gmon/tst-gmon-static-pie.c b/gmon/tst-gmon-static-pie.c > new file mode 100644 > index 0000000000..1eef2583b6 > --- /dev/null > +++ b/gmon/tst-gmon-static-pie.c > @@ -0,0 +1 @@ > +#include "tst-gmon.c" > diff --git a/manual/install.texi b/manual/install.texi > index ea559e4e72..0efa8572df 100644 > --- a/manual/install.texi > +++ b/manual/install.texi > @@ -120,6 +120,15 @@ Don't build shared libraries even if it is possible. Not all systems > support shared libraries; you need ELF support and (currently) the GNU > linker. > > +@item --enable-static-pie > +Enable static position independent executable (static PIE) support. > +Static PIE is similar to static executable, but can be loaded at any > +address without help from a dynamic linker. All static programs as > +well as static tests are built as static PIE, except for those marked > +with no-pie. The resulting glibc can be used with the GCC option, > +-static-pie, which is available with GCC 8 or above, to create static > +PIE. OK. > + > @item --disable-profile > Don't build libraries with profiling information. You may want to use > this option if you don't plan to do profiling. > diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h > index 7a65dc641c..196513851f 100644 > --- a/sysdeps/generic/ldsodefs.h > +++ b/sysdeps/generic/ldsodefs.h > @@ -1051,6 +1051,17 @@ extern void _dl_determine_tlsoffset (void) attribute_hidden; > stack protector, among other things). */ > void __libc_setup_tls (void); > > +# if ENABLE_STATIC_PIE > +/* Relocate static executable with PIE. */ > +extern void _dl_relocate_static_pie (void) attribute_hidden; > + > +/* Get a pointer to _dl_main_map. */ > +extern struct link_map * _dl_get_dl_main_map (void) > + __attribute__ ((visibility ("hidden"))); > +# else > +# define _dl_relocate_static_pie() > +# endif > + > /* Initialization of libpthread for statically linked applications. > If libpthread is not linked in, this is an empty function. */ > void __pthread_initialize_minimal (void) weak_function; > diff --git a/sysdeps/i386/configure b/sysdeps/i386/configure > index 4cf968d8bc..90c63caf35 100644 [snip configure] > --- a/sysdeps/i386/configure.ac > +++ b/sysdeps/i386/configure.ac > @@ -30,6 +30,29 @@ LIBC_COMPILER_BUILTIN_INLINED( > *** Please use host i786, i686, i586, or i486. > *** For example: /source/glibc/configure CFLAGS='-O2 -march=i686' ...])]) > > +dnl Check if linker can convert "movl main@GOT(%ebx), %eax" to > +dnl "leal main@GOTOFF(%ebx), %eax" for static PIE. > +if test "$static_pie" = yes; then > + AC_CACHE_CHECK(for linker static PIE support, libc_cv_ld_static_pie, [dnl > +cat > conftest.s <<\EOF > + .text > + .global _start > +_start: > + movl _start@GOT(%ebx), %eax > +EOF > + libc_cv_pie_option="-Wl,-pie" > + libc_cv_ld_static_pie=no > + if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&AS_MESSAGE_LOG_FD); then > + if $READELF -r conftest | grep 'There are no relocations in this file.' > /dev/null; then > + libc_cv_ld_static_pie=yes > + fi > + fi > +rm -f conftest*]) > + if test "$libc_cv_ld_static_pie" != yes; then > + AC_MSG_ERROR([linker support for static PIE needed]) > + fi > +fi > + OK. > dnl Check whether asm supports Intel MPX > AC_CACHE_CHECK(for Intel MPX support, libc_cv_asm_mpx, [dnl > cat > conftest.s <<\EOF > diff --git a/sysdeps/mips/Makefile b/sysdeps/mips/Makefile > index fd891ddf09..7ac6fa5031 100644 > --- a/sysdeps/mips/Makefile > +++ b/sysdeps/mips/Makefile > @@ -23,6 +23,9 @@ CPPFLAGS-crtn.S += $(pic-ccflag) > endif > > ASFLAGS-.os += $(pic-ccflag) > +# libc.a and libc_p.a must be compiled with -fPIE/-fpie for static PIE. > +ASFLAGS-.o += $(pie-default) > +ASFLAGS-.op += $(pie-default) > > ifeq ($(subdir),elf) > ifneq ($(o32-fpabi),) > diff --git a/sysdeps/x86_64/configure b/sysdeps/x86_64/configure > index efef46b1b7..8674d14569 100644 [snip configure] > diff --git a/sysdeps/x86_64/configure.ac b/sysdeps/x86_64/configure.ac > index fa86e953ee..b7d2c0124f 100644 > --- a/sysdeps/x86_64/configure.ac > +++ b/sysdeps/x86_64/configure.ac > @@ -44,6 +44,31 @@ if test x"$build_mathvec" = xnotset; then > build_mathvec=yes > fi > > +dnl Check if linker supports static PIE with the fix for > +dnl > +dnl https://sourceware.org/bugzilla/show_bug.cgi?id=21782 > +dnl > +if test "$static_pie" = yes; then > + AC_CACHE_CHECK(for linker static PIE support, libc_cv_ld_static_pie, [dnl > +cat > conftest.s <<\EOF > + .text > + .global _start > + .weak foo > +_start: > + leaq foo(%rip), %rax > +EOF > + libc_cv_pie_option="-Wl,-pie" > + if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&AS_MESSAGE_LOG_FD); then > + libc_cv_ld_static_pie=yes > + else > + libc_cv_ld_static_pie=no > + fi > +rm -f conftest*]) > + if test "$libc_cv_ld_static_pie" != yes; then > + AC_MSG_ERROR([linker support for static PIE needed]) > + fi > +fi OK. > + > dnl It is always possible to access static and hidden symbols in an > dnl position independent way. > AC_DEFINE(PI_STATIC_AND_HIDDEN) > -- 2.14.3 -- Cheers, Carlos. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-12-15 21:19 ` Carlos O'Donell @ 2017-12-16 2:04 ` H.J. Lu 2017-12-16 3:06 ` Carlos O'Donell 2017-12-18 13:37 ` Joseph Myers 0 siblings, 2 replies; 37+ messages in thread From: H.J. Lu @ 2017-12-16 2:04 UTC (permalink / raw) To: Carlos O'Donell; +Cc: Szabolcs Nagy, nd, Joseph Myers, GNU C Library On Fri, Dec 15, 2017 at 1:19 PM, Carlos O'Donell <carlos@redhat.com> wrote: > On 12/01/2017 10:24 AM, H.J. Lu wrote: >> On Thu, Nov 30, 2017 at 1:44 PM, Carlos O'Donell <carlos@redhat.com> wrote: >>> H.J., >>> >>> High Level: >>> >>> At a high level I have no objection with the idea of static PIE executables, >>> it makes sense to support such things. >> Thanks for your feedbacks. > > Thank you for putting together a v2, sorry it took me a while to review. > > This version looks good to me, it cleans up the outstanding issues with the > implementation, and you have answered my questions about testing in the design. > The firstword hack is removed in the implementation and that was the only thing > that needed cleanup. > > Looks good to me. Please feel free to commit. Thanks for your time. I checked it in with the updated commit log. I also updated https://sourceware.org/glibc/wiki/PortStatus for static PIE status. Should build-many-glibcs.py be updated to also build static PIE for i386, x86_64 and x32? We can't build it by default since the recent linker is needed. -- H.J. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-12-16 2:04 ` H.J. Lu @ 2017-12-16 3:06 ` Carlos O'Donell 2017-12-18 13:37 ` Joseph Myers 1 sibling, 0 replies; 37+ messages in thread From: Carlos O'Donell @ 2017-12-16 3:06 UTC (permalink / raw) To: H.J. Lu, Joseph Myers; +Cc: Szabolcs Nagy, nd, GNU C Library On 12/15/2017 06:03 PM, H.J. Lu wrote: > On Fri, Dec 15, 2017 at 1:19 PM, Carlos O'Donell <carlos@redhat.com> wrote: >> On 12/01/2017 10:24 AM, H.J. Lu wrote: >>> On Thu, Nov 30, 2017 at 1:44 PM, Carlos O'Donell <carlos@redhat.com> wrote: >>>> H.J., >>>> >>>> High Level: >>>> >>>> At a high level I have no objection with the idea of static PIE executables, >>>> it makes sense to support such things. >>> Thanks for your feedbacks. >> >> Thank you for putting together a v2, sorry it took me a while to review. >> >> This version looks good to me, it cleans up the outstanding issues with the >> implementation, and you have answered my questions about testing in the design. >> The firstword hack is removed in the implementation and that was the only thing >> that needed cleanup. >> >> Looks good to me. Please feel free to commit. > > Thanks for your time. I checked it in with the updated commit log. > I also updated > > https://sourceware.org/glibc/wiki/PortStatus > > for static PIE status. Should build-many-glibcs.py be updated to also > build static > PIE for i386, x86_64 and x32? We can't build it by default since the > recent linker > is needed. It couldn't hurt to enable an extra build for i386, x86_64, and x32 with static PIE, that way we get better coverage. However, I defer this decision to Joseph Myers, if he thinks this would add value without adding too much cost to the build, then I'm happy to see it enabled. Personally I think static PIE should *always* be used since it hardens static executables in ways which are useful. Static executables should be special tools which are always present on the system, and hardening them from attack is important. -- Cheers, Carlos. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-12-16 2:04 ` H.J. Lu 2017-12-16 3:06 ` Carlos O'Donell @ 2017-12-18 13:37 ` Joseph Myers 2017-12-19 1:14 ` H.J. Lu 1 sibling, 1 reply; 37+ messages in thread From: Joseph Myers @ 2017-12-18 13:37 UTC (permalink / raw) To: H.J. Lu; +Cc: Carlos O'Donell, Szabolcs Nagy, nd, GNU C Library On Sat, 16 Dec 2017, H.J. Lu wrote: > Thanks for your time. I checked it in with the updated commit log. > I also updated > > https://sourceware.org/glibc/wiki/PortStatus That's missing key information: * It needs a complete list of architectures that have not yet been verified to work with static PIE. Architectures would then be removed from that list one at a time as and when someone verifies them to work and commits any fixes needed (and if the list becomes empty, the whole section of the wiki page could be removed at that point). * It needs instructions on how to test whether static PIE works for an architecture (or architecture/ABI pair, if appropriate). Is this "configure --enable-static-pie and make sure test results are as good as without that option", or "configure --enable-static-pie and make sure tests X, Y and Z pass", or doing one of those but additionally using GCC 8 or later so -static-pie is supported, or something else? This needs to be on the wiki page so it's completely clear how someone can test the feature for an architecture and have confidence in whether it's working. When new ports are submitted for glibc, you should then seek confirmation of whether they work with static-PIE, as if they don't and get added to glibc without such support, they'd need to be added to the list on the wiki page. > for static PIE status. Should build-many-glibcs.py be updated to also > build static PIE for i386, x86_64 and x32? We can't build it by default > since the recent linker is needed. A few additional builds for configurations where all the GCC / binutils / glibc support required is present would be a good idea (but maybe not if enough support isn't present in the default versions used by build-many-glibcs.py, which means GCC 7 branch and binutils 2.29 branch). -- Joseph S. Myers joseph@codesourcery.com ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] 2017-12-18 13:37 ` Joseph Myers @ 2017-12-19 1:14 ` H.J. Lu 0 siblings, 0 replies; 37+ messages in thread From: H.J. Lu @ 2017-12-19 1:14 UTC (permalink / raw) To: Joseph Myers; +Cc: Carlos O'Donell, Szabolcs Nagy, nd, GNU C Library On Mon, Dec 18, 2017 at 5:37 AM, Joseph Myers <joseph@codesourcery.com> wrote: > On Sat, 16 Dec 2017, H.J. Lu wrote: > >> Thanks for your time. I checked it in with the updated commit log. >> I also updated >> >> https://sourceware.org/glibc/wiki/PortStatus > > That's missing key information: > > * It needs a complete list of architectures that have not yet been > verified to work with static PIE. Architectures would then be removed > from that list one at a time as and when someone verifies them to work and > commits any fixes needed (and if the list becomes empty, the whole > section of the wiki page could be removed at that point). Done. > * It needs instructions on how to test whether static PIE works for an > architecture (or architecture/ABI pair, if appropriate). Is this > "configure --enable-static-pie and make sure test results are as good as > without that option", or "configure --enable-static-pie and make sure > tests X, Y and Z pass", or doing one of those but additionally using GCC 8 > or later so -static-pie is supported, or something else? This needs to be > on the wiki page so it's completely clear how someone can test the feature > for an architecture and have confidence in whether it's working. Only need to add --enable-static-pie to glibc configure to enable static PIE, which is in INSTALL. The test results should be identical with or without --enable-static-pie. > When new ports are submitted for glibc, you should then seek confirmation > of whether they work with static-PIE, as if they don't and get added to > glibc without such support, they'd need to be added to the list on the > wiki page. > >> for static PIE status. Should build-many-glibcs.py be updated to also >> build static PIE for i386, x86_64 and x32? We can't build it by default >> since the recent linker is needed. > > A few additional builds for configurations where all the GCC / binutils / > glibc support required is present would be a good idea (but maybe not if > enough support isn't present in the default versions used by > build-many-glibcs.py, which means GCC 7 branch and binutils 2.29 branch). GCC 7 branch and binutils 2.29 branch support static PIE on x86. The patch is at: https://sourceware.org/ml/libc-alpha/2017-12/msg00614.html -- H.J. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574]
@ 2017-12-15 11:58 H.J. Lu
0 siblings, 0 replies; 37+ messages in thread
From: H.J. Lu @ 2017-12-15 11:58 UTC (permalink / raw)
To: Carlos O'Donell; +Cc: Szabolcs Nagy, nd, Joseph Myers, GNU C Library
On Fri, Dec 8, 2017 at 5:14 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Fri, Dec 1, 2017 at 10:24 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
>> On Thu, Nov 30, 2017 at 1:44 PM, Carlos O'Donell <carlos@redhat.com> wrote:
>>> H.J.,
>>>
>>> High Level:
>>>
>>> At a high level I have no objection with the idea of static PIE executables,
>>> it makes sense to support such things.
>>
>> Thanks for your feedbacks.
>>
>>> My only nit is that we need to do a better job of explaining to users why
>>> they would use them and under what circumstances. To that end you have a bit
>>> more work to do in the commit message, install.texit, and NEWS entry.
>>>
>>> Design:
>>>
>>> I have one design question below which around testing static non-PIE executables
>>> in a --enable-static-pie build. See below.
>>>
>>> Implementation:
>>>
>>> Everything looks good except the use of firstword in +link-static-before-libc,
>>> which I describe below. I think this is a hack and should be changed to better
>>> represent the expected semantics and structure you are looking to support.
>>
>> Fixed.
>>
>>> Thank you for your work in this area.
>>>
>>> Look forward to a v2.
>>>
>>>> From 7026a79c1f71f5decd135208503fd4186193ffb8 Mon Sep 17 00:00:00 2001
>>>> From: "H.J. Lu" <hjl.tools@gmail.com>
>>>> Date: Mon, 17 Jul 2017 08:17:32 -0700
>>>> Subject: [PATCH] Add --enable-static-pie configure option to build static PIE
>>>> [BZ #19574]
>>>>
>>>> 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.
>>>
>>> You write "which are allowed", shouldn't that be "which are not allowed"?
>>
>> Fixed.
>>
>>> The commit message must explain the following:
>>>
>>> * Why would a user use this feature?
>>> - What does it provide over and beyond existing static executables
>>>
>>> * How does a user decide to use this feature?
>>> - Should everyone use it?
>>> - Should you use it if you care about security, and what does it cost?
>>>
>>> Please include the answers to these questions in a the next versions
>>> commit message.
>>
>> I added :
>>
>> Static PIE extends address space layout randomization to static
>> executables. It provides additional security hardening benefits at
>> the cost of some memory and performance.
>>
>> Is this OK?
>>
>>>> @@ -420,7 +440,7 @@ endif
>>>> # Command for statically linking programs with the C library.
>>>> ifndef +link-static
>>>> +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \
>>>> - $(DEFAULT-LDFLAGS-$(@F)) \
>>>> + $(firstword $(DEFAULT-LDFLAGS-$(@F)) $(default-pie-ldflag)) \
>>>
>>> Is the use of firstword here just a hack to put $(no-pie-ldflag) first so
>>> you can override it with the subsequent $(default-pie-ldflag)?
>>>
>>> It is not a robust design to use firstword here because it implies that the
>>> DEFAUTL-LDFLAGS-$(@F) has some structure that we are not documenting.
>>>
>>> I would like to see this done some other way. My preference would be for a new
>>> value other than DEFAULT-LDFLAGS to control the PIE-ness of the built progarm.
>>>
>>
>> I replaced DEFAUTL-LDFLAGS-$(@F) with $($(@F)-no-pie). Now I have
>>
>> # Command for statically linking programs with the C library.
>> ifndef +link-static
>> +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \
>> - $(DEFAULT-LDFLAGS-$(@F)) \
>> + $(if $($(@F)-no-pie),$(no-pie-ldflag),$(default-pie-ldflag)) \
>> $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \
>>
>>>>
>>>> diff --git a/NEWS b/NEWS
>>>> index ab14d1eb1b..61598be94d 100644
>>>> --- a/NEWS
>>>> +++ b/NEWS
>>>> @@ -9,6 +9,11 @@ Version 2.27
>>>>
>>>> Major new features:
>>>>
>>>> +* Add --enable-static-pie configure option to build static PIE. The
>>>> + resulting libc.a can be used with the GCC option, -static-pie, which
>>>> + is available with GCC 8 or above, to create static position independent
>>>> + executable (static PIE).
>>>> +
>>>
>>> The description of a new configure option is relevant only to INSTALL.
>>>
>>> We must explain when users would use this feature and why. NEWS entries are
>>> user facing and must explain the function of the new feature. Does it improve
>>> security for static binaries? Should users switch to using them instead of
>>> normal static binaries?
>>>
>>> Lastly, we must explain which machines are supported in this initial release
>>> of the feature. Only x86_64? You need not check all machines, other maintainers
>>> can check and adjust the NEWS entry, but we have to commit to at least one
>>> machine supporting this feature, which I assume is x86_64.
>>>
>>> For example:
>>>
>>> * The GNU C Library can now be compiled with support for building static
>>> PIE executables (See --enable-static-pie in INSTALL). These static PIE
>>> exectuables are like static executables but can be loaded at any address
>>> and provide additional security hardening benefits at the cost of some
>>> memory and performance. When the library is built with --enable-static-pie
>>> the resulting libc.a is usable with GCC 8 and above to create static PIE
>>> executables using the GCC option '-static-pie'. This feature is currently
>>> supported on x86_64.
>>>
>>
>> I took your example. Thanks.
>>
>>>
>>>> diff --git a/configure.ac b/configure.ac
>>>> index 8ebc490a55..ae219f8fe0 100644
>>>> --- a/configure.ac
>>>> +++ b/configure.ac
>>>> @@ -176,6 +176,11 @@ AC_ARG_ENABLE([profile],
>>>> [build profiled library @<:@default=no@:>@]),
>>>> [profile=$enableval],
>>>> [profile=no])
>>>> +AC_ARG_ENABLE([static-pie],
>>>> + AC_HELP_STRING([--enable-static-pie],
>>>> + [build static executables as PIE @<:@default=no@:>@]),
>>>
>>> This does 2 things:
>>> * It enables support for building static PIE executables.
>>> * It builds all static binaries and tests in the testsuite as static PIE executables.
>>>
>>> It should say that e.g.
>>>
>>> "Enable static PIE executable support and use it in the testsuite."
>>>
>>> I understand the desire to use such a functionality to test static PIE executables
>>> by converting the entire testsuite to use them, but we still need to test non-PIE
>>> static executables? How are we still doing that after this change?
>>>
>>> How are we testing non-PIE static executables after this change?
>>
>> This is similar to PIE vs non-PIE. When you build glibc with GCC
>> defaulting to PIE, most of dynamic tests are built as PIE, except for
>> a couple of them linked with $(no-pie-ldflag). I added
>>
>> elf/tst-tls1-static-non-pie.c
>>
>> which is always built as non-PIE static executable, regardless if
>> --enable-static-pie is used to configure glibc.
>>
>> To get better coverage for non-PIE, we need to build glibc with GCC
>> defaulting to non-PIE and configure glibc without --enable-static-pie.
>>
>>>> diff --git a/manual/install.texi b/manual/install.texi
>>>> index f1fa28c937..86193ade3f 100644
>>>> --- a/manual/install.texi
>>>> +++ b/manual/install.texi
>>>> @@ -120,6 +120,13 @@ Don't build shared libraries even if it is possible. Not all systems
>>>> support shared libraries; you need ELF support and (currently) the GNU
>>>> linker.
>>>>
>>>> +@item --enable-static-pie
>>>
>>> This should be rewritten to explain the feature that it enables first,
>>> and then the ancilliary benefits like turning it on in the testsuite.
>>>
>>>> +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.
>>>> +
>>
>> I changed it to
>>
>> '--enable-static-pie'
>> Enable static position independent executable (static PIE) support.
>> Static PIE is similar to static executable, but can be loaded at
>> any address without help from a dynamic linker. All static
>> programs as well as static tests are built as static PIE, except
>> for those marked with no-pie. The resulting glibc can be used with
>> the GCC option, -static-pie, which is available with GCC 8 or
>> above, to create static PIE.
>>
>> Here is the updated patch.
>>
>> Using GCC 7 and binutils master branch, build-many-glibcs.py with
>> --enable-static-pie with all patches for static PIE applied have the
>> following build successes:
>>
>> PASS: glibcs-aarch64_be-linux-gnu build
>> PASS: glibcs-aarch64-linux-gnu build
>> PASS: glibcs-armeb-linux-gnueabi-be8 build
>> PASS: glibcs-armeb-linux-gnueabi build
>> PASS: glibcs-armeb-linux-gnueabihf-be8 build
>> PASS: glibcs-armeb-linux-gnueabihf build
>> PASS: glibcs-arm-linux-gnueabi build
>> PASS: glibcs-arm-linux-gnueabihf build
>> PASS: glibcs-arm-linux-gnueabihf-v7a build
>> PASS: glibcs-arm-linux-gnueabihf-v7a-disable-multi-arch build
>> PASS: glibcs-m68k-linux-gnu build
>> PASS: glibcs-microblazeel-linux-gnu build
>> PASS: glibcs-microblaze-linux-gnu build
>> PASS: glibcs-mips64el-linux-gnu-n32 build
>> PASS: glibcs-mips64el-linux-gnu-n32-nan2008 build
>> PASS: glibcs-mips64el-linux-gnu-n32-nan2008-soft build
>> PASS: glibcs-mips64el-linux-gnu-n32-soft build
>> PASS: glibcs-mips64el-linux-gnu-n64 build
>> PASS: glibcs-mips64el-linux-gnu-n64-nan2008 build
>> PASS: glibcs-mips64el-linux-gnu-n64-nan2008-soft build
>> PASS: glibcs-mips64el-linux-gnu-n64-soft build
>> PASS: glibcs-mips64-linux-gnu-n32 build
>> PASS: glibcs-mips64-linux-gnu-n32-nan2008 build
>> PASS: glibcs-mips64-linux-gnu-n32-nan2008-soft build
>> PASS: glibcs-mips64-linux-gnu-n32-soft build
>> PASS: glibcs-mips64-linux-gnu-n64 build
>> PASS: glibcs-mips64-linux-gnu-n64-nan2008 build
>> PASS: glibcs-mips64-linux-gnu-n64-nan2008-soft build
>> PASS: glibcs-mips64-linux-gnu-n64-soft build
>> PASS: glibcs-mipsel-linux-gnu build
>> PASS: glibcs-mipsel-linux-gnu-nan2008 build
>> PASS: glibcs-mipsel-linux-gnu-nan2008-soft build
>> PASS: glibcs-mipsel-linux-gnu-soft build
>> PASS: glibcs-mips-linux-gnu build
>> PASS: glibcs-mips-linux-gnu-nan2008 build
>> PASS: glibcs-mips-linux-gnu-nan2008-soft build
>> PASS: glibcs-mips-linux-gnu-soft build
>> PASS: glibcs-nios2-linux-gnu build
>> PASS: glibcs-powerpc64le-linux-gnu build
>> PASS: glibcs-powerpc64-linux-gnu build
>> PASS: glibcs-tilegxbe-linux-gnu-32 build
>> PASS: glibcs-tilegxbe-linux-gnu build
>> PASS: glibcs-tilegx-linux-gnu-32 build
>> PASS: glibcs-tilegx-linux-gnu build
>> PASS: glibcs-tilepro-linux-gnu build
>>
>> I don't know how many of them actually work, except for aarch64.
>>
>> Thanks.
>>
>
> Hi Carlos,
>
> Do you get a chance to take a look
>
> https://sourceware.org/ml/libc-alpha/2017-12/msg00033.html
>
PING.
--
H.J.
^ permalink raw reply [flat|nested] 37+ messages in thread
end of thread, other threads:[~2017-12-19 1:14 UTC | newest] Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2017-11-01 12:46 PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574] H.J. Lu 2017-11-01 16:04 ` Joseph Myers 2017-11-01 16:06 ` H.J. Lu 2017-11-03 17:57 ` H.J. Lu 2017-11-19 2:40 ` H.J. Lu 2017-11-19 15:39 ` Florian Weimer 2017-11-19 16:17 ` H.J. Lu 2017-11-19 19:52 ` H.J. Lu 2017-11-20 14:17 ` Joseph Myers 2017-11-23 14:09 ` H.J. Lu 2017-11-20 12:16 ` Szabolcs Nagy 2017-11-23 13:59 ` H.J. Lu 2017-11-24 13:07 ` Szabolcs Nagy 2017-11-24 15:03 ` H.J. Lu 2017-11-24 22:24 ` H.J. Lu 2017-11-30 14:00 ` H.J. Lu 2017-11-30 15:28 ` Joseph Myers 2017-11-30 16:24 ` H.J. Lu 2017-11-30 16:37 ` Joseph Myers 2017-11-30 16:56 ` H.J. Lu 2017-11-30 18:45 ` Carlos O'Donell 2017-11-30 21:45 ` Carlos O'Donell 2017-11-30 22:37 ` Maciej W. Rozycki [not found] ` <CAMe9rOpDRknZANuSvXAqU_qaXzGRjt=uY5BZLJoE_o9Ke+9yfw@mail.gmail.com> [not found] ` <alpine.DEB.2.00.1711302308170.31156@tp.orcam.me.uk> 2017-12-01 1:08 ` H.J. Lu 2017-12-01 1:58 ` Maciej W. Rozycki 2017-12-01 4:18 ` H.J. Lu 2017-12-01 9:59 ` Maciej W. Rozycki 2017-12-01 12:27 ` Joseph Myers 2017-12-01 13:35 ` H.J. Lu 2017-12-01 18:24 ` H.J. Lu 2017-12-08 13:14 ` H.J. Lu 2017-12-15 21:19 ` Carlos O'Donell 2017-12-16 2:04 ` H.J. Lu 2017-12-16 3:06 ` Carlos O'Donell 2017-12-18 13:37 ` Joseph Myers 2017-12-19 1:14 ` H.J. Lu 2017-12-15 11:58 H.J. Lu
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).