08c3a6
commit 4dca2d3a7b43bf99bd6a567870a3144af4e763ef
08c3a6
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
08c3a6
Date:   Fri Feb 4 15:54:59 2022 -0300
08c3a6
08c3a6
    hppa: Fix bind-now audit (BZ #28857)
08c3a6
    
08c3a6
    On hppa, a function pointer returned by la_symbind is actually a function
08c3a6
    descriptor has the plabel bit set (bit 30).  This must be cleared to get
08c3a6
    the actual address of the descriptor.  If the descriptor has been bound,
08c3a6
    the first word of the descriptor is the physical address of theA function,
08c3a6
    otherwise, the first word of the descriptor points to a trampoline in the
08c3a6
    PLT.
08c3a6
    
08c3a6
    This patch also adds a workaround on tests because on hppa (and it seems
08c3a6
    to be the only ABI I have see it), some shared library adds a dynamic PLT
08c3a6
    relocation to am empty symbol name:
08c3a6
    
08c3a6
    $ readelf -r elf/tst-audit25mod1.so
08c3a6
    [...]
08c3a6
    Relocation section '.rela.plt' at offset 0x464 contains 6 entries:
08c3a6
     Offset     Info    Type            Sym.Value  Sym. Name + Addend
08c3a6
    00002008  00000081 R_PARISC_IPLT                508
08c3a6
    [...]
08c3a6
    
08c3a6
    It breaks some assumptions on the test, where a symbol with an empty
08c3a6
    name ("") is passed on la_symbind.
08c3a6
    
08c3a6
    Checked on x86_64-linux-gnu and hppa-linux-gnu.
08c3a6
    
08c3a6
    (cherry picked from commit 9e94f57484a2aba0fe67ea2059b5843f651887c2)
08c3a6
08c3a6
diff --git a/elf/Makefile b/elf/Makefile
08c3a6
index 57059293d0bc86cb..3e17a0706f5ec2df 100644
08c3a6
--- a/elf/Makefile
08c3a6
+++ b/elf/Makefile
08c3a6
@@ -2116,7 +2116,7 @@ $(objpfx)tst-audit24c.out: $(objpfx)tst-auditmod24c.so
08c3a6
 $(objpfx)tst-audit24c: $(objpfx)tst-audit24amod1.so \
08c3a6
 		       $(objpfx)tst-audit24amod2.so
08c3a6
 tst-audit24c-ENV = LD_BIND_NOW=1 LD_AUDIT=$(objpfx)tst-auditmod24c.so
08c3a6
-LDFLAGS-tst-audit24b = -Wl,-z,lazy
08c3a6
+LDFLAGS-tst-audit24c = -Wl,-z,lazy
08c3a6
 
08c3a6
 $(objpfx)tst-audit24d.out: $(objpfx)tst-auditmod24d.so
08c3a6
 $(objpfx)tst-audit24d: $(objpfx)tst-audit24dmod1.so \
08c3a6
diff --git a/elf/dl-audit.c b/elf/dl-audit.c
08c3a6
index 72a50717ef60a357..ec9b032eae37c103 100644
08c3a6
--- a/elf/dl-audit.c
08c3a6
+++ b/elf/dl-audit.c
08c3a6
@@ -257,7 +257,8 @@ _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
08c3a6
       reloc_result->flags = flags;
08c3a6
     }
08c3a6
 
08c3a6
-  DL_FIXUP_BINDNOW_RELOC (value, new_value, sym.st_value);
08c3a6
+  if (flags & LA_SYMB_ALTVALUE)
08c3a6
+    DL_FIXUP_BINDNOW_RELOC (value, new_value, sym.st_value);
08c3a6
 }
08c3a6
 
08c3a6
 void
08c3a6
diff --git a/elf/tst-auditmod24a.c b/elf/tst-auditmod24a.c
08c3a6
index d8e88f3984af1707..3075dfae2fd3d288 100644
08c3a6
--- a/elf/tst-auditmod24a.c
08c3a6
+++ b/elf/tst-auditmod24a.c
08c3a6
@@ -110,5 +110,7 @@ la_symbind32 (Elf32_Sym *sym, unsigned int ndx,
08c3a6
       return sym->st_value;
08c3a6
     }
08c3a6
 
08c3a6
-  abort ();
08c3a6
+  if (symname[0] != '\0')
08c3a6
+    abort ();
08c3a6
+  return sym->st_value;
08c3a6
 }
08c3a6
diff --git a/elf/tst-auditmod24d.c b/elf/tst-auditmod24d.c
08c3a6
index 8c803ecc0a48f21b..badc6be451ee0357 100644
08c3a6
--- a/elf/tst-auditmod24d.c
08c3a6
+++ b/elf/tst-auditmod24d.c
08c3a6
@@ -116,5 +116,7 @@ la_symbind32 (Elf32_Sym *sym, unsigned int ndx,
08c3a6
 	}
08c3a6
     }
08c3a6
 
08c3a6
-  abort ();
08c3a6
+  if (symname[0] != '\0')
08c3a6
+    abort ();
08c3a6
+  return sym->st_value;
08c3a6
 }
08c3a6
diff --git a/elf/tst-auditmod25.c b/elf/tst-auditmod25.c
08c3a6
index 526f5c54bc2c3b8c..20640a8daf346b5f 100644
08c3a6
--- a/elf/tst-auditmod25.c
08c3a6
+++ b/elf/tst-auditmod25.c
08c3a6
@@ -72,7 +72,7 @@ la_symbind32 (Elf32_Sym *sym, unsigned int ndx,
08c3a6
 	      unsigned int *flags, const char *symname)
08c3a6
 #endif
08c3a6
 {
08c3a6
-  if (*refcook != -1 && *defcook != -1)
08c3a6
+  if (*refcook != -1 && *defcook != -1 && symname[0] != '\0')
08c3a6
     fprintf (stderr, "la_symbind: %s %u\n", symname,
08c3a6
 	     *flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) ? 1 : 0);
08c3a6
   return sym->st_value;
08c3a6
diff --git a/sysdeps/hppa/dl-lookupcfg.h b/sysdeps/hppa/dl-lookupcfg.h
08c3a6
index f4f00714fa158e18..92fd0b7c844713ce 100644
08c3a6
--- a/sysdeps/hppa/dl-lookupcfg.h
08c3a6
+++ b/sysdeps/hppa/dl-lookupcfg.h
08c3a6
@@ -80,7 +80,9 @@ void attribute_hidden _dl_unmap (struct link_map *map);
08c3a6
 /* Extract the code address from a fixup value */
08c3a6
 #define DL_FIXUP_VALUE_CODE_ADDR(value) ((value).ip)
08c3a6
 #define DL_FIXUP_VALUE_ADDR(value) ((uintptr_t) &(value))
08c3a6
-#define DL_FIXUP_ADDR_VALUE(addr) (*(struct fdesc *) (addr))
08c3a6
+/* Clear the plabel bit to get the actual address of the descriptor.  */
08c3a6
+#define DL_FIXUP_ADDR_VALUE(addr) \
08c3a6
+  (*(DL_FIXUP_VALUE_TYPE *) ((uintptr_t) (addr) & ~2))
08c3a6
 #define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr)
08c3a6
-#define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \
08c3a6
-  (*value) = *(struct fdesc *) (st_value)
08c3a6
+#define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value)	\
08c3a6
+  *(value) = *(DL_FIXUP_VALUE_TYPE *) ((uintptr_t) (new_value) & ~2)