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.
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]
Did you run into https://sourceware.org/bugzilla/show_bug.cgi?id=13302
(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.
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 ();
Created attachment 13101 [details] An IFUNC testcase on x86 It failed with static PIE.
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>
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>
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>
Fixed on 2.33.