Re: [PATCH 1/2] elf: Honour skip_ifunc for cross-object IFUNC relocations [BZ #34428]

"H.J. Lu" <[email protected]> Mon, 3 Aug 2026 09:04:41 +0800
Newsgroups gmane.comp.lib.glibc.alpha
Message-ID <CAMe9rOoq0C0LanJyF32x3WFU+E42r+ehup5658_tcE0yEYwHcQ@mail.gmail.com>
On Mon, Aug 3, 2026 at 8:28=E2=80=AFAM H.J. Lu <[email protected]> wrote:
>
> On Mon, Aug 3, 2026 at 8:11=E2=80=AFAM H.J. Lu <[email protected]> wrot=
e:
> >
> > On Mon, Aug 3, 2026 at 7:45=E2=80=AFAM Adhemerval Zanella
> > <[email protected]> wrote:
> > >
> > > Commit 63b31c05a8a dropped the skip_ifunc argument from elf_dynamic_d=
o_Rel,
> > > assuming the elf_dynamic_do_Rel_irelative pass handles every relocati=
on
> > > that may run an IFUNC resolver.  That only holds for IFUNC symbols de=
fined
> > > in the object being relocated, a reference to an IFUNC in another obj=
ect is
> > > an ordinary JMP_SLOT or GLOB_DAT against an undefined symbol, and bei=
ng
> > > IFUNC is only known after symbol resolution (elf_machine_rel).  Those
> > > relocations stay in the regular pass, which no longer propagated
> > > skip_ifunc, so __RTLD_NOIFUNC was ignored for them.
> > >
> > > ldd -u forces non-lazy binding (GLRO(dl_lazy) =3D 0 for DL_DEBUG_UNUS=
ED), so
> > > the resolver was called and the diagnostic emitted:
> > >
> > >   $ ldd -u /bin/ls
> > >   /bin/ls: Relink `' with `/usr/lib64/libc.so.6' for IFUNC symbol `__=
mempcpy_chk'
> > >
> > > ldd -r with LD_BIND_NOW is affected in the same way.
> > >
> > > Restore the skip_ifunc parameter and pass it through _ELF_DYNAMIC_DO_=
RELOC
> > > and ELF_DYNAMIC_RELOCATE_NOIFUNC.
> > >
> > > Checked on x86_64-linux-gnu, aarch64-linux-gnu, and i686-linux-gnu. I
> > > also built for all supported architectures and run the elf tests on
> > > qemu-system for armhf, alpha, hppa, loongarch64, mipsel, mips64le,
> > > powerpc*, riscv64, s390x, and sparc64.
> > > ---
> > >  elf/Makefile                      | 28 +++++++++++++++++++++++
> > >  elf/dl-reloc-static-pie.c         |  2 +-
> > >  elf/dl-reloc.c                    |  3 ++-
> > >  elf/do-rel.h                      | 24 ++++++++++++-------
> > >  elf/dynamic-link.h                | 32 ++++++++++++++++----------
> > >  elf/tst-ifunc-fault-dep-bindnow.c | 19 ++++++++++++++++
> > >  elf/tst-ifunc-fault-dep-lazy.c    | 27 ++++++++++++++++++++++
> > >  elf/tst-ifunc-fault-mod.c         | 38 +++++++++++++++++++++++++++++=
++
> > >  8 files changed, 151 insertions(+), 22 deletions(-)
> > >  create mode 100644 elf/tst-ifunc-fault-dep-bindnow.c
> > >  create mode 100644 elf/tst-ifunc-fault-dep-lazy.c
> > >  create mode 100644 elf/tst-ifunc-fault-mod.c
> > >
> > > diff --git a/elf/Makefile b/elf/Makefile
> > > index 94c5b7e6ed8..6cfb1b5cf30 100644
> > > --- a/elf/Makefile
> > > +++ b/elf/Makefile
> > > @@ -1396,6 +1396,13 @@ modules-names +=3D \
> > >    tst-ifunc-tls-write-lib \
> > >    tst-tls-tdata-reloc-lib \
> > >    # modules-names
> > > +ifeq (yes,$(have-gcc-ifunc))
> > > +tests +=3D \
> > > +  tst-ifunc-fault-dep-bindnow \
> > > +  tst-ifunc-fault-dep-lazy \
> > > +  # tests
> > > +modules-names +=3D tst-ifunc-fault-mod
> > > +endif
> > >  ifneq (no,$(have-test-mtls-descriptor))
> > >  tests +=3D tst-ifunc-tls-init-tlsdesc
> > >  modules-names +=3D tst-ifunc-tls-init-tlsdesc-lib
> > > @@ -2545,6 +2552,27 @@ $(objpfx)tst-ifunc-fault-bindnow.out: $(objpfx=
)tst-ifunc-fault-bindnow \
> > >     $(objpfx)ld.so
> > >         $(tst-ifunc-fault-script)
> > >
> > > +LDFLAGS-tst-ifunc-fault-dep-lazy =3D -Wl,-z,lazy
> > > +LDFLAGS-tst-ifunc-fault-dep-bindnow =3D -Wl,-z,now
> > > +define tst-ifunc-fault-dep-script
> > > +( $(test-wrapper) $(rtld-prefix) --verify $< \
> > > +  && $(test-wrapper-env) LD_TRACE_LOADED_OBJECTS=3D1 $(rtld-prefix) =
$< \
> > > +  && $(test-wrapper-env) LD_TRACE_LOADED_OBJECTS=3D1 LD_DEBUG=3Dunus=
ed \
> > > +                        $(rtld-prefix) $< \
> > > +  && $(test-wrapper-env) LD_TRACE_LOADED_OBJECTS=3D1 LD_WARN=3Dyes L=
D_BIND_NOW=3D1 \
> > > +                        $(rtld-prefix) $< \
> > > +) > $@; $(evaluate-test)
> > > +endef
> > > +$(objpfx)tst-ifunc-fault-dep-lazy: $(objpfx)tst-ifunc-fault-mod.so
> > > +$(objpfx)tst-ifunc-fault-dep-bindnow: $(objpfx)tst-ifunc-fault-mod.s=
o
> > > +$(objpfx)tst-ifunc-fault-dep-lazy.out: $(objpfx)tst-ifunc-fault-dep-=
lazy \
> > > +   $(objpfx)tst-ifunc-fault-mod.so $(objpfx)ld.so
> > > +       $(tst-ifunc-fault-dep-script)
> > > +$(objpfx)tst-ifunc-fault-dep-bindnow.out: \
> > > +   $(objpfx)tst-ifunc-fault-dep-bindnow \
> > > +   $(objpfx)tst-ifunc-fault-mod.so $(objpfx)ld.so
> > > +       $(tst-ifunc-fault-dep-script)
> > > +
> > >  LDFLAGS-tst-ifunc-plt-lib.so =3D -Wl,-z,lazy
> > >
> > >  tst-ifunc-plt-bindnow-ENV =3D LD_BIND_NOW=3D1
> > > diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
> > > index 8463e46147d..53260b57372 100644
> > > --- a/elf/dl-reloc-static-pie.c
> > > +++ b/elf/dl-reloc-static-pie.c
> > > @@ -80,7 +80,7 @@ _dl_relocate_static_pie (void)
> > >
> > >    /* Relocate ourselves so we can do normal function calls and data =
access
> > >       using the global offset table.  IRELATIVE entries are deferred.=
  */
> > > -  ELF_DYNAMIC_RELOCATE_NOIFUNC (main_map, NULL, 0, 0);
> > > +  ELF_DYNAMIC_RELOCATE_NOIFUNC (main_map, NULL, 0, 0, 0);
> > >
> > >    /* Initialize _r_debug_extended.  */
> > >    struct r_debug *r =3D _dl_debug_initialize (0, LM_ID_BASE);
> > > diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
> > > index 15a6a4cffef..80cd7e25d16 100644
> > > --- a/elf/dl-reloc.c
> > > +++ b/elf/dl-reloc.c
> > > @@ -278,7 +278,8 @@ _dl_relocate_object_no_relro (struct link_map *l,=
 struct r_scope_elem *scope[],
> > >         IFUNC resolvers.  Without this, a resolver would see the unre=
located
> > >         initialiser bytes that were placed into the slot by the early
> > >         _dl_allocate_tls_init.  */
> > > -    ELF_DYNAMIC_RELOCATE_NOIFUNC (l, scope, lazy, consider_profiling=
);
> > > +    ELF_DYNAMIC_RELOCATE_NOIFUNC (l, scope, lazy, consider_profiling=
,
> > > +                                 skip_ifunc);
> >
> > ELF_DYNAMIC_RELOCATE_NOIFUNC name is confusing.
> > If it is NOIFUNC, why isn't IFUNC skipped?
> >
>
> There are
>
> /* Like ELF_DYNAMIC_RELOCATE but only processes the non-IRELATIVE pass.
>    The IRELATIVE pass must be completed later via ELF_DYNAMIC_RELOCATE_IF=
UNC.
>    Used by the static-pie startup so the TCB and stack-protector canary c=
an
>    be initialised between the two passes.  */
> # define ELF_DYNAMIC_RELOCATE_NOIFUNC(map, scope, lazy, consider_profile)
>
> This change makes the comments incorrect.

Can ELF_DYNAMIC_RELOCATE_NOIFUNC/ELF_DYNAMIC_RELOCATE_IFUNC
be renamed to ELF_DYNAMIC_RELOCATE_PASS:

# define ELF_DYNAMIC_RELOCATE_PASS(pass, map, scope, lazy, skip_ifunc)


--=20
H.J.