[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 4/4] libelf: treat phdr and shdr similarly



Just like elf_shdr_count(), elf_phdr_count() better bounds checks the
value.

Add table entry size checks to elf_init().

Also both program and section headers are optional, and hence their
checking better is done conditionally only when any such headers are
present.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>

--- a/xen/common/libelf/libelf-loader.c
+++ b/xen/common/libelf/libelf-loader.c
@@ -52,24 +52,45 @@ elf_errorstatus elf_init(struct elf_bina
     elf->class = elf_uval_3264(elf, elf->ehdr, e32.e_ident[EI_CLASS]);
     elf->data = elf_uval_3264(elf, elf->ehdr, e32.e_ident[EI_DATA]);
 
-    /* Sanity check phdr. */
-    offset = elf_uval(elf, elf->ehdr, e_phoff) +
-        elf_uval(elf, elf->ehdr, e_phentsize) * elf_phdr_count(elf);
-    if ( offset > elf->size )
+    /* Sanity check phdr if present. */
+    count = elf_phdr_count(elf);
+    if ( count )
     {
-        elf_err(elf, "ELF: phdr overflow (off %" PRIx64 " > size %lx)\n",
-                offset, (unsigned long)elf->size);
-        return -1;
+        if ( elf_uval(elf, elf->ehdr, e_phentsize) <
+             elf_size(elf, ELF_HANDLE_DECL(elf_phdr)) )
+        {
+            elf_err(elf, "ELF: phdr too small (%" PRIu64 ")\n",
+                    elf_uval(elf, elf->ehdr, e_phentsize));
+            return -1;
+        }
+        offset = elf_uval(elf, elf->ehdr, e_phoff) +
+            elf_uval(elf, elf->ehdr, e_phentsize) * count;
+        if ( offset > elf->size )
+        {
+            elf_err(elf, "ELF: phdr overflow (off %" PRIx64 " > size %lx)\n",
+                    offset, (unsigned long)elf->size);
+            return -1;
+        }
     }
 
-    /* Sanity check shdr. */
-    offset = elf_uval(elf, elf->ehdr, e_shoff) +
-        elf_uval(elf, elf->ehdr, e_shentsize) * elf_shdr_count(elf);
-    if ( offset > elf->size )
+    /* Sanity check shdr if present. */
+    count = elf_shdr_count(elf);
+    if ( count )
     {
-        elf_err(elf, "ELF: shdr overflow (off %" PRIx64 " > size %lx)\n",
-                offset, (unsigned long)elf->size);
-        return -1;
+        if ( elf_uval(elf, elf->ehdr, e_shentsize) < elf_size(elf, shdr) )
+        {
+            elf_err(elf, "ELF: shdr too small (%" PRIu64 ")\n",
+                    elf_uval(elf, elf->ehdr, e_shentsize));
+            return -1;
+        }
+        offset = elf_uval(elf, elf->ehdr, e_shoff) +
+            elf_uval(elf, elf->ehdr, e_shentsize) * count;
+        if ( offset > elf->size )
+        {
+            elf_err(elf, "ELF: shdr overflow (off %" PRIx64 " > size %lx)\n",
+                    offset, (unsigned long)elf->size);
+            return -1;
+        }
     }
 
     /* Find section string table. */
@@ -79,7 +100,6 @@ elf_errorstatus elf_init(struct elf_bina
         elf->sec_strtab = elf_section_start(elf, shdr);
 
     /* Find symbol table and symbol string table. */
-    count = elf_shdr_count(elf);
     for ( i = 1; i < count; i++ )
     {
         shdr = elf_shdr_by_index(elf, i);
--- a/xen/common/libelf/libelf-tools.c
+++ b/xen/common/libelf/libelf-tools.c
@@ -130,8 +130,11 @@ uint64_t elf_round_up(struct elf_binary
 unsigned elf_shdr_count(struct elf_binary *elf)
 {
     unsigned count = elf_uval(elf, elf->ehdr, e_shnum);
-    uint64_t max = elf->size / sizeof(Elf32_Shdr);
+    uint64_t max;
 
+    if ( !count )
+        return 0;
+    max = elf->size / elf_uval(elf, elf->ehdr, e_shentsize);
     if ( max > UINT_MAX )
         max = UINT_MAX;
     if ( count > max )
@@ -144,7 +147,20 @@ unsigned elf_shdr_count(struct elf_binar
 
 unsigned elf_phdr_count(struct elf_binary *elf)
 {
-    return elf_uval(elf, elf->ehdr, e_phnum);
+    unsigned count = elf_uval(elf, elf->ehdr, e_phnum);
+    uint64_t max;
+
+    if ( !count )
+        return 0;
+    max = elf->size / elf_uval(elf, elf->ehdr, e_phentsize);
+    if ( max > UINT_MAX )
+        max = UINT_MAX;
+    if ( count > max )
+    {
+        elf_mark_broken(elf, "far too many program headers");
+        count = max;
+    }
+    return count;
 }
 
 ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char 
*name)


Attachment: libelf-phdr-shdr.patch
Description: Text document

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.