[PATCH v3 2/2] elf: Add GNU_PROPERTY_1_NEEDED check

H.J. Lu hjl.tools@gmail.com
Mon Jun 28 11:55:19 GMT 2021


On Mon, Jun 28, 2021 at 1:47 AM Florian Weimer <fweimer@redhat.com> wrote:
>
> * H. J. Lu:
>
> >> Should the property be used just for error checking?  We would flip the
> >> default unconditionally.  Such a behavioral change simply based on some
> >> input file is quite surprising.
> >
> > The property is used to to allow compiling sources with
> > -fno-direct-extern-access
> > by pieces.  When creating a shared library, if one input relocatable file
> > is compiled with -fno-direct-extern-access, linker will bind all protected
> > symbols locally before seeing ALL relocations against them in different
> > input relocatables files.
>
> What is the advantage of this behavior?  Why should the presence of one
> such object file in the link cause symbol binding behavior change
> everywhere?  Especially if that one file does not even reference any
> protected symbols?

It makes linker work better.  If there are no protected symbols, there should
be no impact.

> >> For (4), I think we need to set a different flag (or perhaps even
> >> flags), and be really careful about what we do.  I think an output file
> >> that is an executable will never require indirect-extern-access, but it
> >
> > What did you mean by that?  We need to compile executable with
> > -fno-direct-extern-access for the whole scheme to work.
>
> indirect-extern-access imposes a requirement on executables, but
> building an executable to comply with the new requirements will not

That is correct.

> impose anything on the rest of the link.  I do not see the markup
> covering that.

The absence of the marker tells ld.so that copy relocation against
protected symbols in the executable is incompatible with the shared
library with the protected symbol AND the marker.

> >> can be incompatible with indirect-extern-access objects at run time.
> >> Shared objects as output files may themselves depend on
> >> indirect-extern-access objects at run time.  Ideally, markup would be
> >> applied to the relocations that are affected by the changes in the ABI.
> >
> > That is what my glibc changes do:
> >
> > $ ./elf/tst-protected1a
> > ./elf/tst-protected1a: protected1:
> > /export/build/gnu/tools-build/glibc-gitlab/build-x86_64-linux/elf/tst-protected1moda.so:
> > copy relocation against non-copyable protected symbol
> > $ readelf -r ./elf/tst-protected1a | grep COPY
> > 0000004071d8  004300000005 R_X86_64_COPY     00000000004071d8 protected1 + 0
> > 0000004071dc  004600000005 R_X86_64_COPY     00000000004071dc protected3 + 0
> >
> > This error happens only if there is a copy relocation against protected symbol
> > definition compiled with -fno-direct-extern-access.
>
> Does this mean that executables do not need any markup at all, and that
> looking at the relocation types is sufficient?  (Same for canonical
> function addresses.)

No.  The key is the absence of the marker:

static inline void __attribute__ ((always_inline))
_dl_check_protected_symbol (const char *undef_name,
    const struct link_map *undef_map,
    const ElfW(Sym) *ref,
    const struct link_map *map,
    int type_class)
{
  if (undef_map != NULL
      && undef_map->l_type == lt_executable
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      && !(undef_map->l_1_needed
   & GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      && (map->l_1_needed
  & GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    {
      if ((type_class & ELF_RTYPE_CLASS_COPY))
/* Disallow copy relocations in executable against protected
   data symbols in a shared object which needs indirect external
   access.  */
_dl_signal_error (0, map->l_name, undef_name,
  N_("copy relocation against non-copyable protected symbol"));
      else if (ref->st_value != 0
       && ref->st_shndx == SHN_UNDEF
       && (type_class & ELF_RTYPE_CLASS_PLT))
/* Disallow non-zero symbol values of undefined symbols in
   executable, which are used as the function pointer, against
   protected function symbols in a shared object with indirect
   external access.  */
_dl_signal_error (0, map->l_name, undef_name,
  N_("non-canonical reference to canonical protected function"));
    }
}

This function is called on each protected symbol lookup.


--
H.J.


More information about the Binutils mailing list