Add --enable-static-pie configure option to build static PIE [BZ #19574]

Static PIE extends address space layout randomization to static
executables.  It provides additional security hardening benefits at
the cost of some memory and performance.

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.

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 address 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.
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.
5. elf_machine_load_address in dl-machine.h are updated to support static
PIE.
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 whether 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.
This commit is contained in:
H.J. Lu 2017-12-15 16:59:33 -08:00
parent 95511aab9d
commit 9d7a3741c9
25 changed files with 521 additions and 17 deletions

View File

@ -1,3 +1,75 @@
2017-12-15 H.J. Lu <hongjiu.lu@intel.com>
[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.
2017-12-15 Joseph Myers <joseph@codesourcery.com> 2017-12-15 Joseph Myers <joseph@codesourcery.com>
* io/Makefile (tst-open-tmpfile-ARGS): New variable. * io/Makefile (tst-open-tmpfile-ARGS): New variable.

View File

@ -86,6 +86,15 @@ will be used, and CFLAGS sets optimization options for the compiler.
systems support shared libraries; you need ELF support and systems support shared libraries; you need ELF support and
(currently) the GNU linker. (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' '--disable-profile'
Don't build libraries with profiling information. You may want to Don't build libraries with profiling information. You may want to
use this option if you don't plan to do profiling. use this option if you don't plan to do profiling.

View File

@ -352,6 +352,14 @@ ifndef static-start-installed-name
static-start-installed-name = $(start-installed-name) static-start-installed-name = $(start-installed-name)
endif 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)) ifeq (yesyes,$(build-shared)$(have-z-combreloc))
combreloc-LDFLAGS = -Wl,-z,combreloc combreloc-LDFLAGS = -Wl,-z,combreloc
LDFLAGS.so += $(combreloc-LDFLAGS) LDFLAGS.so += $(combreloc-LDFLAGS)
@ -371,6 +379,20 @@ LDFLAGS.so += $(hashstyle-LDFLAGS)
LDFLAGS-rtld += $(hashstyle-LDFLAGS) LDFLAGS-rtld += $(hashstyle-LDFLAGS)
endif 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 # If lazy relocations are disabled, add the -z now flag. Use
# LDFLAGS-lib.so instead of LDFLAGS.so, to avoid adding the flag to # LDFLAGS-lib.so instead of LDFLAGS.so, to avoid adding the flag to
# test modules. # test modules.
@ -420,9 +442,9 @@ endif
# Command for statically linking programs with the C library. # Command for statically linking programs with the C library.
ifndef +link-static ifndef +link-static
+link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \ +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)) \ $(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) \ $(+preinit) $(+prectorT) \
$(filter-out $(addprefix $(csu-objpfx),start.o \ $(filter-out $(addprefix $(csu-objpfx),start.o \
$(start-installed-name))\ $(start-installed-name))\
@ -637,8 +659,14 @@ endif
+prectorS = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtbeginS.o` +prectorS = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtbeginS.o`
+postctorS = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtendS.o` +postctorS = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtendS.o`
# Variants of the two previous definitions for statically linking programs. # 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` +prectorT = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtbeginT.o`
+postctorT = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtend.o` +postctorT = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtend.o`
endif
csu-objpfx = $(common-objpfx)csu/ csu-objpfx = $(common-objpfx)csu/
elf-objpfx = $(common-objpfx)elf/ elf-objpfx = $(common-objpfx)elf/
@ -959,7 +987,8 @@ libtypes = $(foreach o,$(object-suffixes-for-libc),$(libtype$o))
all-object-suffixes := .o .os .oS all-object-suffixes := .o .os .oS
object-suffixes := object-suffixes :=
CPPFLAGS-.o = $(pic-default) 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 libtype.o := lib%.a
object-suffixes += .o object-suffixes += .o
ifeq (yes,$(build-shared)) ifeq (yes,$(build-shared))
@ -984,7 +1013,8 @@ ifeq (yes,$(build-profile))
all-object-suffixes += .op all-object-suffixes += .op
object-suffixes += .op object-suffixes += .op
CPPFLAGS-.op = -DPROF $(pic-default) 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 libtype.op = lib%_p.a
endif endif

9
NEWS
View File

@ -9,6 +9,15 @@ Version 2.27
Major new features: 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, cosf, * Optimized x86-64 asin, atan2, exp, expf, log, pow, atan, sin, cosf,
sinf and tan with FMA, contributed by Arjan van de Ven and H.J. Lu sinf and tan with FMA, contributed by Arjan van de Ven and H.J. Lu
from Intel. from Intel.

View File

@ -238,6 +238,9 @@
/* Build glibc with tunables support. */ /* Build glibc with tunables support. */
#define HAVE_TUNABLES 0 #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 /* Some compiler options may now allow to use ebp in __asm__ (used mainly
in i386 6 argument syscall issue). */ in i386 6 argument syscall issue). */
#define CAN_USE_REGISTER_ASM_EBP 0 #define CAN_USE_REGISTER_ASM_EBP 0

