Bug 27072 - static pie ifunc resolvers run before hwcap is setup
Summary: static pie ifunc resolvers run before hwcap is setup
Status: RESOLVED FIXED
Alias: None
Product: glibc
Classification: Unclassified
Component: dynamic-link (show other bugs)
Version: 2.32
: P2 normal
Target Milestone: 2.33
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-12-15 11:01 UTC by Szabolcs Nagy
Modified: 2021-01-21 18:23 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments
An IFUNC testcase on x86 (397 bytes, text/plain)
2021-01-07 20:33 UTC, H.J. Lu
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Szabolcs Nagy 2020-12-15 11:01:02 UTC
as far as i can tell in csu/libc-start.c

  _dl_relocate_static_pie ();

is before

  _dl_aux_init (auxvec);

so ifunc resolvers are run before GL(dl_hwcap) and GL(dl_hwcap2) are set up.

on aarch64 this at least affects memory tagging: non-MTE-safe string functions are selected in static PIE binaries unconditionally.

but i think this is a bug on all targets where hwcap is passed to ifunc resolvers and support static pie.
Comment 1 Florian Weimer 2020-12-15 11:38:39 UTC
Yes, we ran into this on x86 too, where it has been fixed with an artificial IFUNC relocation (which I think it is inappropriate): 

commit 0f09154c64005e78b61484ae87b5ea2028051ea0
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Sat Jul 4 06:35:49 2020 -0700

    x86: Initialize CPU info via IFUNC relocation [BZ 26203]
Comment 2 H.J. Lu 2021-01-07 12:42:27 UTC
Did you run into

https://sourceware.org/bugzilla/show_bug.cgi?id=13302
Comment 3 Szabolcs Nagy 2021-01-07 14:00:57 UTC
(In reply to H.J. Lu from comment #2)
> Did you run into
> 
> https://sourceware.org/bugzilla/show_bug.cgi?id=13302

first of all IRELATIVE relocs are in a separate
section (.rela.plt where DT_JUMPREL points to)
that is processed later than RELATIVE relocs
(which are in .rela.dyn where DT_RELA points to)
see the two 'ranges' in _ELF_DYNAMIC_DO_RELOC.

with static pie 'ELF_DURING_STARTUP' is set, so
the two ranges are not processed separately, but
in one go, but because of the different section,
IRELATIVE is necessarily after RELATIVE in the
binary.

of course glibc may choose to process relocs in
different order than they appear in the binary.
see elf_dynamic_do_Rela, but that's not a linker
issue anymore.

(within DT_JUMPREL i'd expect ld to order IRELATIVE
after JUMP_SLOT relocs, but before TLSDESC relocs,
but such relocs cannot appear in static pie so this
is not relevant here anyway.)

also note that currently in glibc the aarch64 ifunc
resolvers don't depend on RELATIVE relocs so even
if there was no ordering the reloc processing would
work for now (assuming no user ifuncs).

in short 13302 is not relevant to this bug.
Comment 4 H.J. Lu 2021-01-07 17:10:49 UTC
This works on x86:

diff --git a/csu/libc-start.c b/csu/libc-start.c
index db859c3bed..3c2cf2f384 100644
--- a/csu/libc-start.c
+++ b/csu/libc-start.c
@@ -142,6 +142,8 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
   int result;
 
 #ifndef SHARED
+  ARCH_INIT_CPU_FEATURES ();
+
   _dl_relocate_static_pie ();
 
   char **ev = &argv[argc + 1];
@@ -189,8 +191,6 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
 
   __tunables_init (__environ);
 
-  ARCH_INIT_CPU_FEATURES ();
-
   /* Perform IREL{,A} relocations.  */
   ARCH_SETUP_IREL ();
Comment 5 H.J. Lu 2021-01-07 20:33:22 UTC
Created attachment 13101 [details]
An IFUNC testcase on x86

It failed with static PIE.
Comment 6 cvs-commit@gcc.gnu.org 2021-01-19 14:39:00 UTC
The master branch has been updated by H.J. Lu <hjl@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=cabc8a291629011894ff5d1dc4ec7e25ecee6269

commit cabc8a291629011894ff5d1dc4ec7e25ecee6269
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Mon Jan 18 11:45:46 2021 +0000

    elf: Avoid RELATIVE relocation for _dl_sysinfo
    
    Set the default _dl_sysinfo in _dl_aux_init to avoid RELATIVE relocation
    in static PIE.
    
    This is needed for fixing bug 27072 on x86.
    
    Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
Comment 7 cvs-commit@gcc.gnu.org 2021-01-21 15:59:46 UTC
The master branch has been updated by Szabolcs Nagy <nsz@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=47618209d05a0e77932038f21c6bba2425bd75c6

commit 47618209d05a0e77932038f21c6bba2425bd75c6
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
Date:   Fri Jan 15 12:49:24 2021 +0000

    Use hidden visibility for early static PIE code
    
    Extern symbol access in position independent code usually involves GOT
    indirection which needs RELATIVE reloc in a static linked PIE. (On
    some targets this is avoided e.g. because the linker can relax a GOT
    access to a pc-relative access, but this is not generally true.) Code
    that runs before static PIE self relocation must avoid relying on
    dynamic relocations which can be ensured by using hidden visibility.
    However we cannot just make all symbols hidden:
    
    On i386, all calls to IFUNC functions must go through PLT and calls to
    hidden functions CANNOT go through PLT in PIE since EBX used in PIE PLT
    may not be set up for local calls to hidden IFUNC functions.
    
    This patch aims to make symbol references hidden in code that is used
    before and by _dl_relocate_static_pie when building a static PIE libc.
    Note: for an object that is used in the startup code, its references
    and definition may not have consistent visibility: it is only forced
    hidden in the startup code.
    
    This is needed for fixing bug 27072.
    
    Co-authored-by: H.J. Lu <hjl.tools@gmail.com>
    Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
Comment 8 cvs-commit@gcc.gnu.org 2021-01-21 15:59:51 UTC
The master branch has been updated by Szabolcs Nagy <nsz@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=86d439b06fb29af8d063ee8855ff63a863f46ef3

commit 86d439b06fb29af8d063ee8855ff63a863f46ef3
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
Date:   Tue Jan 19 17:17:01 2021 +0000

    csu: Move static pie self relocation later [BZ #27072]
    
    IFUNC resolvers may depend on tunables and cpu feature setup so
    move static pie self relocation after those.
    
    It is hard to guarantee that the ealy startup code does not rely
    on relocations so this is a bit fragile. It would be more robust
    to handle RELATIVE relocs early and only IRELATIVE relocs later,
    but the current relocation processing code cannot do that.
    
    The early startup code up to relocation processing includes
    
      _dl_aux_init (auxvec);
      __libc_init_secure ();
      __tunables_init (__environ);
      ARCH_INIT_CPU_FEATURES ();
      _dl_relocate_static_pie ();
    
    These are simple enough that RELATIVE relocs can be avoided.
    
    The following steps include
    
      ARCH_SETUP_IREL ();
      ARCH_SETUP_TLS ();
      ARCH_APPLY_IREL ();
    
    On some targets IRELATIVE processing relies on TLS setup on
    others TLS setup relies on IRELATIVE relocs, so the right
    position for _dl_relocate_static_pie is target dependent.
    For now move self relocation as early as possible on targets
    that support static PIE.
    
    Fixes bug 27072.
    
    Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
Comment 9 Adhemerval Zanella 2021-01-21 17:06:59 UTC
Fixed on 2.33.