Blame elf/dl-sym-post.h

Packit Service 397d8c
/* Post-processing of a symbol produced by dlsym, dlvsym.
Packit Service 397d8c
   Copyright (C) 1999-2020 Free Software Foundation, Inc.
Packit Service 397d8c
   This file is part of the GNU C Library.
Packit Service 397d8c
Packit Service 397d8c
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 397d8c
   modify it under the terms of the GNU Lesser General Public
Packit Service 397d8c
   License as published by the Free Software Foundation; either
Packit Service 397d8c
   version 2.1 of the License, or (at your option) any later version.
Packit Service 397d8c
Packit Service 397d8c
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 397d8c
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 397d8c
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 397d8c
   Lesser General Public License for more details.
Packit Service 397d8c
Packit Service 397d8c
   You should have received a copy of the GNU Lesser General Public
Packit Service 397d8c
   License along with the GNU C Library; if not, see
Packit Service 397d8c
   <https://www.gnu.org/licenses/>.  */
Packit Service 397d8c
Packit Service 397d8c
Packit Service 397d8c
/* Return the link map containing the caller address.  */
Packit Service 397d8c
static struct link_map *
Packit Service 397d8c
_dl_sym_find_caller_link_map (ElfW(Addr) caller)
Packit Service 397d8c
{
Packit Service 397d8c
  struct link_map *l = _dl_find_dso_for_object (caller);
Packit Service 397d8c
  if (l != NULL)
Packit Service 397d8c
    return l;
Packit Service 397d8c
  else
Packit Service 397d8c
    /* If the address is not recognized the call comes from the main
Packit Service 397d8c
       program (we hope).  */
Packit Service 397d8c
    return GL(dl_ns)[LM_ID_BASE]._ns_loaded;
Packit Service 397d8c
}
Packit Service 397d8c
Packit Service 397d8c
/* Translates RESULT, *REF, VALUE into a symbol address from the point
Packit Service 397d8c
   of view of MATCH.  Performs IFUNC resolution and auditing if
Packit Service 397d8c
   necessary.  If MATCH is NULL, CALLER is used to determine it.  */
Packit Service 397d8c
static void *
Packit Service 397d8c
_dl_sym_post (lookup_t result, const ElfW(Sym) *ref, void *value,
Packit Service 397d8c
              ElfW(Addr) caller, struct link_map *match)
Packit Service 397d8c
{
Packit Service 397d8c
  /* Resolve indirect function address.  */
Packit Service 397d8c
  if (__glibc_unlikely (ELFW(ST_TYPE) (ref->st_info) == STT_GNU_IFUNC))
Packit Service 397d8c
    {
Packit Service 397d8c
      DL_FIXUP_VALUE_TYPE fixup
Packit Service 397d8c
        = DL_FIXUP_MAKE_VALUE (result, (ElfW(Addr)) value);
Packit Service 397d8c
      fixup = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (fixup));
Packit Service 397d8c
      value = (void *) DL_FIXUP_VALUE_CODE_ADDR (fixup);
Packit Service 397d8c
    }
Packit Service 397d8c
Packit Service 397d8c
#ifdef SHARED
Packit Service 397d8c
  /* Auditing checkpoint: we have a new binding.  Provide the
Packit Service 397d8c
     auditing libraries the possibility to change the value and
Packit Service 397d8c
     tell us whether further auditing is wanted.  */
Packit Service 397d8c
  if (__glibc_unlikely (GLRO(dl_naudit) > 0))
Packit Service 397d8c
    {
Packit Service 397d8c
      const char *strtab = (const char *) D_PTR (result,
Packit Service 397d8c
                                                 l_info[DT_STRTAB]);
Packit Service 397d8c
      /* Compute index of the symbol entry in the symbol table of
Packit Service 397d8c
         the DSO with the definition.  */
Packit Service 397d8c
      unsigned int ndx = (ref - (ElfW(Sym) *) D_PTR (result,
Packit Service 397d8c
                                                     l_info[DT_SYMTAB]));
Packit Service 397d8c
Packit Service 397d8c
      if (match == NULL)
Packit Service 397d8c
        match = _dl_sym_find_caller_link_map (caller);
Packit Service 397d8c
Packit Service 397d8c
      if ((match->l_audit_any_plt | result->l_audit_any_plt) != 0)
Packit Service 397d8c
        {
Packit Service 397d8c
          unsigned int altvalue = 0;
Packit Service 397d8c
          struct audit_ifaces *afct = GLRO(dl_audit);
Packit Service 397d8c
          /* Synthesize a symbol record where the st_value field is
Packit Service 397d8c
             the result.  */
Packit Service 397d8c
          ElfW(Sym) sym = *ref;
Packit Service 397d8c
          sym.st_value = (ElfW(Addr)) value;
Packit Service 397d8c
Packit Service 397d8c
          for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
Packit Service 397d8c
            {
Packit Service 397d8c
              struct auditstate *match_audit
Packit Service 397d8c
                = link_map_audit_state (match, cnt);
Packit Service 397d8c
              struct auditstate *result_audit
Packit Service 397d8c
                = link_map_audit_state (result, cnt);
Packit Service 397d8c
              if (afct->symbind != NULL
Packit Service 397d8c
                  && ((match_audit->bindflags & LA_FLG_BINDFROM) != 0
Packit Service 397d8c
                      || ((result_audit->bindflags & LA_FLG_BINDTO)
Packit Service 397d8c
                          != 0)))
Packit Service 397d8c
                {
Packit Service 397d8c
                  unsigned int flags = altvalue | LA_SYMB_DLSYM;
Packit Service 397d8c
                  uintptr_t new_value
Packit Service 397d8c
                    = afct->symbind (&sym, ndx,
Packit Service 397d8c
                                     &match_audit->cookie,
Packit Service 397d8c
                                     &result_audit->cookie,
Packit Service 397d8c
                                     &flags, strtab + ref->st_name);
Packit Service 397d8c
                  if (new_value != (uintptr_t) sym.st_value)
Packit Service 397d8c
                    {
Packit Service 397d8c
                      altvalue = LA_SYMB_ALTVALUE;
Packit Service 397d8c
                      sym.st_value = new_value;
Packit Service 397d8c
                    }
Packit Service 397d8c
                }
Packit Service 397d8c
Packit Service 397d8c
              afct = afct->next;
Packit Service 397d8c
            }
Packit Service 397d8c
Packit Service 397d8c
          value = (void *) sym.st_value;
Packit Service 397d8c
        }
Packit Service 397d8c
    }
Packit Service 397d8c
#endif
Packit Service 397d8c
  return value;
Packit Service 397d8c
}