79
configure vendored
View File

@ -763,6 +763,7 @@ with_default_link
enable_sanity_checks enable_sanity_checks
enable_shared enable_shared
enable_profile enable_profile
enable_static_pie
enable_timezone_tools enable_timezone_tools
enable_hardcoded_path_in_tests enable_hardcoded_path_in_tests
enable_stackguard_randomization enable_stackguard_randomization
@ -1417,6 +1418,8 @@ Optional Features:
in special situations) [default=yes] in special situations) [default=yes]
--enable-shared build shared library [default=yes if GNU ld] --enable-shared build shared library [default=yes if GNU ld]
--enable-profile build profiled library [default=no] --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 --disable-timezone-tools
do not install timezone tools [default=install] do not install timezone tools [default=install]
--enable-hardcoded-path-in-tests --enable-hardcoded-path-in-tests
@ -3350,6 +3353,13 @@ else
profile=no profile=no
fi 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. # Check whether --enable-timezone-tools was given.
if test "${enable_timezone_tools+set}" = set; then : if test "${enable_timezone_tools+set}" = set; then :
enableval=$enable_timezone_tools; enable_timezone_tools=$enableval enableval=$enable_timezone_tools; enable_timezone_tools=$enableval
@ -5806,6 +5816,62 @@ fi
$as_echo "$libc_linker_feature" >&6; } $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 "$as_me:${as_lineno-$LINENO}: checking for -fpie" >&5
$as_echo_n "checking for -fpie... " >&6; } $as_echo_n "checking for -fpie... " >&6; }
if ${libc_cv_fpie+:} false; then : if ${libc_cv_fpie+:} false; then :
@ -6705,6 +6771,19 @@ $as_echo "$libc_cv_pie_default" >&6; }
libc_cv_multidir=`${CC-cc} $CFLAGS $CPPFLAGS -print-multi-directory` 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"

View File

@ -170,6 +170,11 @@ AC_ARG_ENABLE([profile],
[build profiled library @<:@default=no@:>@]), [build profiled library @<:@default=no@:>@]),
[profile=$enableval], [profile=$enableval],
[profile=no]) [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_ARG_ENABLE([timezone-tools],
AC_HELP_STRING([--disable-timezone-tools], AC_HELP_STRING([--disable-timezone-tools],
[do not install timezone tools @<:@default=install@:>@]), [do not install timezone tools @<:@default=install@:>@]),
@ -1287,6 +1292,19 @@ LIBC_LINKER_FEATURE([-z execstack], [-Wl,-z,execstack],
[libc_cv_z_execstack=yes], [libc_cv_z_execstack=no]) [libc_cv_z_execstack=yes], [libc_cv_z_execstack=no])
AC_SUBST(libc_cv_z_execstack) 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 AC_CACHE_CHECK(for -fpie, libc_cv_fpie, [dnl
LIBC_TRY_CC_OPTION([-fpie], [libc_cv_fpie=yes], [libc_cv_fpie=no]) LIBC_TRY_CC_OPTION([-fpie], [libc_cv_fpie=yes], [libc_cv_fpie=no])
]) ])
@ -1794,6 +1812,17 @@ AC_SUBST(libc_cv_pie_default)
libc_cv_multidir=`${CC-cc} $CFLAGS $CPPFLAGS -print-multi-directory` libc_cv_multidir=`${CC-cc} $CFLAGS $CPPFLAGS -print-multi-directory`
AC_SUBST(libc_cv_multidir) 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(profile)
AC_SUBST(static_nss) AC_SUBST(static_nss)

