about summary refs log tree commit diff
path: root/elf
diff options
context:
space:
mode:
Diffstat (limited to 'elf')
-rw-r--r--elf/dl-load.c29
1 files changed, 23 insertions, 6 deletions
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 025b9fd86b..73e9b9ce7b 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