[PATCH] elf: Defer all IRELATIVE relocations until after PLT setup (BZ 20673)
H.J. Lu
hjl.tools@gmail.com
Mon May 11 18:24:28 GMT 2026
On Mon, May 11, 2026 at 10:41 PM Adhemerval Zanella Netto
<adhemerval.zanella@linaro.org> wrote:
>
>
>
> On 08/05/26 20:48, H.J. Lu wrote:
> > On Tue, Apr 28, 2026 at 9:42 PM Adhemerval Zanella
> > <adhemerval.zanella@linaro.org> wrote:
> >>
> >> When a shared library is built with -z lazy and its IFUNC resolver calls
> >> a PLT function, the dynamic linker can crash. The resolver runs while
> >> the PLT stubs still hold their raw ELF virtual addresses — l_addr has
> >> not yet been added — so the call branches to an unmapped address.
> >>
> >> The old code deferred IRELATIVE entries only to the end of the relocation
> >> range currently being processed (via the r2/end2 scan-ahead mechanism in
> >> elf_dynamic_do_Rel). This was sufficient only when both IRELATIVE and the
> >> JMP_SLOT entries for the PLT functions it needs are in the same section.
> >> On x86-64, aarch64, arm, i386 and most other targets, a file-scope
> >> initialiser of the form
> >>
> >> int (*fptr)(void) = some_ifunc;
> >>
> >> causes the linker to place R_*_IRELATIVE in .rela.dyn, while JMP_SLOT
> >> entries for any PLT calls made by the resolver live in .rela.plt.
> >> Processing .rela.dyn before .rela.plt means the resolver fires before the
> >> PLT is usable, regardless of where within .rela.dyn IRELATIVE appears.
> >>
> >> Fix this by splitting IRELATIVE processing into a separate, explicitly
> >> deferred pass. In elf/do-rel.h:
> >>
> >> - Remove the r2/end2 variables and the post-loop IRELATIVE re-scan from
> >> elf_dynamic_do_Rel. IRELATIVE entries are now always skipped in the
> >> non-bootstrap path.
> >>
> >> - Add a new elf_dynamic_do_Rel_irelative function that scans a
> >> relocation range and calls elf_machine_rel/elf_machine_lazy_rel for
> >> IRELATIVE and ifunc relocations.
> >>
> >> In elf/dynamic-link.h, update _ELF_DYNAMIC_DO_RELOC to use a two-phase
> >> approach for non-bootstrap builds unconditionally (regardless of whether
> >> ranges[1].size is zero):
> >>
> >> Phase 1+2: elf_dynamic_do_Rel over .rela.dyn then .rela.plt — processes
> >> everything except IRELATIVE/STT_GNU_IFUNC.
> >> Phase 3+4: elf_dynamic_do_Rel_irelative over .rela.dyn then .rela.plt —
> >> processes only IRELATIVE, by which point all PLT stubs are
> >> valid.
> >>
> >> This guarantees that IRELATIVE resolvers can call PLT stubs safely
> >> regardless of which section the linker placed R_*_IRELATIVE in.
> >>
> >> Add ELF_MACHINE_IRELATIVE to the architectures that were missing it so
> >> the new skip logic in elf_dynamic_do_Rel is compiled for all targets.
> >>
> >> I checked on all ABI that support iFUNC (x86_64, i686, aarch64, arm,
> >> loongarch, powerpc, riscv, s390, and sparc), although on some through
> >> qemu-system (which should not matter for this case).
> >>
> >> It also fixes the mold reported issues [1], which shows an example
> >> where IFUNC relocation placement and processing can works different
> >> for different ABIs.
> >
> > Just to be clear. This patch doesn't fully fix:
> >
> > https://sourceware.org/bugzilla/show_bug.cgi?id=20673
> >
> > This fix only deals with IRELATIVE relocation order within an object.
> > Calling an external function from an IFUC resolver may still crash.
> > Am I correct?
> Yes, it does not solve all the iFUNC raised by Szabolcs [1], nor the
> original BZ#21041 issues [2] which Fangrui creates an example [3]. For this
> I think we will need something like what Florian did [4], and I am exploring
> a solution similar.
>
>
> [1] https://sourceware.org/legacy-ml/libc-alpha/2015-11/msg00108.html
> [2] https://sourceware.org/bugzilla/show_bug.cgi?id=21041
> [3] https://maskray.me/blog/2021-01-18-gnu-indirect-function
> [4] https://sourceware.org/git/?p=glibc.git;a=shortlog;h=refs/heads/fw/bug21242
IFUNC resolvers have many limitations when they call another function.
I don't think we can make it work in all cases. Can you remove the
reference to BZ 20673 in your commit message? Your patch supports
any IRELATIVE relocation orders. It should be good enough on its own.
--
H.J.
More information about the Libc-alpha
mailing list