sparc: Fix la_symbind for bind-now (BZ 23734)

The sparc ABI has multiple cases on how to handle JMP_SLOT relocations,
(sparc_fixup_plt/sparc64_fixup_plt).  For BINDNOW, _dl_audit_symbind
will be responsible to setup the final relocation value; while for
lazy binding _dl_fixup/_dl_profile_fixup will call the audit callback
and tail cail elf_machine_fixup_plt (which will call
sparc64_fixup_plt).

This patch fixes by issuing the SPARC specific routine on bindnow and
forwarding the audit value to elf_machine_fixup_plt for lazy resolution.
It fixes the la_symbind for bind-now tests on sparc64 and sparcv9:

  elf/tst-audit24a
  elf/tst-audit24b
  elf/tst-audit24c
  elf/tst-audit24d

Checked on sparc64-linux-gnu and sparcv9-linux-gnu.
Tested-by: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
This commit is contained in:
Adhemerval Zanella 2023-07-10 17:01:00 -03:00
parent ca230f5833
commit dddc88587a
9 changed files with 66 additions and 14 deletions

View File

@ -176,8 +176,8 @@ rtld_hidden_def (_dl_audit_symbind_alt)
void
_dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
const ElfW(Sym) *defsym, DL_FIXUP_VALUE_TYPE *value,
lookup_t result)
const void *reloc, const ElfW(Sym) *defsym,
DL_FIXUP_VALUE_TYPE *value, lookup_t result, bool lazy)
{
bool for_jmp_slot = reloc_result == NULL;
@ -259,7 +259,7 @@ _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
}
if (flags & LA_SYMB_ALTVALUE)
DL_FIXUP_BINDNOW_RELOC (value, new_value, sym.st_value);
DL_FIXUP_BINDNOW_RELOC (l, reloc, value, new_value, sym.st_value, lazy);
}
void

View File

@ -139,7 +139,7 @@ _dl_fixup (
unsigned int init = atomic_load_acquire (&reloc_result->init);
if (init == 0)
{
_dl_audit_symbind (l, reloc_result, sym, &value, result);
_dl_audit_symbind (l, reloc_result, reloc, sym, &value, result, true);
/* Store the result for later runs. */
if (__glibc_likely (! GLRO(dl_bind_not)))
@ -314,7 +314,8 @@ _dl_profile_fixup (
auditing libraries the possibility to change the value and
tell us whether further auditing is wanted. */
if (defsym != NULL && GLRO(dl_naudit) > 0)
_dl_audit_symbind (l, reloc_result, defsym, &value, result);
_dl_audit_symbind (l, reloc_result, reloc, defsym, &value, result,
true);
#endif
/* Store the result for later runs. */

View File

@ -154,7 +154,8 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
= RESOLVE_MAP (map, scope, &sym, rversion,
ELF_MACHINE_JMP_SLOT);
if (sym != NULL)
_dl_audit_symbind (map, NULL, sym, r_addr_arg, sym_map);
_dl_audit_symbind (map, NULL, r, sym, r_addr_arg, sym_map,
false);
}
#endif
}
@ -200,7 +201,8 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
(struct r_found_version *) NULL,
ELF_MACHINE_JMP_SLOT);
if (sym != NULL)
_dl_audit_symbind (map, NULL , sym,r_addr_arg, sym_map);
_dl_audit_symbind (map, NULL, r, sym,r_addr_arg, sym_map,
false);
}
# endif
}

View File

@ -27,5 +27,5 @@
#define DL_FIXUP_VALUE_ADDR(value) (value)
#define DL_FIXUP_ADDR_VALUE(addr) (addr)
#define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr)
#define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \
#define DL_FIXUP_BINDNOW_RELOC(l, reloc, value, new_value, st_value, lazy) \
(*value) = st_value;

View File

