|
[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 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |