This is the mail archive of the
glibc-cvs@sourceware.org
mailing list for the glibc project.
GNU C Library master sources branch master updated. glibc-2.25-738-gdf3d455
- From: danglin at sourceware dot org
- To: glibc-cvs at sourceware dot org
- Date: 16 Jul 2017 14:51:56 -0000
- Subject: GNU C Library master sources branch master updated. glibc-2.25-738-gdf3d455
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".
The branch, master has been updated
via df3d455b23f3b901ecc1e4b7f1a600943f04471b (commit)
from 66cd050f26c6e1130ff7998b7586c0003da23b46 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=df3d455b23f3b901ecc1e4b7f1a600943f04471b
commit df3d455b23f3b901ecc1e4b7f1a600943f04471b
Author: John David Anglin <danglin@gcc.gnu.org>
Date: Sun Jul 16 10:51:13 2017 -0400
Fix [BZ 20098].
diff --git a/ChangeLog b/ChangeLog
index 2d3bfe2..c69c59b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2017-07-16 John David Anglin <danglin@gcc.gnu.org>
+
+ [BZ 20098]
+ * sysdeps/hppa/dl-fptr.c (_dl_read_access_allowed): New.
+ (_dl_lookup_address): Return address if it is not consistent with
+ being a linker defined function pointer. Likewise, return address
+ if address and function descriptor addresses are not accessible.
+
2017-07-16 Siddhesh Poyarekar <siddhesh@sourceware.org>
* po/libc.pot: Regenerate.
diff --git a/sysdeps/hppa/dl-fptr.c b/sysdeps/hppa/dl-fptr.c
index 83bdb91..96fd09d 100644
--- a/sysdeps/hppa/dl-fptr.c
+++ b/sysdeps/hppa/dl-fptr.c
@@ -28,6 +28,7 @@
#include <dl-fptr.h>
#include <dl-unmap-segments.h>
#include <atomic.h>
+#include <libc-pointer-arith.h>
#ifndef ELF_MACHINE_BOOT_FPTR_TABLE_LEN
/* ELF_MACHINE_BOOT_FPTR_TABLE_LEN should be greater than the number of
@@ -181,24 +182,29 @@ make_fdesc (ElfW(Addr) ip, ElfW(Addr) gp)
static inline ElfW(Addr) * __attribute__ ((always_inline))
make_fptr_table (struct link_map *map)
{
- const ElfW(Sym) *symtab
- = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
+ const ElfW(Sym) *symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
ElfW(Addr) *fptr_table;
size_t size;
size_t len;
+ const ElfW(Sym) *symtabend;
- /* XXX Apparently the only way to find out the size of the dynamic
- symbol section is to assume that the string table follows right
- afterwards... */
- len = ((strtab - (char *) symtab)
+ /* Determine the end of the dynamic symbol table using the hash. */
+ if (map->l_info[DT_HASH] != NULL)
+ symtabend = (symtab + ((Elf_Symndx *) D_PTR (map, l_info[DT_HASH]))[1]);
+ else
+ /* There is no direct way to determine the number of symbols in the
+ dynamic symbol table and no hash table is present. The ELF
+ binary is ill-formed but what shall we do? Use the beginning of
+ the string table which generally follows the symbol table. */
+ symtabend = (const ElfW(Sym) *) strtab;
+
+ len = (((char *) symtabend - (char *) symtab)
/ map->l_info[DT_SYMENT]->d_un.d_val);
- size = ((len * sizeof (fptr_table[0]) + GLRO(dl_pagesize) - 1)
- & -GLRO(dl_pagesize));
- /* XXX We don't support here in the moment systems without MAP_ANON.
- There probably are none for IA-64. In case this is proven wrong
- we will have to open /dev/null here and use the file descriptor
- instead of the hard-coded -1. */
+ size = ALIGN_UP (len * sizeof (fptr_table[0]), GLRO(dl_pagesize));
+
+ /* We don't support systems without MAP_ANON. We avoid using malloc
+ because this might get called before malloc is setup. */
fptr_table = __mmap (NULL, size,
PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE,
-1, 0);
@@ -331,22 +337,45 @@ elf_machine_resolve (void)
return addr;
}
+static inline int
+_dl_read_access_allowed (unsigned int *addr)
+{
+ int result;
+
+ asm ("proberi (%1),3,%0" : "=r" (result) : "r" (addr) : );
+
+ return result;
+}
+
ElfW(Addr)
_dl_lookup_address (const void *address)
{
ElfW(Addr) addr = (ElfW(Addr)) address;
unsigned int *desc, *gptr;
- /* Check for special cases. */
- if ((int) addr == -1
- || (unsigned int) addr < 4096
- || !((unsigned int) addr & 2))
+ /* Return ADDR if the least-significant two bits of ADDR are not consistent
+ with ADDR being a linker defined function pointer. The normal value for
+ a code address in a backtrace is 3. */
+ if (((unsigned int) addr & 3) != 2)
+ return addr;
+
+ /* Handle special case where ADDR points to page 0. */
+ if ((unsigned int) addr < 4096)
return addr;
/* Clear least-significant two bits from descriptor address. */
desc = (unsigned int *) ((unsigned int) addr & ~3);
+ if (!_dl_read_access_allowed (desc))
+ return addr;
- /* Check if descriptor requires resolution. The following trampoline is
+ /* Load first word of candidate descriptor. It should be a pointer
+ with word alignment and point to memory that can be read. */
+ gptr = (unsigned int *) desc[0];
+ if (((unsigned int) gptr & 3) != 0
+ || !_dl_read_access_allowed (gptr))
+ return addr;
+
+ /* See if descriptor requires resolution. The following trampoline is
used in each global offset table for function resolution:
ldw 0(r20),r22
@@ -358,7 +387,6 @@ _dl_lookup_address (const void *address)
.word "_dl_runtime_resolve ltp"
got: .word _DYNAMIC
.word "struct link map address" */
- gptr = (unsigned int *) desc[0];
if (gptr[0] == 0xea9f1fdd /* b,l .-12,r20 */
&& gptr[1] == 0xd6801c1e /* depwi 0,31,2,r20 */
&& (ElfW(Addr)) gptr[2] == elf_machine_resolve ())
-----------------------------------------------------------------------
Summary of changes:
ChangeLog | 8 ++++++
sysdeps/hppa/dl-fptr.c | 64 ++++++++++++++++++++++++++++++++++-------------
2 files changed, 54 insertions(+), 18 deletions(-)
hooks/post-receive
--
GNU C Library master sources