@ -1362,8 +1362,8 @@ void _dl_audit_preinit (struct link_map *l);
the flags with LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT prior calling
la_symbind{32,64}. */
void _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
const ElfW(Sym) *defsym, DL_FIXUP_VALUE_TYPE *value,
lookup_t result)
const void *reloc, const ElfW(Sym) *defsym,
DL_FIXUP_VALUE_TYPE *value, lookup_t result, bool lazy)
attribute_hidden;
/* Same as _dl_audit_symbind, but also sets LA_SYMB_DLSYM flag. */
void _dl_audit_symbind_alt (struct link_map *l, const ElfW(Sym) *ref,

View File

@ -84,5 +84,5 @@ void attribute_hidden _dl_unmap (struct link_map *map);
#define DL_FIXUP_ADDR_VALUE(addr) \
(*(DL_FIXUP_VALUE_TYPE *) ((uintptr_t) (addr) & ~2))
#define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr)
#define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \
#define DL_FIXUP_BINDNOW_RELOC(l, reloc, value, new_value, st_value, lazy) \
*(value) = *(DL_FIXUP_VALUE_TYPE *) ((uintptr_t) (new_value) & ~2)

View File

@ -75,5 +75,5 @@ extern void attribute_hidden _dl_unmap (struct link_map *map);
#define DL_FIXUP_VALUE_ADDR(value) ((uintptr_t) &(value))
#define DL_FIXUP_ADDR_VALUE(addr) (*(struct fdesc *) (addr))
#define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr)
#define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \
#define DL_FIXUP_BINDNOW_RELOC(l, reloc, value, new_value, st_value, lazy) \
(*value) = *(struct fdesc *) (st_value)

View File

@ -25,7 +25,7 @@
/* We need to correctly set the audit modules value for bind-now. */
# define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) \
(((Elf64_FuncDesc *)(addr))->fd_func)
# define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \
# define DL_FIXUP_BINDNOW_RELOC(l, reloc, value, new_value, st_value, lazy) \
({ \
Elf64_FuncDesc *opd = (Elf64_FuncDesc *) (value); \
opd->fd_func = (st_value); \
@ -34,6 +34,6 @@
})
#else
# define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr)
# define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \
# define DL_FIXUP_BINDNOW_RELOC(l, reloc, value, new_value, st_value, lazy) \
(*value) = st_value;
#endif

View File

@ -0,0 +1,49 @@
/* Configuration of lookup functions. SPARC64 version.
Copyright (C) 2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
/* The type of the return value of fixup/profile_fixup. */
#define DL_FIXUP_VALUE_TYPE ElfW(Addr)
/* Construct a value of type DL_FIXUP_VALUE_TYPE from a code address
and a link map. */
#define DL_FIXUP_MAKE_VALUE(map, addr) (addr)
/* Extract the code address from a value of type DL_FIXUP_MAKE_VALUE.
*/
#define DL_FIXUP_VALUE_CODE_ADDR(value) (value)
#define DL_FIXUP_VALUE_ADDR(value) (value)
#define DL_FIXUP_ADDR_VALUE(addr) (addr)
#define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr)
/* For bindnow, _dl_audit_symbind will be responsible to setup the final value
while for lazy binding _dl_fixup/_dl_profile_fixup will call the audit
callbacks and tail cail elf_machine_fixup_plt. */
#ifdef __arch64__
# define DL_SPARC_FIXUP(l, r, value, new_value) \
sparc64_fixup_plt (l, r, value, new_value, (r)->r_addend, 0)
#else
# define DL_SPARC_FIXUP(l, r, value, new_value) \
sparc_fixup_plt (r, value, new_value, 0, 1)
#endif
#define DL_FIXUP_BINDNOW_RELOC(l, reloc, value, new_value, st_value, lazy) \
({ \
if (lazy) \
(*value) = st_value; \
else \
{ \
const PLTREL *__r = (reloc); \
DL_SPARC_FIXUP (l, __r, value, new_value); \
} \
})