View File

@ -37,7 +37,9 @@ extra-objs = start.o \
S$(start-installed-name) S$(start-installed-name)
omit-deps = $(patsubst %.o,%,$(start-installed-name) g$(start-installed-name) \ omit-deps = $(patsubst %.o,%,$(start-installed-name) g$(start-installed-name) \
b$(start-installed-name) $(csu-dummies) \ 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) install-lib = $(start-installed-name) g$(start-installed-name) $(csu-dummies)
# No tests are allowed in the csu/ subdirectory because the startup # No tests are allowed in the csu/ subdirectory because the startup
@ -60,10 +62,17 @@ extra-objs += gmon-start.o
endif endif
ifneq ($(start-installed-name),$(static-start-installed-name)) 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) extra-objs += $(static-start-installed-name) g$(static-start-installed-name)
omit-deps += $(patsubst %.o,%,$(static-start-installed-name) \ omit-deps += $(patsubst %.o,%,$(static-start-installed-name) \
g$(static-start-installed-name)) g$(static-start-installed-name))
install-lib += $(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 endif
before-compile += $(objpfx)abi-tag.h before-compile += $(objpfx)abi-tag.h
@ -82,7 +91,10 @@ multilib-extra-objs = $(addprefix $(multidir)/, $(install-lib))
extra-objs += $(multilib-extra-objs) extra-objs += $(multilib-extra-objs)
endif 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). asm-CPPFLAGS += -I$(objpfx).
# Enable unwinding so backtrace unwinds to __libc_start_main # 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 # We link the ELF startfile along with a SHT_NOTE section indicating
# the kernel ABI the binaries linked with this library will require. # the kernel ABI the binaries linked with this library will require.
$(objpfx)$(start-installed-name): $(objpfx)start.o $(objpfx)abi-note.o \ $(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 $(objpfx)init.o
$(link-relocatable) $(link-relocatable)
$(objpfx)S$(start-installed-name): $(objpfx)start.os $(objpfx)abi-note.o \ $(objpfx)S$(start-installed-name): $(objpfx)start.os $(objpfx)abi-note.o \
@ -113,7 +128,10 @@ endif
# to turn on profiling code at startup. # to turn on profiling code at startup.
ifeq (yes,$(build-shared)) ifeq (yes,$(build-shared))
$(objpfx)g$(start-installed-name): \ $(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) $(link-relocatable)
ifneq ($(start-installed-name),$(static-start-installed-name)) ifneq ($(start-installed-name),$(static-start-installed-name))
$(objpfx)g$(static-start-installed-name): \ $(objpfx)g$(static-start-installed-name): \

View File

@ -141,6 +141,8 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
__libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up; __libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up;
#ifndef SHARED #ifndef SHARED
_dl_relocate_static_pie ();
char **ev = &argv[argc + 1]; char **ev = &argv[argc + 1];
__environ = ev; __environ = ev;

View File

@ -114,6 +114,8 @@ __libc_setup_tls (void)
size_t tcb_offset; size_t tcb_offset;
const ElfW(Phdr) *phdr; 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. */ /* Look through the TLS segment if there is any. */
if (_dl_phdr != NULL) if (_dl_phdr != NULL)
for (phdr = _dl_phdr; phdr < &_dl_phdr[_dl_phnum]; ++phdr) for (phdr = _dl_phdr; phdr < &_dl_phdr[_dl_phnum]; ++phdr)
@ -122,7 +124,7 @@ __libc_setup_tls (void)
/* Remember the values we need. */ /* Remember the values we need. */
memsz = phdr->p_memsz; memsz = phdr->p_memsz;
filesz = phdr->p_filesz; filesz = phdr->p_filesz;
initimage = (void *) phdr->p_vaddr; initimage = (void *) phdr->p_vaddr + main_map->l_addr;
align = phdr->p_align; align = phdr->p_align;
if (phdr->p_align > max_align) if (phdr->p_align > max_align)
max_align = phdr->p_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[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 // _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. */ /* Initialize the TLS block. */
#if TLS_TCB_AT_TP #if TLS_TCB_AT_TP
_dl_static_dtv[2].pointer.val = ((char *) tlsblock + tcb_offset _dl_static_dtv[2].pointer.val = ((char *) tlsblock + tcb_offset

26
csu/static-reloc.c Normal file
View File

@ -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

View File

@ -24,7 +24,8 @@ include ../Makeconfig
headers = elf.h bits/elfclass.h link.h bits/link.h headers = elf.h bits/elfclass.h link.h bits/link.h
routines = $(all-dl-routines) dl-support dl-iteratephdr \ routines = $(all-dl-routines) dl-support dl-iteratephdr \
dl-addr dl-addr-obj enbl-secure dl-profstub \ 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 # The core dynamic linking functions are in libc for the static and
# profiled libraries. # profiled libraries.
@ -52,7 +53,7 @@ endif
all-dl-routines = $(dl-routines) $(sysdep-dl-routines) all-dl-routines = $(dl-routines) $(sysdep-dl-routines)
# But they are absent from the shared libc, because that code is in ld.so. # 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 \ 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 shared-only-routines += dl-caller
# ld.so uses those routines, plus some special stuff for being the program # 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 tst-tls1-static-non-pie
CRT-tst-tls1-static-non-pie := $(csu-objpfx)crt1.o 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 \ tests := tst-tls9 tst-leaks1 \
tst-array1 tst-array2 tst-array3 tst-array4 tst-array5 \ tst-array1 tst-array2 tst-array3 tst-array4 tst-array5 \

52
elf/dl-reloc-static-pie.c Normal file
View File

@ -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

View File

@ -385,3 +385,14 @@ _dl_non_dynamic_init (void)
#ifdef DL_SYSINFO_IMPLEMENTATION #ifdef DL_SYSINFO_IMPLEMENTATION
DL_SYSINFO_IMPLEMENTATION DL_SYSINFO_IMPLEMENTATION
#endif #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

View File

@ -94,7 +94,7 @@ elf_machine_lazy_rel (struct link_map *map,
#ifdef RESOLVE_MAP #ifdef RESOLVE_MAP
# ifdef RTLD_BOOTSTRAP # if defined RTLD_BOOTSTRAP || defined STATIC_PIE_BOOTSTRAP
# define ELF_DURING_STARTUP (1) # define ELF_DURING_STARTUP (1)
# else # else
# define ELF_DURING_STARTUP (0) # define ELF_DURING_STARTUP (0)

View File

@ -38,7 +38,7 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
typedef Elf64_Xword d_tag_utype; typedef Elf64_Xword d_tag_utype;
#endif #endif
#ifndef RTLD_BOOTSTRAP #if !defined RTLD_BOOTSTRAP && !defined STATIC_PIE_BOOTSTRAP
if (dyn == NULL) if (dyn == NULL)
return; return;
#endif #endif
@ -139,9 +139,11 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
/* Only the bind now flags are allowed. */ /* Only the bind now flags are allowed. */
assert (info[VERSYMIDX (DT_FLAGS_1)] == NULL assert (info[VERSYMIDX (DT_FLAGS_1)] == NULL
|| (info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val & ~DF_1_NOW) == 0); || (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 assert (info[DT_FLAGS] == NULL
|| (info[DT_FLAGS]->d_un.d_val & ~DF_BIND_NOW) == 0); || (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_RUNPATH] == NULL);
assert (info[DT_RPATH] == NULL); assert (info[DT_RPATH] == NULL);
#else #else

View File

@ -39,6 +39,10 @@ tests-static += tst-gmon-static
ifeq (yesyes,$(have-fpie)$(build-shared)) ifeq (yesyes,$(have-fpie)$(build-shared))
tests += tst-gmon-pie tests += tst-gmon-pie
tests-pie += 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 endif
# The mcount code won't work without a frame pointer. # 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 CFLAGS-tst-gmon-static.c := $(PIE-ccflag) -fno-omit-frame-pointer -pg
CRT-tst-gmon-static := $(csu-objpfx)gcrt1.o 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 tst-gmon-static-ENV := GMON_OUT_PREFIX=$(objpfx)tst-gmon-static.data
ifeq ($(run-built-tests),yes) ifeq ($(run-built-tests),yes)
tests-special += $(objpfx)tst-gmon-static-gprof.out 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 tests-special += $(objpfx)tst-gmon-pie-gprof.out
endif 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 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 $(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.* > $@; \ $(SHELL) $< $(GPROF) $(objpfx)tst-gmon-pie $(objpfx)tst-gmon-pie.data.* > $@; \
$(evaluate-test) $(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)

View File

@ -0,0 +1 @@
#include "tst-gmon.c"

View File

@ -116,6 +116,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 support shared libraries; you need ELF support and (currently) the GNU
linker. 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 @item --disable-profile
Don't build libraries with profiling information. You may want to use Don't build libraries with profiling information. You may want to use
this option if you don't plan to do profiling. this option if you don't plan to do profiling.

View File

@ -1051,6 +1051,17 @@ extern void _dl_determine_tlsoffset (void) attribute_hidden;
stack protector, among other things). */ stack protector, among other things). */
void __libc_setup_tls (void); 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. /* Initialization of libpthread for statically linked applications.
If libpthread is not linked in, this is an empty function. */ If libpthread is not linked in, this is an empty function. */
void __pthread_initialize_minimal (void) weak_function; void __pthread_initialize_minimal (void) weak_function;

View File

@ -50,6 +50,39 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_compiler_builtin_inlined" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_compiler_builtin_inlined" >&5
$as_echo "$libc_compiler_builtin_inlined" >&6; } $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 "$as_me:${as_lineno-$LINENO}: checking for Intel MPX support" >&5
$as_echo_n "checking for Intel MPX support... " >&6; } $as_echo_n "checking for Intel MPX support... " >&6; }
if ${libc_cv_asm_mpx+:} false; then : if ${libc_cv_asm_mpx+:} false; then :

View File

@ -30,6 +30,29 @@ LIBC_COMPILER_BUILTIN_INLINED(
*** Please use host i786, i686, i586, or i486. *** Please use host i786, i686, i586, or i486.
*** For example: /source/glibc/configure CFLAGS='-O2 -march=i686' ...])]) *** 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 dnl Check whether asm supports Intel MPX
AC_CACHE_CHECK(for Intel MPX support, libc_cv_asm_mpx, [dnl AC_CACHE_CHECK(for Intel MPX support, libc_cv_asm_mpx, [dnl
cat > conftest.s <<\EOF cat > conftest.s <<\EOF

View File

@ -23,6 +23,9 @@ CPPFLAGS-crtn.S += $(pic-ccflag)
endif endif
ASFLAGS-.os += $(pic-ccflag) 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) ifeq ($(subdir),elf)
ifneq ($(o32-fpabi),) ifneq ($(o32-fpabi),)

View File

@ -85,6 +85,39 @@ if test x"$build_mathvec" = xnotset; then
build_mathvec=yes build_mathvec=yes
fi 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 $as_echo "#define PI_STATIC_AND_HIDDEN 1" >>confdefs.h

View File

@ -44,6 +44,31 @@ if test x"$build_mathvec" = xnotset; then
build_mathvec=yes build_mathvec=yes
fi 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 It is always possible to access static and hidden symbols in an
dnl position independent way. dnl position independent way.
AC_DEFINE(PI_STATIC_AND_HIDDEN) AC_DEFINE(PI_STATIC_AND_HIDDEN)