From patchwork Thu Sep 28 12:26:10 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 23196 Received: (qmail 109250 invoked by alias); 28 Sep 2017 12:26:17 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 108745 invoked by uid 89); 28 Sep 2017 12:26:17 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.0 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM, SPF_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mail-oi0-f50.google.com X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=OlpLskgxorWMxmwrXlk042MEIDcwAOqv3fPYuRurlgU=; b=k3wPEtWZ0uBo0er8oSp+1AHcDmohuJK+rQ1JDUs1OJpI+Zp62uytCywohlU742xw9f ujzLf1kdMCZFJ46+WuE4SznL17f6ZDKanMhVAESqHA8Kf4+GSejy/OmjqAFBHLJlqP1B c5i66MhQ2i1gHNj3Gz/9S9yKBAM7jCv5xJsWMl1xMbzzv/MdE/9gEGpHACBB7HZRRdoT /E2R1frOYOwivRxACMYKwtemXewnbOkSxAyNvoabQcnK/lEYTZHSACeAdXiibif6tGp1 pRIokVK4iKO4v2p1XCsrbnj21GG+1O5hvcfr2p1SM7/vk24QdIYtGOuyqWP0oGEhwbNx Hmkg== X-Gm-Message-State: AMCzsaVUs3N9JLjGiGNOLo8HkNanOPoFla82REkmUXoJa6rf3XzWW795 P/gi6eG5bsI0voxcj7LgwWzuVCE18T3itLDNAlc= X-Google-Smtp-Source: AOwi7QDid/tnVT3eT4BeshZIjkSCdigogUfCljIo0Q5bPJ8Y5Nt/q5NfpmdeV/QQ2Agt1p3qCwOGXzKHyw54/eWIHHY= X-Received: by 10.202.243.69 with SMTP id r66mr200059oih.337.1506601571456; Thu, 28 Sep 2017 05:26:11 -0700 (PDT) MIME-Version: 1.0 In-Reply-To: <20170928093750.GA233@x4> References: <20170928093750.GA233@x4> From: "H.J. Lu" Date: Thu, 28 Sep 2017 05:26:10 -0700 Message-ID: Subject: Re: PING: [PATCH] Add --enable-static-pie to build static PIE To: Markus Trippelsdorf Cc: Joseph Myers , GNU C Library On 9/28/17, Markus Trippelsdorf wrote: > On 2017.09.27 at 01:30 -0700, H.J. Lu wrote: >> No separate PIE copy of libc.a, is used for static PIE to minimize >> GCC driver change. To improve system security, glibc can be built with >> --enable-static-pie, and the same libc.a can be used to build both static >> executable and static PIE. > > It doesn't work: > > ~ % echo "int main(){}" | gcc -x c - -static > /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.1/../../../../lib64/libc.a(dl-support.o): > In function `elf_machine_load_address': > /home/markus/glibc/elf/../sysdeps/x86_64/dl-machine.h:59: undefined > reference to `_DYNAMIC' > /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.1/../../../../lib64/libc.a(dl-support.o): > In function `elf_get_dynamic_info': > /home/markus/glibc/elf/get-dynamic-info.h:48: undefined reference to > `_DYNAMIC' > /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: > a.out: hidden symbol `_DYNAMIC' isn't defined > /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: > final link failed: Bad value > collect2: error: ld returned 1 exit status > Thanks for your test. Fixed on hjl/pie/static branch. I am enclosing the updated --enable-static-pie patch. From f09a1df2e8d57577daaf8b8cce10da007de26597 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Mon, 17 Jul 2017 08:17:32 -0700 Subject: [PATCH] Add --enable-static-pie configure option to build static PIE 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. Static PIE can work on all architectures which support PIE, provided 1. 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, like commit 1e8e527dd9718eaebe8417b73befb0c821b7b327 Author: H.J. Lu Date: Fri Aug 4 12:59:35 2017 -0700 i386: Support static PIE in start.S Since start.o may be compiled as PIC, we should check PIC instead of SHARED. Also avoid dynamic relocation against main in static PIE since _start is the entry point before the executable is relocated. 2. elf_machine_dynamic and elf_machine_load_address in dl-machine.h are updated to support static PIE, similar to x86_64 dl-machine.h: /* Return the link-time address of _DYNAMIC. Conveniently, this is the first element of the GOT. This must be inlined in a function which uses global data. */ static inline ElfW(Addr) __attribute__ ((unused)) elf_machine_dynamic (void) { /* This produces an IP-relative reloc which is resolved at link time. */ extern const ElfW(Addr) _GLOBAL_OFFSET_TABLE_[] attribute_hidden; return _GLOBAL_OFFSET_TABLE_[0]; } /* Return the run-time load address of the shared object. */ static inline ElfW(Addr) __attribute__ ((unused)) elf_machine_load_address (void) { /* Compute the difference between the runtime address of _DYNAMIC as seen by an IP-relative reference, and the link-time address found in the special unrelocated first GOT entry. */ #ifdef SHARED extern ElfW(Dyn) _DYNAMIC[] attribute_hidden; return (ElfW(Addr)) &_DYNAMIC - elf_machine_dynamic (); #else extern ElfW(Dyn) _DYNAMIC[] __attribute__((weak, visibility ("hidden"))); if (_DYNAMIC) { /* The address of dynamic must be taken as non-weak to avoid dynamic relocation. */ extern ElfW(Dyn) dynamic[] asm ("_DYNAMIC") attribute_hidden; return (ElfW(Addr)) &dynamic - elf_machine_dynamic (); } else return 0; #endif } 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 Binutils 2.29 or above are OK. Tested on i686 and x86-64. * INSTALL: Regenerated. * Makeconfig (pic-default): Updated for --enable-static-pie. (pie-default): New for --enable-static-pie. (default-pie-ldflag): Likewise. (+link-static-before-libc): Add $(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/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. * elf/dl-support.c: Include "dynamic-link.h" and don't include "get-dynamic-info.h" for --enable-static-pie. (_dl_relocate_static_pie): New function for --enable-static-pie. (STATIC_PIE_BOOTSTRAP): New for --enable-static-pie. (RESOLVE_MAP): Likewise. * elf/dynamic-link.h (ELF_DURING_STARTUP): Also check STATIC_PIE_BOOTSTRAP. * elf/get-dynamic-info.h (elf_get_dynamic_info): Likewise. * manual/install.texi: Document --enable-static-pie. * sysdeps/generic/ldsodefs.h (_dl_relocate_static_pie): New. * sysdeps/x86_64/configure.ac: Check if linker supports static PIE. * sysdeps/x86_64/configure: Regenerated. --- INSTALL | 7 ++++ Makeconfig | 20 ++++++++++-- NEWS | 5 +++ config.h.in | 3 ++ configure | 78 +++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 29 +++++++++++++++++ csu/libc-start.c | 2 ++ csu/libc-tls.c | 6 ++-- elf/dl-support.c | 43 +++++++++++++++++++++++-- elf/dynamic-link.h | 2 +- elf/get-dynamic-info.h | 6 ++-- manual/install.texi | 7 ++++ sysdeps/generic/ldsodefs.h | 7 ++++ sysdeps/x86_64/configure | 33 +++++++++++++++++++ sysdeps/x86_64/configure.ac | 25 +++++++++++++++ 15 files changed, 263 insertions(+), 10 deletions(-) diff --git a/INSTALL b/INSTALL index 4d9024c667..862544f144 100644 --- a/INSTALL +++ b/INSTALL @@ -106,6 +106,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 b51904b797..b45209fe5f 100644 --- a/Makeconfig +++ b/Makeconfig @@ -386,6 +386,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. @@ -435,6 +445,7 @@ endif # Command for statically linking programs with the C library. ifndef +link-static +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \ + $(default-pie-ldflag) \ $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \ $(addprefix $(csu-objpfx),$(static-start-installed-name)) \ $(+preinit) $(+prectorT) \ @@ -651,8 +662,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/ @@ -973,7 +989,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)) @@ -998,7 +1014,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 e346d2afe6..681ba8ce89 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 014fb4ea0e..26ed7865ef 100644 --- a/config.h.in +++ b/config.h.in @@ -236,6 +236,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 067d92d2ba..cd5cf5729f 100755 --- a/configure +++ b/configure @@ -767,6 +767,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 @@ -1424,6 +1425,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 @@ -3372,6 +3374,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 @@ -5994,6 +6003,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 <&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 : @@ -6888,6 +6953,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 d412104d8c..09e1c7f23b 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@:>@]), @@ -1460,6 +1465,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]) ]) @@ -1962,6 +1980,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/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/elf/dl-support.c b/elf/dl-support.c index 5e3de90598..dc994629e7 100644 --- a/elf/dl-support.c +++ b/elf/dl-support.c @@ -26,7 +26,11 @@ #include #include #include -#include +#if ENABLE_STATIC_PIE +# include "dynamic-link.h" +#else +# include +#endif #include #include #include @@ -199,7 +203,9 @@ const ElfW(Ehdr) *_dl_sysinfo_dso; struct link_map *_dl_sysinfo_map; -# include "get-dynamic-info.h" +# if !ENABLE_STATIC_PIE +# include "get-dynamic-info.h" +# endif #endif #include "setup-vdso.h" @@ -302,6 +308,39 @@ _dl_aux_init (ElfW(auxv_t) *av) } #endif +#if ENABLE_STATIC_PIE +/* Relocate static executable with PIE. */ + +void +_dl_relocate_static_pie (void) +{ +# define STATIC_PIE_BOOTSTRAP +# define RESOLVE_MAP(sym, version, flags) (&_dl_main_map) +# include "dynamic-link.h" + + /* Figure out the run-time load addres of static PIE. */ + _dl_main_map.l_addr = elf_machine_load_address (); + + /* Skip if this is a non-PIE static executable. */ + if (!_dl_main_map.l_addr) + return; + + /* Read our own dynamic section and fill in the info array. */ + _dl_main_map.l_ld = ((void *) _dl_main_map.l_addr + + elf_machine_dynamic ()); + elf_get_dynamic_info (&_dl_main_map, NULL); + +# ifdef ELF_MACHINE_BEFORE_RTLD_RELOC + ELF_MACHINE_BEFORE_RTLD_RELOC (_dl_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 (&_dl_main_map, 0, 0, 0); + _dl_main_map.l_relocated = 1; +} +#endif + void _dl_non_dynamic_init (void) 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/manual/install.texi b/manual/install.texi index 35948b1bbb..2a2a430550 100644 --- a/manual/install.texi +++ b/manual/install.texi @@ -136,6 +136,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 1a4449eeb3..b4c032a06c 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/x86_64/configure b/sysdeps/x86_64/configure index efef46b1b7..8ee15b8a25 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 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..53e4a8277c 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 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.5