summaryrefslogtreecommitdiff
path: root/elf/dl-load.c
diff options
context:
space:
mode:
Diffstat (limited to 'elf/dl-load.c')
-rw-r--r--elf/dl-load.c38
1 files changed, 29 insertions, 9 deletions
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 025b9fd86b..1a84e0fe43 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1634,7 +1634,7 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
{
ElfW(Ehdr) *ehdr;
ElfW(Phdr) *phdr, *ph;
- ElfW(Word) *abi_note, abi_note_buf[8];
+ ElfW(Word) *abi_note;
unsigned int osversion;
size_t maplength;
@@ -1751,20 +1751,37 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
/* Check .note.ABI-tag if present. */
for (ph = phdr; ph < &phdr[ehdr->e_phnum]; ++ph)
- if (ph->p_type == PT_NOTE && ph->p_filesz == 32 && ph->p_align >= 4)
+ if (ph->p_type == PT_NOTE && ph->p_filesz >= 32 && ph->p_align >= 4)
{
- if (ph->p_offset + 32 <= (size_t) fbp->len)
+ ElfW(Addr) size = ph->p_filesz;
+
+ if (ph->p_offset + size <= (size_t) fbp->len)
abi_note = (void *) (fbp->buf + ph->p_offset);
else
{
+ abi_note = alloca (size);
__lseek (fd, ph->p_offset, SEEK_SET);
- if (__libc_read (fd, (void *) abi_note_buf, 32) != 32)
+ if (__libc_read (fd, (void *) abi_note, size) != size)
goto read_error;
+ }
+
+ while (memcmp (abi_note, &expected_note, sizeof (expected_note)))
+ {
+#define ROUND(len) (((len) + sizeof (ElfW(Word)) - 1) & -sizeof (ElfW(Word)))
+ ElfW(Addr) note_size = 3 * sizeof (ElfW(Word))
+ + ROUND (abi_note[0])
+ + ROUND (abi_note[1]);
- abi_note = abi_note_buf;
+ if (size - 32 < note_size)
+ {
+ size = 0;
+ break;
+ }
+ size -= note_size;
+ abi_note = (void *) abi_note + note_size;
}
- if (memcmp (abi_note, &expected_note, sizeof (expected_note)))
+ if (size == 0)
continue;
osversion = (abi_note[5] & 0xff) * 65536
@@ -2256,14 +2273,17 @@ _dl_rtld_di_serinfo (struct link_map *loader, Dl_serinfo *si, bool counting)
if (counting)
{
si->dls_cnt++;
- si->dls_size += r->dirnamelen;
+ si->dls_size += r->dirnamelen < 2 ? r->dirnamelen : 2;
}
else
{
Dl_serpath *const sp = &si->dls_serpath[idx++];
sp->dls_name = allocptr;
- allocptr = __mempcpy (allocptr,
- r->dirname, r->dirnamelen - 1);
+ if (r->dirnamelen < 2)
+ *allocptr++ = r->dirnamelen ? '/' : '.';
+ else
+ allocptr = __mempcpy (allocptr,
+ r->dirname, r->dirnamelen - 1);
*allocptr++ = '\0';
sp->dls_flags = flags;
}